xref: /llvm-project/llvm/lib/Transforms/Vectorize/VPlanValue.h (revision e42e5263bd5dd8fb8dd95d5081231f7cf4b82b6f)
1 //===- VPlanValue.h - Represent Values in Vectorizer Plan -----------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// This file contains the declarations of the entities induced by Vectorization
11 /// Plans, e.g. the instructions the VPlan intends to generate if executed.
12 /// VPlan models the following entities:
13 /// VPValue   VPUser   VPDef
14 ///    |        |
15 ///   VPInstruction
16 /// These are documented in docs/VectorizationPlan.rst.
17 ///
18 //===----------------------------------------------------------------------===//
19 
20 #ifndef LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H
21 #define LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H
22 
23 #include "llvm/ADT/DenseMap.h"
24 #include "llvm/ADT/STLExtras.h"
25 #include "llvm/ADT/SmallVector.h"
26 #include "llvm/ADT/TinyPtrVector.h"
27 #include "llvm/ADT/iterator_range.h"
28 
29 namespace llvm {
30 
31 // Forward declarations.
32 class raw_ostream;
33 class Value;
34 class VPDef;
35 class VPSlotTracker;
36 class VPUser;
37 class VPRecipeBase;
38 class VPPredInstPHIRecipe;
39 class VPWidenMemoryInstructionRecipe;
40 
41 // This is the base class of the VPlan Def/Use graph, used for modeling the data
42 // flow into, within and out of the VPlan. VPValues can stand for live-ins
43 // coming from the input IR, instructions which VPlan will generate if executed
44 // and live-outs which the VPlan will need to fix accordingly.
45 class VPValue {
46   friend class VPBuilder;
47   friend class VPDef;
48   friend struct VPlanTransforms;
49   friend class VPBasicBlock;
50   friend class VPInterleavedAccessInfo;
51   friend class VPSlotTracker;
52   friend class VPRecipeBase;
53   friend class VPPredInstPHIRecipe;
54   friend class VPWidenMemoryInstructionRecipe;
55 
56   const unsigned char SubclassID; ///< Subclass identifier (for isa/dyn_cast).
57 
58   SmallVector<VPUser *, 1> Users;
59 
60 protected:
61   // Hold the underlying Value, if any, attached to this VPValue.
62   Value *UnderlyingVal;
63 
64   /// Pointer to the VPDef that defines this VPValue. If it is nullptr, the
65   /// VPValue is not defined by any recipe modeled in VPlan.
66   VPDef *Def;
67 
68   VPValue(const unsigned char SC, Value *UV = nullptr, VPDef *Def = nullptr);
69 
70   // DESIGN PRINCIPLE: Access to the underlying IR must be strictly limited to
71   // the front-end and back-end of VPlan so that the middle-end is as
72   // independent as possible of the underlying IR. We grant access to the
73   // underlying IR using friendship. In that way, we should be able to use VPlan
74   // for multiple underlying IRs (Polly?) by providing a new VPlan front-end,
75   // back-end and analysis information for the new IR.
76 
77   /// Return the underlying Value attached to this VPValue.
78   Value *getUnderlyingValue() { return UnderlyingVal; }
79   const Value *getUnderlyingValue() const { return UnderlyingVal; }
80 
81   // Set \p Val as the underlying Value of this VPValue.
82   void setUnderlyingValue(Value *Val) {
83     assert(!UnderlyingVal && "Underlying Value is already set.");
84     UnderlyingVal = Val;
85   }
86 
87 public:
88   /// An enumeration for keeping track of the concrete subclass of VPValue that
89   /// are actually instantiated. Values of this enumeration are kept in the
90   /// SubclassID field of the VPValue objects. They are used for concrete
91   /// type identification.
92   enum {
93     VPValueSC,
94     VPVInstructionSC,
95     VPVMemoryInstructionSC,
96     VPVReductionSC,
97     VPVReplicateSC,
98     VPVWidenSC,
99     VPVWidenCallSC,
100     VPVWidenGEPSC,
101     VPVWidenSelectSC,
102   };
103 
104   VPValue(Value *UV = nullptr, VPDef *Def = nullptr)
105       : VPValue(VPValueSC, UV, Def) {}
106   VPValue(const VPValue &) = delete;
107   VPValue &operator=(const VPValue &) = delete;
108 
109   virtual ~VPValue();
110 
111   /// \return an ID for the concrete type of this object.
112   /// This is used to implement the classof checks. This should not be used
113   /// for any other purpose, as the values may change as LLVM evolves.
114   unsigned getVPValueID() const { return SubclassID; }
115 
116   void printAsOperand(raw_ostream &OS, VPSlotTracker &Tracker) const;
117   void print(raw_ostream &OS, VPSlotTracker &Tracker) const;
118 
119   /// Dump the value to stderr (for debugging).
120   void dump() const;
121 
122   unsigned getNumUsers() const { return Users.size(); }
123   void addUser(VPUser &User) { Users.push_back(&User); }
124 
125   /// Remove a single \p User from the list of users.
126   void removeUser(VPUser &User) {
127     bool Found = false;
128     // The same user can be added multiple times, e.g. because the same VPValue
129     // is used twice by the same VPUser. Remove a single one.
130     erase_if(Users, [&User, &Found](VPUser *Other) {
131       if (Found)
132         return false;
133       if (Other == &User) {
134         Found = true;
135         return true;
136       }
137       return false;
138     });
139   }
140 
141   typedef SmallVectorImpl<VPUser *>::iterator user_iterator;
142   typedef SmallVectorImpl<VPUser *>::const_iterator const_user_iterator;
143   typedef iterator_range<user_iterator> user_range;
144   typedef iterator_range<const_user_iterator> const_user_range;
145 
146   user_iterator user_begin() { return Users.begin(); }
147   const_user_iterator user_begin() const { return Users.begin(); }
148   user_iterator user_end() { return Users.end(); }
149   const_user_iterator user_end() const { return Users.end(); }
150   user_range users() { return user_range(user_begin(), user_end()); }
151   const_user_range users() const {
152     return const_user_range(user_begin(), user_end());
153   }
154 
155   /// Returns true if the value has more than one unique user.
156   bool hasMoreThanOneUniqueUser() {
157     if (getNumUsers() == 0)
158       return false;
159 
160     // Check if all users match the first user.
161     auto Current = std::next(user_begin());
162     while (Current != user_end() && *user_begin() == *Current)
163       Current++;
164     return Current != user_end();
165   }
166 
167   void replaceAllUsesWith(VPValue *New);
168 
169   VPDef *getDef() { return Def; }
170 };
171 
172 typedef DenseMap<Value *, VPValue *> Value2VPValueTy;
173 typedef DenseMap<VPValue *, Value *> VPValue2ValueTy;
174 
175 raw_ostream &operator<<(raw_ostream &OS, const VPValue &V);
176 
177 /// This class augments VPValue with operands which provide the inverse def-use
178 /// edges from VPValue's users to their defs.
179 class VPUser {
180   SmallVector<VPValue *, 2> Operands;
181 
182 protected:
183   /// Print the operands to \p O.
184   void printOperands(raw_ostream &O, VPSlotTracker &SlotTracker) const;
185 
186 public:
187   VPUser() {}
188   VPUser(ArrayRef<VPValue *> Operands) {
189     for (VPValue *Operand : Operands)
190       addOperand(Operand);
191   }
192 
193   VPUser(std::initializer_list<VPValue *> Operands)
194       : VPUser(ArrayRef<VPValue *>(Operands)) {}
195   template <typename IterT> VPUser(iterator_range<IterT> Operands) {
196     for (VPValue *Operand : Operands)
197       addOperand(Operand);
198   }
199 
200   VPUser(const VPUser &) = delete;
201   VPUser &operator=(const VPUser &) = delete;
202   virtual ~VPUser() {
203     for (VPValue *Op : operands())
204       Op->removeUser(*this);
205   }
206 
207   void addOperand(VPValue *Operand) {
208     Operands.push_back(Operand);
209     Operand->addUser(*this);
210   }
211 
212   unsigned getNumOperands() const { return Operands.size(); }
213   inline VPValue *getOperand(unsigned N) const {
214     assert(N < Operands.size() && "Operand index out of bounds");
215     return Operands[N];
216   }
217 
218   void setOperand(unsigned I, VPValue *New) {
219     Operands[I]->removeUser(*this);
220     Operands[I] = New;
221     New->addUser(*this);
222   }
223 
224   typedef SmallVectorImpl<VPValue *>::iterator operand_iterator;
225   typedef SmallVectorImpl<VPValue *>::const_iterator const_operand_iterator;
226   typedef iterator_range<operand_iterator> operand_range;
227   typedef iterator_range<const_operand_iterator> const_operand_range;
228 
229   operand_iterator op_begin() { return Operands.begin(); }
230   const_operand_iterator op_begin() const { return Operands.begin(); }
231   operand_iterator op_end() { return Operands.end(); }
232   const_operand_iterator op_end() const { return Operands.end(); }
233   operand_range operands() { return operand_range(op_begin(), op_end()); }
234   const_operand_range operands() const {
235     return const_operand_range(op_begin(), op_end());
236   }
237 
238   /// Method to support type inquiry through isa, cast, and dyn_cast.
239   static inline bool classof(const VPRecipeBase *Recipe);
240 };
241 
242 /// This class augments a recipe with a set of VPValues defined by the recipe.
243 /// It allows recipes to define zero, one or multiple VPValues. A VPDef owns
244 /// the VPValues it defines and is responsible for deleting its defined values.
245 /// Single-value VPDefs that also inherit from VPValue must make sure to inherit
246 /// from VPDef before VPValue.
247 class VPDef {
248   friend class VPValue;
249 
250   /// The VPValues defined by this VPDef.
251   TinyPtrVector<VPValue *> DefinedValues;
252 
253   /// Add \p V as a defined value by this VPDef.
254   void addDefinedValue(VPValue *V) {
255     assert(V->getDef() == this &&
256            "can only add VPValue already linked with this VPDef");
257     DefinedValues.push_back(V);
258   }
259 
260   /// Remove \p V from the values defined by this VPDef. \p V must be a defined
261   /// value of this VPDef.
262   void removeDefinedValue(VPValue *V) {
263     assert(V->getDef() == this &&
264            "can only remove VPValue linked with this VPDef");
265     assert(is_contained(DefinedValues, V) &&
266            "VPValue to remove must be in DefinedValues");
267     erase_value(DefinedValues, V);
268     V->Def = nullptr;
269   }
270 
271 public:
272   virtual ~VPDef() {
273     for (VPValue *D : make_early_inc_range(DefinedValues)) {
274       assert(D->Def == this &&
275              "all defined VPValues should point to the containing VPDef");
276       assert(D->getNumUsers() == 0 &&
277              "all defined VPValues should have no more users");
278       D->Def = nullptr;
279       delete D;
280     }
281   }
282 
283   /// Returns the VPValue with index \p I defined by the VPDef.
284   VPValue *getVPValue(unsigned I = 0) {
285     assert(DefinedValues[I] && "defined value must be non-null");
286     return DefinedValues[I];
287   }
288   const VPValue *getVPValue(unsigned I = 0) const {
289     assert(DefinedValues[I] && "defined value must be non-null");
290     return DefinedValues[I];
291   }
292 
293   /// Returns an ArrayRef of the values defined by the VPDef.
294   ArrayRef<VPValue *> definedValues() { return DefinedValues; }
295 
296   /// Returns the number of values defined by the VPDef.
297   unsigned getNumDefinedValues() const { return DefinedValues.size(); }
298 };
299 
300 class VPlan;
301 class VPBasicBlock;
302 class VPRegionBlock;
303 
304 /// This class can be used to assign consecutive numbers to all VPValues in a
305 /// VPlan and allows querying the numbering for printing, similar to the
306 /// ModuleSlotTracker for IR values.
307 class VPSlotTracker {
308   DenseMap<const VPValue *, unsigned> Slots;
309   unsigned NextSlot = 0;
310 
311   void assignSlots(const VPBlockBase *VPBB);
312   void assignSlots(const VPRegionBlock *Region);
313   void assignSlots(const VPBasicBlock *VPBB);
314   void assignSlot(const VPValue *V);
315 
316   void assignSlots(const VPlan &Plan);
317 
318 public:
319   VPSlotTracker(const VPlan *Plan) {
320     if (Plan)
321       assignSlots(*Plan);
322   }
323 
324   unsigned getSlot(const VPValue *V) const {
325     auto I = Slots.find(V);
326     if (I == Slots.end())
327       return -1;
328     return I->second;
329   }
330 };
331 
332 } // namespace llvm
333 
334 #endif // LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H
335