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