xref: /freebsd/contrib/llvm-project/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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