1a7215a90SAlex Zinenko //===- OperationSupport.cpp -----------------------------------------------===//
2a7215a90SAlex Zinenko //
330857107SMehdi Amini // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
456222a06SMehdi Amini // See https://llvm.org/LICENSE.txt for license information.
556222a06SMehdi Amini // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a7215a90SAlex Zinenko //
756222a06SMehdi Amini //===----------------------------------------------------------------------===//
8a7215a90SAlex Zinenko //
9a7215a90SAlex Zinenko // This file contains out-of-line implementations of the support types that
109ffdc930SRiver Riddle // Operation and related classes build on top of.
11a7215a90SAlex Zinenko //
12a7215a90SAlex Zinenko //===----------------------------------------------------------------------===//
13a7215a90SAlex Zinenko 
14a7215a90SAlex Zinenko #include "mlir/IR/OperationSupport.h"
15a7215a90SAlex Zinenko #include "mlir/IR/Block.h"
16*108abd2fSRiver Riddle #include "mlir/IR/OpDefinition.h"
179ffdc930SRiver Riddle #include "mlir/IR/Operation.h"
18*108abd2fSRiver Riddle #include "mlir/IR/StandardTypes.h"
199ffdc930SRiver Riddle using namespace mlir;
20a7215a90SAlex Zinenko 
219ffdc930SRiver Riddle //===----------------------------------------------------------------------===//
229ffdc930SRiver Riddle // OperationState
239ffdc930SRiver Riddle //===----------------------------------------------------------------------===//
24a7215a90SAlex Zinenko 
2548d6cf1cSRiver Riddle OperationState::OperationState(Location location, StringRef name)
262f59f768SRiver Riddle     : location(location), name(name, location->getContext()) {}
27a7215a90SAlex Zinenko 
2848d6cf1cSRiver Riddle OperationState::OperationState(Location location, OperationName name)
292f59f768SRiver Riddle     : location(location), name(name) {}
30a7215a90SAlex Zinenko 
3148d6cf1cSRiver Riddle OperationState::OperationState(Location location, StringRef name,
32a63f6e0bSUday Bondhugula                                ValueRange operands, ArrayRef<Type> types,
33a7215a90SAlex Zinenko                                ArrayRef<NamedAttribute> attributes,
34a7215a90SAlex Zinenko                                ArrayRef<Block *> successors,
354dfd1b5fSRiver Riddle                                MutableArrayRef<std::unique_ptr<Region>> regions)
362f59f768SRiver Riddle     : location(location), name(name, location->getContext()),
37a7215a90SAlex Zinenko       operands(operands.begin(), operands.end()),
38a7215a90SAlex Zinenko       types(types.begin(), types.end()),
39a7215a90SAlex Zinenko       attributes(attributes.begin(), attributes.end()),
40a7215a90SAlex Zinenko       successors(successors.begin(), successors.end()) {
412f59f768SRiver Riddle   for (std::unique_ptr<Region> &r : regions)
42a7215a90SAlex Zinenko     this->regions.push_back(std::move(r));
43a7215a90SAlex Zinenko }
44a7215a90SAlex Zinenko 
45d6ee6a03SRiver Riddle void OperationState::addOperands(ValueRange newOperands) {
46d6ee6a03SRiver Riddle   operands.append(newOperands.begin(), newOperands.end());
47d6ee6a03SRiver Riddle }
48d6ee6a03SRiver Riddle 
49cb177712SRiver Riddle void OperationState::addSuccessors(SuccessorRange newSuccessors) {
50cb177712SRiver Riddle   successors.append(newSuccessors.begin(), newSuccessors.end());
51d6ee6a03SRiver Riddle }
52d6ee6a03SRiver Riddle 
53a7215a90SAlex Zinenko Region *OperationState::addRegion() {
54a7215a90SAlex Zinenko   regions.emplace_back(new Region);
55a7215a90SAlex Zinenko   return regions.back().get();
56a7215a90SAlex Zinenko }
57a7215a90SAlex Zinenko 
58a7215a90SAlex Zinenko void OperationState::addRegion(std::unique_ptr<Region> &&region) {
59a7215a90SAlex Zinenko   regions.push_back(std::move(region));
60a7215a90SAlex Zinenko }
61a7215a90SAlex Zinenko 
629ffdc930SRiver Riddle //===----------------------------------------------------------------------===//
639ffdc930SRiver Riddle // OperandStorage
649ffdc930SRiver Riddle //===----------------------------------------------------------------------===//
659ffdc930SRiver Riddle 
664dfd1b5fSRiver Riddle detail::OperandStorage::OperandStorage(Operation *owner, ValueRange values)
674dfd1b5fSRiver Riddle     : representation(0) {
684dfd1b5fSRiver Riddle   auto &inlineStorage = getInlineStorage();
694dfd1b5fSRiver Riddle   inlineStorage.numOperands = inlineStorage.capacity = values.size();
704dfd1b5fSRiver Riddle   auto *operandPtrBegin = getTrailingObjects<OpOperand>();
714dfd1b5fSRiver Riddle   for (unsigned i = 0, e = inlineStorage.numOperands; i < e; ++i)
724dfd1b5fSRiver Riddle     new (&operandPtrBegin[i]) OpOperand(owner, values[i]);
734dfd1b5fSRiver Riddle }
744dfd1b5fSRiver Riddle 
754dfd1b5fSRiver Riddle detail::OperandStorage::~OperandStorage() {
764dfd1b5fSRiver Riddle   // Destruct the current storage container.
774dfd1b5fSRiver Riddle   if (isDynamicStorage()) {
784dfd1b5fSRiver Riddle     TrailingOperandStorage &storage = getDynamicStorage();
794dfd1b5fSRiver Riddle     storage.~TrailingOperandStorage();
804dfd1b5fSRiver Riddle     free(&storage);
814dfd1b5fSRiver Riddle   } else {
824dfd1b5fSRiver Riddle     getInlineStorage().~TrailingOperandStorage();
834dfd1b5fSRiver Riddle   }
844dfd1b5fSRiver Riddle }
854dfd1b5fSRiver Riddle 
869ffdc930SRiver Riddle /// Replace the operands contained in the storage with the ones provided in
874dfd1b5fSRiver Riddle /// 'values'.
884dfd1b5fSRiver Riddle void detail::OperandStorage::setOperands(Operation *owner, ValueRange values) {
894dfd1b5fSRiver Riddle   MutableArrayRef<OpOperand> storageOperands = resize(owner, values.size());
904dfd1b5fSRiver Riddle   for (unsigned i = 0, e = values.size(); i != e; ++i)
914dfd1b5fSRiver Riddle     storageOperands[i].set(values[i]);
924dfd1b5fSRiver Riddle }
934dfd1b5fSRiver Riddle 
94*108abd2fSRiver Riddle /// Replace the operands beginning at 'start' and ending at 'start' + 'length'
95*108abd2fSRiver Riddle /// with the ones provided in 'operands'. 'operands' may be smaller or larger
96*108abd2fSRiver Riddle /// than the range pointed to by 'start'+'length'.
97*108abd2fSRiver Riddle void detail::OperandStorage::setOperands(Operation *owner, unsigned start,
98*108abd2fSRiver Riddle                                          unsigned length, ValueRange operands) {
99*108abd2fSRiver Riddle   // If the new size is the same, we can update inplace.
100*108abd2fSRiver Riddle   unsigned newSize = operands.size();
101*108abd2fSRiver Riddle   if (newSize == length) {
102*108abd2fSRiver Riddle     MutableArrayRef<OpOperand> storageOperands = getOperands();
103*108abd2fSRiver Riddle     for (unsigned i = 0, e = length; i != e; ++i)
104*108abd2fSRiver Riddle       storageOperands[start + i].set(operands[i]);
105*108abd2fSRiver Riddle     return;
106*108abd2fSRiver Riddle   }
107*108abd2fSRiver Riddle   // If the new size is greater, remove the extra operands and set the rest
108*108abd2fSRiver Riddle   // inplace.
109*108abd2fSRiver Riddle   if (newSize < length) {
110*108abd2fSRiver Riddle     eraseOperands(start + operands.size(), length - newSize);
111*108abd2fSRiver Riddle     setOperands(owner, start, newSize, operands);
112*108abd2fSRiver Riddle     return;
113*108abd2fSRiver Riddle   }
114*108abd2fSRiver Riddle   // Otherwise, the new size is greater so we need to grow the storage.
115*108abd2fSRiver Riddle   auto storageOperands = resize(owner, size() + (newSize - length));
116*108abd2fSRiver Riddle 
117*108abd2fSRiver Riddle   // Shift operands to the right to make space for the new operands.
118*108abd2fSRiver Riddle   unsigned rotateSize = storageOperands.size() - (start + length);
119*108abd2fSRiver Riddle   auto rbegin = storageOperands.rbegin();
120*108abd2fSRiver Riddle   std::rotate(rbegin, std::next(rbegin, newSize - length), rbegin + rotateSize);
121*108abd2fSRiver Riddle 
122*108abd2fSRiver Riddle   // Update the operands inplace.
123*108abd2fSRiver Riddle   for (unsigned i = 0, e = operands.size(); i != e; ++i)
124*108abd2fSRiver Riddle     storageOperands[start + i].set(operands[i]);
125*108abd2fSRiver Riddle }
126*108abd2fSRiver Riddle 
127*108abd2fSRiver Riddle /// Erase an operand held by the storage.
128*108abd2fSRiver Riddle void detail::OperandStorage::eraseOperands(unsigned start, unsigned length) {
129*108abd2fSRiver Riddle   TrailingOperandStorage &storage = getStorage();
130*108abd2fSRiver Riddle   MutableArrayRef<OpOperand> operands = storage.getOperands();
131*108abd2fSRiver Riddle   assert((start + length) <= operands.size());
132*108abd2fSRiver Riddle   storage.numOperands -= length;
133*108abd2fSRiver Riddle 
134*108abd2fSRiver Riddle   // Shift all operands down if the operand to remove is not at the end.
135*108abd2fSRiver Riddle   if (start != storage.numOperands) {
136*108abd2fSRiver Riddle     auto indexIt = std::next(operands.begin(), start);
137*108abd2fSRiver Riddle     std::rotate(indexIt, std::next(indexIt, length), operands.end());
138*108abd2fSRiver Riddle   }
139*108abd2fSRiver Riddle   for (unsigned i = 0; i != length; ++i)
140*108abd2fSRiver Riddle     operands[storage.numOperands + i].~OpOperand();
141*108abd2fSRiver Riddle }
142*108abd2fSRiver Riddle 
1434dfd1b5fSRiver Riddle /// Resize the storage to the given size. Returns the array containing the new
1444dfd1b5fSRiver Riddle /// operands.
1454dfd1b5fSRiver Riddle MutableArrayRef<OpOperand> detail::OperandStorage::resize(Operation *owner,
1464dfd1b5fSRiver Riddle                                                           unsigned newSize) {
1474dfd1b5fSRiver Riddle   TrailingOperandStorage &storage = getStorage();
1484dfd1b5fSRiver Riddle 
1499ffdc930SRiver Riddle   // If the number of operands is less than or equal to the current amount, we
1509ffdc930SRiver Riddle   // can just update in place.
1514dfd1b5fSRiver Riddle   unsigned &numOperands = storage.numOperands;
1524dfd1b5fSRiver Riddle   MutableArrayRef<OpOperand> operands = storage.getOperands();
1534dfd1b5fSRiver Riddle   if (newSize <= numOperands) {
1544dfd1b5fSRiver Riddle     // If the number of new size is less than the current, remove any extra
1554dfd1b5fSRiver Riddle     // operands.
1564dfd1b5fSRiver Riddle     for (unsigned i = newSize; i != numOperands; ++i)
1574dfd1b5fSRiver Riddle       operands[i].~OpOperand();
1584dfd1b5fSRiver Riddle     numOperands = newSize;
1594dfd1b5fSRiver Riddle     return operands.take_front(newSize);
1609ffdc930SRiver Riddle   }
1619ffdc930SRiver Riddle 
1624dfd1b5fSRiver Riddle   // If the new size is within the original inline capacity, grow inplace.
1634dfd1b5fSRiver Riddle   if (newSize <= storage.capacity) {
1644dfd1b5fSRiver Riddle     OpOperand *opBegin = operands.data();
1654dfd1b5fSRiver Riddle     for (unsigned e = newSize; numOperands != e; ++numOperands)
1664dfd1b5fSRiver Riddle       new (&opBegin[numOperands]) OpOperand(owner);
1674dfd1b5fSRiver Riddle     return MutableArrayRef<OpOperand>(opBegin, newSize);
1688da0f85eSRiver Riddle   }
1699ffdc930SRiver Riddle 
1704dfd1b5fSRiver Riddle   // Otherwise, we need to allocate a new storage.
1714dfd1b5fSRiver Riddle   unsigned newCapacity =
1724dfd1b5fSRiver Riddle       std::max(unsigned(llvm::NextPowerOf2(storage.capacity + 2)), newSize);
1734dfd1b5fSRiver Riddle   auto *newStorageMem =
1744dfd1b5fSRiver Riddle       malloc(TrailingOperandStorage::totalSizeToAlloc<OpOperand>(newCapacity));
1754dfd1b5fSRiver Riddle   auto *newStorage = ::new (newStorageMem) TrailingOperandStorage();
1764dfd1b5fSRiver Riddle   newStorage->numOperands = newSize;
1774dfd1b5fSRiver Riddle   newStorage->capacity = newCapacity;
1784dfd1b5fSRiver Riddle 
1794dfd1b5fSRiver Riddle   // Move the current operands to the new storage.
1804dfd1b5fSRiver Riddle   MutableArrayRef<OpOperand> newOperands = newStorage->getOperands();
1814dfd1b5fSRiver Riddle   std::uninitialized_copy(std::make_move_iterator(operands.begin()),
1824dfd1b5fSRiver Riddle                           std::make_move_iterator(operands.end()),
1834dfd1b5fSRiver Riddle                           newOperands.begin());
1844dfd1b5fSRiver Riddle 
1854dfd1b5fSRiver Riddle   // Destroy the original operands.
1864dfd1b5fSRiver Riddle   for (auto &operand : operands)
1874dfd1b5fSRiver Riddle     operand.~OpOperand();
1884dfd1b5fSRiver Riddle 
1894dfd1b5fSRiver Riddle   // Initialize any new operands.
1904dfd1b5fSRiver Riddle   for (unsigned e = newSize; numOperands != e; ++numOperands)
1914dfd1b5fSRiver Riddle     new (&newOperands[numOperands]) OpOperand(owner);
1924dfd1b5fSRiver Riddle 
1934dfd1b5fSRiver Riddle   // If the current storage is also dynamic, free it.
1944dfd1b5fSRiver Riddle   if (isDynamicStorage())
1954dfd1b5fSRiver Riddle     free(&storage);
1964dfd1b5fSRiver Riddle 
1974dfd1b5fSRiver Riddle   // Update the storage representation to use the new dynamic storage.
1984dfd1b5fSRiver Riddle   representation = reinterpret_cast<intptr_t>(newStorage);
1994dfd1b5fSRiver Riddle   representation |= DynamicStorageBit;
2004dfd1b5fSRiver Riddle   return newOperands;
2019ffdc930SRiver Riddle }
2029ffdc930SRiver Riddle 
2039ed22ae5SRiver Riddle //===----------------------------------------------------------------------===//
20448e9ef43SRiver Riddle // ResultStorage
20548e9ef43SRiver Riddle //===----------------------------------------------------------------------===//
20648e9ef43SRiver Riddle 
20748e9ef43SRiver Riddle /// Returns the parent operation of this trailing result.
20848e9ef43SRiver Riddle Operation *detail::TrailingOpResult::getOwner() {
20948e9ef43SRiver Riddle   // We need to do some arithmetic to get the operation pointer. Move the
21048e9ef43SRiver Riddle   // trailing owner to the start of the array.
21148e9ef43SRiver Riddle   TrailingOpResult *trailingIt = this - trailingResultNumber;
21248e9ef43SRiver Riddle 
21348e9ef43SRiver Riddle   // Move the owner past the inline op results to get to the operation.
21448e9ef43SRiver Riddle   auto *inlineResultIt = reinterpret_cast<InLineOpResult *>(trailingIt) -
21548e9ef43SRiver Riddle                          OpResult::getMaxInlineResults();
21648e9ef43SRiver Riddle   return reinterpret_cast<Operation *>(inlineResultIt) - 1;
21748e9ef43SRiver Riddle }
21848e9ef43SRiver Riddle 
21948e9ef43SRiver Riddle //===----------------------------------------------------------------------===//
2209ed22ae5SRiver Riddle // Operation Value-Iterators
2219ed22ae5SRiver Riddle //===----------------------------------------------------------------------===//
2229ed22ae5SRiver Riddle 
2239ed22ae5SRiver Riddle //===----------------------------------------------------------------------===//
22494a4ca4bSRiver Riddle // TypeRange
22594a4ca4bSRiver Riddle 
22694a4ca4bSRiver Riddle TypeRange::TypeRange(ArrayRef<Type> types)
22794a4ca4bSRiver Riddle     : TypeRange(types.data(), types.size()) {}
22894a4ca4bSRiver Riddle TypeRange::TypeRange(OperandRange values)
22994a4ca4bSRiver Riddle     : TypeRange(values.begin().getBase(), values.size()) {}
23094a4ca4bSRiver Riddle TypeRange::TypeRange(ResultRange values)
23194a4ca4bSRiver Riddle     : TypeRange(values.getBase()->getResultTypes().slice(values.getStartIndex(),
23294a4ca4bSRiver Riddle                                                          values.size())) {}
233988249a5SRiver Riddle TypeRange::TypeRange(ArrayRef<Value> values)
234988249a5SRiver Riddle     : TypeRange(values.data(), values.size()) {}
23594a4ca4bSRiver Riddle TypeRange::TypeRange(ValueRange values) : TypeRange(OwnerT(), values.size()) {
23694a4ca4bSRiver Riddle   detail::ValueRangeOwner owner = values.begin().getBase();
23794a4ca4bSRiver Riddle   if (auto *op = reinterpret_cast<Operation *>(owner.ptr.dyn_cast<void *>()))
238b87531caSRiver Riddle     this->base = op->getResultTypes().drop_front(owner.startIndex).data();
23994a4ca4bSRiver Riddle   else if (auto *operand = owner.ptr.dyn_cast<OpOperand *>())
24094a4ca4bSRiver Riddle     this->base = operand;
24194a4ca4bSRiver Riddle   else
24294a4ca4bSRiver Riddle     this->base = owner.ptr.get<const Value *>();
24394a4ca4bSRiver Riddle }
24494a4ca4bSRiver Riddle 
245204c3b55SRiver Riddle /// See `llvm::detail::indexed_accessor_range_base` for details.
24694a4ca4bSRiver Riddle TypeRange::OwnerT TypeRange::offset_base(OwnerT object, ptrdiff_t index) {
24794a4ca4bSRiver Riddle   if (auto *value = object.dyn_cast<const Value *>())
24894a4ca4bSRiver Riddle     return {value + index};
24994a4ca4bSRiver Riddle   if (auto *operand = object.dyn_cast<OpOperand *>())
25094a4ca4bSRiver Riddle     return {operand + index};
25194a4ca4bSRiver Riddle   return {object.dyn_cast<const Type *>() + index};
25294a4ca4bSRiver Riddle }
253204c3b55SRiver Riddle /// See `llvm::detail::indexed_accessor_range_base` for details.
25494a4ca4bSRiver Riddle Type TypeRange::dereference_iterator(OwnerT object, ptrdiff_t index) {
25594a4ca4bSRiver Riddle   if (auto *value = object.dyn_cast<const Value *>())
25694a4ca4bSRiver Riddle     return (value + index)->getType();
25794a4ca4bSRiver Riddle   if (auto *operand = object.dyn_cast<OpOperand *>())
25894a4ca4bSRiver Riddle     return (operand + index)->get().getType();
25994a4ca4bSRiver Riddle   return object.dyn_cast<const Type *>()[index];
26094a4ca4bSRiver Riddle }
26194a4ca4bSRiver Riddle 
26294a4ca4bSRiver Riddle //===----------------------------------------------------------------------===//
2639ed22ae5SRiver Riddle // OperandRange
2649ed22ae5SRiver Riddle 
2659ed22ae5SRiver Riddle OperandRange::OperandRange(Operation *op)
2669ed22ae5SRiver Riddle     : OperandRange(op->getOpOperands().data(), op->getNumOperands()) {}
2679ed22ae5SRiver Riddle 
268621d7ccaSRiver Riddle /// Return the operand index of the first element of this range. The range
269621d7ccaSRiver Riddle /// must not be empty.
270621d7ccaSRiver Riddle unsigned OperandRange::getBeginOperandIndex() const {
271621d7ccaSRiver Riddle   assert(!empty() && "range must not be empty");
272621d7ccaSRiver Riddle   return base->getOperandNumber();
273621d7ccaSRiver Riddle }
274621d7ccaSRiver Riddle 
2759ed22ae5SRiver Riddle //===----------------------------------------------------------------------===//
276*108abd2fSRiver Riddle // MutableOperandRange
277*108abd2fSRiver Riddle 
278*108abd2fSRiver Riddle /// Construct a new mutable range from the given operand, operand start index,
279*108abd2fSRiver Riddle /// and range length.
280*108abd2fSRiver Riddle MutableOperandRange::MutableOperandRange(
281*108abd2fSRiver Riddle     Operation *owner, unsigned start, unsigned length,
282*108abd2fSRiver Riddle     ArrayRef<OperandSegment> operandSegments)
283*108abd2fSRiver Riddle     : owner(owner), start(start), length(length),
284*108abd2fSRiver Riddle       operandSegments(operandSegments.begin(), operandSegments.end()) {
285*108abd2fSRiver Riddle   assert((start + length) <= owner->getNumOperands() && "invalid range");
286*108abd2fSRiver Riddle }
287*108abd2fSRiver Riddle MutableOperandRange::MutableOperandRange(Operation *owner)
288*108abd2fSRiver Riddle     : MutableOperandRange(owner, /*start=*/0, owner->getNumOperands()) {}
289*108abd2fSRiver Riddle 
290*108abd2fSRiver Riddle /// Append the given values to the range.
291*108abd2fSRiver Riddle void MutableOperandRange::append(ValueRange values) {
292*108abd2fSRiver Riddle   if (values.empty())
293*108abd2fSRiver Riddle     return;
294*108abd2fSRiver Riddle   owner->insertOperands(start + length, values);
295*108abd2fSRiver Riddle   updateLength(length + values.size());
296*108abd2fSRiver Riddle }
297*108abd2fSRiver Riddle 
298*108abd2fSRiver Riddle /// Assign this range to the given values.
299*108abd2fSRiver Riddle void MutableOperandRange::assign(ValueRange values) {
300*108abd2fSRiver Riddle   owner->setOperands(start, length, values);
301*108abd2fSRiver Riddle   if (length != values.size())
302*108abd2fSRiver Riddle     updateLength(/*newLength=*/values.size());
303*108abd2fSRiver Riddle }
304*108abd2fSRiver Riddle 
305*108abd2fSRiver Riddle /// Assign the range to the given value.
306*108abd2fSRiver Riddle void MutableOperandRange::assign(Value value) {
307*108abd2fSRiver Riddle   if (length == 1) {
308*108abd2fSRiver Riddle     owner->setOperand(start, value);
309*108abd2fSRiver Riddle   } else {
310*108abd2fSRiver Riddle     owner->setOperands(start, length, value);
311*108abd2fSRiver Riddle     updateLength(/*newLength=*/1);
312*108abd2fSRiver Riddle   }
313*108abd2fSRiver Riddle }
314*108abd2fSRiver Riddle 
315*108abd2fSRiver Riddle /// Erase the operands within the given sub-range.
316*108abd2fSRiver Riddle void MutableOperandRange::erase(unsigned subStart, unsigned subLen) {
317*108abd2fSRiver Riddle   assert((subStart + subLen) <= length && "invalid sub-range");
318*108abd2fSRiver Riddle   if (length == 0)
319*108abd2fSRiver Riddle     return;
320*108abd2fSRiver Riddle   owner->eraseOperands(start + subStart, subLen);
321*108abd2fSRiver Riddle   updateLength(length - subLen);
322*108abd2fSRiver Riddle }
323*108abd2fSRiver Riddle 
324*108abd2fSRiver Riddle /// Clear this range and erase all of the operands.
325*108abd2fSRiver Riddle void MutableOperandRange::clear() {
326*108abd2fSRiver Riddle   if (length != 0) {
327*108abd2fSRiver Riddle     owner->eraseOperands(start, length);
328*108abd2fSRiver Riddle     updateLength(/*newLength=*/0);
329*108abd2fSRiver Riddle   }
330*108abd2fSRiver Riddle }
331*108abd2fSRiver Riddle 
332*108abd2fSRiver Riddle /// Allow implicit conversion to an OperandRange.
333*108abd2fSRiver Riddle MutableOperandRange::operator OperandRange() const {
334*108abd2fSRiver Riddle   return owner->getOperands().slice(start, length);
335*108abd2fSRiver Riddle }
336*108abd2fSRiver Riddle 
337*108abd2fSRiver Riddle /// Update the length of this range to the one provided.
338*108abd2fSRiver Riddle void MutableOperandRange::updateLength(unsigned newLength) {
339*108abd2fSRiver Riddle   int32_t diff = int32_t(newLength) - int32_t(length);
340*108abd2fSRiver Riddle   length = newLength;
341*108abd2fSRiver Riddle 
342*108abd2fSRiver Riddle   // Update any of the provided segment attributes.
343*108abd2fSRiver Riddle   for (OperandSegment &segment : operandSegments) {
344*108abd2fSRiver Riddle     auto attr = segment.second.second.cast<DenseIntElementsAttr>();
345*108abd2fSRiver Riddle     SmallVector<int32_t, 8> segments(attr.getValues<int32_t>());
346*108abd2fSRiver Riddle     segments[segment.first] += diff;
347*108abd2fSRiver Riddle     segment.second.second = DenseIntElementsAttr::get(attr.getType(), segments);
348*108abd2fSRiver Riddle     owner->setAttr(segment.second.first, segment.second.second);
349*108abd2fSRiver Riddle   }
350*108abd2fSRiver Riddle }
351*108abd2fSRiver Riddle 
352*108abd2fSRiver Riddle //===----------------------------------------------------------------------===//
3539ed22ae5SRiver Riddle // ResultRange
3549ed22ae5SRiver Riddle 
3559ed22ae5SRiver Riddle ResultRange::ResultRange(Operation *op)
356fd01d862SRiver Riddle     : ResultRange(op, /*startIndex=*/0, op->getNumResults()) {}
357fd01d862SRiver Riddle 
358aff4ed73SRiver Riddle ArrayRef<Type> ResultRange::getTypes() const {
359b87531caSRiver Riddle   return getBase()->getResultTypes().slice(getStartIndex(), size());
360aff4ed73SRiver Riddle }
361aff4ed73SRiver Riddle 
362204c3b55SRiver Riddle /// See `llvm::indexed_accessor_range` for details.
3630d9ca98cSRiver Riddle OpResult ResultRange::dereference(Operation *op, ptrdiff_t index) {
364fd01d862SRiver Riddle   return op->getResult(index);
365fd01d862SRiver Riddle }
3669ed22ae5SRiver Riddle 
3679ed22ae5SRiver Riddle //===----------------------------------------------------------------------===//
3689ed22ae5SRiver Riddle // ValueRange
3699ed22ae5SRiver Riddle 
370ab46543cSRiver Riddle ValueRange::ValueRange(ArrayRef<Value> values)
3719ed22ae5SRiver Riddle     : ValueRange(values.data(), values.size()) {}
3729ed22ae5SRiver Riddle ValueRange::ValueRange(OperandRange values)
3739ed22ae5SRiver Riddle     : ValueRange(values.begin().getBase(), values.size()) {}
3749ed22ae5SRiver Riddle ValueRange::ValueRange(ResultRange values)
375fd01d862SRiver Riddle     : ValueRange(
376fd01d862SRiver Riddle           {values.getBase(), static_cast<unsigned>(values.getStartIndex())},
377fd01d862SRiver Riddle           values.size()) {}
3789ed22ae5SRiver Riddle 
379204c3b55SRiver Riddle /// See `llvm::detail::indexed_accessor_range_base` for details.
3809ed22ae5SRiver Riddle ValueRange::OwnerT ValueRange::offset_base(const OwnerT &owner,
3819ed22ae5SRiver Riddle                                            ptrdiff_t index) {
382fd01d862SRiver Riddle   if (auto *value = owner.ptr.dyn_cast<const Value *>())
383fd01d862SRiver Riddle     return {value + index};
384fd01d862SRiver Riddle   if (auto *operand = owner.ptr.dyn_cast<OpOperand *>())
385fd01d862SRiver Riddle     return {operand + index};
386fd01d862SRiver Riddle   Operation *operation = reinterpret_cast<Operation *>(owner.ptr.get<void *>());
387fd01d862SRiver Riddle   return {operation, owner.startIndex + static_cast<unsigned>(index)};
3889ed22ae5SRiver Riddle }
389204c3b55SRiver Riddle /// See `llvm::detail::indexed_accessor_range_base` for details.
390ab46543cSRiver Riddle Value ValueRange::dereference_iterator(const OwnerT &owner, ptrdiff_t index) {
391fd01d862SRiver Riddle   if (auto *value = owner.ptr.dyn_cast<const Value *>())
392fd01d862SRiver Riddle     return value[index];
393fd01d862SRiver Riddle   if (auto *operand = owner.ptr.dyn_cast<OpOperand *>())
3949ed22ae5SRiver Riddle     return operand[index].get();
395fd01d862SRiver Riddle   Operation *operation = reinterpret_cast<Operation *>(owner.ptr.get<void *>());
396fd01d862SRiver Riddle   return operation->getResult(owner.startIndex + index);
3979ed22ae5SRiver Riddle }
398