11f58dda4SAyal Zaks //===- VPlan.cpp - Vectorizer Plan ----------------------------------------===// 21f58dda4SAyal Zaks // 31f58dda4SAyal Zaks // The LLVM Compiler Infrastructure 41f58dda4SAyal Zaks // 51f58dda4SAyal Zaks // This file is distributed under the University of Illinois Open Source 61f58dda4SAyal Zaks // License. See LICENSE.TXT for details. 71f58dda4SAyal Zaks // 81f58dda4SAyal Zaks //===----------------------------------------------------------------------===// 91f58dda4SAyal Zaks /// 101f58dda4SAyal Zaks /// \file 111f58dda4SAyal Zaks /// This is the LLVM vectorization plan. It represents a candidate for 121f58dda4SAyal Zaks /// vectorization, allowing to plan and optimize how to vectorize a given loop 131f58dda4SAyal Zaks /// before generating LLVM-IR. 141f58dda4SAyal Zaks /// The vectorizer uses vectorization plans to estimate the costs of potential 151f58dda4SAyal Zaks /// candidates and if profitable to execute the desired plan, generating vector 161f58dda4SAyal Zaks /// LLVM-IR code. 171f58dda4SAyal Zaks /// 181f58dda4SAyal Zaks //===----------------------------------------------------------------------===// 191f58dda4SAyal Zaks 201f58dda4SAyal Zaks #include "VPlan.h" 216cadde7fSEugene Zelenko #include "llvm/ADT/DepthFirstIterator.h" 221f58dda4SAyal Zaks #include "llvm/ADT/PostOrderIterator.h" 236cadde7fSEugene Zelenko #include "llvm/ADT/SmallVector.h" 246cadde7fSEugene Zelenko #include "llvm/ADT/Twine.h" 251f58dda4SAyal Zaks #include "llvm/Analysis/LoopInfo.h" 261f58dda4SAyal Zaks #include "llvm/IR/BasicBlock.h" 276cadde7fSEugene Zelenko #include "llvm/IR/CFG.h" 281f58dda4SAyal Zaks #include "llvm/IR/Dominators.h" 296cadde7fSEugene Zelenko #include "llvm/IR/InstrTypes.h" 306cadde7fSEugene Zelenko #include "llvm/IR/Instruction.h" 316cadde7fSEugene Zelenko #include "llvm/IR/Instructions.h" 326cadde7fSEugene Zelenko #include "llvm/IR/Type.h" 336cadde7fSEugene Zelenko #include "llvm/IR/Value.h" 346cadde7fSEugene Zelenko #include "llvm/Support/Casting.h" 356cadde7fSEugene Zelenko #include "llvm/Support/Debug.h" 366cadde7fSEugene Zelenko #include "llvm/Support/ErrorHandling.h" 371f58dda4SAyal Zaks #include "llvm/Support/GraphWriter.h" 386cadde7fSEugene Zelenko #include "llvm/Support/raw_ostream.h" 391f58dda4SAyal Zaks #include "llvm/Transforms/Utils/BasicBlockUtils.h" 406cadde7fSEugene Zelenko #include <cassert> 416cadde7fSEugene Zelenko #include <iterator> 426cadde7fSEugene Zelenko #include <string> 436cadde7fSEugene Zelenko #include <vector> 441f58dda4SAyal Zaks 451f58dda4SAyal Zaks using namespace llvm; 461f58dda4SAyal Zaks 471f58dda4SAyal Zaks #define DEBUG_TYPE "vplan" 481f58dda4SAyal Zaks 498b9d1f3cSGil Rapaport raw_ostream &llvm::operator<<(raw_ostream &OS, const VPValue &V) { 508b9d1f3cSGil Rapaport if (const VPInstruction *Instr = dyn_cast<VPInstruction>(&V)) 518b9d1f3cSGil Rapaport Instr->print(OS); 528b9d1f3cSGil Rapaport else 538b9d1f3cSGil Rapaport V.printAsOperand(OS); 548b9d1f3cSGil Rapaport return OS; 558b9d1f3cSGil Rapaport } 568b9d1f3cSGil Rapaport 571f58dda4SAyal Zaks /// \return the VPBasicBlock that is the entry of Block, possibly indirectly. 581f58dda4SAyal Zaks const VPBasicBlock *VPBlockBase::getEntryBasicBlock() const { 591f58dda4SAyal Zaks const VPBlockBase *Block = this; 601f58dda4SAyal Zaks while (const VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block)) 611f58dda4SAyal Zaks Block = Region->getEntry(); 621f58dda4SAyal Zaks return cast<VPBasicBlock>(Block); 631f58dda4SAyal Zaks } 641f58dda4SAyal Zaks 651f58dda4SAyal Zaks VPBasicBlock *VPBlockBase::getEntryBasicBlock() { 661f58dda4SAyal Zaks VPBlockBase *Block = this; 671f58dda4SAyal Zaks while (VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block)) 681f58dda4SAyal Zaks Block = Region->getEntry(); 691f58dda4SAyal Zaks return cast<VPBasicBlock>(Block); 701f58dda4SAyal Zaks } 711f58dda4SAyal Zaks 721f58dda4SAyal Zaks /// \return the VPBasicBlock that is the exit of Block, possibly indirectly. 731f58dda4SAyal Zaks const VPBasicBlock *VPBlockBase::getExitBasicBlock() const { 741f58dda4SAyal Zaks const VPBlockBase *Block = this; 751f58dda4SAyal Zaks while (const VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block)) 761f58dda4SAyal Zaks Block = Region->getExit(); 771f58dda4SAyal Zaks return cast<VPBasicBlock>(Block); 781f58dda4SAyal Zaks } 791f58dda4SAyal Zaks 801f58dda4SAyal Zaks VPBasicBlock *VPBlockBase::getExitBasicBlock() { 811f58dda4SAyal Zaks VPBlockBase *Block = this; 821f58dda4SAyal Zaks while (VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block)) 831f58dda4SAyal Zaks Block = Region->getExit(); 841f58dda4SAyal Zaks return cast<VPBasicBlock>(Block); 851f58dda4SAyal Zaks } 861f58dda4SAyal Zaks 871f58dda4SAyal Zaks VPBlockBase *VPBlockBase::getEnclosingBlockWithSuccessors() { 881f58dda4SAyal Zaks if (!Successors.empty() || !Parent) 891f58dda4SAyal Zaks return this; 901f58dda4SAyal Zaks assert(Parent->getExit() == this && 911f58dda4SAyal Zaks "Block w/o successors not the exit of its parent."); 921f58dda4SAyal Zaks return Parent->getEnclosingBlockWithSuccessors(); 931f58dda4SAyal Zaks } 941f58dda4SAyal Zaks 951f58dda4SAyal Zaks VPBlockBase *VPBlockBase::getEnclosingBlockWithPredecessors() { 961f58dda4SAyal Zaks if (!Predecessors.empty() || !Parent) 971f58dda4SAyal Zaks return this; 981f58dda4SAyal Zaks assert(Parent->getEntry() == this && 991f58dda4SAyal Zaks "Block w/o predecessors not the entry of its parent."); 1001f58dda4SAyal Zaks return Parent->getEnclosingBlockWithPredecessors(); 1011f58dda4SAyal Zaks } 1021f58dda4SAyal Zaks 1031f58dda4SAyal Zaks void VPBlockBase::deleteCFG(VPBlockBase *Entry) { 1041f58dda4SAyal Zaks SmallVector<VPBlockBase *, 8> Blocks; 1051f58dda4SAyal Zaks for (VPBlockBase *Block : depth_first(Entry)) 1061f58dda4SAyal Zaks Blocks.push_back(Block); 1071f58dda4SAyal Zaks 1081f58dda4SAyal Zaks for (VPBlockBase *Block : Blocks) 1091f58dda4SAyal Zaks delete Block; 1101f58dda4SAyal Zaks } 1111f58dda4SAyal Zaks 1121f58dda4SAyal Zaks BasicBlock * 1131f58dda4SAyal Zaks VPBasicBlock::createEmptyBasicBlock(VPTransformState::CFGState &CFG) { 1141f58dda4SAyal Zaks // BB stands for IR BasicBlocks. VPBB stands for VPlan VPBasicBlocks. 1151f58dda4SAyal Zaks // Pred stands for Predessor. Prev stands for Previous - last visited/created. 1161f58dda4SAyal Zaks BasicBlock *PrevBB = CFG.PrevBB; 1171f58dda4SAyal Zaks BasicBlock *NewBB = BasicBlock::Create(PrevBB->getContext(), getName(), 1181f58dda4SAyal Zaks PrevBB->getParent(), CFG.LastBB); 119d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "LV: created " << NewBB->getName() << '\n'); 1201f58dda4SAyal Zaks 1211f58dda4SAyal Zaks // Hook up the new basic block to its predecessors. 1221f58dda4SAyal Zaks for (VPBlockBase *PredVPBlock : getHierarchicalPredecessors()) { 1231f58dda4SAyal Zaks VPBasicBlock *PredVPBB = PredVPBlock->getExitBasicBlock(); 1241f58dda4SAyal Zaks auto &PredVPSuccessors = PredVPBB->getSuccessors(); 1251f58dda4SAyal Zaks BasicBlock *PredBB = CFG.VPBB2IRBB[PredVPBB]; 1261f58dda4SAyal Zaks assert(PredBB && "Predecessor basic-block not found building successor."); 1271f58dda4SAyal Zaks auto *PredBBTerminator = PredBB->getTerminator(); 128d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "LV: draw edge from" << PredBB->getName() << '\n'); 1291f58dda4SAyal Zaks if (isa<UnreachableInst>(PredBBTerminator)) { 1301f58dda4SAyal Zaks assert(PredVPSuccessors.size() == 1 && 1311f58dda4SAyal Zaks "Predecessor ending w/o branch must have single successor."); 1321f58dda4SAyal Zaks PredBBTerminator->eraseFromParent(); 1331f58dda4SAyal Zaks BranchInst::Create(NewBB, PredBB); 1341f58dda4SAyal Zaks } else { 1351f58dda4SAyal Zaks assert(PredVPSuccessors.size() == 2 && 1361f58dda4SAyal Zaks "Predecessor ending with branch must have two successors."); 1371f58dda4SAyal Zaks unsigned idx = PredVPSuccessors.front() == this ? 0 : 1; 1381f58dda4SAyal Zaks assert(!PredBBTerminator->getSuccessor(idx) && 1391f58dda4SAyal Zaks "Trying to reset an existing successor block."); 1401f58dda4SAyal Zaks PredBBTerminator->setSuccessor(idx, NewBB); 1411f58dda4SAyal Zaks } 1421f58dda4SAyal Zaks } 1431f58dda4SAyal Zaks return NewBB; 1441f58dda4SAyal Zaks } 1451f58dda4SAyal Zaks 1461f58dda4SAyal Zaks void VPBasicBlock::execute(VPTransformState *State) { 1471f58dda4SAyal Zaks bool Replica = State->Instance && 1481f58dda4SAyal Zaks !(State->Instance->Part == 0 && State->Instance->Lane == 0); 1491f58dda4SAyal Zaks VPBasicBlock *PrevVPBB = State->CFG.PrevVPBB; 1501f58dda4SAyal Zaks VPBlockBase *SingleHPred = nullptr; 1511f58dda4SAyal Zaks BasicBlock *NewBB = State->CFG.PrevBB; // Reuse it if possible. 1521f58dda4SAyal Zaks 1531f58dda4SAyal Zaks // 1. Create an IR basic block, or reuse the last one if possible. 1541f58dda4SAyal Zaks // The last IR basic block is reused, as an optimization, in three cases: 1551f58dda4SAyal Zaks // A. the first VPBB reuses the loop header BB - when PrevVPBB is null; 1561f58dda4SAyal Zaks // B. when the current VPBB has a single (hierarchical) predecessor which 1571f58dda4SAyal Zaks // is PrevVPBB and the latter has a single (hierarchical) successor; and 1581f58dda4SAyal Zaks // C. when the current VPBB is an entry of a region replica - where PrevVPBB 1591f58dda4SAyal Zaks // is the exit of this region from a previous instance, or the predecessor 1601f58dda4SAyal Zaks // of this region. 1611f58dda4SAyal Zaks if (PrevVPBB && /* A */ 1621f58dda4SAyal Zaks !((SingleHPred = getSingleHierarchicalPredecessor()) && 1631f58dda4SAyal Zaks SingleHPred->getExitBasicBlock() == PrevVPBB && 1641f58dda4SAyal Zaks PrevVPBB->getSingleHierarchicalSuccessor()) && /* B */ 1651f58dda4SAyal Zaks !(Replica && getPredecessors().empty())) { /* C */ 1661f58dda4SAyal Zaks NewBB = createEmptyBasicBlock(State->CFG); 1671f58dda4SAyal Zaks State->Builder.SetInsertPoint(NewBB); 1681f58dda4SAyal Zaks // Temporarily terminate with unreachable until CFG is rewired. 1691f58dda4SAyal Zaks UnreachableInst *Terminator = State->Builder.CreateUnreachable(); 1701f58dda4SAyal Zaks State->Builder.SetInsertPoint(Terminator); 1711f58dda4SAyal Zaks // Register NewBB in its loop. In innermost loops its the same for all BB's. 1721f58dda4SAyal Zaks Loop *L = State->LI->getLoopFor(State->CFG.LastBB); 1731f58dda4SAyal Zaks L->addBasicBlockToLoop(NewBB, *State->LI); 1741f58dda4SAyal Zaks State->CFG.PrevBB = NewBB; 1751f58dda4SAyal Zaks } 1761f58dda4SAyal Zaks 1771f58dda4SAyal Zaks // 2. Fill the IR basic block with IR instructions. 178d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "LV: vectorizing VPBB:" << getName() 1791f58dda4SAyal Zaks << " in BB:" << NewBB->getName() << '\n'); 1801f58dda4SAyal Zaks 1811f58dda4SAyal Zaks State->CFG.VPBB2IRBB[this] = NewBB; 1821f58dda4SAyal Zaks State->CFG.PrevVPBB = this; 1831f58dda4SAyal Zaks 1841f58dda4SAyal Zaks for (VPRecipeBase &Recipe : Recipes) 1851f58dda4SAyal Zaks Recipe.execute(*State); 1861f58dda4SAyal Zaks 187d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "LV: filled BB:" << *NewBB); 1881f58dda4SAyal Zaks } 1891f58dda4SAyal Zaks 1901f58dda4SAyal Zaks void VPRegionBlock::execute(VPTransformState *State) { 1911f58dda4SAyal Zaks ReversePostOrderTraversal<VPBlockBase *> RPOT(Entry); 1921f58dda4SAyal Zaks 1931f58dda4SAyal Zaks if (!isReplicator()) { 1941f58dda4SAyal Zaks // Visit the VPBlocks connected to "this", starting from it. 1951f58dda4SAyal Zaks for (VPBlockBase *Block : RPOT) { 196d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "LV: VPBlock in RPO " << Block->getName() << '\n'); 1971f58dda4SAyal Zaks Block->execute(State); 1981f58dda4SAyal Zaks } 1991f58dda4SAyal Zaks return; 2001f58dda4SAyal Zaks } 2011f58dda4SAyal Zaks 2021f58dda4SAyal Zaks assert(!State->Instance && "Replicating a Region with non-null instance."); 2031f58dda4SAyal Zaks 2041f58dda4SAyal Zaks // Enter replicating mode. 2051f58dda4SAyal Zaks State->Instance = {0, 0}; 2061f58dda4SAyal Zaks 2071f58dda4SAyal Zaks for (unsigned Part = 0, UF = State->UF; Part < UF; ++Part) { 2081f58dda4SAyal Zaks State->Instance->Part = Part; 2091f58dda4SAyal Zaks for (unsigned Lane = 0, VF = State->VF; Lane < VF; ++Lane) { 2101f58dda4SAyal Zaks State->Instance->Lane = Lane; 2111f58dda4SAyal Zaks // Visit the VPBlocks connected to \p this, starting from it. 2121f58dda4SAyal Zaks for (VPBlockBase *Block : RPOT) { 213d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "LV: VPBlock in RPO " << Block->getName() << '\n'); 2141f58dda4SAyal Zaks Block->execute(State); 2151f58dda4SAyal Zaks } 2161f58dda4SAyal Zaks } 2171f58dda4SAyal Zaks } 2181f58dda4SAyal Zaks 2191f58dda4SAyal Zaks // Exit replicating mode. 2201f58dda4SAyal Zaks State->Instance.reset(); 2211f58dda4SAyal Zaks } 2221f58dda4SAyal Zaks 2237591e4e9SFlorian Hahn void VPRecipeBase::insertBefore(VPRecipeBase *InsertPos) { 224*3bcff366SFlorian Hahn Parent = InsertPos->getParent(); 225*3bcff366SFlorian Hahn Parent->getRecipeList().insert(InsertPos->getIterator(), this); 2267591e4e9SFlorian Hahn } 2277591e4e9SFlorian Hahn 2288b9d1f3cSGil Rapaport void VPInstruction::generateInstruction(VPTransformState &State, 2298b9d1f3cSGil Rapaport unsigned Part) { 2308b9d1f3cSGil Rapaport IRBuilder<> &Builder = State.Builder; 2318b9d1f3cSGil Rapaport 2328b9d1f3cSGil Rapaport if (Instruction::isBinaryOp(getOpcode())) { 2338b9d1f3cSGil Rapaport Value *A = State.get(getOperand(0), Part); 2348b9d1f3cSGil Rapaport Value *B = State.get(getOperand(1), Part); 2358b9d1f3cSGil Rapaport Value *V = Builder.CreateBinOp((Instruction::BinaryOps)getOpcode(), A, B); 2368b9d1f3cSGil Rapaport State.set(this, V, Part); 2378b9d1f3cSGil Rapaport return; 2388b9d1f3cSGil Rapaport } 2398b9d1f3cSGil Rapaport 2408b9d1f3cSGil Rapaport switch (getOpcode()) { 2418b9d1f3cSGil Rapaport case VPInstruction::Not: { 2428b9d1f3cSGil Rapaport Value *A = State.get(getOperand(0), Part); 2438b9d1f3cSGil Rapaport Value *V = Builder.CreateNot(A); 2448b9d1f3cSGil Rapaport State.set(this, V, Part); 2458b9d1f3cSGil Rapaport break; 2468b9d1f3cSGil Rapaport } 2478b9d1f3cSGil Rapaport default: 2488b9d1f3cSGil Rapaport llvm_unreachable("Unsupported opcode for instruction"); 2498b9d1f3cSGil Rapaport } 2508b9d1f3cSGil Rapaport } 2518b9d1f3cSGil Rapaport 2528b9d1f3cSGil Rapaport void VPInstruction::execute(VPTransformState &State) { 2538b9d1f3cSGil Rapaport assert(!State.Instance && "VPInstruction executing an Instance"); 2548b9d1f3cSGil Rapaport for (unsigned Part = 0; Part < State.UF; ++Part) 2558b9d1f3cSGil Rapaport generateInstruction(State, Part); 2568b9d1f3cSGil Rapaport } 2578b9d1f3cSGil Rapaport 2588b9d1f3cSGil Rapaport void VPInstruction::print(raw_ostream &O, const Twine &Indent) const { 2598b9d1f3cSGil Rapaport O << " +\n" << Indent << "\"EMIT "; 2608b9d1f3cSGil Rapaport print(O); 2618b9d1f3cSGil Rapaport O << "\\l\""; 2628b9d1f3cSGil Rapaport } 2638b9d1f3cSGil Rapaport 2648b9d1f3cSGil Rapaport void VPInstruction::print(raw_ostream &O) const { 2658b9d1f3cSGil Rapaport printAsOperand(O); 2668b9d1f3cSGil Rapaport O << " = "; 2678b9d1f3cSGil Rapaport 2688b9d1f3cSGil Rapaport switch (getOpcode()) { 2698b9d1f3cSGil Rapaport case VPInstruction::Not: 2708b9d1f3cSGil Rapaport O << "not"; 2718b9d1f3cSGil Rapaport break; 2728b9d1f3cSGil Rapaport default: 2738b9d1f3cSGil Rapaport O << Instruction::getOpcodeName(getOpcode()); 2748b9d1f3cSGil Rapaport } 2758b9d1f3cSGil Rapaport 2768b9d1f3cSGil Rapaport for (const VPValue *Operand : operands()) { 2778b9d1f3cSGil Rapaport O << " "; 2788b9d1f3cSGil Rapaport Operand->printAsOperand(O); 2798b9d1f3cSGil Rapaport } 2808b9d1f3cSGil Rapaport } 2818b9d1f3cSGil Rapaport 2821f58dda4SAyal Zaks /// Generate the code inside the body of the vectorized loop. Assumes a single 2831f58dda4SAyal Zaks /// LoopVectorBody basic-block was created for this. Introduce additional 2841f58dda4SAyal Zaks /// basic-blocks as needed, and fill them all. 2851f58dda4SAyal Zaks void VPlan::execute(VPTransformState *State) { 2868b9d1f3cSGil Rapaport // 0. Set the reverse mapping from VPValues to Values for code generation. 2878b9d1f3cSGil Rapaport for (auto &Entry : Value2VPValue) 2888b9d1f3cSGil Rapaport State->VPValue2Value[Entry.second] = Entry.first; 2898b9d1f3cSGil Rapaport 2901f58dda4SAyal Zaks BasicBlock *VectorPreHeaderBB = State->CFG.PrevBB; 2911f58dda4SAyal Zaks BasicBlock *VectorHeaderBB = VectorPreHeaderBB->getSingleSuccessor(); 2921f58dda4SAyal Zaks assert(VectorHeaderBB && "Loop preheader does not have a single successor."); 2931f58dda4SAyal Zaks BasicBlock *VectorLatchBB = VectorHeaderBB; 2941f58dda4SAyal Zaks 2951f58dda4SAyal Zaks // 1. Make room to generate basic-blocks inside loop body if needed. 2961f58dda4SAyal Zaks VectorLatchBB = VectorHeaderBB->splitBasicBlock( 2971f58dda4SAyal Zaks VectorHeaderBB->getFirstInsertionPt(), "vector.body.latch"); 2981f58dda4SAyal Zaks Loop *L = State->LI->getLoopFor(VectorHeaderBB); 2991f58dda4SAyal Zaks L->addBasicBlockToLoop(VectorLatchBB, *State->LI); 3001f58dda4SAyal Zaks // Remove the edge between Header and Latch to allow other connections. 3011f58dda4SAyal Zaks // Temporarily terminate with unreachable until CFG is rewired. 3021f58dda4SAyal Zaks // Note: this asserts the generated code's assumption that 3031f58dda4SAyal Zaks // getFirstInsertionPt() can be dereferenced into an Instruction. 3041f58dda4SAyal Zaks VectorHeaderBB->getTerminator()->eraseFromParent(); 3051f58dda4SAyal Zaks State->Builder.SetInsertPoint(VectorHeaderBB); 3061f58dda4SAyal Zaks UnreachableInst *Terminator = State->Builder.CreateUnreachable(); 3071f58dda4SAyal Zaks State->Builder.SetInsertPoint(Terminator); 3081f58dda4SAyal Zaks 3091f58dda4SAyal Zaks // 2. Generate code in loop body. 3101f58dda4SAyal Zaks State->CFG.PrevVPBB = nullptr; 3111f58dda4SAyal Zaks State->CFG.PrevBB = VectorHeaderBB; 3121f58dda4SAyal Zaks State->CFG.LastBB = VectorLatchBB; 3131f58dda4SAyal Zaks 3141f58dda4SAyal Zaks for (VPBlockBase *Block : depth_first(Entry)) 3151f58dda4SAyal Zaks Block->execute(State); 3161f58dda4SAyal Zaks 3171f58dda4SAyal Zaks // 3. Merge the temporary latch created with the last basic-block filled. 3181f58dda4SAyal Zaks BasicBlock *LastBB = State->CFG.PrevBB; 3191f58dda4SAyal Zaks // Connect LastBB to VectorLatchBB to facilitate their merge. 3201f58dda4SAyal Zaks assert(isa<UnreachableInst>(LastBB->getTerminator()) && 3211f58dda4SAyal Zaks "Expected VPlan CFG to terminate with unreachable"); 3221f58dda4SAyal Zaks LastBB->getTerminator()->eraseFromParent(); 3231f58dda4SAyal Zaks BranchInst::Create(VectorLatchBB, LastBB); 3241f58dda4SAyal Zaks 3251f58dda4SAyal Zaks // Merge LastBB with Latch. 3261f58dda4SAyal Zaks bool Merged = MergeBlockIntoPredecessor(VectorLatchBB, nullptr, State->LI); 3271f58dda4SAyal Zaks (void)Merged; 3281f58dda4SAyal Zaks assert(Merged && "Could not merge last basic block with latch."); 3291f58dda4SAyal Zaks VectorLatchBB = LastBB; 3301f58dda4SAyal Zaks 3311f58dda4SAyal Zaks updateDominatorTree(State->DT, VectorPreHeaderBB, VectorLatchBB); 3321f58dda4SAyal Zaks } 3331f58dda4SAyal Zaks 3341f58dda4SAyal Zaks void VPlan::updateDominatorTree(DominatorTree *DT, BasicBlock *LoopPreHeaderBB, 3351f58dda4SAyal Zaks BasicBlock *LoopLatchBB) { 3361f58dda4SAyal Zaks BasicBlock *LoopHeaderBB = LoopPreHeaderBB->getSingleSuccessor(); 3371f58dda4SAyal Zaks assert(LoopHeaderBB && "Loop preheader does not have a single successor."); 3381f58dda4SAyal Zaks DT->addNewBlock(LoopHeaderBB, LoopPreHeaderBB); 3391f58dda4SAyal Zaks // The vector body may be more than a single basic-block by this point. 3401f58dda4SAyal Zaks // Update the dominator tree information inside the vector body by propagating 3411f58dda4SAyal Zaks // it from header to latch, expecting only triangular control-flow, if any. 3421f58dda4SAyal Zaks BasicBlock *PostDomSucc = nullptr; 3431f58dda4SAyal Zaks for (auto *BB = LoopHeaderBB; BB != LoopLatchBB; BB = PostDomSucc) { 3441f58dda4SAyal Zaks // Get the list of successors of this block. 3451f58dda4SAyal Zaks std::vector<BasicBlock *> Succs(succ_begin(BB), succ_end(BB)); 3461f58dda4SAyal Zaks assert(Succs.size() <= 2 && 3471f58dda4SAyal Zaks "Basic block in vector loop has more than 2 successors."); 3481f58dda4SAyal Zaks PostDomSucc = Succs[0]; 3491f58dda4SAyal Zaks if (Succs.size() == 1) { 3501f58dda4SAyal Zaks assert(PostDomSucc->getSinglePredecessor() && 3511f58dda4SAyal Zaks "PostDom successor has more than one predecessor."); 3521f58dda4SAyal Zaks DT->addNewBlock(PostDomSucc, BB); 3531f58dda4SAyal Zaks continue; 3541f58dda4SAyal Zaks } 3551f58dda4SAyal Zaks BasicBlock *InterimSucc = Succs[1]; 3561f58dda4SAyal Zaks if (PostDomSucc->getSingleSuccessor() == InterimSucc) { 3571f58dda4SAyal Zaks PostDomSucc = Succs[1]; 3581f58dda4SAyal Zaks InterimSucc = Succs[0]; 3591f58dda4SAyal Zaks } 3601f58dda4SAyal Zaks assert(InterimSucc->getSingleSuccessor() == PostDomSucc && 3611f58dda4SAyal Zaks "One successor of a basic block does not lead to the other."); 3621f58dda4SAyal Zaks assert(InterimSucc->getSinglePredecessor() && 3631f58dda4SAyal Zaks "Interim successor has more than one predecessor."); 364e0b5f86bSVedant Kumar assert(pred_size(PostDomSucc) == 2 && 3651f58dda4SAyal Zaks "PostDom successor has more than two predecessors."); 3661f58dda4SAyal Zaks DT->addNewBlock(InterimSucc, BB); 3671f58dda4SAyal Zaks DT->addNewBlock(PostDomSucc, BB); 3681f58dda4SAyal Zaks } 3691f58dda4SAyal Zaks } 3701f58dda4SAyal Zaks 3711f58dda4SAyal Zaks const Twine VPlanPrinter::getUID(const VPBlockBase *Block) { 3721f58dda4SAyal Zaks return (isa<VPRegionBlock>(Block) ? "cluster_N" : "N") + 3731f58dda4SAyal Zaks Twine(getOrCreateBID(Block)); 3741f58dda4SAyal Zaks } 3751f58dda4SAyal Zaks 3761f58dda4SAyal Zaks const Twine VPlanPrinter::getOrCreateName(const VPBlockBase *Block) { 3771f58dda4SAyal Zaks const std::string &Name = Block->getName(); 3781f58dda4SAyal Zaks if (!Name.empty()) 3791f58dda4SAyal Zaks return Name; 3801f58dda4SAyal Zaks return "VPB" + Twine(getOrCreateBID(Block)); 3811f58dda4SAyal Zaks } 3821f58dda4SAyal Zaks 3831f58dda4SAyal Zaks void VPlanPrinter::dump() { 3841f58dda4SAyal Zaks Depth = 1; 3851f58dda4SAyal Zaks bumpIndent(0); 3861f58dda4SAyal Zaks OS << "digraph VPlan {\n"; 3871f58dda4SAyal Zaks OS << "graph [labelloc=t, fontsize=30; label=\"Vectorization Plan"; 3881f58dda4SAyal Zaks if (!Plan.getName().empty()) 3891f58dda4SAyal Zaks OS << "\\n" << DOT::EscapeString(Plan.getName()); 3908b9d1f3cSGil Rapaport if (!Plan.Value2VPValue.empty()) { 3918b9d1f3cSGil Rapaport OS << ", where:"; 3928b9d1f3cSGil Rapaport for (auto Entry : Plan.Value2VPValue) { 3938b9d1f3cSGil Rapaport OS << "\\n" << *Entry.second; 3948b9d1f3cSGil Rapaport OS << DOT::EscapeString(" := "); 3958b9d1f3cSGil Rapaport Entry.first->printAsOperand(OS, false); 3968b9d1f3cSGil Rapaport } 3978b9d1f3cSGil Rapaport } 3981f58dda4SAyal Zaks OS << "\"]\n"; 3991f58dda4SAyal Zaks OS << "node [shape=rect, fontname=Courier, fontsize=30]\n"; 4001f58dda4SAyal Zaks OS << "edge [fontname=Courier, fontsize=30]\n"; 4011f58dda4SAyal Zaks OS << "compound=true\n"; 4021f58dda4SAyal Zaks 4031f58dda4SAyal Zaks for (VPBlockBase *Block : depth_first(Plan.getEntry())) 4041f58dda4SAyal Zaks dumpBlock(Block); 4051f58dda4SAyal Zaks 4061f58dda4SAyal Zaks OS << "}\n"; 4071f58dda4SAyal Zaks } 4081f58dda4SAyal Zaks 4091f58dda4SAyal Zaks void VPlanPrinter::dumpBlock(const VPBlockBase *Block) { 4101f58dda4SAyal Zaks if (const VPBasicBlock *BasicBlock = dyn_cast<VPBasicBlock>(Block)) 4111f58dda4SAyal Zaks dumpBasicBlock(BasicBlock); 4121f58dda4SAyal Zaks else if (const VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block)) 4131f58dda4SAyal Zaks dumpRegion(Region); 4141f58dda4SAyal Zaks else 4151f58dda4SAyal Zaks llvm_unreachable("Unsupported kind of VPBlock."); 4161f58dda4SAyal Zaks } 4171f58dda4SAyal Zaks 4181f58dda4SAyal Zaks void VPlanPrinter::drawEdge(const VPBlockBase *From, const VPBlockBase *To, 4191f58dda4SAyal Zaks bool Hidden, const Twine &Label) { 4201f58dda4SAyal Zaks // Due to "dot" we print an edge between two regions as an edge between the 4211f58dda4SAyal Zaks // exit basic block and the entry basic of the respective regions. 4221f58dda4SAyal Zaks const VPBlockBase *Tail = From->getExitBasicBlock(); 4231f58dda4SAyal Zaks const VPBlockBase *Head = To->getEntryBasicBlock(); 4241f58dda4SAyal Zaks OS << Indent << getUID(Tail) << " -> " << getUID(Head); 4251f58dda4SAyal Zaks OS << " [ label=\"" << Label << '\"'; 4261f58dda4SAyal Zaks if (Tail != From) 4271f58dda4SAyal Zaks OS << " ltail=" << getUID(From); 4281f58dda4SAyal Zaks if (Head != To) 4291f58dda4SAyal Zaks OS << " lhead=" << getUID(To); 4301f58dda4SAyal Zaks if (Hidden) 4311f58dda4SAyal Zaks OS << "; splines=none"; 4321f58dda4SAyal Zaks OS << "]\n"; 4331f58dda4SAyal Zaks } 4341f58dda4SAyal Zaks 4351f58dda4SAyal Zaks void VPlanPrinter::dumpEdges(const VPBlockBase *Block) { 4361f58dda4SAyal Zaks auto &Successors = Block->getSuccessors(); 4371f58dda4SAyal Zaks if (Successors.size() == 1) 4381f58dda4SAyal Zaks drawEdge(Block, Successors.front(), false, ""); 4391f58dda4SAyal Zaks else if (Successors.size() == 2) { 4401f58dda4SAyal Zaks drawEdge(Block, Successors.front(), false, "T"); 4411f58dda4SAyal Zaks drawEdge(Block, Successors.back(), false, "F"); 4421f58dda4SAyal Zaks } else { 4431f58dda4SAyal Zaks unsigned SuccessorNumber = 0; 4441f58dda4SAyal Zaks for (auto *Successor : Successors) 4451f58dda4SAyal Zaks drawEdge(Block, Successor, false, Twine(SuccessorNumber++)); 4461f58dda4SAyal Zaks } 4471f58dda4SAyal Zaks } 4481f58dda4SAyal Zaks 4491f58dda4SAyal Zaks void VPlanPrinter::dumpBasicBlock(const VPBasicBlock *BasicBlock) { 4501f58dda4SAyal Zaks OS << Indent << getUID(BasicBlock) << " [label =\n"; 4511f58dda4SAyal Zaks bumpIndent(1); 4521f58dda4SAyal Zaks OS << Indent << "\"" << DOT::EscapeString(BasicBlock->getName()) << ":\\n\""; 4531f58dda4SAyal Zaks bumpIndent(1); 4541f58dda4SAyal Zaks for (const VPRecipeBase &Recipe : *BasicBlock) 4551f58dda4SAyal Zaks Recipe.print(OS, Indent); 4561f58dda4SAyal Zaks bumpIndent(-2); 4571f58dda4SAyal Zaks OS << "\n" << Indent << "]\n"; 4581f58dda4SAyal Zaks dumpEdges(BasicBlock); 4591f58dda4SAyal Zaks } 4601f58dda4SAyal Zaks 4611f58dda4SAyal Zaks void VPlanPrinter::dumpRegion(const VPRegionBlock *Region) { 4621f58dda4SAyal Zaks OS << Indent << "subgraph " << getUID(Region) << " {\n"; 4631f58dda4SAyal Zaks bumpIndent(1); 4641f58dda4SAyal Zaks OS << Indent << "fontname=Courier\n" 4651f58dda4SAyal Zaks << Indent << "label=\"" 4661f58dda4SAyal Zaks << DOT::EscapeString(Region->isReplicator() ? "<xVFxUF> " : "<x1> ") 4671f58dda4SAyal Zaks << DOT::EscapeString(Region->getName()) << "\"\n"; 4681f58dda4SAyal Zaks // Dump the blocks of the region. 4691f58dda4SAyal Zaks assert(Region->getEntry() && "Region contains no inner blocks."); 4701f58dda4SAyal Zaks for (const VPBlockBase *Block : depth_first(Region->getEntry())) 4711f58dda4SAyal Zaks dumpBlock(Block); 4721f58dda4SAyal Zaks bumpIndent(-1); 4731f58dda4SAyal Zaks OS << Indent << "}\n"; 4741f58dda4SAyal Zaks dumpEdges(Region); 4751f58dda4SAyal Zaks } 4761f58dda4SAyal Zaks 4771f58dda4SAyal Zaks void VPlanPrinter::printAsIngredient(raw_ostream &O, Value *V) { 4781f58dda4SAyal Zaks std::string IngredientString; 4791f58dda4SAyal Zaks raw_string_ostream RSO(IngredientString); 4801f58dda4SAyal Zaks if (auto *Inst = dyn_cast<Instruction>(V)) { 4811f58dda4SAyal Zaks if (!Inst->getType()->isVoidTy()) { 4821f58dda4SAyal Zaks Inst->printAsOperand(RSO, false); 4831f58dda4SAyal Zaks RSO << " = "; 4841f58dda4SAyal Zaks } 4851f58dda4SAyal Zaks RSO << Inst->getOpcodeName() << " "; 4861f58dda4SAyal Zaks unsigned E = Inst->getNumOperands(); 4871f58dda4SAyal Zaks if (E > 0) { 4881f58dda4SAyal Zaks Inst->getOperand(0)->printAsOperand(RSO, false); 4891f58dda4SAyal Zaks for (unsigned I = 1; I < E; ++I) 4901f58dda4SAyal Zaks Inst->getOperand(I)->printAsOperand(RSO << ", ", false); 4911f58dda4SAyal Zaks } 4921f58dda4SAyal Zaks } else // !Inst 4931f58dda4SAyal Zaks V->printAsOperand(RSO, false); 4941f58dda4SAyal Zaks RSO.flush(); 4951f58dda4SAyal Zaks O << DOT::EscapeString(IngredientString); 4961f58dda4SAyal Zaks } 4977333aa9fSHal Finkel 4987333aa9fSHal Finkel void VPWidenRecipe::print(raw_ostream &O, const Twine &Indent) const { 4997333aa9fSHal Finkel O << " +\n" << Indent << "\"WIDEN\\l\""; 5007333aa9fSHal Finkel for (auto &Instr : make_range(Begin, End)) 5017333aa9fSHal Finkel O << " +\n" << Indent << "\" " << VPlanIngredient(&Instr) << "\\l\""; 5027333aa9fSHal Finkel } 5037333aa9fSHal Finkel 5047333aa9fSHal Finkel void VPWidenIntOrFpInductionRecipe::print(raw_ostream &O, 5057333aa9fSHal Finkel const Twine &Indent) const { 5067333aa9fSHal Finkel O << " +\n" << Indent << "\"WIDEN-INDUCTION"; 5077333aa9fSHal Finkel if (Trunc) { 5087333aa9fSHal Finkel O << "\\l\""; 5097333aa9fSHal Finkel O << " +\n" << Indent << "\" " << VPlanIngredient(IV) << "\\l\""; 5107333aa9fSHal Finkel O << " +\n" << Indent << "\" " << VPlanIngredient(Trunc) << "\\l\""; 5117333aa9fSHal Finkel } else 5127333aa9fSHal Finkel O << " " << VPlanIngredient(IV) << "\\l\""; 5137333aa9fSHal Finkel } 5147333aa9fSHal Finkel 5157333aa9fSHal Finkel void VPWidenPHIRecipe::print(raw_ostream &O, const Twine &Indent) const { 5167333aa9fSHal Finkel O << " +\n" << Indent << "\"WIDEN-PHI " << VPlanIngredient(Phi) << "\\l\""; 5177333aa9fSHal Finkel } 5187333aa9fSHal Finkel 5197333aa9fSHal Finkel void VPBlendRecipe::print(raw_ostream &O, const Twine &Indent) const { 5207333aa9fSHal Finkel O << " +\n" << Indent << "\"BLEND "; 5217333aa9fSHal Finkel Phi->printAsOperand(O, false); 5227333aa9fSHal Finkel O << " ="; 5237333aa9fSHal Finkel if (!User) { 5247333aa9fSHal Finkel // Not a User of any mask: not really blending, this is a 5257333aa9fSHal Finkel // single-predecessor phi. 5267333aa9fSHal Finkel O << " "; 5277333aa9fSHal Finkel Phi->getIncomingValue(0)->printAsOperand(O, false); 5287333aa9fSHal Finkel } else { 5297333aa9fSHal Finkel for (unsigned I = 0, E = User->getNumOperands(); I < E; ++I) { 5307333aa9fSHal Finkel O << " "; 5317333aa9fSHal Finkel Phi->getIncomingValue(I)->printAsOperand(O, false); 5327333aa9fSHal Finkel O << "/"; 5337333aa9fSHal Finkel User->getOperand(I)->printAsOperand(O); 5347333aa9fSHal Finkel } 5357333aa9fSHal Finkel } 5367333aa9fSHal Finkel O << "\\l\""; 5377333aa9fSHal Finkel } 5387333aa9fSHal Finkel 5397333aa9fSHal Finkel void VPReplicateRecipe::print(raw_ostream &O, const Twine &Indent) const { 5407333aa9fSHal Finkel O << " +\n" 5417333aa9fSHal Finkel << Indent << "\"" << (IsUniform ? "CLONE " : "REPLICATE ") 5427333aa9fSHal Finkel << VPlanIngredient(Ingredient); 5437333aa9fSHal Finkel if (AlsoPack) 5447333aa9fSHal Finkel O << " (S->V)"; 5457333aa9fSHal Finkel O << "\\l\""; 5467333aa9fSHal Finkel } 5477333aa9fSHal Finkel 5487333aa9fSHal Finkel void VPPredInstPHIRecipe::print(raw_ostream &O, const Twine &Indent) const { 5497333aa9fSHal Finkel O << " +\n" 5507333aa9fSHal Finkel << Indent << "\"PHI-PREDICATED-INSTRUCTION " << VPlanIngredient(PredInst) 5517333aa9fSHal Finkel << "\\l\""; 5527333aa9fSHal Finkel } 5537333aa9fSHal Finkel 5547333aa9fSHal Finkel void VPWidenMemoryInstructionRecipe::print(raw_ostream &O, 5557333aa9fSHal Finkel const Twine &Indent) const { 5567333aa9fSHal Finkel O << " +\n" << Indent << "\"WIDEN " << VPlanIngredient(&Instr); 5577333aa9fSHal Finkel if (User) { 5587333aa9fSHal Finkel O << ", "; 5597333aa9fSHal Finkel User->getOperand(0)->printAsOperand(O); 5607333aa9fSHal Finkel } 5617333aa9fSHal Finkel O << "\\l\""; 5627333aa9fSHal Finkel } 563