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