1 //===- VPlan.cpp - Vectorizer Plan ----------------------------------------===// 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 /// \file 10 /// This is the LLVM vectorization plan. It represents a candidate for 11 /// vectorization, allowing to plan and optimize how to vectorize a given loop 12 /// before generating LLVM-IR. 13 /// The vectorizer uses vectorization plans to estimate the costs of potential 14 /// candidates and if profitable to execute the desired plan, generating vector 15 /// LLVM-IR code. 16 /// 17 //===----------------------------------------------------------------------===// 18 19 #include "VPlan.h" 20 #include "VPlanDominatorTree.h" 21 #include "llvm/ADT/DepthFirstIterator.h" 22 #include "llvm/ADT/PostOrderIterator.h" 23 #include "llvm/ADT/SmallVector.h" 24 #include "llvm/ADT/Twine.h" 25 #include "llvm/Analysis/LoopInfo.h" 26 #include "llvm/IR/BasicBlock.h" 27 #include "llvm/IR/CFG.h" 28 #include "llvm/IR/InstrTypes.h" 29 #include "llvm/IR/Instruction.h" 30 #include "llvm/IR/Instructions.h" 31 #include "llvm/IR/Type.h" 32 #include "llvm/IR/Value.h" 33 #include "llvm/Support/Casting.h" 34 #include "llvm/Support/CommandLine.h" 35 #include "llvm/Support/Debug.h" 36 #include "llvm/Support/ErrorHandling.h" 37 #include "llvm/Support/GenericDomTreeConstruction.h" 38 #include "llvm/Support/GraphWriter.h" 39 #include "llvm/Support/raw_ostream.h" 40 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 41 #include <cassert> 42 #include <iterator> 43 #include <string> 44 #include <vector> 45 46 using namespace llvm; 47 extern cl::opt<bool> EnableVPlanNativePath; 48 49 #define DEBUG_TYPE "vplan" 50 51 raw_ostream &llvm::operator<<(raw_ostream &OS, const VPValue &V) { 52 const VPInstruction *Instr = dyn_cast<VPInstruction>(&V); 53 VPSlotTracker SlotTracker( 54 (Instr && Instr->getParent()) ? Instr->getParent()->getPlan() : nullptr); 55 V.print(OS, SlotTracker); 56 return OS; 57 } 58 59 void VPValue::print(raw_ostream &OS, VPSlotTracker &SlotTracker) const { 60 if (const VPInstruction *Instr = dyn_cast<VPInstruction>(this)) 61 Instr->print(OS, SlotTracker); 62 else 63 printAsOperand(OS, SlotTracker); 64 } 65 66 void VPValue::dump() const { 67 const VPInstruction *Instr = dyn_cast<VPInstruction>(this); 68 VPSlotTracker SlotTracker( 69 (Instr && Instr->getParent()) ? Instr->getParent()->getPlan() : nullptr); 70 print(dbgs(), SlotTracker); 71 dbgs() << "\n"; 72 } 73 74 void VPRecipeBase::dump() const { 75 VPSlotTracker SlotTracker(nullptr); 76 print(dbgs(), "", SlotTracker); 77 dbgs() << "\n"; 78 } 79 80 VPUser *VPRecipeBase::toVPUser() { 81 if (auto *U = dyn_cast<VPInstruction>(this)) 82 return U; 83 if (auto *U = dyn_cast<VPWidenRecipe>(this)) 84 return U; 85 if (auto *U = dyn_cast<VPWidenCallRecipe>(this)) 86 return U; 87 if (auto *U = dyn_cast<VPWidenSelectRecipe>(this)) 88 return U; 89 if (auto *U = dyn_cast<VPWidenGEPRecipe>(this)) 90 return U; 91 if (auto *U = dyn_cast<VPBlendRecipe>(this)) 92 return U; 93 if (auto *U = dyn_cast<VPInterleaveRecipe>(this)) 94 return U; 95 if (auto *U = dyn_cast<VPReplicateRecipe>(this)) 96 return U; 97 if (auto *U = dyn_cast<VPBranchOnMaskRecipe>(this)) 98 return U; 99 if (auto *U = dyn_cast<VPWidenMemoryInstructionRecipe>(this)) 100 return U; 101 return nullptr; 102 } 103 104 VPValue *VPRecipeBase::toVPValue() { 105 if (auto *V = dyn_cast<VPInstruction>(this)) 106 return V; 107 if (auto *V = dyn_cast<VPWidenMemoryInstructionRecipe>(this)) 108 return V; 109 if (auto *V = dyn_cast<VPWidenCallRecipe>(this)) 110 return V; 111 if (auto *V = dyn_cast<VPWidenSelectRecipe>(this)) 112 return V; 113 if (auto *V = dyn_cast<VPWidenGEPRecipe>(this)) 114 return V; 115 return nullptr; 116 } 117 118 const VPValue *VPRecipeBase::toVPValue() const { 119 if (auto *V = dyn_cast<VPInstruction>(this)) 120 return V; 121 if (auto *V = dyn_cast<VPWidenMemoryInstructionRecipe>(this)) 122 return V; 123 if (auto *V = dyn_cast<VPWidenCallRecipe>(this)) 124 return V; 125 if (auto *V = dyn_cast<VPWidenSelectRecipe>(this)) 126 return V; 127 if (auto *V = dyn_cast<VPWidenGEPRecipe>(this)) 128 return V; 129 return nullptr; 130 } 131 132 // Get the top-most entry block of \p Start. This is the entry block of the 133 // containing VPlan. This function is templated to support both const and non-const blocks 134 template <typename T> static T *getPlanEntry(T *Start) { 135 T *Next = Start; 136 T *Current = Start; 137 while ((Next = Next->getParent())) 138 Current = Next; 139 140 SmallSetVector<T *, 8> WorkList; 141 WorkList.insert(Current); 142 143 for (unsigned i = 0; i < WorkList.size(); i++) { 144 T *Current = WorkList[i]; 145 if (Current->getNumPredecessors() == 0) 146 return Current; 147 auto &Predecessors = Current->getPredecessors(); 148 WorkList.insert(Predecessors.begin(), Predecessors.end()); 149 } 150 151 llvm_unreachable("VPlan without any entry node without predecessors"); 152 } 153 154 VPlan *VPBlockBase::getPlan() { return getPlanEntry(this)->Plan; } 155 156 const VPlan *VPBlockBase::getPlan() const { return getPlanEntry(this)->Plan; } 157 158 /// \return the VPBasicBlock that is the entry of Block, possibly indirectly. 159 const VPBasicBlock *VPBlockBase::getEntryBasicBlock() const { 160 const VPBlockBase *Block = this; 161 while (const VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block)) 162 Block = Region->getEntry(); 163 return cast<VPBasicBlock>(Block); 164 } 165 166 VPBasicBlock *VPBlockBase::getEntryBasicBlock() { 167 VPBlockBase *Block = this; 168 while (VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block)) 169 Block = Region->getEntry(); 170 return cast<VPBasicBlock>(Block); 171 } 172 173 void VPBlockBase::setPlan(VPlan *ParentPlan) { 174 assert(ParentPlan->getEntry() == this && 175 "Can only set plan on its entry block."); 176 Plan = ParentPlan; 177 } 178 179 /// \return the VPBasicBlock that is the exit of Block, possibly indirectly. 180 const VPBasicBlock *VPBlockBase::getExitBasicBlock() const { 181 const VPBlockBase *Block = this; 182 while (const VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block)) 183 Block = Region->getExit(); 184 return cast<VPBasicBlock>(Block); 185 } 186 187 VPBasicBlock *VPBlockBase::getExitBasicBlock() { 188 VPBlockBase *Block = this; 189 while (VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block)) 190 Block = Region->getExit(); 191 return cast<VPBasicBlock>(Block); 192 } 193 194 VPBlockBase *VPBlockBase::getEnclosingBlockWithSuccessors() { 195 if (!Successors.empty() || !Parent) 196 return this; 197 assert(Parent->getExit() == this && 198 "Block w/o successors not the exit of its parent."); 199 return Parent->getEnclosingBlockWithSuccessors(); 200 } 201 202 VPBlockBase *VPBlockBase::getEnclosingBlockWithPredecessors() { 203 if (!Predecessors.empty() || !Parent) 204 return this; 205 assert(Parent->getEntry() == this && 206 "Block w/o predecessors not the entry of its parent."); 207 return Parent->getEnclosingBlockWithPredecessors(); 208 } 209 210 void VPBlockBase::deleteCFG(VPBlockBase *Entry) { 211 SmallVector<VPBlockBase *, 8> Blocks; 212 213 VPValue DummyValue; 214 for (VPBlockBase *Block : depth_first(Entry)) { 215 // Drop all references in VPBasicBlocks and replace all uses with 216 // DummyValue. 217 if (auto *VPBB = dyn_cast<VPBasicBlock>(Block)) 218 VPBB->dropAllReferences(&DummyValue); 219 Blocks.push_back(Block); 220 } 221 222 for (VPBlockBase *Block : Blocks) 223 delete Block; 224 } 225 226 VPBasicBlock::iterator VPBasicBlock::getFirstNonPhi() { 227 iterator It = begin(); 228 while (It != end() && (isa<VPWidenPHIRecipe>(&*It) || 229 isa<VPWidenIntOrFpInductionRecipe>(&*It) || 230 isa<VPPredInstPHIRecipe>(&*It) || 231 isa<VPWidenCanonicalIVRecipe>(&*It))) 232 It++; 233 return It; 234 } 235 236 BasicBlock * 237 VPBasicBlock::createEmptyBasicBlock(VPTransformState::CFGState &CFG) { 238 // BB stands for IR BasicBlocks. VPBB stands for VPlan VPBasicBlocks. 239 // Pred stands for Predessor. Prev stands for Previous - last visited/created. 240 BasicBlock *PrevBB = CFG.PrevBB; 241 BasicBlock *NewBB = BasicBlock::Create(PrevBB->getContext(), getName(), 242 PrevBB->getParent(), CFG.LastBB); 243 LLVM_DEBUG(dbgs() << "LV: created " << NewBB->getName() << '\n'); 244 245 // Hook up the new basic block to its predecessors. 246 for (VPBlockBase *PredVPBlock : getHierarchicalPredecessors()) { 247 VPBasicBlock *PredVPBB = PredVPBlock->getExitBasicBlock(); 248 auto &PredVPSuccessors = PredVPBB->getSuccessors(); 249 BasicBlock *PredBB = CFG.VPBB2IRBB[PredVPBB]; 250 251 // In outer loop vectorization scenario, the predecessor BBlock may not yet 252 // be visited(backedge). Mark the VPBasicBlock for fixup at the end of 253 // vectorization. We do not encounter this case in inner loop vectorization 254 // as we start out by building a loop skeleton with the vector loop header 255 // and latch blocks. As a result, we never enter this function for the 256 // header block in the non VPlan-native path. 257 if (!PredBB) { 258 assert(EnableVPlanNativePath && 259 "Unexpected null predecessor in non VPlan-native path"); 260 CFG.VPBBsToFix.push_back(PredVPBB); 261 continue; 262 } 263 264 assert(PredBB && "Predecessor basic-block not found building successor."); 265 auto *PredBBTerminator = PredBB->getTerminator(); 266 LLVM_DEBUG(dbgs() << "LV: draw edge from" << PredBB->getName() << '\n'); 267 if (isa<UnreachableInst>(PredBBTerminator)) { 268 assert(PredVPSuccessors.size() == 1 && 269 "Predecessor ending w/o branch must have single successor."); 270 PredBBTerminator->eraseFromParent(); 271 BranchInst::Create(NewBB, PredBB); 272 } else { 273 assert(PredVPSuccessors.size() == 2 && 274 "Predecessor ending with branch must have two successors."); 275 unsigned idx = PredVPSuccessors.front() == this ? 0 : 1; 276 assert(!PredBBTerminator->getSuccessor(idx) && 277 "Trying to reset an existing successor block."); 278 PredBBTerminator->setSuccessor(idx, NewBB); 279 } 280 } 281 return NewBB; 282 } 283 284 void VPBasicBlock::execute(VPTransformState *State) { 285 bool Replica = State->Instance && 286 !(State->Instance->Part == 0 && State->Instance->Lane == 0); 287 VPBasicBlock *PrevVPBB = State->CFG.PrevVPBB; 288 VPBlockBase *SingleHPred = nullptr; 289 BasicBlock *NewBB = State->CFG.PrevBB; // Reuse it if possible. 290 291 // 1. Create an IR basic block, or reuse the last one if possible. 292 // The last IR basic block is reused, as an optimization, in three cases: 293 // A. the first VPBB reuses the loop header BB - when PrevVPBB is null; 294 // B. when the current VPBB has a single (hierarchical) predecessor which 295 // is PrevVPBB and the latter has a single (hierarchical) successor; and 296 // C. when the current VPBB is an entry of a region replica - where PrevVPBB 297 // is the exit of this region from a previous instance, or the predecessor 298 // of this region. 299 if (PrevVPBB && /* A */ 300 !((SingleHPred = getSingleHierarchicalPredecessor()) && 301 SingleHPred->getExitBasicBlock() == PrevVPBB && 302 PrevVPBB->getSingleHierarchicalSuccessor()) && /* B */ 303 !(Replica && getPredecessors().empty())) { /* C */ 304 NewBB = createEmptyBasicBlock(State->CFG); 305 State->Builder.SetInsertPoint(NewBB); 306 // Temporarily terminate with unreachable until CFG is rewired. 307 UnreachableInst *Terminator = State->Builder.CreateUnreachable(); 308 State->Builder.SetInsertPoint(Terminator); 309 // Register NewBB in its loop. In innermost loops its the same for all BB's. 310 Loop *L = State->LI->getLoopFor(State->CFG.LastBB); 311 L->addBasicBlockToLoop(NewBB, *State->LI); 312 State->CFG.PrevBB = NewBB; 313 } 314 315 // 2. Fill the IR basic block with IR instructions. 316 LLVM_DEBUG(dbgs() << "LV: vectorizing VPBB:" << getName() 317 << " in BB:" << NewBB->getName() << '\n'); 318 319 State->CFG.VPBB2IRBB[this] = NewBB; 320 State->CFG.PrevVPBB = this; 321 322 for (VPRecipeBase &Recipe : Recipes) 323 Recipe.execute(*State); 324 325 VPValue *CBV; 326 if (EnableVPlanNativePath && (CBV = getCondBit())) { 327 Value *IRCBV = CBV->getUnderlyingValue(); 328 assert(IRCBV && "Unexpected null underlying value for condition bit"); 329 330 // Condition bit value in a VPBasicBlock is used as the branch selector. In 331 // the VPlan-native path case, since all branches are uniform we generate a 332 // branch instruction using the condition value from vector lane 0 and dummy 333 // successors. The successors are fixed later when the successor blocks are 334 // visited. 335 Value *NewCond = State->Callback.getOrCreateVectorValues(IRCBV, 0); 336 NewCond = State->Builder.CreateExtractElement(NewCond, 337 State->Builder.getInt32(0)); 338 339 // Replace the temporary unreachable terminator with the new conditional 340 // branch. 341 auto *CurrentTerminator = NewBB->getTerminator(); 342 assert(isa<UnreachableInst>(CurrentTerminator) && 343 "Expected to replace unreachable terminator with conditional " 344 "branch."); 345 auto *CondBr = BranchInst::Create(NewBB, nullptr, NewCond); 346 CondBr->setSuccessor(0, nullptr); 347 ReplaceInstWithInst(CurrentTerminator, CondBr); 348 } 349 350 LLVM_DEBUG(dbgs() << "LV: filled BB:" << *NewBB); 351 } 352 353 void VPBasicBlock::dropAllReferences(VPValue *NewValue) { 354 for (VPRecipeBase &R : Recipes) { 355 if (auto *VPV = R.toVPValue()) 356 VPV->replaceAllUsesWith(NewValue); 357 358 if (auto *User = R.toVPUser()) 359 for (unsigned I = 0, E = User->getNumOperands(); I != E; I++) 360 User->setOperand(I, NewValue); 361 } 362 } 363 364 void VPRegionBlock::execute(VPTransformState *State) { 365 ReversePostOrderTraversal<VPBlockBase *> RPOT(Entry); 366 367 if (!isReplicator()) { 368 // Visit the VPBlocks connected to "this", starting from it. 369 for (VPBlockBase *Block : RPOT) { 370 if (EnableVPlanNativePath) { 371 // The inner loop vectorization path does not represent loop preheader 372 // and exit blocks as part of the VPlan. In the VPlan-native path, skip 373 // vectorizing loop preheader block. In future, we may replace this 374 // check with the check for loop preheader. 375 if (Block->getNumPredecessors() == 0) 376 continue; 377 378 // Skip vectorizing loop exit block. In future, we may replace this 379 // check with the check for loop exit. 380 if (Block->getNumSuccessors() == 0) 381 continue; 382 } 383 384 LLVM_DEBUG(dbgs() << "LV: VPBlock in RPO " << Block->getName() << '\n'); 385 Block->execute(State); 386 } 387 return; 388 } 389 390 assert(!State->Instance && "Replicating a Region with non-null instance."); 391 392 // Enter replicating mode. 393 State->Instance = {0, 0}; 394 395 for (unsigned Part = 0, UF = State->UF; Part < UF; ++Part) { 396 State->Instance->Part = Part; 397 assert(!State->VF.isScalable() && "VF is assumed to be non scalable."); 398 for (unsigned Lane = 0, VF = State->VF.getKnownMinValue(); Lane < VF; 399 ++Lane) { 400 State->Instance->Lane = Lane; 401 // Visit the VPBlocks connected to \p this, starting from it. 402 for (VPBlockBase *Block : RPOT) { 403 LLVM_DEBUG(dbgs() << "LV: VPBlock in RPO " << Block->getName() << '\n'); 404 Block->execute(State); 405 } 406 } 407 } 408 409 // Exit replicating mode. 410 State->Instance.reset(); 411 } 412 413 void VPRecipeBase::insertBefore(VPRecipeBase *InsertPos) { 414 assert(!Parent && "Recipe already in some VPBasicBlock"); 415 assert(InsertPos->getParent() && 416 "Insertion position not in any VPBasicBlock"); 417 Parent = InsertPos->getParent(); 418 Parent->getRecipeList().insert(InsertPos->getIterator(), this); 419 } 420 421 void VPRecipeBase::insertAfter(VPRecipeBase *InsertPos) { 422 assert(!Parent && "Recipe already in some VPBasicBlock"); 423 assert(InsertPos->getParent() && 424 "Insertion position not in any VPBasicBlock"); 425 Parent = InsertPos->getParent(); 426 Parent->getRecipeList().insertAfter(InsertPos->getIterator(), this); 427 } 428 429 void VPRecipeBase::removeFromParent() { 430 assert(getParent() && "Recipe not in any VPBasicBlock"); 431 getParent()->getRecipeList().remove(getIterator()); 432 Parent = nullptr; 433 } 434 435 iplist<VPRecipeBase>::iterator VPRecipeBase::eraseFromParent() { 436 assert(getParent() && "Recipe not in any VPBasicBlock"); 437 return getParent()->getRecipeList().erase(getIterator()); 438 } 439 440 void VPRecipeBase::moveAfter(VPRecipeBase *InsertPos) { 441 removeFromParent(); 442 insertAfter(InsertPos); 443 } 444 445 void VPInstruction::generateInstruction(VPTransformState &State, 446 unsigned Part) { 447 IRBuilder<> &Builder = State.Builder; 448 449 if (Instruction::isBinaryOp(getOpcode())) { 450 Value *A = State.get(getOperand(0), Part); 451 Value *B = State.get(getOperand(1), Part); 452 Value *V = Builder.CreateBinOp((Instruction::BinaryOps)getOpcode(), A, B); 453 State.set(this, V, Part); 454 return; 455 } 456 457 switch (getOpcode()) { 458 case VPInstruction::Not: { 459 Value *A = State.get(getOperand(0), Part); 460 Value *V = Builder.CreateNot(A); 461 State.set(this, V, Part); 462 break; 463 } 464 case VPInstruction::ICmpULE: { 465 Value *IV = State.get(getOperand(0), Part); 466 Value *TC = State.get(getOperand(1), Part); 467 Value *V = Builder.CreateICmpULE(IV, TC); 468 State.set(this, V, Part); 469 break; 470 } 471 case Instruction::Select: { 472 Value *Cond = State.get(getOperand(0), Part); 473 Value *Op1 = State.get(getOperand(1), Part); 474 Value *Op2 = State.get(getOperand(2), Part); 475 Value *V = Builder.CreateSelect(Cond, Op1, Op2); 476 State.set(this, V, Part); 477 break; 478 } 479 case VPInstruction::ActiveLaneMask: { 480 // Get first lane of vector induction variable. 481 Value *VIVElem0 = State.get(getOperand(0), {Part, 0}); 482 // Get the original loop tripcount. 483 Value *ScalarTC = State.TripCount; 484 485 auto *Int1Ty = Type::getInt1Ty(Builder.getContext()); 486 auto *PredTy = FixedVectorType::get(Int1Ty, State.VF.getKnownMinValue()); 487 Instruction *Call = Builder.CreateIntrinsic( 488 Intrinsic::get_active_lane_mask, {PredTy, ScalarTC->getType()}, 489 {VIVElem0, ScalarTC}, nullptr, "active.lane.mask"); 490 State.set(this, Call, Part); 491 break; 492 } 493 default: 494 llvm_unreachable("Unsupported opcode for instruction"); 495 } 496 } 497 498 void VPInstruction::execute(VPTransformState &State) { 499 assert(!State.Instance && "VPInstruction executing an Instance"); 500 for (unsigned Part = 0; Part < State.UF; ++Part) 501 generateInstruction(State, Part); 502 } 503 504 void VPInstruction::print(raw_ostream &O, const Twine &Indent, 505 VPSlotTracker &SlotTracker) const { 506 O << "\"EMIT "; 507 print(O, SlotTracker); 508 } 509 510 void VPInstruction::print(raw_ostream &O) const { 511 VPSlotTracker SlotTracker(getParent()->getPlan()); 512 print(O, SlotTracker); 513 } 514 515 void VPInstruction::print(raw_ostream &O, VPSlotTracker &SlotTracker) const { 516 if (hasResult()) { 517 printAsOperand(O, SlotTracker); 518 O << " = "; 519 } 520 521 switch (getOpcode()) { 522 case VPInstruction::Not: 523 O << "not"; 524 break; 525 case VPInstruction::ICmpULE: 526 O << "icmp ule"; 527 break; 528 case VPInstruction::SLPLoad: 529 O << "combined load"; 530 break; 531 case VPInstruction::SLPStore: 532 O << "combined store"; 533 break; 534 case VPInstruction::ActiveLaneMask: 535 O << "active lane mask"; 536 break; 537 538 default: 539 O << Instruction::getOpcodeName(getOpcode()); 540 } 541 542 for (const VPValue *Operand : operands()) { 543 O << " "; 544 Operand->printAsOperand(O, SlotTracker); 545 } 546 } 547 548 /// Generate the code inside the body of the vectorized loop. Assumes a single 549 /// LoopVectorBody basic-block was created for this. Introduce additional 550 /// basic-blocks as needed, and fill them all. 551 void VPlan::execute(VPTransformState *State) { 552 // -1. Check if the backedge taken count is needed, and if so build it. 553 if (BackedgeTakenCount && BackedgeTakenCount->getNumUsers()) { 554 Value *TC = State->TripCount; 555 IRBuilder<> Builder(State->CFG.PrevBB->getTerminator()); 556 auto *TCMO = Builder.CreateSub(TC, ConstantInt::get(TC->getType(), 1), 557 "trip.count.minus.1"); 558 auto VF = State->VF; 559 Value *VTCMO = 560 VF.isScalar() ? TCMO : Builder.CreateVectorSplat(VF, TCMO, "broadcast"); 561 for (unsigned Part = 0, UF = State->UF; Part < UF; ++Part) 562 State->set(BackedgeTakenCount, VTCMO, Part); 563 } 564 565 // 0. Set the reverse mapping from VPValues to Values for code generation. 566 for (auto &Entry : Value2VPValue) 567 State->VPValue2Value[Entry.second] = Entry.first; 568 569 BasicBlock *VectorPreHeaderBB = State->CFG.PrevBB; 570 BasicBlock *VectorHeaderBB = VectorPreHeaderBB->getSingleSuccessor(); 571 assert(VectorHeaderBB && "Loop preheader does not have a single successor."); 572 573 // 1. Make room to generate basic-blocks inside loop body if needed. 574 BasicBlock *VectorLatchBB = VectorHeaderBB->splitBasicBlock( 575 VectorHeaderBB->getFirstInsertionPt(), "vector.body.latch"); 576 Loop *L = State->LI->getLoopFor(VectorHeaderBB); 577 L->addBasicBlockToLoop(VectorLatchBB, *State->LI); 578 // Remove the edge between Header and Latch to allow other connections. 579 // Temporarily terminate with unreachable until CFG is rewired. 580 // Note: this asserts the generated code's assumption that 581 // getFirstInsertionPt() can be dereferenced into an Instruction. 582 VectorHeaderBB->getTerminator()->eraseFromParent(); 583 State->Builder.SetInsertPoint(VectorHeaderBB); 584 UnreachableInst *Terminator = State->Builder.CreateUnreachable(); 585 State->Builder.SetInsertPoint(Terminator); 586 587 // 2. Generate code in loop body. 588 State->CFG.PrevVPBB = nullptr; 589 State->CFG.PrevBB = VectorHeaderBB; 590 State->CFG.LastBB = VectorLatchBB; 591 592 for (VPBlockBase *Block : depth_first(Entry)) 593 Block->execute(State); 594 595 // Setup branch terminator successors for VPBBs in VPBBsToFix based on 596 // VPBB's successors. 597 for (auto VPBB : State->CFG.VPBBsToFix) { 598 assert(EnableVPlanNativePath && 599 "Unexpected VPBBsToFix in non VPlan-native path"); 600 BasicBlock *BB = State->CFG.VPBB2IRBB[VPBB]; 601 assert(BB && "Unexpected null basic block for VPBB"); 602 603 unsigned Idx = 0; 604 auto *BBTerminator = BB->getTerminator(); 605 606 for (VPBlockBase *SuccVPBlock : VPBB->getHierarchicalSuccessors()) { 607 VPBasicBlock *SuccVPBB = SuccVPBlock->getEntryBasicBlock(); 608 BBTerminator->setSuccessor(Idx, State->CFG.VPBB2IRBB[SuccVPBB]); 609 ++Idx; 610 } 611 } 612 613 // 3. Merge the temporary latch created with the last basic-block filled. 614 BasicBlock *LastBB = State->CFG.PrevBB; 615 // Connect LastBB to VectorLatchBB to facilitate their merge. 616 assert((EnableVPlanNativePath || 617 isa<UnreachableInst>(LastBB->getTerminator())) && 618 "Expected InnerLoop VPlan CFG to terminate with unreachable"); 619 assert((!EnableVPlanNativePath || isa<BranchInst>(LastBB->getTerminator())) && 620 "Expected VPlan CFG to terminate with branch in NativePath"); 621 LastBB->getTerminator()->eraseFromParent(); 622 BranchInst::Create(VectorLatchBB, LastBB); 623 624 // Merge LastBB with Latch. 625 bool Merged = MergeBlockIntoPredecessor(VectorLatchBB, nullptr, State->LI); 626 (void)Merged; 627 assert(Merged && "Could not merge last basic block with latch."); 628 VectorLatchBB = LastBB; 629 630 // We do not attempt to preserve DT for outer loop vectorization currently. 631 if (!EnableVPlanNativePath) 632 updateDominatorTree(State->DT, VectorPreHeaderBB, VectorLatchBB, 633 L->getExitBlock()); 634 } 635 636 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 637 LLVM_DUMP_METHOD 638 void VPlan::dump() const { dbgs() << *this << '\n'; } 639 #endif 640 641 void VPlan::updateDominatorTree(DominatorTree *DT, BasicBlock *LoopPreHeaderBB, 642 BasicBlock *LoopLatchBB, 643 BasicBlock *LoopExitBB) { 644 BasicBlock *LoopHeaderBB = LoopPreHeaderBB->getSingleSuccessor(); 645 assert(LoopHeaderBB && "Loop preheader does not have a single successor."); 646 // The vector body may be more than a single basic-block by this point. 647 // Update the dominator tree information inside the vector body by propagating 648 // it from header to latch, expecting only triangular control-flow, if any. 649 BasicBlock *PostDomSucc = nullptr; 650 for (auto *BB = LoopHeaderBB; BB != LoopLatchBB; BB = PostDomSucc) { 651 // Get the list of successors of this block. 652 std::vector<BasicBlock *> Succs(succ_begin(BB), succ_end(BB)); 653 assert(Succs.size() <= 2 && 654 "Basic block in vector loop has more than 2 successors."); 655 PostDomSucc = Succs[0]; 656 if (Succs.size() == 1) { 657 assert(PostDomSucc->getSinglePredecessor() && 658 "PostDom successor has more than one predecessor."); 659 DT->addNewBlock(PostDomSucc, BB); 660 continue; 661 } 662 BasicBlock *InterimSucc = Succs[1]; 663 if (PostDomSucc->getSingleSuccessor() == InterimSucc) { 664 PostDomSucc = Succs[1]; 665 InterimSucc = Succs[0]; 666 } 667 assert(InterimSucc->getSingleSuccessor() == PostDomSucc && 668 "One successor of a basic block does not lead to the other."); 669 assert(InterimSucc->getSinglePredecessor() && 670 "Interim successor has more than one predecessor."); 671 assert(PostDomSucc->hasNPredecessors(2) && 672 "PostDom successor has more than two predecessors."); 673 DT->addNewBlock(InterimSucc, BB); 674 DT->addNewBlock(PostDomSucc, BB); 675 } 676 // Latch block is a new dominator for the loop exit. 677 DT->changeImmediateDominator(LoopExitBB, LoopLatchBB); 678 assert(DT->verify(DominatorTree::VerificationLevel::Fast)); 679 } 680 681 const Twine VPlanPrinter::getUID(const VPBlockBase *Block) { 682 return (isa<VPRegionBlock>(Block) ? "cluster_N" : "N") + 683 Twine(getOrCreateBID(Block)); 684 } 685 686 const Twine VPlanPrinter::getOrCreateName(const VPBlockBase *Block) { 687 const std::string &Name = Block->getName(); 688 if (!Name.empty()) 689 return Name; 690 return "VPB" + Twine(getOrCreateBID(Block)); 691 } 692 693 void VPlanPrinter::dump() { 694 Depth = 1; 695 bumpIndent(0); 696 OS << "digraph VPlan {\n"; 697 OS << "graph [labelloc=t, fontsize=30; label=\"Vectorization Plan"; 698 if (!Plan.getName().empty()) 699 OS << "\\n" << DOT::EscapeString(Plan.getName()); 700 if (Plan.BackedgeTakenCount) { 701 OS << ", where:\\n"; 702 Plan.BackedgeTakenCount->print(OS, SlotTracker); 703 OS << " := BackedgeTakenCount"; 704 } 705 OS << "\"]\n"; 706 OS << "node [shape=rect, fontname=Courier, fontsize=30]\n"; 707 OS << "edge [fontname=Courier, fontsize=30]\n"; 708 OS << "compound=true\n"; 709 710 for (const VPBlockBase *Block : depth_first(Plan.getEntry())) 711 dumpBlock(Block); 712 713 OS << "}\n"; 714 } 715 716 void VPlanPrinter::dumpBlock(const VPBlockBase *Block) { 717 if (const VPBasicBlock *BasicBlock = dyn_cast<VPBasicBlock>(Block)) 718 dumpBasicBlock(BasicBlock); 719 else if (const VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block)) 720 dumpRegion(Region); 721 else 722 llvm_unreachable("Unsupported kind of VPBlock."); 723 } 724 725 void VPlanPrinter::drawEdge(const VPBlockBase *From, const VPBlockBase *To, 726 bool Hidden, const Twine &Label) { 727 // Due to "dot" we print an edge between two regions as an edge between the 728 // exit basic block and the entry basic of the respective regions. 729 const VPBlockBase *Tail = From->getExitBasicBlock(); 730 const VPBlockBase *Head = To->getEntryBasicBlock(); 731 OS << Indent << getUID(Tail) << " -> " << getUID(Head); 732 OS << " [ label=\"" << Label << '\"'; 733 if (Tail != From) 734 OS << " ltail=" << getUID(From); 735 if (Head != To) 736 OS << " lhead=" << getUID(To); 737 if (Hidden) 738 OS << "; splines=none"; 739 OS << "]\n"; 740 } 741 742 void VPlanPrinter::dumpEdges(const VPBlockBase *Block) { 743 auto &Successors = Block->getSuccessors(); 744 if (Successors.size() == 1) 745 drawEdge(Block, Successors.front(), false, ""); 746 else if (Successors.size() == 2) { 747 drawEdge(Block, Successors.front(), false, "T"); 748 drawEdge(Block, Successors.back(), false, "F"); 749 } else { 750 unsigned SuccessorNumber = 0; 751 for (auto *Successor : Successors) 752 drawEdge(Block, Successor, false, Twine(SuccessorNumber++)); 753 } 754 } 755 756 void VPlanPrinter::dumpBasicBlock(const VPBasicBlock *BasicBlock) { 757 OS << Indent << getUID(BasicBlock) << " [label =\n"; 758 bumpIndent(1); 759 OS << Indent << "\"" << DOT::EscapeString(BasicBlock->getName()) << ":\\n\""; 760 bumpIndent(1); 761 762 // Dump the block predicate. 763 const VPValue *Pred = BasicBlock->getPredicate(); 764 if (Pred) { 765 OS << " +\n" << Indent << " \"BlockPredicate: "; 766 if (const VPInstruction *PredI = dyn_cast<VPInstruction>(Pred)) { 767 PredI->printAsOperand(OS, SlotTracker); 768 OS << " (" << DOT::EscapeString(PredI->getParent()->getName()) 769 << ")\\l\""; 770 } else 771 Pred->printAsOperand(OS, SlotTracker); 772 } 773 774 for (const VPRecipeBase &Recipe : *BasicBlock) { 775 OS << " +\n" << Indent; 776 Recipe.print(OS, Indent, SlotTracker); 777 OS << "\\l\""; 778 } 779 780 // Dump the condition bit. 781 const VPValue *CBV = BasicBlock->getCondBit(); 782 if (CBV) { 783 OS << " +\n" << Indent << " \"CondBit: "; 784 if (const VPInstruction *CBI = dyn_cast<VPInstruction>(CBV)) { 785 CBI->printAsOperand(OS, SlotTracker); 786 OS << " (" << DOT::EscapeString(CBI->getParent()->getName()) << ")\\l\""; 787 } else { 788 CBV->printAsOperand(OS, SlotTracker); 789 OS << "\""; 790 } 791 } 792 793 bumpIndent(-2); 794 OS << "\n" << Indent << "]\n"; 795 dumpEdges(BasicBlock); 796 } 797 798 void VPlanPrinter::dumpRegion(const VPRegionBlock *Region) { 799 OS << Indent << "subgraph " << getUID(Region) << " {\n"; 800 bumpIndent(1); 801 OS << Indent << "fontname=Courier\n" 802 << Indent << "label=\"" 803 << DOT::EscapeString(Region->isReplicator() ? "<xVFxUF> " : "<x1> ") 804 << DOT::EscapeString(Region->getName()) << "\"\n"; 805 // Dump the blocks of the region. 806 assert(Region->getEntry() && "Region contains no inner blocks."); 807 for (const VPBlockBase *Block : depth_first(Region->getEntry())) 808 dumpBlock(Block); 809 bumpIndent(-1); 810 OS << Indent << "}\n"; 811 dumpEdges(Region); 812 } 813 814 void VPlanPrinter::printAsIngredient(raw_ostream &O, const Value *V) { 815 std::string IngredientString; 816 raw_string_ostream RSO(IngredientString); 817 if (auto *Inst = dyn_cast<Instruction>(V)) { 818 if (!Inst->getType()->isVoidTy()) { 819 Inst->printAsOperand(RSO, false); 820 RSO << " = "; 821 } 822 RSO << Inst->getOpcodeName() << " "; 823 unsigned E = Inst->getNumOperands(); 824 if (E > 0) { 825 Inst->getOperand(0)->printAsOperand(RSO, false); 826 for (unsigned I = 1; I < E; ++I) 827 Inst->getOperand(I)->printAsOperand(RSO << ", ", false); 828 } 829 } else // !Inst 830 V->printAsOperand(RSO, false); 831 RSO.flush(); 832 O << DOT::EscapeString(IngredientString); 833 } 834 835 void VPWidenCallRecipe::print(raw_ostream &O, const Twine &Indent, 836 VPSlotTracker &SlotTracker) const { 837 O << "\"WIDEN-CALL "; 838 839 auto *CI = cast<CallInst>(getUnderlyingInstr()); 840 if (CI->getType()->isVoidTy()) 841 O << "void "; 842 else { 843 printAsOperand(O, SlotTracker); 844 O << " = "; 845 } 846 847 O << "call @" << CI->getCalledFunction()->getName() << "("; 848 printOperands(O, SlotTracker); 849 O << ")"; 850 } 851 852 void VPWidenSelectRecipe::print(raw_ostream &O, const Twine &Indent, 853 VPSlotTracker &SlotTracker) const { 854 O << "\"WIDEN-SELECT "; 855 printAsOperand(O, SlotTracker); 856 O << " = select "; 857 getOperand(0)->printAsOperand(O, SlotTracker); 858 O << ", "; 859 getOperand(1)->printAsOperand(O, SlotTracker); 860 O << ", "; 861 getOperand(2)->printAsOperand(O, SlotTracker); 862 O << (InvariantCond ? " (condition is loop invariant)" : ""); 863 } 864 865 void VPWidenRecipe::print(raw_ostream &O, const Twine &Indent, 866 VPSlotTracker &SlotTracker) const { 867 O << "\"WIDEN\\l\""; 868 O << "\" " << VPlanIngredient(&Ingredient); 869 } 870 871 void VPWidenIntOrFpInductionRecipe::print(raw_ostream &O, const Twine &Indent, 872 VPSlotTracker &SlotTracker) const { 873 O << "\"WIDEN-INDUCTION"; 874 if (Trunc) { 875 O << "\\l\""; 876 O << " +\n" << Indent << "\" " << VPlanIngredient(IV) << "\\l\""; 877 O << " +\n" << Indent << "\" " << VPlanIngredient(Trunc); 878 } else 879 O << " " << VPlanIngredient(IV); 880 } 881 882 void VPWidenGEPRecipe::print(raw_ostream &O, const Twine &Indent, 883 VPSlotTracker &SlotTracker) const { 884 O << "\"WIDEN-GEP "; 885 O << (IsPtrLoopInvariant ? "Inv" : "Var"); 886 size_t IndicesNumber = IsIndexLoopInvariant.size(); 887 for (size_t I = 0; I < IndicesNumber; ++I) 888 O << "[" << (IsIndexLoopInvariant[I] ? "Inv" : "Var") << "]"; 889 890 O << " "; 891 printAsOperand(O, SlotTracker); 892 O << " = getelementptr "; 893 printOperands(O, SlotTracker); 894 } 895 896 void VPWidenPHIRecipe::print(raw_ostream &O, const Twine &Indent, 897 VPSlotTracker &SlotTracker) const { 898 O << "\"WIDEN-PHI " << VPlanIngredient(Phi); 899 } 900 901 void VPBlendRecipe::print(raw_ostream &O, const Twine &Indent, 902 VPSlotTracker &SlotTracker) const { 903 O << "\"BLEND "; 904 Phi->printAsOperand(O, false); 905 O << " ="; 906 if (getNumIncomingValues() == 1) { 907 // Not a User of any mask: not really blending, this is a 908 // single-predecessor phi. 909 O << " "; 910 getIncomingValue(0)->printAsOperand(O, SlotTracker); 911 } else { 912 for (unsigned I = 0, E = getNumIncomingValues(); I < E; ++I) { 913 O << " "; 914 getIncomingValue(I)->printAsOperand(O, SlotTracker); 915 O << "/"; 916 getMask(I)->printAsOperand(O, SlotTracker); 917 } 918 } 919 } 920 921 void VPReductionRecipe::print(raw_ostream &O, const Twine &Indent, 922 VPSlotTracker &SlotTracker) const { 923 O << "\"REDUCE of" << *I << " as "; 924 ChainOp->printAsOperand(O, SlotTracker); 925 O << " + reduce("; 926 VecOp->printAsOperand(O, SlotTracker); 927 if (CondOp) { 928 O << ", "; 929 CondOp->printAsOperand(O, SlotTracker); 930 } 931 O << ")"; 932 } 933 934 void VPReplicateRecipe::print(raw_ostream &O, const Twine &Indent, 935 VPSlotTracker &SlotTracker) const { 936 O << "\"" << (IsUniform ? "CLONE " : "REPLICATE ") 937 << VPlanIngredient(Ingredient); 938 if (AlsoPack) 939 O << " (S->V)"; 940 } 941 942 void VPPredInstPHIRecipe::print(raw_ostream &O, const Twine &Indent, 943 VPSlotTracker &SlotTracker) const { 944 O << "\"PHI-PREDICATED-INSTRUCTION " << VPlanIngredient(PredInst); 945 } 946 947 void VPWidenMemoryInstructionRecipe::print(raw_ostream &O, const Twine &Indent, 948 VPSlotTracker &SlotTracker) const { 949 O << "\"WIDEN "; 950 951 if (!isStore()) { 952 printAsOperand(O, SlotTracker); 953 O << " = "; 954 } 955 O << Instruction::getOpcodeName(getUnderlyingInstr()->getOpcode()) << " "; 956 957 printOperands(O, SlotTracker); 958 } 959 960 void VPWidenCanonicalIVRecipe::execute(VPTransformState &State) { 961 Value *CanonicalIV = State.CanonicalIV; 962 Type *STy = CanonicalIV->getType(); 963 IRBuilder<> Builder(State.CFG.PrevBB->getTerminator()); 964 ElementCount VF = State.VF; 965 assert(!VF.isScalable() && "the code following assumes non scalables ECs"); 966 Value *VStart = VF.isScalar() 967 ? CanonicalIV 968 : Builder.CreateVectorSplat(VF.getKnownMinValue(), 969 CanonicalIV, "broadcast"); 970 for (unsigned Part = 0, UF = State.UF; Part < UF; ++Part) { 971 SmallVector<Constant *, 8> Indices; 972 for (unsigned Lane = 0; Lane < VF.getKnownMinValue(); ++Lane) 973 Indices.push_back( 974 ConstantInt::get(STy, Part * VF.getKnownMinValue() + Lane)); 975 // If VF == 1, there is only one iteration in the loop above, thus the 976 // element pushed back into Indices is ConstantInt::get(STy, Part) 977 Constant *VStep = 978 VF.isScalar() ? Indices.back() : ConstantVector::get(Indices); 979 // Add the consecutive indices to the vector value. 980 Value *CanonicalVectorIV = Builder.CreateAdd(VStart, VStep, "vec.iv"); 981 State.set(getVPValue(), CanonicalVectorIV, Part); 982 } 983 } 984 985 void VPWidenCanonicalIVRecipe::print(raw_ostream &O, const Twine &Indent, 986 VPSlotTracker &SlotTracker) const { 987 O << "\"EMIT "; 988 getVPValue()->printAsOperand(O, SlotTracker); 989 O << " = WIDEN-CANONICAL-INDUCTION"; 990 } 991 992 template void DomTreeBuilder::Calculate<VPDominatorTree>(VPDominatorTree &DT); 993 994 void VPValue::replaceAllUsesWith(VPValue *New) { 995 for (unsigned J = 0; J < getNumUsers();) { 996 VPUser *User = Users[J]; 997 unsigned NumUsers = getNumUsers(); 998 for (unsigned I = 0, E = User->getNumOperands(); I < E; ++I) 999 if (User->getOperand(I) == this) 1000 User->setOperand(I, New); 1001 // If a user got removed after updating the current user, the next user to 1002 // update will be moved to the current position, so we only need to 1003 // increment the index if the number of users did not change. 1004 if (NumUsers == getNumUsers()) 1005 J++; 1006 } 1007 } 1008 1009 void VPValue::printAsOperand(raw_ostream &OS, VPSlotTracker &Tracker) const { 1010 if (const Value *UV = getUnderlyingValue()) { 1011 OS << "ir<"; 1012 UV->printAsOperand(OS, false); 1013 OS << ">"; 1014 return; 1015 } 1016 1017 unsigned Slot = Tracker.getSlot(this); 1018 if (Slot == unsigned(-1)) 1019 OS << "<badref>"; 1020 else 1021 OS << "vp<%" << Tracker.getSlot(this) << ">"; 1022 } 1023 1024 void VPUser::printOperands(raw_ostream &O, VPSlotTracker &SlotTracker) const { 1025 bool First = true; 1026 for (VPValue *Op : operands()) { 1027 if (!First) 1028 O << ", "; 1029 Op->printAsOperand(O, SlotTracker); 1030 First = false; 1031 } 1032 } 1033 1034 void VPInterleavedAccessInfo::visitRegion(VPRegionBlock *Region, 1035 Old2NewTy &Old2New, 1036 InterleavedAccessInfo &IAI) { 1037 ReversePostOrderTraversal<VPBlockBase *> RPOT(Region->getEntry()); 1038 for (VPBlockBase *Base : RPOT) { 1039 visitBlock(Base, Old2New, IAI); 1040 } 1041 } 1042 1043 void VPInterleavedAccessInfo::visitBlock(VPBlockBase *Block, Old2NewTy &Old2New, 1044 InterleavedAccessInfo &IAI) { 1045 if (VPBasicBlock *VPBB = dyn_cast<VPBasicBlock>(Block)) { 1046 for (VPRecipeBase &VPI : *VPBB) { 1047 assert(isa<VPInstruction>(&VPI) && "Can only handle VPInstructions"); 1048 auto *VPInst = cast<VPInstruction>(&VPI); 1049 auto *Inst = cast<Instruction>(VPInst->getUnderlyingValue()); 1050 auto *IG = IAI.getInterleaveGroup(Inst); 1051 if (!IG) 1052 continue; 1053 1054 auto NewIGIter = Old2New.find(IG); 1055 if (NewIGIter == Old2New.end()) 1056 Old2New[IG] = new InterleaveGroup<VPInstruction>( 1057 IG->getFactor(), IG->isReverse(), IG->getAlign()); 1058 1059 if (Inst == IG->getInsertPos()) 1060 Old2New[IG]->setInsertPos(VPInst); 1061 1062 InterleaveGroupMap[VPInst] = Old2New[IG]; 1063 InterleaveGroupMap[VPInst]->insertMember( 1064 VPInst, IG->getIndex(Inst), 1065 Align(IG->isReverse() ? (-1) * int(IG->getFactor()) 1066 : IG->getFactor())); 1067 } 1068 } else if (VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block)) 1069 visitRegion(Region, Old2New, IAI); 1070 else 1071 llvm_unreachable("Unsupported kind of VPBlock."); 1072 } 1073 1074 VPInterleavedAccessInfo::VPInterleavedAccessInfo(VPlan &Plan, 1075 InterleavedAccessInfo &IAI) { 1076 Old2NewTy Old2New; 1077 visitRegion(cast<VPRegionBlock>(Plan.getEntry()), Old2New, IAI); 1078 } 1079 1080 void VPSlotTracker::assignSlot(const VPValue *V) { 1081 assert(Slots.find(V) == Slots.end() && "VPValue already has a slot!"); 1082 const Value *UV = V->getUnderlyingValue(); 1083 if (UV) 1084 return; 1085 const auto *VPI = dyn_cast<VPInstruction>(V); 1086 if (VPI && !VPI->hasResult()) 1087 return; 1088 1089 Slots[V] = NextSlot++; 1090 } 1091 1092 void VPSlotTracker::assignSlots(const VPBlockBase *VPBB) { 1093 if (auto *Region = dyn_cast<VPRegionBlock>(VPBB)) 1094 assignSlots(Region); 1095 else 1096 assignSlots(cast<VPBasicBlock>(VPBB)); 1097 } 1098 1099 void VPSlotTracker::assignSlots(const VPRegionBlock *Region) { 1100 ReversePostOrderTraversal<const VPBlockBase *> RPOT(Region->getEntry()); 1101 for (const VPBlockBase *Block : RPOT) 1102 assignSlots(Block); 1103 } 1104 1105 void VPSlotTracker::assignSlots(const VPBasicBlock *VPBB) { 1106 for (const VPRecipeBase &Recipe : *VPBB) { 1107 if (const auto *VPI = dyn_cast<VPInstruction>(&Recipe)) 1108 assignSlot(VPI); 1109 else if (const auto *VPIV = dyn_cast<VPWidenCanonicalIVRecipe>(&Recipe)) 1110 assignSlot(VPIV->getVPValue()); 1111 } 1112 } 1113 1114 void VPSlotTracker::assignSlots(const VPlan &Plan) { 1115 1116 for (const VPValue *V : Plan.VPExternalDefs) 1117 assignSlot(V); 1118 1119 for (auto &E : Plan.Value2VPValue) 1120 if (!isa<VPInstruction>(E.second)) 1121 assignSlot(E.second); 1122 1123 for (const VPValue *V : Plan.VPCBVs) 1124 assignSlot(V); 1125 1126 if (Plan.BackedgeTakenCount) 1127 assignSlot(Plan.BackedgeTakenCount); 1128 1129 ReversePostOrderTraversal<const VPBlockBase *> RPOT(Plan.getEntry()); 1130 for (const VPBlockBase *Block : RPOT) 1131 assignSlots(Block); 1132 } 1133