1227825Stheraven//===- VPlanValue.h - Represent Values in Vectorizer Plan -----------------===//
2227825Stheraven//
3227825Stheraven// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4227825Stheraven// See https://llvm.org/LICENSE.txt for license information.
5227825Stheraven// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6227825Stheraven//
7227825Stheraven//===----------------------------------------------------------------------===//
8227825Stheraven///
9227825Stheraven/// \file
10262801Sdim/// This file contains the declarations of the entities induced by Vectorization
11227825Stheraven/// Plans, e.g. the instructions the VPlan intends to generate if executed.
12227825Stheraven/// VPlan models the following entities:
13227825Stheraven/// VPValue   VPUser   VPDef
14227825Stheraven///    |        |
15227825Stheraven///   VPInstruction
16227825Stheraven/// These are documented in docs/VectorizationPlan.rst.
17227825Stheraven///
18227825Stheraven//===----------------------------------------------------------------------===//
19227825Stheraven
20249998Sdim#ifndef LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H
21227825Stheraven#define LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H
22227825Stheraven
23227825Stheraven#include "llvm/ADT/DenseMap.h"
24227825Stheraven#include "llvm/ADT/STLExtras.h"
25227825Stheraven#include "llvm/ADT/SmallVector.h"
26246487Stheraven#include "llvm/ADT/TinyPtrVector.h"
27227825Stheraven#include "llvm/ADT/iterator_range.h"
28249998Sdim
29227825Stheravennamespace llvm {
30227825Stheraven
31227825Stheraven// Forward declarations.
32227825Stheravenclass raw_ostream;
33227825Stheravenclass Value;
34227825Stheravenclass VPDef;
35227825Stheravenclass VPSlotTracker;
36227825Stheravenclass VPUser;
37227825Stheravenclass VPRecipeBase;
38227825Stheravenclass VPWidenMemoryInstructionRecipe;
39227825Stheraven
40227825Stheraven// This is the base class of the VPlan Def/Use graph, used for modeling the data
41227825Stheraven// flow into, within and out of the VPlan. VPValues can stand for live-ins
42227825Stheraven// coming from the input IR, instructions which VPlan will generate if executed
43227825Stheraven// and live-outs which the VPlan will need to fix accordingly.
44227825Stheravenclass VPValue {
45227825Stheraven  friend class VPBuilder;
46227825Stheraven  friend class VPDef;
47227825Stheraven  friend class VPInstruction;
48227825Stheraven  friend struct VPlanTransforms;
49227825Stheraven  friend class VPBasicBlock;
50227825Stheraven  friend class VPInterleavedAccessInfo;
51227825Stheraven  friend class VPSlotTracker;
52227825Stheraven  friend class VPRecipeBase;
53227825Stheraven  friend class VPWidenMemoryInstructionRecipe;
54227825Stheraven
55227825Stheraven  const unsigned char SubclassID; ///< Subclass identifier (for isa/dyn_cast).
56227825Stheraven
57227825Stheraven  SmallVector<VPUser *, 1> Users;
58227825Stheraven
59227825Stheravenprotected:
60227825Stheraven  // Hold the underlying Value, if any, attached to this VPValue.
61227825Stheraven  Value *UnderlyingVal;
62227825Stheraven
63227825Stheraven  /// Pointer to the VPDef that defines this VPValue. If it is nullptr, the
64227825Stheraven  /// VPValue is not defined by any recipe modeled in VPlan.
65227825Stheraven  VPDef *Def;
66227825Stheraven
67227825Stheraven  VPValue(const unsigned char SC, Value *UV = nullptr, VPDef *Def = nullptr);
68227825Stheraven
69227825Stheraven  // DESIGN PRINCIPLE: Access to the underlying IR must be strictly limited to
70227825Stheraven  // the front-end and back-end of VPlan so that the middle-end is as
71227825Stheraven  // independent as possible of the underlying IR. We grant access to the
72227825Stheraven  // underlying IR using friendship. In that way, we should be able to use VPlan
73227825Stheraven  // for multiple underlying IRs (Polly?) by providing a new VPlan front-end,
74227825Stheraven  // back-end and analysis information for the new IR.
75227825Stheraven
76227825Stheraven  // Set \p Val as the underlying Value of this VPValue.
77227825Stheraven  void setUnderlyingValue(Value *Val) {
78227825Stheraven    assert(!UnderlyingVal && "Underlying Value is already set.");
79227825Stheraven    UnderlyingVal = Val;
80227825Stheraven  }
81227825Stheraven
82227825Stheravenpublic:
83227825Stheraven  /// Return the underlying Value attached to this VPValue.
84227825Stheraven  Value *getUnderlyingValue() { return UnderlyingVal; }
85227825Stheraven  const Value *getUnderlyingValue() const { return UnderlyingVal; }
86227825Stheraven
87227825Stheraven  /// An enumeration for keeping track of the concrete subclass of VPValue that
88227825Stheraven  /// are actually instantiated.
89227825Stheraven  enum {
90227825Stheraven    VPValueSC, /// A generic VPValue, like live-in values or defined by a recipe
91227825Stheraven               /// that defines multiple values.
92227825Stheraven    VPVRecipeSC /// A VPValue sub-class that is a VPRecipeBase.
93227825Stheraven  };
94227825Stheraven
95227825Stheraven  /// Create a live-in VPValue.
96227825Stheraven  VPValue(Value *UV = nullptr) : VPValue(VPValueSC, UV, nullptr) {}
97227825Stheraven  /// Create a VPValue for a \p Def which is a subclass of VPValue.
98227825Stheraven  VPValue(VPDef *Def, Value *UV = nullptr) : VPValue(VPVRecipeSC, UV, Def) {}
99227825Stheraven  /// Create a VPValue for a \p Def which defines multiple values.
100227825Stheraven  VPValue(Value *UV, VPDef *Def) : VPValue(VPValueSC, UV, Def) {}
101227825Stheraven  VPValue(const VPValue &) = delete;
102227825Stheraven  VPValue &operator=(const VPValue &) = delete;
103227825Stheraven
104227825Stheraven  virtual ~VPValue();
105227825Stheraven
106227825Stheraven  /// \return an ID for the concrete type of this object.
107227825Stheraven  /// This is used to implement the classof checks. This should not be used
108227825Stheraven  /// for any other purpose, as the values may change as LLVM evolves.
109227825Stheraven  unsigned getVPValueID() const { return SubclassID; }
110227825Stheraven
111227825Stheraven#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
112227825Stheraven  void printAsOperand(raw_ostream &OS, VPSlotTracker &Tracker) const;
113249998Sdim  void print(raw_ostream &OS, VPSlotTracker &Tracker) const;
114227825Stheraven
115227825Stheraven  /// Dump the value to stderr (for debugging).
116227825Stheraven  void dump() const;
117227825Stheraven#endif
118227825Stheraven
119227825Stheraven  unsigned getNumUsers() const { return Users.size(); }
120227825Stheraven  void addUser(VPUser &User) { Users.push_back(&User); }
121262801Sdim
122262801Sdim  /// Remove a single \p User from the list of users.
123232950Stheraven  void removeUser(VPUser &User) {
124227825Stheraven    // The same user can be added multiple times, e.g. because the same VPValue
125262801Sdim    // is used twice by the same VPUser. Remove a single one.
126262801Sdim    auto *I = find(Users, &User);
127227825Stheraven    if (I != Users.end())
128227825Stheraven      Users.erase(I);
129227825Stheraven  }
130262801Sdim
131262801Sdim  typedef SmallVectorImpl<VPUser *>::iterator user_iterator;
132227825Stheraven  typedef SmallVectorImpl<VPUser *>::const_iterator const_user_iterator;
133262801Sdim  typedef iterator_range<user_iterator> user_range;
134227825Stheraven  typedef iterator_range<const_user_iterator> const_user_range;
135227825Stheraven
136227825Stheraven  user_iterator user_begin() { return Users.begin(); }
137227825Stheraven  const_user_iterator user_begin() const { return Users.begin(); }
138227825Stheraven  user_iterator user_end() { return Users.end(); }
139227825Stheraven  const_user_iterator user_end() const { return Users.end(); }
140227825Stheraven  user_range users() { return user_range(user_begin(), user_end()); }
141227825Stheraven  const_user_range users() const {
142232950Stheraven    return const_user_range(user_begin(), user_end());
143227825Stheraven  }
144232950Stheraven
145253159Stheraven  /// Returns true if the value has more than one unique user.
146227825Stheraven  bool hasMoreThanOneUniqueUser() {
147241903Sdim    if (getNumUsers() == 0)
148227825Stheraven      return false;
149241903Sdim
150241903Sdim    // Check if all users match the first user.
151241903Sdim    auto Current = std::next(user_begin());
152227825Stheraven    while (Current != user_end() && *user_begin() == *Current)
153227825Stheraven      Current++;
154227825Stheraven    return Current != user_end();
155227825Stheraven  }
156227825Stheraven
157227825Stheraven  void replaceAllUsesWith(VPValue *New);
158227825Stheraven
159227825Stheraven  /// Go through the uses list for this VPValue and make each use point to \p
160227825Stheraven  /// New if the callback ShouldReplace returns true for the given use specified
161227825Stheraven  /// by a pair of (VPUser, the use index).
162227825Stheraven  void replaceUsesWithIf(
163227825Stheraven      VPValue *New,
164227825Stheraven      llvm::function_ref<bool(VPUser &U, unsigned Idx)> ShouldReplace);
165227825Stheraven
166227825Stheraven  /// Returns the recipe defining this VPValue or nullptr if it is not defined
167227825Stheraven  /// by a recipe, i.e. is a live-in.
168232950Stheraven  VPRecipeBase *getDefiningRecipe();
169227825Stheraven  const VPRecipeBase *getDefiningRecipe() const;
170253159Stheraven
171253159Stheraven  /// Returns true if this VPValue is defined by a recipe.
172227825Stheraven  bool hasDefiningRecipe() const { return getDefiningRecipe(); }
173241903Sdim
174227825Stheraven  /// Returns true if this VPValue is a live-in, i.e. defined outside the VPlan.
175241903Sdim  bool isLiveIn() const { return !hasDefiningRecipe(); }
176241903Sdim
177241903Sdim  /// Returns the underlying IR value, if this VPValue is defined outside the
178227825Stheraven  /// scope of VPlan. Returns nullptr if the VPValue is defined by a VPDef
179227825Stheraven  /// inside a VPlan.
180227825Stheraven  Value *getLiveInIRValue() {
181227825Stheraven    assert(isLiveIn() &&
182227825Stheraven           "VPValue is not a live-in; it is defined by a VPDef inside a VPlan");
183227825Stheraven    return getUnderlyingValue();
184227825Stheraven  }
185227825Stheraven  const Value *getLiveInIRValue() const {
186227825Stheraven    assert(isLiveIn() &&
187227825Stheraven           "VPValue is not a live-in; it is defined by a VPDef inside a VPlan");
188227825Stheraven    return getUnderlyingValue();
189227825Stheraven  }
190232950Stheraven
191227825Stheraven  /// Returns true if the VPValue is defined outside any vector regions, i.e. it
192227825Stheraven  /// is a live-in value.
193227825Stheraven  /// TODO: Also handle recipes defined in pre-header blocks.
194227825Stheraven  bool isDefinedOutsideVectorRegions() const { return !hasDefiningRecipe(); }
195227825Stheraven};
196227825Stheraven
197227825Stheraventypedef DenseMap<Value *, VPValue *> Value2VPValueTy;
198227825Stheraventypedef DenseMap<VPValue *, Value *> VPValue2ValueTy;
199227825Stheraven
200227825Stheravenraw_ostream &operator<<(raw_ostream &OS, const VPValue &V);
201227825Stheraven
202227825Stheraven/// This class augments VPValue with operands which provide the inverse def-use
203227825Stheraven/// edges from VPValue's users to their defs.
204227825Stheravenclass VPUser {
205227825Stheravenpublic:
206227825Stheraven  /// Subclass identifier (for isa/dyn_cast).
207227825Stheraven  enum class VPUserID {
208227825Stheraven    Recipe,
209227825Stheraven    LiveOut,
210227825Stheraven  };
211227825Stheraven
212227825Stheravenprivate:
213227825Stheraven  SmallVector<VPValue *, 2> Operands;
214227825Stheraven
215227825Stheraven  VPUserID ID;
216227825Stheraven
217227825Stheravenprotected:
218227825Stheraven#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
219262801Sdim  /// Print the operands to \p O.
220227825Stheraven  void printOperands(raw_ostream &O, VPSlotTracker &SlotTracker) const;
221262801Sdim#endif
222262801Sdim
223262801Sdim  VPUser(ArrayRef<VPValue *> Operands, VPUserID ID) : ID(ID) {
224262801Sdim    for (VPValue *Operand : Operands)
225262801Sdim      addOperand(Operand);
226262801Sdim  }
227262801Sdim
228262801Sdim  VPUser(std::initializer_list<VPValue *> Operands, VPUserID ID)
229262801Sdim      : VPUser(ArrayRef<VPValue *>(Operands), ID) {}
230262801Sdim
231262801Sdim  template <typename IterT>
232262801Sdim  VPUser(iterator_range<IterT> Operands, VPUserID ID) : ID(ID) {
233262801Sdim    for (VPValue *Operand : Operands)
234262801Sdim      addOperand(Operand);
235262801Sdim  }
236227825Stheraven
237227825Stheravenpublic:
238227825Stheraven  VPUser() = delete;
239227825Stheraven  VPUser(const VPUser &) = delete;
240227825Stheraven  VPUser &operator=(const VPUser &) = delete;
241227825Stheraven  virtual ~VPUser() {
242227825Stheraven    for (VPValue *Op : operands())
243262801Sdim      Op->removeUser(*this);
244262801Sdim  }
245262801Sdim
246262801Sdim  VPUserID getVPUserID() const { return ID; }
247262801Sdim
248232950Stheraven  void addOperand(VPValue *Operand) {
249227825Stheraven    Operands.push_back(Operand);
250262801Sdim    Operand->addUser(*this);
251262801Sdim  }
252262801Sdim
253262801Sdim  unsigned getNumOperands() const { return Operands.size(); }
254262801Sdim  inline VPValue *getOperand(unsigned N) const {
255227825Stheraven    assert(N < Operands.size() && "Operand index out of bounds");
256227825Stheraven    return Operands[N];
257227825Stheraven  }
258262801Sdim
259262801Sdim  void setOperand(unsigned I, VPValue *New) {
260262801Sdim    Operands[I]->removeUser(*this);
261262801Sdim    Operands[I] = New;
262262801Sdim    New->addUser(*this);
263227825Stheraven  }
264227825Stheraven
265227825Stheraven  void removeLastOperand() {
266227825Stheraven    VPValue *Op = Operands.pop_back_val();
267227825Stheraven    Op->removeUser(*this);
268227825Stheraven  }
269227825Stheraven
270232950Stheraven  typedef SmallVectorImpl<VPValue *>::iterator operand_iterator;
271227825Stheraven  typedef SmallVectorImpl<VPValue *>::const_iterator const_operand_iterator;
272227825Stheraven  typedef iterator_range<operand_iterator> operand_range;
273227825Stheraven  typedef iterator_range<const_operand_iterator> const_operand_range;
274227825Stheraven
275227825Stheraven  operand_iterator op_begin() { return Operands.begin(); }
276227825Stheraven  const_operand_iterator op_begin() const { return Operands.begin(); }
277227825Stheraven  operand_iterator op_end() { return Operands.end(); }
278227825Stheraven  const_operand_iterator op_end() const { return Operands.end(); }
279227825Stheraven  operand_range operands() { return operand_range(op_begin(), op_end()); }
280227825Stheraven  const_operand_range operands() const {
281227825Stheraven    return const_operand_range(op_begin(), op_end());
282227825Stheraven  }
283227825Stheraven
284227825Stheraven  /// Returns true if the VPUser uses scalars of operand \p Op. Conservatively
285227825Stheraven  /// returns if only first (scalar) lane is used, as default.
286227825Stheraven  virtual bool usesScalars(const VPValue *Op) const {
287227825Stheraven    assert(is_contained(operands(), Op) &&
288227825Stheraven           "Op must be an operand of the recipe");
289227825Stheraven    return onlyFirstLaneUsed(Op);
290227825Stheraven  }
291262801Sdim
292227825Stheraven  /// Returns true if the VPUser only uses the first lane of operand \p Op.
293262801Sdim  /// Conservatively returns false.
294262801Sdim  virtual bool onlyFirstLaneUsed(const VPValue *Op) const {
295262801Sdim    assert(is_contained(operands(), Op) &&
296262801Sdim           "Op must be an operand of the recipe");
297262801Sdim    return false;
298262801Sdim  }
299262801Sdim
300262801Sdim  /// Returns true if the VPUser only uses the first part of operand \p Op.
301262801Sdim  /// Conservatively returns false.
302262801Sdim  virtual bool onlyFirstPartUsed(const VPValue *Op) const {
303262801Sdim    assert(is_contained(operands(), Op) &&
304262801Sdim           "Op must be an operand of the recipe");
305262801Sdim    return false;
306262801Sdim  }
307262801Sdim};
308262801Sdim
309262801Sdim/// This class augments a recipe with a set of VPValues defined by the recipe.
310262801Sdim/// It allows recipes to define zero, one or multiple VPValues. A VPDef owns
311262801Sdim/// the VPValues it defines and is responsible for deleting its defined values.
312262801Sdim/// Single-value VPDefs that also inherit from VPValue must make sure to inherit
313262801Sdim/// from VPDef before VPValue.
314262801Sdimclass VPDef {
315262801Sdim  friend class VPValue;
316262801Sdim
317262801Sdim  /// Subclass identifier (for isa/dyn_cast).
318262801Sdim  const unsigned char SubclassID;
319227825Stheraven
320227825Stheraven  /// The VPValues defined by this VPDef.
321227825Stheraven  TinyPtrVector<VPValue *> DefinedValues;
322227825Stheraven
323227825Stheraven  /// Add \p V as a defined value by this VPDef.
324227825Stheraven  void addDefinedValue(VPValue *V) {
325227825Stheraven    assert(V->Def == this &&
326227825Stheraven           "can only add VPValue already linked with this VPDef");
327227825Stheraven    DefinedValues.push_back(V);
328227825Stheraven  }
329249998Sdim
330227825Stheraven  /// Remove \p V from the values defined by this VPDef. \p V must be a defined
331227825Stheraven  /// value of this VPDef.
332227825Stheraven  void removeDefinedValue(VPValue *V) {
333227825Stheraven    assert(V->Def == this && "can only remove VPValue linked with this VPDef");
334227825Stheraven    assert(is_contained(DefinedValues, V) &&
335227825Stheraven           "VPValue to remove must be in DefinedValues");
336227825Stheraven    llvm::erase(DefinedValues, V);
337227825Stheraven    V->Def = nullptr;
338227825Stheraven  }
339227825Stheraven
340227825Stheravenpublic:
341227825Stheraven  /// An enumeration for keeping track of the concrete subclass of VPRecipeBase
342227825Stheraven  /// that is actually instantiated. Values of this enumeration are kept in the
343227825Stheraven  /// SubclassID field of the VPRecipeBase objects. They are used for concrete
344227825Stheraven  /// type identification.
345227825Stheraven  using VPRecipeTy = enum {
346227825Stheraven    VPBranchOnMaskSC,
347227825Stheraven    VPDerivedIVSC,
348227825Stheraven    VPExpandSCEVSC,
349227825Stheraven    VPInstructionSC,
350227825Stheraven    VPInterleaveSC,
351227825Stheraven    VPReductionSC,
352227825Stheraven    VPReplicateSC,
353227825Stheraven    VPScalarIVStepsSC,
354227825Stheraven    VPVectorPointerSC,
355227825Stheraven    VPWidenCallSC,
356227825Stheraven    VPWidenCanonicalIVSC,
357227825Stheraven    VPWidenCastSC,
358227825Stheraven    VPWidenGEPSC,
359227825Stheraven    VPWidenMemoryInstructionSC,
360227825Stheraven    VPWidenSC,
361227825Stheraven    VPWidenSelectSC,
362227825Stheraven    // START: Phi-like recipes. Need to be kept together.
363227825Stheraven    VPBlendSC,
364227825Stheraven    VPPredInstPHISC,
365227825Stheraven    // START: SubclassID for recipes that inherit VPHeaderPHIRecipe.
366227825Stheraven    // VPHeaderPHIRecipe need to be kept together.
367227825Stheraven    VPCanonicalIVPHISC,
368227825Stheraven    VPActiveLaneMaskPHISC,
369227825Stheraven    VPFirstOrderRecurrencePHISC,
370227825Stheraven    VPWidenPHISC,
371227825Stheraven    VPWidenIntOrFpInductionSC,
372227825Stheraven    VPWidenPointerInductionSC,
373227825Stheraven    VPReductionPHISC,
374227825Stheraven    // END: SubclassID for recipes that inherit VPHeaderPHIRecipe
375227825Stheraven    // END: Phi-like recipes
376227825Stheraven    VPFirstPHISC = VPBlendSC,
377227825Stheraven    VPFirstHeaderPHISC = VPCanonicalIVPHISC,
378227825Stheraven    VPLastHeaderPHISC = VPReductionPHISC,
379227825Stheraven    VPLastPHISC = VPReductionPHISC,
380227825Stheraven  };
381262801Sdim
382227825Stheraven  VPDef(const unsigned char SC) : SubclassID(SC) {}
383227825Stheraven
384227825Stheraven  virtual ~VPDef() {
385227825Stheraven    for (VPValue *D : make_early_inc_range(DefinedValues)) {
386227825Stheraven      assert(D->Def == this &&
387227825Stheraven             "all defined VPValues should point to the containing VPDef");
388227825Stheraven      assert(D->getNumUsers() == 0 &&
389227825Stheraven             "all defined VPValues should have no more users");
390227825Stheraven      D->Def = nullptr;
391227825Stheraven      delete D;
392227825Stheraven    }
393227825Stheraven  }
394227825Stheraven
395232950Stheraven  /// Returns the only VPValue defined by the VPDef. Can only be called for
396227825Stheraven  /// VPDefs with a single defined value.
397227825Stheraven  VPValue *getVPSingleValue() {
398227825Stheraven    assert(DefinedValues.size() == 1 && "must have exactly one defined value");
399227825Stheraven    assert(DefinedValues[0] && "defined value must be non-null");
400227825Stheraven    return DefinedValues[0];
401227825Stheraven  }
402227825Stheraven  const VPValue *getVPSingleValue() const {
403232950Stheraven    assert(DefinedValues.size() == 1 && "must have exactly one defined value");
404227825Stheraven    assert(DefinedValues[0] && "defined value must be non-null");
405227825Stheraven    return DefinedValues[0];
406227825Stheraven  }
407227825Stheraven
408227825Stheraven  /// Returns the VPValue with index \p I defined by the VPDef.
409227825Stheraven  VPValue *getVPValue(unsigned I) {
410227825Stheraven    assert(DefinedValues[I] && "defined value must be non-null");
411227825Stheraven    return DefinedValues[I];
412227825Stheraven  }
413227825Stheraven  const VPValue *getVPValue(unsigned I) const {
414227825Stheraven    assert(DefinedValues[I] && "defined value must be non-null");
415227825Stheraven    return DefinedValues[I];
416227825Stheraven  }
417227825Stheraven
418227825Stheraven  /// Returns an ArrayRef of the values defined by the VPDef.
419227825Stheraven  ArrayRef<VPValue *> definedValues() { return DefinedValues; }
420227825Stheraven  /// Returns an ArrayRef of the values defined by the VPDef.
421227825Stheraven  ArrayRef<VPValue *> definedValues() const { return DefinedValues; }
422227825Stheraven
423227825Stheraven  /// Returns the number of values defined by the VPDef.
424227825Stheraven  unsigned getNumDefinedValues() const { return DefinedValues.size(); }
425227825Stheraven
426227825Stheraven  /// \return an ID for the concrete type of this object.
427227825Stheraven  /// This is used to implement the classof checks. This should not be used
428227825Stheraven  /// for any other purpose, as the values may change as LLVM evolves.
429227825Stheraven  unsigned getVPDefID() const { return SubclassID; }
430227825Stheraven
431227825Stheraven#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
432232950Stheraven  /// Dump the VPDef to stderr (for debugging).
433227825Stheraven  void dump() const;
434227825Stheraven
435253159Stheraven  /// Each concrete VPDef prints itself.
436253159Stheraven  virtual void print(raw_ostream &O, const Twine &Indent,
437227825Stheraven                     VPSlotTracker &SlotTracker) const = 0;
438241903Sdim#endif
439227825Stheraven};
440241903Sdim
441241903Sdimclass VPlan;
442241903Sdimclass VPBasicBlock;
443227825Stheraven
444227825Stheraven/// This class can be used to assign consecutive numbers to all VPValues in a
445227825Stheraven/// VPlan and allows querying the numbering for printing, similar to the
446227825Stheraven/// ModuleSlotTracker for IR values.
447227825Stheravenclass VPSlotTracker {
448227825Stheraven  DenseMap<const VPValue *, unsigned> Slots;
449227825Stheraven  unsigned NextSlot = 0;
450227825Stheraven
451227825Stheraven  void assignSlot(const VPValue *V);
452227825Stheraven  void assignSlots(const VPlan &Plan);
453227825Stheraven  void assignSlots(const VPBasicBlock *VPBB);
454227825Stheraven
455227825Stheravenpublic:
456227825Stheraven  VPSlotTracker(const VPlan *Plan = nullptr) {
457227825Stheraven    if (Plan)
458227825Stheraven      assignSlots(*Plan);
459232950Stheraven  }
460227825Stheraven
461232950Stheraven  unsigned getSlot(const VPValue *V) const {
462253159Stheraven    auto I = Slots.find(V);
463227825Stheraven    if (I == Slots.end())
464241903Sdim      return -1;
465227825Stheraven    return I->second;
466241903Sdim  }
467241903Sdim};
468241903Sdim
469227825Stheraven} // namespace llvm
470227825Stheraven
471227825Stheraven#endif // LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H
472227825Stheraven