1 //===- VPlanValue.h - Represent Values in Vectorizer Plan -----------------===//
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
7 //===----------------------------------------------------------------------===//
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
16 /// These are documented in docs/VectorizationPlan.rst.
18 //===----------------------------------------------------------------------===//
20 #ifndef LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H
21 #define LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H
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"
31 // Forward declarations.
38 class VPWidenMemoryInstructionRecipe
;
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.
45 friend class VPBuilder
;
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
;
55 const unsigned char SubclassID
; ///< Subclass identifier (for isa/dyn_cast).
57 SmallVector
<VPUser
*, 1> Users
;
60 // Hold the underlying Value, if any, attached to this VPValue.
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.
67 VPValue(const unsigned char SC
, Value
*UV
= nullptr, VPDef
*Def
= nullptr);
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.
76 // Set \p Val as the underlying Value of this VPValue.
77 void setUnderlyingValue(Value
*Val
) {
78 assert(!UnderlyingVal
&& "Underlying Value is already set.");
83 /// Return the underlying Value attached to this VPValue.
84 Value
*getUnderlyingValue() { return UnderlyingVal
; }
85 const Value
*getUnderlyingValue() const { return UnderlyingVal
; }
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.
94 VPVMemoryInstructionSC
,
102 // Phi-like VPValues. Need to be kept together.
104 VPVFirstOrderRecurrencePHISC
,
106 VPVWidenCanonicalIVSC
,
107 VPVWidenIntOrFpInductionSC
,
112 VPValue(Value
*UV
= nullptr, VPDef
*Def
= nullptr)
113 : VPValue(VPValueSC
, UV
, Def
) {}
114 VPValue(const VPValue
&) = delete;
115 VPValue
&operator=(const VPValue
&) = delete;
119 /// \return an ID for the concrete type of this object.
120 /// This is used to implement the classof checks. This should not be used
121 /// for any other purpose, as the values may change as LLVM evolves.
122 unsigned getVPValueID() const { return SubclassID
; }
124 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
125 void printAsOperand(raw_ostream
&OS
, VPSlotTracker
&Tracker
) const;
126 void print(raw_ostream
&OS
, VPSlotTracker
&Tracker
) const;
128 /// Dump the value to stderr (for debugging).
132 unsigned getNumUsers() const { return Users
.size(); }
133 void addUser(VPUser
&User
) { Users
.push_back(&User
); }
135 /// Remove a single \p User from the list of users.
136 void removeUser(VPUser
&User
) {
138 // The same user can be added multiple times, e.g. because the same VPValue
139 // is used twice by the same VPUser. Remove a single one.
140 erase_if(Users
, [&User
, &Found
](VPUser
*Other
) {
143 if (Other
== &User
) {
151 typedef SmallVectorImpl
<VPUser
*>::iterator user_iterator
;
152 typedef SmallVectorImpl
<VPUser
*>::const_iterator const_user_iterator
;
153 typedef iterator_range
<user_iterator
> user_range
;
154 typedef iterator_range
<const_user_iterator
> const_user_range
;
156 user_iterator
user_begin() { return Users
.begin(); }
157 const_user_iterator
user_begin() const { return Users
.begin(); }
158 user_iterator
user_end() { return Users
.end(); }
159 const_user_iterator
user_end() const { return Users
.end(); }
160 user_range
users() { return user_range(user_begin(), user_end()); }
161 const_user_range
users() const {
162 return const_user_range(user_begin(), user_end());
165 /// Returns true if the value has more than one unique user.
166 bool hasMoreThanOneUniqueUser() {
167 if (getNumUsers() == 0)
170 // Check if all users match the first user.
171 auto Current
= std::next(user_begin());
172 while (Current
!= user_end() && *user_begin() == *Current
)
174 return Current
!= user_end();
177 void replaceAllUsesWith(VPValue
*New
);
179 VPDef
*getDef() { return Def
; }
181 /// Returns the underlying IR value, if this VPValue is defined outside the
182 /// scope of VPlan. Returns nullptr if the VPValue is defined by a VPDef
184 Value
*getLiveInIRValue() {
186 "VPValue is not a live-in; it is defined by a VPDef inside a VPlan");
187 return getUnderlyingValue();
191 typedef DenseMap
<Value
*, VPValue
*> Value2VPValueTy
;
192 typedef DenseMap
<VPValue
*, Value
*> VPValue2ValueTy
;
194 raw_ostream
&operator<<(raw_ostream
&OS
, const VPValue
&V
);
196 /// This class augments VPValue with operands which provide the inverse def-use
197 /// edges from VPValue's users to their defs.
200 /// Subclass identifier (for isa/dyn_cast).
201 enum class VPUserID
{
203 // TODO: Currently VPUsers are used in VPBlockBase, but in the future the
204 // only VPUsers should either be recipes or live-outs.
209 SmallVector
<VPValue
*, 2> Operands
;
214 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
215 /// Print the operands to \p O.
216 void printOperands(raw_ostream
&O
, VPSlotTracker
&SlotTracker
) const;
219 VPUser(ArrayRef
<VPValue
*> Operands
, VPUserID ID
) : ID(ID
) {
220 for (VPValue
*Operand
: Operands
)
224 VPUser(std::initializer_list
<VPValue
*> Operands
, VPUserID ID
)
225 : VPUser(ArrayRef
<VPValue
*>(Operands
), ID
) {}
227 template <typename IterT
>
228 VPUser(iterator_range
<IterT
> Operands
, VPUserID ID
) : ID(ID
) {
229 for (VPValue
*Operand
: Operands
)
235 VPUser(const VPUser
&) = delete;
236 VPUser
&operator=(const VPUser
&) = delete;
238 for (VPValue
*Op
: operands())
239 Op
->removeUser(*this);
242 VPUserID
getVPUserID() const { return ID
; }
244 void addOperand(VPValue
*Operand
) {
245 Operands
.push_back(Operand
);
246 Operand
->addUser(*this);
249 unsigned getNumOperands() const { return Operands
.size(); }
250 inline VPValue
*getOperand(unsigned N
) const {
251 assert(N
< Operands
.size() && "Operand index out of bounds");
255 void setOperand(unsigned I
, VPValue
*New
) {
256 Operands
[I
]->removeUser(*this);
261 void removeLastOperand() {
262 VPValue
*Op
= Operands
.pop_back_val();
263 Op
->removeUser(*this);
266 typedef SmallVectorImpl
<VPValue
*>::iterator operand_iterator
;
267 typedef SmallVectorImpl
<VPValue
*>::const_iterator const_operand_iterator
;
268 typedef iterator_range
<operand_iterator
> operand_range
;
269 typedef iterator_range
<const_operand_iterator
> const_operand_range
;
271 operand_iterator
op_begin() { return Operands
.begin(); }
272 const_operand_iterator
op_begin() const { return Operands
.begin(); }
273 operand_iterator
op_end() { return Operands
.end(); }
274 const_operand_iterator
op_end() const { return Operands
.end(); }
275 operand_range
operands() { return operand_range(op_begin(), op_end()); }
276 const_operand_range
operands() const {
277 return const_operand_range(op_begin(), op_end());
280 /// Method to support type inquiry through isa, cast, and dyn_cast.
281 static inline bool classof(const VPDef
*Recipe
);
284 /// This class augments a recipe with a set of VPValues defined by the recipe.
285 /// It allows recipes to define zero, one or multiple VPValues. A VPDef owns
286 /// the VPValues it defines and is responsible for deleting its defined values.
287 /// Single-value VPDefs that also inherit from VPValue must make sure to inherit
288 /// from VPDef before VPValue.
290 friend class VPValue
;
292 /// Subclass identifier (for isa/dyn_cast).
293 const unsigned char SubclassID
;
295 /// The VPValues defined by this VPDef.
296 TinyPtrVector
<VPValue
*> DefinedValues
;
298 /// Add \p V as a defined value by this VPDef.
299 void addDefinedValue(VPValue
*V
) {
300 assert(V
->getDef() == this &&
301 "can only add VPValue already linked with this VPDef");
302 DefinedValues
.push_back(V
);
305 /// Remove \p V from the values defined by this VPDef. \p V must be a defined
306 /// value of this VPDef.
307 void removeDefinedValue(VPValue
*V
) {
308 assert(V
->getDef() == this &&
309 "can only remove VPValue linked with this VPDef");
310 assert(is_contained(DefinedValues
, V
) &&
311 "VPValue to remove must be in DefinedValues");
312 erase_value(DefinedValues
, V
);
317 /// An enumeration for keeping track of the concrete subclass of VPRecipeBase
318 /// that is actually instantiated. Values of this enumeration are kept in the
319 /// SubclassID field of the VPRecipeBase objects. They are used for concrete
320 /// type identification.
321 using VPRecipeTy
= enum {
329 VPWidenMemoryInstructionSC
,
333 // Phi-like recipes. Need to be kept together.
335 VPFirstOrderRecurrencePHISC
,
337 VPWidenCanonicalIVSC
,
338 VPWidenIntOrFpInductionSC
,
341 VPFirstPHISC
= VPBlendSC
,
342 VPLastPHISC
= VPReductionPHISC
,
345 VPDef(const unsigned char SC
) : SubclassID(SC
) {}
348 for (VPValue
*D
: make_early_inc_range(DefinedValues
)) {
349 assert(D
->Def
== this &&
350 "all defined VPValues should point to the containing VPDef");
351 assert(D
->getNumUsers() == 0 &&
352 "all defined VPValues should have no more users");
358 /// Returns the only VPValue defined by the VPDef. Can only be called for
359 /// VPDefs with a single defined value.
360 VPValue
*getVPSingleValue() {
361 assert(DefinedValues
.size() == 1 && "must have exactly one defined value");
362 assert(DefinedValues
[0] && "defined value must be non-null");
363 return DefinedValues
[0];
365 const VPValue
*getVPSingleValue() const {
366 assert(DefinedValues
.size() == 1 && "must have exactly one defined value");
367 assert(DefinedValues
[0] && "defined value must be non-null");
368 return DefinedValues
[0];
371 /// Returns the VPValue with index \p I defined by the VPDef.
372 VPValue
*getVPValue(unsigned I
) {
373 assert(DefinedValues
[I
] && "defined value must be non-null");
374 return DefinedValues
[I
];
376 const VPValue
*getVPValue(unsigned I
) const {
377 assert(DefinedValues
[I
] && "defined value must be non-null");
378 return DefinedValues
[I
];
381 /// Returns an ArrayRef of the values defined by the VPDef.
382 ArrayRef
<VPValue
*> definedValues() { return DefinedValues
; }
383 /// Returns an ArrayRef of the values defined by the VPDef.
384 ArrayRef
<VPValue
*> definedValues() const { return DefinedValues
; }
386 /// Returns the number of values defined by the VPDef.
387 unsigned getNumDefinedValues() const { return DefinedValues
.size(); }
389 /// \return an ID for the concrete type of this object.
390 /// This is used to implement the classof checks. This should not be used
391 /// for any other purpose, as the values may change as LLVM evolves.
392 unsigned getVPDefID() const { return SubclassID
; }
394 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
395 /// Dump the VPDef to stderr (for debugging).
398 /// Each concrete VPDef prints itself.
399 virtual void print(raw_ostream
&O
, const Twine
&Indent
,
400 VPSlotTracker
&SlotTracker
) const = 0;
408 /// This class can be used to assign consecutive numbers to all VPValues in a
409 /// VPlan and allows querying the numbering for printing, similar to the
410 /// ModuleSlotTracker for IR values.
411 class VPSlotTracker
{
412 DenseMap
<const VPValue
*, unsigned> Slots
;
413 unsigned NextSlot
= 0;
415 void assignSlot(const VPValue
*V
);
416 void assignSlots(const VPlan
&Plan
);
419 VPSlotTracker(const VPlan
*Plan
= nullptr) {
424 unsigned getSlot(const VPValue
*V
) const {
425 auto I
= Slots
.find(V
);
426 if (I
== Slots
.end())
434 #endif // LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H