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 bool TailAgnostic = false; 59 bool MaskAgnostic = false; 60 61 public: 62 VSETVLIInfo() : AVLImm(0) {} 63 64 static VSETVLIInfo getUnknown() { 65 VSETVLIInfo Info; 66 Info.setUnknown(); 67 return Info; 68 } 69 70 bool isValid() const { return State != Uninitialized; } 71 void setUnknown() { State = Unknown; } 72 bool isUnknown() const { return State == Unknown; } 73 74 void setAVLReg(Register Reg) { 75 AVLReg = Reg; 76 State = AVLIsReg; 77 } 78 79 void setAVLImm(unsigned Imm) { 80 AVLImm = Imm; 81 State = AVLIsImm; 82 } 83 84 bool hasAVLImm() const { return State == AVLIsImm; } 85 bool hasAVLReg() const { return State == AVLIsReg; } 86 Register getAVLReg() const { 87 assert(hasAVLReg()); 88 return AVLReg; 89 } 90 unsigned getAVLImm() const { 91 assert(hasAVLImm()); 92 return AVLImm; 93 } 94 95 bool hasSameAVL(const VSETVLIInfo &Other) const { 96 assert(isValid() && Other.isValid() && 97 "Can't compare invalid VSETVLIInfos"); 98 assert(!isUnknown() && !Other.isUnknown() && 99 "Can't compare AVL in unknown state"); 100 if (hasAVLReg() && Other.hasAVLReg()) 101 return getAVLReg() == Other.getAVLReg(); 102 103 if (hasAVLImm() && Other.hasAVLImm()) 104 return getAVLImm() == Other.getAVLImm(); 105 106 return false; 107 } 108 109 void setVTYPE(unsigned VType) { 110 assert(isValid() && !isUnknown() && 111 "Can't set VTYPE for uninitialized or unknown"); 112 VLMul = RISCVVType::getVLMUL(VType); 113 SEW = RISCVVType::getSEW(VType); 114 TailAgnostic = RISCVVType::isTailAgnostic(VType); 115 MaskAgnostic = RISCVVType::isMaskAgnostic(VType); 116 } 117 void setVTYPE(RISCVII::VLMUL L, unsigned S, bool TA, bool MA) { 118 assert(isValid() && !isUnknown() && 119 "Can't set VTYPE for uninitialized or unknown"); 120 VLMul = L; 121 SEW = S; 122 TailAgnostic = TA; 123 MaskAgnostic = MA; 124 } 125 126 unsigned encodeVTYPE() const { 127 assert(isValid() && !isUnknown() && 128 "Can't encode VTYPE for uninitialized or unknown"); 129 return RISCVVType::encodeVTYPE(VLMul, SEW, TailAgnostic, MaskAgnostic); 130 } 131 132 bool hasSameVTYPE(const VSETVLIInfo &Other) const { 133 assert(isValid() && Other.isValid() && 134 "Can't compare invalid VSETVLIInfos"); 135 assert(!isUnknown() && !Other.isUnknown() && 136 "Can't compare VTYPE in unknown state"); 137 return std::tie(VLMul, SEW, TailAgnostic, MaskAgnostic) == 138 std::tie(Other.VLMul, Other.SEW, Other.TailAgnostic, 139 Other.MaskAgnostic); 140 } 141 142 // Convert VLMUL to a fixed point value with 3 bits of fraction. 143 unsigned getSEWLMULRatio() const { 144 assert(isValid() && !isUnknown() && 145 "Can't use VTYPE for uninitialized or unknown"); 146 unsigned LMul; 147 bool Fractional; 148 std::tie(LMul, Fractional) = RISCVVType::decodeVLMUL(VLMul); 149 150 // Convert LMul to a fixed point value with 3 fractional bits. 151 LMul = Fractional ? (8 / LMul) : (LMul * 8); 152 153 assert(SEW >= 8 && "Unexpected SEW value"); 154 return (SEW * 8) / LMul; 155 } 156 157 // Check if the VTYPE for these two VSETVLIInfos produce the same VLMAX. 158 bool hasSameVLMAX(const VSETVLIInfo &Other) const { 159 assert(isValid() && Other.isValid() && 160 "Can't compare invalid VSETVLIInfos"); 161 assert(!isUnknown() && !Other.isUnknown() && 162 "Can't compare VTYPE in unknown state"); 163 return getSEWLMULRatio() == Other.getSEWLMULRatio(); 164 } 165 166 bool isCompatible(const VSETVLIInfo &Other) const { 167 assert(isValid() && Other.isValid() && 168 "Can't compare invalid VSETVLIInfos"); 169 // Nothing is compatible with Unknown. 170 if (isUnknown() || Other.isUnknown()) 171 return false; 172 173 // If other doesn't need an AVLReg and the SEW matches, consider it 174 // compatible. 175 if (Other.hasAVLReg() && Other.AVLReg == RISCV::NoRegister) { 176 if (SEW == Other.SEW) 177 return true; 178 } 179 180 // VTypes must match. 181 if (!hasSameVTYPE(Other)) 182 return false; 183 184 if (hasAVLImm() != Other.hasAVLImm()) 185 return false; 186 187 if (hasAVLImm()) 188 return getAVLImm() == Other.getAVLImm(); 189 190 return getAVLReg() == Other.getAVLReg(); 191 } 192 193 bool operator==(const VSETVLIInfo &Other) const { 194 // Uninitialized is only equal to another Uninitialized. 195 if (!isValid()) 196 return !Other.isValid(); 197 if (!Other.isValid()) 198 return !isValid(); 199 200 // Unknown is only equal to another Unknown. 201 if (isUnknown()) 202 return Other.isUnknown(); 203 if (Other.isUnknown()) 204 return isUnknown(); 205 206 // Otherwise compare the VTYPE and AVL. 207 return hasSameVTYPE(Other) && hasSameAVL(Other); 208 } 209 210 bool operator!=(const VSETVLIInfo &Other) const { return !(*this == Other); } 211 212 // Calculate the VSETVLIInfo visible to a block assuming this and Other are 213 // both predecessors. 214 VSETVLIInfo intersect(const VSETVLIInfo &Other) const { 215 // If the new value isn't valid, ignore it. 216 if (!Other.isValid()) 217 return *this; 218 219 // If this value isn't valid, this must be the first predecessor, use it. 220 if (!isValid()) 221 return Other; 222 223 if (*this == Other) 224 return *this; 225 226 // If the configurations don't match, assume unknown. 227 return VSETVLIInfo::getUnknown(); 228 } 229 230 // Calculate the VSETVLIInfo visible at the end of the block assuming this 231 // is the predecessor value, and Other is change for this block. 232 VSETVLIInfo merge(const VSETVLIInfo &Other) const { 233 assert(isValid() && "Can only merge with a valid VSETVLInfo"); 234 235 // Nothing changed from the predecessor, keep it. 236 if (!Other.isValid()) 237 return *this; 238 239 // If the change is compatible with the input, we won't create a VSETVLI 240 // and should keep the predecessor. 241 if (isCompatible(Other)) 242 return *this; 243 244 // Otherwise just use whatever is in this block. 245 return Other; 246 } 247 }; 248 249 struct BlockData { 250 // The VSETVLIInfo that represents the net changes to the VL/VTYPE registers 251 // made by this block. Calculated in Phase 1. 252 VSETVLIInfo Change; 253 254 // The VSETVLIInfo that represents the VL/VTYPE settings on exit from this 255 // block. Calculated in Phase 2. 256 VSETVLIInfo Exit; 257 258 // The VSETVLIInfo that represents the VL/VTYPE settings from all predecessor 259 // blocks. Calculated in Phase 2, and used by Phase 3. 260 VSETVLIInfo Pred; 261 262 // Keeps track of whether the block is already in the queue. 263 bool InQueue = false; 264 265 BlockData() {} 266 }; 267 268 class RISCVInsertVSETVLI : public MachineFunctionPass { 269 const TargetInstrInfo *TII; 270 MachineRegisterInfo *MRI; 271 272 std::vector<BlockData> BlockInfo; 273 std::queue<const MachineBasicBlock *> WorkList; 274 275 public: 276 static char ID; 277 278 RISCVInsertVSETVLI() : MachineFunctionPass(ID) { 279 initializeRISCVInsertVSETVLIPass(*PassRegistry::getPassRegistry()); 280 } 281 bool runOnMachineFunction(MachineFunction &MF) override; 282 283 void getAnalysisUsage(AnalysisUsage &AU) const override { 284 AU.setPreservesCFG(); 285 MachineFunctionPass::getAnalysisUsage(AU); 286 } 287 288 StringRef getPassName() const override { return RISCV_INSERT_VSETVLI_NAME; } 289 290 private: 291 bool needVSETVLI(const VSETVLIInfo &Require, const VSETVLIInfo &CurInfo); 292 bool needVSETVLIPHI(const VSETVLIInfo &Require, const MachineBasicBlock &MBB); 293 void insertVSETVLI(MachineBasicBlock &MBB, MachineInstr &MI, 294 const VSETVLIInfo &Info, const VSETVLIInfo &PrevInfo); 295 296 bool computeVLVTYPEChanges(const MachineBasicBlock &MBB); 297 void computeIncomingVLVTYPE(const MachineBasicBlock &MBB); 298 void emitVSETVLIs(MachineBasicBlock &MBB); 299 }; 300 301 } // end anonymous namespace 302 303 char RISCVInsertVSETVLI::ID = 0; 304 305 INITIALIZE_PASS(RISCVInsertVSETVLI, DEBUG_TYPE, RISCV_INSERT_VSETVLI_NAME, 306 false, false) 307 308 static MachineInstr *elideCopies(MachineInstr *MI, 309 const MachineRegisterInfo *MRI) { 310 while (true) { 311 if (!MI->isFullCopy()) 312 return MI; 313 if (!Register::isVirtualRegister(MI->getOperand(1).getReg())) 314 return nullptr; 315 MI = MRI->getVRegDef(MI->getOperand(1).getReg()); 316 if (!MI) 317 return nullptr; 318 } 319 } 320 321 static VSETVLIInfo computeInfoForInstr(const MachineInstr &MI, uint64_t TSFlags, 322 const MachineRegisterInfo *MRI) { 323 VSETVLIInfo InstrInfo; 324 unsigned NumOperands = MI.getNumExplicitOperands(); 325 326 RISCVII::VLMUL VLMul = RISCVII::getLMul(TSFlags); 327 328 unsigned Log2SEW = MI.getOperand(NumOperands - 1).getImm(); 329 unsigned SEW = 1 << Log2SEW; 330 assert(RISCVVType::isValidSEW(SEW) && "Unexpected SEW"); 331 332 // Default to tail agnostic unless the destination is tied to a source. 333 // Unless the source is undef. In that case the user would have some control 334 // over the tail values. The tail policy is also ignored on instructions 335 // that only update element 0 like vmv.s.x or reductions so use agnostic 336 // there to match the common case. 337 // FIXME: This is conservatively correct, but we might want to detect that 338 // the input is undefined. 339 bool ForceTailAgnostic = RISCVII::doesForceTailAgnostic(TSFlags); 340 bool TailAgnostic = true; 341 unsigned UseOpIdx; 342 if (!ForceTailAgnostic && MI.isRegTiedToUseOperand(0, &UseOpIdx)) { 343 TailAgnostic = false; 344 // If the tied operand is an IMPLICIT_DEF we can keep TailAgnostic. 345 const MachineOperand &UseMO = MI.getOperand(UseOpIdx); 346 MachineInstr *UseMI = MRI->getVRegDef(UseMO.getReg()); 347 if (UseMI) { 348 UseMI = elideCopies(UseMI, MRI); 349 if (UseMI && UseMI->isImplicitDef()) 350 TailAgnostic = true; 351 } 352 } 353 354 if (RISCVII::hasVLOp(TSFlags)) { 355 const MachineOperand &VLOp = MI.getOperand(MI.getNumExplicitOperands() - 2); 356 if (VLOp.isImm()) 357 InstrInfo.setAVLImm(VLOp.getImm()); 358 else 359 InstrInfo.setAVLReg(VLOp.getReg()); 360 } else 361 InstrInfo.setAVLReg(RISCV::NoRegister); 362 InstrInfo.setVTYPE(VLMul, SEW, /*TailAgnostic*/ TailAgnostic, 363 /*MaskAgnostic*/ false); 364 365 return InstrInfo; 366 } 367 368 void RISCVInsertVSETVLI::insertVSETVLI(MachineBasicBlock &MBB, MachineInstr &MI, 369 const VSETVLIInfo &Info, 370 const VSETVLIInfo &PrevInfo) { 371 DebugLoc DL = MI.getDebugLoc(); 372 373 // Use X0, X0 form if the AVL is the same and the SEW+LMUL gives the same 374 // VLMAX. 375 if (PrevInfo.isValid() && !PrevInfo.isUnknown() && 376 Info.hasSameAVL(PrevInfo) && Info.hasSameVLMAX(PrevInfo)) { 377 BuildMI(MBB, MI, DL, TII->get(RISCV::PseudoVSETVLI)) 378 .addReg(RISCV::X0, RegState::Define | RegState::Dead) 379 .addReg(RISCV::X0, RegState::Kill) 380 .addImm(Info.encodeVTYPE()) 381 .addReg(RISCV::VL, RegState::Implicit); 382 return; 383 } 384 385 if (Info.hasAVLImm()) { 386 BuildMI(MBB, MI, DL, TII->get(RISCV::PseudoVSETIVLI)) 387 .addReg(RISCV::X0, RegState::Define | RegState::Dead) 388 .addImm(Info.getAVLImm()) 389 .addImm(Info.encodeVTYPE()); 390 return; 391 } 392 393 Register AVLReg = Info.getAVLReg(); 394 if (AVLReg == RISCV::NoRegister) { 395 BuildMI(MBB, MI, DL, TII->get(RISCV::PseudoVSETVLI)) 396 .addReg(RISCV::X0, RegState::Define | RegState::Dead) 397 .addReg(RISCV::X0, RegState::Kill) 398 .addImm(Info.encodeVTYPE()) 399 .addReg(RISCV::VL, RegState::Implicit); 400 return; 401 } 402 403 // Use X0 as the DestReg unless AVLReg is X0. 404 Register DestReg = RISCV::X0; 405 if (AVLReg == RISCV::X0) 406 DestReg = MRI->createVirtualRegister(&RISCV::GPRRegClass); 407 BuildMI(MBB, MI, DL, TII->get(RISCV::PseudoVSETVLI)) 408 .addReg(DestReg, RegState::Define | RegState::Dead) 409 .addReg(AVLReg) 410 .addImm(Info.encodeVTYPE()); 411 } 412 413 // Return a VSETVLIInfo representing the changes made by this VSETVLI or 414 // VSETIVLI instruction. 415 static VSETVLIInfo getInfoForVSETVLI(const MachineInstr &MI) { 416 VSETVLIInfo NewInfo; 417 if (MI.getOpcode() == RISCV::PseudoVSETVLI) { 418 Register AVLReg = MI.getOperand(1).getReg(); 419 assert((AVLReg != RISCV::X0 || MI.getOperand(0).getReg() != RISCV::X0) && 420 "Can't handle X0, X0 vsetvli yet"); 421 NewInfo.setAVLReg(AVLReg); 422 } else { 423 assert(MI.getOpcode() == RISCV::PseudoVSETIVLI); 424 NewInfo.setAVLImm(MI.getOperand(1).getImm()); 425 } 426 NewInfo.setVTYPE(MI.getOperand(2).getImm()); 427 428 return NewInfo; 429 } 430 431 bool RISCVInsertVSETVLI::needVSETVLI(const VSETVLIInfo &Require, 432 const VSETVLIInfo &CurInfo) { 433 if (CurInfo.isCompatible(Require)) 434 return false; 435 436 // We didn't find a compatible value. If our AVL is a virtual register, 437 // it might be defined by a VSET(I)VLI. If it has the same VTYPE we need 438 // and the last VL/VTYPE we observed is the same, we don't need a 439 // VSETVLI here. 440 if (!CurInfo.isUnknown() && Require.hasAVLReg() && 441 Require.getAVLReg().isVirtual() && Require.hasSameVTYPE(CurInfo)) { 442 if (MachineInstr *DefMI = MRI->getVRegDef(Require.getAVLReg())) { 443 if (DefMI->getOpcode() == RISCV::PseudoVSETVLI || 444 DefMI->getOpcode() == RISCV::PseudoVSETIVLI) { 445 VSETVLIInfo DefInfo = getInfoForVSETVLI(*DefMI); 446 if (DefInfo.hasSameAVL(CurInfo) && DefInfo.hasSameVTYPE(CurInfo)) 447 return false; 448 } 449 } 450 } 451 452 return true; 453 } 454 455 bool RISCVInsertVSETVLI::computeVLVTYPEChanges(const MachineBasicBlock &MBB) { 456 bool HadVectorOp = false; 457 458 BlockData &BBInfo = BlockInfo[MBB.getNumber()]; 459 for (const MachineInstr &MI : MBB) { 460 // If this is an explicit VSETVLI or VSETIVLI, update our state. 461 if (MI.getOpcode() == RISCV::PseudoVSETVLI || 462 MI.getOpcode() == RISCV::PseudoVSETIVLI) { 463 HadVectorOp = true; 464 BBInfo.Change = getInfoForVSETVLI(MI); 465 continue; 466 } 467 468 uint64_t TSFlags = MI.getDesc().TSFlags; 469 if (RISCVII::hasSEWOp(TSFlags)) { 470 HadVectorOp = true; 471 472 VSETVLIInfo NewInfo = computeInfoForInstr(MI, TSFlags, MRI); 473 474 if (!BBInfo.Change.isValid()) { 475 BBInfo.Change = NewInfo; 476 } else { 477 // If this instruction isn't compatible with the previous VL/VTYPE 478 // we need to insert a VSETVLI. 479 if (needVSETVLI(NewInfo, BBInfo.Change)) 480 BBInfo.Change = NewInfo; 481 } 482 } 483 484 // If this is something that updates VL/VTYPE that we don't know about, set 485 // the state to unknown. 486 if (MI.isCall() || MI.isInlineAsm() || MI.modifiesRegister(RISCV::VL) || 487 MI.modifiesRegister(RISCV::VTYPE)) { 488 BBInfo.Change = VSETVLIInfo::getUnknown(); 489 } 490 } 491 492 // Initial exit state is whatever change we found in the block. 493 BBInfo.Exit = BBInfo.Change; 494 495 return HadVectorOp; 496 } 497 498 void RISCVInsertVSETVLI::computeIncomingVLVTYPE(const MachineBasicBlock &MBB) { 499 BlockData &BBInfo = BlockInfo[MBB.getNumber()]; 500 501 BBInfo.InQueue = false; 502 503 VSETVLIInfo InInfo; 504 if (MBB.pred_empty()) { 505 // There are no predecessors, so use the default starting status. 506 InInfo.setUnknown(); 507 } else { 508 for (MachineBasicBlock *P : MBB.predecessors()) 509 InInfo = InInfo.intersect(BlockInfo[P->getNumber()].Exit); 510 } 511 512 // If we don't have any valid predecessor value, wait until we do. 513 if (!InInfo.isValid()) 514 return; 515 516 BBInfo.Pred = InInfo; 517 518 VSETVLIInfo TmpStatus = BBInfo.Pred.merge(BBInfo.Change); 519 520 // If the new exit value matches the old exit value, we don't need to revisit 521 // any blocks. 522 if (BBInfo.Exit == TmpStatus) 523 return; 524 525 BBInfo.Exit = TmpStatus; 526 527 // Add the successors to the work list so we can propagate the changed exit 528 // status. 529 for (MachineBasicBlock *S : MBB.successors()) 530 if (!BlockInfo[S->getNumber()].InQueue) 531 WorkList.push(S); 532 } 533 534 // If we weren't able to prove a vsetvli was directly unneeded, it might still 535 // be/ unneeded if the AVL is a phi node where all incoming values are VL 536 // outputs from the last VSETVLI in their respective basic blocks. 537 bool RISCVInsertVSETVLI::needVSETVLIPHI(const VSETVLIInfo &Require, 538 const MachineBasicBlock &MBB) { 539 if (DisableInsertVSETVLPHIOpt) 540 return true; 541 542 if (!Require.hasAVLReg()) 543 return true; 544 545 Register AVLReg = Require.getAVLReg(); 546 if (!AVLReg.isVirtual()) 547 return true; 548 549 // We need the AVL to be produce by a PHI node in this basic block. 550 MachineInstr *PHI = MRI->getVRegDef(AVLReg); 551 if (!PHI || PHI->getOpcode() != RISCV::PHI || PHI->getParent() != &MBB) 552 return true; 553 554 for (unsigned PHIOp = 1, NumOps = PHI->getNumOperands(); PHIOp != NumOps; 555 PHIOp += 2) { 556 Register InReg = PHI->getOperand(PHIOp).getReg(); 557 MachineBasicBlock *PBB = PHI->getOperand(PHIOp + 1).getMBB(); 558 const BlockData &PBBInfo = BlockInfo[PBB->getNumber()]; 559 // If the exit from the predecessor has the VTYPE we are looking for 560 // we might be able to avoid a VSETVLI. 561 if (PBBInfo.Exit.isUnknown() || !PBBInfo.Exit.hasSameVTYPE(Require)) 562 return true; 563 564 // We need the PHI input to the be the output of a VSET(I)VLI. 565 MachineInstr *DefMI = MRI->getVRegDef(InReg); 566 if (!DefMI || (DefMI->getOpcode() != RISCV::PseudoVSETVLI && 567 DefMI->getOpcode() != RISCV::PseudoVSETIVLI)) 568 return true; 569 570 // We found a VSET(I)VLI make sure it matches the output of the 571 // predecessor block. 572 VSETVLIInfo DefInfo = getInfoForVSETVLI(*DefMI); 573 if (!DefInfo.hasSameAVL(PBBInfo.Exit) || 574 !DefInfo.hasSameVTYPE(PBBInfo.Exit)) 575 return true; 576 } 577 578 // If all the incoming values to the PHI checked out, we don't need 579 // to insert a VSETVLI. 580 return false; 581 } 582 583 void RISCVInsertVSETVLI::emitVSETVLIs(MachineBasicBlock &MBB) { 584 VSETVLIInfo CurInfo; 585 586 for (MachineInstr &MI : MBB) { 587 // If this is an explicit VSETVLI or VSETIVLI, update our state. 588 if (MI.getOpcode() == RISCV::PseudoVSETVLI || 589 MI.getOpcode() == RISCV::PseudoVSETIVLI) { 590 // Conservatively, mark the VL and VTYPE as live. 591 assert(MI.getOperand(3).getReg() == RISCV::VL && 592 MI.getOperand(4).getReg() == RISCV::VTYPE && 593 "Unexpected operands where VL and VTYPE should be"); 594 MI.getOperand(3).setIsDead(false); 595 MI.getOperand(4).setIsDead(false); 596 CurInfo = getInfoForVSETVLI(MI); 597 continue; 598 } 599 600 uint64_t TSFlags = MI.getDesc().TSFlags; 601 if (RISCVII::hasSEWOp(TSFlags)) { 602 VSETVLIInfo NewInfo = computeInfoForInstr(MI, TSFlags, MRI); 603 if (RISCVII::hasVLOp(TSFlags)) { 604 MachineOperand &VLOp = MI.getOperand(MI.getNumExplicitOperands() - 2); 605 if (VLOp.isReg()) { 606 // Erase the AVL operand from the instruction. 607 VLOp.setReg(RISCV::NoRegister); 608 VLOp.setIsKill(false); 609 } 610 MI.addOperand(MachineOperand::CreateReg(RISCV::VL, /*isDef*/ false, 611 /*isImp*/ true)); 612 } 613 MI.addOperand(MachineOperand::CreateReg(RISCV::VTYPE, /*isDef*/ false, 614 /*isImp*/ true)); 615 616 if (!CurInfo.isValid()) { 617 // We haven't found any vector instructions or VL/VTYPE changes yet, 618 // use the predecessor information. 619 assert(BlockInfo[MBB.getNumber()].Pred.isValid() && 620 "Expected a valid predecessor state."); 621 if (needVSETVLI(NewInfo, BlockInfo[MBB.getNumber()].Pred) && 622 needVSETVLIPHI(NewInfo, MBB)) { 623 insertVSETVLI(MBB, MI, NewInfo, BlockInfo[MBB.getNumber()].Pred); 624 CurInfo = NewInfo; 625 } 626 } else { 627 // If this instruction isn't compatible with the previous VL/VTYPE 628 // we need to insert a VSETVLI. 629 if (needVSETVLI(NewInfo, CurInfo)) { 630 insertVSETVLI(MBB, MI, NewInfo, CurInfo); 631 CurInfo = NewInfo; 632 } 633 } 634 } 635 636 // If this is something updates VL/VTYPE that we don't know about, set 637 // the state to unknown. 638 if (MI.isCall() || MI.isInlineAsm() || MI.modifiesRegister(RISCV::VL) || 639 MI.modifiesRegister(RISCV::VTYPE)) { 640 CurInfo = VSETVLIInfo::getUnknown(); 641 } 642 } 643 } 644 645 bool RISCVInsertVSETVLI::runOnMachineFunction(MachineFunction &MF) { 646 // Skip if the vector extension is not enabled. 647 const RISCVSubtarget &ST = MF.getSubtarget<RISCVSubtarget>(); 648 if (!ST.hasStdExtV()) 649 return false; 650 651 TII = ST.getInstrInfo(); 652 MRI = &MF.getRegInfo(); 653 654 assert(BlockInfo.empty() && "Expect empty block infos"); 655 BlockInfo.resize(MF.getNumBlockIDs()); 656 657 bool HaveVectorOp = false; 658 659 // Phase 1 - determine how VL/VTYPE are affected by the each block. 660 for (const MachineBasicBlock &MBB : MF) 661 HaveVectorOp |= computeVLVTYPEChanges(MBB); 662 663 // If we didn't find any instructions that need VSETVLI, we're done. 664 if (HaveVectorOp) { 665 // Phase 2 - determine the exit VL/VTYPE from each block. We add all 666 // blocks to the list here, but will also add any that need to be revisited 667 // during Phase 2 processing. 668 for (const MachineBasicBlock &MBB : MF) { 669 WorkList.push(&MBB); 670 BlockInfo[MBB.getNumber()].InQueue = true; 671 } 672 while (!WorkList.empty()) { 673 const MachineBasicBlock &MBB = *WorkList.front(); 674 WorkList.pop(); 675 computeIncomingVLVTYPE(MBB); 676 } 677 678 // Phase 3 - add any vsetvli instructions needed in the block. Use the 679 // Phase 2 information to avoid adding vsetvlis before the first vector 680 // instruction in the block if the VL/VTYPE is satisfied by its 681 // predecessors. 682 for (MachineBasicBlock &MBB : MF) 683 emitVSETVLIs(MBB); 684 } 685 686 BlockInfo.clear(); 687 688 return HaveVectorOp; 689 } 690 691 /// Returns an instance of the Insert VSETVLI pass. 692 FunctionPass *llvm::createRISCVInsertVSETVLIPass() { 693 return new RISCVInsertVSETVLI(); 694 } 695