MLIR  17.0.0git
ValueRange.h
Go to the documentation of this file.
1 //===- ValueRange.h - Indexed Value-Iterators Range Classes -----*- 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 the ValueRange related classes.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef MLIR_IR_VALUERANGE_H
14 #define MLIR_IR_VALUERANGE_H
15 
17 #include "mlir/IR/Types.h"
18 #include "mlir/IR/Value.h"
19 #include "llvm/ADT/PointerUnion.h"
20 #include "llvm/ADT/Sequence.h"
21 #include <optional>
22 
23 namespace mlir {
24 class ValueRange;
25 template <typename ValueRangeT>
26 class ValueTypeRange;
27 class TypeRangeRange;
28 template <typename ValueIteratorT>
29 class ValueTypeIterator;
30 class OperandRangeRange;
31 class MutableOperandRangeRange;
32 
33 //===----------------------------------------------------------------------===//
34 // Operation Value-Iterators
35 //===----------------------------------------------------------------------===//
36 
37 //===----------------------------------------------------------------------===//
38 // OperandRange
39 
40 /// This class implements the operand iterators for the Operation class.
42  OperandRange, OpOperand *, Value, Value, Value> {
43 public:
44  using RangeBaseT::RangeBaseT;
45 
46  /// Returns the types of the values within this range.
49  type_range getTypes() const;
50  type_range getType() const;
51 
52  /// Return the operand index of the first element of this range. The range
53  /// must not be empty.
54  unsigned getBeginOperandIndex() const;
55 
56  /// Split this range into a set of contiguous subranges using the given
57  /// elements attribute, which contains the sizes of the sub ranges.
58  OperandRangeRange split(DenseI32ArrayAttr segmentSizes) const;
59 
60 private:
61  /// See `llvm::detail::indexed_accessor_range_base` for details.
62  static OpOperand *offset_base(OpOperand *object, ptrdiff_t index) {
63  return object + index;
64  }
65  /// See `llvm::detail::indexed_accessor_range_base` for details.
66  static Value dereference_iterator(OpOperand *object, ptrdiff_t index) {
67  return object[index].get();
68  }
69 
70  /// Allow access to `offset_base` and `dereference_iterator`.
71  friend RangeBaseT;
72 };
73 
74 //===----------------------------------------------------------------------===//
75 // OperandRangeRange
76 
77 /// This class represents a contiguous range of operand ranges, e.g. from a
78 /// VariadicOfVariadic operand group.
79 class OperandRangeRange final
80  : public llvm::indexed_accessor_range<
81  OperandRangeRange, std::pair<OpOperand *, Attribute>, OperandRange,
82  OperandRange, OperandRange> {
83  using OwnerT = std::pair<OpOperand *, Attribute>;
84  using RangeBaseT =
85  llvm::indexed_accessor_range<OperandRangeRange, OwnerT, OperandRange,
87 
88 public:
89  using RangeBaseT::RangeBaseT;
90 
91  /// Returns the range of types of the values within this range.
92  TypeRangeRange getTypes() const;
93  TypeRangeRange getType() const;
94 
95  /// Construct a range given a parent set of operands, and an I32 elements
96  /// attribute containing the sizes of the sub ranges.
97  OperandRangeRange(OperandRange operands, Attribute operandSegments);
98 
99  /// Flatten all of the sub ranges into a single contiguous operand range.
100  OperandRange join() const;
101 
102 private:
103  /// See `llvm::indexed_accessor_range` for details.
104  static OperandRange dereference(const OwnerT &object, ptrdiff_t index);
105 
106  /// Allow access to `dereference_iterator`.
107  friend RangeBaseT;
108 };
109 
110 //===----------------------------------------------------------------------===//
111 // MutableOperandRange
112 
113 /// This class provides a mutable adaptor for a range of operands. It allows for
114 /// setting, inserting, and erasing operands from the given range.
116 public:
117  /// A pair of a named attribute corresponding to an operand segment attribute,
118  /// and the index within that attribute. The attribute should correspond to a
119  /// dense i32 array attr.
120  using OperandSegment = std::pair<unsigned, NamedAttribute>;
121 
122  /// Construct a new mutable range from the given operand, operand start index,
123  /// and range length. `operandSegments` is an optional set of operand segments
124  /// to be updated when mutating the operand list.
125  MutableOperandRange(Operation *owner, unsigned start, unsigned length,
126  ArrayRef<OperandSegment> operandSegments = std::nullopt);
128 
129  /// Slice this range into a sub range, with the additional operand segment.
131  slice(unsigned subStart, unsigned subLen,
132  std::optional<OperandSegment> segment = std::nullopt) const;
133 
134  /// Append the given values to the range.
135  void append(ValueRange values);
136 
137  /// Assign this range to the given values.
138  void assign(ValueRange values);
139 
140  /// Assign the range to the given value.
141  void assign(Value value);
142 
143  /// Erase the operands within the given sub-range.
144  void erase(unsigned subStart, unsigned subLen = 1);
145 
146  /// Clear this range and erase all of the operands.
147  void clear();
148 
149  /// Returns the current size of the range.
150  unsigned size() const { return length; }
151 
152  /// Returns if the current range is empty.
153  bool empty() const { return size() == 0; }
154 
155  /// Allow implicit conversion to an OperandRange.
156  operator OperandRange() const;
157 
158  /// Returns the owning operation.
159  Operation *getOwner() const { return owner; }
160 
161  /// Split this range into a set of contiguous subranges using the given
162  /// elements attribute, which contains the sizes of the sub ranges.
163  MutableOperandRangeRange split(NamedAttribute segmentSizes) const;
164 
165  /// Returns the value at the given index.
166  Value operator[](unsigned index) const {
167  return operator OperandRange()[index];
168  }
169 
170 private:
171  /// Update the length of this range to the one provided.
172  void updateLength(unsigned newLength);
173 
174  /// The owning operation of this range.
175  Operation *owner;
176 
177  /// The start index of the operand range within the owner operand list, and
178  /// the length starting from `start`.
179  unsigned start, length;
180 
181  /// Optional set of operand segments that should be updated when mutating the
182  /// length of this range.
183  SmallVector<OperandSegment, 1> operandSegments;
184 };
185 
186 //===----------------------------------------------------------------------===//
187 // MutableOperandRangeRange
188 
189 /// This class represents a contiguous range of mutable operand ranges, e.g.
190 /// from a VariadicOfVariadic operand group.
192  : public llvm::indexed_accessor_range<
193  MutableOperandRangeRange,
194  std::pair<MutableOperandRange, NamedAttribute>, MutableOperandRange,
195  MutableOperandRange, MutableOperandRange> {
196  using OwnerT = std::pair<MutableOperandRange, NamedAttribute>;
197  using RangeBaseT =
198  llvm::indexed_accessor_range<MutableOperandRangeRange, OwnerT,
201 
202 public:
203  using RangeBaseT::RangeBaseT;
204 
205  /// Construct a range given a parent set of operands, and an I32 tensor
206  /// elements attribute containing the sizes of the sub ranges.
208  NamedAttribute operandSegmentAttr);
209 
210  /// Flatten all of the sub ranges into a single contiguous mutable operand
211  /// range.
212  MutableOperandRange join() const;
213 
214  /// Allow implicit conversion to an OperandRangeRange.
215  operator OperandRangeRange() const;
216 
217 private:
218  /// See `llvm::indexed_accessor_range` for details.
219  static MutableOperandRange dereference(const OwnerT &object, ptrdiff_t index);
220 
221  /// Allow access to `dereference_iterator`.
222  friend RangeBaseT;
223 };
224 
225 //===----------------------------------------------------------------------===//
226 // ResultRange
227 
228 /// This class implements the result iterators for the Operation class.
229 class ResultRange final
231  ResultRange, detail::OpResultImpl *, OpResult, OpResult, OpResult> {
232 public:
233  using RangeBaseT::RangeBaseT;
234  ResultRange(OpResult result);
235 
236  //===--------------------------------------------------------------------===//
237  // Types
238  //===--------------------------------------------------------------------===//
239 
240  /// Returns the types of the values within this range.
243  type_range getTypes() const;
244  type_range getType() const;
245 
246  //===--------------------------------------------------------------------===//
247  // Uses
248  //===--------------------------------------------------------------------===//
249 
250  class UseIterator;
253 
254  /// Returns a range of all uses of results within this range, which is useful
255  /// for iterating over all uses.
256  use_range getUses() const;
257  use_iterator use_begin() const;
258  use_iterator use_end() const;
259 
260  /// Returns true if no results in this range have uses.
261  bool use_empty() const {
262  return llvm::all_of(*this,
263  [](OpResult result) { return result.use_empty(); });
264  }
265 
266  /// Replace all uses of results of this range with the provided 'values'. The
267  /// size of `values` must match the size of this range.
268  template <typename ValuesT>
269  std::enable_if_t<!std::is_convertible<ValuesT, Operation *>::value>
270  replaceAllUsesWith(ValuesT &&values) {
271  assert(static_cast<size_t>(std::distance(values.begin(), values.end())) ==
272  size() &&
273  "expected 'values' to correspond 1-1 with the number of results");
274 
275  for (auto it : llvm::zip(*this, values))
276  std::get<0>(it).replaceAllUsesWith(std::get<1>(it));
277  }
278 
279  /// Replace all uses of results of this range with results of 'op'.
280  void replaceAllUsesWith(Operation *op);
281 
282  /// Replace uses of results of this range with the provided 'values' if the
283  /// given callback returns true. The size of `values` must match the size of
284  /// this range.
285  template <typename ValuesT>
286  std::enable_if_t<!std::is_convertible<ValuesT, Operation *>::value>
287  replaceUsesWithIf(ValuesT &&values,
288  function_ref<bool(OpOperand &)> shouldReplace) {
289  assert(static_cast<size_t>(std::distance(values.begin(), values.end())) ==
290  size() &&
291  "expected 'values' to correspond 1-1 with the number of results");
292 
293  for (auto it : llvm::zip(*this, values))
294  std::get<0>(it).replaceUsesWithIf(std::get<1>(it), shouldReplace);
295  }
296 
297  /// Replace uses of results of this range with results of `op` if the given
298  /// callback returns true.
299  void replaceUsesWithIf(Operation *op,
300  function_ref<bool(OpOperand &)> shouldReplace);
301 
302  //===--------------------------------------------------------------------===//
303  // Users
304  //===--------------------------------------------------------------------===//
305 
308 
309  /// Returns a range of all users.
313 
314 private:
315  /// See `llvm::detail::indexed_accessor_range_base` for details.
316  static detail::OpResultImpl *offset_base(detail::OpResultImpl *object,
317  ptrdiff_t index) {
318  return object->getNextResultAtOffset(index);
319  }
320  /// See `llvm::detail::indexed_accessor_range_base` for details.
321  static OpResult dereference_iterator(detail::OpResultImpl *object,
322  ptrdiff_t index) {
323  return offset_base(object, index);
324  }
325 
326  /// Allow access to `offset_base` and `dereference_iterator`.
327  friend RangeBaseT;
328 };
329 
330 /// This class implements a use iterator for a range of operation results.
331 /// This iterates over all uses of all results within the given result range.
333  : public llvm::iterator_facade_base<UseIterator, std::forward_iterator_tag,
334  OpOperand> {
335 public:
336  /// Initialize the UseIterator. Specify `end` to return iterator to last
337  /// use, otherwise this is an iterator to the first use.
338  explicit UseIterator(ResultRange results, bool end = false);
339 
340  using llvm::iterator_facade_base<UseIterator, std::forward_iterator_tag,
341  OpOperand>::operator++;
343  OpOperand *operator->() const { return use.getOperand(); }
344  OpOperand &operator*() const { return *use.getOperand(); }
345 
346  bool operator==(const UseIterator &rhs) const { return use == rhs.use; }
347  bool operator!=(const UseIterator &rhs) const { return !(*this == rhs); }
348 
349 private:
350  void skipOverResultsWithNoUsers();
351 
352  /// The range of results being iterated over.
353  ResultRange::iterator it, endIt;
354  /// The use of the result.
356 };
357 
358 //===----------------------------------------------------------------------===//
359 // ValueRange
360 
361 /// This class provides an abstraction over the different types of ranges over
362 /// Values. In many cases, this prevents the need to explicitly materialize a
363 /// SmallVector/std::vector. This class should be used in places that are not
364 /// suitable for a more derived type (e.g. ArrayRef) or a template range
365 /// parameter.
366 class ValueRange final
368  ValueRange,
369  PointerUnion<const Value *, OpOperand *, detail::OpResultImpl *>,
370  Value, Value, Value> {
371 public:
372  /// The type representing the owner of a ValueRange. This is either a list of
373  /// values, operands, or results.
374  using OwnerT =
376 
377  using RangeBaseT::RangeBaseT;
378 
379  template <typename Arg,
380  typename = std::enable_if_t<
381  std::is_constructible<ArrayRef<Value>, Arg>::value &&
382  !std::is_convertible<Arg, Value>::value>>
383  ValueRange(Arg &&arg) : ValueRange(ArrayRef<Value>(std::forward<Arg>(arg))) {}
384  ValueRange(const Value &value) : ValueRange(&value, /*count=*/1) {}
385  ValueRange(const std::initializer_list<Value> &values)
386  : ValueRange(ArrayRef<Value>(values)) {}
388  : ValueRange(OperandRange(values)) {}
390  : ValueRange(ResultRange(values)) {}
392  : ValueRange(ArrayRef<Value>(values.data(), values.size())) {}
393  ValueRange(ArrayRef<Value> values = std::nullopt);
396 
397  /// Returns the types of the values within this range.
402 
403 private:
404  /// See `llvm::detail::indexed_accessor_range_base` for details.
405  static OwnerT offset_base(const OwnerT &owner, ptrdiff_t index);
406  /// See `llvm::detail::indexed_accessor_range_base` for details.
407  static Value dereference_iterator(const OwnerT &owner, ptrdiff_t index);
408 
409  /// Allow access to `offset_base` and `dereference_iterator`.
410  friend RangeBaseT;
411 };
412 
413 } // namespace mlir
414 
415 #endif // MLIR_IR_VALUERANGE_H
Attributes are known-constant values of operations.
Definition: Attributes.h:25
This class represents a contiguous range of mutable operand ranges, e.g.
Definition: ValueRange.h:195
MutableOperandRange join() const
Flatten all of the sub ranges into a single contiguous mutable operand range.
MutableOperandRangeRange(const MutableOperandRange &operands, NamedAttribute operandSegmentAttr)
Construct a range given a parent set of operands, and an I32 tensor elements attribute containing the...
This class provides a mutable adaptor for a range of operands.
Definition: ValueRange.h:115
unsigned size() const
Returns the current size of the range.
Definition: ValueRange.h:150
void assign(ValueRange values)
Assign this range to the given values.
MutableOperandRange slice(unsigned subStart, unsigned subLen, std::optional< OperandSegment > segment=std::nullopt) const
Slice this range into a sub range, with the additional operand segment.
void erase(unsigned subStart, unsigned subLen=1)
Erase the operands within the given sub-range.
void append(ValueRange values)
Append the given values to the range.
Value operator[](unsigned index) const
Returns the value at the given index.
Definition: ValueRange.h:166
bool empty() const
Returns if the current range is empty.
Definition: ValueRange.h:153
void clear()
Clear this range and erase all of the operands.
MutableOperandRange(Operation *owner, unsigned start, unsigned length, ArrayRef< OperandSegment > operandSegments=std::nullopt)
Construct a new mutable range from the given operand, operand start index, and range length.
Operation * getOwner() const
Returns the owning operation.
Definition: ValueRange.h:159
std::pair< unsigned, NamedAttribute > OperandSegment
A pair of a named attribute corresponding to an operand segment attribute, and the index within that ...
Definition: ValueRange.h:120
MutableOperandRangeRange split(NamedAttribute segmentSizes) const
Split this range into a set of contiguous subranges using the given elements attribute,...
NamedAttribute represents a combination of a name and an Attribute value.
Definition: Attributes.h:189
This class represents an operand of an operation.
Definition: Value.h:261
This is a value defined by a result of an operation.
Definition: Value.h:448
This class represents a contiguous range of operand ranges, e.g.
Definition: ValueRange.h:82
OperandRangeRange(OperandRange operands, Attribute operandSegments)
Construct a range given a parent set of operands, and an I32 elements attribute containing the sizes ...
OperandRange join() const
Flatten all of the sub ranges into a single contiguous operand range.
TypeRangeRange getTypes() const
Returns the range of types of the values within this range.
Definition: ValueRange.cpp:17
TypeRangeRange getType() const
Definition: ValueRange.cpp:21
This class implements the operand iterators for the Operation class.
Definition: ValueRange.h:42
unsigned getBeginOperandIndex() const
Return the operand index of the first element of this range.
type_range getType() const
Definition: ValueRange.cpp:30
type_range getTypes() const
Definition: ValueRange.cpp:26
OperandRangeRange split(DenseI32ArrayAttr segmentSizes) const
Split this range into a set of contiguous subranges using the given elements attribute,...
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
This class implements a use iterator for a range of operation results.
Definition: ValueRange.h:334
bool operator!=(const UseIterator &rhs) const
Definition: ValueRange.h:347
UseIterator(ResultRange results, bool end=false)
Initialize the UseIterator.
OpOperand * operator->() const
Definition: ValueRange.h:343
bool operator==(const UseIterator &rhs) const
Definition: ValueRange.h:346
OpOperand & operator*() const
Definition: ValueRange.h:344
This class implements the result iterators for the Operation class.
Definition: ValueRange.h:231
use_range getUses() const
Returns a range of all uses of results within this range, which is useful for iterating over all uses...
bool use_empty() const
Returns true if no results in this range have uses.
Definition: ValueRange.h:261
use_iterator use_begin() const
user_range getUsers()
Returns a range of all users.
ResultRange(OpResult result)
use_iterator use_end() const
std::enable_if_t<!std::is_convertible< ValuesT, Operation * >::value > replaceUsesWithIf(ValuesT &&values, function_ref< bool(OpOperand &)> shouldReplace)
Replace uses of results of this range with the provided 'values' if the given callback returns true.
Definition: ValueRange.h:287
type_range getTypes() const
Definition: ValueRange.cpp:35
user_iterator user_end()
std::enable_if_t<!std::is_convertible< ValuesT, Operation * >::value > replaceAllUsesWith(ValuesT &&values)
Replace all uses of results of this range with the provided 'values'.
Definition: ValueRange.h:270
user_iterator user_begin()
type_range getType() const
Definition: ValueRange.cpp:39
This class provides an abstraction for a range of TypeRange.
Definition: TypeRange.h:92
This class provides an abstraction over the different types of ranges over Values.
Definition: ValueRange.h:370
ValueRange(ResultRange values)
ValueRange(iterator_range< OperandRange::iterator > values)
Definition: ValueRange.h:387
ValueRange(OperandRange values)
ValueRange(Arg &&arg)
Definition: ValueRange.h:383
ValueRange(iterator_range< ResultRange::iterator > values)
Definition: ValueRange.h:389
ValueRange(ArrayRef< BlockArgument > values)
Definition: ValueRange.h:391
type_range getType() const
type_range getTypes() const
ValueRange(ArrayRef< Value > values=std::nullopt)
ValueRange(const std::initializer_list< Value > &values)
Definition: ValueRange.h:385
ValueRange(const Value &value)
Definition: ValueRange.h:384
This class implements iteration on the types of a given range of values.
Definition: TypeRange.h:118
This class implements iteration on the types of a given range of values.
Definition: TypeRange.h:131
OperandType * getOperand() const
Returns the current operands.
Definition: UseDefLists.h:306
An iterator over the users of an IRObject.
Definition: UseDefLists.h:336
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:93
bool use_empty() const
Returns true if this value has no uses.
Definition: Value.h:212
This class provides the implementation for an operation result.
Definition: Value.h:359
OpResultImpl * getNextResultAtOffset(intptr_t offset)
Returns the next operation result at offset after this result.
Definition: Value.cpp:135
This header declares functions that assit transformations in the MemRef dialect.