• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- UseDefLists.h --------------------------------------------*- C++ -*-===//
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 // This file defines generic use/def list machinery and manipulation utilities.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef MLIR_IR_USEDEFLISTS_H
14 #define MLIR_IR_USEDEFLISTS_H
15 
16 #include "mlir/IR/Location.h"
17 #include "llvm/ADT/PointerIntPair.h"
18 #include "llvm/ADT/iterator_range.h"
19 
20 namespace mlir {
21 
22 class Block;
23 class Operation;
24 class Value;
25 template <typename OperandType> class ValueUseIterator;
26 template <typename OperandType> class FilteredValueUseIterator;
27 template <typename UseIteratorT, typename OperandType> class ValueUserIterator;
28 
29 //===----------------------------------------------------------------------===//
30 // IRObjectWithUseList
31 //===----------------------------------------------------------------------===//
32 
33 /// This class represents a single IR object that contains a use list.
34 template <typename OperandType> class IRObjectWithUseList {
35 public:
~IRObjectWithUseList()36   ~IRObjectWithUseList() {
37     assert(use_empty() && "Cannot destroy a value that still has uses!");
38   }
39 
40   /// Drop all uses of this object from their respective owners.
dropAllUses()41   void dropAllUses() {
42     while (!use_empty())
43       use_begin()->drop();
44   }
45 
46   /// Replace all uses of 'this' value with the new value, updating anything in
47   /// the IR that uses 'this' to use the other value instead.  When this returns
48   /// there are zero uses of 'this'.
replaceAllUsesWith(typename OperandType::ValueType newValue)49   void replaceAllUsesWith(typename OperandType::ValueType newValue) {
50     assert((!newValue || this != OperandType::getUseList(newValue)) &&
51            "cannot RAUW a value with itself");
52     while (!use_empty())
53       use_begin()->set(newValue);
54   }
55 
56   //===--------------------------------------------------------------------===//
57   // Uses
58   //===--------------------------------------------------------------------===//
59 
60   using use_iterator = ValueUseIterator<OperandType>;
61   using use_range = iterator_range<use_iterator>;
62 
use_begin()63   use_iterator use_begin() const { return use_iterator(firstUse); }
use_end()64   use_iterator use_end() const { return use_iterator(nullptr); }
65 
66   /// Returns a range of all uses, which is useful for iterating over all uses.
getUses()67   use_range getUses() const { return {use_begin(), use_end()}; }
68 
69   /// Returns true if this value has exactly one use.
hasOneUse()70   bool hasOneUse() const {
71     return firstUse && firstUse->getNextOperandUsingThisValue() == nullptr;
72   }
73 
74   /// Returns true if this value has no uses.
use_empty()75   bool use_empty() const { return firstUse == nullptr; }
76 
77   //===--------------------------------------------------------------------===//
78   // Users
79   //===--------------------------------------------------------------------===//
80 
81   using user_iterator = ValueUserIterator<use_iterator, OperandType>;
82   using user_range = iterator_range<user_iterator>;
83 
user_begin()84   user_iterator user_begin() const { return user_iterator(use_begin()); }
user_end()85   user_iterator user_end() const { return user_iterator(use_end()); }
86 
87   /// Returns a range of all users.
getUsers()88   user_range getUsers() const { return {user_begin(), user_end()}; }
89 
90 protected:
IRObjectWithUseList()91   IRObjectWithUseList() {}
92 
93   /// Return the first operand that is using this value, for use by custom
94   /// use/def iterators.
getFirstUse()95   OperandType *getFirstUse() const { return firstUse; }
96 
97 private:
98   template <typename DerivedT, typename IRValueTy> friend class IROperand;
99   OperandType *firstUse = nullptr;
100 };
101 
102 //===----------------------------------------------------------------------===//
103 // IROperand
104 //===----------------------------------------------------------------------===//
105 
106 /// A reference to a value, suitable for use as an operand of an operation.
107 /// IRValueTy is the root type to use for values this tracks. Derived operand
108 /// types are expected to provide the following:
109 ///  * static IRObjectWithUseList *getUseList(IRValueTy value);
110 ///    - Provide the use list that is attached to the given value.
111 template <typename DerivedT, typename IRValueTy> class IROperand {
112 public:
113   using ValueType = IRValueTy;
114 
IROperand(Operation * owner)115   IROperand(Operation *owner) : owner(owner) {}
IROperand(Operation * owner,ValueType value)116   IROperand(Operation *owner, ValueType value) : value(value), owner(owner) {
117     insertIntoCurrent();
118   }
119 
120   /// Return the current value being used by this operand.
get()121   ValueType get() const { return value; }
122 
123   /// Set the current value being used by this operand.
set(ValueType newValue)124   void set(ValueType newValue) {
125     // It isn't worth optimizing for the case of switching operands on a single
126     // value.
127     removeFromCurrent();
128     value = newValue;
129     insertIntoCurrent();
130   }
131 
132   /// Returns true if this operand contains the given value.
is(ValueType other)133   bool is(ValueType other) const { return value == other; }
134 
135   /// Return the owner of this operand.
getOwner()136   Operation *getOwner() { return owner; }
getOwner()137   Operation *getOwner() const { return owner; }
138 
139   /// \brief Remove this use of the operand.
drop()140   void drop() {
141     removeFromCurrent();
142     value = nullptr;
143     nextUse = nullptr;
144     back = nullptr;
145   }
146 
~IROperand()147   ~IROperand() { removeFromCurrent(); }
148 
149   /// Return the next operand on the use-list of the value we are referring to.
150   /// This should generally only be used by the internal implementation details
151   /// of the SSA machinery.
getNextOperandUsingThisValue()152   DerivedT *getNextOperandUsingThisValue() { return nextUse; }
153 
154   /// We support a move constructor so IROperand's can be in vectors, but this
155   /// shouldn't be used by general clients.
IROperand(IROperand && other)156   IROperand(IROperand &&other) : owner(other.owner) {
157     *this = std::move(other);
158   }
159   IROperand &operator=(IROperand &&other) {
160     removeFromCurrent();
161     other.removeFromCurrent();
162     value = other.value;
163     other.value = nullptr;
164     other.back = nullptr;
165     nextUse = nullptr;
166     back = nullptr;
167     if (value)
168       insertIntoCurrent();
169     return *this;
170   }
171 
172 private:
173   /// The value used as this operand. This can be null when in a 'dropAllUses'
174   /// state.
175   ValueType value = {};
176 
177   /// The next operand in the use-chain.
178   DerivedT *nextUse = nullptr;
179 
180   /// This points to the previous link in the use-chain.
181   DerivedT **back = nullptr;
182 
183   /// The operation owner of this operand.
184   Operation *const owner;
185 
186   /// Operands are not copyable or assignable.
187   IROperand(const IROperand &use) = delete;
188   IROperand &operator=(const IROperand &use) = delete;
189 
removeFromCurrent()190   void removeFromCurrent() {
191     if (!back)
192       return;
193     *back = nextUse;
194     if (nextUse)
195       nextUse->back = back;
196   }
197 
insertIntoCurrent()198   void insertIntoCurrent() {
199     auto *useList = DerivedT::getUseList(value);
200     back = &useList->firstUse;
201     nextUse = useList->firstUse;
202     if (nextUse)
203       nextUse->back = &nextUse;
204     useList->firstUse = static_cast<DerivedT *>(this);
205   }
206 };
207 
208 //===----------------------------------------------------------------------===//
209 // BlockOperand
210 //===----------------------------------------------------------------------===//
211 
212 /// Terminator operations can have Block operands to represent successors.
213 class BlockOperand : public IROperand<BlockOperand, Block *> {
214 public:
215   using IROperand<BlockOperand, Block *>::IROperand;
216 
217   /// Provide the use list that is attached to the given block.
218   static IRObjectWithUseList<BlockOperand> *getUseList(Block *value);
219 
220   /// Return which operand this is in the operand list of the User.
221   unsigned getOperandNumber();
222 };
223 
224 //===----------------------------------------------------------------------===//
225 // OpOperand
226 //===----------------------------------------------------------------------===//
227 
228 namespace detail {
229 /// This class provides an opaque type erased wrapper around a `Value`.
230 class OpaqueValue {
231 public:
232   /// Implicit conversion from 'Value'.
233   OpaqueValue(Value value);
impl(nullptr)234   OpaqueValue(std::nullptr_t = nullptr) : impl(nullptr) {}
235   OpaqueValue(const OpaqueValue &) = default;
236   OpaqueValue &operator=(const OpaqueValue &) = default;
237   bool operator==(const OpaqueValue &other) const { return impl == other.impl; }
238   operator bool() const { return impl; }
239 
240   /// Implicit conversion back to 'Value'.
241   operator Value() const;
242 
243 private:
244   void *impl;
245 };
246 } // namespace detail
247 
248 /// This class represents an operand of an operation. Instances of this class
249 /// contain a reference to a specific `Value`.
250 class OpOperand : public IROperand<OpOperand, detail::OpaqueValue> {
251 public:
252   /// Provide the use list that is attached to the given value.
253   static IRObjectWithUseList<OpOperand> *getUseList(Value value);
254 
255   /// Return the current value being used by this operand.
256   Value get() const;
257 
258   /// Set the operand to the given value.
259   void set(Value value);
260 
261   /// Return which operand this is in the operand list of the User.
262   unsigned getOperandNumber();
263 
264 private:
265   /// Keep the constructor private and accessible to the OperandStorage class
266   /// only to avoid hard-to-debug typo/programming mistakes.
267   friend class OperandStorage;
268   using IROperand<OpOperand, detail::OpaqueValue>::IROperand;
269 };
270 
271 //===----------------------------------------------------------------------===//
272 // ValueUseIterator
273 //===----------------------------------------------------------------------===//
274 
275 /// An iterator class that allows for iterating over the uses of an IR operand
276 /// type.
277 template <typename OperandType>
278 class ValueUseIterator
279     : public llvm::iterator_facade_base<ValueUseIterator<OperandType>,
280                                         std::forward_iterator_tag,
281                                         OperandType> {
282 public:
current(current)283   ValueUseIterator(OperandType *current = nullptr) : current(current) {}
284 
285   /// Returns the user that owns this use.
getUser()286   Operation *getUser() const { return current->getOwner(); }
287 
288   /// Returns the current operands.
getOperand()289   OperandType *getOperand() const { return current; }
290   OperandType &operator*() const { return *current; }
291 
292   using llvm::iterator_facade_base<ValueUseIterator<OperandType>,
293                                    std::forward_iterator_tag,
294                                    OperandType>::operator++;
295   ValueUseIterator &operator++() {
296     assert(current && "incrementing past end()!");
297     current = (OperandType *)current->getNextOperandUsingThisValue();
298     return *this;
299   }
300 
301   bool operator==(const ValueUseIterator &rhs) const {
302     return current == rhs.current;
303   }
304 
305 protected:
306   OperandType *current;
307 };
308 
309 //===----------------------------------------------------------------------===//
310 // ValueUserIterator
311 //===----------------------------------------------------------------------===//
312 
313 /// An iterator over the users of an IRObject. This is a wrapper iterator around
314 /// a specific use iterator.
315 template <typename UseIteratorT, typename OperandType>
316 class ValueUserIterator final
317     : public llvm::mapped_iterator<UseIteratorT,
318                                    Operation *(*)(OperandType &)> {
unwrap(OperandType & value)319   static Operation *unwrap(OperandType &value) { return value.getOwner(); }
320 
321 public:
322   using pointer = Operation *;
323   using reference = Operation *;
324 
325   /// Initializes the user iterator to the specified use iterator.
ValueUserIterator(UseIteratorT it)326   ValueUserIterator(UseIteratorT it)
327       : llvm::mapped_iterator<UseIteratorT, Operation *(*)(OperandType &)>(
328             it, &unwrap) {}
329   Operation *operator->() { return **this; }
330 };
331 
332 } // namespace mlir
333 
334 #endif
335