10f1314c5SHal Finkel //===- LoopVectorizationPlanner.h - Planner for LoopVectorization ---------===//
20f1314c5SHal Finkel //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60f1314c5SHal Finkel //
70f1314c5SHal Finkel //===----------------------------------------------------------------------===//
80f1314c5SHal Finkel ///
90f1314c5SHal Finkel /// \file
100f1314c5SHal Finkel /// This file provides a LoopVectorizationPlanner class.
110f1314c5SHal Finkel /// InnerLoopVectorizer vectorizes loops which contain only one basic
120f1314c5SHal Finkel /// LoopVectorizationPlanner - drives the vectorization process after having
130f1314c5SHal Finkel /// passed Legality checks.
140f1314c5SHal Finkel /// The planner builds and optimizes the Vectorization Plans which record the
150f1314c5SHal Finkel /// decisions how to vectorize the given loop. In particular, represent the
160f1314c5SHal Finkel /// control-flow of the vectorized version, the replication of instructions that
170f1314c5SHal Finkel /// are to be scalarized, and interleave access groups.
180f1314c5SHal Finkel ///
190f1314c5SHal Finkel /// Also provides a VPlan-based builder utility analogous to IRBuilder.
200f1314c5SHal Finkel /// It provides an instruction-level API for generating VPInstructions while
210f1314c5SHal Finkel /// abstracting away the Recipe manipulation details.
220f1314c5SHal Finkel //===----------------------------------------------------------------------===//
230f1314c5SHal Finkel 
240f1314c5SHal Finkel #ifndef LLVM_TRANSFORMS_VECTORIZE_LOOPVECTORIZATIONPLANNER_H
250f1314c5SHal Finkel #define LLVM_TRANSFORMS_VECTORIZE_LOOPVECTORIZATIONPLANNER_H
260f1314c5SHal Finkel 
270f1314c5SHal Finkel #include "VPlan.h"
281b89c832Sserge-sans-paille #include "llvm/Support/InstructionCost.h"
290f1314c5SHal Finkel 
300f1314c5SHal Finkel namespace llvm {
310f1314c5SHal Finkel 
3249999d43SFlorian Hahn class LoopInfo;
33b108a457SSimon Pilgrim class LoopVectorizationLegality;
34b108a457SSimon Pilgrim class LoopVectorizationCostModel;
3518138e02SFlorian Hahn class PredicatedScalarEvolution;
36c773d0f9SFlorian Hahn class LoopVectorizeHints;
37c773d0f9SFlorian Hahn class OptimizationRemarkEmitter;
3849999d43SFlorian Hahn class TargetTransformInfo;
3949999d43SFlorian Hahn class TargetLibraryInfo;
40745bf6cfSDavid Green class VPRecipeBuilder;
4118138e02SFlorian Hahn 
420f1314c5SHal Finkel /// VPlan-based builder utility analogous to IRBuilder.
430f1314c5SHal Finkel class VPBuilder {
440f1314c5SHal Finkel   VPBasicBlock *BB = nullptr;
450f1314c5SHal Finkel   VPBasicBlock::iterator InsertPt = VPBasicBlock::iterator();
460f1314c5SHal Finkel 
470f1314c5SHal Finkel   VPInstruction *createInstruction(unsigned Opcode,
48*02d6950dSDavid Sherwood                                    ArrayRef<VPValue *> Operands, DebugLoc DL,
49*02d6950dSDavid Sherwood                                    const Twine &Name = "") {
50*02d6950dSDavid Sherwood     VPInstruction *Instr = new VPInstruction(Opcode, Operands, DL, Name);
51168d04d5SDiego Caballero     if (BB)
520f1314c5SHal Finkel       BB->insert(Instr, InsertPt);
530f1314c5SHal Finkel     return Instr;
540f1314c5SHal Finkel   }
550f1314c5SHal Finkel 
56168d04d5SDiego Caballero   VPInstruction *createInstruction(unsigned Opcode,
575b362e4cSFlorian Hahn                                    std::initializer_list<VPValue *> Operands,
58*02d6950dSDavid Sherwood                                    DebugLoc DL, const Twine &Name = "") {
59*02d6950dSDavid Sherwood     return createInstruction(Opcode, ArrayRef<VPValue *>(Operands), DL, Name);
60168d04d5SDiego Caballero   }
61168d04d5SDiego Caballero 
620f1314c5SHal Finkel public:
633a3cb929SKazu Hirata   VPBuilder() = default;
640f1314c5SHal Finkel 
65168d04d5SDiego Caballero   /// Clear the insertion point: created instructions will not be inserted into
66168d04d5SDiego Caballero   /// a block.
clearInsertionPoint()67168d04d5SDiego Caballero   void clearInsertionPoint() {
68168d04d5SDiego Caballero     BB = nullptr;
69168d04d5SDiego Caballero     InsertPt = VPBasicBlock::iterator();
70168d04d5SDiego Caballero   }
71168d04d5SDiego Caballero 
getInsertBlock()72168d04d5SDiego Caballero   VPBasicBlock *getInsertBlock() const { return BB; }
getInsertPoint()73168d04d5SDiego Caballero   VPBasicBlock::iterator getInsertPoint() const { return InsertPt; }
74168d04d5SDiego Caballero 
75168d04d5SDiego Caballero   /// InsertPoint - A saved insertion point.
76168d04d5SDiego Caballero   class VPInsertPoint {
77168d04d5SDiego Caballero     VPBasicBlock *Block = nullptr;
78168d04d5SDiego Caballero     VPBasicBlock::iterator Point;
79168d04d5SDiego Caballero 
80168d04d5SDiego Caballero   public:
81168d04d5SDiego Caballero     /// Creates a new insertion point which doesn't point to anything.
82168d04d5SDiego Caballero     VPInsertPoint() = default;
83168d04d5SDiego Caballero 
84168d04d5SDiego Caballero     /// Creates a new insertion point at the given location.
VPInsertPoint(VPBasicBlock * InsertBlock,VPBasicBlock::iterator InsertPoint)85168d04d5SDiego Caballero     VPInsertPoint(VPBasicBlock *InsertBlock, VPBasicBlock::iterator InsertPoint)
86168d04d5SDiego Caballero         : Block(InsertBlock), Point(InsertPoint) {}
87168d04d5SDiego Caballero 
88168d04d5SDiego Caballero     /// Returns true if this insert point is set.
isSet()89168d04d5SDiego Caballero     bool isSet() const { return Block != nullptr; }
90168d04d5SDiego Caballero 
getBlock()91168d04d5SDiego Caballero     VPBasicBlock *getBlock() const { return Block; }
getPoint()92168d04d5SDiego Caballero     VPBasicBlock::iterator getPoint() const { return Point; }
93168d04d5SDiego Caballero   };
94168d04d5SDiego Caballero 
95168d04d5SDiego Caballero   /// Sets the current insert point to a previously-saved location.
restoreIP(VPInsertPoint IP)96168d04d5SDiego Caballero   void restoreIP(VPInsertPoint IP) {
97168d04d5SDiego Caballero     if (IP.isSet())
98168d04d5SDiego Caballero       setInsertPoint(IP.getBlock(), IP.getPoint());
99168d04d5SDiego Caballero     else
100168d04d5SDiego Caballero       clearInsertionPoint();
101168d04d5SDiego Caballero   }
102168d04d5SDiego Caballero 
103168d04d5SDiego Caballero   /// This specifies that created VPInstructions should be appended to the end
104168d04d5SDiego Caballero   /// of the specified block.
setInsertPoint(VPBasicBlock * TheBB)1050f1314c5SHal Finkel   void setInsertPoint(VPBasicBlock *TheBB) {
1060f1314c5SHal Finkel     assert(TheBB && "Attempting to set a null insert point");
1070f1314c5SHal Finkel     BB = TheBB;
1080f1314c5SHal Finkel     InsertPt = BB->end();
1090f1314c5SHal Finkel   }
1100f1314c5SHal Finkel 
111168d04d5SDiego Caballero   /// This specifies that created instructions should be inserted at the
112168d04d5SDiego Caballero   /// specified point.
setInsertPoint(VPBasicBlock * TheBB,VPBasicBlock::iterator IP)113168d04d5SDiego Caballero   void setInsertPoint(VPBasicBlock *TheBB, VPBasicBlock::iterator IP) {
114168d04d5SDiego Caballero     BB = TheBB;
115168d04d5SDiego Caballero     InsertPt = IP;
116168d04d5SDiego Caballero   }
117168d04d5SDiego Caballero 
118168d04d5SDiego Caballero   /// Insert and return the specified instruction.
insert(VPInstruction * I)119168d04d5SDiego Caballero   VPInstruction *insert(VPInstruction *I) const {
120168d04d5SDiego Caballero     BB->insert(I, InsertPt);
121168d04d5SDiego Caballero     return I;
122168d04d5SDiego Caballero   }
123168d04d5SDiego Caballero 
124168d04d5SDiego Caballero   /// Create an N-ary operation with \p Opcode, \p Operands and set \p Inst as
125168d04d5SDiego Caballero   /// its underlying Instruction.
126168d04d5SDiego Caballero   VPValue *createNaryOp(unsigned Opcode, ArrayRef<VPValue *> Operands,
127*02d6950dSDavid Sherwood                         Instruction *Inst = nullptr, const Twine &Name = "") {
1285b362e4cSFlorian Hahn     DebugLoc DL;
1295b362e4cSFlorian Hahn     if (Inst)
1305b362e4cSFlorian Hahn       DL = Inst->getDebugLoc();
131*02d6950dSDavid Sherwood     VPInstruction *NewVPInst = createInstruction(Opcode, Operands, DL, Name);
132168d04d5SDiego Caballero     NewVPInst->setUnderlyingValue(Inst);
133168d04d5SDiego Caballero     return NewVPInst;
134168d04d5SDiego Caballero   }
1355b362e4cSFlorian Hahn   VPValue *createNaryOp(unsigned Opcode, ArrayRef<VPValue *> Operands,
136*02d6950dSDavid Sherwood                         DebugLoc DL, const Twine &Name = "") {
137*02d6950dSDavid Sherwood     return createInstruction(Opcode, Operands, DL, Name);
1380f1314c5SHal Finkel   }
1390f1314c5SHal Finkel 
140*02d6950dSDavid Sherwood   VPValue *createNot(VPValue *Operand, DebugLoc DL, const Twine &Name = "") {
141*02d6950dSDavid Sherwood     return createInstruction(VPInstruction::Not, {Operand}, DL, Name);
1420f1314c5SHal Finkel   }
1430f1314c5SHal Finkel 
144*02d6950dSDavid Sherwood   VPValue *createAnd(VPValue *LHS, VPValue *RHS, DebugLoc DL,
145*02d6950dSDavid Sherwood                      const Twine &Name = "") {
146*02d6950dSDavid Sherwood     return createInstruction(Instruction::BinaryOps::And, {LHS, RHS}, DL, Name);
1470f1314c5SHal Finkel   }
148083ea389SGalina Kistanova 
149*02d6950dSDavid Sherwood   VPValue *createOr(VPValue *LHS, VPValue *RHS, DebugLoc DL,
150*02d6950dSDavid Sherwood                     const Twine &Name = "") {
151*02d6950dSDavid Sherwood     return createInstruction(Instruction::BinaryOps::Or, {LHS, RHS}, DL, Name);
1525b362e4cSFlorian Hahn   }
1535b362e4cSFlorian Hahn 
1545b362e4cSFlorian Hahn   VPValue *createSelect(VPValue *Cond, VPValue *TrueVal, VPValue *FalseVal,
155*02d6950dSDavid Sherwood                         DebugLoc DL, const Twine &Name = "") {
156*02d6950dSDavid Sherwood     return createNaryOp(Instruction::Select, {Cond, TrueVal, FalseVal}, DL,
157*02d6950dSDavid Sherwood                         Name);
158ed253ef7SJuneyoung Lee   }
159ed253ef7SJuneyoung Lee 
160168d04d5SDiego Caballero   //===--------------------------------------------------------------------===//
161168d04d5SDiego Caballero   // RAII helpers.
162168d04d5SDiego Caballero   //===--------------------------------------------------------------------===//
163168d04d5SDiego Caballero 
164168d04d5SDiego Caballero   /// RAII object that stores the current insertion point and restores it when
165168d04d5SDiego Caballero   /// the object is destroyed.
166168d04d5SDiego Caballero   class InsertPointGuard {
167168d04d5SDiego Caballero     VPBuilder &Builder;
168168d04d5SDiego Caballero     VPBasicBlock *Block;
169168d04d5SDiego Caballero     VPBasicBlock::iterator Point;
170168d04d5SDiego Caballero 
171168d04d5SDiego Caballero   public:
InsertPointGuard(VPBuilder & B)172168d04d5SDiego Caballero     InsertPointGuard(VPBuilder &B)
173168d04d5SDiego Caballero         : Builder(B), Block(B.getInsertBlock()), Point(B.getInsertPoint()) {}
174168d04d5SDiego Caballero 
175168d04d5SDiego Caballero     InsertPointGuard(const InsertPointGuard &) = delete;
176168d04d5SDiego Caballero     InsertPointGuard &operator=(const InsertPointGuard &) = delete;
177168d04d5SDiego Caballero 
~InsertPointGuard()178168d04d5SDiego Caballero     ~InsertPointGuard() { Builder.restoreIP(VPInsertPoint(Block, Point)); }
179168d04d5SDiego Caballero   };
180168d04d5SDiego Caballero };
1810f1314c5SHal Finkel 
1820f1314c5SHal Finkel /// TODO: The following VectorizationFactor was pulled out of
1830f1314c5SHal Finkel /// LoopVectorizationCostModel class. LV also deals with
1840f1314c5SHal Finkel /// VectorizerParams::VectorizationFactor and VectorizationCostTy.
1850f1314c5SHal Finkel /// We need to streamline them.
1860f1314c5SHal Finkel 
187cc5ee857SFlorian Hahn /// Information about vectorization costs.
1880f1314c5SHal Finkel struct VectorizationFactor {
189cc5ee857SFlorian Hahn   /// Vector width with best cost.
1905a34b3abSFrancesco Petrogalli   ElementCount Width;
191cc5ee857SFlorian Hahn   /// Cost of the loop with that width.
19286729538SSander de Smalen   InstructionCost Cost;
19386729538SSander de Smalen 
194cb69ba4fSFlorian Hahn   /// Cost of the scalar loop.
195cb69ba4fSFlorian Hahn   InstructionCost ScalarCost;
196cb69ba4fSFlorian Hahn 
197644a965cSFlorian Hahn   /// The minimum trip count required to make vectorization profitable, e.g. due
198644a965cSFlorian Hahn   /// to runtime checks.
199644a965cSFlorian Hahn   ElementCount MinProfitableTripCount;
200644a965cSFlorian Hahn 
VectorizationFactorVectorizationFactor201cb69ba4fSFlorian Hahn   VectorizationFactor(ElementCount Width, InstructionCost Cost,
202cb69ba4fSFlorian Hahn                       InstructionCost ScalarCost)
203cb69ba4fSFlorian Hahn       : Width(Width), Cost(Cost), ScalarCost(ScalarCost) {}
204ba5acbc4SFlorian Hahn 
205cc5ee857SFlorian Hahn   /// Width 1 means no vectorization, cost 0 means uncomputed cost.
DisabledVectorizationFactor2065a34b3abSFrancesco Petrogalli   static VectorizationFactor Disabled() {
207cb69ba4fSFlorian Hahn     return {ElementCount::getFixed(1), 0, 0};
2085a34b3abSFrancesco Petrogalli   }
209e21ed594SFlorian Hahn 
210e21ed594SFlorian Hahn   bool operator==(const VectorizationFactor &rhs) const {
211e21ed594SFlorian Hahn     return Width == rhs.Width && Cost == rhs.Cost;
212e21ed594SFlorian Hahn   }
213a7e2c269SBardia Mahjour 
214a7e2c269SBardia Mahjour   bool operator!=(const VectorizationFactor &rhs) const {
215a7e2c269SBardia Mahjour     return !(*this == rhs);
216a7e2c269SBardia Mahjour   }
2170f1314c5SHal Finkel };
2180f1314c5SHal Finkel 
21981fdc73eSSander de Smalen /// A class that represents two vectorization factors (initialized with 0 by
22081fdc73eSSander de Smalen /// default). One for fixed-width vectorization and one for scalable
22181fdc73eSSander de Smalen /// vectorization. This can be used by the vectorizer to choose from a range of
22281fdc73eSSander de Smalen /// fixed and/or scalable VFs in order to find the most cost-effective VF to
22381fdc73eSSander de Smalen /// vectorize with.
22481fdc73eSSander de Smalen struct FixedScalableVFPair {
22581fdc73eSSander de Smalen   ElementCount FixedVF;
22681fdc73eSSander de Smalen   ElementCount ScalableVF;
22781fdc73eSSander de Smalen 
FixedScalableVFPairFixedScalableVFPair22881fdc73eSSander de Smalen   FixedScalableVFPair()
22981fdc73eSSander de Smalen       : FixedVF(ElementCount::getFixed(0)),
23081fdc73eSSander de Smalen         ScalableVF(ElementCount::getScalable(0)) {}
FixedScalableVFPairFixedScalableVFPair23181fdc73eSSander de Smalen   FixedScalableVFPair(const ElementCount &Max) : FixedScalableVFPair() {
23281fdc73eSSander de Smalen     *(Max.isScalable() ? &ScalableVF : &FixedVF) = Max;
23381fdc73eSSander de Smalen   }
FixedScalableVFPairFixedScalableVFPair23481fdc73eSSander de Smalen   FixedScalableVFPair(const ElementCount &FixedVF,
23581fdc73eSSander de Smalen                       const ElementCount &ScalableVF)
23681fdc73eSSander de Smalen       : FixedVF(FixedVF), ScalableVF(ScalableVF) {
23781fdc73eSSander de Smalen     assert(!FixedVF.isScalable() && ScalableVF.isScalable() &&
23881fdc73eSSander de Smalen            "Invalid scalable properties");
23981fdc73eSSander de Smalen   }
24081fdc73eSSander de Smalen 
getNoneFixedScalableVFPair24181fdc73eSSander de Smalen   static FixedScalableVFPair getNone() { return FixedScalableVFPair(); }
24281fdc73eSSander de Smalen 
24381fdc73eSSander de Smalen   /// \return true if either fixed- or scalable VF is non-zero.
24481fdc73eSSander de Smalen   explicit operator bool() const { return FixedVF || ScalableVF; }
24581fdc73eSSander de Smalen 
24681fdc73eSSander de Smalen   /// \return true if either fixed- or scalable VF is a valid vector VF.
hasVectorFixedScalableVFPair24781fdc73eSSander de Smalen   bool hasVector() const { return FixedVF.isVector() || ScalableVF.isVector(); }
24881fdc73eSSander de Smalen };
24981fdc73eSSander de Smalen 
2500f1314c5SHal Finkel /// Planner drives the vectorization process after having passed
2510f1314c5SHal Finkel /// Legality checks.
2520f1314c5SHal Finkel class LoopVectorizationPlanner {
2530f1314c5SHal Finkel   /// The loop that we evaluate.
2540f1314c5SHal Finkel   Loop *OrigLoop;
2550f1314c5SHal Finkel 
2560f1314c5SHal Finkel   /// Loop Info analysis.
2570f1314c5SHal Finkel   LoopInfo *LI;
2580f1314c5SHal Finkel 
2590f1314c5SHal Finkel   /// Target Library Info.
2600f1314c5SHal Finkel   const TargetLibraryInfo *TLI;
2610f1314c5SHal Finkel 
2620f1314c5SHal Finkel   /// Target Transform Info.
2630f1314c5SHal Finkel   const TargetTransformInfo *TTI;
2640f1314c5SHal Finkel 
2650f1314c5SHal Finkel   /// The legality analysis.
2660f1314c5SHal Finkel   LoopVectorizationLegality *Legal;
2670f1314c5SHal Finkel 
2689bbdde25SFlorian Hahn   /// The profitability analysis.
2690f1314c5SHal Finkel   LoopVectorizationCostModel &CM;
2700f1314c5SHal Finkel 
2717f152543SGil Rapaport   /// The interleaved access analysis.
2727f152543SGil Rapaport   InterleavedAccessInfo &IAI;
2737f152543SGil Rapaport 
27418138e02SFlorian Hahn   PredicatedScalarEvolution &PSE;
27518138e02SFlorian Hahn 
276c773d0f9SFlorian Hahn   const LoopVectorizeHints &Hints;
277c773d0f9SFlorian Hahn 
278c773d0f9SFlorian Hahn   OptimizationRemarkEmitter *ORE;
279c773d0f9SFlorian Hahn 
2800f1314c5SHal Finkel   SmallVector<VPlanPtr, 4> VPlans;
2810f1314c5SHal Finkel 
2820f1314c5SHal Finkel   /// A builder used to construct the current plan.
2830f1314c5SHal Finkel   VPBuilder Builder;
2840f1314c5SHal Finkel 
2850f1314c5SHal Finkel public:
LoopVectorizationPlanner(Loop * L,LoopInfo * LI,const TargetLibraryInfo * TLI,const TargetTransformInfo * TTI,LoopVectorizationLegality * Legal,LoopVectorizationCostModel & CM,InterleavedAccessInfo & IAI,PredicatedScalarEvolution & PSE,const LoopVectorizeHints & Hints,OptimizationRemarkEmitter * ORE)2860f1314c5SHal Finkel   LoopVectorizationPlanner(Loop *L, LoopInfo *LI, const TargetLibraryInfo *TLI,
2870f1314c5SHal Finkel                            const TargetTransformInfo *TTI,
2880f1314c5SHal Finkel                            LoopVectorizationLegality *Legal,
2897f152543SGil Rapaport                            LoopVectorizationCostModel &CM,
29018138e02SFlorian Hahn                            InterleavedAccessInfo &IAI,
291c773d0f9SFlorian Hahn                            PredicatedScalarEvolution &PSE,
292c773d0f9SFlorian Hahn                            const LoopVectorizeHints &Hints,
293c773d0f9SFlorian Hahn                            OptimizationRemarkEmitter *ORE)
29418138e02SFlorian Hahn       : OrigLoop(L), LI(LI), TLI(TLI), TTI(TTI), Legal(Legal), CM(CM), IAI(IAI),
295644a965cSFlorian Hahn         PSE(PSE), Hints(Hints), ORE(ORE) {}
2960f1314c5SHal Finkel 
297ba5acbc4SFlorian Hahn   /// Plan how to best vectorize, return the best VF and its cost, or None if
298ba5acbc4SFlorian Hahn   /// vectorization and interleaving should be avoided up front.
2995a34b3abSFrancesco Petrogalli   Optional<VectorizationFactor> plan(ElementCount UserVF, unsigned UserIC);
3000f1314c5SHal Finkel 
30160f2776bSDiego Caballero   /// Use the VPlan-native path to plan how to best vectorize, return the best
30260f2776bSDiego Caballero   /// VF and its cost.
3035a34b3abSFrancesco Petrogalli   VectorizationFactor planInVPlanNativePath(ElementCount UserVF);
30460f2776bSDiego Caballero 
3053d706c20SDavid Sherwood   /// Return the best VPlan for \p VF.
3063d706c20SDavid Sherwood   VPlan &getBestPlanFor(ElementCount VF) const;
3070f1314c5SHal Finkel 
3080f1314c5SHal Finkel   /// Generate the IR code for the body of the vectorized loop according to the
3093d706c20SDavid Sherwood   /// best selected \p VF, \p UF and VPlan \p BestPlan.
3100dddf04cSFlorian Hahn   /// TODO: \p IsEpilogueVectorization is needed to avoid issues due to epilogue
3110dddf04cSFlorian Hahn   /// vectorization re-using plans for both the main and epilogue vector loops.
3120dddf04cSFlorian Hahn   /// It should be removed once the re-use issue has been fixed.
3133d706c20SDavid Sherwood   void executePlan(ElementCount VF, unsigned UF, VPlan &BestPlan,
3140dddf04cSFlorian Hahn                    InnerLoopVectorizer &LB, DominatorTree *DT,
3150dddf04cSFlorian Hahn                    bool IsEpilogueVectorization);
3160f1314c5SHal Finkel 
31792205cb2SAndrei Elovikov #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
31893a9d2deSAndrei Elovikov   void printPlans(raw_ostream &O);
31992205cb2SAndrei Elovikov #endif
3200f1314c5SHal Finkel 
321a7e2c269SBardia Mahjour   /// Look through the existing plans and return true if we have one with all
322a7e2c269SBardia Mahjour   /// the vectorization factors in question.
hasPlanWithVF(ElementCount VF)323c42bb30bSDavid Sherwood   bool hasPlanWithVF(ElementCount VF) const {
324c42bb30bSDavid Sherwood     return any_of(VPlans,
325c42bb30bSDavid Sherwood                   [&](const VPlanPtr &Plan) { return Plan->hasVF(VF); });
326a7e2c269SBardia Mahjour   }
327a7e2c269SBardia Mahjour 
32845e5d5b4SFlorian Hahn   /// Test a \p Predicate on a \p Range of VF's. Return the value of applying
32945e5d5b4SFlorian Hahn   /// \p Predicate on Range.Start, possibly decreasing Range.End such that the
33045e5d5b4SFlorian Hahn   /// returned value holds for the entire \p Range.
33145e5d5b4SFlorian Hahn   static bool
3325a34b3abSFrancesco Petrogalli   getDecisionAndClampRange(const std::function<bool(ElementCount)> &Predicate,
33345e5d5b4SFlorian Hahn                            VFRange &Range);
33445e5d5b4SFlorian Hahn 
3353ed9f603STiehu Zhang   /// Check if the number of runtime checks exceeds the threshold.
3363ed9f603STiehu Zhang   bool requiresTooManyRuntimeChecks() const;
3373ed9f603STiehu Zhang 
3380f1314c5SHal Finkel protected:
3390f1314c5SHal Finkel   /// Build VPlans for power-of-2 VF's between \p MinVF and \p MaxVF inclusive,
3400f1314c5SHal Finkel   /// according to the information gathered by Legal when it checked if it is
3410f1314c5SHal Finkel   /// legal to vectorize the loop.
342f47573f9SSander de Smalen   void buildVPlans(ElementCount MinVF, ElementCount MaxVF);
3430f1314c5SHal Finkel 
3440f1314c5SHal Finkel private:
3450f1314c5SHal Finkel   /// Build a VPlan according to the information gathered by Legal. \return a
3460f1314c5SHal Finkel   /// VPlan for vectorization factors \p Range.Start and up to \p Range.End
3470f1314c5SHal Finkel   /// exclusive, possibly decreasing \p Range.End.
348b3c6f07dSFlorian Hahn   VPlanPtr buildVPlan(VFRange &Range);
349b3c6f07dSFlorian Hahn 
350b3c6f07dSFlorian Hahn   /// Build a VPlan using VPRecipes according to the information gather by
351b3c6f07dSFlorian Hahn   /// Legal. This method is only used for the legacy inner loop vectorizer.
352a911fef3SFlorian Hahn   VPlanPtr buildVPlanWithVPRecipes(
353e0c479cdSDavid Green       VFRange &Range, SmallPtrSetImpl<Instruction *> &DeadInstructions,
354aa00b1d7SFlorian Hahn       const MapVector<Instruction *, Instruction *> &SinkAfter);
355b3c6f07dSFlorian Hahn 
356b3c6f07dSFlorian Hahn   /// Build VPlans for power-of-2 VF's between \p MinVF and \p MaxVF inclusive,
357b3c6f07dSFlorian Hahn   /// according to the information gathered by Legal when it checked if it is
358b3c6f07dSFlorian Hahn   /// legal to vectorize the loop. This method creates VPlans using VPRecipes.
359f47573f9SSander de Smalen   void buildVPlansWithVPRecipes(ElementCount MinVF, ElementCount MaxVF);
360745bf6cfSDavid Green 
361a00aafc3SFlorian Hahn   // Adjust the recipes for reductions. For in-loop reductions the chain of
362a00aafc3SFlorian Hahn   // instructions leading from the loop exit instr to the phi need to be
363a00aafc3SFlorian Hahn   // converted to reductions, with one operand being vector and the other being
364a00aafc3SFlorian Hahn   // the scalar reduction chain. For other reductions, a select is introduced
365a00aafc3SFlorian Hahn   // between the phi and live-out recipes when folding the tail.
366a00aafc3SFlorian Hahn   void adjustRecipesForReductions(VPBasicBlock *LatchVPBB, VPlanPtr &Plan,
367f9967256SKerry McLaughlin                                   VPRecipeBuilder &RecipeBuilder,
368f9967256SKerry McLaughlin                                   ElementCount MinVF);
3690f1314c5SHal Finkel };
3700f1314c5SHal Finkel 
3710f1314c5SHal Finkel } // namespace llvm
3720f1314c5SHal Finkel 
3730f1314c5SHal Finkel #endif // LLVM_TRANSFORMS_VECTORIZE_LOOPVECTORIZATIONPLANNER_H
374