xref: /freebsd/contrib/llvm-project/llvm/lib/Transforms/Vectorize/VPlanValue.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- VPlanValue.h - Represent Values in Vectorizer Plan -----------------===//
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 entities induced by Vectorization
110b57cec5SDimitry Andric /// Plans, e.g. the instructions the VPlan intends to generate if executed.
120b57cec5SDimitry Andric /// VPlan models the following entities:
13e8d8bef9SDimitry Andric /// VPValue   VPUser   VPDef
14e8d8bef9SDimitry Andric ///    |        |
15e8d8bef9SDimitry Andric ///   VPInstruction
160b57cec5SDimitry Andric /// These are documented in docs/VectorizationPlan.rst.
170b57cec5SDimitry Andric ///
180b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric #ifndef LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H
210b57cec5SDimitry Andric #define LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
24e8d8bef9SDimitry Andric #include "llvm/ADT/STLExtras.h"
250b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
26*0fca6ea1SDimitry Andric #include "llvm/ADT/StringMap.h"
27e8d8bef9SDimitry Andric #include "llvm/ADT/TinyPtrVector.h"
285ffd83dbSDimitry Andric #include "llvm/ADT/iterator_range.h"
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric namespace llvm {
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric // Forward declarations.
335ffd83dbSDimitry Andric class raw_ostream;
345ffd83dbSDimitry Andric class Value;
35e8d8bef9SDimitry Andric class VPDef;
365ffd83dbSDimitry Andric class VPSlotTracker;
370b57cec5SDimitry Andric class VPUser;
38e8d8bef9SDimitry Andric class VPRecipeBase;
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric // This is the base class of the VPlan Def/Use graph, used for modeling the data
410b57cec5SDimitry Andric // flow into, within and out of the VPlan. VPValues can stand for live-ins
420b57cec5SDimitry Andric // coming from the input IR, instructions which VPlan will generate if executed
430b57cec5SDimitry Andric // and live-outs which the VPlan will need to fix accordingly.
440b57cec5SDimitry Andric class VPValue {
450b57cec5SDimitry Andric   friend class VPBuilder;
46e8d8bef9SDimitry Andric   friend class VPDef;
47e8d8bef9SDimitry Andric   friend class VPInstruction;
485ffd83dbSDimitry Andric   friend struct VPlanTransforms;
490b57cec5SDimitry Andric   friend class VPBasicBlock;
500b57cec5SDimitry Andric   friend class VPInterleavedAccessInfo;
515ffd83dbSDimitry Andric   friend class VPSlotTracker;
52e8d8bef9SDimitry Andric   friend class VPRecipeBase;
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric   const unsigned char SubclassID; ///< Subclass identifier (for isa/dyn_cast).
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric   SmallVector<VPUser *, 1> Users;
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric protected:
590b57cec5SDimitry Andric   // Hold the underlying Value, if any, attached to this VPValue.
600b57cec5SDimitry Andric   Value *UnderlyingVal;
610b57cec5SDimitry Andric 
62e8d8bef9SDimitry Andric   /// Pointer to the VPDef that defines this VPValue. If it is nullptr, the
63e8d8bef9SDimitry Andric   /// VPValue is not defined by any recipe modeled in VPlan.
64e8d8bef9SDimitry Andric   VPDef *Def;
65e8d8bef9SDimitry Andric 
66e8d8bef9SDimitry Andric   VPValue(const unsigned char SC, Value *UV = nullptr, VPDef *Def = nullptr);
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric   // DESIGN PRINCIPLE: Access to the underlying IR must be strictly limited to
690b57cec5SDimitry Andric   // the front-end and back-end of VPlan so that the middle-end is as
700b57cec5SDimitry Andric   // independent as possible of the underlying IR. We grant access to the
710b57cec5SDimitry Andric   // underlying IR using friendship. In that way, we should be able to use VPlan
720b57cec5SDimitry Andric   // for multiple underlying IRs (Polly?) by providing a new VPlan front-end,
730b57cec5SDimitry Andric   // back-end and analysis information for the new IR.
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric public:
76e8d8bef9SDimitry Andric   /// Return the underlying Value attached to this VPValue.
getUnderlyingValue()77*0fca6ea1SDimitry Andric   Value *getUnderlyingValue() const { return UnderlyingVal; }
78e8d8bef9SDimitry Andric 
790b57cec5SDimitry Andric   /// An enumeration for keeping track of the concrete subclass of VPValue that
80bdd1243dSDimitry Andric   /// are actually instantiated.
81e8d8bef9SDimitry Andric   enum {
82bdd1243dSDimitry Andric     VPValueSC, /// A generic VPValue, like live-in values or defined by a recipe
83bdd1243dSDimitry Andric                /// that defines multiple values.
84bdd1243dSDimitry Andric     VPVRecipeSC /// A VPValue sub-class that is a VPRecipeBase.
85e8d8bef9SDimitry Andric   };
860b57cec5SDimitry Andric 
87bdd1243dSDimitry Andric   /// Create a live-in VPValue.
VPValue(VPValueSC,UV,nullptr)88bdd1243dSDimitry Andric   VPValue(Value *UV = nullptr) : VPValue(VPValueSC, UV, nullptr) {}
89bdd1243dSDimitry Andric   /// Create a VPValue for a \p Def which is a subclass of VPValue.
VPValue(VPVRecipeSC,UV,Def)90bdd1243dSDimitry Andric   VPValue(VPDef *Def, Value *UV = nullptr) : VPValue(VPVRecipeSC, UV, Def) {}
91bdd1243dSDimitry Andric   /// Create a VPValue for a \p Def which defines multiple values.
VPValue(Value * UV,VPDef * Def)92bdd1243dSDimitry Andric   VPValue(Value *UV, VPDef *Def) : VPValue(VPValueSC, UV, Def) {}
930b57cec5SDimitry Andric   VPValue(const VPValue &) = delete;
940b57cec5SDimitry Andric   VPValue &operator=(const VPValue &) = delete;
950b57cec5SDimitry Andric 
96e8d8bef9SDimitry Andric   virtual ~VPValue();
97e8d8bef9SDimitry Andric 
980b57cec5SDimitry Andric   /// \return an ID for the concrete type of this object.
990b57cec5SDimitry Andric   /// This is used to implement the classof checks. This should not be used
1000b57cec5SDimitry Andric   /// for any other purpose, as the values may change as LLVM evolves.
getVPValueID()1010b57cec5SDimitry Andric   unsigned getVPValueID() const { return SubclassID; }
1020b57cec5SDimitry Andric 
103fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1045ffd83dbSDimitry Andric   void printAsOperand(raw_ostream &OS, VPSlotTracker &Tracker) const;
1055ffd83dbSDimitry Andric   void print(raw_ostream &OS, VPSlotTracker &Tracker) const;
1060b57cec5SDimitry Andric 
107e8d8bef9SDimitry Andric   /// Dump the value to stderr (for debugging).
108e8d8bef9SDimitry Andric   void dump() const;
109fe6060f1SDimitry Andric #endif
110e8d8bef9SDimitry Andric 
getNumUsers()1110b57cec5SDimitry Andric   unsigned getNumUsers() const { return Users.size(); }
addUser(VPUser & User)1120b57cec5SDimitry Andric   void addUser(VPUser &User) { Users.push_back(&User); }
1130b57cec5SDimitry Andric 
114e8d8bef9SDimitry Andric   /// Remove a single \p User from the list of users.
removeUser(VPUser & User)115e8d8bef9SDimitry Andric   void removeUser(VPUser &User) {
116e8d8bef9SDimitry Andric     // The same user can be added multiple times, e.g. because the same VPValue
117e8d8bef9SDimitry Andric     // is used twice by the same VPUser. Remove a single one.
1185f757f3fSDimitry Andric     auto *I = find(Users, &User);
1195f757f3fSDimitry Andric     if (I != Users.end())
1205f757f3fSDimitry Andric       Users.erase(I);
121e8d8bef9SDimitry Andric   }
122e8d8bef9SDimitry Andric 
1230b57cec5SDimitry Andric   typedef SmallVectorImpl<VPUser *>::iterator user_iterator;
1240b57cec5SDimitry Andric   typedef SmallVectorImpl<VPUser *>::const_iterator const_user_iterator;
1250b57cec5SDimitry Andric   typedef iterator_range<user_iterator> user_range;
1260b57cec5SDimitry Andric   typedef iterator_range<const_user_iterator> const_user_range;
1270b57cec5SDimitry Andric 
user_begin()1280b57cec5SDimitry Andric   user_iterator user_begin() { return Users.begin(); }
user_begin()1290b57cec5SDimitry Andric   const_user_iterator user_begin() const { return Users.begin(); }
user_end()1300b57cec5SDimitry Andric   user_iterator user_end() { return Users.end(); }
user_end()1310b57cec5SDimitry Andric   const_user_iterator user_end() const { return Users.end(); }
users()1320b57cec5SDimitry Andric   user_range users() { return user_range(user_begin(), user_end()); }
users()1330b57cec5SDimitry Andric   const_user_range users() const {
1340b57cec5SDimitry Andric     return const_user_range(user_begin(), user_end());
1350b57cec5SDimitry Andric   }
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric   /// Returns true if the value has more than one unique user.
hasMoreThanOneUniqueUser()1380b57cec5SDimitry Andric   bool hasMoreThanOneUniqueUser() {
1390b57cec5SDimitry Andric     if (getNumUsers() == 0)
1400b57cec5SDimitry Andric       return false;
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric     // Check if all users match the first user.
1430b57cec5SDimitry Andric     auto Current = std::next(user_begin());
1440b57cec5SDimitry Andric     while (Current != user_end() && *user_begin() == *Current)
1450b57cec5SDimitry Andric       Current++;
1460b57cec5SDimitry Andric     return Current != user_end();
1470b57cec5SDimitry Andric   }
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric   void replaceAllUsesWith(VPValue *New);
150e8d8bef9SDimitry Andric 
1515f757f3fSDimitry Andric   /// Go through the uses list for this VPValue and make each use point to \p
1525f757f3fSDimitry Andric   /// New if the callback ShouldReplace returns true for the given use specified
1535f757f3fSDimitry Andric   /// by a pair of (VPUser, the use index).
1545f757f3fSDimitry Andric   void replaceUsesWithIf(
1555f757f3fSDimitry Andric       VPValue *New,
1565f757f3fSDimitry Andric       llvm::function_ref<bool(VPUser &U, unsigned Idx)> ShouldReplace);
1575f757f3fSDimitry Andric 
158bdd1243dSDimitry Andric   /// Returns the recipe defining this VPValue or nullptr if it is not defined
159bdd1243dSDimitry Andric   /// by a recipe, i.e. is a live-in.
160bdd1243dSDimitry Andric   VPRecipeBase *getDefiningRecipe();
161bdd1243dSDimitry Andric   const VPRecipeBase *getDefiningRecipe() const;
162bdd1243dSDimitry Andric 
163bdd1243dSDimitry Andric   /// Returns true if this VPValue is defined by a recipe.
hasDefiningRecipe()164bdd1243dSDimitry Andric   bool hasDefiningRecipe() const { return getDefiningRecipe(); }
165e8d8bef9SDimitry Andric 
16606c3fb27SDimitry Andric   /// Returns true if this VPValue is a live-in, i.e. defined outside the VPlan.
isLiveIn()16706c3fb27SDimitry Andric   bool isLiveIn() const { return !hasDefiningRecipe(); }
16806c3fb27SDimitry Andric 
169e8d8bef9SDimitry Andric   /// Returns the underlying IR value, if this VPValue is defined outside the
170e8d8bef9SDimitry Andric   /// scope of VPlan. Returns nullptr if the VPValue is defined by a VPDef
171e8d8bef9SDimitry Andric   /// inside a VPlan.
getLiveInIRValue()172e8d8bef9SDimitry Andric   Value *getLiveInIRValue() {
17306c3fb27SDimitry Andric     assert(isLiveIn() &&
174e8d8bef9SDimitry Andric            "VPValue is not a live-in; it is defined by a VPDef inside a VPlan");
175e8d8bef9SDimitry Andric     return getUnderlyingValue();
176e8d8bef9SDimitry Andric   }
getLiveInIRValue()17704eeddc0SDimitry Andric   const Value *getLiveInIRValue() const {
17806c3fb27SDimitry Andric     assert(isLiveIn() &&
17904eeddc0SDimitry Andric            "VPValue is not a live-in; it is defined by a VPDef inside a VPlan");
18004eeddc0SDimitry Andric     return getUnderlyingValue();
18104eeddc0SDimitry Andric   }
182bdd1243dSDimitry Andric 
183bdd1243dSDimitry Andric   /// Returns true if the VPValue is defined outside any vector regions, i.e. it
184bdd1243dSDimitry Andric   /// is a live-in value.
185bdd1243dSDimitry Andric   /// TODO: Also handle recipes defined in pre-header blocks.
isDefinedOutsideVectorRegions()186bdd1243dSDimitry Andric   bool isDefinedOutsideVectorRegions() const { return !hasDefiningRecipe(); }
187*0fca6ea1SDimitry Andric 
188*0fca6ea1SDimitry Andric   // Set \p Val as the underlying Value of this VPValue.
setUnderlyingValue(Value * Val)189*0fca6ea1SDimitry Andric   void setUnderlyingValue(Value *Val) {
190*0fca6ea1SDimitry Andric     assert(!UnderlyingVal && "Underlying Value is already set.");
191*0fca6ea1SDimitry Andric     UnderlyingVal = Val;
192*0fca6ea1SDimitry Andric   }
1930b57cec5SDimitry Andric };
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric typedef DenseMap<Value *, VPValue *> Value2VPValueTy;
1960b57cec5SDimitry Andric typedef DenseMap<VPValue *, Value *> VPValue2ValueTy;
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const VPValue &V);
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric /// This class augments VPValue with operands which provide the inverse def-use
2010b57cec5SDimitry Andric /// edges from VPValue's users to their defs.
202e8d8bef9SDimitry Andric class VPUser {
203fe6060f1SDimitry Andric public:
204fe6060f1SDimitry Andric   /// Subclass identifier (for isa/dyn_cast).
205fe6060f1SDimitry Andric   enum class VPUserID {
206fe6060f1SDimitry Andric     Recipe,
20781ad6265SDimitry Andric     LiveOut,
208fe6060f1SDimitry Andric   };
209fe6060f1SDimitry Andric 
210fe6060f1SDimitry Andric private:
2110b57cec5SDimitry Andric   SmallVector<VPValue *, 2> Operands;
2120b57cec5SDimitry Andric 
213fe6060f1SDimitry Andric   VPUserID ID;
214fe6060f1SDimitry Andric 
2150b57cec5SDimitry Andric protected:
216fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
217e8d8bef9SDimitry Andric   /// Print the operands to \p O.
218e8d8bef9SDimitry Andric   void printOperands(raw_ostream &O, VPSlotTracker &SlotTracker) const;
219fe6060f1SDimitry Andric #endif
220fe6060f1SDimitry Andric 
VPUser(ArrayRef<VPValue * > Operands,VPUserID ID)221fe6060f1SDimitry Andric   VPUser(ArrayRef<VPValue *> Operands, VPUserID ID) : ID(ID) {
222fe6060f1SDimitry Andric     for (VPValue *Operand : Operands)
223fe6060f1SDimitry Andric       addOperand(Operand);
224fe6060f1SDimitry Andric   }
225fe6060f1SDimitry Andric 
VPUser(std::initializer_list<VPValue * > Operands,VPUserID ID)226fe6060f1SDimitry Andric   VPUser(std::initializer_list<VPValue *> Operands, VPUserID ID)
227fe6060f1SDimitry Andric       : VPUser(ArrayRef<VPValue *>(Operands), ID) {}
228fe6060f1SDimitry Andric 
229fe6060f1SDimitry Andric   template <typename IterT>
VPUser(iterator_range<IterT> Operands,VPUserID ID)230fe6060f1SDimitry Andric   VPUser(iterator_range<IterT> Operands, VPUserID ID) : ID(ID) {
231fe6060f1SDimitry Andric     for (VPValue *Operand : Operands)
232fe6060f1SDimitry Andric       addOperand(Operand);
233fe6060f1SDimitry Andric   }
234e8d8bef9SDimitry Andric 
235e8d8bef9SDimitry Andric public:
236fe6060f1SDimitry Andric   VPUser() = delete;
2370b57cec5SDimitry Andric   VPUser(const VPUser &) = delete;
2380b57cec5SDimitry Andric   VPUser &operator=(const VPUser &) = delete;
~VPUser()239e8d8bef9SDimitry Andric   virtual ~VPUser() {
240e8d8bef9SDimitry Andric     for (VPValue *Op : operands())
241e8d8bef9SDimitry Andric       Op->removeUser(*this);
2420b57cec5SDimitry Andric   }
2430b57cec5SDimitry Andric 
getVPUserID()244fe6060f1SDimitry Andric   VPUserID getVPUserID() const { return ID; }
245fe6060f1SDimitry Andric 
addOperand(VPValue * Operand)2460b57cec5SDimitry Andric   void addOperand(VPValue *Operand) {
2470b57cec5SDimitry Andric     Operands.push_back(Operand);
2480b57cec5SDimitry Andric     Operand->addUser(*this);
2490b57cec5SDimitry Andric   }
2500b57cec5SDimitry Andric 
getNumOperands()2510b57cec5SDimitry Andric   unsigned getNumOperands() const { return Operands.size(); }
getOperand(unsigned N)2520b57cec5SDimitry Andric   inline VPValue *getOperand(unsigned N) const {
2530b57cec5SDimitry Andric     assert(N < Operands.size() && "Operand index out of bounds");
2540b57cec5SDimitry Andric     return Operands[N];
2550b57cec5SDimitry Andric   }
2560b57cec5SDimitry Andric 
setOperand(unsigned I,VPValue * New)257e8d8bef9SDimitry Andric   void setOperand(unsigned I, VPValue *New) {
258e8d8bef9SDimitry Andric     Operands[I]->removeUser(*this);
259e8d8bef9SDimitry Andric     Operands[I] = New;
260e8d8bef9SDimitry Andric     New->addUser(*this);
261e8d8bef9SDimitry Andric   }
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric   typedef SmallVectorImpl<VPValue *>::iterator operand_iterator;
2640b57cec5SDimitry Andric   typedef SmallVectorImpl<VPValue *>::const_iterator const_operand_iterator;
2650b57cec5SDimitry Andric   typedef iterator_range<operand_iterator> operand_range;
2660b57cec5SDimitry Andric   typedef iterator_range<const_operand_iterator> const_operand_range;
2670b57cec5SDimitry Andric 
op_begin()2680b57cec5SDimitry Andric   operand_iterator op_begin() { return Operands.begin(); }
op_begin()2690b57cec5SDimitry Andric   const_operand_iterator op_begin() const { return Operands.begin(); }
op_end()2700b57cec5SDimitry Andric   operand_iterator op_end() { return Operands.end(); }
op_end()2710b57cec5SDimitry Andric   const_operand_iterator op_end() const { return Operands.end(); }
operands()2720b57cec5SDimitry Andric   operand_range operands() { return operand_range(op_begin(), op_end()); }
operands()2730b57cec5SDimitry Andric   const_operand_range operands() const {
2740b57cec5SDimitry Andric     return const_operand_range(op_begin(), op_end());
2750b57cec5SDimitry Andric   }
276e8d8bef9SDimitry Andric 
27781ad6265SDimitry Andric   /// Returns true if the VPUser uses scalars of operand \p Op. Conservatively
27881ad6265SDimitry Andric   /// returns if only first (scalar) lane is used, as default.
usesScalars(const VPValue * Op)27981ad6265SDimitry Andric   virtual bool usesScalars(const VPValue *Op) const {
28081ad6265SDimitry Andric     assert(is_contained(operands(), Op) &&
28181ad6265SDimitry Andric            "Op must be an operand of the recipe");
28281ad6265SDimitry Andric     return onlyFirstLaneUsed(Op);
28381ad6265SDimitry Andric   }
28481ad6265SDimitry Andric 
28581ad6265SDimitry Andric   /// Returns true if the VPUser only uses the first lane of operand \p Op.
28681ad6265SDimitry Andric   /// Conservatively returns false.
onlyFirstLaneUsed(const VPValue * Op)28781ad6265SDimitry Andric   virtual bool onlyFirstLaneUsed(const VPValue *Op) const {
28881ad6265SDimitry Andric     assert(is_contained(operands(), Op) &&
28981ad6265SDimitry Andric            "Op must be an operand of the recipe");
29081ad6265SDimitry Andric     return false;
29181ad6265SDimitry Andric   }
2925f757f3fSDimitry Andric 
2935f757f3fSDimitry Andric   /// Returns true if the VPUser only uses the first part of operand \p Op.
2945f757f3fSDimitry Andric   /// Conservatively returns false.
onlyFirstPartUsed(const VPValue * Op)2955f757f3fSDimitry Andric   virtual bool onlyFirstPartUsed(const VPValue *Op) const {
2965f757f3fSDimitry Andric     assert(is_contained(operands(), Op) &&
2975f757f3fSDimitry Andric            "Op must be an operand of the recipe");
2985f757f3fSDimitry Andric     return false;
2995f757f3fSDimitry Andric   }
3000b57cec5SDimitry Andric };
301e8d8bef9SDimitry Andric 
302e8d8bef9SDimitry Andric /// This class augments a recipe with a set of VPValues defined by the recipe.
303e8d8bef9SDimitry Andric /// It allows recipes to define zero, one or multiple VPValues. A VPDef owns
304e8d8bef9SDimitry Andric /// the VPValues it defines and is responsible for deleting its defined values.
305e8d8bef9SDimitry Andric /// Single-value VPDefs that also inherit from VPValue must make sure to inherit
306e8d8bef9SDimitry Andric /// from VPDef before VPValue.
307e8d8bef9SDimitry Andric class VPDef {
308e8d8bef9SDimitry Andric   friend class VPValue;
309e8d8bef9SDimitry Andric 
310e8d8bef9SDimitry Andric   /// Subclass identifier (for isa/dyn_cast).
311e8d8bef9SDimitry Andric   const unsigned char SubclassID;
312e8d8bef9SDimitry Andric 
313e8d8bef9SDimitry Andric   /// The VPValues defined by this VPDef.
314e8d8bef9SDimitry Andric   TinyPtrVector<VPValue *> DefinedValues;
315e8d8bef9SDimitry Andric 
316e8d8bef9SDimitry Andric   /// Add \p V as a defined value by this VPDef.
addDefinedValue(VPValue * V)317e8d8bef9SDimitry Andric   void addDefinedValue(VPValue *V) {
318bdd1243dSDimitry Andric     assert(V->Def == this &&
319e8d8bef9SDimitry Andric            "can only add VPValue already linked with this VPDef");
320e8d8bef9SDimitry Andric     DefinedValues.push_back(V);
321e8d8bef9SDimitry Andric   }
322e8d8bef9SDimitry Andric 
323e8d8bef9SDimitry Andric   /// Remove \p V from the values defined by this VPDef. \p V must be a defined
324e8d8bef9SDimitry Andric   /// value of this VPDef.
removeDefinedValue(VPValue * V)325e8d8bef9SDimitry Andric   void removeDefinedValue(VPValue *V) {
326bdd1243dSDimitry Andric     assert(V->Def == this && "can only remove VPValue linked with this VPDef");
327e8d8bef9SDimitry Andric     assert(is_contained(DefinedValues, V) &&
328e8d8bef9SDimitry Andric            "VPValue to remove must be in DefinedValues");
3295f757f3fSDimitry Andric     llvm::erase(DefinedValues, V);
330e8d8bef9SDimitry Andric     V->Def = nullptr;
331e8d8bef9SDimitry Andric   }
332e8d8bef9SDimitry Andric 
333e8d8bef9SDimitry Andric public:
334e8d8bef9SDimitry Andric   /// An enumeration for keeping track of the concrete subclass of VPRecipeBase
335e8d8bef9SDimitry Andric   /// that is actually instantiated. Values of this enumeration are kept in the
336e8d8bef9SDimitry Andric   /// SubclassID field of the VPRecipeBase objects. They are used for concrete
337e8d8bef9SDimitry Andric   /// type identification.
338e8d8bef9SDimitry Andric   using VPRecipeTy = enum {
339e8d8bef9SDimitry Andric     VPBranchOnMaskSC,
340bdd1243dSDimitry Andric     VPDerivedIVSC,
34181ad6265SDimitry Andric     VPExpandSCEVSC,
342e8d8bef9SDimitry Andric     VPInstructionSC,
343e8d8bef9SDimitry Andric     VPInterleaveSC,
344*0fca6ea1SDimitry Andric     VPReductionEVLSC,
345e8d8bef9SDimitry Andric     VPReductionSC,
346e8d8bef9SDimitry Andric     VPReplicateSC,
347*0fca6ea1SDimitry Andric     VPScalarCastSC,
34881ad6265SDimitry Andric     VPScalarIVStepsSC,
349647cbc5dSDimitry Andric     VPVectorPointerSC,
350e8d8bef9SDimitry Andric     VPWidenCallSC,
35104eeddc0SDimitry Andric     VPWidenCanonicalIVSC,
35206c3fb27SDimitry Andric     VPWidenCastSC,
353e8d8bef9SDimitry Andric     VPWidenGEPSC,
354*0fca6ea1SDimitry Andric     VPWidenLoadEVLSC,
355*0fca6ea1SDimitry Andric     VPWidenLoadSC,
356*0fca6ea1SDimitry Andric     VPWidenStoreEVLSC,
357*0fca6ea1SDimitry Andric     VPWidenStoreSC,
358e8d8bef9SDimitry Andric     VPWidenSC,
359fe6060f1SDimitry Andric     VPWidenSelectSC,
360fe6060f1SDimitry Andric     VPBlendSC,
361*0fca6ea1SDimitry Andric     // START: Phi-like recipes. Need to be kept together.
362*0fca6ea1SDimitry Andric     VPWidenPHISC,
363bdd1243dSDimitry Andric     VPPredInstPHISC,
36406c3fb27SDimitry Andric     // START: SubclassID for recipes that inherit VPHeaderPHIRecipe.
36506c3fb27SDimitry Andric     // VPHeaderPHIRecipe need to be kept together.
36604eeddc0SDimitry Andric     VPCanonicalIVPHISC,
367753f127fSDimitry Andric     VPActiveLaneMaskPHISC,
368*0fca6ea1SDimitry Andric     VPEVLBasedIVPHISC,
369fe6060f1SDimitry Andric     VPFirstOrderRecurrencePHISC,
370fe6060f1SDimitry Andric     VPWidenIntOrFpInductionSC,
37181ad6265SDimitry Andric     VPWidenPointerInductionSC,
372fe6060f1SDimitry Andric     VPReductionPHISC,
37306c3fb27SDimitry Andric     // END: SubclassID for recipes that inherit VPHeaderPHIRecipe
37406c3fb27SDimitry Andric     // END: Phi-like recipes
375*0fca6ea1SDimitry Andric     VPFirstPHISC = VPWidenPHISC,
376bdd1243dSDimitry Andric     VPFirstHeaderPHISC = VPCanonicalIVPHISC,
37706c3fb27SDimitry Andric     VPLastHeaderPHISC = VPReductionPHISC,
378fe6060f1SDimitry Andric     VPLastPHISC = VPReductionPHISC,
379e8d8bef9SDimitry Andric   };
380e8d8bef9SDimitry Andric 
VPDef(const unsigned char SC)381e8d8bef9SDimitry Andric   VPDef(const unsigned char SC) : SubclassID(SC) {}
382e8d8bef9SDimitry Andric 
~VPDef()383e8d8bef9SDimitry Andric   virtual ~VPDef() {
384e8d8bef9SDimitry Andric     for (VPValue *D : make_early_inc_range(DefinedValues)) {
385e8d8bef9SDimitry Andric       assert(D->Def == this &&
386e8d8bef9SDimitry Andric              "all defined VPValues should point to the containing VPDef");
387e8d8bef9SDimitry Andric       assert(D->getNumUsers() == 0 &&
388e8d8bef9SDimitry Andric              "all defined VPValues should have no more users");
389e8d8bef9SDimitry Andric       D->Def = nullptr;
390e8d8bef9SDimitry Andric       delete D;
391e8d8bef9SDimitry Andric     }
392e8d8bef9SDimitry Andric   }
393e8d8bef9SDimitry Andric 
394fe6060f1SDimitry Andric   /// Returns the only VPValue defined by the VPDef. Can only be called for
395fe6060f1SDimitry Andric   /// VPDefs with a single defined value.
getVPSingleValue()396fe6060f1SDimitry Andric   VPValue *getVPSingleValue() {
397fe6060f1SDimitry Andric     assert(DefinedValues.size() == 1 && "must have exactly one defined value");
398fe6060f1SDimitry Andric     assert(DefinedValues[0] && "defined value must be non-null");
399fe6060f1SDimitry Andric     return DefinedValues[0];
400fe6060f1SDimitry Andric   }
getVPSingleValue()401fe6060f1SDimitry Andric   const VPValue *getVPSingleValue() const {
402fe6060f1SDimitry Andric     assert(DefinedValues.size() == 1 && "must have exactly one defined value");
403fe6060f1SDimitry Andric     assert(DefinedValues[0] && "defined value must be non-null");
404fe6060f1SDimitry Andric     return DefinedValues[0];
405fe6060f1SDimitry Andric   }
406fe6060f1SDimitry Andric 
407e8d8bef9SDimitry Andric   /// Returns the VPValue with index \p I defined by the VPDef.
getVPValue(unsigned I)408fe6060f1SDimitry Andric   VPValue *getVPValue(unsigned I) {
409e8d8bef9SDimitry Andric     assert(DefinedValues[I] && "defined value must be non-null");
410e8d8bef9SDimitry Andric     return DefinedValues[I];
411e8d8bef9SDimitry Andric   }
getVPValue(unsigned I)412fe6060f1SDimitry Andric   const VPValue *getVPValue(unsigned I) const {
413e8d8bef9SDimitry Andric     assert(DefinedValues[I] && "defined value must be non-null");
414e8d8bef9SDimitry Andric     return DefinedValues[I];
415e8d8bef9SDimitry Andric   }
416e8d8bef9SDimitry Andric 
417e8d8bef9SDimitry Andric   /// Returns an ArrayRef of the values defined by the VPDef.
definedValues()418e8d8bef9SDimitry Andric   ArrayRef<VPValue *> definedValues() { return DefinedValues; }
419e8d8bef9SDimitry Andric   /// Returns an ArrayRef of the values defined by the VPDef.
definedValues()420e8d8bef9SDimitry Andric   ArrayRef<VPValue *> definedValues() const { return DefinedValues; }
421e8d8bef9SDimitry Andric 
422e8d8bef9SDimitry Andric   /// Returns the number of values defined by the VPDef.
getNumDefinedValues()423e8d8bef9SDimitry Andric   unsigned getNumDefinedValues() const { return DefinedValues.size(); }
424e8d8bef9SDimitry Andric 
425e8d8bef9SDimitry Andric   /// \return an ID for the concrete type of this object.
426e8d8bef9SDimitry Andric   /// This is used to implement the classof checks. This should not be used
427e8d8bef9SDimitry Andric   /// for any other purpose, as the values may change as LLVM evolves.
getVPDefID()428e8d8bef9SDimitry Andric   unsigned getVPDefID() const { return SubclassID; }
429e8d8bef9SDimitry Andric 
430fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
431e8d8bef9SDimitry Andric   /// Dump the VPDef to stderr (for debugging).
432e8d8bef9SDimitry Andric   void dump() const;
433e8d8bef9SDimitry Andric 
434e8d8bef9SDimitry Andric   /// Each concrete VPDef prints itself.
435e8d8bef9SDimitry Andric   virtual void print(raw_ostream &O, const Twine &Indent,
436e8d8bef9SDimitry Andric                      VPSlotTracker &SlotTracker) const = 0;
437fe6060f1SDimitry Andric #endif
438e8d8bef9SDimitry Andric };
439e8d8bef9SDimitry Andric 
4405ffd83dbSDimitry Andric class VPlan;
4415ffd83dbSDimitry Andric class VPBasicBlock;
4425ffd83dbSDimitry Andric 
443*0fca6ea1SDimitry Andric /// This class can be used to assign names to VPValues. For VPValues without
444*0fca6ea1SDimitry Andric /// underlying value, assign consecutive numbers and use those as names (wrapped
445*0fca6ea1SDimitry Andric /// in vp<>). Otherwise, use the name from the underlying value (wrapped in
446*0fca6ea1SDimitry Andric /// ir<>), appending a .V version number if there are multiple uses of the same
447*0fca6ea1SDimitry Andric /// name. Allows querying names for VPValues for printing, similar to the
4485ffd83dbSDimitry Andric /// ModuleSlotTracker for IR values.
4495ffd83dbSDimitry Andric class VPSlotTracker {
450*0fca6ea1SDimitry Andric   /// Keep track of versioned names assigned to VPValues with underlying IR
451*0fca6ea1SDimitry Andric   /// values.
452*0fca6ea1SDimitry Andric   DenseMap<const VPValue *, std::string> VPValue2Name;
453*0fca6ea1SDimitry Andric   /// Keep track of the next number to use to version the base name.
454*0fca6ea1SDimitry Andric   StringMap<unsigned> BaseName2Version;
455*0fca6ea1SDimitry Andric 
456*0fca6ea1SDimitry Andric   /// Number to assign to the next VPValue without underlying value.
4575ffd83dbSDimitry Andric   unsigned NextSlot = 0;
4585ffd83dbSDimitry Andric 
459*0fca6ea1SDimitry Andric   void assignName(const VPValue *V);
460*0fca6ea1SDimitry Andric   void assignNames(const VPlan &Plan);
461*0fca6ea1SDimitry Andric   void assignNames(const VPBasicBlock *VPBB);
4625ffd83dbSDimitry Andric 
4635ffd83dbSDimitry Andric public:
464e8d8bef9SDimitry Andric   VPSlotTracker(const VPlan *Plan = nullptr) {
4655ffd83dbSDimitry Andric     if (Plan)
466*0fca6ea1SDimitry Andric       assignNames(*Plan);
4675ffd83dbSDimitry Andric   }
4685ffd83dbSDimitry Andric 
469*0fca6ea1SDimitry Andric   /// Returns the name assigned to \p V, if there is one, otherwise try to
470*0fca6ea1SDimitry Andric   /// construct one from the underlying value, if there's one; else return
471*0fca6ea1SDimitry Andric   /// <badref>.
472*0fca6ea1SDimitry Andric   std::string getOrCreateName(const VPValue *V) const;
4735ffd83dbSDimitry Andric };
4740b57cec5SDimitry Andric 
4750b57cec5SDimitry Andric } // namespace llvm
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric #endif // LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H
478