10b57cec5SDimitry Andric //===- VPlan.cpp - Vectorizer Plan ----------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric /// 90b57cec5SDimitry Andric /// \file 100b57cec5SDimitry Andric /// This is the LLVM vectorization plan. It represents a candidate for 110b57cec5SDimitry Andric /// vectorization, allowing to plan and optimize how to vectorize a given loop 120b57cec5SDimitry Andric /// before generating LLVM-IR. 130b57cec5SDimitry Andric /// The vectorizer uses vectorization plans to estimate the costs of potential 140b57cec5SDimitry Andric /// candidates and if profitable to execute the desired plan, generating vector 150b57cec5SDimitry Andric /// LLVM-IR code. 160b57cec5SDimitry Andric /// 170b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric #include "VPlan.h" 20*0fca6ea1SDimitry Andric #include "LoopVectorizationPlanner.h" 21bdd1243dSDimitry Andric #include "VPlanCFG.h" 220b57cec5SDimitry Andric #include "VPlanDominatorTree.h" 23*0fca6ea1SDimitry Andric #include "VPlanPatternMatch.h" 240b57cec5SDimitry Andric #include "llvm/ADT/PostOrderIterator.h" 25e8d8bef9SDimitry Andric #include "llvm/ADT/STLExtras.h" 260b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 2706c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h" 280b57cec5SDimitry Andric #include "llvm/ADT/Twine.h" 29*0fca6ea1SDimitry Andric #include "llvm/Analysis/DomTreeUpdater.h" 300b57cec5SDimitry Andric #include "llvm/Analysis/LoopInfo.h" 310b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h" 320b57cec5SDimitry Andric #include "llvm/IR/CFG.h" 3381ad6265SDimitry Andric #include "llvm/IR/IRBuilder.h" 340b57cec5SDimitry Andric #include "llvm/IR/Instruction.h" 350b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 360b57cec5SDimitry Andric #include "llvm/IR/Type.h" 370b57cec5SDimitry Andric #include "llvm/IR/Value.h" 380b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 39480093f4SDimitry Andric #include "llvm/Support/CommandLine.h" 400b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 410b57cec5SDimitry Andric #include "llvm/Support/GenericDomTreeConstruction.h" 420b57cec5SDimitry Andric #include "llvm/Support/GraphWriter.h" 430b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 440b57cec5SDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h" 4581ad6265SDimitry Andric #include "llvm/Transforms/Utils/LoopVersioning.h" 4681ad6265SDimitry Andric #include "llvm/Transforms/Utils/ScalarEvolutionExpander.h" 470b57cec5SDimitry Andric #include <cassert> 480b57cec5SDimitry Andric #include <string> 490b57cec5SDimitry Andric #include <vector> 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric using namespace llvm; 52*0fca6ea1SDimitry Andric using namespace llvm::VPlanPatternMatch; 5306c3fb27SDimitry Andric 5406c3fb27SDimitry Andric namespace llvm { 550b57cec5SDimitry Andric extern cl::opt<bool> EnableVPlanNativePath; 5606c3fb27SDimitry Andric } 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric #define DEBUG_TYPE "vplan" 590b57cec5SDimitry Andric 60fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 610b57cec5SDimitry Andric raw_ostream &llvm::operator<<(raw_ostream &OS, const VPValue &V) { 625ffd83dbSDimitry Andric const VPInstruction *Instr = dyn_cast<VPInstruction>(&V); 635ffd83dbSDimitry Andric VPSlotTracker SlotTracker( 645ffd83dbSDimitry Andric (Instr && Instr->getParent()) ? Instr->getParent()->getPlan() : nullptr); 655ffd83dbSDimitry Andric V.print(OS, SlotTracker); 660b57cec5SDimitry Andric return OS; 670b57cec5SDimitry Andric } 68fe6060f1SDimitry Andric #endif 69fe6060f1SDimitry Andric 7081ad6265SDimitry Andric Value *VPLane::getAsRuntimeExpr(IRBuilderBase &Builder, 71fe6060f1SDimitry Andric const ElementCount &VF) const { 72fe6060f1SDimitry Andric switch (LaneKind) { 73fe6060f1SDimitry Andric case VPLane::Kind::ScalableLast: 74fe6060f1SDimitry Andric // Lane = RuntimeVF - VF.getKnownMinValue() + Lane 75fe6060f1SDimitry Andric return Builder.CreateSub(getRuntimeVF(Builder, Builder.getInt32Ty(), VF), 76fe6060f1SDimitry Andric Builder.getInt32(VF.getKnownMinValue() - Lane)); 77fe6060f1SDimitry Andric case VPLane::Kind::First: 78fe6060f1SDimitry Andric return Builder.getInt32(Lane); 79fe6060f1SDimitry Andric } 80fe6060f1SDimitry Andric llvm_unreachable("Unknown lane kind"); 81fe6060f1SDimitry Andric } 820b57cec5SDimitry Andric 83e8d8bef9SDimitry Andric VPValue::VPValue(const unsigned char SC, Value *UV, VPDef *Def) 84e8d8bef9SDimitry Andric : SubclassID(SC), UnderlyingVal(UV), Def(Def) { 85e8d8bef9SDimitry Andric if (Def) 86e8d8bef9SDimitry Andric Def->addDefinedValue(this); 87e8d8bef9SDimitry Andric } 88e8d8bef9SDimitry Andric 89e8d8bef9SDimitry Andric VPValue::~VPValue() { 90e8d8bef9SDimitry Andric assert(Users.empty() && "trying to delete a VPValue with remaining users"); 91e8d8bef9SDimitry Andric if (Def) 92e8d8bef9SDimitry Andric Def->removeDefinedValue(this); 93e8d8bef9SDimitry Andric } 94e8d8bef9SDimitry Andric 95fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 965ffd83dbSDimitry Andric void VPValue::print(raw_ostream &OS, VPSlotTracker &SlotTracker) const { 97e8d8bef9SDimitry Andric if (const VPRecipeBase *R = dyn_cast_or_null<VPRecipeBase>(Def)) 98e8d8bef9SDimitry Andric R->print(OS, "", SlotTracker); 995ffd83dbSDimitry Andric else 1005ffd83dbSDimitry Andric printAsOperand(OS, SlotTracker); 1015ffd83dbSDimitry Andric } 1025ffd83dbSDimitry Andric 103e8d8bef9SDimitry Andric void VPValue::dump() const { 104e8d8bef9SDimitry Andric const VPRecipeBase *Instr = dyn_cast_or_null<VPRecipeBase>(this->Def); 105e8d8bef9SDimitry Andric VPSlotTracker SlotTracker( 106e8d8bef9SDimitry Andric (Instr && Instr->getParent()) ? Instr->getParent()->getPlan() : nullptr); 107e8d8bef9SDimitry Andric print(dbgs(), SlotTracker); 108e8d8bef9SDimitry Andric dbgs() << "\n"; 109e8d8bef9SDimitry Andric } 110e8d8bef9SDimitry Andric 111e8d8bef9SDimitry Andric void VPDef::dump() const { 112e8d8bef9SDimitry Andric const VPRecipeBase *Instr = dyn_cast_or_null<VPRecipeBase>(this); 113e8d8bef9SDimitry Andric VPSlotTracker SlotTracker( 114e8d8bef9SDimitry Andric (Instr && Instr->getParent()) ? Instr->getParent()->getPlan() : nullptr); 115e8d8bef9SDimitry Andric print(dbgs(), "", SlotTracker); 116e8d8bef9SDimitry Andric dbgs() << "\n"; 117e8d8bef9SDimitry Andric } 118fe6060f1SDimitry Andric #endif 119e8d8bef9SDimitry Andric 120bdd1243dSDimitry Andric VPRecipeBase *VPValue::getDefiningRecipe() { 121bdd1243dSDimitry Andric return cast_or_null<VPRecipeBase>(Def); 122bdd1243dSDimitry Andric } 123bdd1243dSDimitry Andric 124bdd1243dSDimitry Andric const VPRecipeBase *VPValue::getDefiningRecipe() const { 125bdd1243dSDimitry Andric return cast_or_null<VPRecipeBase>(Def); 126bdd1243dSDimitry Andric } 127bdd1243dSDimitry Andric 1285ffd83dbSDimitry Andric // Get the top-most entry block of \p Start. This is the entry block of the 1295ffd83dbSDimitry Andric // containing VPlan. This function is templated to support both const and non-const blocks 1305ffd83dbSDimitry Andric template <typename T> static T *getPlanEntry(T *Start) { 1315ffd83dbSDimitry Andric T *Next = Start; 1325ffd83dbSDimitry Andric T *Current = Start; 1335ffd83dbSDimitry Andric while ((Next = Next->getParent())) 1345ffd83dbSDimitry Andric Current = Next; 1355ffd83dbSDimitry Andric 1365ffd83dbSDimitry Andric SmallSetVector<T *, 8> WorkList; 1375ffd83dbSDimitry Andric WorkList.insert(Current); 1385ffd83dbSDimitry Andric 1395ffd83dbSDimitry Andric for (unsigned i = 0; i < WorkList.size(); i++) { 1405ffd83dbSDimitry Andric T *Current = WorkList[i]; 1415ffd83dbSDimitry Andric if (Current->getNumPredecessors() == 0) 1425ffd83dbSDimitry Andric return Current; 1435ffd83dbSDimitry Andric auto &Predecessors = Current->getPredecessors(); 1445ffd83dbSDimitry Andric WorkList.insert(Predecessors.begin(), Predecessors.end()); 1455ffd83dbSDimitry Andric } 1465ffd83dbSDimitry Andric 1475ffd83dbSDimitry Andric llvm_unreachable("VPlan without any entry node without predecessors"); 1485ffd83dbSDimitry Andric } 1495ffd83dbSDimitry Andric 1505ffd83dbSDimitry Andric VPlan *VPBlockBase::getPlan() { return getPlanEntry(this)->Plan; } 1515ffd83dbSDimitry Andric 1525ffd83dbSDimitry Andric const VPlan *VPBlockBase::getPlan() const { return getPlanEntry(this)->Plan; } 1535ffd83dbSDimitry Andric 1540b57cec5SDimitry Andric /// \return the VPBasicBlock that is the entry of Block, possibly indirectly. 1550b57cec5SDimitry Andric const VPBasicBlock *VPBlockBase::getEntryBasicBlock() const { 1560b57cec5SDimitry Andric const VPBlockBase *Block = this; 1570b57cec5SDimitry Andric while (const VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block)) 1580b57cec5SDimitry Andric Block = Region->getEntry(); 1590b57cec5SDimitry Andric return cast<VPBasicBlock>(Block); 1600b57cec5SDimitry Andric } 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric VPBasicBlock *VPBlockBase::getEntryBasicBlock() { 1630b57cec5SDimitry Andric VPBlockBase *Block = this; 1640b57cec5SDimitry Andric while (VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block)) 1650b57cec5SDimitry Andric Block = Region->getEntry(); 1660b57cec5SDimitry Andric return cast<VPBasicBlock>(Block); 1670b57cec5SDimitry Andric } 1680b57cec5SDimitry Andric 1695ffd83dbSDimitry Andric void VPBlockBase::setPlan(VPlan *ParentPlan) { 17006c3fb27SDimitry Andric assert( 17106c3fb27SDimitry Andric (ParentPlan->getEntry() == this || ParentPlan->getPreheader() == this) && 17206c3fb27SDimitry Andric "Can only set plan on its entry or preheader block."); 1735ffd83dbSDimitry Andric Plan = ParentPlan; 1745ffd83dbSDimitry Andric } 1755ffd83dbSDimitry Andric 1760b57cec5SDimitry Andric /// \return the VPBasicBlock that is the exit of Block, possibly indirectly. 17781ad6265SDimitry Andric const VPBasicBlock *VPBlockBase::getExitingBasicBlock() const { 1780b57cec5SDimitry Andric const VPBlockBase *Block = this; 1790b57cec5SDimitry Andric while (const VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block)) 18081ad6265SDimitry Andric Block = Region->getExiting(); 1810b57cec5SDimitry Andric return cast<VPBasicBlock>(Block); 1820b57cec5SDimitry Andric } 1830b57cec5SDimitry Andric 18481ad6265SDimitry Andric VPBasicBlock *VPBlockBase::getExitingBasicBlock() { 1850b57cec5SDimitry Andric VPBlockBase *Block = this; 1860b57cec5SDimitry Andric while (VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block)) 18781ad6265SDimitry Andric Block = Region->getExiting(); 1880b57cec5SDimitry Andric return cast<VPBasicBlock>(Block); 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric VPBlockBase *VPBlockBase::getEnclosingBlockWithSuccessors() { 1920b57cec5SDimitry Andric if (!Successors.empty() || !Parent) 1930b57cec5SDimitry Andric return this; 19481ad6265SDimitry Andric assert(Parent->getExiting() == this && 19581ad6265SDimitry Andric "Block w/o successors not the exiting block of its parent."); 1960b57cec5SDimitry Andric return Parent->getEnclosingBlockWithSuccessors(); 1970b57cec5SDimitry Andric } 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric VPBlockBase *VPBlockBase::getEnclosingBlockWithPredecessors() { 2000b57cec5SDimitry Andric if (!Predecessors.empty() || !Parent) 2010b57cec5SDimitry Andric return this; 2020b57cec5SDimitry Andric assert(Parent->getEntry() == this && 2030b57cec5SDimitry Andric "Block w/o predecessors not the entry of its parent."); 2040b57cec5SDimitry Andric return Parent->getEnclosingBlockWithPredecessors(); 2050b57cec5SDimitry Andric } 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric void VPBlockBase::deleteCFG(VPBlockBase *Entry) { 208bdd1243dSDimitry Andric for (VPBlockBase *Block : to_vector(vp_depth_first_shallow(Entry))) 2090b57cec5SDimitry Andric delete Block; 2100b57cec5SDimitry Andric } 2110b57cec5SDimitry Andric 212e8d8bef9SDimitry Andric VPBasicBlock::iterator VPBasicBlock::getFirstNonPhi() { 213e8d8bef9SDimitry Andric iterator It = begin(); 214fe6060f1SDimitry Andric while (It != end() && It->isPhi()) 215e8d8bef9SDimitry Andric It++; 216e8d8bef9SDimitry Andric return It; 217e8d8bef9SDimitry Andric } 218e8d8bef9SDimitry Andric 219*0fca6ea1SDimitry Andric VPTransformState::VPTransformState(ElementCount VF, unsigned UF, LoopInfo *LI, 220*0fca6ea1SDimitry Andric DominatorTree *DT, IRBuilderBase &Builder, 221*0fca6ea1SDimitry Andric InnerLoopVectorizer *ILV, VPlan *Plan, 222*0fca6ea1SDimitry Andric LLVMContext &Ctx) 223*0fca6ea1SDimitry Andric : VF(VF), UF(UF), CFG(DT), LI(LI), Builder(Builder), ILV(ILV), Plan(Plan), 224*0fca6ea1SDimitry Andric LVer(nullptr), 225*0fca6ea1SDimitry Andric TypeAnalysis(Plan->getCanonicalIV()->getScalarType(), Ctx) {} 226*0fca6ea1SDimitry Andric 227e8d8bef9SDimitry Andric Value *VPTransformState::get(VPValue *Def, const VPIteration &Instance) { 22806c3fb27SDimitry Andric if (Def->isLiveIn()) 229e8d8bef9SDimitry Andric return Def->getLiveInIRValue(); 230e8d8bef9SDimitry Andric 231fe6060f1SDimitry Andric if (hasScalarValue(Def, Instance)) { 232fe6060f1SDimitry Andric return Data 233fe6060f1SDimitry Andric .PerPartScalars[Def][Instance.Part][Instance.Lane.mapToCacheIndex(VF)]; 234fe6060f1SDimitry Andric } 235*0fca6ea1SDimitry Andric if (!Instance.Lane.isFirstLane() && 236*0fca6ea1SDimitry Andric vputils::isUniformAfterVectorization(Def) && 237*0fca6ea1SDimitry Andric hasScalarValue(Def, {Instance.Part, VPLane::getFirstLane()})) { 238*0fca6ea1SDimitry Andric return Data.PerPartScalars[Def][Instance.Part][0]; 239*0fca6ea1SDimitry Andric } 240e8d8bef9SDimitry Andric 241fe6060f1SDimitry Andric assert(hasVectorValue(Def, Instance.Part)); 242e8d8bef9SDimitry Andric auto *VecPart = Data.PerPartOutput[Def][Instance.Part]; 243e8d8bef9SDimitry Andric if (!VecPart->getType()->isVectorTy()) { 244fe6060f1SDimitry Andric assert(Instance.Lane.isFirstLane() && "cannot get lane > 0 for scalar"); 245e8d8bef9SDimitry Andric return VecPart; 246e8d8bef9SDimitry Andric } 247e8d8bef9SDimitry Andric // TODO: Cache created scalar values. 248fe6060f1SDimitry Andric Value *Lane = Instance.Lane.getAsRuntimeExpr(Builder, VF); 249fe6060f1SDimitry Andric auto *Extract = Builder.CreateExtractElement(VecPart, Lane); 250fe6060f1SDimitry Andric // set(Def, Extract, Instance); 251fe6060f1SDimitry Andric return Extract; 252e8d8bef9SDimitry Andric } 2535f757f3fSDimitry Andric 254*0fca6ea1SDimitry Andric Value *VPTransformState::get(VPValue *Def, unsigned Part, bool NeedsScalar) { 255*0fca6ea1SDimitry Andric if (NeedsScalar) { 256*0fca6ea1SDimitry Andric assert((VF.isScalar() || Def->isLiveIn() || hasVectorValue(Def, Part) || 257*0fca6ea1SDimitry Andric !vputils::onlyFirstLaneUsed(Def) || 258*0fca6ea1SDimitry Andric (hasScalarValue(Def, VPIteration(Part, 0)) && 259*0fca6ea1SDimitry Andric Data.PerPartScalars[Def][Part].size() == 1)) && 260*0fca6ea1SDimitry Andric "Trying to access a single scalar per part but has multiple scalars " 261*0fca6ea1SDimitry Andric "per part."); 262*0fca6ea1SDimitry Andric return get(Def, VPIteration(Part, 0)); 263*0fca6ea1SDimitry Andric } 264*0fca6ea1SDimitry Andric 2655f757f3fSDimitry Andric // If Values have been set for this Def return the one relevant for \p Part. 2665f757f3fSDimitry Andric if (hasVectorValue(Def, Part)) 2675f757f3fSDimitry Andric return Data.PerPartOutput[Def][Part]; 2685f757f3fSDimitry Andric 2695f757f3fSDimitry Andric auto GetBroadcastInstrs = [this, Def](Value *V) { 2705f757f3fSDimitry Andric bool SafeToHoist = Def->isDefinedOutsideVectorRegions(); 2715f757f3fSDimitry Andric if (VF.isScalar()) 2725f757f3fSDimitry Andric return V; 2735f757f3fSDimitry Andric // Place the code for broadcasting invariant variables in the new preheader. 2745f757f3fSDimitry Andric IRBuilder<>::InsertPointGuard Guard(Builder); 2755f757f3fSDimitry Andric if (SafeToHoist) { 2765f757f3fSDimitry Andric BasicBlock *LoopVectorPreHeader = CFG.VPBB2IRBB[cast<VPBasicBlock>( 2775f757f3fSDimitry Andric Plan->getVectorLoopRegion()->getSinglePredecessor())]; 2785f757f3fSDimitry Andric if (LoopVectorPreHeader) 2795f757f3fSDimitry Andric Builder.SetInsertPoint(LoopVectorPreHeader->getTerminator()); 2805f757f3fSDimitry Andric } 2815f757f3fSDimitry Andric 2825f757f3fSDimitry Andric // Place the code for broadcasting invariant variables in the new preheader. 2835f757f3fSDimitry Andric // Broadcast the scalar into all locations in the vector. 2845f757f3fSDimitry Andric Value *Shuf = Builder.CreateVectorSplat(VF, V, "broadcast"); 2855f757f3fSDimitry Andric 2865f757f3fSDimitry Andric return Shuf; 2875f757f3fSDimitry Andric }; 2885f757f3fSDimitry Andric 2895f757f3fSDimitry Andric if (!hasScalarValue(Def, {Part, 0})) { 2905f757f3fSDimitry Andric assert(Def->isLiveIn() && "expected a live-in"); 2915f757f3fSDimitry Andric if (Part != 0) 2925f757f3fSDimitry Andric return get(Def, 0); 2935f757f3fSDimitry Andric Value *IRV = Def->getLiveInIRValue(); 2945f757f3fSDimitry Andric Value *B = GetBroadcastInstrs(IRV); 2955f757f3fSDimitry Andric set(Def, B, Part); 2965f757f3fSDimitry Andric return B; 2975f757f3fSDimitry Andric } 2985f757f3fSDimitry Andric 2995f757f3fSDimitry Andric Value *ScalarValue = get(Def, {Part, 0}); 3005f757f3fSDimitry Andric // If we aren't vectorizing, we can just copy the scalar map values over 3015f757f3fSDimitry Andric // to the vector map. 3025f757f3fSDimitry Andric if (VF.isScalar()) { 3035f757f3fSDimitry Andric set(Def, ScalarValue, Part); 3045f757f3fSDimitry Andric return ScalarValue; 3055f757f3fSDimitry Andric } 3065f757f3fSDimitry Andric 3075f757f3fSDimitry Andric bool IsUniform = vputils::isUniformAfterVectorization(Def); 3085f757f3fSDimitry Andric 3095f757f3fSDimitry Andric unsigned LastLane = IsUniform ? 0 : VF.getKnownMinValue() - 1; 3105f757f3fSDimitry Andric // Check if there is a scalar value for the selected lane. 3115f757f3fSDimitry Andric if (!hasScalarValue(Def, {Part, LastLane})) { 3125f757f3fSDimitry Andric // At the moment, VPWidenIntOrFpInductionRecipes, VPScalarIVStepsRecipes and 3135f757f3fSDimitry Andric // VPExpandSCEVRecipes can also be uniform. 3145f757f3fSDimitry Andric assert((isa<VPWidenIntOrFpInductionRecipe>(Def->getDefiningRecipe()) || 3155f757f3fSDimitry Andric isa<VPScalarIVStepsRecipe>(Def->getDefiningRecipe()) || 3165f757f3fSDimitry Andric isa<VPExpandSCEVRecipe>(Def->getDefiningRecipe())) && 3175f757f3fSDimitry Andric "unexpected recipe found to be invariant"); 3185f757f3fSDimitry Andric IsUniform = true; 3195f757f3fSDimitry Andric LastLane = 0; 3205f757f3fSDimitry Andric } 3215f757f3fSDimitry Andric 3225f757f3fSDimitry Andric auto *LastInst = cast<Instruction>(get(Def, {Part, LastLane})); 3235f757f3fSDimitry Andric // Set the insert point after the last scalarized instruction or after the 3245f757f3fSDimitry Andric // last PHI, if LastInst is a PHI. This ensures the insertelement sequence 3255f757f3fSDimitry Andric // will directly follow the scalar definitions. 3265f757f3fSDimitry Andric auto OldIP = Builder.saveIP(); 3275f757f3fSDimitry Andric auto NewIP = 3285f757f3fSDimitry Andric isa<PHINode>(LastInst) 3295f757f3fSDimitry Andric ? BasicBlock::iterator(LastInst->getParent()->getFirstNonPHI()) 3305f757f3fSDimitry Andric : std::next(BasicBlock::iterator(LastInst)); 3315f757f3fSDimitry Andric Builder.SetInsertPoint(&*NewIP); 3325f757f3fSDimitry Andric 3335f757f3fSDimitry Andric // However, if we are vectorizing, we need to construct the vector values. 3345f757f3fSDimitry Andric // If the value is known to be uniform after vectorization, we can just 3355f757f3fSDimitry Andric // broadcast the scalar value corresponding to lane zero for each unroll 3365f757f3fSDimitry Andric // iteration. Otherwise, we construct the vector values using 3375f757f3fSDimitry Andric // insertelement instructions. Since the resulting vectors are stored in 3385f757f3fSDimitry Andric // State, we will only generate the insertelements once. 3395f757f3fSDimitry Andric Value *VectorValue = nullptr; 3405f757f3fSDimitry Andric if (IsUniform) { 3415f757f3fSDimitry Andric VectorValue = GetBroadcastInstrs(ScalarValue); 3425f757f3fSDimitry Andric set(Def, VectorValue, Part); 3435f757f3fSDimitry Andric } else { 3445f757f3fSDimitry Andric // Initialize packing with insertelements to start from undef. 3455f757f3fSDimitry Andric assert(!VF.isScalable() && "VF is assumed to be non scalable."); 3465f757f3fSDimitry Andric Value *Undef = PoisonValue::get(VectorType::get(LastInst->getType(), VF)); 3475f757f3fSDimitry Andric set(Def, Undef, Part); 3485f757f3fSDimitry Andric for (unsigned Lane = 0; Lane < VF.getKnownMinValue(); ++Lane) 3495f757f3fSDimitry Andric packScalarIntoVectorValue(Def, {Part, Lane}); 3505f757f3fSDimitry Andric VectorValue = get(Def, Part); 3515f757f3fSDimitry Andric } 3525f757f3fSDimitry Andric Builder.restoreIP(OldIP); 3535f757f3fSDimitry Andric return VectorValue; 3545f757f3fSDimitry Andric } 3555f757f3fSDimitry Andric 35681ad6265SDimitry Andric BasicBlock *VPTransformState::CFGState::getPreheaderBBFor(VPRecipeBase *R) { 35781ad6265SDimitry Andric VPRegionBlock *LoopRegion = R->getParent()->getEnclosingLoopRegion(); 35881ad6265SDimitry Andric return VPBB2IRBB[LoopRegion->getPreheaderVPBB()]; 35981ad6265SDimitry Andric } 36081ad6265SDimitry Andric 36181ad6265SDimitry Andric void VPTransformState::addNewMetadata(Instruction *To, 36281ad6265SDimitry Andric const Instruction *Orig) { 36381ad6265SDimitry Andric // If the loop was versioned with memchecks, add the corresponding no-alias 36481ad6265SDimitry Andric // metadata. 36581ad6265SDimitry Andric if (LVer && (isa<LoadInst>(Orig) || isa<StoreInst>(Orig))) 36681ad6265SDimitry Andric LVer->annotateInstWithNoAlias(To, Orig); 36781ad6265SDimitry Andric } 36881ad6265SDimitry Andric 369*0fca6ea1SDimitry Andric void VPTransformState::addMetadata(Value *To, Instruction *From) { 37006c3fb27SDimitry Andric // No source instruction to transfer metadata from? 37106c3fb27SDimitry Andric if (!From) 37206c3fb27SDimitry Andric return; 37306c3fb27SDimitry Andric 374*0fca6ea1SDimitry Andric if (Instruction *ToI = dyn_cast<Instruction>(To)) { 375*0fca6ea1SDimitry Andric propagateMetadata(ToI, From); 376*0fca6ea1SDimitry Andric addNewMetadata(ToI, From); 37781ad6265SDimitry Andric } 37881ad6265SDimitry Andric } 37981ad6265SDimitry Andric 3805f757f3fSDimitry Andric void VPTransformState::setDebugLocFrom(DebugLoc DL) { 3815f757f3fSDimitry Andric const DILocation *DIL = DL; 38281ad6265SDimitry Andric // When a FSDiscriminator is enabled, we don't need to add the multiply 38381ad6265SDimitry Andric // factors to the discriminators. 3845f757f3fSDimitry Andric if (DIL && 3855f757f3fSDimitry Andric Builder.GetInsertBlock() 3865f757f3fSDimitry Andric ->getParent() 3875f757f3fSDimitry Andric ->shouldEmitDebugInfoForProfiling() && 3885f757f3fSDimitry Andric !EnableFSDiscriminator) { 38981ad6265SDimitry Andric // FIXME: For scalable vectors, assume vscale=1. 39081ad6265SDimitry Andric auto NewDIL = 39181ad6265SDimitry Andric DIL->cloneByMultiplyingDuplicationFactor(UF * VF.getKnownMinValue()); 39281ad6265SDimitry Andric if (NewDIL) 39381ad6265SDimitry Andric Builder.SetCurrentDebugLocation(*NewDIL); 39481ad6265SDimitry Andric else 39581ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "Failed to create new discriminator: " 39681ad6265SDimitry Andric << DIL->getFilename() << " Line: " << DIL->getLine()); 39781ad6265SDimitry Andric } else 39881ad6265SDimitry Andric Builder.SetCurrentDebugLocation(DIL); 39981ad6265SDimitry Andric } 400e8d8bef9SDimitry Andric 4015f757f3fSDimitry Andric void VPTransformState::packScalarIntoVectorValue(VPValue *Def, 4025f757f3fSDimitry Andric const VPIteration &Instance) { 4035f757f3fSDimitry Andric Value *ScalarInst = get(Def, Instance); 4045f757f3fSDimitry Andric Value *VectorValue = get(Def, Instance.Part); 4055f757f3fSDimitry Andric VectorValue = Builder.CreateInsertElement( 4065f757f3fSDimitry Andric VectorValue, ScalarInst, Instance.Lane.getAsRuntimeExpr(Builder, VF)); 4075f757f3fSDimitry Andric set(Def, VectorValue, Instance.Part); 4085f757f3fSDimitry Andric } 4095f757f3fSDimitry Andric 4100b57cec5SDimitry Andric BasicBlock * 4110b57cec5SDimitry Andric VPBasicBlock::createEmptyBasicBlock(VPTransformState::CFGState &CFG) { 4120b57cec5SDimitry Andric // BB stands for IR BasicBlocks. VPBB stands for VPlan VPBasicBlocks. 4130b57cec5SDimitry Andric // Pred stands for Predessor. Prev stands for Previous - last visited/created. 4140b57cec5SDimitry Andric BasicBlock *PrevBB = CFG.PrevBB; 4150b57cec5SDimitry Andric BasicBlock *NewBB = BasicBlock::Create(PrevBB->getContext(), getName(), 41681ad6265SDimitry Andric PrevBB->getParent(), CFG.ExitBB); 4170b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "LV: created " << NewBB->getName() << '\n'); 4180b57cec5SDimitry Andric 4190b57cec5SDimitry Andric // Hook up the new basic block to its predecessors. 4200b57cec5SDimitry Andric for (VPBlockBase *PredVPBlock : getHierarchicalPredecessors()) { 42181ad6265SDimitry Andric VPBasicBlock *PredVPBB = PredVPBlock->getExitingBasicBlock(); 42281ad6265SDimitry Andric auto &PredVPSuccessors = PredVPBB->getHierarchicalSuccessors(); 4230b57cec5SDimitry Andric BasicBlock *PredBB = CFG.VPBB2IRBB[PredVPBB]; 4240b57cec5SDimitry Andric 4250b57cec5SDimitry Andric assert(PredBB && "Predecessor basic-block not found building successor."); 4260b57cec5SDimitry Andric auto *PredBBTerminator = PredBB->getTerminator(); 4270b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "LV: draw edge from" << PredBB->getName() << '\n'); 42881ad6265SDimitry Andric 42981ad6265SDimitry Andric auto *TermBr = dyn_cast<BranchInst>(PredBBTerminator); 4300b57cec5SDimitry Andric if (isa<UnreachableInst>(PredBBTerminator)) { 4310b57cec5SDimitry Andric assert(PredVPSuccessors.size() == 1 && 4320b57cec5SDimitry Andric "Predecessor ending w/o branch must have single successor."); 43381ad6265SDimitry Andric DebugLoc DL = PredBBTerminator->getDebugLoc(); 4340b57cec5SDimitry Andric PredBBTerminator->eraseFromParent(); 43581ad6265SDimitry Andric auto *Br = BranchInst::Create(NewBB, PredBB); 43681ad6265SDimitry Andric Br->setDebugLoc(DL); 43781ad6265SDimitry Andric } else if (TermBr && !TermBr->isConditional()) { 43881ad6265SDimitry Andric TermBr->setSuccessor(0, NewBB); 4390b57cec5SDimitry Andric } else { 44081ad6265SDimitry Andric // Set each forward successor here when it is created, excluding 44181ad6265SDimitry Andric // backedges. A backward successor is set when the branch is created. 4420b57cec5SDimitry Andric unsigned idx = PredVPSuccessors.front() == this ? 0 : 1; 44381ad6265SDimitry Andric assert(!TermBr->getSuccessor(idx) && 4440b57cec5SDimitry Andric "Trying to reset an existing successor block."); 44581ad6265SDimitry Andric TermBr->setSuccessor(idx, NewBB); 4460b57cec5SDimitry Andric } 447*0fca6ea1SDimitry Andric CFG.DTU.applyUpdates({{DominatorTree::Insert, PredBB, NewBB}}); 4480b57cec5SDimitry Andric } 4490b57cec5SDimitry Andric return NewBB; 4500b57cec5SDimitry Andric } 4510b57cec5SDimitry Andric 452*0fca6ea1SDimitry Andric void VPIRBasicBlock::execute(VPTransformState *State) { 453*0fca6ea1SDimitry Andric assert(getHierarchicalSuccessors().size() <= 2 && 454*0fca6ea1SDimitry Andric "VPIRBasicBlock can have at most two successors at the moment!"); 455*0fca6ea1SDimitry Andric State->Builder.SetInsertPoint(getIRBasicBlock()->getTerminator()); 456*0fca6ea1SDimitry Andric executeRecipes(State, getIRBasicBlock()); 457*0fca6ea1SDimitry Andric if (getSingleSuccessor()) { 458*0fca6ea1SDimitry Andric assert(isa<UnreachableInst>(getIRBasicBlock()->getTerminator())); 459*0fca6ea1SDimitry Andric auto *Br = State->Builder.CreateBr(getIRBasicBlock()); 460*0fca6ea1SDimitry Andric Br->setOperand(0, nullptr); 461*0fca6ea1SDimitry Andric getIRBasicBlock()->getTerminator()->eraseFromParent(); 462*0fca6ea1SDimitry Andric } 463*0fca6ea1SDimitry Andric 464*0fca6ea1SDimitry Andric for (VPBlockBase *PredVPBlock : getHierarchicalPredecessors()) { 465*0fca6ea1SDimitry Andric VPBasicBlock *PredVPBB = PredVPBlock->getExitingBasicBlock(); 466*0fca6ea1SDimitry Andric BasicBlock *PredBB = State->CFG.VPBB2IRBB[PredVPBB]; 467*0fca6ea1SDimitry Andric assert(PredBB && "Predecessor basic-block not found building successor."); 468*0fca6ea1SDimitry Andric LLVM_DEBUG(dbgs() << "LV: draw edge from" << PredBB->getName() << '\n'); 469*0fca6ea1SDimitry Andric 470*0fca6ea1SDimitry Andric auto *PredBBTerminator = PredBB->getTerminator(); 471*0fca6ea1SDimitry Andric auto *TermBr = cast<BranchInst>(PredBBTerminator); 472*0fca6ea1SDimitry Andric // Set each forward successor here when it is created, excluding 473*0fca6ea1SDimitry Andric // backedges. A backward successor is set when the branch is created. 474*0fca6ea1SDimitry Andric const auto &PredVPSuccessors = PredVPBB->getHierarchicalSuccessors(); 475*0fca6ea1SDimitry Andric unsigned idx = PredVPSuccessors.front() == this ? 0 : 1; 476*0fca6ea1SDimitry Andric assert(!TermBr->getSuccessor(idx) && 477*0fca6ea1SDimitry Andric "Trying to reset an existing successor block."); 478*0fca6ea1SDimitry Andric TermBr->setSuccessor(idx, IRBB); 479*0fca6ea1SDimitry Andric State->CFG.DTU.applyUpdates({{DominatorTree::Insert, PredBB, IRBB}}); 480*0fca6ea1SDimitry Andric } 481*0fca6ea1SDimitry Andric } 482*0fca6ea1SDimitry Andric 4830b57cec5SDimitry Andric void VPBasicBlock::execute(VPTransformState *State) { 484fe6060f1SDimitry Andric bool Replica = State->Instance && !State->Instance->isFirstIteration(); 4850b57cec5SDimitry Andric VPBasicBlock *PrevVPBB = State->CFG.PrevVPBB; 4860b57cec5SDimitry Andric VPBlockBase *SingleHPred = nullptr; 4870b57cec5SDimitry Andric BasicBlock *NewBB = State->CFG.PrevBB; // Reuse it if possible. 4880b57cec5SDimitry Andric 48981ad6265SDimitry Andric auto IsLoopRegion = [](VPBlockBase *BB) { 49081ad6265SDimitry Andric auto *R = dyn_cast<VPRegionBlock>(BB); 49181ad6265SDimitry Andric return R && !R->isReplicator(); 49281ad6265SDimitry Andric }; 49381ad6265SDimitry Andric 494*0fca6ea1SDimitry Andric // 1. Create an IR basic block. 495*0fca6ea1SDimitry Andric if (PrevVPBB && /* A */ 4960b57cec5SDimitry Andric !((SingleHPred = getSingleHierarchicalPredecessor()) && 49781ad6265SDimitry Andric SingleHPred->getExitingBasicBlock() == PrevVPBB && 49881ad6265SDimitry Andric PrevVPBB->getSingleHierarchicalSuccessor() && 49981ad6265SDimitry Andric (SingleHPred->getParent() == getEnclosingLoopRegion() && 50081ad6265SDimitry Andric !IsLoopRegion(SingleHPred))) && /* B */ 5010b57cec5SDimitry Andric !(Replica && getPredecessors().empty())) { /* C */ 50281ad6265SDimitry Andric // The last IR basic block is reused, as an optimization, in three cases: 50381ad6265SDimitry Andric // A. the first VPBB reuses the loop pre-header BB - when PrevVPBB is null; 50481ad6265SDimitry Andric // B. when the current VPBB has a single (hierarchical) predecessor which 50581ad6265SDimitry Andric // is PrevVPBB and the latter has a single (hierarchical) successor which 50681ad6265SDimitry Andric // both are in the same non-replicator region; and 50781ad6265SDimitry Andric // C. when the current VPBB is an entry of a region replica - where PrevVPBB 50881ad6265SDimitry Andric // is the exiting VPBB of this region from a previous instance, or the 50981ad6265SDimitry Andric // predecessor of this region. 51081ad6265SDimitry Andric 5110b57cec5SDimitry Andric NewBB = createEmptyBasicBlock(State->CFG); 5120b57cec5SDimitry Andric State->Builder.SetInsertPoint(NewBB); 5130b57cec5SDimitry Andric // Temporarily terminate with unreachable until CFG is rewired. 5140b57cec5SDimitry Andric UnreachableInst *Terminator = State->Builder.CreateUnreachable(); 51581ad6265SDimitry Andric // Register NewBB in its loop. In innermost loops its the same for all 51681ad6265SDimitry Andric // BB's. 51781ad6265SDimitry Andric if (State->CurrentVectorLoop) 51881ad6265SDimitry Andric State->CurrentVectorLoop->addBasicBlockToLoop(NewBB, *State->LI); 5190b57cec5SDimitry Andric State->Builder.SetInsertPoint(Terminator); 5200b57cec5SDimitry Andric State->CFG.PrevBB = NewBB; 5210b57cec5SDimitry Andric } 5220b57cec5SDimitry Andric 5230b57cec5SDimitry Andric // 2. Fill the IR basic block with IR instructions. 524*0fca6ea1SDimitry Andric executeRecipes(State, NewBB); 5250b57cec5SDimitry Andric } 5260b57cec5SDimitry Andric 527e8d8bef9SDimitry Andric void VPBasicBlock::dropAllReferences(VPValue *NewValue) { 528e8d8bef9SDimitry Andric for (VPRecipeBase &R : Recipes) { 529e8d8bef9SDimitry Andric for (auto *Def : R.definedValues()) 530e8d8bef9SDimitry Andric Def->replaceAllUsesWith(NewValue); 531e8d8bef9SDimitry Andric 532fe6060f1SDimitry Andric for (unsigned I = 0, E = R.getNumOperands(); I != E; I++) 533fe6060f1SDimitry Andric R.setOperand(I, NewValue); 534e8d8bef9SDimitry Andric } 535e8d8bef9SDimitry Andric } 536e8d8bef9SDimitry Andric 537*0fca6ea1SDimitry Andric void VPBasicBlock::executeRecipes(VPTransformState *State, BasicBlock *BB) { 538*0fca6ea1SDimitry Andric LLVM_DEBUG(dbgs() << "LV: vectorizing VPBB:" << getName() 539*0fca6ea1SDimitry Andric << " in BB:" << BB->getName() << '\n'); 540*0fca6ea1SDimitry Andric 541*0fca6ea1SDimitry Andric State->CFG.VPBB2IRBB[this] = BB; 542*0fca6ea1SDimitry Andric State->CFG.PrevVPBB = this; 543*0fca6ea1SDimitry Andric 544*0fca6ea1SDimitry Andric for (VPRecipeBase &Recipe : Recipes) 545*0fca6ea1SDimitry Andric Recipe.execute(*State); 546*0fca6ea1SDimitry Andric 547*0fca6ea1SDimitry Andric LLVM_DEBUG(dbgs() << "LV: filled BB:" << *BB); 548*0fca6ea1SDimitry Andric } 549*0fca6ea1SDimitry Andric 550fe6060f1SDimitry Andric VPBasicBlock *VPBasicBlock::splitAt(iterator SplitAt) { 551fe6060f1SDimitry Andric assert((SplitAt == end() || SplitAt->getParent() == this) && 552fe6060f1SDimitry Andric "can only split at a position in the same block"); 553fe6060f1SDimitry Andric 5540eae32dcSDimitry Andric SmallVector<VPBlockBase *, 2> Succs(successors()); 555fe6060f1SDimitry Andric // First, disconnect the current block from its successors. 556fe6060f1SDimitry Andric for (VPBlockBase *Succ : Succs) 557fe6060f1SDimitry Andric VPBlockUtils::disconnectBlocks(this, Succ); 558fe6060f1SDimitry Andric 559fe6060f1SDimitry Andric // Create new empty block after the block to split. 560fe6060f1SDimitry Andric auto *SplitBlock = new VPBasicBlock(getName() + ".split"); 561fe6060f1SDimitry Andric VPBlockUtils::insertBlockAfter(SplitBlock, this); 562fe6060f1SDimitry Andric 563fe6060f1SDimitry Andric // Add successors for block to split to new block. 564fe6060f1SDimitry Andric for (VPBlockBase *Succ : Succs) 565fe6060f1SDimitry Andric VPBlockUtils::connectBlocks(SplitBlock, Succ); 566fe6060f1SDimitry Andric 567fe6060f1SDimitry Andric // Finally, move the recipes starting at SplitAt to new block. 568fe6060f1SDimitry Andric for (VPRecipeBase &ToMove : 569fe6060f1SDimitry Andric make_early_inc_range(make_range(SplitAt, this->end()))) 570fe6060f1SDimitry Andric ToMove.moveBefore(*SplitBlock, SplitBlock->end()); 571fe6060f1SDimitry Andric 572fe6060f1SDimitry Andric return SplitBlock; 573fe6060f1SDimitry Andric } 574fe6060f1SDimitry Andric 57581ad6265SDimitry Andric VPRegionBlock *VPBasicBlock::getEnclosingLoopRegion() { 57681ad6265SDimitry Andric VPRegionBlock *P = getParent(); 57781ad6265SDimitry Andric if (P && P->isReplicator()) { 57881ad6265SDimitry Andric P = P->getParent(); 57981ad6265SDimitry Andric assert(!cast<VPRegionBlock>(P)->isReplicator() && 58081ad6265SDimitry Andric "unexpected nested replicate regions"); 58181ad6265SDimitry Andric } 58281ad6265SDimitry Andric return P; 58381ad6265SDimitry Andric } 58481ad6265SDimitry Andric 58581ad6265SDimitry Andric static bool hasConditionalTerminator(const VPBasicBlock *VPBB) { 58681ad6265SDimitry Andric if (VPBB->empty()) { 58781ad6265SDimitry Andric assert( 58881ad6265SDimitry Andric VPBB->getNumSuccessors() < 2 && 58981ad6265SDimitry Andric "block with multiple successors doesn't have a recipe as terminator"); 59081ad6265SDimitry Andric return false; 59181ad6265SDimitry Andric } 59281ad6265SDimitry Andric 59381ad6265SDimitry Andric const VPRecipeBase *R = &VPBB->back(); 594*0fca6ea1SDimitry Andric bool IsCondBranch = isa<VPBranchOnMaskRecipe>(R) || 595*0fca6ea1SDimitry Andric match(R, m_BranchOnCond(m_VPValue())) || 596*0fca6ea1SDimitry Andric match(R, m_BranchOnCount(m_VPValue(), m_VPValue())); 59781ad6265SDimitry Andric (void)IsCondBranch; 59881ad6265SDimitry Andric 599*0fca6ea1SDimitry Andric if (VPBB->getNumSuccessors() >= 2 || 600*0fca6ea1SDimitry Andric (VPBB->isExiting() && !VPBB->getParent()->isReplicator())) { 60181ad6265SDimitry Andric assert(IsCondBranch && "block with multiple successors not terminated by " 60281ad6265SDimitry Andric "conditional branch recipe"); 60381ad6265SDimitry Andric 60481ad6265SDimitry Andric return true; 60581ad6265SDimitry Andric } 60681ad6265SDimitry Andric 60781ad6265SDimitry Andric assert( 60881ad6265SDimitry Andric !IsCondBranch && 60981ad6265SDimitry Andric "block with 0 or 1 successors terminated by conditional branch recipe"); 61081ad6265SDimitry Andric return false; 61181ad6265SDimitry Andric } 61281ad6265SDimitry Andric 61381ad6265SDimitry Andric VPRecipeBase *VPBasicBlock::getTerminator() { 61481ad6265SDimitry Andric if (hasConditionalTerminator(this)) 61581ad6265SDimitry Andric return &back(); 61681ad6265SDimitry Andric return nullptr; 61781ad6265SDimitry Andric } 61881ad6265SDimitry Andric 61981ad6265SDimitry Andric const VPRecipeBase *VPBasicBlock::getTerminator() const { 62081ad6265SDimitry Andric if (hasConditionalTerminator(this)) 62181ad6265SDimitry Andric return &back(); 62281ad6265SDimitry Andric return nullptr; 62381ad6265SDimitry Andric } 62481ad6265SDimitry Andric 62581ad6265SDimitry Andric bool VPBasicBlock::isExiting() const { 626*0fca6ea1SDimitry Andric return getParent() && getParent()->getExitingBasicBlock() == this; 62781ad6265SDimitry Andric } 62881ad6265SDimitry Andric 629fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 630fe6060f1SDimitry Andric void VPBlockBase::printSuccessors(raw_ostream &O, const Twine &Indent) const { 631fe6060f1SDimitry Andric if (getSuccessors().empty()) { 632fe6060f1SDimitry Andric O << Indent << "No successors\n"; 633fe6060f1SDimitry Andric } else { 634fe6060f1SDimitry Andric O << Indent << "Successor(s): "; 635fe6060f1SDimitry Andric ListSeparator LS; 636fe6060f1SDimitry Andric for (auto *Succ : getSuccessors()) 637fe6060f1SDimitry Andric O << LS << Succ->getName(); 638fe6060f1SDimitry Andric O << '\n'; 639fe6060f1SDimitry Andric } 640fe6060f1SDimitry Andric } 641fe6060f1SDimitry Andric 642fe6060f1SDimitry Andric void VPBasicBlock::print(raw_ostream &O, const Twine &Indent, 643fe6060f1SDimitry Andric VPSlotTracker &SlotTracker) const { 644fe6060f1SDimitry Andric O << Indent << getName() << ":\n"; 645fe6060f1SDimitry Andric 646fe6060f1SDimitry Andric auto RecipeIndent = Indent + " "; 647fe6060f1SDimitry Andric for (const VPRecipeBase &Recipe : *this) { 648fe6060f1SDimitry Andric Recipe.print(O, RecipeIndent, SlotTracker); 649fe6060f1SDimitry Andric O << '\n'; 650fe6060f1SDimitry Andric } 651fe6060f1SDimitry Andric 652fe6060f1SDimitry Andric printSuccessors(O, Indent); 653fe6060f1SDimitry Andric } 654fe6060f1SDimitry Andric #endif 655fe6060f1SDimitry Andric 656*0fca6ea1SDimitry Andric static std::pair<VPBlockBase *, VPBlockBase *> cloneFrom(VPBlockBase *Entry); 657*0fca6ea1SDimitry Andric 658*0fca6ea1SDimitry Andric // Clone the CFG for all nodes reachable from \p Entry, this includes cloning 659*0fca6ea1SDimitry Andric // the blocks and their recipes. Operands of cloned recipes will NOT be updated. 660*0fca6ea1SDimitry Andric // Remapping of operands must be done separately. Returns a pair with the new 661*0fca6ea1SDimitry Andric // entry and exiting blocks of the cloned region. If \p Entry isn't part of a 662*0fca6ea1SDimitry Andric // region, return nullptr for the exiting block. 663*0fca6ea1SDimitry Andric static std::pair<VPBlockBase *, VPBlockBase *> cloneFrom(VPBlockBase *Entry) { 664*0fca6ea1SDimitry Andric DenseMap<VPBlockBase *, VPBlockBase *> Old2NewVPBlocks; 665*0fca6ea1SDimitry Andric VPBlockBase *Exiting = nullptr; 666*0fca6ea1SDimitry Andric bool InRegion = Entry->getParent(); 667*0fca6ea1SDimitry Andric // First, clone blocks reachable from Entry. 668*0fca6ea1SDimitry Andric for (VPBlockBase *BB : vp_depth_first_shallow(Entry)) { 669*0fca6ea1SDimitry Andric VPBlockBase *NewBB = BB->clone(); 670*0fca6ea1SDimitry Andric Old2NewVPBlocks[BB] = NewBB; 671*0fca6ea1SDimitry Andric if (InRegion && BB->getNumSuccessors() == 0) { 672*0fca6ea1SDimitry Andric assert(!Exiting && "Multiple exiting blocks?"); 673*0fca6ea1SDimitry Andric Exiting = BB; 674*0fca6ea1SDimitry Andric } 675*0fca6ea1SDimitry Andric } 676*0fca6ea1SDimitry Andric assert((!InRegion || Exiting) && "regions must have a single exiting block"); 677*0fca6ea1SDimitry Andric 678*0fca6ea1SDimitry Andric // Second, update the predecessors & successors of the cloned blocks. 679*0fca6ea1SDimitry Andric for (VPBlockBase *BB : vp_depth_first_shallow(Entry)) { 680*0fca6ea1SDimitry Andric VPBlockBase *NewBB = Old2NewVPBlocks[BB]; 681*0fca6ea1SDimitry Andric SmallVector<VPBlockBase *> NewPreds; 682*0fca6ea1SDimitry Andric for (VPBlockBase *Pred : BB->getPredecessors()) { 683*0fca6ea1SDimitry Andric NewPreds.push_back(Old2NewVPBlocks[Pred]); 684*0fca6ea1SDimitry Andric } 685*0fca6ea1SDimitry Andric NewBB->setPredecessors(NewPreds); 686*0fca6ea1SDimitry Andric SmallVector<VPBlockBase *> NewSuccs; 687*0fca6ea1SDimitry Andric for (VPBlockBase *Succ : BB->successors()) { 688*0fca6ea1SDimitry Andric NewSuccs.push_back(Old2NewVPBlocks[Succ]); 689*0fca6ea1SDimitry Andric } 690*0fca6ea1SDimitry Andric NewBB->setSuccessors(NewSuccs); 691*0fca6ea1SDimitry Andric } 692*0fca6ea1SDimitry Andric 693*0fca6ea1SDimitry Andric #if !defined(NDEBUG) 694*0fca6ea1SDimitry Andric // Verify that the order of predecessors and successors matches in the cloned 695*0fca6ea1SDimitry Andric // version. 696*0fca6ea1SDimitry Andric for (const auto &[OldBB, NewBB] : 697*0fca6ea1SDimitry Andric zip(vp_depth_first_shallow(Entry), 698*0fca6ea1SDimitry Andric vp_depth_first_shallow(Old2NewVPBlocks[Entry]))) { 699*0fca6ea1SDimitry Andric for (const auto &[OldPred, NewPred] : 700*0fca6ea1SDimitry Andric zip(OldBB->getPredecessors(), NewBB->getPredecessors())) 701*0fca6ea1SDimitry Andric assert(NewPred == Old2NewVPBlocks[OldPred] && "Different predecessors"); 702*0fca6ea1SDimitry Andric 703*0fca6ea1SDimitry Andric for (const auto &[OldSucc, NewSucc] : 704*0fca6ea1SDimitry Andric zip(OldBB->successors(), NewBB->successors())) 705*0fca6ea1SDimitry Andric assert(NewSucc == Old2NewVPBlocks[OldSucc] && "Different successors"); 706*0fca6ea1SDimitry Andric } 707*0fca6ea1SDimitry Andric #endif 708*0fca6ea1SDimitry Andric 709*0fca6ea1SDimitry Andric return std::make_pair(Old2NewVPBlocks[Entry], 710*0fca6ea1SDimitry Andric Exiting ? Old2NewVPBlocks[Exiting] : nullptr); 711*0fca6ea1SDimitry Andric } 712*0fca6ea1SDimitry Andric 713*0fca6ea1SDimitry Andric VPRegionBlock *VPRegionBlock::clone() { 714*0fca6ea1SDimitry Andric const auto &[NewEntry, NewExiting] = cloneFrom(getEntry()); 715*0fca6ea1SDimitry Andric auto *NewRegion = 716*0fca6ea1SDimitry Andric new VPRegionBlock(NewEntry, NewExiting, getName(), isReplicator()); 717*0fca6ea1SDimitry Andric for (VPBlockBase *Block : vp_depth_first_shallow(NewEntry)) 718*0fca6ea1SDimitry Andric Block->setParent(NewRegion); 719*0fca6ea1SDimitry Andric return NewRegion; 720*0fca6ea1SDimitry Andric } 721*0fca6ea1SDimitry Andric 722e8d8bef9SDimitry Andric void VPRegionBlock::dropAllReferences(VPValue *NewValue) { 723bdd1243dSDimitry Andric for (VPBlockBase *Block : vp_depth_first_shallow(Entry)) 724e8d8bef9SDimitry Andric // Drop all references in VPBasicBlocks and replace all uses with 725e8d8bef9SDimitry Andric // DummyValue. 726e8d8bef9SDimitry Andric Block->dropAllReferences(NewValue); 727e8d8bef9SDimitry Andric } 728e8d8bef9SDimitry Andric 7290b57cec5SDimitry Andric void VPRegionBlock::execute(VPTransformState *State) { 730bdd1243dSDimitry Andric ReversePostOrderTraversal<VPBlockShallowTraversalWrapper<VPBlockBase *>> 731bdd1243dSDimitry Andric RPOT(Entry); 7320b57cec5SDimitry Andric 7330b57cec5SDimitry Andric if (!isReplicator()) { 73481ad6265SDimitry Andric // Create and register the new vector loop. 73581ad6265SDimitry Andric Loop *PrevLoop = State->CurrentVectorLoop; 73681ad6265SDimitry Andric State->CurrentVectorLoop = State->LI->AllocateLoop(); 73781ad6265SDimitry Andric BasicBlock *VectorPH = State->CFG.VPBB2IRBB[getPreheaderVPBB()]; 73881ad6265SDimitry Andric Loop *ParentLoop = State->LI->getLoopFor(VectorPH); 73981ad6265SDimitry Andric 74081ad6265SDimitry Andric // Insert the new loop into the loop nest and register the new basic blocks 74181ad6265SDimitry Andric // before calling any utilities such as SCEV that require valid LoopInfo. 74281ad6265SDimitry Andric if (ParentLoop) 74381ad6265SDimitry Andric ParentLoop->addChildLoop(State->CurrentVectorLoop); 74481ad6265SDimitry Andric else 74581ad6265SDimitry Andric State->LI->addTopLevelLoop(State->CurrentVectorLoop); 74681ad6265SDimitry Andric 7470b57cec5SDimitry Andric // Visit the VPBlocks connected to "this", starting from it. 7480b57cec5SDimitry Andric for (VPBlockBase *Block : RPOT) { 7490b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "LV: VPBlock in RPO " << Block->getName() << '\n'); 7500b57cec5SDimitry Andric Block->execute(State); 7510b57cec5SDimitry Andric } 75281ad6265SDimitry Andric 75381ad6265SDimitry Andric State->CurrentVectorLoop = PrevLoop; 7540b57cec5SDimitry Andric return; 7550b57cec5SDimitry Andric } 7560b57cec5SDimitry Andric 7570b57cec5SDimitry Andric assert(!State->Instance && "Replicating a Region with non-null instance."); 7580b57cec5SDimitry Andric 7590b57cec5SDimitry Andric // Enter replicating mode. 760fe6060f1SDimitry Andric State->Instance = VPIteration(0, 0); 7610b57cec5SDimitry Andric 7620b57cec5SDimitry Andric for (unsigned Part = 0, UF = State->UF; Part < UF; ++Part) { 7630b57cec5SDimitry Andric State->Instance->Part = Part; 764e8d8bef9SDimitry Andric assert(!State->VF.isScalable() && "VF is assumed to be non scalable."); 765e8d8bef9SDimitry Andric for (unsigned Lane = 0, VF = State->VF.getKnownMinValue(); Lane < VF; 766e8d8bef9SDimitry Andric ++Lane) { 767fe6060f1SDimitry Andric State->Instance->Lane = VPLane(Lane, VPLane::Kind::First); 7680b57cec5SDimitry Andric // Visit the VPBlocks connected to \p this, starting from it. 7690b57cec5SDimitry Andric for (VPBlockBase *Block : RPOT) { 7700b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "LV: VPBlock in RPO " << Block->getName() << '\n'); 7710b57cec5SDimitry Andric Block->execute(State); 7720b57cec5SDimitry Andric } 7730b57cec5SDimitry Andric } 7740b57cec5SDimitry Andric } 7750b57cec5SDimitry Andric 7760b57cec5SDimitry Andric // Exit replicating mode. 7770b57cec5SDimitry Andric State->Instance.reset(); 7780b57cec5SDimitry Andric } 7790b57cec5SDimitry Andric 780*0fca6ea1SDimitry Andric InstructionCost VPBasicBlock::cost(ElementCount VF, VPCostContext &Ctx) { 781*0fca6ea1SDimitry Andric InstructionCost Cost = 0; 782*0fca6ea1SDimitry Andric for (VPRecipeBase &R : Recipes) 783*0fca6ea1SDimitry Andric Cost += R.cost(VF, Ctx); 784*0fca6ea1SDimitry Andric return Cost; 785*0fca6ea1SDimitry Andric } 786*0fca6ea1SDimitry Andric 787*0fca6ea1SDimitry Andric InstructionCost VPRegionBlock::cost(ElementCount VF, VPCostContext &Ctx) { 788*0fca6ea1SDimitry Andric if (!isReplicator()) { 789*0fca6ea1SDimitry Andric InstructionCost Cost = 0; 790*0fca6ea1SDimitry Andric for (VPBlockBase *Block : vp_depth_first_shallow(getEntry())) 791*0fca6ea1SDimitry Andric Cost += Block->cost(VF, Ctx); 792*0fca6ea1SDimitry Andric InstructionCost BackedgeCost = 793*0fca6ea1SDimitry Andric Ctx.TTI.getCFInstrCost(Instruction::Br, TTI::TCK_RecipThroughput); 794*0fca6ea1SDimitry Andric LLVM_DEBUG(dbgs() << "Cost of " << BackedgeCost << " for VF " << VF 795*0fca6ea1SDimitry Andric << ": vector loop backedge\n"); 796*0fca6ea1SDimitry Andric Cost += BackedgeCost; 797*0fca6ea1SDimitry Andric return Cost; 798*0fca6ea1SDimitry Andric } 799*0fca6ea1SDimitry Andric 800*0fca6ea1SDimitry Andric // Compute the cost of a replicate region. Replicating isn't supported for 801*0fca6ea1SDimitry Andric // scalable vectors, return an invalid cost for them. 802*0fca6ea1SDimitry Andric // TODO: Discard scalable VPlans with replicate recipes earlier after 803*0fca6ea1SDimitry Andric // construction. 804*0fca6ea1SDimitry Andric if (VF.isScalable()) 805*0fca6ea1SDimitry Andric return InstructionCost::getInvalid(); 806*0fca6ea1SDimitry Andric 807*0fca6ea1SDimitry Andric // First compute the cost of the conditionally executed recipes, followed by 808*0fca6ea1SDimitry Andric // account for the branching cost, except if the mask is a header mask or 809*0fca6ea1SDimitry Andric // uniform condition. 810*0fca6ea1SDimitry Andric using namespace llvm::VPlanPatternMatch; 811*0fca6ea1SDimitry Andric VPBasicBlock *Then = cast<VPBasicBlock>(getEntry()->getSuccessors()[0]); 812*0fca6ea1SDimitry Andric InstructionCost ThenCost = Then->cost(VF, Ctx); 813*0fca6ea1SDimitry Andric 814*0fca6ea1SDimitry Andric // For the scalar case, we may not always execute the original predicated 815*0fca6ea1SDimitry Andric // block, Thus, scale the block's cost by the probability of executing it. 816*0fca6ea1SDimitry Andric if (VF.isScalar()) 817*0fca6ea1SDimitry Andric return ThenCost / getReciprocalPredBlockProb(); 818*0fca6ea1SDimitry Andric 819*0fca6ea1SDimitry Andric return ThenCost; 820*0fca6ea1SDimitry Andric } 821*0fca6ea1SDimitry Andric 822fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 823fe6060f1SDimitry Andric void VPRegionBlock::print(raw_ostream &O, const Twine &Indent, 824fe6060f1SDimitry Andric VPSlotTracker &SlotTracker) const { 825fe6060f1SDimitry Andric O << Indent << (isReplicator() ? "<xVFxUF> " : "<x1> ") << getName() << ": {"; 826fe6060f1SDimitry Andric auto NewIndent = Indent + " "; 827bdd1243dSDimitry Andric for (auto *BlockBase : vp_depth_first_shallow(Entry)) { 828fe6060f1SDimitry Andric O << '\n'; 829fe6060f1SDimitry Andric BlockBase->print(O, NewIndent, SlotTracker); 830fe6060f1SDimitry Andric } 831fe6060f1SDimitry Andric O << Indent << "}\n"; 832fe6060f1SDimitry Andric 833fe6060f1SDimitry Andric printSuccessors(O, Indent); 834fe6060f1SDimitry Andric } 835fe6060f1SDimitry Andric #endif 836fe6060f1SDimitry Andric 837bdd1243dSDimitry Andric VPlan::~VPlan() { 83806c3fb27SDimitry Andric for (auto &KV : LiveOuts) 83906c3fb27SDimitry Andric delete KV.second; 84006c3fb27SDimitry Andric LiveOuts.clear(); 841bdd1243dSDimitry Andric 842bdd1243dSDimitry Andric if (Entry) { 843bdd1243dSDimitry Andric VPValue DummyValue; 844bdd1243dSDimitry Andric for (VPBlockBase *Block : vp_depth_first_shallow(Entry)) 845bdd1243dSDimitry Andric Block->dropAllReferences(&DummyValue); 846bdd1243dSDimitry Andric 847bdd1243dSDimitry Andric VPBlockBase::deleteCFG(Entry); 84806c3fb27SDimitry Andric 84906c3fb27SDimitry Andric Preheader->dropAllReferences(&DummyValue); 85006c3fb27SDimitry Andric delete Preheader; 851bdd1243dSDimitry Andric } 85206c3fb27SDimitry Andric for (VPValue *VPV : VPLiveInsToFree) 853bdd1243dSDimitry Andric delete VPV; 854bdd1243dSDimitry Andric if (BackedgeTakenCount) 855bdd1243dSDimitry Andric delete BackedgeTakenCount; 85606c3fb27SDimitry Andric } 85706c3fb27SDimitry Andric 858*0fca6ea1SDimitry Andric VPlanPtr VPlan::createInitialVPlan(const SCEV *TripCount, ScalarEvolution &SE, 859*0fca6ea1SDimitry Andric bool RequiresScalarEpilogueCheck, 860*0fca6ea1SDimitry Andric bool TailFolded, Loop *TheLoop) { 861*0fca6ea1SDimitry Andric VPIRBasicBlock *Entry = new VPIRBasicBlock(TheLoop->getLoopPreheader()); 86206c3fb27SDimitry Andric VPBasicBlock *VecPreheader = new VPBasicBlock("vector.ph"); 863*0fca6ea1SDimitry Andric auto Plan = std::make_unique<VPlan>(Entry, VecPreheader); 86406c3fb27SDimitry Andric Plan->TripCount = 86506c3fb27SDimitry Andric vputils::getOrCreateVPValueForSCEVExpr(*Plan, TripCount, SE); 866*0fca6ea1SDimitry Andric // Create VPRegionBlock, with empty header and latch blocks, to be filled 867*0fca6ea1SDimitry Andric // during processing later. 868*0fca6ea1SDimitry Andric VPBasicBlock *HeaderVPBB = new VPBasicBlock("vector.body"); 869*0fca6ea1SDimitry Andric VPBasicBlock *LatchVPBB = new VPBasicBlock("vector.latch"); 870*0fca6ea1SDimitry Andric VPBlockUtils::insertBlockAfter(LatchVPBB, HeaderVPBB); 871*0fca6ea1SDimitry Andric auto *TopRegion = new VPRegionBlock(HeaderVPBB, LatchVPBB, "vector loop", 872*0fca6ea1SDimitry Andric false /*isReplicator*/); 873*0fca6ea1SDimitry Andric 8745f757f3fSDimitry Andric VPBlockUtils::insertBlockAfter(TopRegion, VecPreheader); 8755f757f3fSDimitry Andric VPBasicBlock *MiddleVPBB = new VPBasicBlock("middle.block"); 8765f757f3fSDimitry Andric VPBlockUtils::insertBlockAfter(MiddleVPBB, TopRegion); 877*0fca6ea1SDimitry Andric 878*0fca6ea1SDimitry Andric VPBasicBlock *ScalarPH = new VPBasicBlock("scalar.ph"); 879*0fca6ea1SDimitry Andric if (!RequiresScalarEpilogueCheck) { 880*0fca6ea1SDimitry Andric VPBlockUtils::connectBlocks(MiddleVPBB, ScalarPH); 881*0fca6ea1SDimitry Andric return Plan; 882*0fca6ea1SDimitry Andric } 883*0fca6ea1SDimitry Andric 884*0fca6ea1SDimitry Andric // If needed, add a check in the middle block to see if we have completed 885*0fca6ea1SDimitry Andric // all of the iterations in the first vector loop. Three cases: 886*0fca6ea1SDimitry Andric // 1) If (N - N%VF) == N, then we *don't* need to run the remainder. 887*0fca6ea1SDimitry Andric // Thus if tail is to be folded, we know we don't need to run the 888*0fca6ea1SDimitry Andric // remainder and we can set the condition to true. 889*0fca6ea1SDimitry Andric // 2) If we require a scalar epilogue, there is no conditional branch as 890*0fca6ea1SDimitry Andric // we unconditionally branch to the scalar preheader. Do nothing. 891*0fca6ea1SDimitry Andric // 3) Otherwise, construct a runtime check. 892*0fca6ea1SDimitry Andric BasicBlock *IRExitBlock = TheLoop->getUniqueExitBlock(); 893*0fca6ea1SDimitry Andric auto *VPExitBlock = new VPIRBasicBlock(IRExitBlock); 894*0fca6ea1SDimitry Andric // The connection order corresponds to the operands of the conditional branch. 895*0fca6ea1SDimitry Andric VPBlockUtils::insertBlockAfter(VPExitBlock, MiddleVPBB); 896*0fca6ea1SDimitry Andric VPBlockUtils::connectBlocks(MiddleVPBB, ScalarPH); 897*0fca6ea1SDimitry Andric 898*0fca6ea1SDimitry Andric auto *ScalarLatchTerm = TheLoop->getLoopLatch()->getTerminator(); 899*0fca6ea1SDimitry Andric // Here we use the same DebugLoc as the scalar loop latch terminator instead 900*0fca6ea1SDimitry Andric // of the corresponding compare because they may have ended up with 901*0fca6ea1SDimitry Andric // different line numbers and we want to avoid awkward line stepping while 902*0fca6ea1SDimitry Andric // debugging. Eg. if the compare has got a line number inside the loop. 903*0fca6ea1SDimitry Andric VPBuilder Builder(MiddleVPBB); 904*0fca6ea1SDimitry Andric VPValue *Cmp = 905*0fca6ea1SDimitry Andric TailFolded 906*0fca6ea1SDimitry Andric ? Plan->getOrAddLiveIn(ConstantInt::getTrue( 907*0fca6ea1SDimitry Andric IntegerType::getInt1Ty(TripCount->getType()->getContext()))) 908*0fca6ea1SDimitry Andric : Builder.createICmp(CmpInst::ICMP_EQ, Plan->getTripCount(), 909*0fca6ea1SDimitry Andric &Plan->getVectorTripCount(), 910*0fca6ea1SDimitry Andric ScalarLatchTerm->getDebugLoc(), "cmp.n"); 911*0fca6ea1SDimitry Andric Builder.createNaryOp(VPInstruction::BranchOnCond, {Cmp}, 912*0fca6ea1SDimitry Andric ScalarLatchTerm->getDebugLoc()); 91306c3fb27SDimitry Andric return Plan; 914bdd1243dSDimitry Andric } 915bdd1243dSDimitry Andric 91604eeddc0SDimitry Andric void VPlan::prepareToExecute(Value *TripCountV, Value *VectorTripCountV, 91704eeddc0SDimitry Andric Value *CanonicalIVStartValue, 9185f757f3fSDimitry Andric VPTransformState &State) { 91904eeddc0SDimitry Andric // Check if the backedge taken count is needed, and if so build it. 92004eeddc0SDimitry Andric if (BackedgeTakenCount && BackedgeTakenCount->getNumUsers()) { 92104eeddc0SDimitry Andric IRBuilder<> Builder(State.CFG.PrevBB->getTerminator()); 92204eeddc0SDimitry Andric auto *TCMO = Builder.CreateSub(TripCountV, 92304eeddc0SDimitry Andric ConstantInt::get(TripCountV->getType(), 1), 92404eeddc0SDimitry Andric "trip.count.minus.1"); 925*0fca6ea1SDimitry Andric BackedgeTakenCount->setUnderlyingValue(TCMO); 92604eeddc0SDimitry Andric } 92704eeddc0SDimitry Andric 928*0fca6ea1SDimitry Andric VectorTripCount.setUnderlyingValue(VectorTripCountV); 92904eeddc0SDimitry Andric 9305f757f3fSDimitry Andric IRBuilder<> Builder(State.CFG.PrevBB->getTerminator()); 9315f757f3fSDimitry Andric // FIXME: Model VF * UF computation completely in VPlan. 932*0fca6ea1SDimitry Andric VFxUF.setUnderlyingValue( 933*0fca6ea1SDimitry Andric createStepForVF(Builder, TripCountV->getType(), State.VF, State.UF)); 9345f757f3fSDimitry Andric 93504eeddc0SDimitry Andric // When vectorizing the epilogue loop, the canonical induction start value 93604eeddc0SDimitry Andric // needs to be changed from zero to the value after the main vector loop. 937bdd1243dSDimitry Andric // FIXME: Improve modeling for canonical IV start values in the epilogue loop. 93804eeddc0SDimitry Andric if (CanonicalIVStartValue) { 939*0fca6ea1SDimitry Andric VPValue *VPV = getOrAddLiveIn(CanonicalIVStartValue); 94004eeddc0SDimitry Andric auto *IV = getCanonicalIV(); 94104eeddc0SDimitry Andric assert(all_of(IV->users(), 94204eeddc0SDimitry Andric [](const VPUser *U) { 9435f757f3fSDimitry Andric return isa<VPScalarIVStepsRecipe>(U) || 944*0fca6ea1SDimitry Andric isa<VPScalarCastRecipe>(U) || 9455f757f3fSDimitry Andric isa<VPDerivedIVRecipe>(U) || 9465f757f3fSDimitry Andric cast<VPInstruction>(U)->getOpcode() == 9475f757f3fSDimitry Andric Instruction::Add; 94804eeddc0SDimitry Andric }) && 9495f757f3fSDimitry Andric "the canonical IV should only be used by its increment or " 95006c3fb27SDimitry Andric "ScalarIVSteps when resetting the start value"); 95104eeddc0SDimitry Andric IV->setOperand(0, VPV); 95204eeddc0SDimitry Andric } 95304eeddc0SDimitry Andric } 95404eeddc0SDimitry Andric 955*0fca6ea1SDimitry Andric /// Replace \p VPBB with a VPIRBasicBlock wrapping \p IRBB. All recipes from \p 956*0fca6ea1SDimitry Andric /// VPBB are moved to the newly created VPIRBasicBlock. VPBB must have a single 957*0fca6ea1SDimitry Andric /// predecessor, which is rewired to the new VPIRBasicBlock. All successors of 958*0fca6ea1SDimitry Andric /// VPBB, if any, are rewired to the new VPIRBasicBlock. 959*0fca6ea1SDimitry Andric static void replaceVPBBWithIRVPBB(VPBasicBlock *VPBB, BasicBlock *IRBB) { 960*0fca6ea1SDimitry Andric VPIRBasicBlock *IRMiddleVPBB = new VPIRBasicBlock(IRBB); 961*0fca6ea1SDimitry Andric for (auto &R : make_early_inc_range(*VPBB)) 962*0fca6ea1SDimitry Andric R.moveBefore(*IRMiddleVPBB, IRMiddleVPBB->end()); 963*0fca6ea1SDimitry Andric VPBlockBase *PredVPBB = VPBB->getSinglePredecessor(); 964*0fca6ea1SDimitry Andric VPBlockUtils::disconnectBlocks(PredVPBB, VPBB); 965*0fca6ea1SDimitry Andric VPBlockUtils::connectBlocks(PredVPBB, IRMiddleVPBB); 966*0fca6ea1SDimitry Andric for (auto *Succ : to_vector(VPBB->getSuccessors())) { 967*0fca6ea1SDimitry Andric VPBlockUtils::connectBlocks(IRMiddleVPBB, Succ); 968*0fca6ea1SDimitry Andric VPBlockUtils::disconnectBlocks(VPBB, Succ); 969*0fca6ea1SDimitry Andric } 970*0fca6ea1SDimitry Andric delete VPBB; 971*0fca6ea1SDimitry Andric } 972*0fca6ea1SDimitry Andric 97381ad6265SDimitry Andric /// Generate the code inside the preheader and body of the vectorized loop. 97481ad6265SDimitry Andric /// Assumes a single pre-header basic-block was created for this. Introduce 97581ad6265SDimitry Andric /// additional basic-blocks as needed, and fill them all. 9760b57cec5SDimitry Andric void VPlan::execute(VPTransformState *State) { 97781ad6265SDimitry Andric // Initialize CFG state. 9780b57cec5SDimitry Andric State->CFG.PrevVPBB = nullptr; 97981ad6265SDimitry Andric State->CFG.ExitBB = State->CFG.PrevBB->getSingleSuccessor(); 98081ad6265SDimitry Andric BasicBlock *VectorPreHeader = State->CFG.PrevBB; 98181ad6265SDimitry Andric State->Builder.SetInsertPoint(VectorPreHeader->getTerminator()); 9820b57cec5SDimitry Andric 983*0fca6ea1SDimitry Andric // Disconnect VectorPreHeader from ExitBB in both the CFG and DT. 984*0fca6ea1SDimitry Andric cast<BranchInst>(VectorPreHeader->getTerminator())->setSuccessor(0, nullptr); 985*0fca6ea1SDimitry Andric State->CFG.DTU.applyUpdates( 986*0fca6ea1SDimitry Andric {{DominatorTree::Delete, VectorPreHeader, State->CFG.ExitBB}}); 987*0fca6ea1SDimitry Andric 988*0fca6ea1SDimitry Andric // Replace regular VPBB's for the middle and scalar preheader blocks with 989*0fca6ea1SDimitry Andric // VPIRBasicBlocks wrapping their IR blocks. The IR blocks are created during 990*0fca6ea1SDimitry Andric // skeleton creation, so we can only create the VPIRBasicBlocks now during 991*0fca6ea1SDimitry Andric // VPlan execution rather than earlier during VPlan construction. 992*0fca6ea1SDimitry Andric BasicBlock *MiddleBB = State->CFG.ExitBB; 993*0fca6ea1SDimitry Andric VPBasicBlock *MiddleVPBB = 994*0fca6ea1SDimitry Andric cast<VPBasicBlock>(getVectorLoopRegion()->getSingleSuccessor()); 995*0fca6ea1SDimitry Andric // Find the VPBB for the scalar preheader, relying on the current structure 996*0fca6ea1SDimitry Andric // when creating the middle block and its successrs: if there's a single 997*0fca6ea1SDimitry Andric // predecessor, it must be the scalar preheader. Otherwise, the second 998*0fca6ea1SDimitry Andric // successor is the scalar preheader. 999*0fca6ea1SDimitry Andric BasicBlock *ScalarPh = MiddleBB->getSingleSuccessor(); 1000*0fca6ea1SDimitry Andric auto &MiddleSuccs = MiddleVPBB->getSuccessors(); 1001*0fca6ea1SDimitry Andric assert((MiddleSuccs.size() == 1 || MiddleSuccs.size() == 2) && 1002*0fca6ea1SDimitry Andric "middle block has unexpected successors"); 1003*0fca6ea1SDimitry Andric VPBasicBlock *ScalarPhVPBB = cast<VPBasicBlock>( 1004*0fca6ea1SDimitry Andric MiddleSuccs.size() == 1 ? MiddleSuccs[0] : MiddleSuccs[1]); 1005*0fca6ea1SDimitry Andric assert(!isa<VPIRBasicBlock>(ScalarPhVPBB) && 1006*0fca6ea1SDimitry Andric "scalar preheader cannot be wrapped already"); 1007*0fca6ea1SDimitry Andric replaceVPBBWithIRVPBB(ScalarPhVPBB, ScalarPh); 1008*0fca6ea1SDimitry Andric replaceVPBBWithIRVPBB(MiddleVPBB, MiddleBB); 1009*0fca6ea1SDimitry Andric 1010*0fca6ea1SDimitry Andric // Disconnect the middle block from its single successor (the scalar loop 1011*0fca6ea1SDimitry Andric // header) in both the CFG and DT. The branch will be recreated during VPlan 1012*0fca6ea1SDimitry Andric // execution. 1013*0fca6ea1SDimitry Andric auto *BrInst = new UnreachableInst(MiddleBB->getContext()); 1014*0fca6ea1SDimitry Andric BrInst->insertBefore(MiddleBB->getTerminator()); 1015*0fca6ea1SDimitry Andric MiddleBB->getTerminator()->eraseFromParent(); 1016*0fca6ea1SDimitry Andric State->CFG.DTU.applyUpdates({{DominatorTree::Delete, MiddleBB, ScalarPh}}); 1017*0fca6ea1SDimitry Andric 101881ad6265SDimitry Andric // Generate code in the loop pre-header and body. 1019bdd1243dSDimitry Andric for (VPBlockBase *Block : vp_depth_first_shallow(Entry)) 10200b57cec5SDimitry Andric Block->execute(State); 10210b57cec5SDimitry Andric 102281ad6265SDimitry Andric VPBasicBlock *LatchVPBB = getVectorLoopRegion()->getExitingBasicBlock(); 102381ad6265SDimitry Andric BasicBlock *VectorLatchBB = State->CFG.VPBB2IRBB[LatchVPBB]; 10240b57cec5SDimitry Andric 102504eeddc0SDimitry Andric // Fix the latch value of canonical, reduction and first-order recurrences 102604eeddc0SDimitry Andric // phis in the vector loop. 102781ad6265SDimitry Andric VPBasicBlock *Header = getVectorLoopRegion()->getEntryBasicBlock(); 102804eeddc0SDimitry Andric for (VPRecipeBase &R : Header->phis()) { 102904eeddc0SDimitry Andric // Skip phi-like recipes that generate their backedege values themselves. 103081ad6265SDimitry Andric if (isa<VPWidenPHIRecipe>(&R)) 103104eeddc0SDimitry Andric continue; 103204eeddc0SDimitry Andric 103381ad6265SDimitry Andric if (isa<VPWidenPointerInductionRecipe>(&R) || 103481ad6265SDimitry Andric isa<VPWidenIntOrFpInductionRecipe>(&R)) { 103581ad6265SDimitry Andric PHINode *Phi = nullptr; 103681ad6265SDimitry Andric if (isa<VPWidenIntOrFpInductionRecipe>(&R)) { 103781ad6265SDimitry Andric Phi = cast<PHINode>(State->get(R.getVPSingleValue(), 0)); 103881ad6265SDimitry Andric } else { 103981ad6265SDimitry Andric auto *WidenPhi = cast<VPWidenPointerInductionRecipe>(&R); 1040*0fca6ea1SDimitry Andric assert(!WidenPhi->onlyScalarsGenerated(State->VF.isScalable()) && 1041*0fca6ea1SDimitry Andric "recipe generating only scalars should have been replaced"); 104281ad6265SDimitry Andric auto *GEP = cast<GetElementPtrInst>(State->get(WidenPhi, 0)); 104381ad6265SDimitry Andric Phi = cast<PHINode>(GEP->getPointerOperand()); 104481ad6265SDimitry Andric } 104581ad6265SDimitry Andric 104681ad6265SDimitry Andric Phi->setIncomingBlock(1, VectorLatchBB); 104781ad6265SDimitry Andric 104881ad6265SDimitry Andric // Move the last step to the end of the latch block. This ensures 104981ad6265SDimitry Andric // consistent placement of all induction updates. 105081ad6265SDimitry Andric Instruction *Inc = cast<Instruction>(Phi->getIncomingValue(1)); 105181ad6265SDimitry Andric Inc->moveBefore(VectorLatchBB->getTerminator()->getPrevNode()); 105281ad6265SDimitry Andric continue; 105381ad6265SDimitry Andric } 105481ad6265SDimitry Andric 105504eeddc0SDimitry Andric auto *PhiR = cast<VPHeaderPHIRecipe>(&R); 105604eeddc0SDimitry Andric // For canonical IV, first-order recurrences and in-order reduction phis, 105704eeddc0SDimitry Andric // only a single part is generated, which provides the last part from the 105804eeddc0SDimitry Andric // previous iteration. For non-ordered reductions all UF parts are 105904eeddc0SDimitry Andric // generated. 1060*0fca6ea1SDimitry Andric bool SinglePartNeeded = 1061*0fca6ea1SDimitry Andric isa<VPCanonicalIVPHIRecipe>(PhiR) || 1062*0fca6ea1SDimitry Andric isa<VPFirstOrderRecurrencePHIRecipe, VPEVLBasedIVPHIRecipe>(PhiR) || 1063753f127fSDimitry Andric (isa<VPReductionPHIRecipe>(PhiR) && 1064753f127fSDimitry Andric cast<VPReductionPHIRecipe>(PhiR)->isOrdered()); 1065*0fca6ea1SDimitry Andric bool NeedsScalar = 1066*0fca6ea1SDimitry Andric isa<VPCanonicalIVPHIRecipe, VPEVLBasedIVPHIRecipe>(PhiR) || 1067*0fca6ea1SDimitry Andric (isa<VPReductionPHIRecipe>(PhiR) && 1068*0fca6ea1SDimitry Andric cast<VPReductionPHIRecipe>(PhiR)->isInLoop()); 106904eeddc0SDimitry Andric unsigned LastPartForNewPhi = SinglePartNeeded ? 1 : State->UF; 107004eeddc0SDimitry Andric 107104eeddc0SDimitry Andric for (unsigned Part = 0; Part < LastPartForNewPhi; ++Part) { 1072*0fca6ea1SDimitry Andric Value *Phi = State->get(PhiR, Part, NeedsScalar); 1073*0fca6ea1SDimitry Andric Value *Val = 1074*0fca6ea1SDimitry Andric State->get(PhiR->getBackedgeValue(), 1075*0fca6ea1SDimitry Andric SinglePartNeeded ? State->UF - 1 : Part, NeedsScalar); 107604eeddc0SDimitry Andric cast<PHINode>(Phi)->addIncoming(Val, VectorLatchBB); 107704eeddc0SDimitry Andric } 107804eeddc0SDimitry Andric } 107904eeddc0SDimitry Andric 1080*0fca6ea1SDimitry Andric State->CFG.DTU.flush(); 1081*0fca6ea1SDimitry Andric assert(State->CFG.DTU.getDomTree().verify( 1082*0fca6ea1SDimitry Andric DominatorTree::VerificationLevel::Fast) && 1083*0fca6ea1SDimitry Andric "DT not preserved correctly"); 108481ad6265SDimitry Andric } 1085*0fca6ea1SDimitry Andric 1086*0fca6ea1SDimitry Andric InstructionCost VPlan::cost(ElementCount VF, VPCostContext &Ctx) { 1087*0fca6ea1SDimitry Andric // For now only return the cost of the vector loop region, ignoring any other 1088*0fca6ea1SDimitry Andric // blocks, like the preheader or middle blocks. 1089*0fca6ea1SDimitry Andric return getVectorLoopRegion()->cost(VF, Ctx); 10900b57cec5SDimitry Andric } 10910b57cec5SDimitry Andric 1092480093f4SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 10935f757f3fSDimitry Andric void VPlan::printLiveIns(raw_ostream &O) const { 1094fe6060f1SDimitry Andric VPSlotTracker SlotTracker(this); 1095fe6060f1SDimitry Andric 10965f757f3fSDimitry Andric if (VFxUF.getNumUsers() > 0) { 10975f757f3fSDimitry Andric O << "\nLive-in "; 10985f757f3fSDimitry Andric VFxUF.printAsOperand(O, SlotTracker); 10995f757f3fSDimitry Andric O << " = VF * UF"; 11005f757f3fSDimitry Andric } 1101349cc55cSDimitry Andric 110204eeddc0SDimitry Andric if (VectorTripCount.getNumUsers() > 0) { 110304eeddc0SDimitry Andric O << "\nLive-in "; 110404eeddc0SDimitry Andric VectorTripCount.printAsOperand(O, SlotTracker); 110506c3fb27SDimitry Andric O << " = vector-trip-count"; 110604eeddc0SDimitry Andric } 110704eeddc0SDimitry Andric 1108349cc55cSDimitry Andric if (BackedgeTakenCount && BackedgeTakenCount->getNumUsers()) { 1109349cc55cSDimitry Andric O << "\nLive-in "; 1110349cc55cSDimitry Andric BackedgeTakenCount->printAsOperand(O, SlotTracker); 111106c3fb27SDimitry Andric O << " = backedge-taken count"; 111206c3fb27SDimitry Andric } 111306c3fb27SDimitry Andric 111406c3fb27SDimitry Andric O << "\n"; 111506c3fb27SDimitry Andric if (TripCount->isLiveIn()) 111606c3fb27SDimitry Andric O << "Live-in "; 111706c3fb27SDimitry Andric TripCount->printAsOperand(O, SlotTracker); 111806c3fb27SDimitry Andric O << " = original trip-count"; 111906c3fb27SDimitry Andric O << "\n"; 11205f757f3fSDimitry Andric } 11215f757f3fSDimitry Andric 11225f757f3fSDimitry Andric LLVM_DUMP_METHOD 11235f757f3fSDimitry Andric void VPlan::print(raw_ostream &O) const { 11245f757f3fSDimitry Andric VPSlotTracker SlotTracker(this); 11255f757f3fSDimitry Andric 11265f757f3fSDimitry Andric O << "VPlan '" << getName() << "' {"; 11275f757f3fSDimitry Andric 11285f757f3fSDimitry Andric printLiveIns(O); 112906c3fb27SDimitry Andric 113006c3fb27SDimitry Andric if (!getPreheader()->empty()) { 113106c3fb27SDimitry Andric O << "\n"; 113206c3fb27SDimitry Andric getPreheader()->print(O, "", SlotTracker); 1133349cc55cSDimitry Andric } 1134349cc55cSDimitry Andric 1135bdd1243dSDimitry Andric for (const VPBlockBase *Block : vp_depth_first_shallow(getEntry())) { 1136fe6060f1SDimitry Andric O << '\n'; 1137fe6060f1SDimitry Andric Block->print(O, "", SlotTracker); 1138fe6060f1SDimitry Andric } 113981ad6265SDimitry Andric 114081ad6265SDimitry Andric if (!LiveOuts.empty()) 114181ad6265SDimitry Andric O << "\n"; 1142bdd1243dSDimitry Andric for (const auto &KV : LiveOuts) { 114306c3fb27SDimitry Andric KV.second->print(O, SlotTracker); 114481ad6265SDimitry Andric } 114581ad6265SDimitry Andric 1146fe6060f1SDimitry Andric O << "}\n"; 1147fe6060f1SDimitry Andric } 1148fe6060f1SDimitry Andric 1149bdd1243dSDimitry Andric std::string VPlan::getName() const { 1150bdd1243dSDimitry Andric std::string Out; 1151bdd1243dSDimitry Andric raw_string_ostream RSO(Out); 1152bdd1243dSDimitry Andric RSO << Name << " for "; 1153bdd1243dSDimitry Andric if (!VFs.empty()) { 1154bdd1243dSDimitry Andric RSO << "VF={" << VFs[0]; 1155bdd1243dSDimitry Andric for (ElementCount VF : drop_begin(VFs)) 1156bdd1243dSDimitry Andric RSO << "," << VF; 1157bdd1243dSDimitry Andric RSO << "},"; 1158bdd1243dSDimitry Andric } 1159bdd1243dSDimitry Andric 1160bdd1243dSDimitry Andric if (UFs.empty()) { 1161bdd1243dSDimitry Andric RSO << "UF>=1"; 1162bdd1243dSDimitry Andric } else { 1163bdd1243dSDimitry Andric RSO << "UF={" << UFs[0]; 1164bdd1243dSDimitry Andric for (unsigned UF : drop_begin(UFs)) 1165bdd1243dSDimitry Andric RSO << "," << UF; 1166bdd1243dSDimitry Andric RSO << "}"; 1167bdd1243dSDimitry Andric } 1168bdd1243dSDimitry Andric 1169bdd1243dSDimitry Andric return Out; 1170bdd1243dSDimitry Andric } 1171bdd1243dSDimitry Andric 1172fe6060f1SDimitry Andric LLVM_DUMP_METHOD 1173fe6060f1SDimitry Andric void VPlan::printDOT(raw_ostream &O) const { 1174fe6060f1SDimitry Andric VPlanPrinter Printer(O, *this); 1175fe6060f1SDimitry Andric Printer.dump(); 1176fe6060f1SDimitry Andric } 1177fe6060f1SDimitry Andric 1178fe6060f1SDimitry Andric LLVM_DUMP_METHOD 1179fe6060f1SDimitry Andric void VPlan::dump() const { print(dbgs()); } 1180480093f4SDimitry Andric #endif 1181480093f4SDimitry Andric 118281ad6265SDimitry Andric void VPlan::addLiveOut(PHINode *PN, VPValue *V) { 118381ad6265SDimitry Andric assert(LiveOuts.count(PN) == 0 && "an exit value for PN already exists"); 118481ad6265SDimitry Andric LiveOuts.insert({PN, new VPLiveOut(PN, V)}); 118581ad6265SDimitry Andric } 118681ad6265SDimitry Andric 1187*0fca6ea1SDimitry Andric static void remapOperands(VPBlockBase *Entry, VPBlockBase *NewEntry, 1188*0fca6ea1SDimitry Andric DenseMap<VPValue *, VPValue *> &Old2NewVPValues) { 1189*0fca6ea1SDimitry Andric // Update the operands of all cloned recipes starting at NewEntry. This 1190*0fca6ea1SDimitry Andric // traverses all reachable blocks. This is done in two steps, to handle cycles 1191*0fca6ea1SDimitry Andric // in PHI recipes. 1192*0fca6ea1SDimitry Andric ReversePostOrderTraversal<VPBlockDeepTraversalWrapper<VPBlockBase *>> 1193*0fca6ea1SDimitry Andric OldDeepRPOT(Entry); 1194*0fca6ea1SDimitry Andric ReversePostOrderTraversal<VPBlockDeepTraversalWrapper<VPBlockBase *>> 1195*0fca6ea1SDimitry Andric NewDeepRPOT(NewEntry); 1196*0fca6ea1SDimitry Andric // First, collect all mappings from old to new VPValues defined by cloned 1197*0fca6ea1SDimitry Andric // recipes. 1198*0fca6ea1SDimitry Andric for (const auto &[OldBB, NewBB] : 1199*0fca6ea1SDimitry Andric zip(VPBlockUtils::blocksOnly<VPBasicBlock>(OldDeepRPOT), 1200*0fca6ea1SDimitry Andric VPBlockUtils::blocksOnly<VPBasicBlock>(NewDeepRPOT))) { 1201*0fca6ea1SDimitry Andric assert(OldBB->getRecipeList().size() == NewBB->getRecipeList().size() && 1202*0fca6ea1SDimitry Andric "blocks must have the same number of recipes"); 1203*0fca6ea1SDimitry Andric for (const auto &[OldR, NewR] : zip(*OldBB, *NewBB)) { 1204*0fca6ea1SDimitry Andric assert(OldR.getNumOperands() == NewR.getNumOperands() && 1205*0fca6ea1SDimitry Andric "recipes must have the same number of operands"); 1206*0fca6ea1SDimitry Andric assert(OldR.getNumDefinedValues() == NewR.getNumDefinedValues() && 1207*0fca6ea1SDimitry Andric "recipes must define the same number of operands"); 1208*0fca6ea1SDimitry Andric for (const auto &[OldV, NewV] : 1209*0fca6ea1SDimitry Andric zip(OldR.definedValues(), NewR.definedValues())) 1210*0fca6ea1SDimitry Andric Old2NewVPValues[OldV] = NewV; 12110b57cec5SDimitry Andric } 12120b57cec5SDimitry Andric } 1213*0fca6ea1SDimitry Andric 1214*0fca6ea1SDimitry Andric // Update all operands to use cloned VPValues. 1215*0fca6ea1SDimitry Andric for (VPBasicBlock *NewBB : 1216*0fca6ea1SDimitry Andric VPBlockUtils::blocksOnly<VPBasicBlock>(NewDeepRPOT)) { 1217*0fca6ea1SDimitry Andric for (VPRecipeBase &NewR : *NewBB) 1218*0fca6ea1SDimitry Andric for (unsigned I = 0, E = NewR.getNumOperands(); I != E; ++I) { 1219*0fca6ea1SDimitry Andric VPValue *NewOp = Old2NewVPValues.lookup(NewR.getOperand(I)); 1220*0fca6ea1SDimitry Andric NewR.setOperand(I, NewOp); 12210b57cec5SDimitry Andric } 1222*0fca6ea1SDimitry Andric } 1223*0fca6ea1SDimitry Andric } 1224*0fca6ea1SDimitry Andric 1225*0fca6ea1SDimitry Andric VPlan *VPlan::duplicate() { 1226*0fca6ea1SDimitry Andric // Clone blocks. 1227*0fca6ea1SDimitry Andric VPBasicBlock *NewPreheader = Preheader->clone(); 1228*0fca6ea1SDimitry Andric const auto &[NewEntry, __] = cloneFrom(Entry); 1229*0fca6ea1SDimitry Andric 1230*0fca6ea1SDimitry Andric // Create VPlan, clone live-ins and remap operands in the cloned blocks. 1231*0fca6ea1SDimitry Andric auto *NewPlan = new VPlan(NewPreheader, cast<VPBasicBlock>(NewEntry)); 1232*0fca6ea1SDimitry Andric DenseMap<VPValue *, VPValue *> Old2NewVPValues; 1233*0fca6ea1SDimitry Andric for (VPValue *OldLiveIn : VPLiveInsToFree) { 1234*0fca6ea1SDimitry Andric Old2NewVPValues[OldLiveIn] = 1235*0fca6ea1SDimitry Andric NewPlan->getOrAddLiveIn(OldLiveIn->getLiveInIRValue()); 1236*0fca6ea1SDimitry Andric } 1237*0fca6ea1SDimitry Andric Old2NewVPValues[&VectorTripCount] = &NewPlan->VectorTripCount; 1238*0fca6ea1SDimitry Andric Old2NewVPValues[&VFxUF] = &NewPlan->VFxUF; 1239*0fca6ea1SDimitry Andric if (BackedgeTakenCount) { 1240*0fca6ea1SDimitry Andric NewPlan->BackedgeTakenCount = new VPValue(); 1241*0fca6ea1SDimitry Andric Old2NewVPValues[BackedgeTakenCount] = NewPlan->BackedgeTakenCount; 1242*0fca6ea1SDimitry Andric } 1243*0fca6ea1SDimitry Andric assert(TripCount && "trip count must be set"); 1244*0fca6ea1SDimitry Andric if (TripCount->isLiveIn()) 1245*0fca6ea1SDimitry Andric Old2NewVPValues[TripCount] = 1246*0fca6ea1SDimitry Andric NewPlan->getOrAddLiveIn(TripCount->getLiveInIRValue()); 1247*0fca6ea1SDimitry Andric // else NewTripCount will be created and inserted into Old2NewVPValues when 1248*0fca6ea1SDimitry Andric // TripCount is cloned. In any case NewPlan->TripCount is updated below. 1249*0fca6ea1SDimitry Andric 1250*0fca6ea1SDimitry Andric remapOperands(Preheader, NewPreheader, Old2NewVPValues); 1251*0fca6ea1SDimitry Andric remapOperands(Entry, NewEntry, Old2NewVPValues); 1252*0fca6ea1SDimitry Andric 1253*0fca6ea1SDimitry Andric // Clone live-outs. 1254*0fca6ea1SDimitry Andric for (const auto &[_, LO] : LiveOuts) 1255*0fca6ea1SDimitry Andric NewPlan->addLiveOut(LO->getPhi(), Old2NewVPValues[LO->getOperand(0)]); 1256*0fca6ea1SDimitry Andric 1257*0fca6ea1SDimitry Andric // Initialize remaining fields of cloned VPlan. 1258*0fca6ea1SDimitry Andric NewPlan->VFs = VFs; 1259*0fca6ea1SDimitry Andric NewPlan->UFs = UFs; 1260*0fca6ea1SDimitry Andric // TODO: Adjust names. 1261*0fca6ea1SDimitry Andric NewPlan->Name = Name; 1262*0fca6ea1SDimitry Andric assert(Old2NewVPValues.contains(TripCount) && 1263*0fca6ea1SDimitry Andric "TripCount must have been added to Old2NewVPValues"); 1264*0fca6ea1SDimitry Andric NewPlan->TripCount = Old2NewVPValues[TripCount]; 1265*0fca6ea1SDimitry Andric return NewPlan; 12660b57cec5SDimitry Andric } 12670b57cec5SDimitry Andric 1268fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 126981ad6265SDimitry Andric 1270349cc55cSDimitry Andric Twine VPlanPrinter::getUID(const VPBlockBase *Block) { 12710b57cec5SDimitry Andric return (isa<VPRegionBlock>(Block) ? "cluster_N" : "N") + 12720b57cec5SDimitry Andric Twine(getOrCreateBID(Block)); 12730b57cec5SDimitry Andric } 12740b57cec5SDimitry Andric 1275349cc55cSDimitry Andric Twine VPlanPrinter::getOrCreateName(const VPBlockBase *Block) { 12760b57cec5SDimitry Andric const std::string &Name = Block->getName(); 12770b57cec5SDimitry Andric if (!Name.empty()) 12780b57cec5SDimitry Andric return Name; 12790b57cec5SDimitry Andric return "VPB" + Twine(getOrCreateBID(Block)); 12800b57cec5SDimitry Andric } 12810b57cec5SDimitry Andric 12820b57cec5SDimitry Andric void VPlanPrinter::dump() { 12830b57cec5SDimitry Andric Depth = 1; 12840b57cec5SDimitry Andric bumpIndent(0); 12850b57cec5SDimitry Andric OS << "digraph VPlan {\n"; 12860b57cec5SDimitry Andric OS << "graph [labelloc=t, fontsize=30; label=\"Vectorization Plan"; 12870b57cec5SDimitry Andric if (!Plan.getName().empty()) 12880b57cec5SDimitry Andric OS << "\\n" << DOT::EscapeString(Plan.getName()); 12895f757f3fSDimitry Andric 12905f757f3fSDimitry Andric { 12915f757f3fSDimitry Andric // Print live-ins. 12925f757f3fSDimitry Andric std::string Str; 12935f757f3fSDimitry Andric raw_string_ostream SS(Str); 12945f757f3fSDimitry Andric Plan.printLiveIns(SS); 12955f757f3fSDimitry Andric SmallVector<StringRef, 0> Lines; 12965f757f3fSDimitry Andric StringRef(Str).rtrim('\n').split(Lines, "\n"); 12975f757f3fSDimitry Andric for (auto Line : Lines) 12985f757f3fSDimitry Andric OS << DOT::EscapeString(Line.str()) << "\\n"; 12990b57cec5SDimitry Andric } 13005f757f3fSDimitry Andric 13010b57cec5SDimitry Andric OS << "\"]\n"; 13020b57cec5SDimitry Andric OS << "node [shape=rect, fontname=Courier, fontsize=30]\n"; 13030b57cec5SDimitry Andric OS << "edge [fontname=Courier, fontsize=30]\n"; 13040b57cec5SDimitry Andric OS << "compound=true\n"; 13050b57cec5SDimitry Andric 130606c3fb27SDimitry Andric dumpBlock(Plan.getPreheader()); 130706c3fb27SDimitry Andric 1308bdd1243dSDimitry Andric for (const VPBlockBase *Block : vp_depth_first_shallow(Plan.getEntry())) 13090b57cec5SDimitry Andric dumpBlock(Block); 13100b57cec5SDimitry Andric 13110b57cec5SDimitry Andric OS << "}\n"; 13120b57cec5SDimitry Andric } 13130b57cec5SDimitry Andric 13140b57cec5SDimitry Andric void VPlanPrinter::dumpBlock(const VPBlockBase *Block) { 13150b57cec5SDimitry Andric if (const VPBasicBlock *BasicBlock = dyn_cast<VPBasicBlock>(Block)) 13160b57cec5SDimitry Andric dumpBasicBlock(BasicBlock); 13170b57cec5SDimitry Andric else if (const VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block)) 13180b57cec5SDimitry Andric dumpRegion(Region); 13190b57cec5SDimitry Andric else 13200b57cec5SDimitry Andric llvm_unreachable("Unsupported kind of VPBlock."); 13210b57cec5SDimitry Andric } 13220b57cec5SDimitry Andric 13230b57cec5SDimitry Andric void VPlanPrinter::drawEdge(const VPBlockBase *From, const VPBlockBase *To, 13240b57cec5SDimitry Andric bool Hidden, const Twine &Label) { 13250b57cec5SDimitry Andric // Due to "dot" we print an edge between two regions as an edge between the 132681ad6265SDimitry Andric // exiting basic block and the entry basic of the respective regions. 132781ad6265SDimitry Andric const VPBlockBase *Tail = From->getExitingBasicBlock(); 13280b57cec5SDimitry Andric const VPBlockBase *Head = To->getEntryBasicBlock(); 13290b57cec5SDimitry Andric OS << Indent << getUID(Tail) << " -> " << getUID(Head); 13300b57cec5SDimitry Andric OS << " [ label=\"" << Label << '\"'; 13310b57cec5SDimitry Andric if (Tail != From) 13320b57cec5SDimitry Andric OS << " ltail=" << getUID(From); 13330b57cec5SDimitry Andric if (Head != To) 13340b57cec5SDimitry Andric OS << " lhead=" << getUID(To); 13350b57cec5SDimitry Andric if (Hidden) 13360b57cec5SDimitry Andric OS << "; splines=none"; 13370b57cec5SDimitry Andric OS << "]\n"; 13380b57cec5SDimitry Andric } 13390b57cec5SDimitry Andric 13400b57cec5SDimitry Andric void VPlanPrinter::dumpEdges(const VPBlockBase *Block) { 13410b57cec5SDimitry Andric auto &Successors = Block->getSuccessors(); 13420b57cec5SDimitry Andric if (Successors.size() == 1) 13430b57cec5SDimitry Andric drawEdge(Block, Successors.front(), false, ""); 13440b57cec5SDimitry Andric else if (Successors.size() == 2) { 13450b57cec5SDimitry Andric drawEdge(Block, Successors.front(), false, "T"); 13460b57cec5SDimitry Andric drawEdge(Block, Successors.back(), false, "F"); 13470b57cec5SDimitry Andric } else { 13480b57cec5SDimitry Andric unsigned SuccessorNumber = 0; 13490b57cec5SDimitry Andric for (auto *Successor : Successors) 13500b57cec5SDimitry Andric drawEdge(Block, Successor, false, Twine(SuccessorNumber++)); 13510b57cec5SDimitry Andric } 13520b57cec5SDimitry Andric } 13530b57cec5SDimitry Andric 13540b57cec5SDimitry Andric void VPlanPrinter::dumpBasicBlock(const VPBasicBlock *BasicBlock) { 1355fe6060f1SDimitry Andric // Implement dot-formatted dump by performing plain-text dump into the 1356fe6060f1SDimitry Andric // temporary storage followed by some post-processing. 13570b57cec5SDimitry Andric OS << Indent << getUID(BasicBlock) << " [label =\n"; 13580b57cec5SDimitry Andric bumpIndent(1); 1359fe6060f1SDimitry Andric std::string Str; 1360fe6060f1SDimitry Andric raw_string_ostream SS(Str); 1361fe6060f1SDimitry Andric // Use no indentation as we need to wrap the lines into quotes ourselves. 1362fe6060f1SDimitry Andric BasicBlock->print(SS, "", SlotTracker); 13630b57cec5SDimitry Andric 1364fe6060f1SDimitry Andric // We need to process each line of the output separately, so split 1365fe6060f1SDimitry Andric // single-string plain-text dump. 1366fe6060f1SDimitry Andric SmallVector<StringRef, 0> Lines; 1367fe6060f1SDimitry Andric StringRef(Str).rtrim('\n').split(Lines, "\n"); 13680b57cec5SDimitry Andric 1369fe6060f1SDimitry Andric auto EmitLine = [&](StringRef Line, StringRef Suffix) { 1370fe6060f1SDimitry Andric OS << Indent << '"' << DOT::EscapeString(Line.str()) << "\\l\"" << Suffix; 1371fe6060f1SDimitry Andric }; 13720b57cec5SDimitry Andric 1373fe6060f1SDimitry Andric // Don't need the "+" after the last line. 1374fe6060f1SDimitry Andric for (auto Line : make_range(Lines.begin(), Lines.end() - 1)) 1375fe6060f1SDimitry Andric EmitLine(Line, " +\n"); 1376fe6060f1SDimitry Andric EmitLine(Lines.back(), "\n"); 13770b57cec5SDimitry Andric 1378fe6060f1SDimitry Andric bumpIndent(-1); 1379fe6060f1SDimitry Andric OS << Indent << "]\n"; 1380fe6060f1SDimitry Andric 13810b57cec5SDimitry Andric dumpEdges(BasicBlock); 13820b57cec5SDimitry Andric } 13830b57cec5SDimitry Andric 13840b57cec5SDimitry Andric void VPlanPrinter::dumpRegion(const VPRegionBlock *Region) { 13850b57cec5SDimitry Andric OS << Indent << "subgraph " << getUID(Region) << " {\n"; 13860b57cec5SDimitry Andric bumpIndent(1); 13870b57cec5SDimitry Andric OS << Indent << "fontname=Courier\n" 13880b57cec5SDimitry Andric << Indent << "label=\"" 13890b57cec5SDimitry Andric << DOT::EscapeString(Region->isReplicator() ? "<xVFxUF> " : "<x1> ") 13900b57cec5SDimitry Andric << DOT::EscapeString(Region->getName()) << "\"\n"; 13910b57cec5SDimitry Andric // Dump the blocks of the region. 13920b57cec5SDimitry Andric assert(Region->getEntry() && "Region contains no inner blocks."); 1393bdd1243dSDimitry Andric for (const VPBlockBase *Block : vp_depth_first_shallow(Region->getEntry())) 13940b57cec5SDimitry Andric dumpBlock(Block); 13950b57cec5SDimitry Andric bumpIndent(-1); 13960b57cec5SDimitry Andric OS << Indent << "}\n"; 13970b57cec5SDimitry Andric dumpEdges(Region); 13980b57cec5SDimitry Andric } 13990b57cec5SDimitry Andric 1400fe6060f1SDimitry Andric void VPlanIngredient::print(raw_ostream &O) const { 14010b57cec5SDimitry Andric if (auto *Inst = dyn_cast<Instruction>(V)) { 14020b57cec5SDimitry Andric if (!Inst->getType()->isVoidTy()) { 1403fe6060f1SDimitry Andric Inst->printAsOperand(O, false); 1404fe6060f1SDimitry Andric O << " = "; 14050b57cec5SDimitry Andric } 1406fe6060f1SDimitry Andric O << Inst->getOpcodeName() << " "; 14070b57cec5SDimitry Andric unsigned E = Inst->getNumOperands(); 14080b57cec5SDimitry Andric if (E > 0) { 1409fe6060f1SDimitry Andric Inst->getOperand(0)->printAsOperand(O, false); 14100b57cec5SDimitry Andric for (unsigned I = 1; I < E; ++I) 1411fe6060f1SDimitry Andric Inst->getOperand(I)->printAsOperand(O << ", ", false); 14120b57cec5SDimitry Andric } 14130b57cec5SDimitry Andric } else // !Inst 1414fe6060f1SDimitry Andric V->printAsOperand(O, false); 14150b57cec5SDimitry Andric } 14160b57cec5SDimitry Andric 1417fe6060f1SDimitry Andric #endif 14180b57cec5SDimitry Andric 14190b57cec5SDimitry Andric template void DomTreeBuilder::Calculate<VPDominatorTree>(VPDominatorTree &DT); 14200b57cec5SDimitry Andric 14210b57cec5SDimitry Andric void VPValue::replaceAllUsesWith(VPValue *New) { 14227a6dacacSDimitry Andric replaceUsesWithIf(New, [](VPUser &, unsigned) { return true; }); 14235f757f3fSDimitry Andric } 14245f757f3fSDimitry Andric 14255f757f3fSDimitry Andric void VPValue::replaceUsesWithIf( 14265f757f3fSDimitry Andric VPValue *New, 14275f757f3fSDimitry Andric llvm::function_ref<bool(VPUser &U, unsigned Idx)> ShouldReplace) { 14287a6dacacSDimitry Andric // Note that this early exit is required for correctness; the implementation 14297a6dacacSDimitry Andric // below relies on the number of users for this VPValue to decrease, which 14307a6dacacSDimitry Andric // isn't the case if this == New. 14315f757f3fSDimitry Andric if (this == New) 14325f757f3fSDimitry Andric return; 14337a6dacacSDimitry Andric 14345f757f3fSDimitry Andric for (unsigned J = 0; J < getNumUsers();) { 14355f757f3fSDimitry Andric VPUser *User = Users[J]; 14365f757f3fSDimitry Andric bool RemovedUser = false; 14375f757f3fSDimitry Andric for (unsigned I = 0, E = User->getNumOperands(); I < E; ++I) { 14385f757f3fSDimitry Andric if (User->getOperand(I) != this || !ShouldReplace(*User, I)) 14395f757f3fSDimitry Andric continue; 14405f757f3fSDimitry Andric 14415f757f3fSDimitry Andric RemovedUser = true; 14425f757f3fSDimitry Andric User->setOperand(I, New); 14435f757f3fSDimitry Andric } 14445f757f3fSDimitry Andric // If a user got removed after updating the current user, the next user to 14455f757f3fSDimitry Andric // update will be moved to the current position, so we only need to 14465f757f3fSDimitry Andric // increment the index if the number of users did not change. 14475f757f3fSDimitry Andric if (!RemovedUser) 1448e8d8bef9SDimitry Andric J++; 1449e8d8bef9SDimitry Andric } 14500b57cec5SDimitry Andric } 14510b57cec5SDimitry Andric 1452fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 14535ffd83dbSDimitry Andric void VPValue::printAsOperand(raw_ostream &OS, VPSlotTracker &Tracker) const { 1454*0fca6ea1SDimitry Andric OS << Tracker.getOrCreateName(this); 14555ffd83dbSDimitry Andric } 14565ffd83dbSDimitry Andric 1457e8d8bef9SDimitry Andric void VPUser::printOperands(raw_ostream &O, VPSlotTracker &SlotTracker) const { 1458e8d8bef9SDimitry Andric interleaveComma(operands(), O, [&O, &SlotTracker](VPValue *Op) { 1459e8d8bef9SDimitry Andric Op->printAsOperand(O, SlotTracker); 1460e8d8bef9SDimitry Andric }); 1461e8d8bef9SDimitry Andric } 1462fe6060f1SDimitry Andric #endif 1463e8d8bef9SDimitry Andric 14640b57cec5SDimitry Andric void VPInterleavedAccessInfo::visitRegion(VPRegionBlock *Region, 14650b57cec5SDimitry Andric Old2NewTy &Old2New, 14660b57cec5SDimitry Andric InterleavedAccessInfo &IAI) { 1467bdd1243dSDimitry Andric ReversePostOrderTraversal<VPBlockShallowTraversalWrapper<VPBlockBase *>> 1468bdd1243dSDimitry Andric RPOT(Region->getEntry()); 14690b57cec5SDimitry Andric for (VPBlockBase *Base : RPOT) { 14700b57cec5SDimitry Andric visitBlock(Base, Old2New, IAI); 14710b57cec5SDimitry Andric } 14720b57cec5SDimitry Andric } 14730b57cec5SDimitry Andric 14740b57cec5SDimitry Andric void VPInterleavedAccessInfo::visitBlock(VPBlockBase *Block, Old2NewTy &Old2New, 14750b57cec5SDimitry Andric InterleavedAccessInfo &IAI) { 14760b57cec5SDimitry Andric if (VPBasicBlock *VPBB = dyn_cast<VPBasicBlock>(Block)) { 14770b57cec5SDimitry Andric for (VPRecipeBase &VPI : *VPBB) { 1478*0fca6ea1SDimitry Andric if (isa<VPWidenPHIRecipe>(&VPI)) 1479fe6060f1SDimitry Andric continue; 14800b57cec5SDimitry Andric assert(isa<VPInstruction>(&VPI) && "Can only handle VPInstructions"); 14810b57cec5SDimitry Andric auto *VPInst = cast<VPInstruction>(&VPI); 148281ad6265SDimitry Andric 148381ad6265SDimitry Andric auto *Inst = dyn_cast_or_null<Instruction>(VPInst->getUnderlyingValue()); 148481ad6265SDimitry Andric if (!Inst) 148581ad6265SDimitry Andric continue; 14860b57cec5SDimitry Andric auto *IG = IAI.getInterleaveGroup(Inst); 14870b57cec5SDimitry Andric if (!IG) 14880b57cec5SDimitry Andric continue; 14890b57cec5SDimitry Andric 14900b57cec5SDimitry Andric auto NewIGIter = Old2New.find(IG); 14910b57cec5SDimitry Andric if (NewIGIter == Old2New.end()) 14920b57cec5SDimitry Andric Old2New[IG] = new InterleaveGroup<VPInstruction>( 14935ffd83dbSDimitry Andric IG->getFactor(), IG->isReverse(), IG->getAlign()); 14940b57cec5SDimitry Andric 14950b57cec5SDimitry Andric if (Inst == IG->getInsertPos()) 14960b57cec5SDimitry Andric Old2New[IG]->setInsertPos(VPInst); 14970b57cec5SDimitry Andric 14980b57cec5SDimitry Andric InterleaveGroupMap[VPInst] = Old2New[IG]; 14990b57cec5SDimitry Andric InterleaveGroupMap[VPInst]->insertMember( 15000b57cec5SDimitry Andric VPInst, IG->getIndex(Inst), 15018bcb0991SDimitry Andric Align(IG->isReverse() ? (-1) * int(IG->getFactor()) 15028bcb0991SDimitry Andric : IG->getFactor())); 15030b57cec5SDimitry Andric } 15040b57cec5SDimitry Andric } else if (VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block)) 15050b57cec5SDimitry Andric visitRegion(Region, Old2New, IAI); 15060b57cec5SDimitry Andric else 15070b57cec5SDimitry Andric llvm_unreachable("Unsupported kind of VPBlock."); 15080b57cec5SDimitry Andric } 15090b57cec5SDimitry Andric 15100b57cec5SDimitry Andric VPInterleavedAccessInfo::VPInterleavedAccessInfo(VPlan &Plan, 15110b57cec5SDimitry Andric InterleavedAccessInfo &IAI) { 15120b57cec5SDimitry Andric Old2NewTy Old2New; 151381ad6265SDimitry Andric visitRegion(Plan.getVectorLoopRegion(), Old2New, IAI); 15140b57cec5SDimitry Andric } 15155ffd83dbSDimitry Andric 1516*0fca6ea1SDimitry Andric void VPSlotTracker::assignName(const VPValue *V) { 1517*0fca6ea1SDimitry Andric assert(!VPValue2Name.contains(V) && "VPValue already has a name!"); 1518*0fca6ea1SDimitry Andric auto *UV = V->getUnderlyingValue(); 1519*0fca6ea1SDimitry Andric if (!UV) { 1520*0fca6ea1SDimitry Andric VPValue2Name[V] = (Twine("vp<%") + Twine(NextSlot) + ">").str(); 1521*0fca6ea1SDimitry Andric NextSlot++; 1522*0fca6ea1SDimitry Andric return; 15235ffd83dbSDimitry Andric } 15245ffd83dbSDimitry Andric 1525*0fca6ea1SDimitry Andric // Use the name of the underlying Value, wrapped in "ir<>", and versioned by 1526*0fca6ea1SDimitry Andric // appending ".Number" to the name if there are multiple uses. 1527*0fca6ea1SDimitry Andric std::string Name; 1528*0fca6ea1SDimitry Andric raw_string_ostream S(Name); 1529*0fca6ea1SDimitry Andric UV->printAsOperand(S, false); 1530*0fca6ea1SDimitry Andric assert(!Name.empty() && "Name cannot be empty."); 1531*0fca6ea1SDimitry Andric std::string BaseName = (Twine("ir<") + Name + Twine(">")).str(); 1532*0fca6ea1SDimitry Andric 1533*0fca6ea1SDimitry Andric // First assign the base name for V. 1534*0fca6ea1SDimitry Andric const auto &[A, _] = VPValue2Name.insert({V, BaseName}); 1535*0fca6ea1SDimitry Andric // Integer or FP constants with different types will result in he same string 1536*0fca6ea1SDimitry Andric // due to stripping types. 1537*0fca6ea1SDimitry Andric if (V->isLiveIn() && isa<ConstantInt, ConstantFP>(UV)) 1538*0fca6ea1SDimitry Andric return; 1539*0fca6ea1SDimitry Andric 1540*0fca6ea1SDimitry Andric // If it is already used by C > 0 other VPValues, increase the version counter 1541*0fca6ea1SDimitry Andric // C and use it for V. 1542*0fca6ea1SDimitry Andric const auto &[C, UseInserted] = BaseName2Version.insert({BaseName, 0}); 1543*0fca6ea1SDimitry Andric if (!UseInserted) { 1544*0fca6ea1SDimitry Andric C->second++; 1545*0fca6ea1SDimitry Andric A->second = (BaseName + Twine(".") + Twine(C->second)).str(); 1546*0fca6ea1SDimitry Andric } 1547*0fca6ea1SDimitry Andric } 1548*0fca6ea1SDimitry Andric 1549*0fca6ea1SDimitry Andric void VPSlotTracker::assignNames(const VPlan &Plan) { 15505f757f3fSDimitry Andric if (Plan.VFxUF.getNumUsers() > 0) 1551*0fca6ea1SDimitry Andric assignName(&Plan.VFxUF); 1552*0fca6ea1SDimitry Andric assignName(&Plan.VectorTripCount); 15535ffd83dbSDimitry Andric if (Plan.BackedgeTakenCount) 1554*0fca6ea1SDimitry Andric assignName(Plan.BackedgeTakenCount); 1555*0fca6ea1SDimitry Andric for (VPValue *LI : Plan.VPLiveInsToFree) 1556*0fca6ea1SDimitry Andric assignName(LI); 1557*0fca6ea1SDimitry Andric assignNames(Plan.getPreheader()); 15585ffd83dbSDimitry Andric 1559bdd1243dSDimitry Andric ReversePostOrderTraversal<VPBlockDeepTraversalWrapper<const VPBlockBase *>> 1560bdd1243dSDimitry Andric RPOT(VPBlockDeepTraversalWrapper<const VPBlockBase *>(Plan.getEntry())); 1561fe6060f1SDimitry Andric for (const VPBasicBlock *VPBB : 1562fe6060f1SDimitry Andric VPBlockUtils::blocksOnly<const VPBasicBlock>(RPOT)) 1563*0fca6ea1SDimitry Andric assignNames(VPBB); 156406c3fb27SDimitry Andric } 156506c3fb27SDimitry Andric 1566*0fca6ea1SDimitry Andric void VPSlotTracker::assignNames(const VPBasicBlock *VPBB) { 1567fe6060f1SDimitry Andric for (const VPRecipeBase &Recipe : *VPBB) 1568fe6060f1SDimitry Andric for (VPValue *Def : Recipe.definedValues()) 1569*0fca6ea1SDimitry Andric assignName(Def); 15705ffd83dbSDimitry Andric } 15711fd87a68SDimitry Andric 1572*0fca6ea1SDimitry Andric std::string VPSlotTracker::getOrCreateName(const VPValue *V) const { 1573*0fca6ea1SDimitry Andric std::string Name = VPValue2Name.lookup(V); 1574*0fca6ea1SDimitry Andric if (!Name.empty()) 1575*0fca6ea1SDimitry Andric return Name; 1576*0fca6ea1SDimitry Andric 1577*0fca6ea1SDimitry Andric // If no name was assigned, no VPlan was provided when creating the slot 1578*0fca6ea1SDimitry Andric // tracker or it is not reachable from the provided VPlan. This can happen, 1579*0fca6ea1SDimitry Andric // e.g. when trying to print a recipe that has not been inserted into a VPlan 1580*0fca6ea1SDimitry Andric // in a debugger. 1581*0fca6ea1SDimitry Andric // TODO: Update VPSlotTracker constructor to assign names to recipes & 1582*0fca6ea1SDimitry Andric // VPValues not associated with a VPlan, instead of constructing names ad-hoc 1583*0fca6ea1SDimitry Andric // here. 1584*0fca6ea1SDimitry Andric const VPRecipeBase *DefR = V->getDefiningRecipe(); 1585*0fca6ea1SDimitry Andric (void)DefR; 1586*0fca6ea1SDimitry Andric assert((!DefR || !DefR->getParent() || !DefR->getParent()->getPlan()) && 1587*0fca6ea1SDimitry Andric "VPValue defined by a recipe in a VPlan?"); 1588*0fca6ea1SDimitry Andric 1589*0fca6ea1SDimitry Andric // Use the underlying value's name, if there is one. 1590*0fca6ea1SDimitry Andric if (auto *UV = V->getUnderlyingValue()) { 1591*0fca6ea1SDimitry Andric std::string Name; 1592*0fca6ea1SDimitry Andric raw_string_ostream S(Name); 1593*0fca6ea1SDimitry Andric UV->printAsOperand(S, false); 1594*0fca6ea1SDimitry Andric return (Twine("ir<") + Name + ">").str(); 159581ad6265SDimitry Andric } 159681ad6265SDimitry Andric 1597*0fca6ea1SDimitry Andric return "<badref>"; 1598*0fca6ea1SDimitry Andric } 1599*0fca6ea1SDimitry Andric 1600*0fca6ea1SDimitry Andric bool vputils::onlyFirstLaneUsed(const VPValue *Def) { 16015f757f3fSDimitry Andric return all_of(Def->users(), 1602*0fca6ea1SDimitry Andric [Def](const VPUser *U) { return U->onlyFirstLaneUsed(Def); }); 1603*0fca6ea1SDimitry Andric } 1604*0fca6ea1SDimitry Andric 1605*0fca6ea1SDimitry Andric bool vputils::onlyFirstPartUsed(const VPValue *Def) { 1606*0fca6ea1SDimitry Andric return all_of(Def->users(), 1607*0fca6ea1SDimitry Andric [Def](const VPUser *U) { return U->onlyFirstPartUsed(Def); }); 16085f757f3fSDimitry Andric } 16095f757f3fSDimitry Andric 161081ad6265SDimitry Andric VPValue *vputils::getOrCreateVPValueForSCEVExpr(VPlan &Plan, const SCEV *Expr, 161181ad6265SDimitry Andric ScalarEvolution &SE) { 161206c3fb27SDimitry Andric if (auto *Expanded = Plan.getSCEVExpansion(Expr)) 161306c3fb27SDimitry Andric return Expanded; 161406c3fb27SDimitry Andric VPValue *Expanded = nullptr; 161581ad6265SDimitry Andric if (auto *E = dyn_cast<SCEVConstant>(Expr)) 1616*0fca6ea1SDimitry Andric Expanded = Plan.getOrAddLiveIn(E->getValue()); 161706c3fb27SDimitry Andric else if (auto *E = dyn_cast<SCEVUnknown>(Expr)) 1618*0fca6ea1SDimitry Andric Expanded = Plan.getOrAddLiveIn(E->getValue()); 161906c3fb27SDimitry Andric else { 162006c3fb27SDimitry Andric Expanded = new VPExpandSCEVRecipe(Expr, SE); 162106c3fb27SDimitry Andric Plan.getPreheader()->appendRecipe(Expanded->getDefiningRecipe()); 162206c3fb27SDimitry Andric } 162306c3fb27SDimitry Andric Plan.addSCEVExpansion(Expr, Expanded); 162406c3fb27SDimitry Andric return Expanded; 16251fd87a68SDimitry Andric } 1626*0fca6ea1SDimitry Andric 1627*0fca6ea1SDimitry Andric bool vputils::isHeaderMask(VPValue *V, VPlan &Plan) { 1628*0fca6ea1SDimitry Andric if (isa<VPActiveLaneMaskPHIRecipe>(V)) 1629*0fca6ea1SDimitry Andric return true; 1630*0fca6ea1SDimitry Andric 1631*0fca6ea1SDimitry Andric auto IsWideCanonicalIV = [](VPValue *A) { 1632*0fca6ea1SDimitry Andric return isa<VPWidenCanonicalIVRecipe>(A) || 1633*0fca6ea1SDimitry Andric (isa<VPWidenIntOrFpInductionRecipe>(A) && 1634*0fca6ea1SDimitry Andric cast<VPWidenIntOrFpInductionRecipe>(A)->isCanonical()); 1635*0fca6ea1SDimitry Andric }; 1636*0fca6ea1SDimitry Andric 1637*0fca6ea1SDimitry Andric VPValue *A, *B; 1638*0fca6ea1SDimitry Andric if (match(V, m_ActiveLaneMask(m_VPValue(A), m_VPValue(B)))) 1639*0fca6ea1SDimitry Andric return B == Plan.getTripCount() && 1640*0fca6ea1SDimitry Andric (match(A, m_ScalarIVSteps(m_CanonicalIV(), m_SpecificInt(1))) || 1641*0fca6ea1SDimitry Andric IsWideCanonicalIV(A)); 1642*0fca6ea1SDimitry Andric 1643*0fca6ea1SDimitry Andric return match(V, m_Binary<Instruction::ICmp>(m_VPValue(A), m_VPValue(B))) && 1644*0fca6ea1SDimitry Andric IsWideCanonicalIV(A) && B == Plan.getOrCreateBackedgeTakenCount(); 1645*0fca6ea1SDimitry Andric } 1646