xref: /freebsd/contrib/llvm-project/llvm/lib/Transforms/Vectorize/VPlan.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- VPlan.h - Represent A Vectorizer Plan --------------------*- 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 /// \file
100b57cec5SDimitry Andric /// This file contains the declarations of the Vectorization Plan base classes:
110b57cec5SDimitry Andric /// 1. VPBasicBlock and VPRegionBlock that inherit from a common pure virtual
120b57cec5SDimitry Andric ///    VPBlockBase, together implementing a Hierarchical CFG;
13bdd1243dSDimitry Andric /// 2. Pure virtual VPRecipeBase serving as the base class for recipes contained
140b57cec5SDimitry Andric ///    within VPBasicBlocks;
157a6dacacSDimitry Andric /// 3. Pure virtual VPSingleDefRecipe serving as a base class for recipes that
167a6dacacSDimitry Andric ///    also inherit from VPValue.
177a6dacacSDimitry Andric /// 4. VPInstruction, a concrete Recipe and VPUser modeling a single planned
180b57cec5SDimitry Andric ///    instruction;
197a6dacacSDimitry Andric /// 5. The VPlan class holding a candidate for vectorization;
207a6dacacSDimitry Andric /// 6. The VPlanPrinter class providing a way to print a plan in dot format;
210b57cec5SDimitry Andric /// These are documented in docs/VectorizationPlan.rst.
220b57cec5SDimitry Andric //
230b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric #ifndef LLVM_TRANSFORMS_VECTORIZE_VPLAN_H
260b57cec5SDimitry Andric #define LLVM_TRANSFORMS_VECTORIZE_VPLAN_H
270b57cec5SDimitry Andric 
285f757f3fSDimitry Andric #include "VPlanAnalysis.h"
290b57cec5SDimitry Andric #include "VPlanValue.h"
300b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
3181ad6265SDimitry Andric #include "llvm/ADT/MapVector.h"
32480093f4SDimitry Andric #include "llvm/ADT/SmallBitVector.h"
330b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
340b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
350b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
360b57cec5SDimitry Andric #include "llvm/ADT/ilist.h"
370b57cec5SDimitry Andric #include "llvm/ADT/ilist_node.h"
38*0fca6ea1SDimitry Andric #include "llvm/Analysis/DomTreeUpdater.h"
3906c3fb27SDimitry Andric #include "llvm/Analysis/IVDescriptors.h"
4081ad6265SDimitry Andric #include "llvm/Analysis/LoopInfo.h"
410b57cec5SDimitry Andric #include "llvm/Analysis/VectorUtils.h"
420eae32dcSDimitry Andric #include "llvm/IR/DebugLoc.h"
4381ad6265SDimitry Andric #include "llvm/IR/FMF.h"
4406c3fb27SDimitry Andric #include "llvm/IR/Operator.h"
45*0fca6ea1SDimitry Andric #include "llvm/Support/InstructionCost.h"
460b57cec5SDimitry Andric #include <algorithm>
470b57cec5SDimitry Andric #include <cassert>
480b57cec5SDimitry Andric #include <cstddef>
490b57cec5SDimitry Andric #include <string>
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric namespace llvm {
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric class BasicBlock;
540b57cec5SDimitry Andric class DominatorTree;
550b57cec5SDimitry Andric class InnerLoopVectorizer;
5681ad6265SDimitry Andric class IRBuilderBase;
570b57cec5SDimitry Andric class LoopInfo;
580b57cec5SDimitry Andric class raw_ostream;
59e8d8bef9SDimitry Andric class RecurrenceDescriptor;
60bdd1243dSDimitry Andric class SCEV;
61bdd1243dSDimitry Andric class Type;
620b57cec5SDimitry Andric class VPBasicBlock;
630b57cec5SDimitry Andric class VPRegionBlock;
640b57cec5SDimitry Andric class VPlan;
654824e7fdSDimitry Andric class VPReplicateRecipe;
660b57cec5SDimitry Andric class VPlanSlp;
67bdd1243dSDimitry Andric class Value;
68*0fca6ea1SDimitry Andric class LoopVectorizationCostModel;
6906c3fb27SDimitry Andric class LoopVersioning;
70bdd1243dSDimitry Andric 
71*0fca6ea1SDimitry Andric struct VPCostContext;
72*0fca6ea1SDimitry Andric 
73bdd1243dSDimitry Andric namespace Intrinsic {
74bdd1243dSDimitry Andric typedef unsigned ID;
75bdd1243dSDimitry Andric }
760b57cec5SDimitry Andric 
77fe6060f1SDimitry Andric /// Returns a calculation for the total number of elements for a given \p VF.
78fe6060f1SDimitry Andric /// For fixed width vectors this value is a constant, whereas for scalable
79fe6060f1SDimitry Andric /// vectors it is an expression determined at runtime.
8081ad6265SDimitry Andric Value *getRuntimeVF(IRBuilderBase &B, Type *Ty, ElementCount VF);
81fe6060f1SDimitry Andric 
8204eeddc0SDimitry Andric /// Return a value for Step multiplied by VF.
8381ad6265SDimitry Andric Value *createStepForVF(IRBuilderBase &B, Type *Ty, ElementCount VF,
8481ad6265SDimitry Andric                        int64_t Step);
8504eeddc0SDimitry Andric 
8606c3fb27SDimitry Andric const SCEV *createTripCountSCEV(Type *IdxTy, PredicatedScalarEvolution &PSE,
8706c3fb27SDimitry Andric                                 Loop *CurLoop = nullptr);
88bdd1243dSDimitry Andric 
89*0fca6ea1SDimitry Andric /// A helper function that returns the reciprocal of the block probability of
90*0fca6ea1SDimitry Andric /// predicated blocks. If we return X, we are assuming the predicated block
91*0fca6ea1SDimitry Andric /// will execute once for every X iterations of the loop header.
92*0fca6ea1SDimitry Andric ///
93*0fca6ea1SDimitry Andric /// TODO: We should use actual block probability here, if available. Currently,
94*0fca6ea1SDimitry Andric ///       we always assume predicated blocks have a 50% chance of executing.
getReciprocalPredBlockProb()95*0fca6ea1SDimitry Andric inline unsigned getReciprocalPredBlockProb() { return 2; }
96*0fca6ea1SDimitry Andric 
970b57cec5SDimitry Andric /// A range of powers-of-2 vectorization factors with fixed start and
980b57cec5SDimitry Andric /// adjustable end. The range includes start and excludes end, e.g.,:
9906c3fb27SDimitry Andric /// [1, 16) = {1, 2, 4, 8}
1000b57cec5SDimitry Andric struct VFRange {
1010b57cec5SDimitry Andric   // A power of 2.
102e8d8bef9SDimitry Andric   const ElementCount Start;
1030b57cec5SDimitry Andric 
10406c3fb27SDimitry Andric   // A power of 2. If End <= Start range is empty.
105e8d8bef9SDimitry Andric   ElementCount End;
106e8d8bef9SDimitry Andric 
isEmptyVFRange107e8d8bef9SDimitry Andric   bool isEmpty() const {
108e8d8bef9SDimitry Andric     return End.getKnownMinValue() <= Start.getKnownMinValue();
109e8d8bef9SDimitry Andric   }
110e8d8bef9SDimitry Andric 
VFRangeVFRange111e8d8bef9SDimitry Andric   VFRange(const ElementCount &Start, const ElementCount &End)
112e8d8bef9SDimitry Andric       : Start(Start), End(End) {
113e8d8bef9SDimitry Andric     assert(Start.isScalable() == End.isScalable() &&
114e8d8bef9SDimitry Andric            "Both Start and End should have the same scalable flag");
115e8d8bef9SDimitry Andric     assert(isPowerOf2_32(Start.getKnownMinValue()) &&
116e8d8bef9SDimitry Andric            "Expected Start to be a power of 2");
11706c3fb27SDimitry Andric     assert(isPowerOf2_32(End.getKnownMinValue()) &&
11806c3fb27SDimitry Andric            "Expected End to be a power of 2");
11906c3fb27SDimitry Andric   }
12006c3fb27SDimitry Andric 
12106c3fb27SDimitry Andric   /// Iterator to iterate over vectorization factors in a VFRange.
12206c3fb27SDimitry Andric   class iterator
12306c3fb27SDimitry Andric       : public iterator_facade_base<iterator, std::forward_iterator_tag,
12406c3fb27SDimitry Andric                                     ElementCount> {
12506c3fb27SDimitry Andric     ElementCount VF;
12606c3fb27SDimitry Andric 
12706c3fb27SDimitry Andric   public:
iteratorVFRange12806c3fb27SDimitry Andric     iterator(ElementCount VF) : VF(VF) {}
12906c3fb27SDimitry Andric 
13006c3fb27SDimitry Andric     bool operator==(const iterator &Other) const { return VF == Other.VF; }
13106c3fb27SDimitry Andric 
13206c3fb27SDimitry Andric     ElementCount operator*() const { return VF; }
13306c3fb27SDimitry Andric 
13406c3fb27SDimitry Andric     iterator &operator++() {
13506c3fb27SDimitry Andric       VF *= 2;
13606c3fb27SDimitry Andric       return *this;
13706c3fb27SDimitry Andric     }
13806c3fb27SDimitry Andric   };
13906c3fb27SDimitry Andric 
beginVFRange14006c3fb27SDimitry Andric   iterator begin() { return iterator(Start); }
endVFRange14106c3fb27SDimitry Andric   iterator end() {
14206c3fb27SDimitry Andric     assert(isPowerOf2_32(End.getKnownMinValue()));
14306c3fb27SDimitry Andric     return iterator(End);
144e8d8bef9SDimitry Andric   }
1450b57cec5SDimitry Andric };
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric using VPlanPtr = std::unique_ptr<VPlan>;
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric /// In what follows, the term "input IR" refers to code that is fed into the
1500b57cec5SDimitry Andric /// vectorizer whereas the term "output IR" refers to code that is generated by
1510b57cec5SDimitry Andric /// the vectorizer.
1520b57cec5SDimitry Andric 
153fe6060f1SDimitry Andric /// VPLane provides a way to access lanes in both fixed width and scalable
154fe6060f1SDimitry Andric /// vectors, where for the latter the lane index sometimes needs calculating
155fe6060f1SDimitry Andric /// as a runtime expression.
156fe6060f1SDimitry Andric class VPLane {
157fe6060f1SDimitry Andric public:
158fe6060f1SDimitry Andric   /// Kind describes how to interpret Lane.
159fe6060f1SDimitry Andric   enum class Kind : uint8_t {
160fe6060f1SDimitry Andric     /// For First, Lane is the index into the first N elements of a
161fe6060f1SDimitry Andric     /// fixed-vector <N x <ElTy>> or a scalable vector <vscale x N x <ElTy>>.
162fe6060f1SDimitry Andric     First,
163fe6060f1SDimitry Andric     /// For ScalableLast, Lane is the offset from the start of the last
164fe6060f1SDimitry Andric     /// N-element subvector in a scalable vector <vscale x N x <ElTy>>. For
165fe6060f1SDimitry Andric     /// example, a Lane of 0 corresponds to lane `(vscale - 1) * N`, a Lane of
166fe6060f1SDimitry Andric     /// 1 corresponds to `((vscale - 1) * N) + 1`, etc.
167fe6060f1SDimitry Andric     ScalableLast
168fe6060f1SDimitry Andric   };
169fe6060f1SDimitry Andric 
170fe6060f1SDimitry Andric private:
171fe6060f1SDimitry Andric   /// in [0..VF)
172fe6060f1SDimitry Andric   unsigned Lane;
173fe6060f1SDimitry Andric 
174fe6060f1SDimitry Andric   /// Indicates how the Lane should be interpreted, as described above.
175fe6060f1SDimitry Andric   Kind LaneKind;
176fe6060f1SDimitry Andric 
177fe6060f1SDimitry Andric public:
VPLane(unsigned Lane,Kind LaneKind)178fe6060f1SDimitry Andric   VPLane(unsigned Lane, Kind LaneKind) : Lane(Lane), LaneKind(LaneKind) {}
179fe6060f1SDimitry Andric 
getFirstLane()180fe6060f1SDimitry Andric   static VPLane getFirstLane() { return VPLane(0, VPLane::Kind::First); }
181fe6060f1SDimitry Andric 
getLaneFromEnd(const ElementCount & VF,unsigned Offset)182*0fca6ea1SDimitry Andric   static VPLane getLaneFromEnd(const ElementCount &VF, unsigned Offset) {
183*0fca6ea1SDimitry Andric     assert(Offset > 0 && Offset <= VF.getKnownMinValue() &&
184*0fca6ea1SDimitry Andric            "trying to extract with invalid offset");
185*0fca6ea1SDimitry Andric     unsigned LaneOffset = VF.getKnownMinValue() - Offset;
186fe6060f1SDimitry Andric     Kind LaneKind;
187fe6060f1SDimitry Andric     if (VF.isScalable())
188fe6060f1SDimitry Andric       // In this case 'LaneOffset' refers to the offset from the start of the
189fe6060f1SDimitry Andric       // last subvector with VF.getKnownMinValue() elements.
190fe6060f1SDimitry Andric       LaneKind = VPLane::Kind::ScalableLast;
191fe6060f1SDimitry Andric     else
192fe6060f1SDimitry Andric       LaneKind = VPLane::Kind::First;
193fe6060f1SDimitry Andric     return VPLane(LaneOffset, LaneKind);
194fe6060f1SDimitry Andric   }
195fe6060f1SDimitry Andric 
getLastLaneForVF(const ElementCount & VF)196*0fca6ea1SDimitry Andric   static VPLane getLastLaneForVF(const ElementCount &VF) {
197*0fca6ea1SDimitry Andric     return getLaneFromEnd(VF, 1);
198*0fca6ea1SDimitry Andric   }
199*0fca6ea1SDimitry Andric 
200fe6060f1SDimitry Andric   /// Returns a compile-time known value for the lane index and asserts if the
201fe6060f1SDimitry Andric   /// lane can only be calculated at runtime.
getKnownLane()202fe6060f1SDimitry Andric   unsigned getKnownLane() const {
203fe6060f1SDimitry Andric     assert(LaneKind == Kind::First);
204fe6060f1SDimitry Andric     return Lane;
205fe6060f1SDimitry Andric   }
206fe6060f1SDimitry Andric 
207fe6060f1SDimitry Andric   /// Returns an expression describing the lane index that can be used at
208fe6060f1SDimitry Andric   /// runtime.
20981ad6265SDimitry Andric   Value *getAsRuntimeExpr(IRBuilderBase &Builder, const ElementCount &VF) const;
210fe6060f1SDimitry Andric 
211fe6060f1SDimitry Andric   /// Returns the Kind of lane offset.
getKind()212fe6060f1SDimitry Andric   Kind getKind() const { return LaneKind; }
213fe6060f1SDimitry Andric 
214fe6060f1SDimitry Andric   /// Returns true if this is the first lane of the whole vector.
isFirstLane()215fe6060f1SDimitry Andric   bool isFirstLane() const { return Lane == 0 && LaneKind == Kind::First; }
216fe6060f1SDimitry Andric 
217fe6060f1SDimitry Andric   /// Maps the lane to a cache index based on \p VF.
mapToCacheIndex(const ElementCount & VF)218fe6060f1SDimitry Andric   unsigned mapToCacheIndex(const ElementCount &VF) const {
219fe6060f1SDimitry Andric     switch (LaneKind) {
220fe6060f1SDimitry Andric     case VPLane::Kind::ScalableLast:
221fe6060f1SDimitry Andric       assert(VF.isScalable() && Lane < VF.getKnownMinValue());
222fe6060f1SDimitry Andric       return VF.getKnownMinValue() + Lane;
223fe6060f1SDimitry Andric     default:
224fe6060f1SDimitry Andric       assert(Lane < VF.getKnownMinValue());
225fe6060f1SDimitry Andric       return Lane;
226fe6060f1SDimitry Andric     }
227fe6060f1SDimitry Andric   }
228fe6060f1SDimitry Andric 
229fe6060f1SDimitry Andric   /// Returns the maxmimum number of lanes that we are able to consider
230fe6060f1SDimitry Andric   /// caching for \p VF.
getNumCachedLanes(const ElementCount & VF)231fe6060f1SDimitry Andric   static unsigned getNumCachedLanes(const ElementCount &VF) {
232fe6060f1SDimitry Andric     return VF.getKnownMinValue() * (VF.isScalable() ? 2 : 1);
233fe6060f1SDimitry Andric   }
234fe6060f1SDimitry Andric };
235fe6060f1SDimitry Andric 
2360b57cec5SDimitry Andric /// VPIteration represents a single point in the iteration space of the output
2370b57cec5SDimitry Andric /// (vectorized and/or unrolled) IR loop.
2380b57cec5SDimitry Andric struct VPIteration {
2390b57cec5SDimitry Andric   /// in [0..UF)
2400b57cec5SDimitry Andric   unsigned Part;
2410b57cec5SDimitry Andric 
242fe6060f1SDimitry Andric   VPLane Lane;
2430b57cec5SDimitry Andric 
244fe6060f1SDimitry Andric   VPIteration(unsigned Part, unsigned Lane,
245fe6060f1SDimitry Andric               VPLane::Kind Kind = VPLane::Kind::First)
PartVPIteration246fe6060f1SDimitry Andric       : Part(Part), Lane(Lane, Kind) {}
2470b57cec5SDimitry Andric 
VPIterationVPIteration248fe6060f1SDimitry Andric   VPIteration(unsigned Part, const VPLane &Lane) : Part(Part), Lane(Lane) {}
2490b57cec5SDimitry Andric 
isFirstIterationVPIteration250fe6060f1SDimitry Andric   bool isFirstIteration() const { return Part == 0 && Lane.isFirstLane(); }
2510b57cec5SDimitry Andric };
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric /// VPTransformState holds information passed down when "executing" a VPlan,
2540b57cec5SDimitry Andric /// needed for generating the output IR.
2550b57cec5SDimitry Andric struct VPTransformState {
256fe6060f1SDimitry Andric   VPTransformState(ElementCount VF, unsigned UF, LoopInfo *LI,
25781ad6265SDimitry Andric                    DominatorTree *DT, IRBuilderBase &Builder,
258*0fca6ea1SDimitry Andric                    InnerLoopVectorizer *ILV, VPlan *Plan, LLVMContext &Ctx);
2590b57cec5SDimitry Andric 
2600b57cec5SDimitry Andric   /// The chosen Vectorization and Unroll Factors of the loop being vectorized.
261e8d8bef9SDimitry Andric   ElementCount VF;
2620b57cec5SDimitry Andric   unsigned UF;
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric   /// Hold the indices to generate specific scalar instructions. Null indicates
2650b57cec5SDimitry Andric   /// that all instances are to be generated, using either scalar or vector
2660b57cec5SDimitry Andric   /// instructions.
267bdd1243dSDimitry Andric   std::optional<VPIteration> Instance;
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric   struct DataState {
2700b57cec5SDimitry Andric     /// A type for vectorized values in the new loop. Each value from the
2710b57cec5SDimitry Andric     /// original loop, when vectorized, is represented by UF vector values in
2720b57cec5SDimitry Andric     /// the new unrolled loop, where UF is the unroll factor.
2730b57cec5SDimitry Andric     typedef SmallVector<Value *, 2> PerPartValuesTy;
2740b57cec5SDimitry Andric 
2750b57cec5SDimitry Andric     DenseMap<VPValue *, PerPartValuesTy> PerPartOutput;
276e8d8bef9SDimitry Andric 
277e8d8bef9SDimitry Andric     using ScalarsPerPartValuesTy = SmallVector<SmallVector<Value *, 4>, 2>;
278e8d8bef9SDimitry Andric     DenseMap<VPValue *, ScalarsPerPartValuesTy> PerPartScalars;
2790b57cec5SDimitry Andric   } Data;
2800b57cec5SDimitry Andric 
281*0fca6ea1SDimitry Andric   /// Get the generated vector Value for a given VPValue \p Def and a given \p
282*0fca6ea1SDimitry Andric   /// Part if \p IsScalar is false, otherwise return the generated scalar
283*0fca6ea1SDimitry Andric   /// for \p Part. \See set.
284*0fca6ea1SDimitry Andric   Value *get(VPValue *Def, unsigned Part, bool IsScalar = false);
2850b57cec5SDimitry Andric 
2865ffd83dbSDimitry Andric   /// Get the generated Value for a given VPValue and given Part and Lane.
287e8d8bef9SDimitry Andric   Value *get(VPValue *Def, const VPIteration &Instance);
288e8d8bef9SDimitry Andric 
hasVectorValueVPTransformState289e8d8bef9SDimitry Andric   bool hasVectorValue(VPValue *Def, unsigned Part) {
290e8d8bef9SDimitry Andric     auto I = Data.PerPartOutput.find(Def);
291e8d8bef9SDimitry Andric     return I != Data.PerPartOutput.end() && Part < I->second.size() &&
292e8d8bef9SDimitry Andric            I->second[Part];
2935ffd83dbSDimitry Andric   }
2945ffd83dbSDimitry Andric 
hasScalarValueVPTransformState295e8d8bef9SDimitry Andric   bool hasScalarValue(VPValue *Def, VPIteration Instance) {
296e8d8bef9SDimitry Andric     auto I = Data.PerPartScalars.find(Def);
297e8d8bef9SDimitry Andric     if (I == Data.PerPartScalars.end())
298e8d8bef9SDimitry Andric       return false;
299fe6060f1SDimitry Andric     unsigned CacheIdx = Instance.Lane.mapToCacheIndex(VF);
300e8d8bef9SDimitry Andric     return Instance.Part < I->second.size() &&
301fe6060f1SDimitry Andric            CacheIdx < I->second[Instance.Part].size() &&
302fe6060f1SDimitry Andric            I->second[Instance.Part][CacheIdx];
303480093f4SDimitry Andric   }
304480093f4SDimitry Andric 
305*0fca6ea1SDimitry Andric   /// Set the generated vector Value for a given VPValue and a given Part, if \p
306*0fca6ea1SDimitry Andric   /// IsScalar is false. If \p IsScalar is true, set the scalar in (Part, 0).
307*0fca6ea1SDimitry Andric   void set(VPValue *Def, Value *V, unsigned Part, bool IsScalar = false) {
308*0fca6ea1SDimitry Andric     if (IsScalar) {
309*0fca6ea1SDimitry Andric       set(Def, V, VPIteration(Part, 0));
310*0fca6ea1SDimitry Andric       return;
311*0fca6ea1SDimitry Andric     }
312*0fca6ea1SDimitry Andric     assert((VF.isScalar() || V->getType()->isVectorTy()) &&
313*0fca6ea1SDimitry Andric            "scalar values must be stored as (Part, 0)");
3140b57cec5SDimitry Andric     if (!Data.PerPartOutput.count(Def)) {
3150b57cec5SDimitry Andric       DataState::PerPartValuesTy Entry(UF);
3160b57cec5SDimitry Andric       Data.PerPartOutput[Def] = Entry;
3170b57cec5SDimitry Andric     }
3180b57cec5SDimitry Andric     Data.PerPartOutput[Def][Part] = V;
3190b57cec5SDimitry Andric   }
320*0fca6ea1SDimitry Andric 
321fe6060f1SDimitry Andric   /// Reset an existing vector value for \p Def and a given \p Part.
resetVPTransformState322fe6060f1SDimitry Andric   void reset(VPValue *Def, Value *V, unsigned Part) {
323fe6060f1SDimitry Andric     auto Iter = Data.PerPartOutput.find(Def);
324fe6060f1SDimitry Andric     assert(Iter != Data.PerPartOutput.end() &&
325fe6060f1SDimitry Andric            "need to overwrite existing value");
326fe6060f1SDimitry Andric     Iter->second[Part] = V;
327fe6060f1SDimitry Andric   }
328e8d8bef9SDimitry Andric 
329fe6060f1SDimitry Andric   /// Set the generated scalar \p V for \p Def and the given \p Instance.
setVPTransformState330e8d8bef9SDimitry Andric   void set(VPValue *Def, Value *V, const VPIteration &Instance) {
331e8d8bef9SDimitry Andric     auto Iter = Data.PerPartScalars.insert({Def, {}});
332e8d8bef9SDimitry Andric     auto &PerPartVec = Iter.first->second;
333*0fca6ea1SDimitry Andric     if (PerPartVec.size() <= Instance.Part)
334*0fca6ea1SDimitry Andric       PerPartVec.resize(Instance.Part + 1);
335e8d8bef9SDimitry Andric     auto &Scalars = PerPartVec[Instance.Part];
336fe6060f1SDimitry Andric     unsigned CacheIdx = Instance.Lane.mapToCacheIndex(VF);
337*0fca6ea1SDimitry Andric     if (Scalars.size() <= CacheIdx)
338*0fca6ea1SDimitry Andric       Scalars.resize(CacheIdx + 1);
339fe6060f1SDimitry Andric     assert(!Scalars[CacheIdx] && "should overwrite existing value");
340fe6060f1SDimitry Andric     Scalars[CacheIdx] = V;
341fe6060f1SDimitry Andric   }
342fe6060f1SDimitry Andric 
343fe6060f1SDimitry Andric   /// Reset an existing scalar value for \p Def and a given \p Instance.
resetVPTransformState344fe6060f1SDimitry Andric   void reset(VPValue *Def, Value *V, const VPIteration &Instance) {
345fe6060f1SDimitry Andric     auto Iter = Data.PerPartScalars.find(Def);
346fe6060f1SDimitry Andric     assert(Iter != Data.PerPartScalars.end() &&
347fe6060f1SDimitry Andric            "need to overwrite existing value");
348fe6060f1SDimitry Andric     assert(Instance.Part < Iter->second.size() &&
349fe6060f1SDimitry Andric            "need to overwrite existing value");
350fe6060f1SDimitry Andric     unsigned CacheIdx = Instance.Lane.mapToCacheIndex(VF);
351fe6060f1SDimitry Andric     assert(CacheIdx < Iter->second[Instance.Part].size() &&
352fe6060f1SDimitry Andric            "need to overwrite existing value");
353fe6060f1SDimitry Andric     Iter->second[Instance.Part][CacheIdx] = V;
354e8d8bef9SDimitry Andric   }
3550b57cec5SDimitry Andric 
35681ad6265SDimitry Andric   /// Add additional metadata to \p To that was not present on \p Orig.
35781ad6265SDimitry Andric   ///
35881ad6265SDimitry Andric   /// Currently this is used to add the noalias annotations based on the
35981ad6265SDimitry Andric   /// inserted memchecks.  Use this for instructions that are *cloned* into the
36081ad6265SDimitry Andric   /// vector loop.
36181ad6265SDimitry Andric   void addNewMetadata(Instruction *To, const Instruction *Orig);
36281ad6265SDimitry Andric 
36381ad6265SDimitry Andric   /// Add metadata from one instruction to another.
36481ad6265SDimitry Andric   ///
36581ad6265SDimitry Andric   /// This includes both the original MDs from \p From and additional ones (\see
36681ad6265SDimitry Andric   /// addNewMetadata).  Use this for *newly created* instructions in the vector
36781ad6265SDimitry Andric   /// loop.
368*0fca6ea1SDimitry Andric   void addMetadata(Value *To, Instruction *From);
36981ad6265SDimitry Andric 
3705f757f3fSDimitry Andric   /// Set the debug location in the builder using the debug location \p DL.
3715f757f3fSDimitry Andric   void setDebugLocFrom(DebugLoc DL);
3725f757f3fSDimitry Andric 
3735f757f3fSDimitry Andric   /// Construct the vector value of a scalarized value \p V one lane at a time.
3745f757f3fSDimitry Andric   void packScalarIntoVectorValue(VPValue *Def, const VPIteration &Instance);
37581ad6265SDimitry Andric 
3760b57cec5SDimitry Andric   /// Hold state information used when constructing the CFG of the output IR,
3770b57cec5SDimitry Andric   /// traversing the VPBasicBlocks and generating corresponding IR BasicBlocks.
3780b57cec5SDimitry Andric   struct CFGState {
3790b57cec5SDimitry Andric     /// The previous VPBasicBlock visited. Initially set to null.
3800b57cec5SDimitry Andric     VPBasicBlock *PrevVPBB = nullptr;
3810b57cec5SDimitry Andric 
3820b57cec5SDimitry Andric     /// The previous IR BasicBlock created or used. Initially set to the new
3830b57cec5SDimitry Andric     /// header BasicBlock.
3840b57cec5SDimitry Andric     BasicBlock *PrevBB = nullptr;
3850b57cec5SDimitry Andric 
38681ad6265SDimitry Andric     /// The last IR BasicBlock in the output IR. Set to the exit block of the
38781ad6265SDimitry Andric     /// vector loop.
38881ad6265SDimitry Andric     BasicBlock *ExitBB = nullptr;
389fe6060f1SDimitry Andric 
3900b57cec5SDimitry Andric     /// A mapping of each VPBasicBlock to the corresponding BasicBlock. In case
3910b57cec5SDimitry Andric     /// of replication, maps the BasicBlock of the last replica created.
3920b57cec5SDimitry Andric     SmallDenseMap<VPBasicBlock *, BasicBlock *> VPBB2IRBB;
3930b57cec5SDimitry Andric 
394*0fca6ea1SDimitry Andric     /// Updater for the DominatorTree.
395*0fca6ea1SDimitry Andric     DomTreeUpdater DTU;
396*0fca6ea1SDimitry Andric 
CFGStateVPTransformState::CFGState397*0fca6ea1SDimitry Andric     CFGState(DominatorTree *DT)
398*0fca6ea1SDimitry Andric         : DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy) {}
39981ad6265SDimitry Andric 
40081ad6265SDimitry Andric     /// Returns the BasicBlock* mapped to the pre-header of the loop region
40181ad6265SDimitry Andric     /// containing \p R.
40281ad6265SDimitry Andric     BasicBlock *getPreheaderBBFor(VPRecipeBase *R);
4030b57cec5SDimitry Andric   } CFG;
4040b57cec5SDimitry Andric 
4050b57cec5SDimitry Andric   /// Hold a pointer to LoopInfo to register new basic blocks in the loop.
4060b57cec5SDimitry Andric   LoopInfo *LI;
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric   /// Hold a reference to the IRBuilder used to generate output IR code.
40981ad6265SDimitry Andric   IRBuilderBase &Builder;
4100b57cec5SDimitry Andric 
4110b57cec5SDimitry Andric   /// Hold a pointer to InnerLoopVectorizer to reuse its IR generation methods.
4120b57cec5SDimitry Andric   InnerLoopVectorizer *ILV;
4130b57cec5SDimitry Andric 
414fe6060f1SDimitry Andric   /// Pointer to the VPlan code is generated for.
415fe6060f1SDimitry Andric   VPlan *Plan;
4164824e7fdSDimitry Andric 
41781ad6265SDimitry Andric   /// The loop object for the current parent region, or nullptr.
41881ad6265SDimitry Andric   Loop *CurrentVectorLoop = nullptr;
419fe6060f1SDimitry Andric 
42081ad6265SDimitry Andric   /// LoopVersioning.  It's only set up (non-null) if memchecks were
42181ad6265SDimitry Andric   /// used.
42281ad6265SDimitry Andric   ///
42381ad6265SDimitry Andric   /// This is currently only used to add no-alias metadata based on the
42481ad6265SDimitry Andric   /// memchecks.  The actually versioning is performed manually.
42506c3fb27SDimitry Andric   LoopVersioning *LVer = nullptr;
42606c3fb27SDimitry Andric 
42706c3fb27SDimitry Andric   /// Map SCEVs to their expanded values. Populated when executing
42806c3fb27SDimitry Andric   /// VPExpandSCEVRecipes.
42906c3fb27SDimitry Andric   DenseMap<const SCEV *, Value *> ExpandedSCEVs;
4305f757f3fSDimitry Andric 
4315f757f3fSDimitry Andric   /// VPlan-based type analysis.
4325f757f3fSDimitry Andric   VPTypeAnalysis TypeAnalysis;
4330b57cec5SDimitry Andric };
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric /// VPBlockBase is the building block of the Hierarchical Control-Flow Graph.
4360b57cec5SDimitry Andric /// A VPBlockBase can be either a VPBasicBlock or a VPRegionBlock.
4370b57cec5SDimitry Andric class VPBlockBase {
4380b57cec5SDimitry Andric   friend class VPBlockUtils;
4390b57cec5SDimitry Andric 
4400b57cec5SDimitry Andric   const unsigned char SubclassID; ///< Subclass identifier (for isa/dyn_cast).
4410b57cec5SDimitry Andric 
4420b57cec5SDimitry Andric   /// An optional name for the block.
4430b57cec5SDimitry Andric   std::string Name;
4440b57cec5SDimitry Andric 
4450b57cec5SDimitry Andric   /// The immediate VPRegionBlock which this VPBlockBase belongs to, or null if
4460b57cec5SDimitry Andric   /// it is a topmost VPBlockBase.
4470b57cec5SDimitry Andric   VPRegionBlock *Parent = nullptr;
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric   /// List of predecessor blocks.
4500b57cec5SDimitry Andric   SmallVector<VPBlockBase *, 1> Predecessors;
4510b57cec5SDimitry Andric 
4520b57cec5SDimitry Andric   /// List of successor blocks.
4530b57cec5SDimitry Andric   SmallVector<VPBlockBase *, 1> Successors;
4540b57cec5SDimitry Andric 
4555ffd83dbSDimitry Andric   /// VPlan containing the block. Can only be set on the entry block of the
4565ffd83dbSDimitry Andric   /// plan.
4575ffd83dbSDimitry Andric   VPlan *Plan = nullptr;
4585ffd83dbSDimitry Andric 
4590b57cec5SDimitry Andric   /// Add \p Successor as the last successor to this block.
appendSuccessor(VPBlockBase * Successor)4600b57cec5SDimitry Andric   void appendSuccessor(VPBlockBase *Successor) {
4610b57cec5SDimitry Andric     assert(Successor && "Cannot add nullptr successor!");
4620b57cec5SDimitry Andric     Successors.push_back(Successor);
4630b57cec5SDimitry Andric   }
4640b57cec5SDimitry Andric 
4650b57cec5SDimitry Andric   /// Add \p Predecessor as the last predecessor to this block.
appendPredecessor(VPBlockBase * Predecessor)4660b57cec5SDimitry Andric   void appendPredecessor(VPBlockBase *Predecessor) {
4670b57cec5SDimitry Andric     assert(Predecessor && "Cannot add nullptr predecessor!");
4680b57cec5SDimitry Andric     Predecessors.push_back(Predecessor);
4690b57cec5SDimitry Andric   }
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric   /// Remove \p Predecessor from the predecessors of this block.
removePredecessor(VPBlockBase * Predecessor)4720b57cec5SDimitry Andric   void removePredecessor(VPBlockBase *Predecessor) {
473e8d8bef9SDimitry Andric     auto Pos = find(Predecessors, Predecessor);
4740b57cec5SDimitry Andric     assert(Pos && "Predecessor does not exist");
4750b57cec5SDimitry Andric     Predecessors.erase(Pos);
4760b57cec5SDimitry Andric   }
4770b57cec5SDimitry Andric 
4780b57cec5SDimitry Andric   /// Remove \p Successor from the successors of this block.
removeSuccessor(VPBlockBase * Successor)4790b57cec5SDimitry Andric   void removeSuccessor(VPBlockBase *Successor) {
480e8d8bef9SDimitry Andric     auto Pos = find(Successors, Successor);
4810b57cec5SDimitry Andric     assert(Pos && "Successor does not exist");
4820b57cec5SDimitry Andric     Successors.erase(Pos);
4830b57cec5SDimitry Andric   }
4840b57cec5SDimitry Andric 
4850b57cec5SDimitry Andric protected:
VPBlockBase(const unsigned char SC,const std::string & N)4860b57cec5SDimitry Andric   VPBlockBase(const unsigned char SC, const std::string &N)
4870b57cec5SDimitry Andric       : SubclassID(SC), Name(N) {}
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric public:
4900b57cec5SDimitry Andric   /// An enumeration for keeping track of the concrete subclass of VPBlockBase
4910b57cec5SDimitry Andric   /// that are actually instantiated. Values of this enumeration are kept in the
4920b57cec5SDimitry Andric   /// SubclassID field of the VPBlockBase objects. They are used for concrete
4930b57cec5SDimitry Andric   /// type identification.
494*0fca6ea1SDimitry Andric   using VPBlockTy = enum { VPRegionBlockSC, VPBasicBlockSC, VPIRBasicBlockSC };
4950b57cec5SDimitry Andric 
4960b57cec5SDimitry Andric   using VPBlocksTy = SmallVectorImpl<VPBlockBase *>;
4970b57cec5SDimitry Andric 
4980b57cec5SDimitry Andric   virtual ~VPBlockBase() = default;
4990b57cec5SDimitry Andric 
getName()5000b57cec5SDimitry Andric   const std::string &getName() const { return Name; }
5010b57cec5SDimitry Andric 
setName(const Twine & newName)5020b57cec5SDimitry Andric   void setName(const Twine &newName) { Name = newName.str(); }
5030b57cec5SDimitry Andric 
5040b57cec5SDimitry Andric   /// \return an ID for the concrete type of this object.
5050b57cec5SDimitry Andric   /// This is used to implement the classof checks. This should not be used
5060b57cec5SDimitry Andric   /// for any other purpose, as the values may change as LLVM evolves.
getVPBlockID()5070b57cec5SDimitry Andric   unsigned getVPBlockID() const { return SubclassID; }
5080b57cec5SDimitry Andric 
getParent()5090b57cec5SDimitry Andric   VPRegionBlock *getParent() { return Parent; }
getParent()5100b57cec5SDimitry Andric   const VPRegionBlock *getParent() const { return Parent; }
5110b57cec5SDimitry Andric 
5125ffd83dbSDimitry Andric   /// \return A pointer to the plan containing the current block.
5135ffd83dbSDimitry Andric   VPlan *getPlan();
5145ffd83dbSDimitry Andric   const VPlan *getPlan() const;
5155ffd83dbSDimitry Andric 
5165ffd83dbSDimitry Andric   /// Sets the pointer of the plan containing the block. The block must be the
5175ffd83dbSDimitry Andric   /// entry block into the VPlan.
5185ffd83dbSDimitry Andric   void setPlan(VPlan *ParentPlan);
5195ffd83dbSDimitry Andric 
setParent(VPRegionBlock * P)5200b57cec5SDimitry Andric   void setParent(VPRegionBlock *P) { Parent = P; }
5210b57cec5SDimitry Andric 
5220b57cec5SDimitry Andric   /// \return the VPBasicBlock that is the entry of this VPBlockBase,
5230b57cec5SDimitry Andric   /// recursively, if the latter is a VPRegionBlock. Otherwise, if this
5240b57cec5SDimitry Andric   /// VPBlockBase is a VPBasicBlock, it is returned.
5250b57cec5SDimitry Andric   const VPBasicBlock *getEntryBasicBlock() const;
5260b57cec5SDimitry Andric   VPBasicBlock *getEntryBasicBlock();
5270b57cec5SDimitry Andric 
52881ad6265SDimitry Andric   /// \return the VPBasicBlock that is the exiting this VPBlockBase,
5290b57cec5SDimitry Andric   /// recursively, if the latter is a VPRegionBlock. Otherwise, if this
5300b57cec5SDimitry Andric   /// VPBlockBase is a VPBasicBlock, it is returned.
53181ad6265SDimitry Andric   const VPBasicBlock *getExitingBasicBlock() const;
53281ad6265SDimitry Andric   VPBasicBlock *getExitingBasicBlock();
5330b57cec5SDimitry Andric 
getSuccessors()5340b57cec5SDimitry Andric   const VPBlocksTy &getSuccessors() const { return Successors; }
getSuccessors()5350b57cec5SDimitry Andric   VPBlocksTy &getSuccessors() { return Successors; }
5360b57cec5SDimitry Andric 
successors()5370eae32dcSDimitry Andric   iterator_range<VPBlockBase **> successors() { return Successors; }
5380eae32dcSDimitry Andric 
getPredecessors()5390b57cec5SDimitry Andric   const VPBlocksTy &getPredecessors() const { return Predecessors; }
getPredecessors()5400b57cec5SDimitry Andric   VPBlocksTy &getPredecessors() { return Predecessors; }
5410b57cec5SDimitry Andric 
5420b57cec5SDimitry Andric   /// \return the successor of this VPBlockBase if it has a single successor.
5430b57cec5SDimitry Andric   /// Otherwise return a null pointer.
getSingleSuccessor()5440b57cec5SDimitry Andric   VPBlockBase *getSingleSuccessor() const {
5450b57cec5SDimitry Andric     return (Successors.size() == 1 ? *Successors.begin() : nullptr);
5460b57cec5SDimitry Andric   }
5470b57cec5SDimitry Andric 
5480b57cec5SDimitry Andric   /// \return the predecessor of this VPBlockBase if it has a single
5490b57cec5SDimitry Andric   /// predecessor. Otherwise return a null pointer.
getSinglePredecessor()5500b57cec5SDimitry Andric   VPBlockBase *getSinglePredecessor() const {
5510b57cec5SDimitry Andric     return (Predecessors.size() == 1 ? *Predecessors.begin() : nullptr);
5520b57cec5SDimitry Andric   }
5530b57cec5SDimitry Andric 
getNumSuccessors()5540b57cec5SDimitry Andric   size_t getNumSuccessors() const { return Successors.size(); }
getNumPredecessors()5550b57cec5SDimitry Andric   size_t getNumPredecessors() const { return Predecessors.size(); }
5560b57cec5SDimitry Andric 
5570b57cec5SDimitry Andric   /// An Enclosing Block of a block B is any block containing B, including B
5580b57cec5SDimitry Andric   /// itself. \return the closest enclosing block starting from "this", which
5590b57cec5SDimitry Andric   /// has successors. \return the root enclosing block if all enclosing blocks
5600b57cec5SDimitry Andric   /// have no successors.
5610b57cec5SDimitry Andric   VPBlockBase *getEnclosingBlockWithSuccessors();
5620b57cec5SDimitry Andric 
5630b57cec5SDimitry Andric   /// \return the closest enclosing block starting from "this", which has
5640b57cec5SDimitry Andric   /// predecessors. \return the root enclosing block if all enclosing blocks
5650b57cec5SDimitry Andric   /// have no predecessors.
5660b57cec5SDimitry Andric   VPBlockBase *getEnclosingBlockWithPredecessors();
5670b57cec5SDimitry Andric 
5680b57cec5SDimitry Andric   /// \return the successors either attached directly to this VPBlockBase or, if
5690b57cec5SDimitry Andric   /// this VPBlockBase is the exit block of a VPRegionBlock and has no
5700b57cec5SDimitry Andric   /// successors of its own, search recursively for the first enclosing
5710b57cec5SDimitry Andric   /// VPRegionBlock that has successors and return them. If no such
5720b57cec5SDimitry Andric   /// VPRegionBlock exists, return the (empty) successors of the topmost
5730b57cec5SDimitry Andric   /// VPBlockBase reached.
getHierarchicalSuccessors()5740b57cec5SDimitry Andric   const VPBlocksTy &getHierarchicalSuccessors() {
5750b57cec5SDimitry Andric     return getEnclosingBlockWithSuccessors()->getSuccessors();
5760b57cec5SDimitry Andric   }
5770b57cec5SDimitry Andric 
5780b57cec5SDimitry Andric   /// \return the hierarchical successor of this VPBlockBase if it has a single
5790b57cec5SDimitry Andric   /// hierarchical successor. Otherwise return a null pointer.
getSingleHierarchicalSuccessor()5800b57cec5SDimitry Andric   VPBlockBase *getSingleHierarchicalSuccessor() {
5810b57cec5SDimitry Andric     return getEnclosingBlockWithSuccessors()->getSingleSuccessor();
5820b57cec5SDimitry Andric   }
5830b57cec5SDimitry Andric 
5840b57cec5SDimitry Andric   /// \return the predecessors either attached directly to this VPBlockBase or,
5850b57cec5SDimitry Andric   /// if this VPBlockBase is the entry block of a VPRegionBlock and has no
5860b57cec5SDimitry Andric   /// predecessors of its own, search recursively for the first enclosing
5870b57cec5SDimitry Andric   /// VPRegionBlock that has predecessors and return them. If no such
5880b57cec5SDimitry Andric   /// VPRegionBlock exists, return the (empty) predecessors of the topmost
5890b57cec5SDimitry Andric   /// VPBlockBase reached.
getHierarchicalPredecessors()5900b57cec5SDimitry Andric   const VPBlocksTy &getHierarchicalPredecessors() {
5910b57cec5SDimitry Andric     return getEnclosingBlockWithPredecessors()->getPredecessors();
5920b57cec5SDimitry Andric   }
5930b57cec5SDimitry Andric 
5940b57cec5SDimitry Andric   /// \return the hierarchical predecessor of this VPBlockBase if it has a
5950b57cec5SDimitry Andric   /// single hierarchical predecessor. Otherwise return a null pointer.
getSingleHierarchicalPredecessor()5960b57cec5SDimitry Andric   VPBlockBase *getSingleHierarchicalPredecessor() {
5970b57cec5SDimitry Andric     return getEnclosingBlockWithPredecessors()->getSinglePredecessor();
5980b57cec5SDimitry Andric   }
5990b57cec5SDimitry Andric 
6000b57cec5SDimitry Andric   /// Set a given VPBlockBase \p Successor as the single successor of this
6010b57cec5SDimitry Andric   /// VPBlockBase. This VPBlockBase is not added as predecessor of \p Successor.
6020b57cec5SDimitry Andric   /// This VPBlockBase must have no successors.
setOneSuccessor(VPBlockBase * Successor)6030b57cec5SDimitry Andric   void setOneSuccessor(VPBlockBase *Successor) {
6040b57cec5SDimitry Andric     assert(Successors.empty() && "Setting one successor when others exist.");
6055f757f3fSDimitry Andric     assert(Successor->getParent() == getParent() &&
6065f757f3fSDimitry Andric            "connected blocks must have the same parent");
6070b57cec5SDimitry Andric     appendSuccessor(Successor);
6080b57cec5SDimitry Andric   }
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric   /// Set two given VPBlockBases \p IfTrue and \p IfFalse to be the two
61181ad6265SDimitry Andric   /// successors of this VPBlockBase. This VPBlockBase is not added as
61281ad6265SDimitry Andric   /// predecessor of \p IfTrue or \p IfFalse. This VPBlockBase must have no
61381ad6265SDimitry Andric   /// successors.
setTwoSuccessors(VPBlockBase * IfTrue,VPBlockBase * IfFalse)61481ad6265SDimitry Andric   void setTwoSuccessors(VPBlockBase *IfTrue, VPBlockBase *IfFalse) {
6150b57cec5SDimitry Andric     assert(Successors.empty() && "Setting two successors when others exist.");
6160b57cec5SDimitry Andric     appendSuccessor(IfTrue);
6170b57cec5SDimitry Andric     appendSuccessor(IfFalse);
6180b57cec5SDimitry Andric   }
6190b57cec5SDimitry Andric 
6200b57cec5SDimitry Andric   /// Set each VPBasicBlock in \p NewPreds as predecessor of this VPBlockBase.
6210b57cec5SDimitry Andric   /// This VPBlockBase must have no predecessors. This VPBlockBase is not added
6220b57cec5SDimitry Andric   /// as successor of any VPBasicBlock in \p NewPreds.
setPredecessors(ArrayRef<VPBlockBase * > NewPreds)6230b57cec5SDimitry Andric   void setPredecessors(ArrayRef<VPBlockBase *> NewPreds) {
6240b57cec5SDimitry Andric     assert(Predecessors.empty() && "Block predecessors already set.");
6250b57cec5SDimitry Andric     for (auto *Pred : NewPreds)
6260b57cec5SDimitry Andric       appendPredecessor(Pred);
6270b57cec5SDimitry Andric   }
6280b57cec5SDimitry Andric 
629*0fca6ea1SDimitry Andric   /// Set each VPBasicBlock in \p NewSuccss as successor of this VPBlockBase.
630*0fca6ea1SDimitry Andric   /// This VPBlockBase must have no successors. This VPBlockBase is not added
631*0fca6ea1SDimitry Andric   /// as predecessor of any VPBasicBlock in \p NewSuccs.
setSuccessors(ArrayRef<VPBlockBase * > NewSuccs)632*0fca6ea1SDimitry Andric   void setSuccessors(ArrayRef<VPBlockBase *> NewSuccs) {
633*0fca6ea1SDimitry Andric     assert(Successors.empty() && "Block successors already set.");
634*0fca6ea1SDimitry Andric     for (auto *Succ : NewSuccs)
635*0fca6ea1SDimitry Andric       appendSuccessor(Succ);
636*0fca6ea1SDimitry Andric   }
637*0fca6ea1SDimitry Andric 
6380b57cec5SDimitry Andric   /// Remove all the predecessor of this block.
clearPredecessors()6390b57cec5SDimitry Andric   void clearPredecessors() { Predecessors.clear(); }
6400b57cec5SDimitry Andric 
64181ad6265SDimitry Andric   /// Remove all the successors of this block.
clearSuccessors()64281ad6265SDimitry Andric   void clearSuccessors() { Successors.clear(); }
6430b57cec5SDimitry Andric 
6440b57cec5SDimitry Andric   /// The method which generates the output IR that correspond to this
6450b57cec5SDimitry Andric   /// VPBlockBase, thereby "executing" the VPlan.
646bdd1243dSDimitry Andric   virtual void execute(VPTransformState *State) = 0;
6470b57cec5SDimitry Andric 
648*0fca6ea1SDimitry Andric   /// Return the cost of the block.
649*0fca6ea1SDimitry Andric   virtual InstructionCost cost(ElementCount VF, VPCostContext &Ctx) = 0;
650*0fca6ea1SDimitry Andric 
6510b57cec5SDimitry Andric   /// Delete all blocks reachable from a given VPBlockBase, inclusive.
6520b57cec5SDimitry Andric   static void deleteCFG(VPBlockBase *Entry);
6530b57cec5SDimitry Andric 
6540b57cec5SDimitry Andric   /// Return true if it is legal to hoist instructions into this block.
isLegalToHoistInto()6550b57cec5SDimitry Andric   bool isLegalToHoistInto() {
6560b57cec5SDimitry Andric     // There are currently no constraints that prevent an instruction to be
6570b57cec5SDimitry Andric     // hoisted into a VPBlockBase.
6580b57cec5SDimitry Andric     return true;
6590b57cec5SDimitry Andric   }
660e8d8bef9SDimitry Andric 
661e8d8bef9SDimitry Andric   /// Replace all operands of VPUsers in the block with \p NewValue and also
662e8d8bef9SDimitry Andric   /// replaces all uses of VPValues defined in the block with NewValue.
663e8d8bef9SDimitry Andric   virtual void dropAllReferences(VPValue *NewValue) = 0;
664fe6060f1SDimitry Andric 
665fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
printAsOperand(raw_ostream & OS,bool PrintType)666fe6060f1SDimitry Andric   void printAsOperand(raw_ostream &OS, bool PrintType) const {
667fe6060f1SDimitry Andric     OS << getName();
668fe6060f1SDimitry Andric   }
669fe6060f1SDimitry Andric 
670fe6060f1SDimitry Andric   /// Print plain-text dump of this VPBlockBase to \p O, prefixing all lines
671fe6060f1SDimitry Andric   /// with \p Indent. \p SlotTracker is used to print unnamed VPValue's using
672fe6060f1SDimitry Andric   /// consequtive numbers.
673fe6060f1SDimitry Andric   ///
674fe6060f1SDimitry Andric   /// Note that the numbering is applied to the whole VPlan, so printing
675fe6060f1SDimitry Andric   /// individual blocks is consistent with the whole VPlan printing.
676fe6060f1SDimitry Andric   virtual void print(raw_ostream &O, const Twine &Indent,
677fe6060f1SDimitry Andric                      VPSlotTracker &SlotTracker) const = 0;
678fe6060f1SDimitry Andric 
679fe6060f1SDimitry Andric   /// Print plain-text dump of this VPlan to \p O.
print(raw_ostream & O)680fe6060f1SDimitry Andric   void print(raw_ostream &O) const {
681fe6060f1SDimitry Andric     VPSlotTracker SlotTracker(getPlan());
682fe6060f1SDimitry Andric     print(O, "", SlotTracker);
683fe6060f1SDimitry Andric   }
684fe6060f1SDimitry Andric 
685fe6060f1SDimitry Andric   /// Print the successors of this block to \p O, prefixing all lines with \p
686fe6060f1SDimitry Andric   /// Indent.
687fe6060f1SDimitry Andric   void printSuccessors(raw_ostream &O, const Twine &Indent) const;
688fe6060f1SDimitry Andric 
689fe6060f1SDimitry Andric   /// Dump this VPBlockBase to dbgs().
dump()690fe6060f1SDimitry Andric   LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
691fe6060f1SDimitry Andric #endif
692*0fca6ea1SDimitry Andric 
693*0fca6ea1SDimitry Andric   /// Clone the current block and it's recipes without updating the operands of
694*0fca6ea1SDimitry Andric   /// the cloned recipes, including all blocks in the single-entry single-exit
695*0fca6ea1SDimitry Andric   /// region for VPRegionBlocks.
696*0fca6ea1SDimitry Andric   virtual VPBlockBase *clone() = 0;
6970b57cec5SDimitry Andric };
6980b57cec5SDimitry Andric 
69981ad6265SDimitry Andric /// A value that is used outside the VPlan. The operand of the user needs to be
700*0fca6ea1SDimitry Andric /// added to the associated phi node. The incoming block from VPlan is
701*0fca6ea1SDimitry Andric /// determined by where the VPValue is defined: if it is defined by a recipe
702*0fca6ea1SDimitry Andric /// outside a region, its parent block is used, otherwise the middle block is
703*0fca6ea1SDimitry Andric /// used.
70481ad6265SDimitry Andric class VPLiveOut : public VPUser {
70581ad6265SDimitry Andric   PHINode *Phi;
70681ad6265SDimitry Andric 
70781ad6265SDimitry Andric public:
VPLiveOut(PHINode * Phi,VPValue * Op)70881ad6265SDimitry Andric   VPLiveOut(PHINode *Phi, VPValue *Op)
70981ad6265SDimitry Andric       : VPUser({Op}, VPUser::VPUserID::LiveOut), Phi(Phi) {}
71081ad6265SDimitry Andric 
classof(const VPUser * U)71106c3fb27SDimitry Andric   static inline bool classof(const VPUser *U) {
71206c3fb27SDimitry Andric     return U->getVPUserID() == VPUser::VPUserID::LiveOut;
71306c3fb27SDimitry Andric   }
71406c3fb27SDimitry Andric 
715*0fca6ea1SDimitry Andric   /// Fix the wrapped phi node. This means adding an incoming value to exit
716*0fca6ea1SDimitry Andric   /// block phi's from the vector loop via middle block (values from scalar loop
717*0fca6ea1SDimitry Andric   /// already reach these phi's), and updating the value to scalar header phi's
718*0fca6ea1SDimitry Andric   /// from the scalar preheader.
71981ad6265SDimitry Andric   void fixPhi(VPlan &Plan, VPTransformState &State);
72081ad6265SDimitry Andric 
72181ad6265SDimitry Andric   /// Returns true if the VPLiveOut uses scalars of operand \p Op.
usesScalars(const VPValue * Op)72281ad6265SDimitry Andric   bool usesScalars(const VPValue *Op) const override {
72381ad6265SDimitry Andric     assert(is_contained(operands(), Op) &&
72481ad6265SDimitry Andric            "Op must be an operand of the recipe");
72581ad6265SDimitry Andric     return true;
72681ad6265SDimitry Andric   }
72781ad6265SDimitry Andric 
getPhi()72881ad6265SDimitry Andric   PHINode *getPhi() const { return Phi; }
72906c3fb27SDimitry Andric 
73006c3fb27SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
73106c3fb27SDimitry Andric   /// Print the VPLiveOut to \p O.
73206c3fb27SDimitry Andric   void print(raw_ostream &O, VPSlotTracker &SlotTracker) const;
73306c3fb27SDimitry Andric #endif
73481ad6265SDimitry Andric };
73581ad6265SDimitry Andric 
736*0fca6ea1SDimitry Andric /// Struct to hold various analysis needed for cost computations.
737*0fca6ea1SDimitry Andric struct VPCostContext {
738*0fca6ea1SDimitry Andric   const TargetTransformInfo &TTI;
739*0fca6ea1SDimitry Andric   VPTypeAnalysis Types;
740*0fca6ea1SDimitry Andric   LLVMContext &LLVMCtx;
741*0fca6ea1SDimitry Andric   LoopVectorizationCostModel &CM;
742*0fca6ea1SDimitry Andric   SmallPtrSet<Instruction *, 8> SkipCostComputation;
743*0fca6ea1SDimitry Andric 
VPCostContextVPCostContext744*0fca6ea1SDimitry Andric   VPCostContext(const TargetTransformInfo &TTI, Type *CanIVTy,
745*0fca6ea1SDimitry Andric                 LLVMContext &LLVMCtx, LoopVectorizationCostModel &CM)
746*0fca6ea1SDimitry Andric       : TTI(TTI), Types(CanIVTy, LLVMCtx), LLVMCtx(LLVMCtx), CM(CM) {}
747*0fca6ea1SDimitry Andric 
748*0fca6ea1SDimitry Andric   /// Return the cost for \p UI with \p VF using the legacy cost model as
749*0fca6ea1SDimitry Andric   /// fallback until computing the cost of all recipes migrates to VPlan.
750*0fca6ea1SDimitry Andric   InstructionCost getLegacyCost(Instruction *UI, ElementCount VF) const;
751*0fca6ea1SDimitry Andric 
752*0fca6ea1SDimitry Andric   /// Return true if the cost for \p UI shouldn't be computed, e.g. because it
753*0fca6ea1SDimitry Andric   /// has already been pre-computed.
754*0fca6ea1SDimitry Andric   bool skipCostComputation(Instruction *UI, bool IsVector) const;
755*0fca6ea1SDimitry Andric };
756*0fca6ea1SDimitry Andric 
7570b57cec5SDimitry Andric /// VPRecipeBase is a base class modeling a sequence of one or more output IR
7585f757f3fSDimitry Andric /// instructions. VPRecipeBase owns the VPValues it defines through VPDef
759e8d8bef9SDimitry Andric /// and is responsible for deleting its defined values. Single-value
7607a6dacacSDimitry Andric /// recipes must inherit from VPSingleDef instead of inheriting from both
7617a6dacacSDimitry Andric /// VPRecipeBase and VPValue separately.
762e8d8bef9SDimitry Andric class VPRecipeBase : public ilist_node_with_parent<VPRecipeBase, VPBasicBlock>,
763fe6060f1SDimitry Andric                      public VPDef,
764fe6060f1SDimitry Andric                      public VPUser {
7650b57cec5SDimitry Andric   friend VPBasicBlock;
766480093f4SDimitry Andric   friend class VPBlockUtils;
7670b57cec5SDimitry Andric 
7680b57cec5SDimitry Andric   /// Each VPRecipe belongs to a single VPBasicBlock.
7690b57cec5SDimitry Andric   VPBasicBlock *Parent = nullptr;
7700b57cec5SDimitry Andric 
7715f757f3fSDimitry Andric   /// The debug location for the recipe.
7725f757f3fSDimitry Andric   DebugLoc DL;
7735f757f3fSDimitry Andric 
7740b57cec5SDimitry Andric public:
7755f757f3fSDimitry Andric   VPRecipeBase(const unsigned char SC, ArrayRef<VPValue *> Operands,
7765f757f3fSDimitry Andric                DebugLoc DL = {})
VPDef(SC)7775f757f3fSDimitry Andric       : VPDef(SC), VPUser(Operands, VPUser::VPUserID::Recipe), DL(DL) {}
778fe6060f1SDimitry Andric 
779fe6060f1SDimitry Andric   template <typename IterT>
7805f757f3fSDimitry Andric   VPRecipeBase(const unsigned char SC, iterator_range<IterT> Operands,
7815f757f3fSDimitry Andric                DebugLoc DL = {})
VPDef(SC)7825f757f3fSDimitry Andric       : VPDef(SC), VPUser(Operands, VPUser::VPUserID::Recipe), DL(DL) {}
7830b57cec5SDimitry Andric   virtual ~VPRecipeBase() = default;
7840b57cec5SDimitry Andric 
785*0fca6ea1SDimitry Andric   /// Clone the current recipe.
786*0fca6ea1SDimitry Andric   virtual VPRecipeBase *clone() = 0;
787*0fca6ea1SDimitry Andric 
7880b57cec5SDimitry Andric   /// \return the VPBasicBlock which this VPRecipe belongs to.
getParent()7890b57cec5SDimitry Andric   VPBasicBlock *getParent() { return Parent; }
getParent()7900b57cec5SDimitry Andric   const VPBasicBlock *getParent() const { return Parent; }
7910b57cec5SDimitry Andric 
7920b57cec5SDimitry Andric   /// The method which generates the output IR instructions that correspond to
7930b57cec5SDimitry Andric   /// this VPRecipe, thereby "executing" the VPlan.
794bdd1243dSDimitry Andric   virtual void execute(VPTransformState &State) = 0;
7950b57cec5SDimitry Andric 
796*0fca6ea1SDimitry Andric   /// Return the cost of this recipe, taking into account if the cost
797*0fca6ea1SDimitry Andric   /// computation should be skipped and the ForceTargetInstructionCost flag.
798*0fca6ea1SDimitry Andric   /// Also takes care of printing the cost for debugging.
799*0fca6ea1SDimitry Andric   virtual InstructionCost cost(ElementCount VF, VPCostContext &Ctx);
800*0fca6ea1SDimitry Andric 
8010b57cec5SDimitry Andric   /// Insert an unlinked recipe into a basic block immediately before
8020b57cec5SDimitry Andric   /// the specified recipe.
8030b57cec5SDimitry Andric   void insertBefore(VPRecipeBase *InsertPos);
80481ad6265SDimitry Andric   /// Insert an unlinked recipe into \p BB immediately before the insertion
80581ad6265SDimitry Andric   /// point \p IP;
80681ad6265SDimitry Andric   void insertBefore(VPBasicBlock &BB, iplist<VPRecipeBase>::iterator IP);
8070b57cec5SDimitry Andric 
808480093f4SDimitry Andric   /// Insert an unlinked Recipe into a basic block immediately after
809480093f4SDimitry Andric   /// the specified Recipe.
810480093f4SDimitry Andric   void insertAfter(VPRecipeBase *InsertPos);
811480093f4SDimitry Andric 
8128bcb0991SDimitry Andric   /// Unlink this recipe from its current VPBasicBlock and insert it into
8138bcb0991SDimitry Andric   /// the VPBasicBlock that MovePos lives in, right after MovePos.
8148bcb0991SDimitry Andric   void moveAfter(VPRecipeBase *MovePos);
8158bcb0991SDimitry Andric 
816e8d8bef9SDimitry Andric   /// Unlink this recipe and insert into BB before I.
817e8d8bef9SDimitry Andric   ///
818e8d8bef9SDimitry Andric   /// \pre I is a valid iterator into BB.
819e8d8bef9SDimitry Andric   void moveBefore(VPBasicBlock &BB, iplist<VPRecipeBase>::iterator I);
820e8d8bef9SDimitry Andric 
821480093f4SDimitry Andric   /// This method unlinks 'this' from the containing basic block, but does not
822480093f4SDimitry Andric   /// delete it.
823480093f4SDimitry Andric   void removeFromParent();
824480093f4SDimitry Andric 
8250b57cec5SDimitry Andric   /// This method unlinks 'this' from the containing basic block and deletes it.
8260b57cec5SDimitry Andric   ///
8270b57cec5SDimitry Andric   /// \returns an iterator pointing to the element after the erased one
8280b57cec5SDimitry Andric   iplist<VPRecipeBase>::iterator eraseFromParent();
829e8d8bef9SDimitry Andric 
830e8d8bef9SDimitry Andric   /// Method to support type inquiry through isa, cast, and dyn_cast.
classof(const VPDef * D)831e8d8bef9SDimitry Andric   static inline bool classof(const VPDef *D) {
832e8d8bef9SDimitry Andric     // All VPDefs are also VPRecipeBases.
833e8d8bef9SDimitry Andric     return true;
834e8d8bef9SDimitry Andric   }
835fe6060f1SDimitry Andric 
classof(const VPUser * U)836fe6060f1SDimitry Andric   static inline bool classof(const VPUser *U) {
837fe6060f1SDimitry Andric     return U->getVPUserID() == VPUser::VPUserID::Recipe;
838fe6060f1SDimitry Andric   }
839fe6060f1SDimitry Andric 
840fe6060f1SDimitry Andric   /// Returns true if the recipe may have side-effects.
841fe6060f1SDimitry Andric   bool mayHaveSideEffects() const;
842fe6060f1SDimitry Andric 
843fe6060f1SDimitry Andric   /// Returns true for PHI-like recipes.
isPhi()844fe6060f1SDimitry Andric   bool isPhi() const {
845fe6060f1SDimitry Andric     return getVPDefID() >= VPFirstPHISC && getVPDefID() <= VPLastPHISC;
846fe6060f1SDimitry Andric   }
847fe6060f1SDimitry Andric 
848fe6060f1SDimitry Andric   /// Returns true if the recipe may read from memory.
849fe6060f1SDimitry Andric   bool mayReadFromMemory() const;
850fe6060f1SDimitry Andric 
851fe6060f1SDimitry Andric   /// Returns true if the recipe may write to memory.
852fe6060f1SDimitry Andric   bool mayWriteToMemory() const;
853fe6060f1SDimitry Andric 
854fe6060f1SDimitry Andric   /// Returns true if the recipe may read from or write to memory.
mayReadOrWriteMemory()855fe6060f1SDimitry Andric   bool mayReadOrWriteMemory() const {
856fe6060f1SDimitry Andric     return mayReadFromMemory() || mayWriteToMemory();
857fe6060f1SDimitry Andric   }
8585f757f3fSDimitry Andric 
8595f757f3fSDimitry Andric   /// Returns the debug location of the recipe.
getDebugLoc()8605f757f3fSDimitry Andric   DebugLoc getDebugLoc() const { return DL; }
861*0fca6ea1SDimitry Andric 
862*0fca6ea1SDimitry Andric protected:
863*0fca6ea1SDimitry Andric   /// Compute the cost of this recipe using the legacy cost model and the
864*0fca6ea1SDimitry Andric   /// underlying instructions.
865*0fca6ea1SDimitry Andric   InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const;
8660b57cec5SDimitry Andric };
8670b57cec5SDimitry Andric 
868bdd1243dSDimitry Andric // Helper macro to define common classof implementations for recipes.
869bdd1243dSDimitry Andric #define VP_CLASSOF_IMPL(VPDefID)                                               \
870bdd1243dSDimitry Andric   static inline bool classof(const VPDef *D) {                                 \
871bdd1243dSDimitry Andric     return D->getVPDefID() == VPDefID;                                         \
872bdd1243dSDimitry Andric   }                                                                            \
873bdd1243dSDimitry Andric   static inline bool classof(const VPValue *V) {                               \
874bdd1243dSDimitry Andric     auto *R = V->getDefiningRecipe();                                          \
875bdd1243dSDimitry Andric     return R && R->getVPDefID() == VPDefID;                                    \
876bdd1243dSDimitry Andric   }                                                                            \
877bdd1243dSDimitry Andric   static inline bool classof(const VPUser *U) {                                \
878bdd1243dSDimitry Andric     auto *R = dyn_cast<VPRecipeBase>(U);                                       \
879bdd1243dSDimitry Andric     return R && R->getVPDefID() == VPDefID;                                    \
880bdd1243dSDimitry Andric   }                                                                            \
881bdd1243dSDimitry Andric   static inline bool classof(const VPRecipeBase *R) {                          \
882bdd1243dSDimitry Andric     return R->getVPDefID() == VPDefID;                                         \
8837a6dacacSDimitry Andric   }                                                                            \
8847a6dacacSDimitry Andric   static inline bool classof(const VPSingleDefRecipe *R) {                     \
8857a6dacacSDimitry Andric     return R->getVPDefID() == VPDefID;                                         \
886e8d8bef9SDimitry Andric   }
887e8d8bef9SDimitry Andric 
8887a6dacacSDimitry Andric /// VPSingleDef is a base class for recipes for modeling a sequence of one or
8897a6dacacSDimitry Andric /// more output IR that define a single result VPValue.
8907a6dacacSDimitry Andric /// Note that VPRecipeBase must be inherited from before VPValue.
8917a6dacacSDimitry Andric class VPSingleDefRecipe : public VPRecipeBase, public VPValue {
8927a6dacacSDimitry Andric public:
8937a6dacacSDimitry Andric   template <typename IterT>
8947a6dacacSDimitry Andric   VPSingleDefRecipe(const unsigned char SC, IterT Operands, DebugLoc DL = {})
VPRecipeBase(SC,Operands,DL)8957a6dacacSDimitry Andric       : VPRecipeBase(SC, Operands, DL), VPValue(this) {}
8967a6dacacSDimitry Andric 
8977a6dacacSDimitry Andric   VPSingleDefRecipe(const unsigned char SC, ArrayRef<VPValue *> Operands,
8987a6dacacSDimitry Andric                     DebugLoc DL = {})
VPRecipeBase(SC,Operands,DL)8997a6dacacSDimitry Andric       : VPRecipeBase(SC, Operands, DL), VPValue(this) {}
9007a6dacacSDimitry Andric 
9017a6dacacSDimitry Andric   template <typename IterT>
9027a6dacacSDimitry Andric   VPSingleDefRecipe(const unsigned char SC, IterT Operands, Value *UV,
9037a6dacacSDimitry Andric                     DebugLoc DL = {})
VPRecipeBase(SC,Operands,DL)9047a6dacacSDimitry Andric       : VPRecipeBase(SC, Operands, DL), VPValue(this, UV) {}
9057a6dacacSDimitry Andric 
classof(const VPRecipeBase * R)9067a6dacacSDimitry Andric   static inline bool classof(const VPRecipeBase *R) {
9077a6dacacSDimitry Andric     switch (R->getVPDefID()) {
9087a6dacacSDimitry Andric     case VPRecipeBase::VPDerivedIVSC:
909*0fca6ea1SDimitry Andric     case VPRecipeBase::VPEVLBasedIVPHISC:
9107a6dacacSDimitry Andric     case VPRecipeBase::VPExpandSCEVSC:
9117a6dacacSDimitry Andric     case VPRecipeBase::VPInstructionSC:
912*0fca6ea1SDimitry Andric     case VPRecipeBase::VPReductionEVLSC:
9137a6dacacSDimitry Andric     case VPRecipeBase::VPReductionSC:
9147a6dacacSDimitry Andric     case VPRecipeBase::VPReplicateSC:
9157a6dacacSDimitry Andric     case VPRecipeBase::VPScalarIVStepsSC:
9167a6dacacSDimitry Andric     case VPRecipeBase::VPVectorPointerSC:
9177a6dacacSDimitry Andric     case VPRecipeBase::VPWidenCallSC:
9187a6dacacSDimitry Andric     case VPRecipeBase::VPWidenCanonicalIVSC:
9197a6dacacSDimitry Andric     case VPRecipeBase::VPWidenCastSC:
9207a6dacacSDimitry Andric     case VPRecipeBase::VPWidenGEPSC:
9217a6dacacSDimitry Andric     case VPRecipeBase::VPWidenSC:
9227a6dacacSDimitry Andric     case VPRecipeBase::VPWidenSelectSC:
9237a6dacacSDimitry Andric     case VPRecipeBase::VPBlendSC:
9247a6dacacSDimitry Andric     case VPRecipeBase::VPPredInstPHISC:
9257a6dacacSDimitry Andric     case VPRecipeBase::VPCanonicalIVPHISC:
9267a6dacacSDimitry Andric     case VPRecipeBase::VPActiveLaneMaskPHISC:
9277a6dacacSDimitry Andric     case VPRecipeBase::VPFirstOrderRecurrencePHISC:
9287a6dacacSDimitry Andric     case VPRecipeBase::VPWidenPHISC:
9297a6dacacSDimitry Andric     case VPRecipeBase::VPWidenIntOrFpInductionSC:
9307a6dacacSDimitry Andric     case VPRecipeBase::VPWidenPointerInductionSC:
9317a6dacacSDimitry Andric     case VPRecipeBase::VPReductionPHISC:
932*0fca6ea1SDimitry Andric     case VPRecipeBase::VPScalarCastSC:
9337a6dacacSDimitry Andric       return true;
9347a6dacacSDimitry Andric     case VPRecipeBase::VPInterleaveSC:
9357a6dacacSDimitry Andric     case VPRecipeBase::VPBranchOnMaskSC:
936*0fca6ea1SDimitry Andric     case VPRecipeBase::VPWidenLoadEVLSC:
937*0fca6ea1SDimitry Andric     case VPRecipeBase::VPWidenLoadSC:
938*0fca6ea1SDimitry Andric     case VPRecipeBase::VPWidenStoreEVLSC:
939*0fca6ea1SDimitry Andric     case VPRecipeBase::VPWidenStoreSC:
9407a6dacacSDimitry Andric       // TODO: Widened stores don't define a value, but widened loads do. Split
9417a6dacacSDimitry Andric       // the recipes to be able to make widened loads VPSingleDefRecipes.
9427a6dacacSDimitry Andric       return false;
9437a6dacacSDimitry Andric     }
9447a6dacacSDimitry Andric     llvm_unreachable("Unhandled VPDefID");
9457a6dacacSDimitry Andric   }
9467a6dacacSDimitry Andric 
classof(const VPUser * U)9477a6dacacSDimitry Andric   static inline bool classof(const VPUser *U) {
9487a6dacacSDimitry Andric     auto *R = dyn_cast<VPRecipeBase>(U);
9497a6dacacSDimitry Andric     return R && classof(R);
9507a6dacacSDimitry Andric   }
9517a6dacacSDimitry Andric 
952*0fca6ea1SDimitry Andric   virtual VPSingleDefRecipe *clone() override = 0;
953*0fca6ea1SDimitry Andric 
9547a6dacacSDimitry Andric   /// Returns the underlying instruction.
getUnderlyingInstr()9557a6dacacSDimitry Andric   Instruction *getUnderlyingInstr() {
9567a6dacacSDimitry Andric     return cast<Instruction>(getUnderlyingValue());
9577a6dacacSDimitry Andric   }
getUnderlyingInstr()9587a6dacacSDimitry Andric   const Instruction *getUnderlyingInstr() const {
9597a6dacacSDimitry Andric     return cast<Instruction>(getUnderlyingValue());
9607a6dacacSDimitry Andric   }
9617a6dacacSDimitry Andric };
9627a6dacacSDimitry Andric 
9635f757f3fSDimitry Andric /// Class to record LLVM IR flag for a recipe along with it.
9647a6dacacSDimitry Andric class VPRecipeWithIRFlags : public VPSingleDefRecipe {
9655f757f3fSDimitry Andric   enum class OperationType : unsigned char {
9665f757f3fSDimitry Andric     Cmp,
9675f757f3fSDimitry Andric     OverflowingBinOp,
9685f757f3fSDimitry Andric     DisjointOp,
9695f757f3fSDimitry Andric     PossiblyExactOp,
9705f757f3fSDimitry Andric     GEPOp,
9715f757f3fSDimitry Andric     FPMathOp,
9725f757f3fSDimitry Andric     NonNegOp,
9735f757f3fSDimitry Andric     Other
9745f757f3fSDimitry Andric   };
9755f757f3fSDimitry Andric 
9765f757f3fSDimitry Andric public:
9775f757f3fSDimitry Andric   struct WrapFlagsTy {
9785f757f3fSDimitry Andric     char HasNUW : 1;
9795f757f3fSDimitry Andric     char HasNSW : 1;
9805f757f3fSDimitry Andric 
WrapFlagsTyWrapFlagsTy9815f757f3fSDimitry Andric     WrapFlagsTy(bool HasNUW, bool HasNSW) : HasNUW(HasNUW), HasNSW(HasNSW) {}
9825f757f3fSDimitry Andric   };
9835f757f3fSDimitry Andric 
984*0fca6ea1SDimitry Andric   struct DisjointFlagsTy {
985*0fca6ea1SDimitry Andric     char IsDisjoint : 1;
DisjointFlagsTyDisjointFlagsTy986*0fca6ea1SDimitry Andric     DisjointFlagsTy(bool IsDisjoint) : IsDisjoint(IsDisjoint) {}
987*0fca6ea1SDimitry Andric   };
988*0fca6ea1SDimitry Andric 
9891db9f3b2SDimitry Andric protected:
9901db9f3b2SDimitry Andric   struct GEPFlagsTy {
9911db9f3b2SDimitry Andric     char IsInBounds : 1;
GEPFlagsTyGEPFlagsTy9921db9f3b2SDimitry Andric     GEPFlagsTy(bool IsInBounds) : IsInBounds(IsInBounds) {}
9931db9f3b2SDimitry Andric   };
9941db9f3b2SDimitry Andric 
9955f757f3fSDimitry Andric private:
9965f757f3fSDimitry Andric   struct ExactFlagsTy {
9975f757f3fSDimitry Andric     char IsExact : 1;
9985f757f3fSDimitry Andric   };
9995f757f3fSDimitry Andric   struct NonNegFlagsTy {
10005f757f3fSDimitry Andric     char NonNeg : 1;
10015f757f3fSDimitry Andric   };
10025f757f3fSDimitry Andric   struct FastMathFlagsTy {
10035f757f3fSDimitry Andric     char AllowReassoc : 1;
10045f757f3fSDimitry Andric     char NoNaNs : 1;
10055f757f3fSDimitry Andric     char NoInfs : 1;
10065f757f3fSDimitry Andric     char NoSignedZeros : 1;
10075f757f3fSDimitry Andric     char AllowReciprocal : 1;
10085f757f3fSDimitry Andric     char AllowContract : 1;
10095f757f3fSDimitry Andric     char ApproxFunc : 1;
10105f757f3fSDimitry Andric 
10115f757f3fSDimitry Andric     FastMathFlagsTy(const FastMathFlags &FMF);
10125f757f3fSDimitry Andric   };
10135f757f3fSDimitry Andric 
10145f757f3fSDimitry Andric   OperationType OpType;
10155f757f3fSDimitry Andric 
10165f757f3fSDimitry Andric   union {
10175f757f3fSDimitry Andric     CmpInst::Predicate CmpPredicate;
10185f757f3fSDimitry Andric     WrapFlagsTy WrapFlags;
10195f757f3fSDimitry Andric     DisjointFlagsTy DisjointFlags;
10205f757f3fSDimitry Andric     ExactFlagsTy ExactFlags;
10215f757f3fSDimitry Andric     GEPFlagsTy GEPFlags;
10225f757f3fSDimitry Andric     NonNegFlagsTy NonNegFlags;
10235f757f3fSDimitry Andric     FastMathFlagsTy FMFs;
10245f757f3fSDimitry Andric     unsigned AllFlags;
10255f757f3fSDimitry Andric   };
10265f757f3fSDimitry Andric 
1027*0fca6ea1SDimitry Andric protected:
transferFlags(VPRecipeWithIRFlags & Other)1028*0fca6ea1SDimitry Andric   void transferFlags(VPRecipeWithIRFlags &Other) {
1029*0fca6ea1SDimitry Andric     OpType = Other.OpType;
1030*0fca6ea1SDimitry Andric     AllFlags = Other.AllFlags;
1031*0fca6ea1SDimitry Andric   }
1032*0fca6ea1SDimitry Andric 
10335f757f3fSDimitry Andric public:
10345f757f3fSDimitry Andric   template <typename IterT>
10355f757f3fSDimitry Andric   VPRecipeWithIRFlags(const unsigned char SC, IterT Operands, DebugLoc DL = {})
VPSingleDefRecipe(SC,Operands,DL)10367a6dacacSDimitry Andric       : VPSingleDefRecipe(SC, Operands, DL) {
10375f757f3fSDimitry Andric     OpType = OperationType::Other;
10385f757f3fSDimitry Andric     AllFlags = 0;
10395f757f3fSDimitry Andric   }
10405f757f3fSDimitry Andric 
10415f757f3fSDimitry Andric   template <typename IterT>
VPRecipeWithIRFlags(const unsigned char SC,IterT Operands,Instruction & I)10425f757f3fSDimitry Andric   VPRecipeWithIRFlags(const unsigned char SC, IterT Operands, Instruction &I)
10437a6dacacSDimitry Andric       : VPSingleDefRecipe(SC, Operands, &I, I.getDebugLoc()) {
10445f757f3fSDimitry Andric     if (auto *Op = dyn_cast<CmpInst>(&I)) {
10455f757f3fSDimitry Andric       OpType = OperationType::Cmp;
10465f757f3fSDimitry Andric       CmpPredicate = Op->getPredicate();
10475f757f3fSDimitry Andric     } else if (auto *Op = dyn_cast<PossiblyDisjointInst>(&I)) {
10485f757f3fSDimitry Andric       OpType = OperationType::DisjointOp;
10495f757f3fSDimitry Andric       DisjointFlags.IsDisjoint = Op->isDisjoint();
10505f757f3fSDimitry Andric     } else if (auto *Op = dyn_cast<OverflowingBinaryOperator>(&I)) {
10515f757f3fSDimitry Andric       OpType = OperationType::OverflowingBinOp;
10525f757f3fSDimitry Andric       WrapFlags = {Op->hasNoUnsignedWrap(), Op->hasNoSignedWrap()};
10535f757f3fSDimitry Andric     } else if (auto *Op = dyn_cast<PossiblyExactOperator>(&I)) {
10545f757f3fSDimitry Andric       OpType = OperationType::PossiblyExactOp;
10555f757f3fSDimitry Andric       ExactFlags.IsExact = Op->isExact();
10565f757f3fSDimitry Andric     } else if (auto *GEP = dyn_cast<GetElementPtrInst>(&I)) {
10575f757f3fSDimitry Andric       OpType = OperationType::GEPOp;
10585f757f3fSDimitry Andric       GEPFlags.IsInBounds = GEP->isInBounds();
10595f757f3fSDimitry Andric     } else if (auto *PNNI = dyn_cast<PossiblyNonNegInst>(&I)) {
10605f757f3fSDimitry Andric       OpType = OperationType::NonNegOp;
10615f757f3fSDimitry Andric       NonNegFlags.NonNeg = PNNI->hasNonNeg();
10625f757f3fSDimitry Andric     } else if (auto *Op = dyn_cast<FPMathOperator>(&I)) {
10635f757f3fSDimitry Andric       OpType = OperationType::FPMathOp;
10645f757f3fSDimitry Andric       FMFs = Op->getFastMathFlags();
10657a6dacacSDimitry Andric     } else {
10667a6dacacSDimitry Andric       OpType = OperationType::Other;
10677a6dacacSDimitry Andric       AllFlags = 0;
10685f757f3fSDimitry Andric     }
10695f757f3fSDimitry Andric   }
10705f757f3fSDimitry Andric 
10715f757f3fSDimitry Andric   template <typename IterT>
10725f757f3fSDimitry Andric   VPRecipeWithIRFlags(const unsigned char SC, IterT Operands,
10735f757f3fSDimitry Andric                       CmpInst::Predicate Pred, DebugLoc DL = {})
VPSingleDefRecipe(SC,Operands,DL)10747a6dacacSDimitry Andric       : VPSingleDefRecipe(SC, Operands, DL), OpType(OperationType::Cmp),
10755f757f3fSDimitry Andric         CmpPredicate(Pred) {}
10765f757f3fSDimitry Andric 
10775f757f3fSDimitry Andric   template <typename IterT>
10785f757f3fSDimitry Andric   VPRecipeWithIRFlags(const unsigned char SC, IterT Operands,
10795f757f3fSDimitry Andric                       WrapFlagsTy WrapFlags, DebugLoc DL = {})
VPSingleDefRecipe(SC,Operands,DL)10807a6dacacSDimitry Andric       : VPSingleDefRecipe(SC, Operands, DL),
10817a6dacacSDimitry Andric         OpType(OperationType::OverflowingBinOp), WrapFlags(WrapFlags) {}
10825f757f3fSDimitry Andric 
10835f757f3fSDimitry Andric   template <typename IterT>
10845f757f3fSDimitry Andric   VPRecipeWithIRFlags(const unsigned char SC, IterT Operands,
10855f757f3fSDimitry Andric                       FastMathFlags FMFs, DebugLoc DL = {})
VPSingleDefRecipe(SC,Operands,DL)10867a6dacacSDimitry Andric       : VPSingleDefRecipe(SC, Operands, DL), OpType(OperationType::FPMathOp),
10875f757f3fSDimitry Andric         FMFs(FMFs) {}
10885f757f3fSDimitry Andric 
1089*0fca6ea1SDimitry Andric   template <typename IterT>
1090*0fca6ea1SDimitry Andric   VPRecipeWithIRFlags(const unsigned char SC, IterT Operands,
1091*0fca6ea1SDimitry Andric                       DisjointFlagsTy DisjointFlags, DebugLoc DL = {})
VPSingleDefRecipe(SC,Operands,DL)1092*0fca6ea1SDimitry Andric       : VPSingleDefRecipe(SC, Operands, DL), OpType(OperationType::DisjointOp),
1093*0fca6ea1SDimitry Andric         DisjointFlags(DisjointFlags) {}
1094*0fca6ea1SDimitry Andric 
10951db9f3b2SDimitry Andric protected:
10961db9f3b2SDimitry Andric   template <typename IterT>
10971db9f3b2SDimitry Andric   VPRecipeWithIRFlags(const unsigned char SC, IterT Operands,
10981db9f3b2SDimitry Andric                       GEPFlagsTy GEPFlags, DebugLoc DL = {})
VPSingleDefRecipe(SC,Operands,DL)10997a6dacacSDimitry Andric       : VPSingleDefRecipe(SC, Operands, DL), OpType(OperationType::GEPOp),
11001db9f3b2SDimitry Andric         GEPFlags(GEPFlags) {}
11011db9f3b2SDimitry Andric 
11021db9f3b2SDimitry Andric public:
classof(const VPRecipeBase * R)11035f757f3fSDimitry Andric   static inline bool classof(const VPRecipeBase *R) {
11045f757f3fSDimitry Andric     return R->getVPDefID() == VPRecipeBase::VPInstructionSC ||
11055f757f3fSDimitry Andric            R->getVPDefID() == VPRecipeBase::VPWidenSC ||
11065f757f3fSDimitry Andric            R->getVPDefID() == VPRecipeBase::VPWidenGEPSC ||
11075f757f3fSDimitry Andric            R->getVPDefID() == VPRecipeBase::VPWidenCastSC ||
11081db9f3b2SDimitry Andric            R->getVPDefID() == VPRecipeBase::VPReplicateSC ||
11091db9f3b2SDimitry Andric            R->getVPDefID() == VPRecipeBase::VPVectorPointerSC;
11105f757f3fSDimitry Andric   }
11115f757f3fSDimitry Andric 
classof(const VPUser * U)1112*0fca6ea1SDimitry Andric   static inline bool classof(const VPUser *U) {
1113*0fca6ea1SDimitry Andric     auto *R = dyn_cast<VPRecipeBase>(U);
1114*0fca6ea1SDimitry Andric     return R && classof(R);
1115*0fca6ea1SDimitry Andric   }
1116*0fca6ea1SDimitry Andric 
11175f757f3fSDimitry Andric   /// Drop all poison-generating flags.
dropPoisonGeneratingFlags()11185f757f3fSDimitry Andric   void dropPoisonGeneratingFlags() {
11195f757f3fSDimitry Andric     // NOTE: This needs to be kept in-sync with
11205f757f3fSDimitry Andric     // Instruction::dropPoisonGeneratingFlags.
11215f757f3fSDimitry Andric     switch (OpType) {
11225f757f3fSDimitry Andric     case OperationType::OverflowingBinOp:
11235f757f3fSDimitry Andric       WrapFlags.HasNUW = false;
11245f757f3fSDimitry Andric       WrapFlags.HasNSW = false;
11255f757f3fSDimitry Andric       break;
11265f757f3fSDimitry Andric     case OperationType::DisjointOp:
11275f757f3fSDimitry Andric       DisjointFlags.IsDisjoint = false;
11285f757f3fSDimitry Andric       break;
11295f757f3fSDimitry Andric     case OperationType::PossiblyExactOp:
11305f757f3fSDimitry Andric       ExactFlags.IsExact = false;
11315f757f3fSDimitry Andric       break;
11325f757f3fSDimitry Andric     case OperationType::GEPOp:
11335f757f3fSDimitry Andric       GEPFlags.IsInBounds = false;
11345f757f3fSDimitry Andric       break;
11355f757f3fSDimitry Andric     case OperationType::FPMathOp:
11365f757f3fSDimitry Andric       FMFs.NoNaNs = false;
11375f757f3fSDimitry Andric       FMFs.NoInfs = false;
11385f757f3fSDimitry Andric       break;
11395f757f3fSDimitry Andric     case OperationType::NonNegOp:
11405f757f3fSDimitry Andric       NonNegFlags.NonNeg = false;
11415f757f3fSDimitry Andric       break;
11425f757f3fSDimitry Andric     case OperationType::Cmp:
11435f757f3fSDimitry Andric     case OperationType::Other:
11445f757f3fSDimitry Andric       break;
11455f757f3fSDimitry Andric     }
11465f757f3fSDimitry Andric   }
11475f757f3fSDimitry Andric 
11485f757f3fSDimitry Andric   /// Set the IR flags for \p I.
setFlags(Instruction * I)11495f757f3fSDimitry Andric   void setFlags(Instruction *I) const {
11505f757f3fSDimitry Andric     switch (OpType) {
11515f757f3fSDimitry Andric     case OperationType::OverflowingBinOp:
11525f757f3fSDimitry Andric       I->setHasNoUnsignedWrap(WrapFlags.HasNUW);
11535f757f3fSDimitry Andric       I->setHasNoSignedWrap(WrapFlags.HasNSW);
11545f757f3fSDimitry Andric       break;
11555f757f3fSDimitry Andric     case OperationType::DisjointOp:
11565f757f3fSDimitry Andric       cast<PossiblyDisjointInst>(I)->setIsDisjoint(DisjointFlags.IsDisjoint);
11575f757f3fSDimitry Andric       break;
11585f757f3fSDimitry Andric     case OperationType::PossiblyExactOp:
11595f757f3fSDimitry Andric       I->setIsExact(ExactFlags.IsExact);
11605f757f3fSDimitry Andric       break;
11615f757f3fSDimitry Andric     case OperationType::GEPOp:
1162*0fca6ea1SDimitry Andric       // TODO(gep_nowrap): Track the full GEPNoWrapFlags in VPlan.
1163*0fca6ea1SDimitry Andric       cast<GetElementPtrInst>(I)->setNoWrapFlags(
1164*0fca6ea1SDimitry Andric           GEPFlags.IsInBounds ? GEPNoWrapFlags::inBounds()
1165*0fca6ea1SDimitry Andric                               : GEPNoWrapFlags::none());
11665f757f3fSDimitry Andric       break;
11675f757f3fSDimitry Andric     case OperationType::FPMathOp:
11685f757f3fSDimitry Andric       I->setHasAllowReassoc(FMFs.AllowReassoc);
11695f757f3fSDimitry Andric       I->setHasNoNaNs(FMFs.NoNaNs);
11705f757f3fSDimitry Andric       I->setHasNoInfs(FMFs.NoInfs);
11715f757f3fSDimitry Andric       I->setHasNoSignedZeros(FMFs.NoSignedZeros);
11725f757f3fSDimitry Andric       I->setHasAllowReciprocal(FMFs.AllowReciprocal);
11735f757f3fSDimitry Andric       I->setHasAllowContract(FMFs.AllowContract);
11745f757f3fSDimitry Andric       I->setHasApproxFunc(FMFs.ApproxFunc);
11755f757f3fSDimitry Andric       break;
11765f757f3fSDimitry Andric     case OperationType::NonNegOp:
11775f757f3fSDimitry Andric       I->setNonNeg(NonNegFlags.NonNeg);
11785f757f3fSDimitry Andric       break;
11795f757f3fSDimitry Andric     case OperationType::Cmp:
11805f757f3fSDimitry Andric     case OperationType::Other:
11815f757f3fSDimitry Andric       break;
11825f757f3fSDimitry Andric     }
11835f757f3fSDimitry Andric   }
11845f757f3fSDimitry Andric 
getPredicate()11855f757f3fSDimitry Andric   CmpInst::Predicate getPredicate() const {
11865f757f3fSDimitry Andric     assert(OpType == OperationType::Cmp &&
11875f757f3fSDimitry Andric            "recipe doesn't have a compare predicate");
11885f757f3fSDimitry Andric     return CmpPredicate;
11895f757f3fSDimitry Andric   }
11905f757f3fSDimitry Andric 
isInBounds()11915f757f3fSDimitry Andric   bool isInBounds() const {
11925f757f3fSDimitry Andric     assert(OpType == OperationType::GEPOp &&
11935f757f3fSDimitry Andric            "recipe doesn't have inbounds flag");
11945f757f3fSDimitry Andric     return GEPFlags.IsInBounds;
11955f757f3fSDimitry Andric   }
11965f757f3fSDimitry Andric 
11975f757f3fSDimitry Andric   /// Returns true if the recipe has fast-math flags.
hasFastMathFlags()11985f757f3fSDimitry Andric   bool hasFastMathFlags() const { return OpType == OperationType::FPMathOp; }
11995f757f3fSDimitry Andric 
12005f757f3fSDimitry Andric   FastMathFlags getFastMathFlags() const;
12015f757f3fSDimitry Andric 
hasNoUnsignedWrap()12025f757f3fSDimitry Andric   bool hasNoUnsignedWrap() const {
12035f757f3fSDimitry Andric     assert(OpType == OperationType::OverflowingBinOp &&
12045f757f3fSDimitry Andric            "recipe doesn't have a NUW flag");
12055f757f3fSDimitry Andric     return WrapFlags.HasNUW;
12065f757f3fSDimitry Andric   }
12075f757f3fSDimitry Andric 
hasNoSignedWrap()12085f757f3fSDimitry Andric   bool hasNoSignedWrap() const {
12095f757f3fSDimitry Andric     assert(OpType == OperationType::OverflowingBinOp &&
12105f757f3fSDimitry Andric            "recipe doesn't have a NSW flag");
12115f757f3fSDimitry Andric     return WrapFlags.HasNSW;
12125f757f3fSDimitry Andric   }
12135f757f3fSDimitry Andric 
isDisjoint()1214*0fca6ea1SDimitry Andric   bool isDisjoint() const {
1215*0fca6ea1SDimitry Andric     assert(OpType == OperationType::DisjointOp &&
1216*0fca6ea1SDimitry Andric            "recipe cannot have a disjoing flag");
1217*0fca6ea1SDimitry Andric     return DisjointFlags.IsDisjoint;
1218*0fca6ea1SDimitry Andric   }
1219*0fca6ea1SDimitry Andric 
12205f757f3fSDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
12215f757f3fSDimitry Andric   void printFlags(raw_ostream &O) const;
12225f757f3fSDimitry Andric #endif
12235f757f3fSDimitry Andric };
12245f757f3fSDimitry Andric 
12250b57cec5SDimitry Andric /// This is a concrete Recipe that models a single VPlan-level instruction.
12260b57cec5SDimitry Andric /// While as any Recipe it may generate a sequence of IR instructions when
12270b57cec5SDimitry Andric /// executed, these instructions would always form a single-def expression as
12280b57cec5SDimitry Andric /// the VPInstruction is also a single def-use vertex.
12297a6dacacSDimitry Andric class VPInstruction : public VPRecipeWithIRFlags {
12300b57cec5SDimitry Andric   friend class VPlanSlp;
12310b57cec5SDimitry Andric 
12320b57cec5SDimitry Andric public:
12330b57cec5SDimitry Andric   /// VPlan opcodes, extending LLVM IR with idiomatics instructions.
12340b57cec5SDimitry Andric   enum {
1235fe6060f1SDimitry Andric     FirstOrderRecurrenceSplice =
1236fe6060f1SDimitry Andric         Instruction::OtherOpsEnd + 1, // Combines the incoming and previous
1237fe6060f1SDimitry Andric                                       // values of a first-order recurrence.
1238fe6060f1SDimitry Andric     Not,
12390b57cec5SDimitry Andric     SLPLoad,
12400b57cec5SDimitry Andric     SLPStore,
12415ffd83dbSDimitry Andric     ActiveLaneMask,
1242*0fca6ea1SDimitry Andric     ExplicitVectorLength,
1243*0fca6ea1SDimitry Andric     /// Creates a scalar phi in a leaf VPBB with a single predecessor in VPlan.
1244*0fca6ea1SDimitry Andric     /// The first operand is the incoming value from the predecessor in VPlan,
1245*0fca6ea1SDimitry Andric     /// the second operand is the incoming value for all other predecessors
1246*0fca6ea1SDimitry Andric     /// (which are currently not modeled in VPlan).
1247*0fca6ea1SDimitry Andric     ResumePhi,
124806c3fb27SDimitry Andric     CalculateTripCountMinusVF,
12495f757f3fSDimitry Andric     // Increment the canonical IV separately for each unrolled part.
1250753f127fSDimitry Andric     CanonicalIVIncrementForPart,
125104eeddc0SDimitry Andric     BranchOnCount,
12521db9f3b2SDimitry Andric     BranchOnCond,
12531db9f3b2SDimitry Andric     ComputeReductionResult,
1254*0fca6ea1SDimitry Andric     // Takes the VPValue to extract from as first operand and the lane or part
1255*0fca6ea1SDimitry Andric     // to extract as second operand, counting from the end starting with 1 for
1256*0fca6ea1SDimitry Andric     // last. The second operand must be a positive constant and <= VF when
1257*0fca6ea1SDimitry Andric     // extracting from a vector or <= UF when extracting from an unrolled
1258*0fca6ea1SDimitry Andric     // scalar.
1259*0fca6ea1SDimitry Andric     ExtractFromEnd,
1260*0fca6ea1SDimitry Andric     LogicalAnd, // Non-poison propagating logical And.
1261*0fca6ea1SDimitry Andric     // Add an offset in bytes (second operand) to a base pointer (first
1262*0fca6ea1SDimitry Andric     // operand). Only generates scalar values (either for the first lane only or
1263*0fca6ea1SDimitry Andric     // for all lanes, depending on its uses).
1264*0fca6ea1SDimitry Andric     PtrAdd,
12650b57cec5SDimitry Andric   };
12660b57cec5SDimitry Andric 
12670b57cec5SDimitry Andric private:
12680b57cec5SDimitry Andric   typedef unsigned char OpcodeTy;
12690b57cec5SDimitry Andric   OpcodeTy Opcode;
12700b57cec5SDimitry Andric 
1271753f127fSDimitry Andric   /// An optional name that can be used for the generated IR instruction.
1272753f127fSDimitry Andric   const std::string Name;
1273753f127fSDimitry Andric 
1274*0fca6ea1SDimitry Andric   /// Returns true if this VPInstruction generates scalar values for all lanes.
1275*0fca6ea1SDimitry Andric   /// Most VPInstructions generate a single value per part, either vector or
1276*0fca6ea1SDimitry Andric   /// scalar. VPReplicateRecipe takes care of generating multiple (scalar)
1277*0fca6ea1SDimitry Andric   /// values per all lanes, stemming from an original ingredient. This method
1278*0fca6ea1SDimitry Andric   /// identifies the (rare) cases of VPInstructions that do so as well, w/o an
1279*0fca6ea1SDimitry Andric   /// underlying ingredient.
1280*0fca6ea1SDimitry Andric   bool doesGeneratePerAllLanes() const;
1281*0fca6ea1SDimitry Andric 
1282*0fca6ea1SDimitry Andric   /// Returns true if we can generate a scalar for the first lane only if
1283*0fca6ea1SDimitry Andric   /// needed.
1284*0fca6ea1SDimitry Andric   bool canGenerateScalarForFirstLane() const;
1285*0fca6ea1SDimitry Andric 
1286*0fca6ea1SDimitry Andric   /// Utility methods serving execute(): generates a single instance of the
1287*0fca6ea1SDimitry Andric   /// modeled instruction for a given part. \returns the generated value for \p
1288*0fca6ea1SDimitry Andric   /// Part. In some cases an existing value is returned rather than a generated
128906c3fb27SDimitry Andric   /// one.
1290*0fca6ea1SDimitry Andric   Value *generatePerPart(VPTransformState &State, unsigned Part);
1291*0fca6ea1SDimitry Andric 
1292*0fca6ea1SDimitry Andric   /// Utility methods serving execute(): generates a scalar single instance of
1293*0fca6ea1SDimitry Andric   /// the modeled instruction for a given lane. \returns the scalar generated
1294*0fca6ea1SDimitry Andric   /// value for lane \p Lane.
1295*0fca6ea1SDimitry Andric   Value *generatePerLane(VPTransformState &State, const VPIteration &Lane);
12960b57cec5SDimitry Andric 
12975f757f3fSDimitry Andric #if !defined(NDEBUG)
12985f757f3fSDimitry Andric   /// Return true if the VPInstruction is a floating point math operation, i.e.
12995f757f3fSDimitry Andric   /// has fast-math flags.
13005f757f3fSDimitry Andric   bool isFPMathOp() const;
13015f757f3fSDimitry Andric #endif
13025f757f3fSDimitry Andric 
13030b57cec5SDimitry Andric public:
1304753f127fSDimitry Andric   VPInstruction(unsigned Opcode, ArrayRef<VPValue *> Operands, DebugLoc DL,
1305753f127fSDimitry Andric                 const Twine &Name = "")
VPRecipeWithIRFlags(VPDef::VPInstructionSC,Operands,DL)13065f757f3fSDimitry Andric       : VPRecipeWithIRFlags(VPDef::VPInstructionSC, Operands, DL),
13077a6dacacSDimitry Andric         Opcode(Opcode), Name(Name.str()) {}
1308e8d8bef9SDimitry Andric 
13090eae32dcSDimitry Andric   VPInstruction(unsigned Opcode, std::initializer_list<VPValue *> Operands,
1310753f127fSDimitry Andric                 DebugLoc DL = {}, const Twine &Name = "")
VPInstruction(Opcode,ArrayRef<VPValue * > (Operands),DL,Name)1311753f127fSDimitry Andric       : VPInstruction(Opcode, ArrayRef<VPValue *>(Operands), DL, Name) {}
13120b57cec5SDimitry Andric 
13135f757f3fSDimitry Andric   VPInstruction(unsigned Opcode, CmpInst::Predicate Pred, VPValue *A,
13145f757f3fSDimitry Andric                 VPValue *B, DebugLoc DL = {}, const Twine &Name = "");
13150b57cec5SDimitry Andric 
13165f757f3fSDimitry Andric   VPInstruction(unsigned Opcode, std::initializer_list<VPValue *> Operands,
13175f757f3fSDimitry Andric                 WrapFlagsTy WrapFlags, DebugLoc DL = {}, const Twine &Name = "")
VPRecipeWithIRFlags(VPDef::VPInstructionSC,Operands,WrapFlags,DL)13185f757f3fSDimitry Andric       : VPRecipeWithIRFlags(VPDef::VPInstructionSC, Operands, WrapFlags, DL),
13197a6dacacSDimitry Andric         Opcode(Opcode), Name(Name.str()) {}
13205f757f3fSDimitry Andric 
13215f757f3fSDimitry Andric   VPInstruction(unsigned Opcode, std::initializer_list<VPValue *> Operands,
1322*0fca6ea1SDimitry Andric                 DisjointFlagsTy DisjointFlag, DebugLoc DL = {},
1323*0fca6ea1SDimitry Andric                 const Twine &Name = "")
VPRecipeWithIRFlags(VPDef::VPInstructionSC,Operands,DisjointFlag,DL)1324*0fca6ea1SDimitry Andric       : VPRecipeWithIRFlags(VPDef::VPInstructionSC, Operands, DisjointFlag, DL),
1325*0fca6ea1SDimitry Andric         Opcode(Opcode), Name(Name.str()) {
1326*0fca6ea1SDimitry Andric     assert(Opcode == Instruction::Or && "only OR opcodes can be disjoint");
1327*0fca6ea1SDimitry Andric   }
1328*0fca6ea1SDimitry Andric 
1329*0fca6ea1SDimitry Andric   VPInstruction(unsigned Opcode, std::initializer_list<VPValue *> Operands,
13305f757f3fSDimitry Andric                 FastMathFlags FMFs, DebugLoc DL = {}, const Twine &Name = "");
13315f757f3fSDimitry Andric 
VP_CLASSOF_IMPL(VPDef::VPInstructionSC)13325f757f3fSDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPInstructionSC)
13330b57cec5SDimitry Andric 
1334*0fca6ea1SDimitry Andric   VPInstruction *clone() override {
1335*0fca6ea1SDimitry Andric     SmallVector<VPValue *, 2> Operands(operands());
1336*0fca6ea1SDimitry Andric     auto *New = new VPInstruction(Opcode, Operands, getDebugLoc(), Name);
1337*0fca6ea1SDimitry Andric     New->transferFlags(*this);
1338*0fca6ea1SDimitry Andric     return New;
1339*0fca6ea1SDimitry Andric   }
1340*0fca6ea1SDimitry Andric 
getOpcode()13410b57cec5SDimitry Andric   unsigned getOpcode() const { return Opcode; }
13420b57cec5SDimitry Andric 
13430b57cec5SDimitry Andric   /// Generate the instruction.
13440b57cec5SDimitry Andric   /// TODO: We currently execute only per-part unless a specific instance is
13450b57cec5SDimitry Andric   /// provided.
13460b57cec5SDimitry Andric   void execute(VPTransformState &State) override;
13470b57cec5SDimitry Andric 
1348fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1349e8d8bef9SDimitry Andric   /// Print the VPInstruction to \p O.
13505ffd83dbSDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
13515ffd83dbSDimitry Andric              VPSlotTracker &SlotTracker) const override;
13520b57cec5SDimitry Andric 
1353e8d8bef9SDimitry Andric   /// Print the VPInstruction to dbgs() (for debugging).
1354fe6060f1SDimitry Andric   LLVM_DUMP_METHOD void dump() const;
1355fe6060f1SDimitry Andric #endif
13560b57cec5SDimitry Andric 
13570b57cec5SDimitry Andric   /// Return true if this instruction may modify memory.
mayWriteToMemory()13580b57cec5SDimitry Andric   bool mayWriteToMemory() const {
13590b57cec5SDimitry Andric     // TODO: we can use attributes of the called function to rule out memory
13600b57cec5SDimitry Andric     //       modifications.
13610b57cec5SDimitry Andric     return Opcode == Instruction::Store || Opcode == Instruction::Call ||
13620b57cec5SDimitry Andric            Opcode == Instruction::Invoke || Opcode == SLPStore;
13630b57cec5SDimitry Andric   }
13645ffd83dbSDimitry Andric 
hasResult()13655ffd83dbSDimitry Andric   bool hasResult() const {
13665ffd83dbSDimitry Andric     // CallInst may or may not have a result, depending on the called function.
13675ffd83dbSDimitry Andric     // Conservatively return calls have results for now.
13685ffd83dbSDimitry Andric     switch (getOpcode()) {
13695ffd83dbSDimitry Andric     case Instruction::Ret:
13705ffd83dbSDimitry Andric     case Instruction::Br:
13715ffd83dbSDimitry Andric     case Instruction::Store:
13725ffd83dbSDimitry Andric     case Instruction::Switch:
13735ffd83dbSDimitry Andric     case Instruction::IndirectBr:
13745ffd83dbSDimitry Andric     case Instruction::Resume:
13755ffd83dbSDimitry Andric     case Instruction::CatchRet:
13765ffd83dbSDimitry Andric     case Instruction::Unreachable:
13775ffd83dbSDimitry Andric     case Instruction::Fence:
13785ffd83dbSDimitry Andric     case Instruction::AtomicRMW:
137981ad6265SDimitry Andric     case VPInstruction::BranchOnCond:
138004eeddc0SDimitry Andric     case VPInstruction::BranchOnCount:
13815ffd83dbSDimitry Andric       return false;
13825ffd83dbSDimitry Andric     default:
13835ffd83dbSDimitry Andric       return true;
13845ffd83dbSDimitry Andric     }
13855ffd83dbSDimitry Andric   }
13864824e7fdSDimitry Andric 
13871fd87a68SDimitry Andric   /// Returns true if the recipe only uses the first lane of operand \p Op.
1388*0fca6ea1SDimitry Andric   bool onlyFirstLaneUsed(const VPValue *Op) const override;
13895f757f3fSDimitry Andric 
13905f757f3fSDimitry Andric   /// Returns true if the recipe only uses the first part of operand \p Op.
1391*0fca6ea1SDimitry Andric   bool onlyFirstPartUsed(const VPValue *Op) const override;
1392*0fca6ea1SDimitry Andric 
1393*0fca6ea1SDimitry Andric   /// Returns true if this VPInstruction produces a scalar value from a vector,
1394*0fca6ea1SDimitry Andric   /// e.g. by performing a reduction or extracting a lane.
1395*0fca6ea1SDimitry Andric   bool isVectorToScalar() const;
1396*0fca6ea1SDimitry Andric 
1397*0fca6ea1SDimitry Andric   /// Returns true if this VPInstruction's operands are single scalars and the
1398*0fca6ea1SDimitry Andric   /// result is also a single scalar.
1399*0fca6ea1SDimitry Andric   bool isSingleScalar() const;
14000b57cec5SDimitry Andric };
14010b57cec5SDimitry Andric 
1402*0fca6ea1SDimitry Andric /// VPWidenRecipe is a recipe for producing a widened instruction using the
1403*0fca6ea1SDimitry Andric /// opcode and operands of the recipe. This recipe covers most of the
1404*0fca6ea1SDimitry Andric /// traditional vectorization cases where each recipe transforms into a
1405*0fca6ea1SDimitry Andric /// vectorized version of itself.
14067a6dacacSDimitry Andric class VPWidenRecipe : public VPRecipeWithIRFlags {
14075f757f3fSDimitry Andric   unsigned Opcode;
140806c3fb27SDimitry Andric 
14090b57cec5SDimitry Andric public:
14105ffd83dbSDimitry Andric   template <typename IterT>
VPWidenRecipe(Instruction & I,iterator_range<IterT> Operands)14115ffd83dbSDimitry Andric   VPWidenRecipe(Instruction &I, iterator_range<IterT> Operands)
14127a6dacacSDimitry Andric       : VPRecipeWithIRFlags(VPDef::VPWidenSC, Operands, I),
14135f757f3fSDimitry Andric         Opcode(I.getOpcode()) {}
14140b57cec5SDimitry Andric 
14150b57cec5SDimitry Andric   ~VPWidenRecipe() override = default;
14160b57cec5SDimitry Andric 
clone()1417*0fca6ea1SDimitry Andric   VPWidenRecipe *clone() override {
1418*0fca6ea1SDimitry Andric     auto *R = new VPWidenRecipe(*getUnderlyingInstr(), operands());
1419*0fca6ea1SDimitry Andric     R->transferFlags(*this);
1420*0fca6ea1SDimitry Andric     return R;
1421*0fca6ea1SDimitry Andric   }
1422*0fca6ea1SDimitry Andric 
1423bdd1243dSDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPWidenSC)
14240b57cec5SDimitry Andric 
1425*0fca6ea1SDimitry Andric   /// Produce a widened instruction using the opcode and operands of the recipe,
1426*0fca6ea1SDimitry Andric   /// processing State.VF elements.
14270b57cec5SDimitry Andric   void execute(VPTransformState &State) override;
14280b57cec5SDimitry Andric 
getOpcode()14295f757f3fSDimitry Andric   unsigned getOpcode() const { return Opcode; }
14305f757f3fSDimitry Andric 
1431fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
14325ffd83dbSDimitry Andric   /// Print the recipe.
14335ffd83dbSDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
14345ffd83dbSDimitry Andric              VPSlotTracker &SlotTracker) const override;
1435fe6060f1SDimitry Andric #endif
14365ffd83dbSDimitry Andric };
14375ffd83dbSDimitry Andric 
143806c3fb27SDimitry Andric /// VPWidenCastRecipe is a recipe to create vector cast instructions.
14397a6dacacSDimitry Andric class VPWidenCastRecipe : public VPRecipeWithIRFlags {
144006c3fb27SDimitry Andric   /// Cast instruction opcode.
144106c3fb27SDimitry Andric   Instruction::CastOps Opcode;
144206c3fb27SDimitry Andric 
144306c3fb27SDimitry Andric   /// Result type for the cast.
144406c3fb27SDimitry Andric   Type *ResultTy;
144506c3fb27SDimitry Andric 
144606c3fb27SDimitry Andric public:
VPWidenCastRecipe(Instruction::CastOps Opcode,VPValue * Op,Type * ResultTy,CastInst & UI)144706c3fb27SDimitry Andric   VPWidenCastRecipe(Instruction::CastOps Opcode, VPValue *Op, Type *ResultTy,
14485f757f3fSDimitry Andric                     CastInst &UI)
14497a6dacacSDimitry Andric       : VPRecipeWithIRFlags(VPDef::VPWidenCastSC, Op, UI), Opcode(Opcode),
14507a6dacacSDimitry Andric         ResultTy(ResultTy) {
14515f757f3fSDimitry Andric     assert(UI.getOpcode() == Opcode &&
145206c3fb27SDimitry Andric            "opcode of underlying cast doesn't match");
145306c3fb27SDimitry Andric   }
145406c3fb27SDimitry Andric 
VPWidenCastRecipe(Instruction::CastOps Opcode,VPValue * Op,Type * ResultTy)14555f757f3fSDimitry Andric   VPWidenCastRecipe(Instruction::CastOps Opcode, VPValue *Op, Type *ResultTy)
14567a6dacacSDimitry Andric       : VPRecipeWithIRFlags(VPDef::VPWidenCastSC, Op), Opcode(Opcode),
14577a6dacacSDimitry Andric         ResultTy(ResultTy) {}
14585f757f3fSDimitry Andric 
145906c3fb27SDimitry Andric   ~VPWidenCastRecipe() override = default;
146006c3fb27SDimitry Andric 
clone()1461*0fca6ea1SDimitry Andric   VPWidenCastRecipe *clone() override {
1462*0fca6ea1SDimitry Andric     if (auto *UV = getUnderlyingValue())
1463*0fca6ea1SDimitry Andric       return new VPWidenCastRecipe(Opcode, getOperand(0), ResultTy,
1464*0fca6ea1SDimitry Andric                                    *cast<CastInst>(UV));
1465*0fca6ea1SDimitry Andric 
1466*0fca6ea1SDimitry Andric     return new VPWidenCastRecipe(Opcode, getOperand(0), ResultTy);
1467*0fca6ea1SDimitry Andric   }
1468*0fca6ea1SDimitry Andric 
146906c3fb27SDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPWidenCastSC)
147006c3fb27SDimitry Andric 
147106c3fb27SDimitry Andric   /// Produce widened copies of the cast.
147206c3fb27SDimitry Andric   void execute(VPTransformState &State) override;
147306c3fb27SDimitry Andric 
147406c3fb27SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
147506c3fb27SDimitry Andric   /// Print the recipe.
147606c3fb27SDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
147706c3fb27SDimitry Andric              VPSlotTracker &SlotTracker) const override;
147806c3fb27SDimitry Andric #endif
147906c3fb27SDimitry Andric 
getOpcode()148006c3fb27SDimitry Andric   Instruction::CastOps getOpcode() const { return Opcode; }
148106c3fb27SDimitry Andric 
148206c3fb27SDimitry Andric   /// Returns the result type of the cast.
getResultType()148306c3fb27SDimitry Andric   Type *getResultType() const { return ResultTy; }
148406c3fb27SDimitry Andric };
148506c3fb27SDimitry Andric 
1486*0fca6ea1SDimitry Andric /// VPScalarCastRecipe is a recipe to create scalar cast instructions.
1487*0fca6ea1SDimitry Andric class VPScalarCastRecipe : public VPSingleDefRecipe {
1488*0fca6ea1SDimitry Andric   Instruction::CastOps Opcode;
1489*0fca6ea1SDimitry Andric 
1490*0fca6ea1SDimitry Andric   Type *ResultTy;
1491*0fca6ea1SDimitry Andric 
1492*0fca6ea1SDimitry Andric   Value *generate(VPTransformState &State, unsigned Part);
1493*0fca6ea1SDimitry Andric 
1494*0fca6ea1SDimitry Andric public:
VPScalarCastRecipe(Instruction::CastOps Opcode,VPValue * Op,Type * ResultTy)1495*0fca6ea1SDimitry Andric   VPScalarCastRecipe(Instruction::CastOps Opcode, VPValue *Op, Type *ResultTy)
1496*0fca6ea1SDimitry Andric       : VPSingleDefRecipe(VPDef::VPScalarCastSC, {Op}), Opcode(Opcode),
1497*0fca6ea1SDimitry Andric         ResultTy(ResultTy) {}
1498*0fca6ea1SDimitry Andric 
1499*0fca6ea1SDimitry Andric   ~VPScalarCastRecipe() override = default;
1500*0fca6ea1SDimitry Andric 
clone()1501*0fca6ea1SDimitry Andric   VPScalarCastRecipe *clone() override {
1502*0fca6ea1SDimitry Andric     return new VPScalarCastRecipe(Opcode, getOperand(0), ResultTy);
1503*0fca6ea1SDimitry Andric   }
1504*0fca6ea1SDimitry Andric 
1505*0fca6ea1SDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPScalarCastSC)
1506*0fca6ea1SDimitry Andric 
1507*0fca6ea1SDimitry Andric   void execute(VPTransformState &State) override;
1508*0fca6ea1SDimitry Andric 
1509*0fca6ea1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1510*0fca6ea1SDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
1511*0fca6ea1SDimitry Andric              VPSlotTracker &SlotTracker) const override;
1512*0fca6ea1SDimitry Andric #endif
1513*0fca6ea1SDimitry Andric 
1514*0fca6ea1SDimitry Andric   /// Returns the result type of the cast.
getResultType()1515*0fca6ea1SDimitry Andric   Type *getResultType() const { return ResultTy; }
1516*0fca6ea1SDimitry Andric 
onlyFirstLaneUsed(const VPValue * Op)1517*0fca6ea1SDimitry Andric   bool onlyFirstLaneUsed(const VPValue *Op) const override {
1518*0fca6ea1SDimitry Andric     // At the moment, only uniform codegen is implemented.
1519*0fca6ea1SDimitry Andric     assert(is_contained(operands(), Op) &&
1520*0fca6ea1SDimitry Andric            "Op must be an operand of the recipe");
1521*0fca6ea1SDimitry Andric     return true;
1522*0fca6ea1SDimitry Andric   }
1523*0fca6ea1SDimitry Andric };
1524*0fca6ea1SDimitry Andric 
15255ffd83dbSDimitry Andric /// A recipe for widening Call instructions.
15267a6dacacSDimitry Andric class VPWidenCallRecipe : public VPSingleDefRecipe {
1527bdd1243dSDimitry Andric   /// ID of the vector intrinsic to call when widening the call. If set the
1528bdd1243dSDimitry Andric   /// Intrinsic::not_intrinsic, a library call will be used instead.
1529bdd1243dSDimitry Andric   Intrinsic::ID VectorIntrinsicID;
153006c3fb27SDimitry Andric   /// If this recipe represents a library call, Variant stores a pointer to
153106c3fb27SDimitry Andric   /// the chosen function. There is a 1:1 mapping between a given VF and the
153206c3fb27SDimitry Andric   /// chosen vectorized variant, so there will be a different vplan for each
153306c3fb27SDimitry Andric   /// VF with a valid variant.
153406c3fb27SDimitry Andric   Function *Variant;
15355ffd83dbSDimitry Andric 
15365ffd83dbSDimitry Andric public:
15375ffd83dbSDimitry Andric   template <typename IterT>
1538*0fca6ea1SDimitry Andric   VPWidenCallRecipe(Value *UV, iterator_range<IterT> CallArguments,
15397a6dacacSDimitry Andric                     Intrinsic::ID VectorIntrinsicID, DebugLoc DL = {},
154006c3fb27SDimitry Andric                     Function *Variant = nullptr)
VPSingleDefRecipe(VPDef::VPWidenCallSC,CallArguments,UV,DL)1541*0fca6ea1SDimitry Andric       : VPSingleDefRecipe(VPDef::VPWidenCallSC, CallArguments, UV, DL),
1542*0fca6ea1SDimitry Andric         VectorIntrinsicID(VectorIntrinsicID), Variant(Variant) {
1543*0fca6ea1SDimitry Andric     assert(
1544*0fca6ea1SDimitry Andric         isa<Function>(getOperand(getNumOperands() - 1)->getLiveInIRValue()) &&
1545*0fca6ea1SDimitry Andric         "last operand must be the called function");
1546*0fca6ea1SDimitry Andric   }
15475ffd83dbSDimitry Andric 
15485ffd83dbSDimitry Andric   ~VPWidenCallRecipe() override = default;
15495ffd83dbSDimitry Andric 
clone()1550*0fca6ea1SDimitry Andric   VPWidenCallRecipe *clone() override {
1551*0fca6ea1SDimitry Andric     return new VPWidenCallRecipe(getUnderlyingValue(), operands(),
1552*0fca6ea1SDimitry Andric                                  VectorIntrinsicID, getDebugLoc(), Variant);
1553*0fca6ea1SDimitry Andric   }
1554*0fca6ea1SDimitry Andric 
1555bdd1243dSDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPWidenCallSC)
15560b57cec5SDimitry Andric 
15575ffd83dbSDimitry Andric   /// Produce a widened version of the call instruction.
15585ffd83dbSDimitry Andric   void execute(VPTransformState &State) override;
15595ffd83dbSDimitry Andric 
getCalledScalarFunction()1560*0fca6ea1SDimitry Andric   Function *getCalledScalarFunction() const {
1561*0fca6ea1SDimitry Andric     return cast<Function>(getOperand(getNumOperands() - 1)->getLiveInIRValue());
1562*0fca6ea1SDimitry Andric   }
1563*0fca6ea1SDimitry Andric 
arg_operands()1564*0fca6ea1SDimitry Andric   operand_range arg_operands() {
1565*0fca6ea1SDimitry Andric     return make_range(op_begin(), op_begin() + getNumOperands() - 1);
1566*0fca6ea1SDimitry Andric   }
arg_operands()1567*0fca6ea1SDimitry Andric   const_operand_range arg_operands() const {
1568*0fca6ea1SDimitry Andric     return make_range(op_begin(), op_begin() + getNumOperands() - 1);
1569*0fca6ea1SDimitry Andric   }
1570*0fca6ea1SDimitry Andric 
1571fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
15720b57cec5SDimitry Andric   /// Print the recipe.
15735ffd83dbSDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
15745ffd83dbSDimitry Andric              VPSlotTracker &SlotTracker) const override;
1575fe6060f1SDimitry Andric #endif
15765ffd83dbSDimitry Andric };
15775ffd83dbSDimitry Andric 
15785ffd83dbSDimitry Andric /// A recipe for widening select instructions.
15797a6dacacSDimitry Andric struct VPWidenSelectRecipe : public VPSingleDefRecipe {
15805ffd83dbSDimitry Andric   template <typename IterT>
VPWidenSelectRecipeVPWidenSelectRecipe158106c3fb27SDimitry Andric   VPWidenSelectRecipe(SelectInst &I, iterator_range<IterT> Operands)
15827a6dacacSDimitry Andric       : VPSingleDefRecipe(VPDef::VPWidenSelectSC, Operands, &I,
15837a6dacacSDimitry Andric                           I.getDebugLoc()) {}
15845ffd83dbSDimitry Andric 
15855ffd83dbSDimitry Andric   ~VPWidenSelectRecipe() override = default;
15865ffd83dbSDimitry Andric 
cloneVPWidenSelectRecipe1587*0fca6ea1SDimitry Andric   VPWidenSelectRecipe *clone() override {
1588*0fca6ea1SDimitry Andric     return new VPWidenSelectRecipe(*cast<SelectInst>(getUnderlyingInstr()),
1589*0fca6ea1SDimitry Andric                                    operands());
1590*0fca6ea1SDimitry Andric   }
1591*0fca6ea1SDimitry Andric 
1592bdd1243dSDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPWidenSelectSC)
15935ffd83dbSDimitry Andric 
15945ffd83dbSDimitry Andric   /// Produce a widened version of the select instruction.
15955ffd83dbSDimitry Andric   void execute(VPTransformState &State) override;
15965ffd83dbSDimitry Andric 
1597fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
15985ffd83dbSDimitry Andric   /// Print the recipe.
15995ffd83dbSDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
16005ffd83dbSDimitry Andric              VPSlotTracker &SlotTracker) const override;
1601fe6060f1SDimitry Andric #endif
160206c3fb27SDimitry Andric 
getCondVPWidenSelectRecipe160306c3fb27SDimitry Andric   VPValue *getCond() const {
160406c3fb27SDimitry Andric     return getOperand(0);
160506c3fb27SDimitry Andric   }
160606c3fb27SDimitry Andric 
isInvariantCondVPWidenSelectRecipe160706c3fb27SDimitry Andric   bool isInvariantCond() const {
160806c3fb27SDimitry Andric     return getCond()->isDefinedOutsideVectorRegions();
160906c3fb27SDimitry Andric   }
16100b57cec5SDimitry Andric };
16110b57cec5SDimitry Andric 
1612480093f4SDimitry Andric /// A recipe for handling GEP instructions.
16137a6dacacSDimitry Andric class VPWidenGEPRecipe : public VPRecipeWithIRFlags {
isPointerLoopInvariant()161406c3fb27SDimitry Andric   bool isPointerLoopInvariant() const {
161506c3fb27SDimitry Andric     return getOperand(0)->isDefinedOutsideVectorRegions();
161606c3fb27SDimitry Andric   }
161706c3fb27SDimitry Andric 
isIndexLoopInvariant(unsigned I)161806c3fb27SDimitry Andric   bool isIndexLoopInvariant(unsigned I) const {
161906c3fb27SDimitry Andric     return getOperand(I + 1)->isDefinedOutsideVectorRegions();
162006c3fb27SDimitry Andric   }
162106c3fb27SDimitry Andric 
areAllOperandsInvariant()162206c3fb27SDimitry Andric   bool areAllOperandsInvariant() const {
162306c3fb27SDimitry Andric     return all_of(operands(), [](VPValue *Op) {
162406c3fb27SDimitry Andric       return Op->isDefinedOutsideVectorRegions();
162506c3fb27SDimitry Andric     });
162606c3fb27SDimitry Andric   }
1627480093f4SDimitry Andric 
1628480093f4SDimitry Andric public:
16295ffd83dbSDimitry Andric   template <typename IterT>
VPWidenGEPRecipe(GetElementPtrInst * GEP,iterator_range<IterT> Operands)1630e8d8bef9SDimitry Andric   VPWidenGEPRecipe(GetElementPtrInst *GEP, iterator_range<IterT> Operands)
16317a6dacacSDimitry Andric       : VPRecipeWithIRFlags(VPDef::VPWidenGEPSC, Operands, *GEP) {}
1632e8d8bef9SDimitry Andric 
1633480093f4SDimitry Andric   ~VPWidenGEPRecipe() override = default;
1634480093f4SDimitry Andric 
clone()1635*0fca6ea1SDimitry Andric   VPWidenGEPRecipe *clone() override {
1636*0fca6ea1SDimitry Andric     return new VPWidenGEPRecipe(cast<GetElementPtrInst>(getUnderlyingInstr()),
1637*0fca6ea1SDimitry Andric                                 operands());
1638*0fca6ea1SDimitry Andric   }
1639*0fca6ea1SDimitry Andric 
1640bdd1243dSDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPWidenGEPSC)
1641480093f4SDimitry Andric 
1642480093f4SDimitry Andric   /// Generate the gep nodes.
1643480093f4SDimitry Andric   void execute(VPTransformState &State) override;
1644480093f4SDimitry Andric 
1645fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1646480093f4SDimitry Andric   /// Print the recipe.
16475ffd83dbSDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
16485ffd83dbSDimitry Andric              VPSlotTracker &SlotTracker) const override;
1649fe6060f1SDimitry Andric #endif
1650480093f4SDimitry Andric };
1651480093f4SDimitry Andric 
1652647cbc5dSDimitry Andric /// A recipe to compute the pointers for widened memory accesses of IndexTy for
1653647cbc5dSDimitry Andric /// all parts. If IsReverse is true, compute pointers for accessing the input in
1654647cbc5dSDimitry Andric /// reverse order per part.
16557a6dacacSDimitry Andric class VPVectorPointerRecipe : public VPRecipeWithIRFlags {
1656647cbc5dSDimitry Andric   Type *IndexedTy;
1657647cbc5dSDimitry Andric   bool IsReverse;
1658647cbc5dSDimitry Andric 
1659647cbc5dSDimitry Andric public:
VPVectorPointerRecipe(VPValue * Ptr,Type * IndexedTy,bool IsReverse,bool IsInBounds,DebugLoc DL)1660647cbc5dSDimitry Andric   VPVectorPointerRecipe(VPValue *Ptr, Type *IndexedTy, bool IsReverse,
16611db9f3b2SDimitry Andric                         bool IsInBounds, DebugLoc DL)
16621db9f3b2SDimitry Andric       : VPRecipeWithIRFlags(VPDef::VPVectorPointerSC, ArrayRef<VPValue *>(Ptr),
16631db9f3b2SDimitry Andric                             GEPFlagsTy(IsInBounds), DL),
16647a6dacacSDimitry Andric         IndexedTy(IndexedTy), IsReverse(IsReverse) {}
1665647cbc5dSDimitry Andric 
1666647cbc5dSDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPVectorPointerSC)
1667647cbc5dSDimitry Andric 
1668647cbc5dSDimitry Andric   void execute(VPTransformState &State) override;
1669647cbc5dSDimitry Andric 
onlyFirstLaneUsed(const VPValue * Op)1670647cbc5dSDimitry Andric   bool onlyFirstLaneUsed(const VPValue *Op) const override {
1671647cbc5dSDimitry Andric     assert(is_contained(operands(), Op) &&
1672647cbc5dSDimitry Andric            "Op must be an operand of the recipe");
1673647cbc5dSDimitry Andric     return true;
1674647cbc5dSDimitry Andric   }
1675647cbc5dSDimitry Andric 
clone()1676*0fca6ea1SDimitry Andric   VPVectorPointerRecipe *clone() override {
1677*0fca6ea1SDimitry Andric     return new VPVectorPointerRecipe(getOperand(0), IndexedTy, IsReverse,
1678*0fca6ea1SDimitry Andric                                      isInBounds(), getDebugLoc());
1679*0fca6ea1SDimitry Andric   }
1680*0fca6ea1SDimitry Andric 
1681647cbc5dSDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1682647cbc5dSDimitry Andric   /// Print the recipe.
1683647cbc5dSDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
1684647cbc5dSDimitry Andric              VPSlotTracker &SlotTracker) const override;
1685647cbc5dSDimitry Andric #endif
1686647cbc5dSDimitry Andric };
1687647cbc5dSDimitry Andric 
168804eeddc0SDimitry Andric /// A pure virtual base class for all recipes modeling header phis, including
168904eeddc0SDimitry Andric /// phis for first order recurrences, pointer inductions and reductions. The
169004eeddc0SDimitry Andric /// start value is the first operand of the recipe and the incoming value from
169104eeddc0SDimitry Andric /// the backedge is the second operand.
1692bdd1243dSDimitry Andric ///
1693bdd1243dSDimitry Andric /// Inductions are modeled using the following sub-classes:
1694bdd1243dSDimitry Andric ///  * VPCanonicalIVPHIRecipe: Canonical scalar induction of the vector loop,
1695bdd1243dSDimitry Andric ///    starting at a specified value (zero for the main vector loop, the resume
1696bdd1243dSDimitry Andric ///    value for the epilogue vector loop) and stepping by 1. The induction
1697bdd1243dSDimitry Andric ///    controls exiting of the vector loop by comparing against the vector trip
1698bdd1243dSDimitry Andric ///    count. Produces a single scalar PHI for the induction value per
1699bdd1243dSDimitry Andric ///    iteration.
1700bdd1243dSDimitry Andric ///  * VPWidenIntOrFpInductionRecipe: Generates vector values for integer and
1701bdd1243dSDimitry Andric ///    floating point inductions with arbitrary start and step values. Produces
1702bdd1243dSDimitry Andric ///    a vector PHI per-part.
1703bdd1243dSDimitry Andric ///  * VPDerivedIVRecipe: Converts the canonical IV value to the corresponding
1704bdd1243dSDimitry Andric ///    value of an IV with different start and step values. Produces a single
1705bdd1243dSDimitry Andric ///    scalar value per iteration
1706bdd1243dSDimitry Andric ///  * VPScalarIVStepsRecipe: Generates scalar values per-lane based on a
1707bdd1243dSDimitry Andric ///    canonical or derived induction.
1708bdd1243dSDimitry Andric ///  * VPWidenPointerInductionRecipe: Generate vector and scalar values for a
1709bdd1243dSDimitry Andric ///    pointer induction. Produces either a vector PHI per-part or scalar values
1710bdd1243dSDimitry Andric ///    per-lane based on the canonical induction.
17117a6dacacSDimitry Andric class VPHeaderPHIRecipe : public VPSingleDefRecipe {
1712fe6060f1SDimitry Andric protected:
171306c3fb27SDimitry Andric   VPHeaderPHIRecipe(unsigned char VPDefID, Instruction *UnderlyingInstr,
17145f757f3fSDimitry Andric                     VPValue *Start = nullptr, DebugLoc DL = {})
VPSingleDefRecipe(VPDefID,ArrayRef<VPValue * > (),UnderlyingInstr,DL)17157a6dacacSDimitry Andric       : VPSingleDefRecipe(VPDefID, ArrayRef<VPValue *>(), UnderlyingInstr, DL) {
1716fe6060f1SDimitry Andric     if (Start)
1717fe6060f1SDimitry Andric       addOperand(Start);
1718fe6060f1SDimitry Andric   }
1719e8d8bef9SDimitry Andric 
17200b57cec5SDimitry Andric public:
172104eeddc0SDimitry Andric   ~VPHeaderPHIRecipe() override = default;
1722fe6060f1SDimitry Andric 
172304eeddc0SDimitry Andric   /// Method to support type inquiry through isa, cast, and dyn_cast.
classof(const VPRecipeBase * B)172404eeddc0SDimitry Andric   static inline bool classof(const VPRecipeBase *B) {
1725bdd1243dSDimitry Andric     return B->getVPDefID() >= VPDef::VPFirstHeaderPHISC &&
172606c3fb27SDimitry Andric            B->getVPDefID() <= VPDef::VPLastHeaderPHISC;
172704eeddc0SDimitry Andric   }
classof(const VPValue * V)172804eeddc0SDimitry Andric   static inline bool classof(const VPValue *V) {
1729bdd1243dSDimitry Andric     auto *B = V->getDefiningRecipe();
1730bdd1243dSDimitry Andric     return B && B->getVPDefID() >= VPRecipeBase::VPFirstHeaderPHISC &&
173106c3fb27SDimitry Andric            B->getVPDefID() <= VPRecipeBase::VPLastHeaderPHISC;
173204eeddc0SDimitry Andric   }
173304eeddc0SDimitry Andric 
173404eeddc0SDimitry Andric   /// Generate the phi nodes.
173504eeddc0SDimitry Andric   void execute(VPTransformState &State) override = 0;
173604eeddc0SDimitry Andric 
173704eeddc0SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
173804eeddc0SDimitry Andric   /// Print the recipe.
173904eeddc0SDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
174004eeddc0SDimitry Andric              VPSlotTracker &SlotTracker) const override = 0;
174104eeddc0SDimitry Andric #endif
174204eeddc0SDimitry Andric 
174304eeddc0SDimitry Andric   /// Returns the start value of the phi, if one is set.
getStartValue()174404eeddc0SDimitry Andric   VPValue *getStartValue() {
174504eeddc0SDimitry Andric     return getNumOperands() == 0 ? nullptr : getOperand(0);
174604eeddc0SDimitry Andric   }
getStartValue()174781ad6265SDimitry Andric   VPValue *getStartValue() const {
174881ad6265SDimitry Andric     return getNumOperands() == 0 ? nullptr : getOperand(0);
174981ad6265SDimitry Andric   }
175004eeddc0SDimitry Andric 
1751bdd1243dSDimitry Andric   /// Update the start value of the recipe.
setStartValue(VPValue * V)1752bdd1243dSDimitry Andric   void setStartValue(VPValue *V) { setOperand(0, V); }
1753bdd1243dSDimitry Andric 
175404eeddc0SDimitry Andric   /// Returns the incoming value from the loop backedge.
getBackedgeValue()175506c3fb27SDimitry Andric   virtual VPValue *getBackedgeValue() {
175604eeddc0SDimitry Andric     return getOperand(1);
175704eeddc0SDimitry Andric   }
175804eeddc0SDimitry Andric 
175904eeddc0SDimitry Andric   /// Returns the backedge value as a recipe. The backedge value is guaranteed
176004eeddc0SDimitry Andric   /// to be a recipe.
getBackedgeRecipe()176106c3fb27SDimitry Andric   virtual VPRecipeBase &getBackedgeRecipe() {
1762bdd1243dSDimitry Andric     return *getBackedgeValue()->getDefiningRecipe();
176304eeddc0SDimitry Andric   }
176404eeddc0SDimitry Andric };
176504eeddc0SDimitry Andric 
176606c3fb27SDimitry Andric /// A recipe for handling phi nodes of integer and floating-point inductions,
176706c3fb27SDimitry Andric /// producing their vector values.
176806c3fb27SDimitry Andric class VPWidenIntOrFpInductionRecipe : public VPHeaderPHIRecipe {
176906c3fb27SDimitry Andric   PHINode *IV;
177006c3fb27SDimitry Andric   TruncInst *Trunc;
177106c3fb27SDimitry Andric   const InductionDescriptor &IndDesc;
177206c3fb27SDimitry Andric 
177306c3fb27SDimitry Andric public:
VPWidenIntOrFpInductionRecipe(PHINode * IV,VPValue * Start,VPValue * Step,const InductionDescriptor & IndDesc)177406c3fb27SDimitry Andric   VPWidenIntOrFpInductionRecipe(PHINode *IV, VPValue *Start, VPValue *Step,
177506c3fb27SDimitry Andric                                 const InductionDescriptor &IndDesc)
177606c3fb27SDimitry Andric       : VPHeaderPHIRecipe(VPDef::VPWidenIntOrFpInductionSC, IV, Start), IV(IV),
177706c3fb27SDimitry Andric         Trunc(nullptr), IndDesc(IndDesc) {
177806c3fb27SDimitry Andric     addOperand(Step);
177906c3fb27SDimitry Andric   }
178006c3fb27SDimitry Andric 
VPWidenIntOrFpInductionRecipe(PHINode * IV,VPValue * Start,VPValue * Step,const InductionDescriptor & IndDesc,TruncInst * Trunc)178106c3fb27SDimitry Andric   VPWidenIntOrFpInductionRecipe(PHINode *IV, VPValue *Start, VPValue *Step,
178206c3fb27SDimitry Andric                                 const InductionDescriptor &IndDesc,
178306c3fb27SDimitry Andric                                 TruncInst *Trunc)
178406c3fb27SDimitry Andric       : VPHeaderPHIRecipe(VPDef::VPWidenIntOrFpInductionSC, Trunc, Start),
178506c3fb27SDimitry Andric         IV(IV), Trunc(Trunc), IndDesc(IndDesc) {
178606c3fb27SDimitry Andric     addOperand(Step);
178706c3fb27SDimitry Andric   }
178806c3fb27SDimitry Andric 
178906c3fb27SDimitry Andric   ~VPWidenIntOrFpInductionRecipe() override = default;
179006c3fb27SDimitry Andric 
clone()1791*0fca6ea1SDimitry Andric   VPWidenIntOrFpInductionRecipe *clone() override {
1792*0fca6ea1SDimitry Andric     return new VPWidenIntOrFpInductionRecipe(IV, getStartValue(),
1793*0fca6ea1SDimitry Andric                                              getStepValue(), IndDesc, Trunc);
1794*0fca6ea1SDimitry Andric   }
1795*0fca6ea1SDimitry Andric 
179606c3fb27SDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPWidenIntOrFpInductionSC)
179706c3fb27SDimitry Andric 
179806c3fb27SDimitry Andric   /// Generate the vectorized and scalarized versions of the phi node as
179906c3fb27SDimitry Andric   /// needed by their users.
180006c3fb27SDimitry Andric   void execute(VPTransformState &State) override;
180106c3fb27SDimitry Andric 
180206c3fb27SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
180306c3fb27SDimitry Andric   /// Print the recipe.
180406c3fb27SDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
180506c3fb27SDimitry Andric              VPSlotTracker &SlotTracker) const override;
180606c3fb27SDimitry Andric #endif
180706c3fb27SDimitry Andric 
getBackedgeValue()180806c3fb27SDimitry Andric   VPValue *getBackedgeValue() override {
180906c3fb27SDimitry Andric     // TODO: All operands of base recipe must exist and be at same index in
181006c3fb27SDimitry Andric     // derived recipe.
181106c3fb27SDimitry Andric     llvm_unreachable(
181206c3fb27SDimitry Andric         "VPWidenIntOrFpInductionRecipe generates its own backedge value");
181306c3fb27SDimitry Andric   }
181406c3fb27SDimitry Andric 
getBackedgeRecipe()181506c3fb27SDimitry Andric   VPRecipeBase &getBackedgeRecipe() override {
181606c3fb27SDimitry Andric     // TODO: All operands of base recipe must exist and be at same index in
181706c3fb27SDimitry Andric     // derived recipe.
181806c3fb27SDimitry Andric     llvm_unreachable(
181906c3fb27SDimitry Andric         "VPWidenIntOrFpInductionRecipe generates its own backedge value");
182006c3fb27SDimitry Andric   }
182106c3fb27SDimitry Andric 
182206c3fb27SDimitry Andric   /// Returns the step value of the induction.
getStepValue()182306c3fb27SDimitry Andric   VPValue *getStepValue() { return getOperand(1); }
getStepValue()182406c3fb27SDimitry Andric   const VPValue *getStepValue() const { return getOperand(1); }
182506c3fb27SDimitry Andric 
182606c3fb27SDimitry Andric   /// Returns the first defined value as TruncInst, if it is one or nullptr
182706c3fb27SDimitry Andric   /// otherwise.
getTruncInst()182806c3fb27SDimitry Andric   TruncInst *getTruncInst() { return Trunc; }
getTruncInst()182906c3fb27SDimitry Andric   const TruncInst *getTruncInst() const { return Trunc; }
183006c3fb27SDimitry Andric 
getPHINode()183106c3fb27SDimitry Andric   PHINode *getPHINode() { return IV; }
183206c3fb27SDimitry Andric 
183306c3fb27SDimitry Andric   /// Returns the induction descriptor for the recipe.
getInductionDescriptor()183406c3fb27SDimitry Andric   const InductionDescriptor &getInductionDescriptor() const { return IndDesc; }
183506c3fb27SDimitry Andric 
183606c3fb27SDimitry Andric   /// Returns true if the induction is canonical, i.e. starting at 0 and
1837*0fca6ea1SDimitry Andric   /// incremented by UF * VF (= the original IV is incremented by 1) and has the
1838*0fca6ea1SDimitry Andric   /// same type as the canonical induction.
183906c3fb27SDimitry Andric   bool isCanonical() const;
184006c3fb27SDimitry Andric 
184106c3fb27SDimitry Andric   /// Returns the scalar type of the induction.
getScalarType()18425f757f3fSDimitry Andric   Type *getScalarType() const {
184306c3fb27SDimitry Andric     return Trunc ? Trunc->getType() : IV->getType();
184406c3fb27SDimitry Andric   }
184506c3fb27SDimitry Andric };
184606c3fb27SDimitry Andric 
184781ad6265SDimitry Andric class VPWidenPointerInductionRecipe : public VPHeaderPHIRecipe {
184881ad6265SDimitry Andric   const InductionDescriptor &IndDesc;
184981ad6265SDimitry Andric 
18506246ae0bSDimitry Andric   bool IsScalarAfterVectorization;
18516246ae0bSDimitry Andric 
185281ad6265SDimitry Andric public:
185381ad6265SDimitry Andric   /// Create a new VPWidenPointerInductionRecipe for \p Phi with start value \p
185481ad6265SDimitry Andric   /// Start.
VPWidenPointerInductionRecipe(PHINode * Phi,VPValue * Start,VPValue * Step,const InductionDescriptor & IndDesc,bool IsScalarAfterVectorization)1855bdd1243dSDimitry Andric   VPWidenPointerInductionRecipe(PHINode *Phi, VPValue *Start, VPValue *Step,
185681ad6265SDimitry Andric                                 const InductionDescriptor &IndDesc,
18576246ae0bSDimitry Andric                                 bool IsScalarAfterVectorization)
1858bdd1243dSDimitry Andric       : VPHeaderPHIRecipe(VPDef::VPWidenPointerInductionSC, Phi),
1859bdd1243dSDimitry Andric         IndDesc(IndDesc),
18606246ae0bSDimitry Andric         IsScalarAfterVectorization(IsScalarAfterVectorization) {
186181ad6265SDimitry Andric     addOperand(Start);
1862bdd1243dSDimitry Andric     addOperand(Step);
186381ad6265SDimitry Andric   }
186481ad6265SDimitry Andric 
186581ad6265SDimitry Andric   ~VPWidenPointerInductionRecipe() override = default;
186681ad6265SDimitry Andric 
clone()1867*0fca6ea1SDimitry Andric   VPWidenPointerInductionRecipe *clone() override {
1868*0fca6ea1SDimitry Andric     return new VPWidenPointerInductionRecipe(
1869*0fca6ea1SDimitry Andric         cast<PHINode>(getUnderlyingInstr()), getOperand(0), getOperand(1),
1870*0fca6ea1SDimitry Andric         IndDesc, IsScalarAfterVectorization);
1871*0fca6ea1SDimitry Andric   }
1872*0fca6ea1SDimitry Andric 
1873bdd1243dSDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPWidenPointerInductionSC)
187481ad6265SDimitry Andric 
187581ad6265SDimitry Andric   /// Generate vector values for the pointer induction.
187681ad6265SDimitry Andric   void execute(VPTransformState &State) override;
187781ad6265SDimitry Andric 
187881ad6265SDimitry Andric   /// Returns true if only scalar values will be generated.
1879*0fca6ea1SDimitry Andric   bool onlyScalarsGenerated(bool IsScalable);
188081ad6265SDimitry Andric 
1881bdd1243dSDimitry Andric   /// Returns the induction descriptor for the recipe.
getInductionDescriptor()1882bdd1243dSDimitry Andric   const InductionDescriptor &getInductionDescriptor() const { return IndDesc; }
1883bdd1243dSDimitry Andric 
188481ad6265SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
188581ad6265SDimitry Andric   /// Print the recipe.
188681ad6265SDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
188781ad6265SDimitry Andric              VPSlotTracker &SlotTracker) const override;
188881ad6265SDimitry Andric #endif
188981ad6265SDimitry Andric };
189081ad6265SDimitry Andric 
1891*0fca6ea1SDimitry Andric /// A recipe for handling phis that are widened in the vector loop.
189204eeddc0SDimitry Andric /// In the VPlan native path, all incoming VPValues & VPBasicBlock pairs are
189304eeddc0SDimitry Andric /// managed in the recipe directly.
1894*0fca6ea1SDimitry Andric class VPWidenPHIRecipe : public VPSingleDefRecipe {
189504eeddc0SDimitry Andric   /// List of incoming blocks. Only used in the VPlan native path.
189604eeddc0SDimitry Andric   SmallVector<VPBasicBlock *, 2> IncomingBlocks;
189704eeddc0SDimitry Andric 
189804eeddc0SDimitry Andric public:
1899fe6060f1SDimitry Andric   /// Create a new VPWidenPHIRecipe for \p Phi with start value \p Start.
190004eeddc0SDimitry Andric   VPWidenPHIRecipe(PHINode *Phi, VPValue *Start = nullptr)
VPSingleDefRecipe(VPDef::VPWidenPHISC,ArrayRef<VPValue * > (),Phi)1901*0fca6ea1SDimitry Andric       : VPSingleDefRecipe(VPDef::VPWidenPHISC, ArrayRef<VPValue *>(), Phi) {
190204eeddc0SDimitry Andric     if (Start)
190304eeddc0SDimitry Andric       addOperand(Start);
1904e8d8bef9SDimitry Andric   }
1905e8d8bef9SDimitry Andric 
clone()1906*0fca6ea1SDimitry Andric   VPWidenPHIRecipe *clone() override {
1907*0fca6ea1SDimitry Andric     llvm_unreachable("cloning not implemented yet");
1908*0fca6ea1SDimitry Andric   }
1909*0fca6ea1SDimitry Andric 
19100b57cec5SDimitry Andric   ~VPWidenPHIRecipe() override = default;
19110b57cec5SDimitry Andric 
1912bdd1243dSDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPWidenPHISC)
19130b57cec5SDimitry Andric 
19140b57cec5SDimitry Andric   /// Generate the phi/select nodes.
19150b57cec5SDimitry Andric   void execute(VPTransformState &State) override;
19160b57cec5SDimitry Andric 
1917fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
19180b57cec5SDimitry Andric   /// Print the recipe.
19195ffd83dbSDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
19205ffd83dbSDimitry Andric              VPSlotTracker &SlotTracker) const override;
1921fe6060f1SDimitry Andric #endif
1922e8d8bef9SDimitry Andric 
1923fe6060f1SDimitry Andric   /// Adds a pair (\p IncomingV, \p IncomingBlock) to the phi.
addIncoming(VPValue * IncomingV,VPBasicBlock * IncomingBlock)1924fe6060f1SDimitry Andric   void addIncoming(VPValue *IncomingV, VPBasicBlock *IncomingBlock) {
1925fe6060f1SDimitry Andric     addOperand(IncomingV);
1926fe6060f1SDimitry Andric     IncomingBlocks.push_back(IncomingBlock);
1927fe6060f1SDimitry Andric   }
1928fe6060f1SDimitry Andric 
1929fe6060f1SDimitry Andric   /// Returns the \p I th incoming VPBasicBlock.
getIncomingBlock(unsigned I)1930fe6060f1SDimitry Andric   VPBasicBlock *getIncomingBlock(unsigned I) { return IncomingBlocks[I]; }
193104eeddc0SDimitry Andric 
193204eeddc0SDimitry Andric   /// Returns the \p I th incoming VPValue.
getIncomingValue(unsigned I)193304eeddc0SDimitry Andric   VPValue *getIncomingValue(unsigned I) { return getOperand(I); }
1934fe6060f1SDimitry Andric };
1935fe6060f1SDimitry Andric 
1936fe6060f1SDimitry Andric /// A recipe for handling first-order recurrence phis. The start value is the
1937fe6060f1SDimitry Andric /// first operand of the recipe and the incoming value from the backedge is the
1938fe6060f1SDimitry Andric /// second operand.
193904eeddc0SDimitry Andric struct VPFirstOrderRecurrencePHIRecipe : public VPHeaderPHIRecipe {
VPFirstOrderRecurrencePHIRecipeVPFirstOrderRecurrencePHIRecipe1940fe6060f1SDimitry Andric   VPFirstOrderRecurrencePHIRecipe(PHINode *Phi, VPValue &Start)
1941bdd1243dSDimitry Andric       : VPHeaderPHIRecipe(VPDef::VPFirstOrderRecurrencePHISC, Phi, &Start) {}
1942fe6060f1SDimitry Andric 
VP_CLASSOF_IMPLVPFirstOrderRecurrencePHIRecipe1943bdd1243dSDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPFirstOrderRecurrencePHISC)
1944bdd1243dSDimitry Andric 
194504eeddc0SDimitry Andric   static inline bool classof(const VPHeaderPHIRecipe *R) {
1946bdd1243dSDimitry Andric     return R->getVPDefID() == VPDef::VPFirstOrderRecurrencePHISC;
1947fe6060f1SDimitry Andric   }
1948fe6060f1SDimitry Andric 
cloneVPFirstOrderRecurrencePHIRecipe1949*0fca6ea1SDimitry Andric   VPFirstOrderRecurrencePHIRecipe *clone() override {
1950*0fca6ea1SDimitry Andric     return new VPFirstOrderRecurrencePHIRecipe(
1951*0fca6ea1SDimitry Andric         cast<PHINode>(getUnderlyingInstr()), *getOperand(0));
1952*0fca6ea1SDimitry Andric   }
1953*0fca6ea1SDimitry Andric 
1954fe6060f1SDimitry Andric   void execute(VPTransformState &State) override;
1955fe6060f1SDimitry Andric 
1956fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1957fe6060f1SDimitry Andric   /// Print the recipe.
1958fe6060f1SDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
1959fe6060f1SDimitry Andric              VPSlotTracker &SlotTracker) const override;
1960fe6060f1SDimitry Andric #endif
1961fe6060f1SDimitry Andric };
1962fe6060f1SDimitry Andric 
1963fe6060f1SDimitry Andric /// A recipe for handling reduction phis. The start value is the first operand
1964fe6060f1SDimitry Andric /// of the recipe and the incoming value from the backedge is the second
1965fe6060f1SDimitry Andric /// operand.
196604eeddc0SDimitry Andric class VPReductionPHIRecipe : public VPHeaderPHIRecipe {
1967fe6060f1SDimitry Andric   /// Descriptor for the reduction.
19680eae32dcSDimitry Andric   const RecurrenceDescriptor &RdxDesc;
1969fe6060f1SDimitry Andric 
1970fe6060f1SDimitry Andric   /// The phi is part of an in-loop reduction.
1971fe6060f1SDimitry Andric   bool IsInLoop;
1972fe6060f1SDimitry Andric 
1973fe6060f1SDimitry Andric   /// The phi is part of an ordered reduction. Requires IsInLoop to be true.
1974fe6060f1SDimitry Andric   bool IsOrdered;
1975fe6060f1SDimitry Andric 
1976fe6060f1SDimitry Andric public:
1977fe6060f1SDimitry Andric   /// Create a new VPReductionPHIRecipe for the reduction \p Phi described by \p
1978fe6060f1SDimitry Andric   /// RdxDesc.
19790eae32dcSDimitry Andric   VPReductionPHIRecipe(PHINode *Phi, const RecurrenceDescriptor &RdxDesc,
1980fe6060f1SDimitry Andric                        VPValue &Start, bool IsInLoop = false,
1981fe6060f1SDimitry Andric                        bool IsOrdered = false)
1982bdd1243dSDimitry Andric       : VPHeaderPHIRecipe(VPDef::VPReductionPHISC, Phi, &Start),
1983fe6060f1SDimitry Andric         RdxDesc(RdxDesc), IsInLoop(IsInLoop), IsOrdered(IsOrdered) {
1984fe6060f1SDimitry Andric     assert((!IsOrdered || IsInLoop) && "IsOrdered requires IsInLoop");
1985fe6060f1SDimitry Andric   }
1986fe6060f1SDimitry Andric 
1987fe6060f1SDimitry Andric   ~VPReductionPHIRecipe() override = default;
1988fe6060f1SDimitry Andric 
clone()1989*0fca6ea1SDimitry Andric   VPReductionPHIRecipe *clone() override {
1990*0fca6ea1SDimitry Andric     auto *R =
1991*0fca6ea1SDimitry Andric         new VPReductionPHIRecipe(cast<PHINode>(getUnderlyingInstr()), RdxDesc,
1992*0fca6ea1SDimitry Andric                                  *getOperand(0), IsInLoop, IsOrdered);
1993*0fca6ea1SDimitry Andric     R->addOperand(getBackedgeValue());
1994*0fca6ea1SDimitry Andric     return R;
1995*0fca6ea1SDimitry Andric   }
1996*0fca6ea1SDimitry Andric 
VP_CLASSOF_IMPL(VPDef::VPReductionPHISC)1997bdd1243dSDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPReductionPHISC)
1998bdd1243dSDimitry Andric 
199904eeddc0SDimitry Andric   static inline bool classof(const VPHeaderPHIRecipe *R) {
2000bdd1243dSDimitry Andric     return R->getVPDefID() == VPDef::VPReductionPHISC;
2001fe6060f1SDimitry Andric   }
2002fe6060f1SDimitry Andric 
2003fe6060f1SDimitry Andric   /// Generate the phi/select nodes.
2004fe6060f1SDimitry Andric   void execute(VPTransformState &State) override;
2005fe6060f1SDimitry Andric 
2006fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2007fe6060f1SDimitry Andric   /// Print the recipe.
2008fe6060f1SDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
2009fe6060f1SDimitry Andric              VPSlotTracker &SlotTracker) const override;
2010fe6060f1SDimitry Andric #endif
2011fe6060f1SDimitry Andric 
getRecurrenceDescriptor()20120eae32dcSDimitry Andric   const RecurrenceDescriptor &getRecurrenceDescriptor() const {
20130eae32dcSDimitry Andric     return RdxDesc;
20140eae32dcSDimitry Andric   }
2015fe6060f1SDimitry Andric 
2016fe6060f1SDimitry Andric   /// Returns true, if the phi is part of an ordered reduction.
isOrdered()2017fe6060f1SDimitry Andric   bool isOrdered() const { return IsOrdered; }
2018fe6060f1SDimitry Andric 
2019fe6060f1SDimitry Andric   /// Returns true, if the phi is part of an in-loop reduction.
isInLoop()2020fe6060f1SDimitry Andric   bool isInLoop() const { return IsInLoop; }
20210b57cec5SDimitry Andric };
20220b57cec5SDimitry Andric 
20230b57cec5SDimitry Andric /// A recipe for vectorizing a phi-node as a sequence of mask-based select
20240b57cec5SDimitry Andric /// instructions.
20257a6dacacSDimitry Andric class VPBlendRecipe : public VPSingleDefRecipe {
2026e8d8bef9SDimitry Andric public:
20275ffd83dbSDimitry Andric   /// The blend operation is a User of the incoming values and of their
2028*0fca6ea1SDimitry Andric   /// respective masks, ordered [I0, I1, M1, I2, M2, ...]. Note that the first
2029*0fca6ea1SDimitry Andric   /// incoming value does not have a mask associated.
VPBlendRecipe(PHINode * Phi,ArrayRef<VPValue * > Operands)20305ffd83dbSDimitry Andric   VPBlendRecipe(PHINode *Phi, ArrayRef<VPValue *> Operands)
20317a6dacacSDimitry Andric       : VPSingleDefRecipe(VPDef::VPBlendSC, Operands, Phi, Phi->getDebugLoc()) {
2032*0fca6ea1SDimitry Andric     assert((Operands.size() + 1) % 2 == 0 &&
2033*0fca6ea1SDimitry Andric            "Expected an odd number of operands");
2034*0fca6ea1SDimitry Andric   }
2035*0fca6ea1SDimitry Andric 
clone()2036*0fca6ea1SDimitry Andric   VPBlendRecipe *clone() override {
2037*0fca6ea1SDimitry Andric     SmallVector<VPValue *> Ops(operands());
2038*0fca6ea1SDimitry Andric     return new VPBlendRecipe(cast<PHINode>(getUnderlyingValue()), Ops);
20390b57cec5SDimitry Andric   }
20400b57cec5SDimitry Andric 
VP_CLASSOF_IMPL(VPDef::VPBlendSC)2041bdd1243dSDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPBlendSC)
20420b57cec5SDimitry Andric 
2043*0fca6ea1SDimitry Andric   /// Return the number of incoming values, taking into account that the first
20445ffd83dbSDimitry Andric   /// incoming value has no mask.
2045e8d8bef9SDimitry Andric   unsigned getNumIncomingValues() const { return (getNumOperands() + 1) / 2; }
20465ffd83dbSDimitry Andric 
20475ffd83dbSDimitry Andric   /// Return incoming value number \p Idx.
getIncomingValue(unsigned Idx)2048*0fca6ea1SDimitry Andric   VPValue *getIncomingValue(unsigned Idx) const {
2049*0fca6ea1SDimitry Andric     return Idx == 0 ? getOperand(0) : getOperand(Idx * 2 - 1);
2050*0fca6ea1SDimitry Andric   }
20515ffd83dbSDimitry Andric 
20525ffd83dbSDimitry Andric   /// Return mask number \p Idx.
getMask(unsigned Idx)2053*0fca6ea1SDimitry Andric   VPValue *getMask(unsigned Idx) const {
2054*0fca6ea1SDimitry Andric     assert(Idx > 0 && "First index has no mask associated.");
2055*0fca6ea1SDimitry Andric     return getOperand(Idx * 2);
2056*0fca6ea1SDimitry Andric   }
20575ffd83dbSDimitry Andric 
20580b57cec5SDimitry Andric   /// Generate the phi/select nodes.
20590b57cec5SDimitry Andric   void execute(VPTransformState &State) override;
20600b57cec5SDimitry Andric 
2061fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
20620b57cec5SDimitry Andric   /// Print the recipe.
20635ffd83dbSDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
20645ffd83dbSDimitry Andric              VPSlotTracker &SlotTracker) const override;
2065fe6060f1SDimitry Andric #endif
20661fd87a68SDimitry Andric 
20671fd87a68SDimitry Andric   /// Returns true if the recipe only uses the first lane of operand \p Op.
onlyFirstLaneUsed(const VPValue * Op)20681fd87a68SDimitry Andric   bool onlyFirstLaneUsed(const VPValue *Op) const override {
20691fd87a68SDimitry Andric     assert(is_contained(operands(), Op) &&
20701fd87a68SDimitry Andric            "Op must be an operand of the recipe");
20711fd87a68SDimitry Andric     // Recursing through Blend recipes only, must terminate at header phi's the
20721fd87a68SDimitry Andric     // latest.
207381ad6265SDimitry Andric     return all_of(users(),
207481ad6265SDimitry Andric                   [this](VPUser *U) { return U->onlyFirstLaneUsed(this); });
20751fd87a68SDimitry Andric   }
20760b57cec5SDimitry Andric };
20770b57cec5SDimitry Andric 
20780b57cec5SDimitry Andric /// VPInterleaveRecipe is a recipe for transforming an interleave group of load
2079e8d8bef9SDimitry Andric /// or stores into one wide load/store and shuffles. The first operand of a
2080e8d8bef9SDimitry Andric /// VPInterleave recipe is the address, followed by the stored values, followed
2081e8d8bef9SDimitry Andric /// by an optional mask.
2082fe6060f1SDimitry Andric class VPInterleaveRecipe : public VPRecipeBase {
20830b57cec5SDimitry Andric   const InterleaveGroup<Instruction> *IG;
2084e8d8bef9SDimitry Andric 
208506c3fb27SDimitry Andric   /// Indicates if the interleave group is in a conditional block and requires a
208606c3fb27SDimitry Andric   /// mask.
2087e8d8bef9SDimitry Andric   bool HasMask = false;
20880b57cec5SDimitry Andric 
208906c3fb27SDimitry Andric   /// Indicates if gaps between members of the group need to be masked out or if
209006c3fb27SDimitry Andric   /// unusued gaps can be loaded speculatively.
209106c3fb27SDimitry Andric   bool NeedsMaskForGaps = false;
209206c3fb27SDimitry Andric 
20930b57cec5SDimitry Andric public:
VPInterleaveRecipe(const InterleaveGroup<Instruction> * IG,VPValue * Addr,ArrayRef<VPValue * > StoredValues,VPValue * Mask,bool NeedsMaskForGaps)2094480093f4SDimitry Andric   VPInterleaveRecipe(const InterleaveGroup<Instruction> *IG, VPValue *Addr,
209506c3fb27SDimitry Andric                      ArrayRef<VPValue *> StoredValues, VPValue *Mask,
209606c3fb27SDimitry Andric                      bool NeedsMaskForGaps)
209706c3fb27SDimitry Andric       : VPRecipeBase(VPDef::VPInterleaveSC, {Addr}), IG(IG),
209806c3fb27SDimitry Andric         NeedsMaskForGaps(NeedsMaskForGaps) {
2099e8d8bef9SDimitry Andric     for (unsigned i = 0; i < IG->getFactor(); ++i)
2100e8d8bef9SDimitry Andric       if (Instruction *I = IG->getMember(i)) {
2101e8d8bef9SDimitry Andric         if (I->getType()->isVoidTy())
2102e8d8bef9SDimitry Andric           continue;
2103e8d8bef9SDimitry Andric         new VPValue(I, this);
2104e8d8bef9SDimitry Andric       }
2105e8d8bef9SDimitry Andric 
2106e8d8bef9SDimitry Andric     for (auto *SV : StoredValues)
2107e8d8bef9SDimitry Andric       addOperand(SV);
2108e8d8bef9SDimitry Andric     if (Mask) {
2109e8d8bef9SDimitry Andric       HasMask = true;
2110e8d8bef9SDimitry Andric       addOperand(Mask);
2111e8d8bef9SDimitry Andric     }
21120b57cec5SDimitry Andric   }
21130b57cec5SDimitry Andric   ~VPInterleaveRecipe() override = default;
21140b57cec5SDimitry Andric 
clone()2115*0fca6ea1SDimitry Andric   VPInterleaveRecipe *clone() override {
2116*0fca6ea1SDimitry Andric     return new VPInterleaveRecipe(IG, getAddr(), getStoredValues(), getMask(),
2117*0fca6ea1SDimitry Andric                                   NeedsMaskForGaps);
2118*0fca6ea1SDimitry Andric   }
2119*0fca6ea1SDimitry Andric 
VP_CLASSOF_IMPL(VPDef::VPInterleaveSC)2120bdd1243dSDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPInterleaveSC)
21210b57cec5SDimitry Andric 
2122480093f4SDimitry Andric   /// Return the address accessed by this recipe.
2123480093f4SDimitry Andric   VPValue *getAddr() const {
2124e8d8bef9SDimitry Andric     return getOperand(0); // Address is the 1st, mandatory operand.
2125480093f4SDimitry Andric   }
2126480093f4SDimitry Andric 
2127480093f4SDimitry Andric   /// Return the mask used by this recipe. Note that a full mask is represented
2128480093f4SDimitry Andric   /// by a nullptr.
getMask()2129480093f4SDimitry Andric   VPValue *getMask() const {
2130480093f4SDimitry Andric     // Mask is optional and therefore the last, currently 2nd operand.
2131e8d8bef9SDimitry Andric     return HasMask ? getOperand(getNumOperands() - 1) : nullptr;
2132e8d8bef9SDimitry Andric   }
2133e8d8bef9SDimitry Andric 
2134e8d8bef9SDimitry Andric   /// Return the VPValues stored by this interleave group. If it is a load
2135e8d8bef9SDimitry Andric   /// interleave group, return an empty ArrayRef.
getStoredValues()2136e8d8bef9SDimitry Andric   ArrayRef<VPValue *> getStoredValues() const {
2137e8d8bef9SDimitry Andric     // The first operand is the address, followed by the stored values, followed
2138e8d8bef9SDimitry Andric     // by an optional mask.
2139e8d8bef9SDimitry Andric     return ArrayRef<VPValue *>(op_begin(), getNumOperands())
2140349cc55cSDimitry Andric         .slice(1, getNumStoreOperands());
2141480093f4SDimitry Andric   }
2142480093f4SDimitry Andric 
21430b57cec5SDimitry Andric   /// Generate the wide load or store, and shuffles.
21440b57cec5SDimitry Andric   void execute(VPTransformState &State) override;
21450b57cec5SDimitry Andric 
2146fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
21470b57cec5SDimitry Andric   /// Print the recipe.
21485ffd83dbSDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
21495ffd83dbSDimitry Andric              VPSlotTracker &SlotTracker) const override;
2150fe6060f1SDimitry Andric #endif
21510b57cec5SDimitry Andric 
getInterleaveGroup()21520b57cec5SDimitry Andric   const InterleaveGroup<Instruction> *getInterleaveGroup() { return IG; }
2153349cc55cSDimitry Andric 
2154349cc55cSDimitry Andric   /// Returns the number of stored operands of this interleave group. Returns 0
2155349cc55cSDimitry Andric   /// for load interleave groups.
getNumStoreOperands()2156349cc55cSDimitry Andric   unsigned getNumStoreOperands() const {
2157349cc55cSDimitry Andric     return getNumOperands() - (HasMask ? 2 : 1);
2158349cc55cSDimitry Andric   }
215981ad6265SDimitry Andric 
216081ad6265SDimitry Andric   /// The recipe only uses the first lane of the address.
onlyFirstLaneUsed(const VPValue * Op)216181ad6265SDimitry Andric   bool onlyFirstLaneUsed(const VPValue *Op) const override {
216281ad6265SDimitry Andric     assert(is_contained(operands(), Op) &&
216381ad6265SDimitry Andric            "Op must be an operand of the recipe");
2164bdd1243dSDimitry Andric     return Op == getAddr() && !llvm::is_contained(getStoredValues(), Op);
216581ad6265SDimitry Andric   }
2166*0fca6ea1SDimitry Andric 
getInsertPos()2167*0fca6ea1SDimitry Andric   Instruction *getInsertPos() const { return IG->getInsertPos(); }
21680b57cec5SDimitry Andric };
21690b57cec5SDimitry Andric 
2170e8d8bef9SDimitry Andric /// A recipe to represent inloop reduction operations, performing a reduction on
2171e8d8bef9SDimitry Andric /// a vector operand into a scalar value, and adding the result to a chain.
2172e8d8bef9SDimitry Andric /// The Operands are {ChainOp, VecOp, [Condition]}.
21737a6dacacSDimitry Andric class VPReductionRecipe : public VPSingleDefRecipe {
2174e8d8bef9SDimitry Andric   /// The recurrence decriptor for the reduction in question.
21755f757f3fSDimitry Andric   const RecurrenceDescriptor &RdxDesc;
2176*0fca6ea1SDimitry Andric   bool IsOrdered;
2177*0fca6ea1SDimitry Andric   /// Whether the reduction is conditional.
2178*0fca6ea1SDimitry Andric   bool IsConditional = false;
2179*0fca6ea1SDimitry Andric 
2180*0fca6ea1SDimitry Andric protected:
VPReductionRecipe(const unsigned char SC,const RecurrenceDescriptor & R,Instruction * I,ArrayRef<VPValue * > Operands,VPValue * CondOp,bool IsOrdered)2181*0fca6ea1SDimitry Andric   VPReductionRecipe(const unsigned char SC, const RecurrenceDescriptor &R,
2182*0fca6ea1SDimitry Andric                     Instruction *I, ArrayRef<VPValue *> Operands,
2183*0fca6ea1SDimitry Andric                     VPValue *CondOp, bool IsOrdered)
2184*0fca6ea1SDimitry Andric       : VPSingleDefRecipe(SC, Operands, I), RdxDesc(R), IsOrdered(IsOrdered) {
2185*0fca6ea1SDimitry Andric     if (CondOp) {
2186*0fca6ea1SDimitry Andric       IsConditional = true;
2187*0fca6ea1SDimitry Andric       addOperand(CondOp);
2188*0fca6ea1SDimitry Andric     }
2189*0fca6ea1SDimitry Andric   }
2190e8d8bef9SDimitry Andric 
2191e8d8bef9SDimitry Andric public:
VPReductionRecipe(const RecurrenceDescriptor & R,Instruction * I,VPValue * ChainOp,VPValue * VecOp,VPValue * CondOp,bool IsOrdered)21925f757f3fSDimitry Andric   VPReductionRecipe(const RecurrenceDescriptor &R, Instruction *I,
2193*0fca6ea1SDimitry Andric                     VPValue *ChainOp, VPValue *VecOp, VPValue *CondOp,
2194*0fca6ea1SDimitry Andric                     bool IsOrdered)
2195*0fca6ea1SDimitry Andric       : VPReductionRecipe(VPDef::VPReductionSC, R, I,
2196*0fca6ea1SDimitry Andric                           ArrayRef<VPValue *>({ChainOp, VecOp}), CondOp,
2197*0fca6ea1SDimitry Andric                           IsOrdered) {}
2198e8d8bef9SDimitry Andric 
2199e8d8bef9SDimitry Andric   ~VPReductionRecipe() override = default;
2200e8d8bef9SDimitry Andric 
clone()2201*0fca6ea1SDimitry Andric   VPReductionRecipe *clone() override {
2202*0fca6ea1SDimitry Andric     return new VPReductionRecipe(RdxDesc, getUnderlyingInstr(), getChainOp(),
2203*0fca6ea1SDimitry Andric                                  getVecOp(), getCondOp(), IsOrdered);
2204*0fca6ea1SDimitry Andric   }
2205*0fca6ea1SDimitry Andric 
classof(const VPRecipeBase * R)2206*0fca6ea1SDimitry Andric   static inline bool classof(const VPRecipeBase *R) {
2207*0fca6ea1SDimitry Andric     return R->getVPDefID() == VPRecipeBase::VPReductionSC ||
2208*0fca6ea1SDimitry Andric            R->getVPDefID() == VPRecipeBase::VPReductionEVLSC;
2209*0fca6ea1SDimitry Andric   }
2210*0fca6ea1SDimitry Andric 
classof(const VPUser * U)2211*0fca6ea1SDimitry Andric   static inline bool classof(const VPUser *U) {
2212*0fca6ea1SDimitry Andric     auto *R = dyn_cast<VPRecipeBase>(U);
2213*0fca6ea1SDimitry Andric     return R && classof(R);
2214*0fca6ea1SDimitry Andric   }
2215e8d8bef9SDimitry Andric 
2216e8d8bef9SDimitry Andric   /// Generate the reduction in the loop
2217e8d8bef9SDimitry Andric   void execute(VPTransformState &State) override;
2218e8d8bef9SDimitry Andric 
2219fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2220e8d8bef9SDimitry Andric   /// Print the recipe.
2221e8d8bef9SDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
2222e8d8bef9SDimitry Andric              VPSlotTracker &SlotTracker) const override;
2223fe6060f1SDimitry Andric #endif
2224e8d8bef9SDimitry Andric 
2225*0fca6ea1SDimitry Andric   /// Return the recurrence decriptor for the in-loop reduction.
getRecurrenceDescriptor()2226*0fca6ea1SDimitry Andric   const RecurrenceDescriptor &getRecurrenceDescriptor() const {
2227*0fca6ea1SDimitry Andric     return RdxDesc;
2228*0fca6ea1SDimitry Andric   }
2229*0fca6ea1SDimitry Andric   /// Return true if the in-loop reduction is ordered.
isOrdered()2230*0fca6ea1SDimitry Andric   bool isOrdered() const { return IsOrdered; };
2231*0fca6ea1SDimitry Andric   /// Return true if the in-loop reduction is conditional.
isConditional()2232*0fca6ea1SDimitry Andric   bool isConditional() const { return IsConditional; };
2233e8d8bef9SDimitry Andric   /// The VPValue of the scalar Chain being accumulated.
getChainOp()2234e8d8bef9SDimitry Andric   VPValue *getChainOp() const { return getOperand(0); }
2235e8d8bef9SDimitry Andric   /// The VPValue of the vector value to be reduced.
getVecOp()2236e8d8bef9SDimitry Andric   VPValue *getVecOp() const { return getOperand(1); }
2237e8d8bef9SDimitry Andric   /// The VPValue of the condition for the block.
getCondOp()2238e8d8bef9SDimitry Andric   VPValue *getCondOp() const {
2239*0fca6ea1SDimitry Andric     return isConditional() ? getOperand(getNumOperands() - 1) : nullptr;
2240*0fca6ea1SDimitry Andric   }
2241*0fca6ea1SDimitry Andric };
2242*0fca6ea1SDimitry Andric 
2243*0fca6ea1SDimitry Andric /// A recipe to represent inloop reduction operations with vector-predication
2244*0fca6ea1SDimitry Andric /// intrinsics, performing a reduction on a vector operand with the explicit
2245*0fca6ea1SDimitry Andric /// vector length (EVL) into a scalar value, and adding the result to a chain.
2246*0fca6ea1SDimitry Andric /// The Operands are {ChainOp, VecOp, EVL, [Condition]}.
2247*0fca6ea1SDimitry Andric class VPReductionEVLRecipe : public VPReductionRecipe {
2248*0fca6ea1SDimitry Andric public:
VPReductionEVLRecipe(VPReductionRecipe * R,VPValue * EVL,VPValue * CondOp)2249*0fca6ea1SDimitry Andric   VPReductionEVLRecipe(VPReductionRecipe *R, VPValue *EVL, VPValue *CondOp)
2250*0fca6ea1SDimitry Andric       : VPReductionRecipe(
2251*0fca6ea1SDimitry Andric             VPDef::VPReductionEVLSC, R->getRecurrenceDescriptor(),
2252*0fca6ea1SDimitry Andric             cast_or_null<Instruction>(R->getUnderlyingValue()),
2253*0fca6ea1SDimitry Andric             ArrayRef<VPValue *>({R->getChainOp(), R->getVecOp(), EVL}), CondOp,
2254*0fca6ea1SDimitry Andric             R->isOrdered()) {}
2255*0fca6ea1SDimitry Andric 
2256*0fca6ea1SDimitry Andric   ~VPReductionEVLRecipe() override = default;
2257*0fca6ea1SDimitry Andric 
clone()2258*0fca6ea1SDimitry Andric   VPReductionEVLRecipe *clone() override {
2259*0fca6ea1SDimitry Andric     llvm_unreachable("cloning not implemented yet");
2260*0fca6ea1SDimitry Andric   }
2261*0fca6ea1SDimitry Andric 
2262*0fca6ea1SDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPReductionEVLSC)
2263*0fca6ea1SDimitry Andric 
2264*0fca6ea1SDimitry Andric   /// Generate the reduction in the loop
2265*0fca6ea1SDimitry Andric   void execute(VPTransformState &State) override;
2266*0fca6ea1SDimitry Andric 
2267*0fca6ea1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2268*0fca6ea1SDimitry Andric   /// Print the recipe.
2269*0fca6ea1SDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
2270*0fca6ea1SDimitry Andric              VPSlotTracker &SlotTracker) const override;
2271*0fca6ea1SDimitry Andric #endif
2272*0fca6ea1SDimitry Andric 
2273*0fca6ea1SDimitry Andric   /// The VPValue of the explicit vector length.
getEVL()2274*0fca6ea1SDimitry Andric   VPValue *getEVL() const { return getOperand(2); }
2275*0fca6ea1SDimitry Andric 
2276*0fca6ea1SDimitry Andric   /// Returns true if the recipe only uses the first lane of operand \p Op.
onlyFirstLaneUsed(const VPValue * Op)2277*0fca6ea1SDimitry Andric   bool onlyFirstLaneUsed(const VPValue *Op) const override {
2278*0fca6ea1SDimitry Andric     assert(is_contained(operands(), Op) &&
2279*0fca6ea1SDimitry Andric            "Op must be an operand of the recipe");
2280*0fca6ea1SDimitry Andric     return Op == getEVL();
2281e8d8bef9SDimitry Andric   }
2282e8d8bef9SDimitry Andric };
2283e8d8bef9SDimitry Andric 
22840b57cec5SDimitry Andric /// VPReplicateRecipe replicates a given instruction producing multiple scalar
22850b57cec5SDimitry Andric /// copies of the original scalar type, one per lane, instead of producing a
22860b57cec5SDimitry Andric /// single copy of widened type for all lanes. If the instruction is known to be
22870b57cec5SDimitry Andric /// uniform only one copy, per lane zero, will be generated.
22887a6dacacSDimitry Andric class VPReplicateRecipe : public VPRecipeWithIRFlags {
22890b57cec5SDimitry Andric   /// Indicator if only a single replica per lane is needed.
22900b57cec5SDimitry Andric   bool IsUniform;
22910b57cec5SDimitry Andric 
22920b57cec5SDimitry Andric   /// Indicator if the replicas are also predicated.
22930b57cec5SDimitry Andric   bool IsPredicated;
22940b57cec5SDimitry Andric 
22950b57cec5SDimitry Andric public:
22965ffd83dbSDimitry Andric   template <typename IterT>
22975ffd83dbSDimitry Andric   VPReplicateRecipe(Instruction *I, iterator_range<IterT> Operands,
229806c3fb27SDimitry Andric                     bool IsUniform, VPValue *Mask = nullptr)
229906c3fb27SDimitry Andric       : VPRecipeWithIRFlags(VPDef::VPReplicateSC, Operands, *I),
23007a6dacacSDimitry Andric         IsUniform(IsUniform), IsPredicated(Mask) {
230106c3fb27SDimitry Andric     if (Mask)
230206c3fb27SDimitry Andric       addOperand(Mask);
23030b57cec5SDimitry Andric   }
23040b57cec5SDimitry Andric 
23050b57cec5SDimitry Andric   ~VPReplicateRecipe() override = default;
23060b57cec5SDimitry Andric 
clone()2307*0fca6ea1SDimitry Andric   VPReplicateRecipe *clone() override {
2308*0fca6ea1SDimitry Andric     auto *Copy =
2309*0fca6ea1SDimitry Andric         new VPReplicateRecipe(getUnderlyingInstr(), operands(), IsUniform,
2310*0fca6ea1SDimitry Andric                               isPredicated() ? getMask() : nullptr);
2311*0fca6ea1SDimitry Andric     Copy->transferFlags(*this);
2312*0fca6ea1SDimitry Andric     return Copy;
2313*0fca6ea1SDimitry Andric   }
2314*0fca6ea1SDimitry Andric 
2315bdd1243dSDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPReplicateSC)
23160b57cec5SDimitry Andric 
23170b57cec5SDimitry Andric   /// Generate replicas of the desired Ingredient. Replicas will be generated
23180b57cec5SDimitry Andric   /// for all parts and lanes unless a specific part and lane are specified in
23190b57cec5SDimitry Andric   /// the \p State.
23200b57cec5SDimitry Andric   void execute(VPTransformState &State) override;
23210b57cec5SDimitry Andric 
2322fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
23230b57cec5SDimitry Andric   /// Print the recipe.
23245ffd83dbSDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
23255ffd83dbSDimitry Andric              VPSlotTracker &SlotTracker) const override;
2326fe6060f1SDimitry Andric #endif
2327e8d8bef9SDimitry Andric 
isUniform()2328e8d8bef9SDimitry Andric   bool isUniform() const { return IsUniform; }
2329fe6060f1SDimitry Andric 
isPredicated()2330fe6060f1SDimitry Andric   bool isPredicated() const { return IsPredicated; }
23311fd87a68SDimitry Andric 
23321fd87a68SDimitry Andric   /// Returns true if the recipe only uses the first lane of operand \p Op.
onlyFirstLaneUsed(const VPValue * Op)23331fd87a68SDimitry Andric   bool onlyFirstLaneUsed(const VPValue *Op) const override {
23341fd87a68SDimitry Andric     assert(is_contained(operands(), Op) &&
23351fd87a68SDimitry Andric            "Op must be an operand of the recipe");
23361fd87a68SDimitry Andric     return isUniform();
23371fd87a68SDimitry Andric   }
233881ad6265SDimitry Andric 
233981ad6265SDimitry Andric   /// Returns true if the recipe uses scalars of operand \p Op.
usesScalars(const VPValue * Op)234081ad6265SDimitry Andric   bool usesScalars(const VPValue *Op) const override {
234181ad6265SDimitry Andric     assert(is_contained(operands(), Op) &&
234281ad6265SDimitry Andric            "Op must be an operand of the recipe");
234381ad6265SDimitry Andric     return true;
234481ad6265SDimitry Andric   }
234506c3fb27SDimitry Andric 
234606c3fb27SDimitry Andric   /// Returns true if the recipe is used by a widened recipe via an intervening
234706c3fb27SDimitry Andric   /// VPPredInstPHIRecipe. In this case, the scalar values should also be packed
234806c3fb27SDimitry Andric   /// in a vector.
234906c3fb27SDimitry Andric   bool shouldPack() const;
235006c3fb27SDimitry Andric 
235106c3fb27SDimitry Andric   /// Return the mask of a predicated VPReplicateRecipe.
getMask()235206c3fb27SDimitry Andric   VPValue *getMask() {
235306c3fb27SDimitry Andric     assert(isPredicated() && "Trying to get the mask of a unpredicated recipe");
235406c3fb27SDimitry Andric     return getOperand(getNumOperands() - 1);
235506c3fb27SDimitry Andric   }
2356*0fca6ea1SDimitry Andric 
getOpcode()2357*0fca6ea1SDimitry Andric   unsigned getOpcode() const { return getUnderlyingInstr()->getOpcode(); }
23580b57cec5SDimitry Andric };
23590b57cec5SDimitry Andric 
23600b57cec5SDimitry Andric /// A recipe for generating conditional branches on the bits of a mask.
2361fe6060f1SDimitry Andric class VPBranchOnMaskRecipe : public VPRecipeBase {
23620b57cec5SDimitry Andric public:
VPBranchOnMaskRecipe(VPValue * BlockInMask)2363fe6060f1SDimitry Andric   VPBranchOnMaskRecipe(VPValue *BlockInMask)
2364bdd1243dSDimitry Andric       : VPRecipeBase(VPDef::VPBranchOnMaskSC, {}) {
23650b57cec5SDimitry Andric     if (BlockInMask) // nullptr means all-one mask.
2366e8d8bef9SDimitry Andric       addOperand(BlockInMask);
23670b57cec5SDimitry Andric   }
23680b57cec5SDimitry Andric 
clone()2369*0fca6ea1SDimitry Andric   VPBranchOnMaskRecipe *clone() override {
2370*0fca6ea1SDimitry Andric     return new VPBranchOnMaskRecipe(getOperand(0));
2371*0fca6ea1SDimitry Andric   }
2372*0fca6ea1SDimitry Andric 
2373bdd1243dSDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPBranchOnMaskSC)
23740b57cec5SDimitry Andric 
23750b57cec5SDimitry Andric   /// Generate the extraction of the appropriate bit from the block mask and the
23760b57cec5SDimitry Andric   /// conditional branch.
23770b57cec5SDimitry Andric   void execute(VPTransformState &State) override;
23780b57cec5SDimitry Andric 
2379fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
23800b57cec5SDimitry Andric   /// Print the recipe.
print(raw_ostream & O,const Twine & Indent,VPSlotTracker & SlotTracker)23815ffd83dbSDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
23825ffd83dbSDimitry Andric              VPSlotTracker &SlotTracker) const override {
2383fe6060f1SDimitry Andric     O << Indent << "BRANCH-ON-MASK ";
23845ffd83dbSDimitry Andric     if (VPValue *Mask = getMask())
2385e8d8bef9SDimitry Andric       Mask->printAsOperand(O, SlotTracker);
23860b57cec5SDimitry Andric     else
23870b57cec5SDimitry Andric       O << " All-One";
23880b57cec5SDimitry Andric   }
2389fe6060f1SDimitry Andric #endif
23905ffd83dbSDimitry Andric 
23915ffd83dbSDimitry Andric   /// Return the mask used by this recipe. Note that a full mask is represented
23925ffd83dbSDimitry Andric   /// by a nullptr.
getMask()23935ffd83dbSDimitry Andric   VPValue *getMask() const {
2394e8d8bef9SDimitry Andric     assert(getNumOperands() <= 1 && "should have either 0 or 1 operands");
23955ffd83dbSDimitry Andric     // Mask is optional.
2396e8d8bef9SDimitry Andric     return getNumOperands() == 1 ? getOperand(0) : nullptr;
23975ffd83dbSDimitry Andric   }
239881ad6265SDimitry Andric 
239981ad6265SDimitry Andric   /// Returns true if the recipe uses scalars of operand \p Op.
usesScalars(const VPValue * Op)240081ad6265SDimitry Andric   bool usesScalars(const VPValue *Op) const override {
240181ad6265SDimitry Andric     assert(is_contained(operands(), Op) &&
240281ad6265SDimitry Andric            "Op must be an operand of the recipe");
240381ad6265SDimitry Andric     return true;
240481ad6265SDimitry Andric   }
24050b57cec5SDimitry Andric };
24060b57cec5SDimitry Andric 
24070b57cec5SDimitry Andric /// VPPredInstPHIRecipe is a recipe for generating the phi nodes needed when
24080b57cec5SDimitry Andric /// control converges back from a Branch-on-Mask. The phi nodes are needed in
24090b57cec5SDimitry Andric /// order to merge values that are set under such a branch and feed their uses.
24100b57cec5SDimitry Andric /// The phi nodes can be scalar or vector depending on the users of the value.
24110b57cec5SDimitry Andric /// This recipe works in concert with VPBranchOnMaskRecipe.
24127a6dacacSDimitry Andric class VPPredInstPHIRecipe : public VPSingleDefRecipe {
24130b57cec5SDimitry Andric public:
24140b57cec5SDimitry Andric   /// Construct a VPPredInstPHIRecipe given \p PredInst whose value needs a phi
24150b57cec5SDimitry Andric   /// nodes after merging back from a Branch-on-Mask.
VPPredInstPHIRecipe(VPValue * PredV)2416e8d8bef9SDimitry Andric   VPPredInstPHIRecipe(VPValue *PredV)
24177a6dacacSDimitry Andric       : VPSingleDefRecipe(VPDef::VPPredInstPHISC, PredV) {}
24180b57cec5SDimitry Andric   ~VPPredInstPHIRecipe() override = default;
24190b57cec5SDimitry Andric 
clone()2420*0fca6ea1SDimitry Andric   VPPredInstPHIRecipe *clone() override {
2421*0fca6ea1SDimitry Andric     return new VPPredInstPHIRecipe(getOperand(0));
2422*0fca6ea1SDimitry Andric   }
2423*0fca6ea1SDimitry Andric 
2424bdd1243dSDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPPredInstPHISC)
24250b57cec5SDimitry Andric 
24260b57cec5SDimitry Andric   /// Generates phi nodes for live-outs as needed to retain SSA form.
24270b57cec5SDimitry Andric   void execute(VPTransformState &State) override;
24280b57cec5SDimitry Andric 
2429fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
24300b57cec5SDimitry Andric   /// Print the recipe.
24315ffd83dbSDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
24325ffd83dbSDimitry Andric              VPSlotTracker &SlotTracker) const override;
2433fe6060f1SDimitry Andric #endif
243481ad6265SDimitry Andric 
243581ad6265SDimitry Andric   /// Returns true if the recipe uses scalars of operand \p Op.
usesScalars(const VPValue * Op)243681ad6265SDimitry Andric   bool usesScalars(const VPValue *Op) const override {
243781ad6265SDimitry Andric     assert(is_contained(operands(), Op) &&
243881ad6265SDimitry Andric            "Op must be an operand of the recipe");
243981ad6265SDimitry Andric     return true;
244081ad6265SDimitry Andric   }
24410b57cec5SDimitry Andric };
24420b57cec5SDimitry Andric 
2443*0fca6ea1SDimitry Andric /// A common base class for widening memory operations. An optional mask can be
2444*0fca6ea1SDimitry Andric /// provided as the last operand.
2445*0fca6ea1SDimitry Andric class VPWidenMemoryRecipe : public VPRecipeBase {
2446*0fca6ea1SDimitry Andric protected:
2447e8d8bef9SDimitry Andric   Instruction &Ingredient;
24480b57cec5SDimitry Andric 
2449*0fca6ea1SDimitry Andric   /// Whether the accessed addresses are consecutive.
2450349cc55cSDimitry Andric   bool Consecutive;
2451349cc55cSDimitry Andric 
2452*0fca6ea1SDimitry Andric   /// Whether the consecutive accessed addresses are in reverse order.
2453349cc55cSDimitry Andric   bool Reverse;
2454349cc55cSDimitry Andric 
2455*0fca6ea1SDimitry Andric   /// Whether the memory access is masked.
2456*0fca6ea1SDimitry Andric   bool IsMasked = false;
2457*0fca6ea1SDimitry Andric 
setMask(VPValue * Mask)24585ffd83dbSDimitry Andric   void setMask(VPValue *Mask) {
2459*0fca6ea1SDimitry Andric     assert(!IsMasked && "cannot re-set mask");
24605ffd83dbSDimitry Andric     if (!Mask)
24615ffd83dbSDimitry Andric       return;
2462e8d8bef9SDimitry Andric     addOperand(Mask);
2463*0fca6ea1SDimitry Andric     IsMasked = true;
24640b57cec5SDimitry Andric   }
24650b57cec5SDimitry Andric 
VPWidenMemoryRecipe(const char unsigned SC,Instruction & I,std::initializer_list<VPValue * > Operands,bool Consecutive,bool Reverse,DebugLoc DL)2466*0fca6ea1SDimitry Andric   VPWidenMemoryRecipe(const char unsigned SC, Instruction &I,
2467*0fca6ea1SDimitry Andric                       std::initializer_list<VPValue *> Operands,
2468*0fca6ea1SDimitry Andric                       bool Consecutive, bool Reverse, DebugLoc DL)
2469*0fca6ea1SDimitry Andric       : VPRecipeBase(SC, Operands, DL), Ingredient(I), Consecutive(Consecutive),
2470*0fca6ea1SDimitry Andric         Reverse(Reverse) {
2471*0fca6ea1SDimitry Andric     assert((Consecutive || !Reverse) && "Reverse implies consecutive");
24725ffd83dbSDimitry Andric   }
24735ffd83dbSDimitry Andric 
24745ffd83dbSDimitry Andric public:
clone()2475*0fca6ea1SDimitry Andric   VPWidenMemoryRecipe *clone() override {
2476*0fca6ea1SDimitry Andric     llvm_unreachable("cloning not supported");
24775ffd83dbSDimitry Andric   }
24785ffd83dbSDimitry Andric 
classof(const VPRecipeBase * R)2479*0fca6ea1SDimitry Andric   static inline bool classof(const VPRecipeBase *R) {
2480*0fca6ea1SDimitry Andric     return R->getVPDefID() == VPRecipeBase::VPWidenLoadSC ||
2481*0fca6ea1SDimitry Andric            R->getVPDefID() == VPRecipeBase::VPWidenStoreSC ||
2482*0fca6ea1SDimitry Andric            R->getVPDefID() == VPRecipeBase::VPWidenLoadEVLSC ||
2483*0fca6ea1SDimitry Andric            R->getVPDefID() == VPRecipeBase::VPWidenStoreEVLSC;
24845ffd83dbSDimitry Andric   }
24855ffd83dbSDimitry Andric 
classof(const VPUser * U)2486*0fca6ea1SDimitry Andric   static inline bool classof(const VPUser *U) {
2487*0fca6ea1SDimitry Andric     auto *R = dyn_cast<VPRecipeBase>(U);
2488*0fca6ea1SDimitry Andric     return R && classof(R);
2489*0fca6ea1SDimitry Andric   }
2490*0fca6ea1SDimitry Andric 
2491*0fca6ea1SDimitry Andric   /// Return whether the loaded-from / stored-to addresses are consecutive.
isConsecutive()2492*0fca6ea1SDimitry Andric   bool isConsecutive() const { return Consecutive; }
2493*0fca6ea1SDimitry Andric 
2494*0fca6ea1SDimitry Andric   /// Return whether the consecutive loaded/stored addresses are in reverse
2495*0fca6ea1SDimitry Andric   /// order.
isReverse()2496*0fca6ea1SDimitry Andric   bool isReverse() const { return Reverse; }
24970b57cec5SDimitry Andric 
2498480093f4SDimitry Andric   /// Return the address accessed by this recipe.
getAddr()2499*0fca6ea1SDimitry Andric   VPValue *getAddr() const { return getOperand(0); }
2500*0fca6ea1SDimitry Andric 
2501*0fca6ea1SDimitry Andric   /// Returns true if the recipe is masked.
isMasked()2502*0fca6ea1SDimitry Andric   bool isMasked() const { return IsMasked; }
2503480093f4SDimitry Andric 
2504480093f4SDimitry Andric   /// Return the mask used by this recipe. Note that a full mask is represented
2505480093f4SDimitry Andric   /// by a nullptr.
getMask()2506480093f4SDimitry Andric   VPValue *getMask() const {
25075ffd83dbSDimitry Andric     // Mask is optional and therefore the last operand.
2508e8d8bef9SDimitry Andric     return isMasked() ? getOperand(getNumOperands() - 1) : nullptr;
25095ffd83dbSDimitry Andric   }
25105ffd83dbSDimitry Andric 
2511*0fca6ea1SDimitry Andric   /// Generate the wide load/store.
execute(VPTransformState & State)2512*0fca6ea1SDimitry Andric   void execute(VPTransformState &State) override {
2513*0fca6ea1SDimitry Andric     llvm_unreachable("VPWidenMemoryRecipe should not be instantiated.");
2514480093f4SDimitry Andric   }
2515480093f4SDimitry Andric 
getIngredient()2516*0fca6ea1SDimitry Andric   Instruction &getIngredient() const { return Ingredient; }
2517*0fca6ea1SDimitry Andric };
2518349cc55cSDimitry Andric 
2519*0fca6ea1SDimitry Andric /// A recipe for widening load operations, using the address to load from and an
2520*0fca6ea1SDimitry Andric /// optional mask.
2521*0fca6ea1SDimitry Andric struct VPWidenLoadRecipe final : public VPWidenMemoryRecipe, public VPValue {
VPWidenLoadRecipefinal2522*0fca6ea1SDimitry Andric   VPWidenLoadRecipe(LoadInst &Load, VPValue *Addr, VPValue *Mask,
2523*0fca6ea1SDimitry Andric                     bool Consecutive, bool Reverse, DebugLoc DL)
2524*0fca6ea1SDimitry Andric       : VPWidenMemoryRecipe(VPDef::VPWidenLoadSC, Load, {Addr}, Consecutive,
2525*0fca6ea1SDimitry Andric                             Reverse, DL),
2526*0fca6ea1SDimitry Andric         VPValue(this, &Load) {
2527*0fca6ea1SDimitry Andric     setMask(Mask);
2528*0fca6ea1SDimitry Andric   }
2529349cc55cSDimitry Andric 
clonefinal2530*0fca6ea1SDimitry Andric   VPWidenLoadRecipe *clone() override {
2531*0fca6ea1SDimitry Andric     return new VPWidenLoadRecipe(cast<LoadInst>(Ingredient), getAddr(),
2532*0fca6ea1SDimitry Andric                                  getMask(), Consecutive, Reverse,
2533*0fca6ea1SDimitry Andric                                  getDebugLoc());
2534*0fca6ea1SDimitry Andric   }
2535*0fca6ea1SDimitry Andric 
2536*0fca6ea1SDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPWidenLoadSC);
2537*0fca6ea1SDimitry Andric 
2538*0fca6ea1SDimitry Andric   /// Generate a wide load or gather.
25390b57cec5SDimitry Andric   void execute(VPTransformState &State) override;
25400b57cec5SDimitry Andric 
2541fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
25420b57cec5SDimitry Andric   /// Print the recipe.
25435ffd83dbSDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
25445ffd83dbSDimitry Andric              VPSlotTracker &SlotTracker) const override;
2545fe6060f1SDimitry Andric #endif
25461fd87a68SDimitry Andric 
25471fd87a68SDimitry Andric   /// Returns true if the recipe only uses the first lane of operand \p Op.
onlyFirstLaneUsedfinal25481fd87a68SDimitry Andric   bool onlyFirstLaneUsed(const VPValue *Op) const override {
25491fd87a68SDimitry Andric     assert(is_contained(operands(), Op) &&
25501fd87a68SDimitry Andric            "Op must be an operand of the recipe");
2551*0fca6ea1SDimitry Andric     // Widened, consecutive loads operations only demand the first lane of
2552*0fca6ea1SDimitry Andric     // their address.
2553*0fca6ea1SDimitry Andric     return Op == getAddr() && isConsecutive();
2554*0fca6ea1SDimitry Andric   }
2555*0fca6ea1SDimitry Andric };
25561fd87a68SDimitry Andric 
2557*0fca6ea1SDimitry Andric /// A recipe for widening load operations with vector-predication intrinsics,
2558*0fca6ea1SDimitry Andric /// using the address to load from, the explicit vector length and an optional
2559*0fca6ea1SDimitry Andric /// mask.
2560*0fca6ea1SDimitry Andric struct VPWidenLoadEVLRecipe final : public VPWidenMemoryRecipe, public VPValue {
VPWidenLoadEVLRecipefinal2561*0fca6ea1SDimitry Andric   VPWidenLoadEVLRecipe(VPWidenLoadRecipe *L, VPValue *EVL, VPValue *Mask)
2562*0fca6ea1SDimitry Andric       : VPWidenMemoryRecipe(VPDef::VPWidenLoadEVLSC, L->getIngredient(),
2563*0fca6ea1SDimitry Andric                             {L->getAddr(), EVL}, L->isConsecutive(),
2564*0fca6ea1SDimitry Andric                             L->isReverse(), L->getDebugLoc()),
2565*0fca6ea1SDimitry Andric         VPValue(this, &getIngredient()) {
2566*0fca6ea1SDimitry Andric     setMask(Mask);
2567*0fca6ea1SDimitry Andric   }
2568*0fca6ea1SDimitry Andric 
VP_CLASSOF_IMPLfinal2569*0fca6ea1SDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPWidenLoadEVLSC)
2570*0fca6ea1SDimitry Andric 
2571*0fca6ea1SDimitry Andric   /// Return the EVL operand.
2572*0fca6ea1SDimitry Andric   VPValue *getEVL() const { return getOperand(1); }
2573*0fca6ea1SDimitry Andric 
2574*0fca6ea1SDimitry Andric   /// Generate the wide load or gather.
2575*0fca6ea1SDimitry Andric   void execute(VPTransformState &State) override;
2576*0fca6ea1SDimitry Andric 
2577*0fca6ea1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2578*0fca6ea1SDimitry Andric   /// Print the recipe.
2579*0fca6ea1SDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
2580*0fca6ea1SDimitry Andric              VPSlotTracker &SlotTracker) const override;
2581*0fca6ea1SDimitry Andric #endif
2582*0fca6ea1SDimitry Andric 
2583*0fca6ea1SDimitry Andric   /// Returns true if the recipe only uses the first lane of operand \p Op.
onlyFirstLaneUsedfinal2584*0fca6ea1SDimitry Andric   bool onlyFirstLaneUsed(const VPValue *Op) const override {
2585*0fca6ea1SDimitry Andric     assert(is_contained(operands(), Op) &&
2586*0fca6ea1SDimitry Andric            "Op must be an operand of the recipe");
2587*0fca6ea1SDimitry Andric     // Widened loads only demand the first lane of EVL and consecutive loads
2588*0fca6ea1SDimitry Andric     // only demand the first lane of their address.
2589*0fca6ea1SDimitry Andric     return Op == getEVL() || (Op == getAddr() && isConsecutive());
2590*0fca6ea1SDimitry Andric   }
2591*0fca6ea1SDimitry Andric };
2592*0fca6ea1SDimitry Andric 
2593*0fca6ea1SDimitry Andric /// A recipe for widening store operations, using the stored value, the address
2594*0fca6ea1SDimitry Andric /// to store to and an optional mask.
2595*0fca6ea1SDimitry Andric struct VPWidenStoreRecipe final : public VPWidenMemoryRecipe {
VPWidenStoreRecipefinal2596*0fca6ea1SDimitry Andric   VPWidenStoreRecipe(StoreInst &Store, VPValue *Addr, VPValue *StoredVal,
2597*0fca6ea1SDimitry Andric                      VPValue *Mask, bool Consecutive, bool Reverse, DebugLoc DL)
2598*0fca6ea1SDimitry Andric       : VPWidenMemoryRecipe(VPDef::VPWidenStoreSC, Store, {Addr, StoredVal},
2599*0fca6ea1SDimitry Andric                             Consecutive, Reverse, DL) {
2600*0fca6ea1SDimitry Andric     setMask(Mask);
2601*0fca6ea1SDimitry Andric   }
2602*0fca6ea1SDimitry Andric 
clonefinal2603*0fca6ea1SDimitry Andric   VPWidenStoreRecipe *clone() override {
2604*0fca6ea1SDimitry Andric     return new VPWidenStoreRecipe(cast<StoreInst>(Ingredient), getAddr(),
2605*0fca6ea1SDimitry Andric                                   getStoredValue(), getMask(), Consecutive,
2606*0fca6ea1SDimitry Andric                                   Reverse, getDebugLoc());
2607*0fca6ea1SDimitry Andric   }
2608*0fca6ea1SDimitry Andric 
2609*0fca6ea1SDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPWidenStoreSC);
2610*0fca6ea1SDimitry Andric 
2611*0fca6ea1SDimitry Andric   /// Return the value stored by this recipe.
getStoredValuefinal2612*0fca6ea1SDimitry Andric   VPValue *getStoredValue() const { return getOperand(1); }
2613*0fca6ea1SDimitry Andric 
2614*0fca6ea1SDimitry Andric   /// Generate a wide store or scatter.
2615*0fca6ea1SDimitry Andric   void execute(VPTransformState &State) override;
2616*0fca6ea1SDimitry Andric 
2617*0fca6ea1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2618*0fca6ea1SDimitry Andric   /// Print the recipe.
2619*0fca6ea1SDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
2620*0fca6ea1SDimitry Andric              VPSlotTracker &SlotTracker) const override;
2621*0fca6ea1SDimitry Andric #endif
2622*0fca6ea1SDimitry Andric 
2623*0fca6ea1SDimitry Andric   /// Returns true if the recipe only uses the first lane of operand \p Op.
onlyFirstLaneUsedfinal2624*0fca6ea1SDimitry Andric   bool onlyFirstLaneUsed(const VPValue *Op) const override {
2625*0fca6ea1SDimitry Andric     assert(is_contained(operands(), Op) &&
2626*0fca6ea1SDimitry Andric            "Op must be an operand of the recipe");
2627*0fca6ea1SDimitry Andric     // Widened, consecutive stores only demand the first lane of their address,
2628*0fca6ea1SDimitry Andric     // unless the same operand is also stored.
2629*0fca6ea1SDimitry Andric     return Op == getAddr() && isConsecutive() && Op != getStoredValue();
2630*0fca6ea1SDimitry Andric   }
2631*0fca6ea1SDimitry Andric };
2632*0fca6ea1SDimitry Andric 
2633*0fca6ea1SDimitry Andric /// A recipe for widening store operations with vector-predication intrinsics,
2634*0fca6ea1SDimitry Andric /// using the value to store, the address to store to, the explicit vector
2635*0fca6ea1SDimitry Andric /// length and an optional mask.
2636*0fca6ea1SDimitry Andric struct VPWidenStoreEVLRecipe final : public VPWidenMemoryRecipe {
VPWidenStoreEVLRecipefinal2637*0fca6ea1SDimitry Andric   VPWidenStoreEVLRecipe(VPWidenStoreRecipe *S, VPValue *EVL, VPValue *Mask)
2638*0fca6ea1SDimitry Andric       : VPWidenMemoryRecipe(VPDef::VPWidenStoreEVLSC, S->getIngredient(),
2639*0fca6ea1SDimitry Andric                             {S->getAddr(), S->getStoredValue(), EVL},
2640*0fca6ea1SDimitry Andric                             S->isConsecutive(), S->isReverse(),
2641*0fca6ea1SDimitry Andric                             S->getDebugLoc()) {
2642*0fca6ea1SDimitry Andric     setMask(Mask);
2643*0fca6ea1SDimitry Andric   }
2644*0fca6ea1SDimitry Andric 
VP_CLASSOF_IMPLfinal2645*0fca6ea1SDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPWidenStoreEVLSC)
2646*0fca6ea1SDimitry Andric 
2647*0fca6ea1SDimitry Andric   /// Return the address accessed by this recipe.
2648*0fca6ea1SDimitry Andric   VPValue *getStoredValue() const { return getOperand(1); }
2649*0fca6ea1SDimitry Andric 
2650*0fca6ea1SDimitry Andric   /// Return the EVL operand.
getEVLfinal2651*0fca6ea1SDimitry Andric   VPValue *getEVL() const { return getOperand(2); }
2652*0fca6ea1SDimitry Andric 
2653*0fca6ea1SDimitry Andric   /// Generate the wide store or scatter.
2654*0fca6ea1SDimitry Andric   void execute(VPTransformState &State) override;
2655*0fca6ea1SDimitry Andric 
2656*0fca6ea1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2657*0fca6ea1SDimitry Andric   /// Print the recipe.
2658*0fca6ea1SDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
2659*0fca6ea1SDimitry Andric              VPSlotTracker &SlotTracker) const override;
2660*0fca6ea1SDimitry Andric #endif
2661*0fca6ea1SDimitry Andric 
2662*0fca6ea1SDimitry Andric   /// Returns true if the recipe only uses the first lane of operand \p Op.
onlyFirstLaneUsedfinal2663*0fca6ea1SDimitry Andric   bool onlyFirstLaneUsed(const VPValue *Op) const override {
2664*0fca6ea1SDimitry Andric     assert(is_contained(operands(), Op) &&
2665*0fca6ea1SDimitry Andric            "Op must be an operand of the recipe");
2666*0fca6ea1SDimitry Andric     if (Op == getEVL()) {
2667*0fca6ea1SDimitry Andric       assert(getStoredValue() != Op && "unexpected store of EVL");
2668*0fca6ea1SDimitry Andric       return true;
2669*0fca6ea1SDimitry Andric     }
26701fd87a68SDimitry Andric     // Widened, consecutive memory operations only demand the first lane of
267181ad6265SDimitry Andric     // their address, unless the same operand is also stored. That latter can
267281ad6265SDimitry Andric     // happen with opaque pointers.
2673*0fca6ea1SDimitry Andric     return Op == getAddr() && isConsecutive() && Op != getStoredValue();
26741fd87a68SDimitry Andric   }
267581ad6265SDimitry Andric };
267681ad6265SDimitry Andric 
267781ad6265SDimitry Andric /// Recipe to expand a SCEV expression.
26787a6dacacSDimitry Andric class VPExpandSCEVRecipe : public VPSingleDefRecipe {
267981ad6265SDimitry Andric   const SCEV *Expr;
268081ad6265SDimitry Andric   ScalarEvolution &SE;
268181ad6265SDimitry Andric 
268281ad6265SDimitry Andric public:
VPExpandSCEVRecipe(const SCEV * Expr,ScalarEvolution & SE)268381ad6265SDimitry Andric   VPExpandSCEVRecipe(const SCEV *Expr, ScalarEvolution &SE)
26847a6dacacSDimitry Andric       : VPSingleDefRecipe(VPDef::VPExpandSCEVSC, {}), Expr(Expr), SE(SE) {}
268581ad6265SDimitry Andric 
268681ad6265SDimitry Andric   ~VPExpandSCEVRecipe() override = default;
268781ad6265SDimitry Andric 
clone()2688*0fca6ea1SDimitry Andric   VPExpandSCEVRecipe *clone() override {
2689*0fca6ea1SDimitry Andric     return new VPExpandSCEVRecipe(Expr, SE);
2690*0fca6ea1SDimitry Andric   }
2691*0fca6ea1SDimitry Andric 
2692bdd1243dSDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPExpandSCEVSC)
269381ad6265SDimitry Andric 
269481ad6265SDimitry Andric   /// Generate a canonical vector induction variable of the vector loop, with
269581ad6265SDimitry Andric   void execute(VPTransformState &State) override;
269681ad6265SDimitry Andric 
269781ad6265SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
269881ad6265SDimitry Andric   /// Print the recipe.
269981ad6265SDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
270081ad6265SDimitry Andric              VPSlotTracker &SlotTracker) const override;
270181ad6265SDimitry Andric #endif
270281ad6265SDimitry Andric 
getSCEV()270381ad6265SDimitry Andric   const SCEV *getSCEV() const { return Expr; }
27045ffd83dbSDimitry Andric };
27055ffd83dbSDimitry Andric 
270604eeddc0SDimitry Andric /// Canonical scalar induction phi of the vector loop. Starting at the specified
270704eeddc0SDimitry Andric /// start value (either 0 or the resume value when vectorizing the epilogue
270804eeddc0SDimitry Andric /// loop). VPWidenCanonicalIVRecipe represents the vector version of the
270904eeddc0SDimitry Andric /// canonical induction variable.
271004eeddc0SDimitry Andric class VPCanonicalIVPHIRecipe : public VPHeaderPHIRecipe {
271104eeddc0SDimitry Andric public:
VPCanonicalIVPHIRecipe(VPValue * StartV,DebugLoc DL)271204eeddc0SDimitry Andric   VPCanonicalIVPHIRecipe(VPValue *StartV, DebugLoc DL)
27135f757f3fSDimitry Andric       : VPHeaderPHIRecipe(VPDef::VPCanonicalIVPHISC, nullptr, StartV, DL) {}
271404eeddc0SDimitry Andric 
271504eeddc0SDimitry Andric   ~VPCanonicalIVPHIRecipe() override = default;
271604eeddc0SDimitry Andric 
clone()2717*0fca6ea1SDimitry Andric   VPCanonicalIVPHIRecipe *clone() override {
2718*0fca6ea1SDimitry Andric     auto *R = new VPCanonicalIVPHIRecipe(getOperand(0), getDebugLoc());
2719*0fca6ea1SDimitry Andric     R->addOperand(getBackedgeValue());
2720*0fca6ea1SDimitry Andric     return R;
2721*0fca6ea1SDimitry Andric   }
2722*0fca6ea1SDimitry Andric 
VP_CLASSOF_IMPL(VPDef::VPCanonicalIVPHISC)2723bdd1243dSDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPCanonicalIVPHISC)
2724bdd1243dSDimitry Andric 
272581ad6265SDimitry Andric   static inline bool classof(const VPHeaderPHIRecipe *D) {
2726bdd1243dSDimitry Andric     return D->getVPDefID() == VPDef::VPCanonicalIVPHISC;
272781ad6265SDimitry Andric   }
272804eeddc0SDimitry Andric 
272904eeddc0SDimitry Andric   /// Generate the canonical scalar induction phi of the vector loop.
273004eeddc0SDimitry Andric   void execute(VPTransformState &State) override;
273104eeddc0SDimitry Andric 
273204eeddc0SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
273304eeddc0SDimitry Andric   /// Print the recipe.
273404eeddc0SDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
273504eeddc0SDimitry Andric              VPSlotTracker &SlotTracker) const override;
273604eeddc0SDimitry Andric #endif
273704eeddc0SDimitry Andric 
273804eeddc0SDimitry Andric   /// Returns the scalar type of the induction.
getScalarType()27395f757f3fSDimitry Andric   Type *getScalarType() const {
27405f757f3fSDimitry Andric     return getStartValue()->getLiveInIRValue()->getType();
274104eeddc0SDimitry Andric   }
27421fd87a68SDimitry Andric 
27431fd87a68SDimitry Andric   /// Returns true if the recipe only uses the first lane of operand \p Op.
onlyFirstLaneUsed(const VPValue * Op)27441fd87a68SDimitry Andric   bool onlyFirstLaneUsed(const VPValue *Op) const override {
27451fd87a68SDimitry Andric     assert(is_contained(operands(), Op) &&
27461fd87a68SDimitry Andric            "Op must be an operand of the recipe");
27471fd87a68SDimitry Andric     return true;
27481fd87a68SDimitry Andric   }
2749bdd1243dSDimitry Andric 
27505f757f3fSDimitry Andric   /// Returns true if the recipe only uses the first part of operand \p Op.
onlyFirstPartUsed(const VPValue * Op)27515f757f3fSDimitry Andric   bool onlyFirstPartUsed(const VPValue *Op) const override {
27525f757f3fSDimitry Andric     assert(is_contained(operands(), Op) &&
27535f757f3fSDimitry Andric            "Op must be an operand of the recipe");
27545f757f3fSDimitry Andric     return true;
27555f757f3fSDimitry Andric   }
27565f757f3fSDimitry Andric 
275706c3fb27SDimitry Andric   /// Check if the induction described by \p Kind, /p Start and \p Step is
2758*0fca6ea1SDimitry Andric   /// canonical, i.e.  has the same start and step (of 1) as the canonical IV.
275906c3fb27SDimitry Andric   bool isCanonical(InductionDescriptor::InductionKind Kind, VPValue *Start,
2760*0fca6ea1SDimitry Andric                    VPValue *Step) const;
276104eeddc0SDimitry Andric };
276204eeddc0SDimitry Andric 
2763753f127fSDimitry Andric /// A recipe for generating the active lane mask for the vector loop that is
2764753f127fSDimitry Andric /// used to predicate the vector operations.
2765753f127fSDimitry Andric /// TODO: It would be good to use the existing VPWidenPHIRecipe instead and
2766753f127fSDimitry Andric /// remove VPActiveLaneMaskPHIRecipe.
2767753f127fSDimitry Andric class VPActiveLaneMaskPHIRecipe : public VPHeaderPHIRecipe {
2768753f127fSDimitry Andric public:
VPActiveLaneMaskPHIRecipe(VPValue * StartMask,DebugLoc DL)2769753f127fSDimitry Andric   VPActiveLaneMaskPHIRecipe(VPValue *StartMask, DebugLoc DL)
27705f757f3fSDimitry Andric       : VPHeaderPHIRecipe(VPDef::VPActiveLaneMaskPHISC, nullptr, StartMask,
27715f757f3fSDimitry Andric                           DL) {}
2772753f127fSDimitry Andric 
2773753f127fSDimitry Andric   ~VPActiveLaneMaskPHIRecipe() override = default;
2774753f127fSDimitry Andric 
clone()2775*0fca6ea1SDimitry Andric   VPActiveLaneMaskPHIRecipe *clone() override {
2776*0fca6ea1SDimitry Andric     return new VPActiveLaneMaskPHIRecipe(getOperand(0), getDebugLoc());
2777*0fca6ea1SDimitry Andric   }
2778*0fca6ea1SDimitry Andric 
VP_CLASSOF_IMPL(VPDef::VPActiveLaneMaskPHISC)2779bdd1243dSDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPActiveLaneMaskPHISC)
2780bdd1243dSDimitry Andric 
2781753f127fSDimitry Andric   static inline bool classof(const VPHeaderPHIRecipe *D) {
2782bdd1243dSDimitry Andric     return D->getVPDefID() == VPDef::VPActiveLaneMaskPHISC;
2783753f127fSDimitry Andric   }
2784753f127fSDimitry Andric 
2785753f127fSDimitry Andric   /// Generate the active lane mask phi of the vector loop.
2786753f127fSDimitry Andric   void execute(VPTransformState &State) override;
2787753f127fSDimitry Andric 
2788753f127fSDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2789753f127fSDimitry Andric   /// Print the recipe.
2790753f127fSDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
2791753f127fSDimitry Andric              VPSlotTracker &SlotTracker) const override;
2792753f127fSDimitry Andric #endif
2793753f127fSDimitry Andric };
2794753f127fSDimitry Andric 
2795*0fca6ea1SDimitry Andric /// A recipe for generating the phi node for the current index of elements,
2796*0fca6ea1SDimitry Andric /// adjusted in accordance with EVL value. It starts at the start value of the
2797*0fca6ea1SDimitry Andric /// canonical induction and gets incremented by EVL in each iteration of the
2798*0fca6ea1SDimitry Andric /// vector loop.
2799*0fca6ea1SDimitry Andric class VPEVLBasedIVPHIRecipe : public VPHeaderPHIRecipe {
2800*0fca6ea1SDimitry Andric public:
VPEVLBasedIVPHIRecipe(VPValue * StartIV,DebugLoc DL)2801*0fca6ea1SDimitry Andric   VPEVLBasedIVPHIRecipe(VPValue *StartIV, DebugLoc DL)
2802*0fca6ea1SDimitry Andric       : VPHeaderPHIRecipe(VPDef::VPEVLBasedIVPHISC, nullptr, StartIV, DL) {}
2803*0fca6ea1SDimitry Andric 
2804*0fca6ea1SDimitry Andric   ~VPEVLBasedIVPHIRecipe() override = default;
2805*0fca6ea1SDimitry Andric 
clone()2806*0fca6ea1SDimitry Andric   VPEVLBasedIVPHIRecipe *clone() override {
2807*0fca6ea1SDimitry Andric     llvm_unreachable("cloning not implemented yet");
2808*0fca6ea1SDimitry Andric   }
2809*0fca6ea1SDimitry Andric 
VP_CLASSOF_IMPL(VPDef::VPEVLBasedIVPHISC)2810*0fca6ea1SDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPEVLBasedIVPHISC)
2811*0fca6ea1SDimitry Andric 
2812*0fca6ea1SDimitry Andric   static inline bool classof(const VPHeaderPHIRecipe *D) {
2813*0fca6ea1SDimitry Andric     return D->getVPDefID() == VPDef::VPEVLBasedIVPHISC;
2814*0fca6ea1SDimitry Andric   }
2815*0fca6ea1SDimitry Andric 
2816*0fca6ea1SDimitry Andric   /// Generate phi for handling IV based on EVL over iterations correctly.
2817*0fca6ea1SDimitry Andric   /// TODO: investigate if it can share the code with VPCanonicalIVPHIRecipe.
2818*0fca6ea1SDimitry Andric   void execute(VPTransformState &State) override;
2819*0fca6ea1SDimitry Andric 
2820*0fca6ea1SDimitry Andric   /// Returns true if the recipe only uses the first lane of operand \p Op.
onlyFirstLaneUsed(const VPValue * Op)2821*0fca6ea1SDimitry Andric   bool onlyFirstLaneUsed(const VPValue *Op) const override {
2822*0fca6ea1SDimitry Andric     assert(is_contained(operands(), Op) &&
2823*0fca6ea1SDimitry Andric            "Op must be an operand of the recipe");
2824*0fca6ea1SDimitry Andric     return true;
2825*0fca6ea1SDimitry Andric   }
2826*0fca6ea1SDimitry Andric 
2827*0fca6ea1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2828*0fca6ea1SDimitry Andric   /// Print the recipe.
2829*0fca6ea1SDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
2830*0fca6ea1SDimitry Andric              VPSlotTracker &SlotTracker) const override;
2831*0fca6ea1SDimitry Andric #endif
2832*0fca6ea1SDimitry Andric };
2833*0fca6ea1SDimitry Andric 
28345ffd83dbSDimitry Andric /// A Recipe for widening the canonical induction variable of the vector loop.
28357a6dacacSDimitry Andric class VPWidenCanonicalIVRecipe : public VPSingleDefRecipe {
28365ffd83dbSDimitry Andric public:
VPWidenCanonicalIVRecipe(VPCanonicalIVPHIRecipe * CanonicalIV)283704eeddc0SDimitry Andric   VPWidenCanonicalIVRecipe(VPCanonicalIVPHIRecipe *CanonicalIV)
28387a6dacacSDimitry Andric       : VPSingleDefRecipe(VPDef::VPWidenCanonicalIVSC, {CanonicalIV}) {}
2839e8d8bef9SDimitry Andric 
28405ffd83dbSDimitry Andric   ~VPWidenCanonicalIVRecipe() override = default;
28415ffd83dbSDimitry Andric 
clone()2842*0fca6ea1SDimitry Andric   VPWidenCanonicalIVRecipe *clone() override {
2843*0fca6ea1SDimitry Andric     return new VPWidenCanonicalIVRecipe(
2844*0fca6ea1SDimitry Andric         cast<VPCanonicalIVPHIRecipe>(getOperand(0)));
2845*0fca6ea1SDimitry Andric   }
2846*0fca6ea1SDimitry Andric 
2847bdd1243dSDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPWidenCanonicalIVSC)
284804eeddc0SDimitry Andric 
28495ffd83dbSDimitry Andric   /// Generate a canonical vector induction variable of the vector loop, with
28505ffd83dbSDimitry Andric   /// start = {<Part*VF, Part*VF+1, ..., Part*VF+VF-1> for 0 <= Part < UF}, and
28515ffd83dbSDimitry Andric   /// step = <VF*UF, VF*UF, ..., VF*UF>.
28525ffd83dbSDimitry Andric   void execute(VPTransformState &State) override;
28535ffd83dbSDimitry Andric 
2854fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
28555ffd83dbSDimitry Andric   /// Print the recipe.
28565ffd83dbSDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
28575ffd83dbSDimitry Andric              VPSlotTracker &SlotTracker) const override;
2858fe6060f1SDimitry Andric #endif
28590b57cec5SDimitry Andric };
28600b57cec5SDimitry Andric 
2861*0fca6ea1SDimitry Andric /// A recipe for converting the input value \p IV value to the corresponding
2862*0fca6ea1SDimitry Andric /// value of an IV with different start and step values, using Start + IV *
2863bdd1243dSDimitry Andric /// Step.
28647a6dacacSDimitry Andric class VPDerivedIVRecipe : public VPSingleDefRecipe {
28655f757f3fSDimitry Andric   /// Kind of the induction.
28665f757f3fSDimitry Andric   const InductionDescriptor::InductionKind Kind;
28675f757f3fSDimitry Andric   /// If not nullptr, the floating point induction binary operator. Must be set
28685f757f3fSDimitry Andric   /// for floating point inductions.
28695f757f3fSDimitry Andric   const FPMathOperator *FPBinOp;
2870bdd1243dSDimitry Andric 
2871bdd1243dSDimitry Andric public:
VPDerivedIVRecipe(const InductionDescriptor & IndDesc,VPValue * Start,VPCanonicalIVPHIRecipe * CanonicalIV,VPValue * Step)2872bdd1243dSDimitry Andric   VPDerivedIVRecipe(const InductionDescriptor &IndDesc, VPValue *Start,
2873*0fca6ea1SDimitry Andric                     VPCanonicalIVPHIRecipe *CanonicalIV, VPValue *Step)
2874*0fca6ea1SDimitry Andric       : VPDerivedIVRecipe(
2875*0fca6ea1SDimitry Andric             IndDesc.getKind(),
2876*0fca6ea1SDimitry Andric             dyn_cast_or_null<FPMathOperator>(IndDesc.getInductionBinOp()),
2877*0fca6ea1SDimitry Andric             Start, CanonicalIV, Step) {}
2878*0fca6ea1SDimitry Andric 
VPDerivedIVRecipe(InductionDescriptor::InductionKind Kind,const FPMathOperator * FPBinOp,VPValue * Start,VPValue * IV,VPValue * Step)2879*0fca6ea1SDimitry Andric   VPDerivedIVRecipe(InductionDescriptor::InductionKind Kind,
2880*0fca6ea1SDimitry Andric                     const FPMathOperator *FPBinOp, VPValue *Start, VPValue *IV,
2881*0fca6ea1SDimitry Andric                     VPValue *Step)
2882*0fca6ea1SDimitry Andric       : VPSingleDefRecipe(VPDef::VPDerivedIVSC, {Start, IV, Step}), Kind(Kind),
2883*0fca6ea1SDimitry Andric         FPBinOp(FPBinOp) {}
2884bdd1243dSDimitry Andric 
2885bdd1243dSDimitry Andric   ~VPDerivedIVRecipe() override = default;
2886bdd1243dSDimitry Andric 
clone()2887*0fca6ea1SDimitry Andric   VPDerivedIVRecipe *clone() override {
2888*0fca6ea1SDimitry Andric     return new VPDerivedIVRecipe(Kind, FPBinOp, getStartValue(), getOperand(1),
2889*0fca6ea1SDimitry Andric                                  getStepValue());
2890*0fca6ea1SDimitry Andric   }
2891*0fca6ea1SDimitry Andric 
2892bdd1243dSDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPDerivedIVSC)
2893bdd1243dSDimitry Andric 
2894bdd1243dSDimitry Andric   /// Generate the transformed value of the induction at offset StartValue (1.
2895bdd1243dSDimitry Andric   /// operand) + IV (2. operand) * StepValue (3, operand).
2896bdd1243dSDimitry Andric   void execute(VPTransformState &State) override;
2897bdd1243dSDimitry Andric 
2898bdd1243dSDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2899bdd1243dSDimitry Andric   /// Print the recipe.
2900bdd1243dSDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
2901bdd1243dSDimitry Andric              VPSlotTracker &SlotTracker) const override;
2902bdd1243dSDimitry Andric #endif
2903bdd1243dSDimitry Andric 
getScalarType()29045f757f3fSDimitry Andric   Type *getScalarType() const {
2905*0fca6ea1SDimitry Andric     return getStartValue()->getLiveInIRValue()->getType();
29065f757f3fSDimitry Andric   }
29075f757f3fSDimitry Andric 
getStartValue()2908bdd1243dSDimitry Andric   VPValue *getStartValue() const { return getOperand(0); }
getStepValue()2909bdd1243dSDimitry Andric   VPValue *getStepValue() const { return getOperand(2); }
2910bdd1243dSDimitry Andric 
2911bdd1243dSDimitry Andric   /// Returns true if the recipe only uses the first lane of operand \p Op.
onlyFirstLaneUsed(const VPValue * Op)2912bdd1243dSDimitry Andric   bool onlyFirstLaneUsed(const VPValue *Op) const override {
2913bdd1243dSDimitry Andric     assert(is_contained(operands(), Op) &&
2914bdd1243dSDimitry Andric            "Op must be an operand of the recipe");
2915bdd1243dSDimitry Andric     return true;
2916bdd1243dSDimitry Andric   }
2917bdd1243dSDimitry Andric };
2918bdd1243dSDimitry Andric 
291981ad6265SDimitry Andric /// A recipe for handling phi nodes of integer and floating-point inductions,
292081ad6265SDimitry Andric /// producing their scalar values.
29217a6dacacSDimitry Andric class VPScalarIVStepsRecipe : public VPRecipeWithIRFlags {
29225f757f3fSDimitry Andric   Instruction::BinaryOps InductionOpcode;
292381ad6265SDimitry Andric 
292481ad6265SDimitry Andric public:
VPScalarIVStepsRecipe(VPValue * IV,VPValue * Step,Instruction::BinaryOps Opcode,FastMathFlags FMFs)29255f757f3fSDimitry Andric   VPScalarIVStepsRecipe(VPValue *IV, VPValue *Step,
29265f757f3fSDimitry Andric                         Instruction::BinaryOps Opcode, FastMathFlags FMFs)
29275f757f3fSDimitry Andric       : VPRecipeWithIRFlags(VPDef::VPScalarIVStepsSC,
29285f757f3fSDimitry Andric                             ArrayRef<VPValue *>({IV, Step}), FMFs),
29297a6dacacSDimitry Andric         InductionOpcode(Opcode) {}
29305f757f3fSDimitry Andric 
VPScalarIVStepsRecipe(const InductionDescriptor & IndDesc,VPValue * IV,VPValue * Step)2931bdd1243dSDimitry Andric   VPScalarIVStepsRecipe(const InductionDescriptor &IndDesc, VPValue *IV,
2932bdd1243dSDimitry Andric                         VPValue *Step)
29335f757f3fSDimitry Andric       : VPScalarIVStepsRecipe(
29345f757f3fSDimitry Andric             IV, Step, IndDesc.getInductionOpcode(),
29355f757f3fSDimitry Andric             dyn_cast_or_null<FPMathOperator>(IndDesc.getInductionBinOp())
29365f757f3fSDimitry Andric                 ? IndDesc.getInductionBinOp()->getFastMathFlags()
29375f757f3fSDimitry Andric                 : FastMathFlags()) {}
293881ad6265SDimitry Andric 
293981ad6265SDimitry Andric   ~VPScalarIVStepsRecipe() override = default;
294081ad6265SDimitry Andric 
clone()2941*0fca6ea1SDimitry Andric   VPScalarIVStepsRecipe *clone() override {
2942*0fca6ea1SDimitry Andric     return new VPScalarIVStepsRecipe(
2943*0fca6ea1SDimitry Andric         getOperand(0), getOperand(1), InductionOpcode,
2944*0fca6ea1SDimitry Andric         hasFastMathFlags() ? getFastMathFlags() : FastMathFlags());
2945*0fca6ea1SDimitry Andric   }
2946*0fca6ea1SDimitry Andric 
2947bdd1243dSDimitry Andric   VP_CLASSOF_IMPL(VPDef::VPScalarIVStepsSC)
294881ad6265SDimitry Andric 
294981ad6265SDimitry Andric   /// Generate the scalarized versions of the phi node as needed by their users.
295081ad6265SDimitry Andric   void execute(VPTransformState &State) override;
295181ad6265SDimitry Andric 
295281ad6265SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
295381ad6265SDimitry Andric   /// Print the recipe.
295481ad6265SDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
295581ad6265SDimitry Andric              VPSlotTracker &SlotTracker) const override;
295681ad6265SDimitry Andric #endif
295781ad6265SDimitry Andric 
getStepValue()2958bdd1243dSDimitry Andric   VPValue *getStepValue() const { return getOperand(1); }
295981ad6265SDimitry Andric 
296081ad6265SDimitry Andric   /// Returns true if the recipe only uses the first lane of operand \p Op.
onlyFirstLaneUsed(const VPValue * Op)296181ad6265SDimitry Andric   bool onlyFirstLaneUsed(const VPValue *Op) const override {
296281ad6265SDimitry Andric     assert(is_contained(operands(), Op) &&
296381ad6265SDimitry Andric            "Op must be an operand of the recipe");
296481ad6265SDimitry Andric     return true;
296581ad6265SDimitry Andric   }
296681ad6265SDimitry Andric };
296781ad6265SDimitry Andric 
29680b57cec5SDimitry Andric /// VPBasicBlock serves as the leaf of the Hierarchical Control-Flow Graph. It
29690b57cec5SDimitry Andric /// holds a sequence of zero or more VPRecipe's each representing a sequence of
2970fe6060f1SDimitry Andric /// output IR instructions. All PHI-like recipes must come before any non-PHI recipes.
29710b57cec5SDimitry Andric class VPBasicBlock : public VPBlockBase {
29720b57cec5SDimitry Andric public:
29730b57cec5SDimitry Andric   using RecipeListTy = iplist<VPRecipeBase>;
29740b57cec5SDimitry Andric 
2975*0fca6ea1SDimitry Andric protected:
29760b57cec5SDimitry Andric   /// The VPRecipes held in the order of output instructions to generate.
29770b57cec5SDimitry Andric   RecipeListTy Recipes;
29780b57cec5SDimitry Andric 
2979*0fca6ea1SDimitry Andric   VPBasicBlock(const unsigned char BlockSC, const Twine &Name = "")
2980*0fca6ea1SDimitry Andric       : VPBlockBase(BlockSC, Name.str()) {}
2981*0fca6ea1SDimitry Andric 
29820b57cec5SDimitry Andric public:
29830b57cec5SDimitry Andric   VPBasicBlock(const Twine &Name = "", VPRecipeBase *Recipe = nullptr)
29840b57cec5SDimitry Andric       : VPBlockBase(VPBasicBlockSC, Name.str()) {
29850b57cec5SDimitry Andric     if (Recipe)
29860b57cec5SDimitry Andric       appendRecipe(Recipe);
29870b57cec5SDimitry Andric   }
29880b57cec5SDimitry Andric 
~VPBasicBlock()2989fe6060f1SDimitry Andric   ~VPBasicBlock() override {
2990fe6060f1SDimitry Andric     while (!Recipes.empty())
2991fe6060f1SDimitry Andric       Recipes.pop_back();
2992fe6060f1SDimitry Andric   }
29930b57cec5SDimitry Andric 
29940b57cec5SDimitry Andric   /// Instruction iterators...
29950b57cec5SDimitry Andric   using iterator = RecipeListTy::iterator;
29960b57cec5SDimitry Andric   using const_iterator = RecipeListTy::const_iterator;
29970b57cec5SDimitry Andric   using reverse_iterator = RecipeListTy::reverse_iterator;
29980b57cec5SDimitry Andric   using const_reverse_iterator = RecipeListTy::const_reverse_iterator;
29990b57cec5SDimitry Andric 
30000b57cec5SDimitry Andric   //===--------------------------------------------------------------------===//
30010b57cec5SDimitry Andric   /// Recipe iterator methods
30020b57cec5SDimitry Andric   ///
begin()30030b57cec5SDimitry Andric   inline iterator begin() { return Recipes.begin(); }
begin()30040b57cec5SDimitry Andric   inline const_iterator begin() const { return Recipes.begin(); }
end()30050b57cec5SDimitry Andric   inline iterator end() { return Recipes.end(); }
end()30060b57cec5SDimitry Andric   inline const_iterator end() const { return Recipes.end(); }
30070b57cec5SDimitry Andric 
rbegin()30080b57cec5SDimitry Andric   inline reverse_iterator rbegin() { return Recipes.rbegin(); }
rbegin()30090b57cec5SDimitry Andric   inline const_reverse_iterator rbegin() const { return Recipes.rbegin(); }
rend()30100b57cec5SDimitry Andric   inline reverse_iterator rend() { return Recipes.rend(); }
rend()30110b57cec5SDimitry Andric   inline const_reverse_iterator rend() const { return Recipes.rend(); }
30120b57cec5SDimitry Andric 
size()30130b57cec5SDimitry Andric   inline size_t size() const { return Recipes.size(); }
empty()30140b57cec5SDimitry Andric   inline bool empty() const { return Recipes.empty(); }
front()30150b57cec5SDimitry Andric   inline const VPRecipeBase &front() const { return Recipes.front(); }
front()30160b57cec5SDimitry Andric   inline VPRecipeBase &front() { return Recipes.front(); }
back()30170b57cec5SDimitry Andric   inline const VPRecipeBase &back() const { return Recipes.back(); }
back()30180b57cec5SDimitry Andric   inline VPRecipeBase &back() { return Recipes.back(); }
30190b57cec5SDimitry Andric 
30200b57cec5SDimitry Andric   /// Returns a reference to the list of recipes.
getRecipeList()30210b57cec5SDimitry Andric   RecipeListTy &getRecipeList() { return Recipes; }
30220b57cec5SDimitry Andric 
30230b57cec5SDimitry Andric   /// Returns a pointer to a member of the recipe list.
getSublistAccess(VPRecipeBase *)30240b57cec5SDimitry Andric   static RecipeListTy VPBasicBlock::*getSublistAccess(VPRecipeBase *) {
30250b57cec5SDimitry Andric     return &VPBasicBlock::Recipes;
30260b57cec5SDimitry Andric   }
30270b57cec5SDimitry Andric 
30280b57cec5SDimitry Andric   /// Method to support type inquiry through isa, cast, and dyn_cast.
classof(const VPBlockBase * V)30290b57cec5SDimitry Andric   static inline bool classof(const VPBlockBase *V) {
3030*0fca6ea1SDimitry Andric     return V->getVPBlockID() == VPBlockBase::VPBasicBlockSC ||
3031*0fca6ea1SDimitry Andric            V->getVPBlockID() == VPBlockBase::VPIRBasicBlockSC;
30320b57cec5SDimitry Andric   }
30330b57cec5SDimitry Andric 
insert(VPRecipeBase * Recipe,iterator InsertPt)30340b57cec5SDimitry Andric   void insert(VPRecipeBase *Recipe, iterator InsertPt) {
30350b57cec5SDimitry Andric     assert(Recipe && "No recipe to append.");
30360b57cec5SDimitry Andric     assert(!Recipe->Parent && "Recipe already in VPlan");
30370b57cec5SDimitry Andric     Recipe->Parent = this;
30380b57cec5SDimitry Andric     Recipes.insert(InsertPt, Recipe);
30390b57cec5SDimitry Andric   }
30400b57cec5SDimitry Andric 
30410b57cec5SDimitry Andric   /// Augment the existing recipes of a VPBasicBlock with an additional
30420b57cec5SDimitry Andric   /// \p Recipe as the last recipe.
appendRecipe(VPRecipeBase * Recipe)30430b57cec5SDimitry Andric   void appendRecipe(VPRecipeBase *Recipe) { insert(Recipe, end()); }
30440b57cec5SDimitry Andric 
30450b57cec5SDimitry Andric   /// The method which generates the output IR instructions that correspond to
30460b57cec5SDimitry Andric   /// this VPBasicBlock, thereby "executing" the VPlan.
3047bdd1243dSDimitry Andric   void execute(VPTransformState *State) override;
30480b57cec5SDimitry Andric 
3049*0fca6ea1SDimitry Andric   /// Return the cost of this VPBasicBlock.
3050*0fca6ea1SDimitry Andric   InstructionCost cost(ElementCount VF, VPCostContext &Ctx) override;
3051*0fca6ea1SDimitry Andric 
3052e8d8bef9SDimitry Andric   /// Return the position of the first non-phi node recipe in the block.
3053e8d8bef9SDimitry Andric   iterator getFirstNonPhi();
3054e8d8bef9SDimitry Andric 
3055fe6060f1SDimitry Andric   /// Returns an iterator range over the PHI-like recipes in the block.
phis()3056fe6060f1SDimitry Andric   iterator_range<iterator> phis() {
3057fe6060f1SDimitry Andric     return make_range(begin(), getFirstNonPhi());
3058fe6060f1SDimitry Andric   }
3059fe6060f1SDimitry Andric 
3060e8d8bef9SDimitry Andric   void dropAllReferences(VPValue *NewValue) override;
3061e8d8bef9SDimitry Andric 
3062fe6060f1SDimitry Andric   /// Split current block at \p SplitAt by inserting a new block between the
3063fe6060f1SDimitry Andric   /// current block and its successors and moving all recipes starting at
3064fe6060f1SDimitry Andric   /// SplitAt to the new block. Returns the new block.
3065fe6060f1SDimitry Andric   VPBasicBlock *splitAt(iterator SplitAt);
3066fe6060f1SDimitry Andric 
306781ad6265SDimitry Andric   VPRegionBlock *getEnclosingLoopRegion();
306881ad6265SDimitry Andric 
3069fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3070fe6060f1SDimitry Andric   /// Print this VPBsicBlock to \p O, prefixing all lines with \p Indent. \p
3071fe6060f1SDimitry Andric   /// SlotTracker is used to print unnamed VPValue's using consequtive numbers.
3072fe6060f1SDimitry Andric   ///
3073fe6060f1SDimitry Andric   /// Note that the numbering is applied to the whole VPlan, so printing
3074fe6060f1SDimitry Andric   /// individual blocks is consistent with the whole VPlan printing.
3075fe6060f1SDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
3076fe6060f1SDimitry Andric              VPSlotTracker &SlotTracker) const override;
3077fe6060f1SDimitry Andric   using VPBlockBase::print; // Get the print(raw_stream &O) version.
3078fe6060f1SDimitry Andric #endif
3079fe6060f1SDimitry Andric 
308081ad6265SDimitry Andric   /// If the block has multiple successors, return the branch recipe terminating
308181ad6265SDimitry Andric   /// the block. If there are no or only a single successor, return nullptr;
308281ad6265SDimitry Andric   VPRecipeBase *getTerminator();
308381ad6265SDimitry Andric   const VPRecipeBase *getTerminator() const;
308481ad6265SDimitry Andric 
308581ad6265SDimitry Andric   /// Returns true if the block is exiting it's parent region.
308681ad6265SDimitry Andric   bool isExiting() const;
308781ad6265SDimitry Andric 
3088*0fca6ea1SDimitry Andric   /// Clone the current block and it's recipes, without updating the operands of
3089*0fca6ea1SDimitry Andric   /// the cloned recipes.
clone()3090*0fca6ea1SDimitry Andric   VPBasicBlock *clone() override {
3091*0fca6ea1SDimitry Andric     auto *NewBlock = new VPBasicBlock(getName());
3092*0fca6ea1SDimitry Andric     for (VPRecipeBase &R : *this)
3093*0fca6ea1SDimitry Andric       NewBlock->appendRecipe(R.clone());
3094*0fca6ea1SDimitry Andric     return NewBlock;
3095*0fca6ea1SDimitry Andric   }
3096*0fca6ea1SDimitry Andric 
3097*0fca6ea1SDimitry Andric protected:
3098*0fca6ea1SDimitry Andric   /// Execute the recipes in the IR basic block \p BB.
3099*0fca6ea1SDimitry Andric   void executeRecipes(VPTransformState *State, BasicBlock *BB);
3100*0fca6ea1SDimitry Andric 
31010b57cec5SDimitry Andric private:
31020b57cec5SDimitry Andric   /// Create an IR BasicBlock to hold the output instructions generated by this
31030b57cec5SDimitry Andric   /// VPBasicBlock, and return it. Update the CFGState accordingly.
31040b57cec5SDimitry Andric   BasicBlock *createEmptyBasicBlock(VPTransformState::CFGState &CFG);
31050b57cec5SDimitry Andric };
31060b57cec5SDimitry Andric 
3107*0fca6ea1SDimitry Andric /// A special type of VPBasicBlock that wraps an existing IR basic block.
3108*0fca6ea1SDimitry Andric /// Recipes of the block get added before the first non-phi instruction in the
3109*0fca6ea1SDimitry Andric /// wrapped block.
3110*0fca6ea1SDimitry Andric /// Note: At the moment, VPIRBasicBlock can only be used to wrap VPlan's
3111*0fca6ea1SDimitry Andric /// preheader block.
3112*0fca6ea1SDimitry Andric class VPIRBasicBlock : public VPBasicBlock {
3113*0fca6ea1SDimitry Andric   BasicBlock *IRBB;
3114*0fca6ea1SDimitry Andric 
3115*0fca6ea1SDimitry Andric public:
VPIRBasicBlock(BasicBlock * IRBB)3116*0fca6ea1SDimitry Andric   VPIRBasicBlock(BasicBlock *IRBB)
3117*0fca6ea1SDimitry Andric       : VPBasicBlock(VPIRBasicBlockSC,
3118*0fca6ea1SDimitry Andric                      (Twine("ir-bb<") + IRBB->getName() + Twine(">")).str()),
3119*0fca6ea1SDimitry Andric         IRBB(IRBB) {}
3120*0fca6ea1SDimitry Andric 
~VPIRBasicBlock()3121*0fca6ea1SDimitry Andric   ~VPIRBasicBlock() override {}
3122*0fca6ea1SDimitry Andric 
classof(const VPBlockBase * V)3123*0fca6ea1SDimitry Andric   static inline bool classof(const VPBlockBase *V) {
3124*0fca6ea1SDimitry Andric     return V->getVPBlockID() == VPBlockBase::VPIRBasicBlockSC;
3125*0fca6ea1SDimitry Andric   }
3126*0fca6ea1SDimitry Andric 
3127*0fca6ea1SDimitry Andric   /// The method which generates the output IR instructions that correspond to
3128*0fca6ea1SDimitry Andric   /// this VPBasicBlock, thereby "executing" the VPlan.
3129*0fca6ea1SDimitry Andric   void execute(VPTransformState *State) override;
3130*0fca6ea1SDimitry Andric 
clone()3131*0fca6ea1SDimitry Andric   VPIRBasicBlock *clone() override {
3132*0fca6ea1SDimitry Andric     auto *NewBlock = new VPIRBasicBlock(IRBB);
3133*0fca6ea1SDimitry Andric     for (VPRecipeBase &R : Recipes)
3134*0fca6ea1SDimitry Andric       NewBlock->appendRecipe(R.clone());
3135*0fca6ea1SDimitry Andric     return NewBlock;
3136*0fca6ea1SDimitry Andric   }
3137*0fca6ea1SDimitry Andric 
getIRBasicBlock()3138*0fca6ea1SDimitry Andric   BasicBlock *getIRBasicBlock() const { return IRBB; }
3139*0fca6ea1SDimitry Andric };
3140*0fca6ea1SDimitry Andric 
31410b57cec5SDimitry Andric /// VPRegionBlock represents a collection of VPBasicBlocks and VPRegionBlocks
314281ad6265SDimitry Andric /// which form a Single-Entry-Single-Exiting subgraph of the output IR CFG.
31430b57cec5SDimitry Andric /// A VPRegionBlock may indicate that its contents are to be replicated several
31440b57cec5SDimitry Andric /// times. This is designed to support predicated scalarization, in which a
31450b57cec5SDimitry Andric /// scalar if-then code structure needs to be generated VF * UF times. Having
31460b57cec5SDimitry Andric /// this replication indicator helps to keep a single model for multiple
31470b57cec5SDimitry Andric /// candidate VF's. The actual replication takes place only once the desired VF
31480b57cec5SDimitry Andric /// and UF have been determined.
31490b57cec5SDimitry Andric class VPRegionBlock : public VPBlockBase {
31500b57cec5SDimitry Andric   /// Hold the Single Entry of the SESE region modelled by the VPRegionBlock.
31510b57cec5SDimitry Andric   VPBlockBase *Entry;
31520b57cec5SDimitry Andric 
315381ad6265SDimitry Andric   /// Hold the Single Exiting block of the SESE region modelled by the
315481ad6265SDimitry Andric   /// VPRegionBlock.
315581ad6265SDimitry Andric   VPBlockBase *Exiting;
31560b57cec5SDimitry Andric 
31570b57cec5SDimitry Andric   /// An indicator whether this region is to generate multiple replicated
31580b57cec5SDimitry Andric   /// instances of output IR corresponding to its VPBlockBases.
31590b57cec5SDimitry Andric   bool IsReplicator;
31600b57cec5SDimitry Andric 
31610b57cec5SDimitry Andric public:
316281ad6265SDimitry Andric   VPRegionBlock(VPBlockBase *Entry, VPBlockBase *Exiting,
31630b57cec5SDimitry Andric                 const std::string &Name = "", bool IsReplicator = false)
VPBlockBase(VPRegionBlockSC,Name)316481ad6265SDimitry Andric       : VPBlockBase(VPRegionBlockSC, Name), Entry(Entry), Exiting(Exiting),
31650b57cec5SDimitry Andric         IsReplicator(IsReplicator) {
31660b57cec5SDimitry Andric     assert(Entry->getPredecessors().empty() && "Entry block has predecessors.");
316781ad6265SDimitry Andric     assert(Exiting->getSuccessors().empty() && "Exit block has successors.");
31680b57cec5SDimitry Andric     Entry->setParent(this);
316981ad6265SDimitry Andric     Exiting->setParent(this);
31700b57cec5SDimitry Andric   }
31710b57cec5SDimitry Andric   VPRegionBlock(const std::string &Name = "", bool IsReplicator = false)
VPBlockBase(VPRegionBlockSC,Name)317281ad6265SDimitry Andric       : VPBlockBase(VPRegionBlockSC, Name), Entry(nullptr), Exiting(nullptr),
31730b57cec5SDimitry Andric         IsReplicator(IsReplicator) {}
31740b57cec5SDimitry Andric 
~VPRegionBlock()31750b57cec5SDimitry Andric   ~VPRegionBlock() override {
3176e8d8bef9SDimitry Andric     if (Entry) {
3177e8d8bef9SDimitry Andric       VPValue DummyValue;
3178e8d8bef9SDimitry Andric       Entry->dropAllReferences(&DummyValue);
31790b57cec5SDimitry Andric       deleteCFG(Entry);
31800b57cec5SDimitry Andric     }
3181e8d8bef9SDimitry Andric   }
31820b57cec5SDimitry Andric 
31830b57cec5SDimitry Andric   /// Method to support type inquiry through isa, cast, and dyn_cast.
classof(const VPBlockBase * V)31840b57cec5SDimitry Andric   static inline bool classof(const VPBlockBase *V) {
31850b57cec5SDimitry Andric     return V->getVPBlockID() == VPBlockBase::VPRegionBlockSC;
31860b57cec5SDimitry Andric   }
31870b57cec5SDimitry Andric 
getEntry()31880b57cec5SDimitry Andric   const VPBlockBase *getEntry() const { return Entry; }
getEntry()31890b57cec5SDimitry Andric   VPBlockBase *getEntry() { return Entry; }
31900b57cec5SDimitry Andric 
31910b57cec5SDimitry Andric   /// Set \p EntryBlock as the entry VPBlockBase of this VPRegionBlock. \p
31920b57cec5SDimitry Andric   /// EntryBlock must have no predecessors.
setEntry(VPBlockBase * EntryBlock)31930b57cec5SDimitry Andric   void setEntry(VPBlockBase *EntryBlock) {
31940b57cec5SDimitry Andric     assert(EntryBlock->getPredecessors().empty() &&
31950b57cec5SDimitry Andric            "Entry block cannot have predecessors.");
31960b57cec5SDimitry Andric     Entry = EntryBlock;
31970b57cec5SDimitry Andric     EntryBlock->setParent(this);
31980b57cec5SDimitry Andric   }
31990b57cec5SDimitry Andric 
getExiting()320081ad6265SDimitry Andric   const VPBlockBase *getExiting() const { return Exiting; }
getExiting()320181ad6265SDimitry Andric   VPBlockBase *getExiting() { return Exiting; }
32020b57cec5SDimitry Andric 
320381ad6265SDimitry Andric   /// Set \p ExitingBlock as the exiting VPBlockBase of this VPRegionBlock. \p
320481ad6265SDimitry Andric   /// ExitingBlock must have no successors.
setExiting(VPBlockBase * ExitingBlock)320581ad6265SDimitry Andric   void setExiting(VPBlockBase *ExitingBlock) {
320681ad6265SDimitry Andric     assert(ExitingBlock->getSuccessors().empty() &&
32070b57cec5SDimitry Andric            "Exit block cannot have successors.");
320881ad6265SDimitry Andric     Exiting = ExitingBlock;
320981ad6265SDimitry Andric     ExitingBlock->setParent(this);
321081ad6265SDimitry Andric   }
321181ad6265SDimitry Andric 
321281ad6265SDimitry Andric   /// Returns the pre-header VPBasicBlock of the loop region.
getPreheaderVPBB()321381ad6265SDimitry Andric   VPBasicBlock *getPreheaderVPBB() {
321481ad6265SDimitry Andric     assert(!isReplicator() && "should only get pre-header of loop regions");
321581ad6265SDimitry Andric     return getSinglePredecessor()->getExitingBasicBlock();
32160b57cec5SDimitry Andric   }
32170b57cec5SDimitry Andric 
32180b57cec5SDimitry Andric   /// An indicator whether this region is to generate multiple replicated
32190b57cec5SDimitry Andric   /// instances of output IR corresponding to its VPBlockBases.
isReplicator()32200b57cec5SDimitry Andric   bool isReplicator() const { return IsReplicator; }
32210b57cec5SDimitry Andric 
32220b57cec5SDimitry Andric   /// The method which generates the output IR instructions that correspond to
32230b57cec5SDimitry Andric   /// this VPRegionBlock, thereby "executing" the VPlan.
3224bdd1243dSDimitry Andric   void execute(VPTransformState *State) override;
3225e8d8bef9SDimitry Andric 
3226*0fca6ea1SDimitry Andric   // Return the cost of this region.
3227*0fca6ea1SDimitry Andric   InstructionCost cost(ElementCount VF, VPCostContext &Ctx) override;
3228*0fca6ea1SDimitry Andric 
3229e8d8bef9SDimitry Andric   void dropAllReferences(VPValue *NewValue) override;
3230fe6060f1SDimitry Andric 
3231fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3232fe6060f1SDimitry Andric   /// Print this VPRegionBlock to \p O (recursively), prefixing all lines with
3233fe6060f1SDimitry Andric   /// \p Indent. \p SlotTracker is used to print unnamed VPValue's using
3234fe6060f1SDimitry Andric   /// consequtive numbers.
3235fe6060f1SDimitry Andric   ///
3236fe6060f1SDimitry Andric   /// Note that the numbering is applied to the whole VPlan, so printing
3237fe6060f1SDimitry Andric   /// individual regions is consistent with the whole VPlan printing.
3238fe6060f1SDimitry Andric   void print(raw_ostream &O, const Twine &Indent,
3239fe6060f1SDimitry Andric              VPSlotTracker &SlotTracker) const override;
3240fe6060f1SDimitry Andric   using VPBlockBase::print; // Get the print(raw_stream &O) version.
3241fe6060f1SDimitry Andric #endif
3242*0fca6ea1SDimitry Andric 
3243*0fca6ea1SDimitry Andric   /// Clone all blocks in the single-entry single-exit region of the block and
3244*0fca6ea1SDimitry Andric   /// their recipes without updating the operands of the cloned recipes.
3245*0fca6ea1SDimitry Andric   VPRegionBlock *clone() override;
32460b57cec5SDimitry Andric };
32470b57cec5SDimitry Andric 
3248480093f4SDimitry Andric /// VPlan models a candidate for vectorization, encoding various decisions take
3249480093f4SDimitry Andric /// to produce efficient output IR, including which branches, basic-blocks and
3250480093f4SDimitry Andric /// output IR instructions to generate, and their cost. VPlan holds a
3251480093f4SDimitry Andric /// Hierarchical-CFG of VPBasicBlocks and VPRegionBlocks rooted at an Entry
325206c3fb27SDimitry Andric /// VPBasicBlock.
3253480093f4SDimitry Andric class VPlan {
3254480093f4SDimitry Andric   friend class VPlanPrinter;
32555ffd83dbSDimitry Andric   friend class VPSlotTracker;
3256480093f4SDimitry Andric 
325706c3fb27SDimitry Andric   /// Hold the single entry to the Hierarchical CFG of the VPlan, i.e. the
325806c3fb27SDimitry Andric   /// preheader of the vector loop.
325906c3fb27SDimitry Andric   VPBasicBlock *Entry;
326006c3fb27SDimitry Andric 
326106c3fb27SDimitry Andric   /// VPBasicBlock corresponding to the original preheader. Used to place
326206c3fb27SDimitry Andric   /// VPExpandSCEV recipes for expressions used during skeleton creation and the
326306c3fb27SDimitry Andric   /// rest of VPlan execution.
326406c3fb27SDimitry Andric   VPBasicBlock *Preheader;
3265480093f4SDimitry Andric 
3266480093f4SDimitry Andric   /// Holds the VFs applicable to this VPlan.
3267e8d8bef9SDimitry Andric   SmallSetVector<ElementCount, 2> VFs;
3268480093f4SDimitry Andric 
3269bdd1243dSDimitry Andric   /// Holds the UFs applicable to this VPlan. If empty, the VPlan is valid for
3270bdd1243dSDimitry Andric   /// any UF.
3271bdd1243dSDimitry Andric   SmallSetVector<unsigned, 2> UFs;
3272bdd1243dSDimitry Andric 
3273480093f4SDimitry Andric   /// Holds the name of the VPlan, for printing.
3274480093f4SDimitry Andric   std::string Name;
3275480093f4SDimitry Andric 
327604eeddc0SDimitry Andric   /// Represents the trip count of the original loop, for folding
3277480093f4SDimitry Andric   /// the tail.
327804eeddc0SDimitry Andric   VPValue *TripCount = nullptr;
327904eeddc0SDimitry Andric 
328004eeddc0SDimitry Andric   /// Represents the backedge taken count of the original loop, for folding
328104eeddc0SDimitry Andric   /// the tail. It equals TripCount - 1.
3282480093f4SDimitry Andric   VPValue *BackedgeTakenCount = nullptr;
3283480093f4SDimitry Andric 
328404eeddc0SDimitry Andric   /// Represents the vector trip count.
328504eeddc0SDimitry Andric   VPValue VectorTripCount;
328604eeddc0SDimitry Andric 
32875f757f3fSDimitry Andric   /// Represents the loop-invariant VF * UF of the vector loop region.
32885f757f3fSDimitry Andric   VPValue VFxUF;
32895f757f3fSDimitry Andric 
3290480093f4SDimitry Andric   /// Holds a mapping between Values and their corresponding VPValue inside
3291480093f4SDimitry Andric   /// VPlan.
3292480093f4SDimitry Andric   Value2VPValueTy Value2VPValue;
3293480093f4SDimitry Andric 
329406c3fb27SDimitry Andric   /// Contains all the external definitions created for this VPlan. External
329506c3fb27SDimitry Andric   /// definitions are VPValues that hold a pointer to their underlying IR.
329606c3fb27SDimitry Andric   SmallVector<VPValue *, 16> VPLiveInsToFree;
3297e8d8bef9SDimitry Andric 
3298*0fca6ea1SDimitry Andric   /// Values used outside the plan. It contains live-outs that need fixing. Any
3299*0fca6ea1SDimitry Andric   /// live-out that is fixed outside VPlan needs to be removed. The remaining
3300*0fca6ea1SDimitry Andric   /// live-outs are fixed via VPLiveOut::fixPhi.
330181ad6265SDimitry Andric   MapVector<PHINode *, VPLiveOut *> LiveOuts;
330281ad6265SDimitry Andric 
330306c3fb27SDimitry Andric   /// Mapping from SCEVs to the VPValues representing their expansions.
330406c3fb27SDimitry Andric   /// NOTE: This mapping is temporary and will be removed once all users have
330506c3fb27SDimitry Andric   /// been modeled in VPlan directly.
330606c3fb27SDimitry Andric   DenseMap<const SCEV *, VPValue *> SCEVToExpansion;
330706c3fb27SDimitry Andric 
3308480093f4SDimitry Andric public:
330906c3fb27SDimitry Andric   /// Construct a VPlan with original preheader \p Preheader, trip count \p TC
331006c3fb27SDimitry Andric   /// and \p Entry to the plan. At the moment, \p Preheader and \p Entry need to
331106c3fb27SDimitry Andric   /// be disconnected, as the bypass blocks between them are not yet modeled in
331206c3fb27SDimitry Andric   /// VPlan.
VPlan(VPBasicBlock * Preheader,VPValue * TC,VPBasicBlock * Entry)331306c3fb27SDimitry Andric   VPlan(VPBasicBlock *Preheader, VPValue *TC, VPBasicBlock *Entry)
331406c3fb27SDimitry Andric       : VPlan(Preheader, Entry) {
331506c3fb27SDimitry Andric     TripCount = TC;
331606c3fb27SDimitry Andric   }
331706c3fb27SDimitry Andric 
331806c3fb27SDimitry Andric   /// Construct a VPlan with original preheader \p Preheader and \p Entry to
331906c3fb27SDimitry Andric   /// the plan. At the moment, \p Preheader and \p Entry need to be
332006c3fb27SDimitry Andric   /// disconnected, as the bypass blocks between them are not yet modeled in
332106c3fb27SDimitry Andric   /// VPlan.
VPlan(VPBasicBlock * Preheader,VPBasicBlock * Entry)332206c3fb27SDimitry Andric   VPlan(VPBasicBlock *Preheader, VPBasicBlock *Entry)
332306c3fb27SDimitry Andric       : Entry(Entry), Preheader(Preheader) {
33245ffd83dbSDimitry Andric     Entry->setPlan(this);
332506c3fb27SDimitry Andric     Preheader->setPlan(this);
332606c3fb27SDimitry Andric     assert(Preheader->getNumSuccessors() == 0 &&
332706c3fb27SDimitry Andric            Preheader->getNumPredecessors() == 0 &&
332806c3fb27SDimitry Andric            "preheader must be disconnected");
33295ffd83dbSDimitry Andric   }
3330480093f4SDimitry Andric 
3331bdd1243dSDimitry Andric   ~VPlan();
3332480093f4SDimitry Andric 
3333*0fca6ea1SDimitry Andric   /// Create initial VPlan, having an "entry" VPBasicBlock (wrapping
3334*0fca6ea1SDimitry Andric   /// original scalar pre-header ) which contains SCEV expansions that need
3335*0fca6ea1SDimitry Andric   /// to happen before the CFG is modified; a VPBasicBlock for the vector
33365f757f3fSDimitry Andric   /// pre-header, followed by a region for the vector loop, followed by the
3337*0fca6ea1SDimitry Andric   /// middle VPBasicBlock. If a check is needed to guard executing the scalar
3338*0fca6ea1SDimitry Andric   /// epilogue loop, it will be added to the middle block, together with
3339*0fca6ea1SDimitry Andric   /// VPBasicBlocks for the scalar preheader and exit blocks.
334006c3fb27SDimitry Andric   static VPlanPtr createInitialVPlan(const SCEV *TripCount,
3341*0fca6ea1SDimitry Andric                                      ScalarEvolution &PSE,
3342*0fca6ea1SDimitry Andric                                      bool RequiresScalarEpilogueCheck,
3343*0fca6ea1SDimitry Andric                                      bool TailFolded, Loop *TheLoop);
334406c3fb27SDimitry Andric 
334504eeddc0SDimitry Andric   /// Prepare the plan for execution, setting up the required live-in values.
334604eeddc0SDimitry Andric   void prepareToExecute(Value *TripCount, Value *VectorTripCount,
33475f757f3fSDimitry Andric                         Value *CanonicalIVStartValue, VPTransformState &State);
334804eeddc0SDimitry Andric 
3349480093f4SDimitry Andric   /// Generate the IR code for this VPlan.
3350bdd1243dSDimitry Andric   void execute(VPTransformState *State);
3351480093f4SDimitry Andric 
3352*0fca6ea1SDimitry Andric   /// Return the cost of this plan.
3353*0fca6ea1SDimitry Andric   InstructionCost cost(ElementCount VF, VPCostContext &Ctx);
3354*0fca6ea1SDimitry Andric 
getEntry()335506c3fb27SDimitry Andric   VPBasicBlock *getEntry() { return Entry; }
getEntry()335606c3fb27SDimitry Andric   const VPBasicBlock *getEntry() const { return Entry; }
3357480093f4SDimitry Andric 
335804eeddc0SDimitry Andric   /// The trip count of the original loop.
getTripCount()335906c3fb27SDimitry Andric   VPValue *getTripCount() const {
336006c3fb27SDimitry Andric     assert(TripCount && "trip count needs to be set before accessing it");
336104eeddc0SDimitry Andric     return TripCount;
336204eeddc0SDimitry Andric   }
336304eeddc0SDimitry Andric 
3364*0fca6ea1SDimitry Andric   /// Resets the trip count for the VPlan. The caller must make sure all uses of
3365*0fca6ea1SDimitry Andric   /// the original trip count have been replaced.
resetTripCount(VPValue * NewTripCount)3366*0fca6ea1SDimitry Andric   void resetTripCount(VPValue *NewTripCount) {
3367*0fca6ea1SDimitry Andric     assert(TripCount && NewTripCount && TripCount->getNumUsers() == 0 &&
3368*0fca6ea1SDimitry Andric            "TripCount always must be set");
3369*0fca6ea1SDimitry Andric     TripCount = NewTripCount;
3370*0fca6ea1SDimitry Andric   }
3371*0fca6ea1SDimitry Andric 
3372480093f4SDimitry Andric   /// The backedge taken count of the original loop.
getOrCreateBackedgeTakenCount()3373480093f4SDimitry Andric   VPValue *getOrCreateBackedgeTakenCount() {
3374480093f4SDimitry Andric     if (!BackedgeTakenCount)
3375480093f4SDimitry Andric       BackedgeTakenCount = new VPValue();
3376480093f4SDimitry Andric     return BackedgeTakenCount;
3377480093f4SDimitry Andric   }
3378480093f4SDimitry Andric 
337904eeddc0SDimitry Andric   /// The vector trip count.
getVectorTripCount()338004eeddc0SDimitry Andric   VPValue &getVectorTripCount() { return VectorTripCount; }
338104eeddc0SDimitry Andric 
33825f757f3fSDimitry Andric   /// Returns VF * UF of the vector loop region.
getVFxUF()33835f757f3fSDimitry Andric   VPValue &getVFxUF() { return VFxUF; }
33845f757f3fSDimitry Andric 
addVF(ElementCount VF)3385e8d8bef9SDimitry Andric   void addVF(ElementCount VF) { VFs.insert(VF); }
3386480093f4SDimitry Andric 
setVF(ElementCount VF)3387bdd1243dSDimitry Andric   void setVF(ElementCount VF) {
3388bdd1243dSDimitry Andric     assert(hasVF(VF) && "Cannot set VF not already in plan");
3389bdd1243dSDimitry Andric     VFs.clear();
3390bdd1243dSDimitry Andric     VFs.insert(VF);
3391bdd1243dSDimitry Andric   }
3392bdd1243dSDimitry Andric 
hasVF(ElementCount VF)3393e8d8bef9SDimitry Andric   bool hasVF(ElementCount VF) { return VFs.count(VF); }
hasScalableVF()3394*0fca6ea1SDimitry Andric   bool hasScalableVF() {
3395*0fca6ea1SDimitry Andric     return any_of(VFs, [](ElementCount VF) { return VF.isScalable(); });
3396*0fca6ea1SDimitry Andric   }
3397*0fca6ea1SDimitry Andric 
3398*0fca6ea1SDimitry Andric   /// Returns an iterator range over all VFs of the plan.
3399*0fca6ea1SDimitry Andric   iterator_range<SmallSetVector<ElementCount, 2>::iterator>
vectorFactors()3400*0fca6ea1SDimitry Andric   vectorFactors() const {
3401*0fca6ea1SDimitry Andric     return {VFs.begin(), VFs.end()};
3402*0fca6ea1SDimitry Andric   }
3403480093f4SDimitry Andric 
hasScalarVFOnly()3404bdd1243dSDimitry Andric   bool hasScalarVFOnly() const { return VFs.size() == 1 && VFs[0].isScalar(); }
3405bdd1243dSDimitry Andric 
hasUF(unsigned UF)3406bdd1243dSDimitry Andric   bool hasUF(unsigned UF) const { return UFs.empty() || UFs.contains(UF); }
3407bdd1243dSDimitry Andric 
setUF(unsigned UF)3408bdd1243dSDimitry Andric   void setUF(unsigned UF) {
3409bdd1243dSDimitry Andric     assert(hasUF(UF) && "Cannot set the UF not already in plan");
3410bdd1243dSDimitry Andric     UFs.clear();
3411bdd1243dSDimitry Andric     UFs.insert(UF);
3412bdd1243dSDimitry Andric   }
3413bdd1243dSDimitry Andric 
3414bdd1243dSDimitry Andric   /// Return a string with the name of the plan and the applicable VFs and UFs.
3415bdd1243dSDimitry Andric   std::string getName() const;
3416480093f4SDimitry Andric 
setName(const Twine & newName)3417480093f4SDimitry Andric   void setName(const Twine &newName) { Name = newName.str(); }
3418480093f4SDimitry Andric 
3419*0fca6ea1SDimitry Andric   /// Gets the live-in VPValue for \p V or adds a new live-in (if none exists
3420*0fca6ea1SDimitry Andric   ///  yet) for \p V.
getOrAddLiveIn(Value * V)3421*0fca6ea1SDimitry Andric   VPValue *getOrAddLiveIn(Value *V) {
3422480093f4SDimitry Andric     assert(V && "Trying to get or add the VPValue of a null Value");
342306c3fb27SDimitry Andric     if (!Value2VPValue.count(V)) {
342406c3fb27SDimitry Andric       VPValue *VPV = new VPValue(V);
342506c3fb27SDimitry Andric       VPLiveInsToFree.push_back(VPV);
3426*0fca6ea1SDimitry Andric       assert(VPV->isLiveIn() && "VPV must be a live-in.");
3427*0fca6ea1SDimitry Andric       assert(!Value2VPValue.count(V) && "Value already exists in VPlan");
3428*0fca6ea1SDimitry Andric       Value2VPValue[V] = VPV;
342906c3fb27SDimitry Andric     }
343006c3fb27SDimitry Andric 
3431*0fca6ea1SDimitry Andric     assert(Value2VPValue.count(V) && "Value does not exist in VPlan");
3432*0fca6ea1SDimitry Andric     assert(Value2VPValue[V]->isLiveIn() &&
3433*0fca6ea1SDimitry Andric            "Only live-ins should be in mapping");
3434*0fca6ea1SDimitry Andric     return Value2VPValue[V];
3435480093f4SDimitry Andric   }
3436480093f4SDimitry Andric 
3437*0fca6ea1SDimitry Andric   /// Return the live-in VPValue for \p V, if there is one or nullptr otherwise.
getLiveIn(Value * V)3438*0fca6ea1SDimitry Andric   VPValue *getLiveIn(Value *V) const { return Value2VPValue.lookup(V); }
3439*0fca6ea1SDimitry Andric 
3440fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
34415f757f3fSDimitry Andric   /// Print the live-ins of this VPlan to \p O.
34425f757f3fSDimitry Andric   void printLiveIns(raw_ostream &O) const;
34435f757f3fSDimitry Andric 
3444fe6060f1SDimitry Andric   /// Print this VPlan to \p O.
3445fe6060f1SDimitry Andric   void print(raw_ostream &O) const;
3446fe6060f1SDimitry Andric 
3447fe6060f1SDimitry Andric   /// Print this VPlan in DOT format to \p O.
3448fe6060f1SDimitry Andric   void printDOT(raw_ostream &O) const;
3449fe6060f1SDimitry Andric 
3450480093f4SDimitry Andric   /// Dump the plan to stderr (for debugging).
3451fe6060f1SDimitry Andric   LLVM_DUMP_METHOD void dump() const;
3452fe6060f1SDimitry Andric #endif
3453480093f4SDimitry Andric 
345404eeddc0SDimitry Andric   /// Returns the VPRegionBlock of the vector loop.
getVectorLoopRegion()345504eeddc0SDimitry Andric   VPRegionBlock *getVectorLoopRegion() {
345681ad6265SDimitry Andric     return cast<VPRegionBlock>(getEntry()->getSingleSuccessor());
345781ad6265SDimitry Andric   }
getVectorLoopRegion()345881ad6265SDimitry Andric   const VPRegionBlock *getVectorLoopRegion() const {
345981ad6265SDimitry Andric     return cast<VPRegionBlock>(getEntry()->getSingleSuccessor());
346004eeddc0SDimitry Andric   }
346104eeddc0SDimitry Andric 
346204eeddc0SDimitry Andric   /// Returns the canonical induction recipe of the vector loop.
getCanonicalIV()346304eeddc0SDimitry Andric   VPCanonicalIVPHIRecipe *getCanonicalIV() {
346404eeddc0SDimitry Andric     VPBasicBlock *EntryVPBB = getVectorLoopRegion()->getEntryBasicBlock();
346504eeddc0SDimitry Andric     if (EntryVPBB->empty()) {
346604eeddc0SDimitry Andric       // VPlan native path.
346704eeddc0SDimitry Andric       EntryVPBB = cast<VPBasicBlock>(EntryVPBB->getSingleSuccessor());
346804eeddc0SDimitry Andric     }
346904eeddc0SDimitry Andric     return cast<VPCanonicalIVPHIRecipe>(&*EntryVPBB->begin());
347004eeddc0SDimitry Andric   }
347104eeddc0SDimitry Andric 
347281ad6265SDimitry Andric   void addLiveOut(PHINode *PN, VPValue *V);
347381ad6265SDimitry Andric 
removeLiveOut(PHINode * PN)347481ad6265SDimitry Andric   void removeLiveOut(PHINode *PN) {
347581ad6265SDimitry Andric     delete LiveOuts[PN];
347681ad6265SDimitry Andric     LiveOuts.erase(PN);
347781ad6265SDimitry Andric   }
347881ad6265SDimitry Andric 
getLiveOuts()347981ad6265SDimitry Andric   const MapVector<PHINode *, VPLiveOut *> &getLiveOuts() const {
348081ad6265SDimitry Andric     return LiveOuts;
348181ad6265SDimitry Andric   }
348281ad6265SDimitry Andric 
getSCEVExpansion(const SCEV * S)348306c3fb27SDimitry Andric   VPValue *getSCEVExpansion(const SCEV *S) const {
348406c3fb27SDimitry Andric     return SCEVToExpansion.lookup(S);
348506c3fb27SDimitry Andric   }
348606c3fb27SDimitry Andric 
addSCEVExpansion(const SCEV * S,VPValue * V)348706c3fb27SDimitry Andric   void addSCEVExpansion(const SCEV *S, VPValue *V) {
348806c3fb27SDimitry Andric     assert(!SCEVToExpansion.contains(S) && "SCEV already expanded");
348906c3fb27SDimitry Andric     SCEVToExpansion[S] = V;
349006c3fb27SDimitry Andric   }
349106c3fb27SDimitry Andric 
349206c3fb27SDimitry Andric   /// \return The block corresponding to the original preheader.
getPreheader()349306c3fb27SDimitry Andric   VPBasicBlock *getPreheader() { return Preheader; }
getPreheader()349406c3fb27SDimitry Andric   const VPBasicBlock *getPreheader() const { return Preheader; }
349506c3fb27SDimitry Andric 
3496*0fca6ea1SDimitry Andric   /// Clone the current VPlan, update all VPValues of the new VPlan and cloned
3497*0fca6ea1SDimitry Andric   /// recipes to refer to the clones, and return it.
3498*0fca6ea1SDimitry Andric   VPlan *duplicate();
3499480093f4SDimitry Andric };
3500480093f4SDimitry Andric 
3501fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3502480093f4SDimitry Andric /// VPlanPrinter prints a given VPlan to a given output stream. The printing is
3503480093f4SDimitry Andric /// indented and follows the dot format.
3504480093f4SDimitry Andric class VPlanPrinter {
3505480093f4SDimitry Andric   raw_ostream &OS;
3506480093f4SDimitry Andric   const VPlan &Plan;
3507480093f4SDimitry Andric   unsigned Depth = 0;
3508480093f4SDimitry Andric   unsigned TabWidth = 2;
3509480093f4SDimitry Andric   std::string Indent;
3510480093f4SDimitry Andric   unsigned BID = 0;
3511480093f4SDimitry Andric   SmallDenseMap<const VPBlockBase *, unsigned> BlockID;
3512480093f4SDimitry Andric 
35135ffd83dbSDimitry Andric   VPSlotTracker SlotTracker;
35145ffd83dbSDimitry Andric 
3515480093f4SDimitry Andric   /// Handle indentation.
bumpIndent(int b)3516480093f4SDimitry Andric   void bumpIndent(int b) { Indent = std::string((Depth += b) * TabWidth, ' '); }
3517480093f4SDimitry Andric 
3518480093f4SDimitry Andric   /// Print a given \p Block of the Plan.
3519480093f4SDimitry Andric   void dumpBlock(const VPBlockBase *Block);
3520480093f4SDimitry Andric 
3521480093f4SDimitry Andric   /// Print the information related to the CFG edges going out of a given
3522480093f4SDimitry Andric   /// \p Block, followed by printing the successor blocks themselves.
3523480093f4SDimitry Andric   void dumpEdges(const VPBlockBase *Block);
3524480093f4SDimitry Andric 
3525480093f4SDimitry Andric   /// Print a given \p BasicBlock, including its VPRecipes, followed by printing
3526480093f4SDimitry Andric   /// its successor blocks.
3527480093f4SDimitry Andric   void dumpBasicBlock(const VPBasicBlock *BasicBlock);
3528480093f4SDimitry Andric 
3529480093f4SDimitry Andric   /// Print a given \p Region of the Plan.
3530480093f4SDimitry Andric   void dumpRegion(const VPRegionBlock *Region);
3531480093f4SDimitry Andric 
getOrCreateBID(const VPBlockBase * Block)3532480093f4SDimitry Andric   unsigned getOrCreateBID(const VPBlockBase *Block) {
3533480093f4SDimitry Andric     return BlockID.count(Block) ? BlockID[Block] : BlockID[Block] = BID++;
3534480093f4SDimitry Andric   }
3535480093f4SDimitry Andric 
3536349cc55cSDimitry Andric   Twine getOrCreateName(const VPBlockBase *Block);
3537480093f4SDimitry Andric 
3538349cc55cSDimitry Andric   Twine getUID(const VPBlockBase *Block);
3539480093f4SDimitry Andric 
3540480093f4SDimitry Andric   /// Print the information related to a CFG edge between two VPBlockBases.
3541480093f4SDimitry Andric   void drawEdge(const VPBlockBase *From, const VPBlockBase *To, bool Hidden,
3542480093f4SDimitry Andric                 const Twine &Label);
3543480093f4SDimitry Andric 
3544fe6060f1SDimitry Andric public:
VPlanPrinter(raw_ostream & O,const VPlan & P)3545fe6060f1SDimitry Andric   VPlanPrinter(raw_ostream &O, const VPlan &P)
3546fe6060f1SDimitry Andric       : OS(O), Plan(P), SlotTracker(&P) {}
3547480093f4SDimitry Andric 
3548fe6060f1SDimitry Andric   LLVM_DUMP_METHOD void dump();
3549480093f4SDimitry Andric };
3550480093f4SDimitry Andric 
3551480093f4SDimitry Andric struct VPlanIngredient {
3552e8d8bef9SDimitry Andric   const Value *V;
3553480093f4SDimitry Andric 
VPlanIngredientVPlanIngredient3554e8d8bef9SDimitry Andric   VPlanIngredient(const Value *V) : V(V) {}
3555fe6060f1SDimitry Andric 
3556fe6060f1SDimitry Andric   void print(raw_ostream &O) const;
3557480093f4SDimitry Andric };
3558480093f4SDimitry Andric 
3559480093f4SDimitry Andric inline raw_ostream &operator<<(raw_ostream &OS, const VPlanIngredient &I) {
3560fe6060f1SDimitry Andric   I.print(OS);
3561480093f4SDimitry Andric   return OS;
3562480093f4SDimitry Andric }
3563480093f4SDimitry Andric 
3564480093f4SDimitry Andric inline raw_ostream &operator<<(raw_ostream &OS, const VPlan &Plan) {
3565fe6060f1SDimitry Andric   Plan.print(OS);
3566480093f4SDimitry Andric   return OS;
3567480093f4SDimitry Andric }
3568fe6060f1SDimitry Andric #endif
3569480093f4SDimitry Andric 
35700b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
35710b57cec5SDimitry Andric // VPlan Utilities
35720b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
35730b57cec5SDimitry Andric 
35740b57cec5SDimitry Andric /// Class that provides utilities for VPBlockBases in VPlan.
35750b57cec5SDimitry Andric class VPBlockUtils {
35760b57cec5SDimitry Andric public:
35770b57cec5SDimitry Andric   VPBlockUtils() = delete;
35780b57cec5SDimitry Andric 
35790b57cec5SDimitry Andric   /// Insert disconnected VPBlockBase \p NewBlock after \p BlockPtr. Add \p
35800b57cec5SDimitry Andric   /// NewBlock as successor of \p BlockPtr and \p BlockPtr as predecessor of \p
35810eae32dcSDimitry Andric   /// NewBlock, and propagate \p BlockPtr parent to \p NewBlock. \p BlockPtr's
358281ad6265SDimitry Andric   /// successors are moved from \p BlockPtr to \p NewBlock. \p NewBlock must
358381ad6265SDimitry Andric   /// have neither successors nor predecessors.
insertBlockAfter(VPBlockBase * NewBlock,VPBlockBase * BlockPtr)35840b57cec5SDimitry Andric   static void insertBlockAfter(VPBlockBase *NewBlock, VPBlockBase *BlockPtr) {
35850b57cec5SDimitry Andric     assert(NewBlock->getSuccessors().empty() &&
35860eae32dcSDimitry Andric            NewBlock->getPredecessors().empty() &&
35870eae32dcSDimitry Andric            "Can't insert new block with predecessors or successors.");
35880b57cec5SDimitry Andric     NewBlock->setParent(BlockPtr->getParent());
35890eae32dcSDimitry Andric     SmallVector<VPBlockBase *> Succs(BlockPtr->successors());
35900eae32dcSDimitry Andric     for (VPBlockBase *Succ : Succs) {
35910eae32dcSDimitry Andric       disconnectBlocks(BlockPtr, Succ);
35920eae32dcSDimitry Andric       connectBlocks(NewBlock, Succ);
35930eae32dcSDimitry Andric     }
35940eae32dcSDimitry Andric     connectBlocks(BlockPtr, NewBlock);
35950b57cec5SDimitry Andric   }
35960b57cec5SDimitry Andric 
35970b57cec5SDimitry Andric   /// Insert disconnected VPBlockBases \p IfTrue and \p IfFalse after \p
35980b57cec5SDimitry Andric   /// BlockPtr. Add \p IfTrue and \p IfFalse as succesors of \p BlockPtr and \p
35990b57cec5SDimitry Andric   /// BlockPtr as predecessor of \p IfTrue and \p IfFalse. Propagate \p BlockPtr
360081ad6265SDimitry Andric   /// parent to \p IfTrue and \p IfFalse. \p BlockPtr must have no successors
360181ad6265SDimitry Andric   /// and \p IfTrue and \p IfFalse must have neither successors nor
360281ad6265SDimitry Andric   /// predecessors.
insertTwoBlocksAfter(VPBlockBase * IfTrue,VPBlockBase * IfFalse,VPBlockBase * BlockPtr)36030b57cec5SDimitry Andric   static void insertTwoBlocksAfter(VPBlockBase *IfTrue, VPBlockBase *IfFalse,
360481ad6265SDimitry Andric                                    VPBlockBase *BlockPtr) {
36050b57cec5SDimitry Andric     assert(IfTrue->getSuccessors().empty() &&
36060b57cec5SDimitry Andric            "Can't insert IfTrue with successors.");
36070b57cec5SDimitry Andric     assert(IfFalse->getSuccessors().empty() &&
36080b57cec5SDimitry Andric            "Can't insert IfFalse with successors.");
360981ad6265SDimitry Andric     BlockPtr->setTwoSuccessors(IfTrue, IfFalse);
36100b57cec5SDimitry Andric     IfTrue->setPredecessors({BlockPtr});
36110b57cec5SDimitry Andric     IfFalse->setPredecessors({BlockPtr});
36120b57cec5SDimitry Andric     IfTrue->setParent(BlockPtr->getParent());
36130b57cec5SDimitry Andric     IfFalse->setParent(BlockPtr->getParent());
36140b57cec5SDimitry Andric   }
36150b57cec5SDimitry Andric 
36160b57cec5SDimitry Andric   /// Connect VPBlockBases \p From and \p To bi-directionally. Append \p To to
36170b57cec5SDimitry Andric   /// the successors of \p From and \p From to the predecessors of \p To. Both
36180b57cec5SDimitry Andric   /// VPBlockBases must have the same parent, which can be null. Both
36190b57cec5SDimitry Andric   /// VPBlockBases can be already connected to other VPBlockBases.
connectBlocks(VPBlockBase * From,VPBlockBase * To)36200b57cec5SDimitry Andric   static void connectBlocks(VPBlockBase *From, VPBlockBase *To) {
36210b57cec5SDimitry Andric     assert((From->getParent() == To->getParent()) &&
36220b57cec5SDimitry Andric            "Can't connect two block with different parents");
36230b57cec5SDimitry Andric     assert(From->getNumSuccessors() < 2 &&
36240b57cec5SDimitry Andric            "Blocks can't have more than two successors.");
36250b57cec5SDimitry Andric     From->appendSuccessor(To);
36260b57cec5SDimitry Andric     To->appendPredecessor(From);
36270b57cec5SDimitry Andric   }
36280b57cec5SDimitry Andric 
36290b57cec5SDimitry Andric   /// Disconnect VPBlockBases \p From and \p To bi-directionally. Remove \p To
36300b57cec5SDimitry Andric   /// from the successors of \p From and \p From from the predecessors of \p To.
disconnectBlocks(VPBlockBase * From,VPBlockBase * To)36310b57cec5SDimitry Andric   static void disconnectBlocks(VPBlockBase *From, VPBlockBase *To) {
36320b57cec5SDimitry Andric     assert(To && "Successor to disconnect is null.");
36330b57cec5SDimitry Andric     From->removeSuccessor(To);
36340b57cec5SDimitry Andric     To->removePredecessor(From);
36350b57cec5SDimitry Andric   }
36360b57cec5SDimitry Andric 
3637fe6060f1SDimitry Andric   /// Return an iterator range over \p Range which only includes \p BlockTy
3638fe6060f1SDimitry Andric   /// blocks. The accesses are casted to \p BlockTy.
3639fe6060f1SDimitry Andric   template <typename BlockTy, typename T>
blocksOnly(const T & Range)3640fe6060f1SDimitry Andric   static auto blocksOnly(const T &Range) {
3641fe6060f1SDimitry Andric     // Create BaseTy with correct const-ness based on BlockTy.
3642bdd1243dSDimitry Andric     using BaseTy = std::conditional_t<std::is_const<BlockTy>::value,
3643bdd1243dSDimitry Andric                                       const VPBlockBase, VPBlockBase>;
3644fe6060f1SDimitry Andric 
3645fe6060f1SDimitry Andric     // We need to first create an iterator range over (const) BlocktTy & instead
3646fe6060f1SDimitry Andric     // of (const) BlockTy * for filter_range to work properly.
3647fe6060f1SDimitry Andric     auto Mapped =
3648fe6060f1SDimitry Andric         map_range(Range, [](BaseTy *Block) -> BaseTy & { return *Block; });
3649fe6060f1SDimitry Andric     auto Filter = make_filter_range(
3650fe6060f1SDimitry Andric         Mapped, [](BaseTy &Block) { return isa<BlockTy>(&Block); });
3651fe6060f1SDimitry Andric     return map_range(Filter, [](BaseTy &Block) -> BlockTy * {
3652fe6060f1SDimitry Andric       return cast<BlockTy>(&Block);
3653fe6060f1SDimitry Andric     });
3654fe6060f1SDimitry Andric   }
36550b57cec5SDimitry Andric };
36560b57cec5SDimitry Andric 
36570b57cec5SDimitry Andric class VPInterleavedAccessInfo {
36580b57cec5SDimitry Andric   DenseMap<VPInstruction *, InterleaveGroup<VPInstruction> *>
36590b57cec5SDimitry Andric       InterleaveGroupMap;
36600b57cec5SDimitry Andric 
36610b57cec5SDimitry Andric   /// Type for mapping of instruction based interleave groups to VPInstruction
36620b57cec5SDimitry Andric   /// interleave groups
36630b57cec5SDimitry Andric   using Old2NewTy = DenseMap<InterleaveGroup<Instruction> *,
36640b57cec5SDimitry Andric                              InterleaveGroup<VPInstruction> *>;
36650b57cec5SDimitry Andric 
36660b57cec5SDimitry Andric   /// Recursively \p Region and populate VPlan based interleave groups based on
36670b57cec5SDimitry Andric   /// \p IAI.
36680b57cec5SDimitry Andric   void visitRegion(VPRegionBlock *Region, Old2NewTy &Old2New,
36690b57cec5SDimitry Andric                    InterleavedAccessInfo &IAI);
36700b57cec5SDimitry Andric   /// Recursively traverse \p Block and populate VPlan based interleave groups
36710b57cec5SDimitry Andric   /// based on \p IAI.
36720b57cec5SDimitry Andric   void visitBlock(VPBlockBase *Block, Old2NewTy &Old2New,
36730b57cec5SDimitry Andric                   InterleavedAccessInfo &IAI);
36740b57cec5SDimitry Andric 
36750b57cec5SDimitry Andric public:
36760b57cec5SDimitry Andric   VPInterleavedAccessInfo(VPlan &Plan, InterleavedAccessInfo &IAI);
36770b57cec5SDimitry Andric 
~VPInterleavedAccessInfo()36780b57cec5SDimitry Andric   ~VPInterleavedAccessInfo() {
36790b57cec5SDimitry Andric     SmallPtrSet<InterleaveGroup<VPInstruction> *, 4> DelSet;
36800b57cec5SDimitry Andric     // Avoid releasing a pointer twice.
36810b57cec5SDimitry Andric     for (auto &I : InterleaveGroupMap)
36820b57cec5SDimitry Andric       DelSet.insert(I.second);
36830b57cec5SDimitry Andric     for (auto *Ptr : DelSet)
36840b57cec5SDimitry Andric       delete Ptr;
36850b57cec5SDimitry Andric   }
36860b57cec5SDimitry Andric 
36870b57cec5SDimitry Andric   /// Get the interleave group that \p Instr belongs to.
36880b57cec5SDimitry Andric   ///
36890b57cec5SDimitry Andric   /// \returns nullptr if doesn't have such group.
36900b57cec5SDimitry Andric   InterleaveGroup<VPInstruction> *
getInterleaveGroup(VPInstruction * Instr)36910b57cec5SDimitry Andric   getInterleaveGroup(VPInstruction *Instr) const {
3692e8d8bef9SDimitry Andric     return InterleaveGroupMap.lookup(Instr);
36930b57cec5SDimitry Andric   }
36940b57cec5SDimitry Andric };
36950b57cec5SDimitry Andric 
36960b57cec5SDimitry Andric /// Class that maps (parts of) an existing VPlan to trees of combined
36970b57cec5SDimitry Andric /// VPInstructions.
36980b57cec5SDimitry Andric class VPlanSlp {
36990b57cec5SDimitry Andric   enum class OpMode { Failed, Load, Opcode };
37000b57cec5SDimitry Andric 
37010b57cec5SDimitry Andric   /// A DenseMapInfo implementation for using SmallVector<VPValue *, 4> as
37020b57cec5SDimitry Andric   /// DenseMap keys.
37030b57cec5SDimitry Andric   struct BundleDenseMapInfo {
getEmptyKeyBundleDenseMapInfo37040b57cec5SDimitry Andric     static SmallVector<VPValue *, 4> getEmptyKey() {
37050b57cec5SDimitry Andric       return {reinterpret_cast<VPValue *>(-1)};
37060b57cec5SDimitry Andric     }
37070b57cec5SDimitry Andric 
getTombstoneKeyBundleDenseMapInfo37080b57cec5SDimitry Andric     static SmallVector<VPValue *, 4> getTombstoneKey() {
37090b57cec5SDimitry Andric       return {reinterpret_cast<VPValue *>(-2)};
37100b57cec5SDimitry Andric     }
37110b57cec5SDimitry Andric 
getHashValueBundleDenseMapInfo37120b57cec5SDimitry Andric     static unsigned getHashValue(const SmallVector<VPValue *, 4> &V) {
37130b57cec5SDimitry Andric       return static_cast<unsigned>(hash_combine_range(V.begin(), V.end()));
37140b57cec5SDimitry Andric     }
37150b57cec5SDimitry Andric 
isEqualBundleDenseMapInfo37160b57cec5SDimitry Andric     static bool isEqual(const SmallVector<VPValue *, 4> &LHS,
37170b57cec5SDimitry Andric                         const SmallVector<VPValue *, 4> &RHS) {
37180b57cec5SDimitry Andric       return LHS == RHS;
37190b57cec5SDimitry Andric     }
37200b57cec5SDimitry Andric   };
37210b57cec5SDimitry Andric 
37220b57cec5SDimitry Andric   /// Mapping of values in the original VPlan to a combined VPInstruction.
37230b57cec5SDimitry Andric   DenseMap<SmallVector<VPValue *, 4>, VPInstruction *, BundleDenseMapInfo>
37240b57cec5SDimitry Andric       BundleToCombined;
37250b57cec5SDimitry Andric 
37260b57cec5SDimitry Andric   VPInterleavedAccessInfo &IAI;
37270b57cec5SDimitry Andric 
37280b57cec5SDimitry Andric   /// Basic block to operate on. For now, only instructions in a single BB are
37290b57cec5SDimitry Andric   /// considered.
37300b57cec5SDimitry Andric   const VPBasicBlock &BB;
37310b57cec5SDimitry Andric 
37320b57cec5SDimitry Andric   /// Indicates whether we managed to combine all visited instructions or not.
37330b57cec5SDimitry Andric   bool CompletelySLP = true;
37340b57cec5SDimitry Andric 
37350b57cec5SDimitry Andric   /// Width of the widest combined bundle in bits.
37360b57cec5SDimitry Andric   unsigned WidestBundleBits = 0;
37370b57cec5SDimitry Andric 
37380b57cec5SDimitry Andric   using MultiNodeOpTy =
37390b57cec5SDimitry Andric       typename std::pair<VPInstruction *, SmallVector<VPValue *, 4>>;
37400b57cec5SDimitry Andric 
37410b57cec5SDimitry Andric   // Input operand bundles for the current multi node. Each multi node operand
37420b57cec5SDimitry Andric   // bundle contains values not matching the multi node's opcode. They will
37430b57cec5SDimitry Andric   // be reordered in reorderMultiNodeOps, once we completed building a
37440b57cec5SDimitry Andric   // multi node.
37450b57cec5SDimitry Andric   SmallVector<MultiNodeOpTy, 4> MultiNodeOps;
37460b57cec5SDimitry Andric 
37470b57cec5SDimitry Andric   /// Indicates whether we are building a multi node currently.
37480b57cec5SDimitry Andric   bool MultiNodeActive = false;
37490b57cec5SDimitry Andric 
37500b57cec5SDimitry Andric   /// Check if we can vectorize Operands together.
37510b57cec5SDimitry Andric   bool areVectorizable(ArrayRef<VPValue *> Operands) const;
37520b57cec5SDimitry Andric 
37530b57cec5SDimitry Andric   /// Add combined instruction \p New for the bundle \p Operands.
37540b57cec5SDimitry Andric   void addCombined(ArrayRef<VPValue *> Operands, VPInstruction *New);
37550b57cec5SDimitry Andric 
37560b57cec5SDimitry Andric   /// Indicate we hit a bundle we failed to combine. Returns nullptr for now.
37570b57cec5SDimitry Andric   VPInstruction *markFailed();
37580b57cec5SDimitry Andric 
37590b57cec5SDimitry Andric   /// Reorder operands in the multi node to maximize sequential memory access
37600b57cec5SDimitry Andric   /// and commutative operations.
37610b57cec5SDimitry Andric   SmallVector<MultiNodeOpTy, 4> reorderMultiNodeOps();
37620b57cec5SDimitry Andric 
37630b57cec5SDimitry Andric   /// Choose the best candidate to use for the lane after \p Last. The set of
37640b57cec5SDimitry Andric   /// candidates to choose from are values with an opcode matching \p Last's
37650b57cec5SDimitry Andric   /// or loads consecutive to \p Last.
37660b57cec5SDimitry Andric   std::pair<OpMode, VPValue *> getBest(OpMode Mode, VPValue *Last,
37670b57cec5SDimitry Andric                                        SmallPtrSetImpl<VPValue *> &Candidates,
37680b57cec5SDimitry Andric                                        VPInterleavedAccessInfo &IAI);
37690b57cec5SDimitry Andric 
3770fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
37710b57cec5SDimitry Andric   /// Print bundle \p Values to dbgs().
37720b57cec5SDimitry Andric   void dumpBundle(ArrayRef<VPValue *> Values);
3773fe6060f1SDimitry Andric #endif
37740b57cec5SDimitry Andric 
37750b57cec5SDimitry Andric public:
VPlanSlp(VPInterleavedAccessInfo & IAI,VPBasicBlock & BB)37760b57cec5SDimitry Andric   VPlanSlp(VPInterleavedAccessInfo &IAI, VPBasicBlock &BB) : IAI(IAI), BB(BB) {}
37770b57cec5SDimitry Andric 
3778e8d8bef9SDimitry Andric   ~VPlanSlp() = default;
37790b57cec5SDimitry Andric 
37800b57cec5SDimitry Andric   /// Tries to build an SLP tree rooted at \p Operands and returns a
37810b57cec5SDimitry Andric   /// VPInstruction combining \p Operands, if they can be combined.
37820b57cec5SDimitry Andric   VPInstruction *buildGraph(ArrayRef<VPValue *> Operands);
37830b57cec5SDimitry Andric 
37840b57cec5SDimitry Andric   /// Return the width of the widest combined bundle in bits.
getWidestBundleBits()37850b57cec5SDimitry Andric   unsigned getWidestBundleBits() const { return WidestBundleBits; }
37860b57cec5SDimitry Andric 
37870b57cec5SDimitry Andric   /// Return true if all visited instruction can be combined.
isCompletelySLP()37880b57cec5SDimitry Andric   bool isCompletelySLP() const { return CompletelySLP; }
37890b57cec5SDimitry Andric };
37901fd87a68SDimitry Andric 
37911fd87a68SDimitry Andric namespace vputils {
37921fd87a68SDimitry Andric 
37931fd87a68SDimitry Andric /// Returns true if only the first lane of \p Def is used.
3794*0fca6ea1SDimitry Andric bool onlyFirstLaneUsed(const VPValue *Def);
37951fd87a68SDimitry Andric 
37965f757f3fSDimitry Andric /// Returns true if only the first part of \p Def is used.
3797*0fca6ea1SDimitry Andric bool onlyFirstPartUsed(const VPValue *Def);
37985f757f3fSDimitry Andric 
379981ad6265SDimitry Andric /// Get or create a VPValue that corresponds to the expansion of \p Expr. If \p
380081ad6265SDimitry Andric /// Expr is a SCEVConstant or SCEVUnknown, return a VPValue wrapping the live-in
380181ad6265SDimitry Andric /// value. Otherwise return a VPExpandSCEVRecipe to expand \p Expr. If \p Plan's
380281ad6265SDimitry Andric /// pre-header already contains a recipe expanding \p Expr, return it. If not,
380381ad6265SDimitry Andric /// create a new one.
380481ad6265SDimitry Andric VPValue *getOrCreateVPValueForSCEVExpr(VPlan &Plan, const SCEV *Expr,
380581ad6265SDimitry Andric                                        ScalarEvolution &SE);
3806bdd1243dSDimitry Andric 
3807bdd1243dSDimitry Andric /// Returns true if \p VPV is uniform after vectorization.
isUniformAfterVectorization(VPValue * VPV)3808bdd1243dSDimitry Andric inline bool isUniformAfterVectorization(VPValue *VPV) {
3809bdd1243dSDimitry Andric   // A value defined outside the vector region must be uniform after
3810bdd1243dSDimitry Andric   // vectorization inside a vector region.
3811bdd1243dSDimitry Andric   if (VPV->isDefinedOutsideVectorRegions())
3812bdd1243dSDimitry Andric     return true;
3813bdd1243dSDimitry Andric   VPRecipeBase *Def = VPV->getDefiningRecipe();
3814bdd1243dSDimitry Andric   assert(Def && "Must have definition for value defined inside vector region");
3815bdd1243dSDimitry Andric   if (auto Rep = dyn_cast<VPReplicateRecipe>(Def))
3816bdd1243dSDimitry Andric     return Rep->isUniform();
381706c3fb27SDimitry Andric   if (auto *GEP = dyn_cast<VPWidenGEPRecipe>(Def))
381806c3fb27SDimitry Andric     return all_of(GEP->operands(), isUniformAfterVectorization);
38191db9f3b2SDimitry Andric   if (auto *VPI = dyn_cast<VPInstruction>(Def))
3820*0fca6ea1SDimitry Andric     return VPI->isSingleScalar() || VPI->isVectorToScalar();
3821bdd1243dSDimitry Andric   return false;
3822bdd1243dSDimitry Andric }
3823*0fca6ea1SDimitry Andric 
3824*0fca6ea1SDimitry Andric /// Return true if \p V is a header mask in \p Plan.
3825*0fca6ea1SDimitry Andric bool isHeaderMask(VPValue *V, VPlan &Plan);
38261fd87a68SDimitry Andric } // end namespace vputils
38271fd87a68SDimitry Andric 
38280b57cec5SDimitry Andric } // end namespace llvm
38290b57cec5SDimitry Andric 
38300b57cec5SDimitry Andric #endif // LLVM_TRANSFORMS_VECTORIZE_VPLAN_H
3831