Allow creating standalone Regions
Currently, regions can only be constructed by passing in a `Function` or an
`Instruction` pointer referencing the parent object, unlike `Function`s or
`Instruction`s themselves that can be created without a parent. It leads to a
rather complex flow in operation construction where one has to create the
operation first before being able to work with its regions. It may be
necessary to work with the regions before the operation is created. In
particular, in `build` and `parse` functions that are executed _before_ the
operation is created in cases where boilerplate region manipulation is required
(for example, inserting the hypothetical default terminator in affine regions).
Allow creating standalone regions. Such regions are meant to own a list of
blocks and transfer them to other regions on demand.
Each instruction stores a fixed number of regions as trailing objects and has
ownership of them. This decreases the size of the Instruction object for the
common case of instructions without regions. Keep this behavior intact. To
allow some flexibility in construction, make OperationState store an owning
vector of regions. When the Builder creates an Instruction from
OperationState, the bodies of the regions are transferred into the
instruction-owned regions to minimize copying. Thus, it becomes possible to
fill standalone regions with blocks and move them to an operation when it is
constructed, or move blocks from a region to an operation region, e.g., for
inlining.
PiperOrigin-RevId: 240368183
2019-03-27 00:55:06 +08:00
|
|
|
//===- OperationSupport.cpp -----------------------------------------------===//
|
|
|
|
//
|
2020-01-26 11:58:30 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
2019-12-24 01:35:36 +08:00
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
Allow creating standalone Regions
Currently, regions can only be constructed by passing in a `Function` or an
`Instruction` pointer referencing the parent object, unlike `Function`s or
`Instruction`s themselves that can be created without a parent. It leads to a
rather complex flow in operation construction where one has to create the
operation first before being able to work with its regions. It may be
necessary to work with the regions before the operation is created. In
particular, in `build` and `parse` functions that are executed _before_ the
operation is created in cases where boilerplate region manipulation is required
(for example, inserting the hypothetical default terminator in affine regions).
Allow creating standalone regions. Such regions are meant to own a list of
blocks and transfer them to other regions on demand.
Each instruction stores a fixed number of regions as trailing objects and has
ownership of them. This decreases the size of the Instruction object for the
common case of instructions without regions. Keep this behavior intact. To
allow some flexibility in construction, make OperationState store an owning
vector of regions. When the Builder creates an Instruction from
OperationState, the bodies of the regions are transferred into the
instruction-owned regions to minimize copying. Thus, it becomes possible to
fill standalone regions with blocks and move them to an operation when it is
constructed, or move blocks from a region to an operation region, e.g., for
inlining.
PiperOrigin-RevId: 240368183
2019-03-27 00:55:06 +08:00
|
|
|
//
|
2019-12-24 01:35:36 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
Allow creating standalone Regions
Currently, regions can only be constructed by passing in a `Function` or an
`Instruction` pointer referencing the parent object, unlike `Function`s or
`Instruction`s themselves that can be created without a parent. It leads to a
rather complex flow in operation construction where one has to create the
operation first before being able to work with its regions. It may be
necessary to work with the regions before the operation is created. In
particular, in `build` and `parse` functions that are executed _before_ the
operation is created in cases where boilerplate region manipulation is required
(for example, inserting the hypothetical default terminator in affine regions).
Allow creating standalone regions. Such regions are meant to own a list of
blocks and transfer them to other regions on demand.
Each instruction stores a fixed number of regions as trailing objects and has
ownership of them. This decreases the size of the Instruction object for the
common case of instructions without regions. Keep this behavior intact. To
allow some flexibility in construction, make OperationState store an owning
vector of regions. When the Builder creates an Instruction from
OperationState, the bodies of the regions are transferred into the
instruction-owned regions to minimize copying. Thus, it becomes possible to
fill standalone regions with blocks and move them to an operation when it is
constructed, or move blocks from a region to an operation region, e.g., for
inlining.
PiperOrigin-RevId: 240368183
2019-03-27 00:55:06 +08:00
|
|
|
//
|
|
|
|
// This file contains out-of-line implementations of the support types that
|
2019-03-27 05:45:38 +08:00
|
|
|
// Operation and related classes build on top of.
|
Allow creating standalone Regions
Currently, regions can only be constructed by passing in a `Function` or an
`Instruction` pointer referencing the parent object, unlike `Function`s or
`Instruction`s themselves that can be created without a parent. It leads to a
rather complex flow in operation construction where one has to create the
operation first before being able to work with its regions. It may be
necessary to work with the regions before the operation is created. In
particular, in `build` and `parse` functions that are executed _before_ the
operation is created in cases where boilerplate region manipulation is required
(for example, inserting the hypothetical default terminator in affine regions).
Allow creating standalone regions. Such regions are meant to own a list of
blocks and transfer them to other regions on demand.
Each instruction stores a fixed number of regions as trailing objects and has
ownership of them. This decreases the size of the Instruction object for the
common case of instructions without regions. Keep this behavior intact. To
allow some flexibility in construction, make OperationState store an owning
vector of regions. When the Builder creates an Instruction from
OperationState, the bodies of the regions are transferred into the
instruction-owned regions to minimize copying. Thus, it becomes possible to
fill standalone regions with blocks and move them to an operation when it is
constructed, or move blocks from a region to an operation region, e.g., for
inlining.
PiperOrigin-RevId: 240368183
2019-03-27 00:55:06 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "mlir/IR/OperationSupport.h"
|
|
|
|
#include "mlir/IR/Block.h"
|
2019-03-27 05:45:38 +08:00
|
|
|
#include "mlir/IR/Operation.h"
|
|
|
|
using namespace mlir;
|
Allow creating standalone Regions
Currently, regions can only be constructed by passing in a `Function` or an
`Instruction` pointer referencing the parent object, unlike `Function`s or
`Instruction`s themselves that can be created without a parent. It leads to a
rather complex flow in operation construction where one has to create the
operation first before being able to work with its regions. It may be
necessary to work with the regions before the operation is created. In
particular, in `build` and `parse` functions that are executed _before_ the
operation is created in cases where boilerplate region manipulation is required
(for example, inserting the hypothetical default terminator in affine regions).
Allow creating standalone regions. Such regions are meant to own a list of
blocks and transfer them to other regions on demand.
Each instruction stores a fixed number of regions as trailing objects and has
ownership of them. This decreases the size of the Instruction object for the
common case of instructions without regions. Keep this behavior intact. To
allow some flexibility in construction, make OperationState store an owning
vector of regions. When the Builder creates an Instruction from
OperationState, the bodies of the regions are transferred into the
instruction-owned regions to minimize copying. Thus, it becomes possible to
fill standalone regions with blocks and move them to an operation when it is
constructed, or move blocks from a region to an operation region, e.g., for
inlining.
PiperOrigin-RevId: 240368183
2019-03-27 00:55:06 +08:00
|
|
|
|
2019-03-27 05:45:38 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// OperationState
|
|
|
|
//===----------------------------------------------------------------------===//
|
Allow creating standalone Regions
Currently, regions can only be constructed by passing in a `Function` or an
`Instruction` pointer referencing the parent object, unlike `Function`s or
`Instruction`s themselves that can be created without a parent. It leads to a
rather complex flow in operation construction where one has to create the
operation first before being able to work with its regions. It may be
necessary to work with the regions before the operation is created. In
particular, in `build` and `parse` functions that are executed _before_ the
operation is created in cases where boilerplate region manipulation is required
(for example, inserting the hypothetical default terminator in affine regions).
Allow creating standalone regions. Such regions are meant to own a list of
blocks and transfer them to other regions on demand.
Each instruction stores a fixed number of regions as trailing objects and has
ownership of them. This decreases the size of the Instruction object for the
common case of instructions without regions. Keep this behavior intact. To
allow some flexibility in construction, make OperationState store an owning
vector of regions. When the Builder creates an Instruction from
OperationState, the bodies of the regions are transferred into the
instruction-owned regions to minimize copying. Thus, it becomes possible to
fill standalone regions with blocks and move them to an operation when it is
constructed, or move blocks from a region to an operation region, e.g., for
inlining.
PiperOrigin-RevId: 240368183
2019-03-27 00:55:06 +08:00
|
|
|
|
2019-06-23 02:08:52 +08:00
|
|
|
OperationState::OperationState(Location location, StringRef name)
|
2019-08-27 08:34:06 +08:00
|
|
|
: location(location), name(name, location->getContext()) {}
|
Allow creating standalone Regions
Currently, regions can only be constructed by passing in a `Function` or an
`Instruction` pointer referencing the parent object, unlike `Function`s or
`Instruction`s themselves that can be created without a parent. It leads to a
rather complex flow in operation construction where one has to create the
operation first before being able to work with its regions. It may be
necessary to work with the regions before the operation is created. In
particular, in `build` and `parse` functions that are executed _before_ the
operation is created in cases where boilerplate region manipulation is required
(for example, inserting the hypothetical default terminator in affine regions).
Allow creating standalone regions. Such regions are meant to own a list of
blocks and transfer them to other regions on demand.
Each instruction stores a fixed number of regions as trailing objects and has
ownership of them. This decreases the size of the Instruction object for the
common case of instructions without regions. Keep this behavior intact. To
allow some flexibility in construction, make OperationState store an owning
vector of regions. When the Builder creates an Instruction from
OperationState, the bodies of the regions are transferred into the
instruction-owned regions to minimize copying. Thus, it becomes possible to
fill standalone regions with blocks and move them to an operation when it is
constructed, or move blocks from a region to an operation region, e.g., for
inlining.
PiperOrigin-RevId: 240368183
2019-03-27 00:55:06 +08:00
|
|
|
|
2019-06-23 02:08:52 +08:00
|
|
|
OperationState::OperationState(Location location, OperationName name)
|
2019-08-27 08:34:06 +08:00
|
|
|
: location(location), name(name) {}
|
Allow creating standalone Regions
Currently, regions can only be constructed by passing in a `Function` or an
`Instruction` pointer referencing the parent object, unlike `Function`s or
`Instruction`s themselves that can be created without a parent. It leads to a
rather complex flow in operation construction where one has to create the
operation first before being able to work with its regions. It may be
necessary to work with the regions before the operation is created. In
particular, in `build` and `parse` functions that are executed _before_ the
operation is created in cases where boilerplate region manipulation is required
(for example, inserting the hypothetical default terminator in affine regions).
Allow creating standalone regions. Such regions are meant to own a list of
blocks and transfer them to other regions on demand.
Each instruction stores a fixed number of regions as trailing objects and has
ownership of them. This decreases the size of the Instruction object for the
common case of instructions without regions. Keep this behavior intact. To
allow some flexibility in construction, make OperationState store an owning
vector of regions. When the Builder creates an Instruction from
OperationState, the bodies of the regions are transferred into the
instruction-owned regions to minimize copying. Thus, it becomes possible to
fill standalone regions with blocks and move them to an operation when it is
constructed, or move blocks from a region to an operation region, e.g., for
inlining.
PiperOrigin-RevId: 240368183
2019-03-27 00:55:06 +08:00
|
|
|
|
2019-06-23 02:08:52 +08:00
|
|
|
OperationState::OperationState(Location location, StringRef name,
|
2019-12-09 22:26:05 +08:00
|
|
|
ValueRange operands, ArrayRef<Type> types,
|
Allow creating standalone Regions
Currently, regions can only be constructed by passing in a `Function` or an
`Instruction` pointer referencing the parent object, unlike `Function`s or
`Instruction`s themselves that can be created without a parent. It leads to a
rather complex flow in operation construction where one has to create the
operation first before being able to work with its regions. It may be
necessary to work with the regions before the operation is created. In
particular, in `build` and `parse` functions that are executed _before_ the
operation is created in cases where boilerplate region manipulation is required
(for example, inserting the hypothetical default terminator in affine regions).
Allow creating standalone regions. Such regions are meant to own a list of
blocks and transfer them to other regions on demand.
Each instruction stores a fixed number of regions as trailing objects and has
ownership of them. This decreases the size of the Instruction object for the
common case of instructions without regions. Keep this behavior intact. To
allow some flexibility in construction, make OperationState store an owning
vector of regions. When the Builder creates an Instruction from
OperationState, the bodies of the regions are transferred into the
instruction-owned regions to minimize copying. Thus, it becomes possible to
fill standalone regions with blocks and move them to an operation when it is
constructed, or move blocks from a region to an operation region, e.g., for
inlining.
PiperOrigin-RevId: 240368183
2019-03-27 00:55:06 +08:00
|
|
|
ArrayRef<NamedAttribute> attributes,
|
|
|
|
ArrayRef<Block *> successors,
|
|
|
|
MutableArrayRef<std::unique_ptr<Region>> regions,
|
|
|
|
bool resizableOperandList)
|
2019-08-27 08:34:06 +08:00
|
|
|
: location(location), name(name, location->getContext()),
|
Allow creating standalone Regions
Currently, regions can only be constructed by passing in a `Function` or an
`Instruction` pointer referencing the parent object, unlike `Function`s or
`Instruction`s themselves that can be created without a parent. It leads to a
rather complex flow in operation construction where one has to create the
operation first before being able to work with its regions. It may be
necessary to work with the regions before the operation is created. In
particular, in `build` and `parse` functions that are executed _before_ the
operation is created in cases where boilerplate region manipulation is required
(for example, inserting the hypothetical default terminator in affine regions).
Allow creating standalone regions. Such regions are meant to own a list of
blocks and transfer them to other regions on demand.
Each instruction stores a fixed number of regions as trailing objects and has
ownership of them. This decreases the size of the Instruction object for the
common case of instructions without regions. Keep this behavior intact. To
allow some flexibility in construction, make OperationState store an owning
vector of regions. When the Builder creates an Instruction from
OperationState, the bodies of the regions are transferred into the
instruction-owned regions to minimize copying. Thus, it becomes possible to
fill standalone regions with blocks and move them to an operation when it is
constructed, or move blocks from a region to an operation region, e.g., for
inlining.
PiperOrigin-RevId: 240368183
2019-03-27 00:55:06 +08:00
|
|
|
operands(operands.begin(), operands.end()),
|
|
|
|
types(types.begin(), types.end()),
|
|
|
|
attributes(attributes.begin(), attributes.end()),
|
|
|
|
successors(successors.begin(), successors.end()) {
|
2019-08-27 08:34:06 +08:00
|
|
|
for (std::unique_ptr<Region> &r : regions)
|
Allow creating standalone Regions
Currently, regions can only be constructed by passing in a `Function` or an
`Instruction` pointer referencing the parent object, unlike `Function`s or
`Instruction`s themselves that can be created without a parent. It leads to a
rather complex flow in operation construction where one has to create the
operation first before being able to work with its regions. It may be
necessary to work with the regions before the operation is created. In
particular, in `build` and `parse` functions that are executed _before_ the
operation is created in cases where boilerplate region manipulation is required
(for example, inserting the hypothetical default terminator in affine regions).
Allow creating standalone regions. Such regions are meant to own a list of
blocks and transfer them to other regions on demand.
Each instruction stores a fixed number of regions as trailing objects and has
ownership of them. This decreases the size of the Instruction object for the
common case of instructions without regions. Keep this behavior intact. To
allow some flexibility in construction, make OperationState store an owning
vector of regions. When the Builder creates an Instruction from
OperationState, the bodies of the regions are transferred into the
instruction-owned regions to minimize copying. Thus, it becomes possible to
fill standalone regions with blocks and move them to an operation when it is
constructed, or move blocks from a region to an operation region, e.g., for
inlining.
PiperOrigin-RevId: 240368183
2019-03-27 00:55:06 +08:00
|
|
|
this->regions.push_back(std::move(r));
|
|
|
|
}
|
|
|
|
|
2019-12-08 02:35:01 +08:00
|
|
|
void OperationState::addOperands(ValueRange newOperands) {
|
|
|
|
assert(successors.empty() && "Non successor operands should be added first.");
|
|
|
|
operands.append(newOperands.begin(), newOperands.end());
|
|
|
|
}
|
|
|
|
|
|
|
|
void OperationState::addSuccessor(Block *successor, ValueRange succOperands) {
|
|
|
|
successors.push_back(successor);
|
|
|
|
// Insert a sentinel operand to mark a barrier between successor operands.
|
|
|
|
operands.push_back(nullptr);
|
|
|
|
operands.append(succOperands.begin(), succOperands.end());
|
|
|
|
}
|
|
|
|
|
Allow creating standalone Regions
Currently, regions can only be constructed by passing in a `Function` or an
`Instruction` pointer referencing the parent object, unlike `Function`s or
`Instruction`s themselves that can be created without a parent. It leads to a
rather complex flow in operation construction where one has to create the
operation first before being able to work with its regions. It may be
necessary to work with the regions before the operation is created. In
particular, in `build` and `parse` functions that are executed _before_ the
operation is created in cases where boilerplate region manipulation is required
(for example, inserting the hypothetical default terminator in affine regions).
Allow creating standalone regions. Such regions are meant to own a list of
blocks and transfer them to other regions on demand.
Each instruction stores a fixed number of regions as trailing objects and has
ownership of them. This decreases the size of the Instruction object for the
common case of instructions without regions. Keep this behavior intact. To
allow some flexibility in construction, make OperationState store an owning
vector of regions. When the Builder creates an Instruction from
OperationState, the bodies of the regions are transferred into the
instruction-owned regions to minimize copying. Thus, it becomes possible to
fill standalone regions with blocks and move them to an operation when it is
constructed, or move blocks from a region to an operation region, e.g., for
inlining.
PiperOrigin-RevId: 240368183
2019-03-27 00:55:06 +08:00
|
|
|
Region *OperationState::addRegion() {
|
|
|
|
regions.emplace_back(new Region);
|
|
|
|
return regions.back().get();
|
|
|
|
}
|
|
|
|
|
|
|
|
void OperationState::addRegion(std::unique_ptr<Region> &®ion) {
|
|
|
|
regions.push_back(std::move(region));
|
|
|
|
}
|
|
|
|
|
2019-03-27 05:45:38 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// OperandStorage
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// Replace the operands contained in the storage with the ones provided in
|
|
|
|
/// 'operands'.
|
|
|
|
void detail::OperandStorage::setOperands(Operation *owner,
|
2019-12-08 02:35:01 +08:00
|
|
|
ValueRange operands) {
|
2019-03-27 05:45:38 +08:00
|
|
|
// If the number of operands is less than or equal to the current amount, we
|
|
|
|
// can just update in place.
|
|
|
|
if (operands.size() <= numOperands) {
|
2019-03-29 02:25:19 +08:00
|
|
|
auto opOperands = getOperands();
|
2019-03-27 05:45:38 +08:00
|
|
|
|
|
|
|
// If the number of new operands is less than the current count, then remove
|
|
|
|
// any extra operands.
|
|
|
|
for (unsigned i = operands.size(); i != numOperands; ++i)
|
2019-03-29 02:25:19 +08:00
|
|
|
opOperands[i].~OpOperand();
|
2019-03-27 05:45:38 +08:00
|
|
|
|
|
|
|
// Set the operands in place.
|
|
|
|
numOperands = operands.size();
|
|
|
|
for (unsigned i = 0; i != numOperands; ++i)
|
2019-03-29 02:25:19 +08:00
|
|
|
opOperands[i].set(operands[i]);
|
2019-03-27 05:45:38 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, we need to be resizable.
|
|
|
|
assert(resizable && "Only resizable operations may add operands");
|
|
|
|
|
|
|
|
// Grow the capacity if necessary.
|
|
|
|
auto &resizeUtil = getResizableStorage();
|
|
|
|
if (resizeUtil.capacity < operands.size())
|
|
|
|
grow(resizeUtil, operands.size());
|
|
|
|
|
|
|
|
// Set the operands.
|
2019-03-29 02:25:19 +08:00
|
|
|
OpOperand *opBegin = getRawOperands();
|
2019-03-27 05:45:38 +08:00
|
|
|
for (unsigned i = 0; i != numOperands; ++i)
|
|
|
|
opBegin[i].set(operands[i]);
|
|
|
|
for (unsigned e = operands.size(); numOperands != e; ++numOperands)
|
2019-03-29 02:25:19 +08:00
|
|
|
new (&opBegin[numOperands]) OpOperand(owner, operands[numOperands]);
|
2019-03-27 05:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Erase an operand held by the storage.
|
|
|
|
void detail::OperandStorage::eraseOperand(unsigned index) {
|
|
|
|
assert(index < size());
|
2019-03-29 02:25:19 +08:00
|
|
|
auto operands = getOperands();
|
2019-03-27 05:45:38 +08:00
|
|
|
--numOperands;
|
|
|
|
|
|
|
|
// Shift all operands down by 1 if the operand to remove is not at the end.
|
2019-07-02 05:38:02 +08:00
|
|
|
auto indexIt = std::next(operands.begin(), index);
|
2019-03-27 05:45:38 +08:00
|
|
|
if (index != numOperands)
|
2019-07-02 05:38:02 +08:00
|
|
|
std::rotate(indexIt, std::next(indexIt), operands.end());
|
2019-03-29 02:25:19 +08:00
|
|
|
operands[numOperands].~OpOperand();
|
2019-03-27 05:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Grow the internal operand storage.
|
|
|
|
void detail::OperandStorage::grow(ResizableStorage &resizeUtil,
|
|
|
|
size_t minSize) {
|
|
|
|
// Allocate a new storage array.
|
|
|
|
resizeUtil.capacity =
|
|
|
|
std::max(size_t(llvm::NextPowerOf2(resizeUtil.capacity + 2)), minSize);
|
2019-03-29 02:25:19 +08:00
|
|
|
OpOperand *newStorage = static_cast<OpOperand *>(
|
|
|
|
llvm::safe_malloc(resizeUtil.capacity * sizeof(OpOperand)));
|
2019-03-27 05:45:38 +08:00
|
|
|
|
|
|
|
// Move the current operands to the new storage.
|
2019-03-29 02:25:19 +08:00
|
|
|
auto operands = getOperands();
|
2019-03-27 05:45:38 +08:00
|
|
|
std::uninitialized_copy(std::make_move_iterator(operands.begin()),
|
|
|
|
std::make_move_iterator(operands.end()), newStorage);
|
|
|
|
|
|
|
|
// Destroy the original operands and update the resizable storage pointer.
|
|
|
|
for (auto &operand : operands)
|
2019-03-29 02:25:19 +08:00
|
|
|
operand.~OpOperand();
|
2019-03-27 05:45:38 +08:00
|
|
|
resizeUtil.setDynamicStorage(newStorage);
|
|
|
|
}
|
2019-12-11 05:20:50 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Operation Value-Iterators
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// OperandRange
|
|
|
|
|
|
|
|
OperandRange::OperandRange(Operation *op)
|
|
|
|
: OperandRange(op->getOpOperands().data(), op->getNumOperands()) {}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ResultRange
|
|
|
|
|
|
|
|
ResultRange::ResultRange(Operation *op)
|
2020-01-03 06:28:37 +08:00
|
|
|
: ResultRange(op, /*startIndex=*/0, op->getNumResults()) {}
|
|
|
|
|
2020-01-04 05:12:25 +08:00
|
|
|
/// See `indexed_accessor_range` for details.
|
|
|
|
OpResult ResultRange::dereference(Operation *op, ptrdiff_t index) {
|
2020-01-03 06:28:37 +08:00
|
|
|
return op->getResult(index);
|
|
|
|
}
|
2019-12-11 05:20:50 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ValueRange
|
|
|
|
|
2019-12-24 04:36:20 +08:00
|
|
|
ValueRange::ValueRange(ArrayRef<Value> values)
|
2019-12-11 05:20:50 +08:00
|
|
|
: ValueRange(values.data(), values.size()) {}
|
|
|
|
ValueRange::ValueRange(OperandRange values)
|
|
|
|
: ValueRange(values.begin().getBase(), values.size()) {}
|
|
|
|
ValueRange::ValueRange(ResultRange values)
|
2020-01-03 06:28:37 +08:00
|
|
|
: ValueRange(
|
|
|
|
{values.getBase(), static_cast<unsigned>(values.getStartIndex())},
|
|
|
|
values.size()) {}
|
2019-12-11 05:20:50 +08:00
|
|
|
|
|
|
|
/// See `detail::indexed_accessor_range_base` for details.
|
|
|
|
ValueRange::OwnerT ValueRange::offset_base(const OwnerT &owner,
|
|
|
|
ptrdiff_t index) {
|
2020-01-03 06:28:37 +08:00
|
|
|
if (auto *value = owner.ptr.dyn_cast<const Value *>())
|
|
|
|
return {value + index};
|
|
|
|
if (auto *operand = owner.ptr.dyn_cast<OpOperand *>())
|
|
|
|
return {operand + index};
|
|
|
|
Operation *operation = reinterpret_cast<Operation *>(owner.ptr.get<void *>());
|
|
|
|
return {operation, owner.startIndex + static_cast<unsigned>(index)};
|
2019-12-11 05:20:50 +08:00
|
|
|
}
|
|
|
|
/// See `detail::indexed_accessor_range_base` for details.
|
2019-12-24 04:36:20 +08:00
|
|
|
Value ValueRange::dereference_iterator(const OwnerT &owner, ptrdiff_t index) {
|
2020-01-03 06:28:37 +08:00
|
|
|
if (auto *value = owner.ptr.dyn_cast<const Value *>())
|
|
|
|
return value[index];
|
|
|
|
if (auto *operand = owner.ptr.dyn_cast<OpOperand *>())
|
2019-12-11 05:20:50 +08:00
|
|
|
return operand[index].get();
|
2020-01-03 06:28:37 +08:00
|
|
|
Operation *operation = reinterpret_cast<Operation *>(owner.ptr.get<void *>());
|
|
|
|
return operation->getResult(owner.startIndex + index);
|
2019-12-11 05:20:50 +08:00
|
|
|
}
|