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