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