1 //===- RISCVInsertVSETVLI.cpp - Insert VSETVLI instructions ---------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements a function pass that inserts VSETVLI instructions where 10 // needed. 11 // 12 // This pass consists of 3 phases: 13 // 14 // Phase 1 collects how each basic block affects VL/VTYPE. 15 // 16 // Phase 2 uses the information from phase 1 to do a data flow analysis to 17 // propagate the VL/VTYPE changes through the function. This gives us the 18 // VL/VTYPE at the start of each basic block. 19 // 20 // Phase 3 inserts VSETVLI instructions in each basic block. Information from 21 // phase 2 is used to prevent inserting a VSETVLI before the first vector 22 // instruction in the block if possible. 23 // 24 //===----------------------------------------------------------------------===// 25 26 #include "RISCV.h" 27 #include "RISCVSubtarget.h" 28 #include "llvm/CodeGen/LiveIntervals.h" 29 #include "llvm/CodeGen/MachineFunctionPass.h" 30 #include <queue> 31 using namespace llvm; 32 33 #define DEBUG_TYPE "riscv-insert-vsetvli" 34 #define RISCV_INSERT_VSETVLI_NAME "RISCV Insert VSETVLI pass" 35 36 static cl::opt<bool> DisableInsertVSETVLPHIOpt( 37 "riscv-disable-insert-vsetvl-phi-opt", cl::init(false), cl::Hidden, 38 cl::desc("Disable looking through phis when inserting vsetvlis.")); 39 40 namespace { 41 42 class VSETVLIInfo { 43 union { 44 Register AVLReg; 45 unsigned AVLImm; 46 }; 47 48 enum : uint8_t { 49 Uninitialized, 50 AVLIsReg, 51 AVLIsImm, 52 Unknown, 53 } State = Uninitialized; 54 55 // Fields from VTYPE. 56 RISCVII::VLMUL VLMul = RISCVII::LMUL_1; 57 uint8_t SEW = 0; 58 uint8_t TailAgnostic : 1; 59 uint8_t MaskAgnostic : 1; 60 uint8_t MaskRegOp : 1; 61 uint8_t StoreOp : 1; 62 uint8_t SEWLMULRatioOnly : 1; 63 64 public: 65 VSETVLIInfo() 66 : AVLImm(0), TailAgnostic(false), MaskAgnostic(false), MaskRegOp(false), 67 StoreOp(false), SEWLMULRatioOnly(false) {} 68 69 static VSETVLIInfo getUnknown() { 70 VSETVLIInfo Info; 71 Info.setUnknown(); 72 return Info; 73 } 74 75 bool isValid() const { return State != Uninitialized; } 76 void setUnknown() { State = Unknown; } 77 bool isUnknown() const { return State == Unknown; } 78 79 void setAVLReg(Register Reg) { 80 AVLReg = Reg; 81 State = AVLIsReg; 82 } 83 84 void setAVLImm(unsigned Imm) { 85 AVLImm = Imm; 86 State = AVLIsImm; 87 } 88 89 bool hasAVLImm() const { return State == AVLIsImm; } 90 bool hasAVLReg() const { return State == AVLIsReg; } 91 Register getAVLReg() const { 92 assert(hasAVLReg()); 93 return AVLReg; 94 } 95 unsigned getAVLImm() const { 96 assert(hasAVLImm()); 97 return AVLImm; 98 } 99 100 bool hasSameAVL(const VSETVLIInfo &Other) const { 101 assert(isValid() && Other.isValid() && 102 "Can't compare invalid VSETVLIInfos"); 103 assert(!isUnknown() && !Other.isUnknown() && 104 "Can't compare AVL in unknown state"); 105 if (hasAVLReg() && Other.hasAVLReg()) 106 return getAVLReg() == Other.getAVLReg(); 107 108 if (hasAVLImm() && Other.hasAVLImm()) 109 return getAVLImm() == Other.getAVLImm(); 110 111 return false; 112 } 113 114 void setVTYPE(unsigned VType) { 115 assert(isValid() && !isUnknown() && 116 "Can't set VTYPE for uninitialized or unknown"); 117 VLMul = RISCVVType::getVLMUL(VType); 118 SEW = RISCVVType::getSEW(VType); 119 TailAgnostic = RISCVVType::isTailAgnostic(VType); 120 MaskAgnostic = RISCVVType::isMaskAgnostic(VType); 121 } 122 void setVTYPE(RISCVII::VLMUL L, unsigned S, bool TA, bool MA, bool MRO, 123 bool IsStore) { 124 assert(isValid() && !isUnknown() && 125 "Can't set VTYPE for uninitialized or unknown"); 126 VLMul = L; 127 SEW = S; 128 TailAgnostic = TA; 129 MaskAgnostic = MA; 130 MaskRegOp = MRO; 131 StoreOp = IsStore; 132 } 133 134 unsigned encodeVTYPE() const { 135 assert(isValid() && !isUnknown() && !SEWLMULRatioOnly && 136 "Can't encode VTYPE for uninitialized or unknown"); 137 return RISCVVType::encodeVTYPE(VLMul, SEW, TailAgnostic, MaskAgnostic); 138 } 139 140 bool hasSEWLMULRatioOnly() const { return SEWLMULRatioOnly; } 141 142 bool hasSameVTYPE(const VSETVLIInfo &Other) const { 143 assert(isValid() && Other.isValid() && 144 "Can't compare invalid VSETVLIInfos"); 145 assert(!isUnknown() && !Other.isUnknown() && 146 "Can't compare VTYPE in unknown state"); 147 assert(!SEWLMULRatioOnly && !Other.SEWLMULRatioOnly && 148 "Can't compare when only LMUL/SEW ratio is valid."); 149 return std::tie(VLMul, SEW, TailAgnostic, MaskAgnostic) == 150 std::tie(Other.VLMul, Other.SEW, Other.TailAgnostic, 151 Other.MaskAgnostic); 152 } 153 154 static unsigned getSEWLMULRatio(unsigned SEW, RISCVII::VLMUL VLMul) { 155 unsigned LMul; 156 bool Fractional; 157 std::tie(LMul, Fractional) = RISCVVType::decodeVLMUL(VLMul); 158 159 // Convert LMul to a fixed point value with 3 fractional bits. 160 LMul = Fractional ? (8 / LMul) : (LMul * 8); 161 162 assert(SEW >= 8 && "Unexpected SEW value"); 163 return (SEW * 8) / LMul; 164 } 165 166 unsigned getSEWLMULRatio() const { 167 assert(isValid() && !isUnknown() && 168 "Can't use VTYPE for uninitialized or unknown"); 169 return getSEWLMULRatio(SEW, VLMul); 170 } 171 172 // Check if the VTYPE for these two VSETVLIInfos produce the same VLMAX. 173 bool hasSameVLMAX(const VSETVLIInfo &Other) const { 174 assert(isValid() && Other.isValid() && 175 "Can't compare invalid VSETVLIInfos"); 176 assert(!isUnknown() && !Other.isUnknown() && 177 "Can't compare VTYPE in unknown state"); 178 return getSEWLMULRatio() == Other.getSEWLMULRatio(); 179 } 180 181 bool hasCompatibleVTYPE(const VSETVLIInfo &InstrInfo, bool Strict) const { 182 // Simple case, see if full VTYPE matches. 183 if (hasSameVTYPE(InstrInfo)) 184 return true; 185 186 if (Strict) 187 return false; 188 189 // If this is a mask reg operation, it only cares about VLMAX. 190 // FIXME: Mask reg operations are probably ok if "this" VLMAX is larger 191 // than "InstrInfo". 192 // FIXME: The policy bits can probably be ignored for mask reg operations. 193 if (InstrInfo.MaskRegOp && hasSameVLMAX(InstrInfo) && 194 TailAgnostic == InstrInfo.TailAgnostic && 195 MaskAgnostic == InstrInfo.MaskAgnostic) 196 return true; 197 198 return false; 199 } 200 201 // Determine whether the vector instructions requirements represented by 202 // InstrInfo are compatible with the previous vsetvli instruction represented 203 // by this. 204 bool isCompatible(const VSETVLIInfo &InstrInfo, bool Strict) const { 205 assert(isValid() && InstrInfo.isValid() && 206 "Can't compare invalid VSETVLIInfos"); 207 assert(!InstrInfo.SEWLMULRatioOnly && 208 "Expected a valid VTYPE for instruction!"); 209 // Nothing is compatible with Unknown. 210 if (isUnknown() || InstrInfo.isUnknown()) 211 return false; 212 213 // If only our VLMAX ratio is valid, then this isn't compatible. 214 if (SEWLMULRatioOnly) 215 return false; 216 217 // If the instruction doesn't need an AVLReg and the SEW matches, consider 218 // it compatible. 219 if (!Strict && InstrInfo.hasAVLReg() && 220 InstrInfo.AVLReg == RISCV::NoRegister) { 221 if (SEW == InstrInfo.SEW) 222 return true; 223 } 224 225 // The AVL must match. 226 if (!hasSameAVL(InstrInfo)) 227 return false; 228 229 if (hasCompatibleVTYPE(InstrInfo, Strict)) 230 return true; 231 232 // Strict matches must ensure a full VTYPE match. 233 if (Strict) 234 return false; 235 236 // Store instructions don't use the policy fields. 237 // TODO: Move into hasCompatibleVTYPE? 238 if (InstrInfo.StoreOp && VLMul == InstrInfo.VLMul && SEW == InstrInfo.SEW) 239 return true; 240 241 // Anything else is not compatible. 242 return false; 243 } 244 245 bool isCompatibleWithLoadStoreEEW(unsigned EEW, 246 const VSETVLIInfo &InstrInfo) const { 247 assert(isValid() && InstrInfo.isValid() && 248 "Can't compare invalid VSETVLIInfos"); 249 assert(!InstrInfo.SEWLMULRatioOnly && 250 "Expected a valid VTYPE for instruction!"); 251 assert(EEW == InstrInfo.SEW && "Mismatched EEW/SEW for store"); 252 253 if (isUnknown() || hasSEWLMULRatioOnly()) 254 return false; 255 256 if (!hasSameAVL(InstrInfo)) 257 return false; 258 259 // Stores can ignore the tail and mask policies. 260 if (!InstrInfo.StoreOp && (TailAgnostic != InstrInfo.TailAgnostic || 261 MaskAgnostic != InstrInfo.MaskAgnostic)) 262 return false; 263 264 return getSEWLMULRatio() == getSEWLMULRatio(EEW, InstrInfo.VLMul); 265 } 266 267 bool operator==(const VSETVLIInfo &Other) const { 268 // Uninitialized is only equal to another Uninitialized. 269 if (!isValid()) 270 return !Other.isValid(); 271 if (!Other.isValid()) 272 return !isValid(); 273 274 // Unknown is only equal to another Unknown. 275 if (isUnknown()) 276 return Other.isUnknown(); 277 if (Other.isUnknown()) 278 return isUnknown(); 279 280 if (!hasSameAVL(Other)) 281 return false; 282 283 // If only the VLMAX is valid, check that it is the same. 284 if (SEWLMULRatioOnly && Other.SEWLMULRatioOnly) 285 return hasSameVLMAX(Other); 286 287 // If the full VTYPE is valid, check that it is the same. 288 if (!SEWLMULRatioOnly && !Other.SEWLMULRatioOnly) 289 return hasSameVTYPE(Other); 290 291 // If the SEWLMULRatioOnly bits are different, then they aren't equal. 292 return false; 293 } 294 295 // Calculate the VSETVLIInfo visible to a block assuming this and Other are 296 // both predecessors. 297 VSETVLIInfo intersect(const VSETVLIInfo &Other) const { 298 // If the new value isn't valid, ignore it. 299 if (!Other.isValid()) 300 return *this; 301 302 // If this value isn't valid, this must be the first predecessor, use it. 303 if (!isValid()) 304 return Other; 305 306 // If either is unknown, the result is unknown. 307 if (isUnknown() || Other.isUnknown()) 308 return VSETVLIInfo::getUnknown(); 309 310 // If we have an exact, match return this. 311 if (*this == Other) 312 return *this; 313 314 // Not an exact match, but maybe the AVL and VLMAX are the same. If so, 315 // return an SEW/LMUL ratio only value. 316 if (hasSameAVL(Other) && hasSameVLMAX(Other)) { 317 VSETVLIInfo MergeInfo = *this; 318 MergeInfo.SEWLMULRatioOnly = true; 319 return MergeInfo; 320 } 321 322 // Otherwise the result is unknown. 323 return VSETVLIInfo::getUnknown(); 324 } 325 326 // Calculate the VSETVLIInfo visible at the end of the block assuming this 327 // is the predecessor value, and Other is change for this block. 328 VSETVLIInfo merge(const VSETVLIInfo &Other) const { 329 assert(isValid() && "Can only merge with a valid VSETVLInfo"); 330 331 // Nothing changed from the predecessor, keep it. 332 if (!Other.isValid()) 333 return *this; 334 335 // If the change is compatible with the input, we won't create a VSETVLI 336 // and should keep the predecessor. 337 if (isCompatible(Other, /*Strict*/ true)) 338 return *this; 339 340 // Otherwise just use whatever is in this block. 341 return Other; 342 } 343 }; 344 345 struct BlockData { 346 // The VSETVLIInfo that represents the net changes to the VL/VTYPE registers 347 // made by this block. Calculated in Phase 1. 348 VSETVLIInfo Change; 349 350 // The VSETVLIInfo that represents the VL/VTYPE settings on exit from this 351 // block. Calculated in Phase 2. 352 VSETVLIInfo Exit; 353 354 // The VSETVLIInfo that represents the VL/VTYPE settings from all predecessor 355 // blocks. Calculated in Phase 2, and used by Phase 3. 356 VSETVLIInfo Pred; 357 358 // Keeps track of whether the block is already in the queue. 359 bool InQueue = false; 360 361 BlockData() {} 362 }; 363 364 class RISCVInsertVSETVLI : public MachineFunctionPass { 365 const TargetInstrInfo *TII; 366 MachineRegisterInfo *MRI; 367 368 std::vector<BlockData> BlockInfo; 369 std::queue<const MachineBasicBlock *> WorkList; 370 371 public: 372 static char ID; 373 374 RISCVInsertVSETVLI() : MachineFunctionPass(ID) { 375 initializeRISCVInsertVSETVLIPass(*PassRegistry::getPassRegistry()); 376 } 377 bool runOnMachineFunction(MachineFunction &MF) override; 378 379 void getAnalysisUsage(AnalysisUsage &AU) const override { 380 AU.setPreservesCFG(); 381 MachineFunctionPass::getAnalysisUsage(AU); 382 } 383 384 StringRef getPassName() const override { return RISCV_INSERT_VSETVLI_NAME; } 385 386 private: 387 bool needVSETVLI(const VSETVLIInfo &Require, const VSETVLIInfo &CurInfo); 388 bool needVSETVLIPHI(const VSETVLIInfo &Require, const MachineBasicBlock &MBB); 389 void insertVSETVLI(MachineBasicBlock &MBB, MachineInstr &MI, 390 const VSETVLIInfo &Info, const VSETVLIInfo &PrevInfo); 391 392 bool computeVLVTYPEChanges(const MachineBasicBlock &MBB); 393 void computeIncomingVLVTYPE(const MachineBasicBlock &MBB); 394 void emitVSETVLIs(MachineBasicBlock &MBB); 395 }; 396 397 } // end anonymous namespace 398 399 char RISCVInsertVSETVLI::ID = 0; 400 401 INITIALIZE_PASS(RISCVInsertVSETVLI, DEBUG_TYPE, RISCV_INSERT_VSETVLI_NAME, 402 false, false) 403 404 static MachineInstr *elideCopies(MachineInstr *MI, 405 const MachineRegisterInfo *MRI) { 406 while (true) { 407 if (!MI->isFullCopy()) 408 return MI; 409 if (!Register::isVirtualRegister(MI->getOperand(1).getReg())) 410 return nullptr; 411 MI = MRI->getVRegDef(MI->getOperand(1).getReg()); 412 if (!MI) 413 return nullptr; 414 } 415 } 416 417 static VSETVLIInfo computeInfoForInstr(const MachineInstr &MI, uint64_t TSFlags, 418 const MachineRegisterInfo *MRI) { 419 VSETVLIInfo InstrInfo; 420 unsigned NumOperands = MI.getNumExplicitOperands(); 421 bool HasPolicy = RISCVII::hasVecPolicyOp(TSFlags); 422 423 // Default to tail agnostic unless the destination is tied to a source. 424 // Unless the source is undef. In that case the user would have some control 425 // over the tail values. Some pseudo instructions force a tail agnostic policy 426 // despite having a tied def. 427 bool ForceTailAgnostic = RISCVII::doesForceTailAgnostic(TSFlags); 428 bool TailAgnostic = true; 429 // If the instruction has policy argument, use the argument. 430 if (HasPolicy) { 431 const MachineOperand &Op = MI.getOperand(MI.getNumExplicitOperands() - 1); 432 TailAgnostic = Op.getImm() & 0x1; 433 } 434 435 unsigned UseOpIdx; 436 if (!(ForceTailAgnostic || (HasPolicy && TailAgnostic)) && 437 MI.isRegTiedToUseOperand(0, &UseOpIdx)) { 438 TailAgnostic = false; 439 // If the tied operand is an IMPLICIT_DEF we can keep TailAgnostic. 440 const MachineOperand &UseMO = MI.getOperand(UseOpIdx); 441 MachineInstr *UseMI = MRI->getVRegDef(UseMO.getReg()); 442 if (UseMI) { 443 UseMI = elideCopies(UseMI, MRI); 444 if (UseMI && UseMI->isImplicitDef()) 445 TailAgnostic = true; 446 } 447 } 448 449 // Remove the tail policy so we can find the SEW and VL. 450 if (HasPolicy) 451 --NumOperands; 452 453 RISCVII::VLMUL VLMul = RISCVII::getLMul(TSFlags); 454 455 unsigned Log2SEW = MI.getOperand(NumOperands - 1).getImm(); 456 // A Log2SEW of 0 is an operation on mask registers only. 457 bool MaskRegOp = Log2SEW == 0; 458 unsigned SEW = Log2SEW ? 1 << Log2SEW : 8; 459 assert(RISCVVType::isValidSEW(SEW) && "Unexpected SEW"); 460 461 // If there are no explicit defs, this is a store instruction which can 462 // ignore the tail and mask policies. 463 bool StoreOp = MI.getNumExplicitDefs() == 0; 464 465 if (RISCVII::hasVLOp(TSFlags)) { 466 const MachineOperand &VLOp = MI.getOperand(NumOperands - 2); 467 if (VLOp.isImm()) { 468 int64_t Imm = VLOp.getImm(); 469 // Conver the VLMax sentintel to X0 register. 470 if (Imm == RISCV::VLMaxSentinel) 471 InstrInfo.setAVLReg(RISCV::X0); 472 else 473 InstrInfo.setAVLImm(Imm); 474 } else { 475 InstrInfo.setAVLReg(VLOp.getReg()); 476 } 477 } else 478 InstrInfo.setAVLReg(RISCV::NoRegister); 479 InstrInfo.setVTYPE(VLMul, SEW, /*TailAgnostic*/ TailAgnostic, 480 /*MaskAgnostic*/ false, MaskRegOp, StoreOp); 481 482 return InstrInfo; 483 } 484 485 void RISCVInsertVSETVLI::insertVSETVLI(MachineBasicBlock &MBB, MachineInstr &MI, 486 const VSETVLIInfo &Info, 487 const VSETVLIInfo &PrevInfo) { 488 DebugLoc DL = MI.getDebugLoc(); 489 490 // Use X0, X0 form if the AVL is the same and the SEW+LMUL gives the same 491 // VLMAX. 492 if (PrevInfo.isValid() && !PrevInfo.isUnknown() && 493 Info.hasSameAVL(PrevInfo) && Info.hasSameVLMAX(PrevInfo)) { 494 BuildMI(MBB, MI, DL, TII->get(RISCV::PseudoVSETVLIX0)) 495 .addReg(RISCV::X0, RegState::Define | RegState::Dead) 496 .addReg(RISCV::X0, RegState::Kill) 497 .addImm(Info.encodeVTYPE()) 498 .addReg(RISCV::VL, RegState::Implicit); 499 return; 500 } 501 502 if (Info.hasAVLImm()) { 503 BuildMI(MBB, MI, DL, TII->get(RISCV::PseudoVSETIVLI)) 504 .addReg(RISCV::X0, RegState::Define | RegState::Dead) 505 .addImm(Info.getAVLImm()) 506 .addImm(Info.encodeVTYPE()); 507 return; 508 } 509 510 Register AVLReg = Info.getAVLReg(); 511 if (AVLReg == RISCV::NoRegister) { 512 // We can only use x0, x0 if there's no chance of the vtype change causing 513 // the previous vl to become invalid. 514 if (PrevInfo.isValid() && !PrevInfo.isUnknown() && 515 Info.hasSameVLMAX(PrevInfo)) { 516 BuildMI(MBB, MI, DL, TII->get(RISCV::PseudoVSETVLIX0)) 517 .addReg(RISCV::X0, RegState::Define | RegState::Dead) 518 .addReg(RISCV::X0, RegState::Kill) 519 .addImm(Info.encodeVTYPE()) 520 .addReg(RISCV::VL, RegState::Implicit); 521 return; 522 } 523 // Otherwise use an AVL of 0 to avoid depending on previous vl. 524 BuildMI(MBB, MI, DL, TII->get(RISCV::PseudoVSETIVLI)) 525 .addReg(RISCV::X0, RegState::Define | RegState::Dead) 526 .addImm(0) 527 .addImm(Info.encodeVTYPE()); 528 return; 529 } 530 531 if (AVLReg.isVirtual()) 532 MRI->constrainRegClass(AVLReg, &RISCV::GPRNoX0RegClass); 533 534 // Use X0 as the DestReg unless AVLReg is X0. We also need to change the 535 // opcode if the AVLReg is X0 as they have different register classes for 536 // the AVL operand. 537 Register DestReg = RISCV::X0; 538 unsigned Opcode = RISCV::PseudoVSETVLI; 539 if (AVLReg == RISCV::X0) { 540 DestReg = MRI->createVirtualRegister(&RISCV::GPRRegClass); 541 Opcode = RISCV::PseudoVSETVLIX0; 542 } 543 BuildMI(MBB, MI, DL, TII->get(Opcode)) 544 .addReg(DestReg, RegState::Define | RegState::Dead) 545 .addReg(AVLReg) 546 .addImm(Info.encodeVTYPE()); 547 } 548 549 // Return a VSETVLIInfo representing the changes made by this VSETVLI or 550 // VSETIVLI instruction. 551 static VSETVLIInfo getInfoForVSETVLI(const MachineInstr &MI) { 552 VSETVLIInfo NewInfo; 553 if (MI.getOpcode() == RISCV::PseudoVSETIVLI) { 554 NewInfo.setAVLImm(MI.getOperand(1).getImm()); 555 } else { 556 assert(MI.getOpcode() == RISCV::PseudoVSETVLI || 557 MI.getOpcode() == RISCV::PseudoVSETVLIX0); 558 Register AVLReg = MI.getOperand(1).getReg(); 559 assert((AVLReg != RISCV::X0 || MI.getOperand(0).getReg() != RISCV::X0) && 560 "Can't handle X0, X0 vsetvli yet"); 561 NewInfo.setAVLReg(AVLReg); 562 } 563 NewInfo.setVTYPE(MI.getOperand(2).getImm()); 564 565 return NewInfo; 566 } 567 568 bool RISCVInsertVSETVLI::needVSETVLI(const VSETVLIInfo &Require, 569 const VSETVLIInfo &CurInfo) { 570 if (CurInfo.isCompatible(Require, /*Strict*/ false)) 571 return false; 572 573 // We didn't find a compatible value. If our AVL is a virtual register, 574 // it might be defined by a VSET(I)VLI. If it has the same VTYPE we need 575 // and the last VL/VTYPE we observed is the same, we don't need a 576 // VSETVLI here. 577 if (!CurInfo.isUnknown() && Require.hasAVLReg() && 578 Require.getAVLReg().isVirtual() && !CurInfo.hasSEWLMULRatioOnly() && 579 CurInfo.hasCompatibleVTYPE(Require, /*Strict*/ false)) { 580 if (MachineInstr *DefMI = MRI->getVRegDef(Require.getAVLReg())) { 581 if (DefMI->getOpcode() == RISCV::PseudoVSETVLI || 582 DefMI->getOpcode() == RISCV::PseudoVSETVLIX0 || 583 DefMI->getOpcode() == RISCV::PseudoVSETIVLI) { 584 VSETVLIInfo DefInfo = getInfoForVSETVLI(*DefMI); 585 if (DefInfo.hasSameAVL(CurInfo) && DefInfo.hasSameVTYPE(CurInfo)) 586 return false; 587 } 588 } 589 } 590 591 return true; 592 } 593 594 bool canSkipVSETVLIForLoadStore(const MachineInstr &MI, 595 const VSETVLIInfo &Require, 596 const VSETVLIInfo &CurInfo) { 597 unsigned EEW; 598 switch (MI.getOpcode()) { 599 default: 600 return false; 601 case RISCV::PseudoVLE8_V_M1: 602 case RISCV::PseudoVLE8_V_M1_MASK: 603 case RISCV::PseudoVLE8_V_M2: 604 case RISCV::PseudoVLE8_V_M2_MASK: 605 case RISCV::PseudoVLE8_V_M4: 606 case RISCV::PseudoVLE8_V_M4_MASK: 607 case RISCV::PseudoVLE8_V_M8: 608 case RISCV::PseudoVLE8_V_M8_MASK: 609 case RISCV::PseudoVLE8_V_MF2: 610 case RISCV::PseudoVLE8_V_MF2_MASK: 611 case RISCV::PseudoVLE8_V_MF4: 612 case RISCV::PseudoVLE8_V_MF4_MASK: 613 case RISCV::PseudoVLE8_V_MF8: 614 case RISCV::PseudoVLE8_V_MF8_MASK: 615 case RISCV::PseudoVLSE8_V_M1: 616 case RISCV::PseudoVLSE8_V_M1_MASK: 617 case RISCV::PseudoVLSE8_V_M2: 618 case RISCV::PseudoVLSE8_V_M2_MASK: 619 case RISCV::PseudoVLSE8_V_M4: 620 case RISCV::PseudoVLSE8_V_M4_MASK: 621 case RISCV::PseudoVLSE8_V_M8: 622 case RISCV::PseudoVLSE8_V_M8_MASK: 623 case RISCV::PseudoVLSE8_V_MF2: 624 case RISCV::PseudoVLSE8_V_MF2_MASK: 625 case RISCV::PseudoVLSE8_V_MF4: 626 case RISCV::PseudoVLSE8_V_MF4_MASK: 627 case RISCV::PseudoVLSE8_V_MF8: 628 case RISCV::PseudoVLSE8_V_MF8_MASK: 629 case RISCV::PseudoVSE8_V_M1: 630 case RISCV::PseudoVSE8_V_M1_MASK: 631 case RISCV::PseudoVSE8_V_M2: 632 case RISCV::PseudoVSE8_V_M2_MASK: 633 case RISCV::PseudoVSE8_V_M4: 634 case RISCV::PseudoVSE8_V_M4_MASK: 635 case RISCV::PseudoVSE8_V_M8: 636 case RISCV::PseudoVSE8_V_M8_MASK: 637 case RISCV::PseudoVSE8_V_MF2: 638 case RISCV::PseudoVSE8_V_MF2_MASK: 639 case RISCV::PseudoVSE8_V_MF4: 640 case RISCV::PseudoVSE8_V_MF4_MASK: 641 case RISCV::PseudoVSE8_V_MF8: 642 case RISCV::PseudoVSE8_V_MF8_MASK: 643 case RISCV::PseudoVSSE8_V_M1: 644 case RISCV::PseudoVSSE8_V_M1_MASK: 645 case RISCV::PseudoVSSE8_V_M2: 646 case RISCV::PseudoVSSE8_V_M2_MASK: 647 case RISCV::PseudoVSSE8_V_M4: 648 case RISCV::PseudoVSSE8_V_M4_MASK: 649 case RISCV::PseudoVSSE8_V_M8: 650 case RISCV::PseudoVSSE8_V_M8_MASK: 651 case RISCV::PseudoVSSE8_V_MF2: 652 case RISCV::PseudoVSSE8_V_MF2_MASK: 653 case RISCV::PseudoVSSE8_V_MF4: 654 case RISCV::PseudoVSSE8_V_MF4_MASK: 655 case RISCV::PseudoVSSE8_V_MF8: 656 case RISCV::PseudoVSSE8_V_MF8_MASK: 657 EEW = 8; 658 break; 659 case RISCV::PseudoVLE16_V_M1: 660 case RISCV::PseudoVLE16_V_M1_MASK: 661 case RISCV::PseudoVLE16_V_M2: 662 case RISCV::PseudoVLE16_V_M2_MASK: 663 case RISCV::PseudoVLE16_V_M4: 664 case RISCV::PseudoVLE16_V_M4_MASK: 665 case RISCV::PseudoVLE16_V_M8: 666 case RISCV::PseudoVLE16_V_M8_MASK: 667 case RISCV::PseudoVLE16_V_MF2: 668 case RISCV::PseudoVLE16_V_MF2_MASK: 669 case RISCV::PseudoVLE16_V_MF4: 670 case RISCV::PseudoVLE16_V_MF4_MASK: 671 case RISCV::PseudoVLSE16_V_M1: 672 case RISCV::PseudoVLSE16_V_M1_MASK: 673 case RISCV::PseudoVLSE16_V_M2: 674 case RISCV::PseudoVLSE16_V_M2_MASK: 675 case RISCV::PseudoVLSE16_V_M4: 676 case RISCV::PseudoVLSE16_V_M4_MASK: 677 case RISCV::PseudoVLSE16_V_M8: 678 case RISCV::PseudoVLSE16_V_M8_MASK: 679 case RISCV::PseudoVLSE16_V_MF2: 680 case RISCV::PseudoVLSE16_V_MF2_MASK: 681 case RISCV::PseudoVLSE16_V_MF4: 682 case RISCV::PseudoVLSE16_V_MF4_MASK: 683 case RISCV::PseudoVSE16_V_M1: 684 case RISCV::PseudoVSE16_V_M1_MASK: 685 case RISCV::PseudoVSE16_V_M2: 686 case RISCV::PseudoVSE16_V_M2_MASK: 687 case RISCV::PseudoVSE16_V_M4: 688 case RISCV::PseudoVSE16_V_M4_MASK: 689 case RISCV::PseudoVSE16_V_M8: 690 case RISCV::PseudoVSE16_V_M8_MASK: 691 case RISCV::PseudoVSE16_V_MF2: 692 case RISCV::PseudoVSE16_V_MF2_MASK: 693 case RISCV::PseudoVSE16_V_MF4: 694 case RISCV::PseudoVSE16_V_MF4_MASK: 695 case RISCV::PseudoVSSE16_V_M1: 696 case RISCV::PseudoVSSE16_V_M1_MASK: 697 case RISCV::PseudoVSSE16_V_M2: 698 case RISCV::PseudoVSSE16_V_M2_MASK: 699 case RISCV::PseudoVSSE16_V_M4: 700 case RISCV::PseudoVSSE16_V_M4_MASK: 701 case RISCV::PseudoVSSE16_V_M8: 702 case RISCV::PseudoVSSE16_V_M8_MASK: 703 case RISCV::PseudoVSSE16_V_MF2: 704 case RISCV::PseudoVSSE16_V_MF2_MASK: 705 case RISCV::PseudoVSSE16_V_MF4: 706 case RISCV::PseudoVSSE16_V_MF4_MASK: 707 EEW = 16; 708 break; 709 case RISCV::PseudoVLE32_V_M1: 710 case RISCV::PseudoVLE32_V_M1_MASK: 711 case RISCV::PseudoVLE32_V_M2: 712 case RISCV::PseudoVLE32_V_M2_MASK: 713 case RISCV::PseudoVLE32_V_M4: 714 case RISCV::PseudoVLE32_V_M4_MASK: 715 case RISCV::PseudoVLE32_V_M8: 716 case RISCV::PseudoVLE32_V_M8_MASK: 717 case RISCV::PseudoVLE32_V_MF2: 718 case RISCV::PseudoVLE32_V_MF2_MASK: 719 case RISCV::PseudoVLSE32_V_M1: 720 case RISCV::PseudoVLSE32_V_M1_MASK: 721 case RISCV::PseudoVLSE32_V_M2: 722 case RISCV::PseudoVLSE32_V_M2_MASK: 723 case RISCV::PseudoVLSE32_V_M4: 724 case RISCV::PseudoVLSE32_V_M4_MASK: 725 case RISCV::PseudoVLSE32_V_M8: 726 case RISCV::PseudoVLSE32_V_M8_MASK: 727 case RISCV::PseudoVLSE32_V_MF2: 728 case RISCV::PseudoVLSE32_V_MF2_MASK: 729 case RISCV::PseudoVSE32_V_M1: 730 case RISCV::PseudoVSE32_V_M1_MASK: 731 case RISCV::PseudoVSE32_V_M2: 732 case RISCV::PseudoVSE32_V_M2_MASK: 733 case RISCV::PseudoVSE32_V_M4: 734 case RISCV::PseudoVSE32_V_M4_MASK: 735 case RISCV::PseudoVSE32_V_M8: 736 case RISCV::PseudoVSE32_V_M8_MASK: 737 case RISCV::PseudoVSE32_V_MF2: 738 case RISCV::PseudoVSE32_V_MF2_MASK: 739 case RISCV::PseudoVSSE32_V_M1: 740 case RISCV::PseudoVSSE32_V_M1_MASK: 741 case RISCV::PseudoVSSE32_V_M2: 742 case RISCV::PseudoVSSE32_V_M2_MASK: 743 case RISCV::PseudoVSSE32_V_M4: 744 case RISCV::PseudoVSSE32_V_M4_MASK: 745 case RISCV::PseudoVSSE32_V_M8: 746 case RISCV::PseudoVSSE32_V_M8_MASK: 747 case RISCV::PseudoVSSE32_V_MF2: 748 case RISCV::PseudoVSSE32_V_MF2_MASK: 749 EEW = 32; 750 break; 751 case RISCV::PseudoVLE64_V_M1: 752 case RISCV::PseudoVLE64_V_M1_MASK: 753 case RISCV::PseudoVLE64_V_M2: 754 case RISCV::PseudoVLE64_V_M2_MASK: 755 case RISCV::PseudoVLE64_V_M4: 756 case RISCV::PseudoVLE64_V_M4_MASK: 757 case RISCV::PseudoVLE64_V_M8: 758 case RISCV::PseudoVLE64_V_M8_MASK: 759 case RISCV::PseudoVLSE64_V_M1: 760 case RISCV::PseudoVLSE64_V_M1_MASK: 761 case RISCV::PseudoVLSE64_V_M2: 762 case RISCV::PseudoVLSE64_V_M2_MASK: 763 case RISCV::PseudoVLSE64_V_M4: 764 case RISCV::PseudoVLSE64_V_M4_MASK: 765 case RISCV::PseudoVLSE64_V_M8: 766 case RISCV::PseudoVLSE64_V_M8_MASK: 767 case RISCV::PseudoVSE64_V_M1: 768 case RISCV::PseudoVSE64_V_M1_MASK: 769 case RISCV::PseudoVSE64_V_M2: 770 case RISCV::PseudoVSE64_V_M2_MASK: 771 case RISCV::PseudoVSE64_V_M4: 772 case RISCV::PseudoVSE64_V_M4_MASK: 773 case RISCV::PseudoVSE64_V_M8: 774 case RISCV::PseudoVSE64_V_M8_MASK: 775 case RISCV::PseudoVSSE64_V_M1: 776 case RISCV::PseudoVSSE64_V_M1_MASK: 777 case RISCV::PseudoVSSE64_V_M2: 778 case RISCV::PseudoVSSE64_V_M2_MASK: 779 case RISCV::PseudoVSSE64_V_M4: 780 case RISCV::PseudoVSSE64_V_M4_MASK: 781 case RISCV::PseudoVSSE64_V_M8: 782 case RISCV::PseudoVSSE64_V_M8_MASK: 783 EEW = 64; 784 break; 785 } 786 787 return CurInfo.isCompatibleWithLoadStoreEEW(EEW, Require); 788 } 789 790 bool RISCVInsertVSETVLI::computeVLVTYPEChanges(const MachineBasicBlock &MBB) { 791 bool HadVectorOp = false; 792 793 BlockData &BBInfo = BlockInfo[MBB.getNumber()]; 794 for (const MachineInstr &MI : MBB) { 795 // If this is an explicit VSETVLI or VSETIVLI, update our state. 796 if (MI.getOpcode() == RISCV::PseudoVSETVLI || 797 MI.getOpcode() == RISCV::PseudoVSETVLIX0 || 798 MI.getOpcode() == RISCV::PseudoVSETIVLI) { 799 HadVectorOp = true; 800 BBInfo.Change = getInfoForVSETVLI(MI); 801 continue; 802 } 803 804 uint64_t TSFlags = MI.getDesc().TSFlags; 805 if (RISCVII::hasSEWOp(TSFlags)) { 806 HadVectorOp = true; 807 808 VSETVLIInfo NewInfo = computeInfoForInstr(MI, TSFlags, MRI); 809 810 if (!BBInfo.Change.isValid()) { 811 BBInfo.Change = NewInfo; 812 } else { 813 // If this instruction isn't compatible with the previous VL/VTYPE 814 // we need to insert a VSETVLI. 815 // If this is a unit-stride or strided load/store, we may be able to use 816 // the EMUL=(EEW/SEW)*LMUL relationship to avoid changing vtype. 817 // NOTE: We only do this if the vtype we're comparing against was 818 // created in this block. We need the first and third phase to treat 819 // the store the same way. 820 if (!canSkipVSETVLIForLoadStore(MI, NewInfo, BBInfo.Change) && 821 needVSETVLI(NewInfo, BBInfo.Change)) 822 BBInfo.Change = NewInfo; 823 } 824 } 825 826 // If this is something that updates VL/VTYPE that we don't know about, set 827 // the state to unknown. 828 if (MI.isCall() || MI.isInlineAsm() || MI.modifiesRegister(RISCV::VL) || 829 MI.modifiesRegister(RISCV::VTYPE)) { 830 BBInfo.Change = VSETVLIInfo::getUnknown(); 831 } 832 } 833 834 // Initial exit state is whatever change we found in the block. 835 BBInfo.Exit = BBInfo.Change; 836 837 return HadVectorOp; 838 } 839 840 void RISCVInsertVSETVLI::computeIncomingVLVTYPE(const MachineBasicBlock &MBB) { 841 BlockData &BBInfo = BlockInfo[MBB.getNumber()]; 842 843 BBInfo.InQueue = false; 844 845 VSETVLIInfo InInfo; 846 if (MBB.pred_empty()) { 847 // There are no predecessors, so use the default starting status. 848 InInfo.setUnknown(); 849 } else { 850 for (MachineBasicBlock *P : MBB.predecessors()) 851 InInfo = InInfo.intersect(BlockInfo[P->getNumber()].Exit); 852 } 853 854 // If we don't have any valid predecessor value, wait until we do. 855 if (!InInfo.isValid()) 856 return; 857 858 BBInfo.Pred = InInfo; 859 860 VSETVLIInfo TmpStatus = BBInfo.Pred.merge(BBInfo.Change); 861 862 // If the new exit value matches the old exit value, we don't need to revisit 863 // any blocks. 864 if (BBInfo.Exit == TmpStatus) 865 return; 866 867 BBInfo.Exit = TmpStatus; 868 869 // Add the successors to the work list so we can propagate the changed exit 870 // status. 871 for (MachineBasicBlock *S : MBB.successors()) 872 if (!BlockInfo[S->getNumber()].InQueue) 873 WorkList.push(S); 874 } 875 876 // If we weren't able to prove a vsetvli was directly unneeded, it might still 877 // be/ unneeded if the AVL is a phi node where all incoming values are VL 878 // outputs from the last VSETVLI in their respective basic blocks. 879 bool RISCVInsertVSETVLI::needVSETVLIPHI(const VSETVLIInfo &Require, 880 const MachineBasicBlock &MBB) { 881 if (DisableInsertVSETVLPHIOpt) 882 return true; 883 884 if (!Require.hasAVLReg()) 885 return true; 886 887 Register AVLReg = Require.getAVLReg(); 888 if (!AVLReg.isVirtual()) 889 return true; 890 891 // We need the AVL to be produce by a PHI node in this basic block. 892 MachineInstr *PHI = MRI->getVRegDef(AVLReg); 893 if (!PHI || PHI->getOpcode() != RISCV::PHI || PHI->getParent() != &MBB) 894 return true; 895 896 for (unsigned PHIOp = 1, NumOps = PHI->getNumOperands(); PHIOp != NumOps; 897 PHIOp += 2) { 898 Register InReg = PHI->getOperand(PHIOp).getReg(); 899 MachineBasicBlock *PBB = PHI->getOperand(PHIOp + 1).getMBB(); 900 const BlockData &PBBInfo = BlockInfo[PBB->getNumber()]; 901 // If the exit from the predecessor has the VTYPE we are looking for 902 // we might be able to avoid a VSETVLI. 903 if (PBBInfo.Exit.isUnknown() || 904 !PBBInfo.Exit.hasCompatibleVTYPE(Require, /*Strict*/ false)) 905 return true; 906 907 // We need the PHI input to the be the output of a VSET(I)VLI. 908 MachineInstr *DefMI = MRI->getVRegDef(InReg); 909 if (!DefMI || (DefMI->getOpcode() != RISCV::PseudoVSETVLI && 910 DefMI->getOpcode() != RISCV::PseudoVSETVLIX0 && 911 DefMI->getOpcode() != RISCV::PseudoVSETIVLI)) 912 return true; 913 914 // We found a VSET(I)VLI make sure it matches the output of the 915 // predecessor block. 916 VSETVLIInfo DefInfo = getInfoForVSETVLI(*DefMI); 917 if (!DefInfo.hasSameAVL(PBBInfo.Exit) || 918 !DefInfo.hasSameVTYPE(PBBInfo.Exit)) 919 return true; 920 } 921 922 // If all the incoming values to the PHI checked out, we don't need 923 // to insert a VSETVLI. 924 return false; 925 } 926 927 void RISCVInsertVSETVLI::emitVSETVLIs(MachineBasicBlock &MBB) { 928 VSETVLIInfo CurInfo; 929 // Only be set if current VSETVLIInfo is from an explicit VSET(I)VLI. 930 MachineInstr *PrevVSETVLIMI = nullptr; 931 932 for (MachineInstr &MI : MBB) { 933 // If this is an explicit VSETVLI or VSETIVLI, update our state. 934 if (MI.getOpcode() == RISCV::PseudoVSETVLI || 935 MI.getOpcode() == RISCV::PseudoVSETVLIX0 || 936 MI.getOpcode() == RISCV::PseudoVSETIVLI) { 937 // Conservatively, mark the VL and VTYPE as live. 938 assert(MI.getOperand(3).getReg() == RISCV::VL && 939 MI.getOperand(4).getReg() == RISCV::VTYPE && 940 "Unexpected operands where VL and VTYPE should be"); 941 MI.getOperand(3).setIsDead(false); 942 MI.getOperand(4).setIsDead(false); 943 CurInfo = getInfoForVSETVLI(MI); 944 PrevVSETVLIMI = &MI; 945 continue; 946 } 947 948 uint64_t TSFlags = MI.getDesc().TSFlags; 949 if (RISCVII::hasSEWOp(TSFlags)) { 950 VSETVLIInfo NewInfo = computeInfoForInstr(MI, TSFlags, MRI); 951 if (RISCVII::hasVLOp(TSFlags)) { 952 unsigned Offset = 2; 953 if (RISCVII::hasVecPolicyOp(TSFlags)) 954 Offset = 3; 955 MachineOperand &VLOp = 956 MI.getOperand(MI.getNumExplicitOperands() - Offset); 957 if (VLOp.isReg()) { 958 // Erase the AVL operand from the instruction. 959 VLOp.setReg(RISCV::NoRegister); 960 VLOp.setIsKill(false); 961 } 962 MI.addOperand(MachineOperand::CreateReg(RISCV::VL, /*isDef*/ false, 963 /*isImp*/ true)); 964 } 965 MI.addOperand(MachineOperand::CreateReg(RISCV::VTYPE, /*isDef*/ false, 966 /*isImp*/ true)); 967 968 if (!CurInfo.isValid()) { 969 // We haven't found any vector instructions or VL/VTYPE changes yet, 970 // use the predecessor information. 971 assert(BlockInfo[MBB.getNumber()].Pred.isValid() && 972 "Expected a valid predecessor state."); 973 if (needVSETVLI(NewInfo, BlockInfo[MBB.getNumber()].Pred) && 974 needVSETVLIPHI(NewInfo, MBB)) { 975 insertVSETVLI(MBB, MI, NewInfo, BlockInfo[MBB.getNumber()].Pred); 976 CurInfo = NewInfo; 977 } 978 } else { 979 // If this instruction isn't compatible with the previous VL/VTYPE 980 // we need to insert a VSETVLI. 981 // If this is a unit-stride or strided load/store, we may be able to use 982 // the EMUL=(EEW/SEW)*LMUL relationship to avoid changing vtype. 983 // NOTE: We can't use predecessor information for the store. We must 984 // treat it the same as the first phase so that we produce the correct 985 // vl/vtype for succesor blocks. 986 if (!canSkipVSETVLIForLoadStore(MI, NewInfo, CurInfo) && 987 needVSETVLI(NewInfo, CurInfo)) { 988 // If the previous VL/VTYPE is set by VSETVLI and do not use, Merge it 989 // with current VL/VTYPE. 990 bool NeedInsertVSETVLI = true; 991 if (PrevVSETVLIMI) { 992 bool HasSameAVL = 993 CurInfo.hasSameAVL(NewInfo) || 994 (NewInfo.hasAVLReg() && NewInfo.getAVLReg().isVirtual() && 995 NewInfo.getAVLReg() == PrevVSETVLIMI->getOperand(0).getReg()); 996 // If these two VSETVLI have the same AVL and the same VLMAX, 997 // we could merge these two VSETVLI. 998 if (HasSameAVL && 999 CurInfo.getSEWLMULRatio() == NewInfo.getSEWLMULRatio()) { 1000 PrevVSETVLIMI->getOperand(2).setImm(NewInfo.encodeVTYPE()); 1001 NeedInsertVSETVLI = false; 1002 } 1003 } 1004 if (NeedInsertVSETVLI) 1005 insertVSETVLI(MBB, MI, NewInfo, CurInfo); 1006 CurInfo = NewInfo; 1007 } 1008 } 1009 PrevVSETVLIMI = nullptr; 1010 } 1011 1012 // If this is something updates VL/VTYPE that we don't know about, set 1013 // the state to unknown. 1014 if (MI.isCall() || MI.isInlineAsm() || MI.modifiesRegister(RISCV::VL) || 1015 MI.modifiesRegister(RISCV::VTYPE)) { 1016 CurInfo = VSETVLIInfo::getUnknown(); 1017 PrevVSETVLIMI = nullptr; 1018 } 1019 } 1020 } 1021 1022 bool RISCVInsertVSETVLI::runOnMachineFunction(MachineFunction &MF) { 1023 // Skip if the vector extension is not enabled. 1024 const RISCVSubtarget &ST = MF.getSubtarget<RISCVSubtarget>(); 1025 if (!ST.hasVInstructions()) 1026 return false; 1027 1028 TII = ST.getInstrInfo(); 1029 MRI = &MF.getRegInfo(); 1030 1031 assert(BlockInfo.empty() && "Expect empty block infos"); 1032 BlockInfo.resize(MF.getNumBlockIDs()); 1033 1034 bool HaveVectorOp = false; 1035 1036 // Phase 1 - determine how VL/VTYPE are affected by the each block. 1037 for (const MachineBasicBlock &MBB : MF) 1038 HaveVectorOp |= computeVLVTYPEChanges(MBB); 1039 1040 // If we didn't find any instructions that need VSETVLI, we're done. 1041 if (HaveVectorOp) { 1042 // Phase 2 - determine the exit VL/VTYPE from each block. We add all 1043 // blocks to the list here, but will also add any that need to be revisited 1044 // during Phase 2 processing. 1045 for (const MachineBasicBlock &MBB : MF) { 1046 WorkList.push(&MBB); 1047 BlockInfo[MBB.getNumber()].InQueue = true; 1048 } 1049 while (!WorkList.empty()) { 1050 const MachineBasicBlock &MBB = *WorkList.front(); 1051 WorkList.pop(); 1052 computeIncomingVLVTYPE(MBB); 1053 } 1054 1055 // Phase 3 - add any vsetvli instructions needed in the block. Use the 1056 // Phase 2 information to avoid adding vsetvlis before the first vector 1057 // instruction in the block if the VL/VTYPE is satisfied by its 1058 // predecessors. 1059 for (MachineBasicBlock &MBB : MF) 1060 emitVSETVLIs(MBB); 1061 } 1062 1063 BlockInfo.clear(); 1064 1065 return HaveVectorOp; 1066 } 1067 1068 /// Returns an instance of the Insert VSETVLI pass. 1069 FunctionPass *llvm::createRISCVInsertVSETVLIPass() { 1070 return new RISCVInsertVSETVLI(); 1071 } 1072