109467b48Spatrick //===- VPRecipeBuilder.h - Helper class to build recipes --------*- C++ -*-===// 209467b48Spatrick // 309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information. 509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 609467b48Spatrick // 709467b48Spatrick //===----------------------------------------------------------------------===// 809467b48Spatrick 909467b48Spatrick #ifndef LLVM_TRANSFORMS_VECTORIZE_VPRECIPEBUILDER_H 1009467b48Spatrick #define LLVM_TRANSFORMS_VECTORIZE_VPRECIPEBUILDER_H 1109467b48Spatrick 1209467b48Spatrick #include "LoopVectorizationPlanner.h" 1309467b48Spatrick #include "VPlan.h" 1409467b48Spatrick #include "llvm/ADT/DenseMap.h" 1573471bf0Spatrick #include "llvm/ADT/PointerUnion.h" 1609467b48Spatrick #include "llvm/IR/IRBuilder.h" 1709467b48Spatrick 1809467b48Spatrick namespace llvm { 1909467b48Spatrick 2009467b48Spatrick class LoopVectorizationLegality; 2109467b48Spatrick class LoopVectorizationCostModel; 2209467b48Spatrick class TargetLibraryInfo; 2309467b48Spatrick 2473471bf0Spatrick using VPRecipeOrVPValueTy = PointerUnion<VPRecipeBase *, VPValue *>; 2573471bf0Spatrick 2609467b48Spatrick /// Helper class to create VPRecipies from IR instructions. 2709467b48Spatrick class VPRecipeBuilder { 2809467b48Spatrick /// The loop that we evaluate. 2909467b48Spatrick Loop *OrigLoop; 3009467b48Spatrick 3109467b48Spatrick /// Target Library Info. 3209467b48Spatrick const TargetLibraryInfo *TLI; 3309467b48Spatrick 3409467b48Spatrick /// The legality analysis. 3509467b48Spatrick LoopVectorizationLegality *Legal; 3609467b48Spatrick 3709467b48Spatrick /// The profitablity analysis. 3809467b48Spatrick LoopVectorizationCostModel &CM; 3909467b48Spatrick 40097a140dSpatrick PredicatedScalarEvolution &PSE; 41097a140dSpatrick 4209467b48Spatrick VPBuilder &Builder; 4309467b48Spatrick 4409467b48Spatrick /// When we if-convert we need to create edge masks. We have to cache values 4509467b48Spatrick /// so that we don't end up with exponential recursion/IR. Note that 4609467b48Spatrick /// if-conversion currently takes place during VPlan-construction, so these 4709467b48Spatrick /// caches are only used at that stage. 4809467b48Spatrick using EdgeMaskCacheTy = 4909467b48Spatrick DenseMap<std::pair<BasicBlock *, BasicBlock *>, VPValue *>; 5009467b48Spatrick using BlockMaskCacheTy = DenseMap<BasicBlock *, VPValue *>; 5109467b48Spatrick EdgeMaskCacheTy EdgeMaskCache; 5209467b48Spatrick BlockMaskCacheTy BlockMaskCache; 5309467b48Spatrick 5409467b48Spatrick // VPlan-VPlan transformations support: Hold a mapping from ingredients to 5509467b48Spatrick // their recipe. To save on memory, only do so for selected ingredients, 56097a140dSpatrick // marked by having a nullptr entry in this map. 5709467b48Spatrick DenseMap<Instruction *, VPRecipeBase *> Ingredient2Recipe; 58097a140dSpatrick 5973471bf0Spatrick /// Cross-iteration reduction & first-order recurrence phis for which we need 6073471bf0Spatrick /// to add the incoming value from the backedge after all recipes have been 6173471bf0Spatrick /// created. 62*d415bd75Srobert SmallVector<VPHeaderPHIRecipe *, 4> PhisToFix; 6373471bf0Spatrick 64097a140dSpatrick /// Check if \p I can be widened at the start of \p Range and possibly 65097a140dSpatrick /// decrease the range such that the returned value holds for the entire \p 66097a140dSpatrick /// Range. The function should not be called for memory instructions or calls. 67097a140dSpatrick bool shouldWiden(Instruction *I, VFRange &Range) const; 68097a140dSpatrick 69097a140dSpatrick /// Check if the load or store instruction \p I should widened for \p 70097a140dSpatrick /// Range.Start and potentially masked. Such instructions are handled by a 71097a140dSpatrick /// recipe that takes an additional VPInstruction for the mask. 7273471bf0Spatrick VPRecipeBase *tryToWidenMemory(Instruction *I, ArrayRef<VPValue *> Operands, 7373471bf0Spatrick VFRange &Range, VPlanPtr &Plan); 74097a140dSpatrick 75*d415bd75Srobert /// Check if an induction recipe should be constructed for \p Phi. If so build 76*d415bd75Srobert /// and return it. If not, return null. 77*d415bd75Srobert VPRecipeBase *tryToOptimizeInductionPHI(PHINode *Phi, 78*d415bd75Srobert ArrayRef<VPValue *> Operands, 79*d415bd75Srobert VPlan &Plan, VFRange &Range); 80097a140dSpatrick 81097a140dSpatrick /// Optimize the special case where the operand of \p I is a constant integer 82097a140dSpatrick /// induction variable. 83097a140dSpatrick VPWidenIntOrFpInductionRecipe * 8473471bf0Spatrick tryToOptimizeInductionTruncate(TruncInst *I, ArrayRef<VPValue *> Operands, 85*d415bd75Srobert VFRange &Range, VPlan &Plan); 86097a140dSpatrick 8773471bf0Spatrick /// Handle non-loop phi nodes. Return a VPValue, if all incoming values match 8873471bf0Spatrick /// or a new VPBlendRecipe otherwise. Currently all such phi nodes are turned 8973471bf0Spatrick /// into a sequence of select instructions as the vectorizer currently 9073471bf0Spatrick /// performs full if-conversion. 9173471bf0Spatrick VPRecipeOrVPValueTy tryToBlend(PHINode *Phi, ArrayRef<VPValue *> Operands, 9273471bf0Spatrick VPlanPtr &Plan); 93097a140dSpatrick 94097a140dSpatrick /// Handle call instructions. If \p CI can be widened for \p Range.Start, 95097a140dSpatrick /// return a new VPWidenCallRecipe. Range.End may be decreased to ensure same 96097a140dSpatrick /// decision from \p Range.Start to \p Range.End. 9773471bf0Spatrick VPWidenCallRecipe *tryToWidenCall(CallInst *CI, ArrayRef<VPValue *> Operands, 9873471bf0Spatrick VFRange &Range) const; 99097a140dSpatrick 100097a140dSpatrick /// Check if \p I has an opcode that can be widened and return a VPWidenRecipe 101097a140dSpatrick /// if it can. The function should only be called if the cost-model indicates 102097a140dSpatrick /// that widening should be performed. 103*d415bd75Srobert VPRecipeBase *tryToWiden(Instruction *I, ArrayRef<VPValue *> Operands, 104*d415bd75Srobert VPBasicBlock *VPBB, VPlanPtr &Plan); 10573471bf0Spatrick 10673471bf0Spatrick /// Return a VPRecipeOrValueTy with VPRecipeBase * being set. This can be used to force the use as VPRecipeBase* for recipe sub-types that also inherit from VPValue. toVPRecipeResult(VPRecipeBase * R)10773471bf0Spatrick VPRecipeOrVPValueTy toVPRecipeResult(VPRecipeBase *R) const { return R; } 108097a140dSpatrick 109097a140dSpatrick public: VPRecipeBuilder(Loop * OrigLoop,const TargetLibraryInfo * TLI,LoopVectorizationLegality * Legal,LoopVectorizationCostModel & CM,PredicatedScalarEvolution & PSE,VPBuilder & Builder)110097a140dSpatrick VPRecipeBuilder(Loop *OrigLoop, const TargetLibraryInfo *TLI, 111097a140dSpatrick LoopVectorizationLegality *Legal, 112097a140dSpatrick LoopVectorizationCostModel &CM, 113097a140dSpatrick PredicatedScalarEvolution &PSE, VPBuilder &Builder) 114097a140dSpatrick : OrigLoop(OrigLoop), TLI(TLI), Legal(Legal), CM(CM), PSE(PSE), 115097a140dSpatrick Builder(Builder) {} 116097a140dSpatrick 11773471bf0Spatrick /// Check if an existing VPValue can be used for \p Instr or a recipe can be 11873471bf0Spatrick /// create for \p I withing the given VF \p Range. If an existing VPValue can 11973471bf0Spatrick /// be used or if a recipe can be created, return it. Otherwise return a 12073471bf0Spatrick /// VPRecipeOrVPValueTy with nullptr. 12173471bf0Spatrick VPRecipeOrVPValueTy tryToCreateWidenRecipe(Instruction *Instr, 12273471bf0Spatrick ArrayRef<VPValue *> Operands, 123*d415bd75Srobert VFRange &Range, VPBasicBlock *VPBB, 124*d415bd75Srobert VPlanPtr &Plan); 12509467b48Spatrick 12609467b48Spatrick /// Set the recipe created for given ingredient. This operation is a no-op for 12709467b48Spatrick /// ingredients that were not marked using a nullptr entry in the map. setRecipe(Instruction * I,VPRecipeBase * R)12809467b48Spatrick void setRecipe(Instruction *I, VPRecipeBase *R) { 12909467b48Spatrick if (!Ingredient2Recipe.count(I)) 13009467b48Spatrick return; 13109467b48Spatrick assert(Ingredient2Recipe[I] == nullptr && 13209467b48Spatrick "Recipe already set for ingredient"); 13309467b48Spatrick Ingredient2Recipe[I] = R; 13409467b48Spatrick } 13509467b48Spatrick 13609467b48Spatrick /// A helper function that computes the predicate of the block BB, assuming 13709467b48Spatrick /// that the header block of the loop is set to True. It returns the *entry* 13809467b48Spatrick /// mask for the block BB. 13909467b48Spatrick VPValue *createBlockInMask(BasicBlock *BB, VPlanPtr &Plan); 14009467b48Spatrick 14109467b48Spatrick /// A helper function that computes the predicate of the edge between SRC 14209467b48Spatrick /// and DST. 14309467b48Spatrick VPValue *createEdgeMask(BasicBlock *Src, BasicBlock *Dst, VPlanPtr &Plan); 14409467b48Spatrick 14509467b48Spatrick /// Mark given ingredient for recording its recipe once one is created for 14609467b48Spatrick /// it. recordRecipeOf(Instruction * I)14709467b48Spatrick void recordRecipeOf(Instruction *I) { 14809467b48Spatrick assert((!Ingredient2Recipe.count(I) || Ingredient2Recipe[I] == nullptr) && 14909467b48Spatrick "Recipe already set for ingredient"); 15009467b48Spatrick Ingredient2Recipe[I] = nullptr; 15109467b48Spatrick } 15209467b48Spatrick 15309467b48Spatrick /// Return the recipe created for given ingredient. getRecipe(Instruction * I)15409467b48Spatrick VPRecipeBase *getRecipe(Instruction *I) { 15509467b48Spatrick assert(Ingredient2Recipe.count(I) && 15609467b48Spatrick "Recording this ingredients recipe was not requested"); 15709467b48Spatrick assert(Ingredient2Recipe[I] != nullptr && 15809467b48Spatrick "Ingredient doesn't have a recipe"); 15909467b48Spatrick return Ingredient2Recipe[I]; 16009467b48Spatrick } 16109467b48Spatrick 162*d415bd75Srobert /// Create a replicating region for \p PredRecipe. 163*d415bd75Srobert VPRegionBlock *createReplicateRegion(VPReplicateRecipe *PredRecipe, 16409467b48Spatrick VPlanPtr &Plan); 16509467b48Spatrick 16609467b48Spatrick /// Build a VPReplicationRecipe for \p I and enclose it within a Region if it 16709467b48Spatrick /// is predicated. \return \p VPBB augmented with this new recipe if \p I is 16809467b48Spatrick /// not predicated, otherwise \return a new VPBasicBlock that succeeds the new 16909467b48Spatrick /// Region. Update the packing decision of predicated instructions if they 17009467b48Spatrick /// feed \p I. Range.End may be decreased to ensure same recipe behavior from 17109467b48Spatrick /// \p Range.Start to \p Range.End. 17209467b48Spatrick VPBasicBlock *handleReplication( 17309467b48Spatrick Instruction *I, VFRange &Range, VPBasicBlock *VPBB, 17409467b48Spatrick VPlanPtr &Plan); 17573471bf0Spatrick 17673471bf0Spatrick /// Add the incoming values from the backedge to reduction & first-order 17773471bf0Spatrick /// recurrence cross-iteration phis. 17873471bf0Spatrick void fixHeaderPhis(); 17909467b48Spatrick }; 18009467b48Spatrick } // end namespace llvm 18109467b48Spatrick 18209467b48Spatrick #endif // LLVM_TRANSFORMS_VECTORIZE_VPRECIPEBUILDER_H 183