My Project
UseDefLists.h
Go to the documentation of this file.
1 //===- UseDefLists.h --------------------------------------------*- C++ -*-===//
2 //
3 // Part of the MLIR 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 
34 template <typename OperandType> class IRObjectWithUseList {
35 public:
37  assert(use_empty() && "Cannot destroy a value that still has uses!");
38  }
39 
41  void dropAllUses() {
42  while (!use_empty())
43  use_begin()->drop();
44  }
45 
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 
62 
63  use_iterator use_begin() const { return use_iterator(firstUse); }
64  use_iterator use_end() const { return use_iterator(nullptr); }
65 
67  use_range getUses() const { return {use_begin(), use_end()}; }
68 
70  bool hasOneUse() const {
71  return firstUse && firstUse->getNextOperandUsingThisValue() == nullptr;
72  }
73 
75  bool use_empty() const { return firstUse == nullptr; }
76 
77  //===--------------------------------------------------------------------===//
78  // Users
79  //===--------------------------------------------------------------------===//
80 
83 
86 
88  user_range getUsers() const { return {user_begin(), user_end()}; }
89 
90 protected:
92 
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 // IRMultiObjectWithUseList
104 //===----------------------------------------------------------------------===//
105 
108 template <typename OperandType>
109 class IRMultiObjectWithUseList : public IRObjectWithUseList<OperandType> {
110 public:
112  using ValueType = typename OperandType::ValueType;
113 
115  void dropAllUses(ValueType value) {
116  assert(this == OperandType::getUseList(value) &&
117  "value not attached to this use list");
118  for (OperandType &use : llvm::make_early_inc_range(getUses(value)))
119  use.drop();
120  }
121  using BaseType::dropAllUses;
122 
126  void replaceAllUsesWith(ValueType oldValue, ValueType newValue) {
127  assert(this == OperandType::getUseList(oldValue) &&
128  "value not attached to this use list");
129  assert((!newValue || this != OperandType::getUseList(newValue)) &&
130  "cannot RAUW a value with itself");
131  for (OperandType &use : llvm::make_early_inc_range(getUses(oldValue)))
132  use.set(newValue);
133  }
134 
135  //===--------------------------------------------------------------------===//
136  // Uses
137  //===--------------------------------------------------------------------===//
138 
141 
143  return filtered_use_iterator(this->getFirstUse(), value);
144  }
147  return {use_begin(value), use_end(value)};
148  }
149  bool hasOneUse(ValueType value) const {
150  return mlir::has_single_element(getUses(value));
151  }
152  bool use_empty(ValueType value) const {
153  return use_begin(value) == use_end(value);
154  }
155  using BaseType::getUses;
156  using BaseType::hasOneUse;
157  using BaseType::use_begin;
158  using BaseType::use_empty;
159  using BaseType::use_end;
160 
161  //===--------------------------------------------------------------------===//
162  // Users
163  //===--------------------------------------------------------------------===//
164 
165  using filtered_user_iterator =
168 
170  return {use_begin(value)};
171  }
172  filtered_user_iterator user_end(ValueType value) const { return {use_end()}; }
174  return {user_begin(value), user_end(value)};
175  }
176  using BaseType::getUsers;
177  using BaseType::user_begin;
178  using BaseType::user_end;
179 };
180 
181 //===----------------------------------------------------------------------===//
182 // IROperand
183 //===----------------------------------------------------------------------===//
184 
190 template <typename DerivedT, typename IRValueTy> class IROperand {
191 public:
192  using ValueType = IRValueTy;
193 
194  IROperand(Operation *owner) : owner(owner) {}
195  IROperand(Operation *owner, ValueType value) : value(value), owner(owner) {
196  insertIntoCurrent();
197  }
198 
200  ValueType get() const { return value; }
201 
203  void set(ValueType newValue) {
204  // It isn't worth optimizing for the case of switching operands on a single
205  // value.
206  removeFromCurrent();
207  value = newValue;
208  insertIntoCurrent();
209  }
210 
212  Operation *getOwner() { return owner; }
213  Operation *getOwner() const { return owner; }
214 
216  void drop() {
217  removeFromCurrent();
218  value = nullptr;
219  nextUse = nullptr;
220  back = nullptr;
221  }
222 
223  ~IROperand() { removeFromCurrent(); }
224 
228  DerivedT *getNextOperandUsingThisValue() { return nextUse; }
229 
232  IROperand(IROperand &&other) : owner(other.owner) {
233  *this = std::move(other);
234  }
236  removeFromCurrent();
237  other.removeFromCurrent();
238  value = other.value;
239  other.value = nullptr;
240  other.back = nullptr;
241  nextUse = nullptr;
242  back = nullptr;
243  insertIntoCurrent();
244  return *this;
245  }
246 
247 private:
250  ValueType value = {};
251 
253  DerivedT *nextUse = nullptr;
254 
256  DerivedT **back = nullptr;
257 
259  Operation *const owner;
260 
262  IROperand(const IROperand &use) = delete;
263  IROperand &operator=(const IROperand &use) = delete;
264 
265  void removeFromCurrent() {
266  if (!back)
267  return;
268  *back = nextUse;
269  if (nextUse)
270  nextUse->back = back;
271  }
272 
273  void insertIntoCurrent() {
274  auto *useList = DerivedT::getUseList(value);
275  back = &useList->firstUse;
276  nextUse = useList->firstUse;
277  if (nextUse)
278  nextUse->back = &nextUse;
279  useList->firstUse = static_cast<DerivedT *>(this);
280  }
281 };
282 
283 //===----------------------------------------------------------------------===//
284 // BlockOperand
285 //===----------------------------------------------------------------------===//
286 
288 class BlockOperand : public IROperand<BlockOperand, Block *> {
289 public:
291 
293  static IRObjectWithUseList<BlockOperand> *getUseList(Block *value);
294 
296  unsigned getOperandNumber();
297 
298 private:
300  unsigned numSuccessorOperands = 0;
301 
303  friend Operation;
304 };
305 
306 //===----------------------------------------------------------------------===//
307 // OpOperand
308 //===----------------------------------------------------------------------===//
309 
310 namespace detail {
312 class OpaqueValue {
313 public:
315  OpaqueValue(Value value);
316  OpaqueValue(std::nullptr_t = nullptr) : impl(nullptr) {}
317  OpaqueValue(const OpaqueValue &) = default;
318  OpaqueValue &operator=(const OpaqueValue &) = default;
319  operator bool() const { return impl; }
320 
322  operator Value() const;
323 
324 private:
325  void *impl;
326 };
327 } // namespace detail
328 
330 class OpOperand : public IROperand<OpOperand, detail::OpaqueValue> {
331 public:
333 
335  static IRObjectWithUseList<OpOperand> *getUseList(Value value);
336 
338  Value get() const;
339 
341  void set(Value value);
342 
344  unsigned getOperandNumber();
345 };
346 
347 //===----------------------------------------------------------------------===//
348 // ValueUseIterator
349 //===----------------------------------------------------------------------===//
350 
351 namespace detail {
355 template <typename DerivedT, typename OperandType>
357  : public llvm::iterator_facade_base<DerivedT, std::forward_iterator_tag,
358  OperandType> {
359 public:
360  template <typename T>
362  : current(other.getOperand()) {}
363  ValueUseIteratorImpl(OperandType *current = nullptr) : current(current) {}
364 
365  Operation *getUser() const { return current->getOwner(); }
366  OperandType *getOperand() const { return current; }
367 
368  OperandType &operator*() const { return *current; }
369 
370  using llvm::iterator_facade_base<DerivedT, std::forward_iterator_tag,
371  OperandType>::operator++;
373  assert(current && "incrementing past end()!");
374  current = (OperandType *)current->getNextOperandUsingThisValue();
375  return *this;
376  }
377 
378  bool operator==(const ValueUseIteratorImpl &rhs) const {
379  return current == rhs.current;
380  }
381 
382 protected:
383  OperandType *current;
384 };
385 
386 } // end namespace detail
387 
389 template <typename OperandType>
390 class ValueUseIterator
391  : public detail::ValueUseIteratorImpl<ValueUseIterator<OperandType>,
392  OperandType> {
393 public:
395  OperandType>::ValueUseIteratorImpl;
396 };
397 
401 template <typename OperandType>
403  : public detail::ValueUseIteratorImpl<FilteredValueUseIterator<OperandType>,
404  OperandType> {
405 public:
406  using BaseT =
408  OperandType>;
409 
410  FilteredValueUseIterator() = default;
412  : BaseT(it), filterVal(nullptr) {}
413  FilteredValueUseIterator(OperandType *current,
414  typename OperandType::ValueType filterVal)
415  : BaseT(current), filterVal(filterVal) {
416  findNextValid();
417  }
418 
419  using BaseT::operator++;
421  BaseT::operator++();
422  findNextValid();
423  return *this;
424  }
425 
426 private:
427  void findNextValid() {
428  if (!filterVal)
429  return;
430  while (this->current && ((OperandType *)this->current)->get() != filterVal)
431  BaseT::operator++();
432  }
433 
435  typename OperandType::ValueType filterVal;
436 };
437 
438 //===----------------------------------------------------------------------===//
439 // ValueUserIterator
440 //===----------------------------------------------------------------------===//
441 
443 template <typename UseIteratorT, typename OperandType>
444 class ValueUserIterator final
445  : public llvm::mapped_iterator<UseIteratorT,
446  Operation *(*)(OperandType &)> {
447  static Operation *unwrap(OperandType &value) { return value.getOwner(); }
448 
449 public:
450  using pointer = Operation *;
451  using reference = Operation *;
452 
454  ValueUserIterator(UseIteratorT it)
455  : llvm::mapped_iterator<UseIteratorT, Operation *(*)(OperandType &)>(
456  it, &unwrap) {}
457  Operation *operator->() { return **this; }
458 };
459 
460 } // namespace mlir
461 
462 #endif
Definition: InferTypeOpInterface.cpp:20
IROperand(Operation *owner)
Definition: UseDefLists.h:194
filtered_use_iterator use_end(ValueType) const
Definition: UseDefLists.h:145
FilteredValueUseIterator(OperandType *current, typename OperandType::ValueType filterVal)
Definition: UseDefLists.h:413
bool has_single_element(ContainerTy &&c)
Returns true of the given range only contains a single element.
Definition: STLExtras.h:336
Definition: PassRegistry.cpp:413
Definition: Operation.h:27
bool use_empty(ValueType value) const
Definition: UseDefLists.h:152
ValueUserIterator< use_iterator, OperandType > user_iterator
Definition: UseDefLists.h:81
Operation * getUser() const
Definition: UseDefLists.h:365
Block represents an ordered list of Operations.
Definition: Block.h:21
FilteredValueUseIterator< OperandType > & operator++()
Definition: UseDefLists.h:420
use_iterator use_end() const
Definition: UseDefLists.h:64
DerivedT * getNextOperandUsingThisValue()
Definition: UseDefLists.h:228
~IROperand()
Definition: UseDefLists.h:223
An iterator over all of the uses of an IR object.
Definition: UseDefLists.h:25
filtered_user_iterator user_end(ValueType value) const
Definition: UseDefLists.h:172
Operation * getOwner()
Return the owner of this operand.
Definition: UseDefLists.h:212
user_range getUsers() const
Returns a range of all users.
Definition: UseDefLists.h:88
Terminator operations can have Block operands to represent successors.
Definition: UseDefLists.h:288
Definition: UseDefLists.h:356
user_iterator user_begin() const
Definition: UseDefLists.h:84
An iterator over all users of a ValueBase.
Definition: UseDefLists.h:27
ValueUseIterator< OperandType > use_iterator
Definition: UseDefLists.h:60
filtered_user_iterator user_begin(ValueType value) const
Definition: UseDefLists.h:169
void replaceAllUsesWith(typename OperandType::ValueType newValue)
Definition: UseDefLists.h:49
OperandType * getFirstUse() const
Definition: UseDefLists.h:95
FilteredValueUseIterator(const ValueUseIterator< OperandType > &it)
Definition: UseDefLists.h:411
bool hasOneUse(ValueType value) const
Definition: UseDefLists.h:149
void dropAllUses()
Drop all uses of this object from their respective owners.
Definition: UseDefLists.h:41
user_iterator user_end() const
Definition: UseDefLists.h:85
This class represents a single IR object that contains a use list.
Definition: UseDefLists.h:34
use_range getUses() const
Returns a range of all uses, which is useful for iterating over all uses.
Definition: UseDefLists.h:67
void replaceAllUsesWith(ValueType oldValue, ValueType newValue)
Definition: UseDefLists.h:126
OpaqueValue(std::nullptr_t=nullptr)
Definition: UseDefLists.h:316
OperandType * getOperand() const
Definition: UseDefLists.h:366
IRObjectWithUseList()
Definition: UseDefLists.h:91
typename OpOperand ::ValueType ValueType
Definition: UseDefLists.h:112
friend class IROperand
Definition: UseDefLists.h:98
bool operator==(const ValueUseIteratorImpl &rhs) const
Definition: UseDefLists.h:378
IROperand(IROperand &&other)
Definition: UseDefLists.h:232
filtered_use_range getUses(ValueType value) const
Definition: UseDefLists.h:146
filtered_use_iterator use_begin(ValueType value) const
Definition: UseDefLists.h:142
Definition: Value.h:38
~IRObjectWithUseList()
Definition: UseDefLists.h:36
filtered_user_range getUsers(ValueType value) const
Definition: UseDefLists.h:173
void dropAllUses(ValueType value)
Drop all uses of value from their respective owners.
Definition: UseDefLists.h:115
OperandType * current
Definition: UseDefLists.h:383
ValueUseIteratorImpl & operator++()
Definition: UseDefLists.h:372
Operation * operator->()
Definition: UseDefLists.h:457
Definition: LLVM.h:50
use_iterator use_begin() const
Definition: UseDefLists.h:63
ValueUseIteratorImpl(OperandType *current=nullptr)
Definition: UseDefLists.h:363
IROperand(Operation *owner, ValueType value)
Definition: UseDefLists.h:195
Definition: UseDefLists.h:109
A reference to a value, suitable for use as an operand of an operation.
Definition: UseDefLists.h:330
ValueUseIteratorImpl(const ValueUseIteratorImpl< T, OperandType > &other)
Definition: UseDefLists.h:361
IROperand & operator=(IROperand &&other)
Definition: UseDefLists.h:235
Definition: UseDefLists.h:26
Definition: UseDefLists.h:190
ValueUserIterator(UseIteratorT it)
Initializes the result type iterator to the specified result iterator.
Definition: UseDefLists.h:454
This class provides an opaque type erased wrapper around a Value.
Definition: UseDefLists.h:312
Operation * getOwner() const
Definition: UseDefLists.h:213
bool hasOneUse() const
Returns true if this value has exactly one use.
Definition: UseDefLists.h:70
bool use_empty() const
Returns true if this value has no uses.
Definition: UseDefLists.h:75
OperandType & operator*() const
Definition: UseDefLists.h:368
void drop()
Remove this use of the operand.
Definition: UseDefLists.h:216