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