xref: /openbsd-src/gnu/llvm/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
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