10b57cec5SDimitry Andric //===- VPRecipeBuilder.h - Helper class to build recipes --------*- C++ -*-===// 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 #ifndef LLVM_TRANSFORMS_VECTORIZE_VPRECIPEBUILDER_H 100b57cec5SDimitry Andric #define LLVM_TRANSFORMS_VECTORIZE_VPRECIPEBUILDER_H 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include "LoopVectorizationPlanner.h" 130b57cec5SDimitry Andric #include "VPlan.h" 140b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 15fe6060f1SDimitry Andric #include "llvm/ADT/PointerUnion.h" 160b57cec5SDimitry Andric #include "llvm/IR/IRBuilder.h" 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric namespace llvm { 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric class LoopVectorizationLegality; 210b57cec5SDimitry Andric class LoopVectorizationCostModel; 220b57cec5SDimitry Andric class TargetLibraryInfo; 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric /// Helper class to create VPRecipies from IR instructions. 250b57cec5SDimitry Andric class VPRecipeBuilder { 26*0fca6ea1SDimitry Andric /// The VPlan new recipes are added to. 27*0fca6ea1SDimitry Andric VPlan &Plan; 28*0fca6ea1SDimitry Andric 290b57cec5SDimitry Andric /// The loop that we evaluate. 300b57cec5SDimitry Andric Loop *OrigLoop; 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric /// Target Library Info. 330b57cec5SDimitry Andric const TargetLibraryInfo *TLI; 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric /// The legality analysis. 360b57cec5SDimitry Andric LoopVectorizationLegality *Legal; 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric /// The profitablity analysis. 390b57cec5SDimitry Andric LoopVectorizationCostModel &CM; 400b57cec5SDimitry Andric 415ffd83dbSDimitry Andric PredicatedScalarEvolution &PSE; 425ffd83dbSDimitry Andric 430b57cec5SDimitry Andric VPBuilder &Builder; 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric /// When we if-convert we need to create edge masks. We have to cache values 460b57cec5SDimitry Andric /// so that we don't end up with exponential recursion/IR. Note that 470b57cec5SDimitry Andric /// if-conversion currently takes place during VPlan-construction, so these 480b57cec5SDimitry Andric /// caches are only used at that stage. 490b57cec5SDimitry Andric using EdgeMaskCacheTy = 500b57cec5SDimitry Andric DenseMap<std::pair<BasicBlock *, BasicBlock *>, VPValue *>; 510b57cec5SDimitry Andric using BlockMaskCacheTy = DenseMap<BasicBlock *, VPValue *>; 520b57cec5SDimitry Andric EdgeMaskCacheTy EdgeMaskCache; 530b57cec5SDimitry Andric BlockMaskCacheTy BlockMaskCache; 540b57cec5SDimitry Andric 55*0fca6ea1SDimitry Andric // VPlan construction support: Hold a mapping from ingredients to 56*0fca6ea1SDimitry Andric // their recipe. 57480093f4SDimitry Andric DenseMap<Instruction *, VPRecipeBase *> Ingredient2Recipe; 585ffd83dbSDimitry Andric 59fe6060f1SDimitry Andric /// Cross-iteration reduction & first-order recurrence phis for which we need 60fe6060f1SDimitry Andric /// to add the incoming value from the backedge after all recipes have been 61fe6060f1SDimitry Andric /// created. 6204eeddc0SDimitry Andric SmallVector<VPHeaderPHIRecipe *, 4> PhisToFix; 63fe6060f1SDimitry Andric 645ffd83dbSDimitry Andric /// Check if \p I can be widened at the start of \p Range and possibly 655ffd83dbSDimitry Andric /// decrease the range such that the returned value holds for the entire \p 665ffd83dbSDimitry Andric /// Range. The function should not be called for memory instructions or calls. 675ffd83dbSDimitry Andric bool shouldWiden(Instruction *I, VFRange &Range) const; 685ffd83dbSDimitry Andric 695ffd83dbSDimitry Andric /// Check if the load or store instruction \p I should widened for \p 705ffd83dbSDimitry Andric /// Range.Start and potentially masked. Such instructions are handled by a 715ffd83dbSDimitry Andric /// recipe that takes an additional VPInstruction for the mask. 72*0fca6ea1SDimitry Andric VPWidenMemoryRecipe *tryToWidenMemory(Instruction *I, 73*0fca6ea1SDimitry Andric ArrayRef<VPValue *> Operands, 74*0fca6ea1SDimitry Andric VFRange &Range); 755ffd83dbSDimitry Andric 7681ad6265SDimitry Andric /// Check if an induction recipe should be constructed for \p Phi. If so build 7781ad6265SDimitry Andric /// and return it. If not, return null. 78*0fca6ea1SDimitry Andric VPHeaderPHIRecipe *tryToOptimizeInductionPHI(PHINode *Phi, 7981ad6265SDimitry Andric ArrayRef<VPValue *> Operands, 80*0fca6ea1SDimitry Andric VFRange &Range); 815ffd83dbSDimitry Andric 825ffd83dbSDimitry Andric /// Optimize the special case where the operand of \p I is a constant integer 835ffd83dbSDimitry Andric /// induction variable. 845ffd83dbSDimitry Andric VPWidenIntOrFpInductionRecipe * 85fe6060f1SDimitry Andric tryToOptimizeInductionTruncate(TruncInst *I, ArrayRef<VPValue *> Operands, 86*0fca6ea1SDimitry Andric VFRange &Range); 875ffd83dbSDimitry Andric 88*0fca6ea1SDimitry Andric /// Handle non-loop phi nodes. Return a new VPBlendRecipe otherwise. Currently 89*0fca6ea1SDimitry Andric /// all such phi nodes are turned into a sequence of select instructions as 90*0fca6ea1SDimitry Andric /// the vectorizer currently performs full if-conversion. 91*0fca6ea1SDimitry Andric VPBlendRecipe *tryToBlend(PHINode *Phi, ArrayRef<VPValue *> Operands); 925ffd83dbSDimitry Andric 935ffd83dbSDimitry Andric /// Handle call instructions. If \p CI can be widened for \p Range.Start, 945ffd83dbSDimitry Andric /// return a new VPWidenCallRecipe. Range.End may be decreased to ensure same 955ffd83dbSDimitry Andric /// decision from \p Range.Start to \p Range.End. 96fe6060f1SDimitry Andric VPWidenCallRecipe *tryToWidenCall(CallInst *CI, ArrayRef<VPValue *> Operands, 97*0fca6ea1SDimitry Andric VFRange &Range); 985ffd83dbSDimitry Andric 995ffd83dbSDimitry Andric /// Check if \p I has an opcode that can be widened and return a VPWidenRecipe 1005ffd83dbSDimitry Andric /// if it can. The function should only be called if the cost-model indicates 1015ffd83dbSDimitry Andric /// that widening should be performed. 102*0fca6ea1SDimitry Andric VPWidenRecipe *tryToWiden(Instruction *I, ArrayRef<VPValue *> Operands, 103*0fca6ea1SDimitry Andric VPBasicBlock *VPBB); 1045ffd83dbSDimitry Andric 1055ffd83dbSDimitry Andric public: VPRecipeBuilder(VPlan & Plan,Loop * OrigLoop,const TargetLibraryInfo * TLI,LoopVectorizationLegality * Legal,LoopVectorizationCostModel & CM,PredicatedScalarEvolution & PSE,VPBuilder & Builder)106*0fca6ea1SDimitry Andric VPRecipeBuilder(VPlan &Plan, Loop *OrigLoop, const TargetLibraryInfo *TLI, 1075ffd83dbSDimitry Andric LoopVectorizationLegality *Legal, 1085ffd83dbSDimitry Andric LoopVectorizationCostModel &CM, 1095ffd83dbSDimitry Andric PredicatedScalarEvolution &PSE, VPBuilder &Builder) 110*0fca6ea1SDimitry Andric : Plan(Plan), OrigLoop(OrigLoop), TLI(TLI), Legal(Legal), CM(CM), 111*0fca6ea1SDimitry Andric PSE(PSE), Builder(Builder) {} 1125ffd83dbSDimitry Andric 113*0fca6ea1SDimitry Andric /// Create and return a widened recipe for \p I if one can be created within 114*0fca6ea1SDimitry Andric /// the given VF \p Range. 115*0fca6ea1SDimitry Andric VPRecipeBase *tryToCreateWidenRecipe(Instruction *Instr, 116fe6060f1SDimitry Andric ArrayRef<VPValue *> Operands, 117*0fca6ea1SDimitry Andric VFRange &Range, VPBasicBlock *VPBB); 118480093f4SDimitry Andric 119*0fca6ea1SDimitry Andric /// Set the recipe created for given ingredient. setRecipe(Instruction * I,VPRecipeBase * R)120480093f4SDimitry Andric void setRecipe(Instruction *I, VPRecipeBase *R) { 121*0fca6ea1SDimitry Andric assert(!Ingredient2Recipe.contains(I) && 122*0fca6ea1SDimitry Andric "Cannot reset recipe for instruction."); 123480093f4SDimitry Andric Ingredient2Recipe[I] = R; 124480093f4SDimitry Andric } 125480093f4SDimitry Andric 1265f757f3fSDimitry Andric /// Create the mask for the vector loop header block. 127*0fca6ea1SDimitry Andric void createHeaderMask(); 1285f757f3fSDimitry Andric 1290b57cec5SDimitry Andric /// A helper function that computes the predicate of the block BB, assuming 1305f757f3fSDimitry Andric /// that the header block of the loop is set to True or the loop mask when 1311db9f3b2SDimitry Andric /// tail folding. 132*0fca6ea1SDimitry Andric void createBlockInMask(BasicBlock *BB); 1331db9f3b2SDimitry Andric 1341db9f3b2SDimitry Andric /// Returns the *entry* mask for the block \p BB. 1351db9f3b2SDimitry Andric VPValue *getBlockInMask(BasicBlock *BB) const; 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric /// A helper function that computes the predicate of the edge between SRC 1380b57cec5SDimitry Andric /// and DST. 139*0fca6ea1SDimitry Andric VPValue *createEdgeMask(BasicBlock *Src, BasicBlock *Dst); 1400b57cec5SDimitry Andric 141*0fca6ea1SDimitry Andric /// A helper that returns the previously computed predicate of the edge 142*0fca6ea1SDimitry Andric /// between SRC and DST. 143*0fca6ea1SDimitry Andric VPValue *getEdgeMask(BasicBlock *Src, BasicBlock *Dst) const; 144480093f4SDimitry Andric 145480093f4SDimitry Andric /// Return the recipe created for given ingredient. getRecipe(Instruction * I)146480093f4SDimitry Andric VPRecipeBase *getRecipe(Instruction *I) { 147480093f4SDimitry Andric assert(Ingredient2Recipe.count(I) && 148480093f4SDimitry Andric "Recording this ingredients recipe was not requested"); 149480093f4SDimitry Andric assert(Ingredient2Recipe[I] != nullptr && 150480093f4SDimitry Andric "Ingredient doesn't have a recipe"); 151480093f4SDimitry Andric return Ingredient2Recipe[I]; 152480093f4SDimitry Andric } 1530b57cec5SDimitry Andric 15406c3fb27SDimitry Andric /// Build a VPReplicationRecipe for \p I. If it is predicated, add the mask as 15506c3fb27SDimitry Andric /// last operand. Range.End may be decreased to ensure same recipe behavior 15606c3fb27SDimitry Andric /// from \p Range.Start to \p Range.End. 157*0fca6ea1SDimitry Andric VPReplicateRecipe *handleReplication(Instruction *I, VFRange &Range); 158fe6060f1SDimitry Andric 159fe6060f1SDimitry Andric /// Add the incoming values from the backedge to reduction & first-order 160fe6060f1SDimitry Andric /// recurrence cross-iteration phis. 161fe6060f1SDimitry Andric void fixHeaderPhis(); 162*0fca6ea1SDimitry Andric 163*0fca6ea1SDimitry Andric /// Returns a range mapping the values of the range \p Operands to their 164*0fca6ea1SDimitry Andric /// corresponding VPValues. 165*0fca6ea1SDimitry Andric iterator_range<mapped_iterator<Use *, std::function<VPValue *(Value *)>>> 166*0fca6ea1SDimitry Andric mapToVPValues(User::op_range Operands); 167*0fca6ea1SDimitry Andric getVPValueOrAddLiveIn(Value * V,VPlan & Plan)168*0fca6ea1SDimitry Andric VPValue *getVPValueOrAddLiveIn(Value *V, VPlan &Plan) { 169*0fca6ea1SDimitry Andric if (auto *I = dyn_cast<Instruction>(V)) { 170*0fca6ea1SDimitry Andric if (auto *R = Ingredient2Recipe.lookup(I)) 171*0fca6ea1SDimitry Andric return R->getVPSingleValue(); 172*0fca6ea1SDimitry Andric } 173*0fca6ea1SDimitry Andric return Plan.getOrAddLiveIn(V); 174*0fca6ea1SDimitry Andric } 1750b57cec5SDimitry Andric }; 1760b57cec5SDimitry Andric } // end namespace llvm 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric #endif // LLVM_TRANSFORMS_VECTORIZE_VPRECIPEBUILDER_H 179