2018-12-28 07:06:22 +08:00
|
|
|
//===- Value.cpp - MLIR Value Classes -------------------------------------===//
|
2018-08-02 01:43:18 +08:00
|
|
|
//
|
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
|
2018-08-02 01:43:18 +08:00
|
|
|
//
|
2019-12-24 01:35:36 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2018-08-02 01:43:18 +08:00
|
|
|
|
2018-12-28 07:06:22 +08:00
|
|
|
#include "mlir/IR/Value.h"
|
2019-04-25 00:24:57 +08:00
|
|
|
#include "mlir/IR/Block.h"
|
2019-03-27 05:45:38 +08:00
|
|
|
#include "mlir/IR/Operation.h"
|
2020-01-03 06:28:37 +08:00
|
|
|
#include "mlir/IR/StandardTypes.h"
|
2018-08-02 01:43:18 +08:00
|
|
|
using namespace mlir;
|
|
|
|
|
2020-01-03 06:28:37 +08:00
|
|
|
/// Construct a value.
|
|
|
|
Value::Value(detail::BlockArgumentImpl *impl)
|
|
|
|
: ownerAndKind(impl, Kind::BlockArgument) {}
|
|
|
|
Value::Value(Operation *op, unsigned resultNo) {
|
|
|
|
assert(op->getNumResults() > resultNo && "invalid result number");
|
|
|
|
if (LLVM_LIKELY(canPackResultInline(resultNo))) {
|
|
|
|
ownerAndKind = {op, static_cast<Kind>(resultNo)};
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we can't pack the result directly, we need to represent this as a
|
|
|
|
// trailing result.
|
|
|
|
unsigned trailingResultNo =
|
|
|
|
resultNo - static_cast<unsigned>(Kind::TrailingOpResult);
|
|
|
|
ownerAndKind = {op->getTrailingResult(trailingResultNo),
|
|
|
|
Kind::TrailingOpResult};
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Return the type of this value.
|
|
|
|
Type Value::getType() const {
|
|
|
|
if (BlockArgument arg = dyn_cast<BlockArgument>())
|
|
|
|
return arg.getType();
|
|
|
|
|
|
|
|
// If this is an operation result, query the parent operation.
|
|
|
|
OpResult result = cast<OpResult>();
|
|
|
|
Operation *owner = result.getOwner();
|
|
|
|
if (owner->hasSingleResult)
|
|
|
|
return owner->resultType;
|
|
|
|
return owner->resultType.cast<TupleType>().getType(result.getResultNumber());
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Mutate the type of this Value to be of the specified type.
|
|
|
|
void Value::setType(Type newType) {
|
|
|
|
if (BlockArgument arg = dyn_cast<BlockArgument>())
|
|
|
|
return arg.setType(newType);
|
|
|
|
OpResult result = cast<OpResult>();
|
|
|
|
|
|
|
|
// If the owner has a single result, simply update it directly.
|
|
|
|
Operation *owner = result.getOwner();
|
|
|
|
if (owner->hasSingleResult) {
|
|
|
|
owner->resultType = newType;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
unsigned resultNo = result.getResultNumber();
|
|
|
|
|
|
|
|
// Otherwise, rebuild the tuple if the new type is different from the current.
|
|
|
|
auto curTypes = owner->resultType.cast<TupleType>().getTypes();
|
|
|
|
if (curTypes[resultNo] == newType)
|
|
|
|
return;
|
|
|
|
auto newTypes = llvm::to_vector<4>(curTypes);
|
|
|
|
newTypes[resultNo] = newType;
|
|
|
|
owner->resultType = TupleType::get(newTypes, newType.getContext());
|
|
|
|
}
|
|
|
|
|
2019-03-27 08:05:09 +08:00
|
|
|
/// If this value is the result of an Operation, return the operation that
|
|
|
|
/// defines it.
|
2019-12-24 04:36:20 +08:00
|
|
|
Operation *Value::getDefiningOp() const {
|
|
|
|
if (auto result = dyn_cast<OpResult>())
|
2020-01-12 00:54:04 +08:00
|
|
|
return result.getOwner();
|
2018-08-02 01:43:18 +08:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2020-01-12 00:54:04 +08:00
|
|
|
Location Value::getLoc() const {
|
2019-07-09 02:20:26 +08:00
|
|
|
if (auto *op = getDefiningOp())
|
2019-04-02 01:42:34 +08:00
|
|
|
return op->getLoc();
|
|
|
|
return UnknownLoc::get(getContext());
|
|
|
|
}
|
|
|
|
|
2019-04-25 00:24:57 +08:00
|
|
|
/// Return the Region in which this Value is defined.
|
2019-08-10 11:07:25 +08:00
|
|
|
Region *Value::getParentRegion() {
|
2019-10-15 07:21:17 +08:00
|
|
|
if (auto *op = getDefiningOp())
|
|
|
|
return op->getParentRegion();
|
2020-01-12 00:54:04 +08:00
|
|
|
return cast<BlockArgument>().getOwner()->getParent();
|
2019-04-25 00:24:57 +08:00
|
|
|
}
|
|
|
|
|
2019-12-28 12:33:53 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2019-12-31 12:49:47 +08:00
|
|
|
// Value::UseLists
|
2019-12-28 12:33:53 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2019-12-31 12:49:47 +08:00
|
|
|
/// Provide the use list that is attached to this value.
|
|
|
|
IRObjectWithUseList<OpOperand> *Value::getUseList() const {
|
|
|
|
if (BlockArgument arg = dyn_cast<BlockArgument>())
|
|
|
|
return arg.getImpl();
|
|
|
|
return cast<OpResult>().getOwner();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Drop all uses of this object from their respective owners.
|
|
|
|
void Value::dropAllUses() const {
|
|
|
|
if (BlockArgument arg = dyn_cast<BlockArgument>())
|
|
|
|
return arg.getImpl()->dropAllUses();
|
2020-01-29 03:19:20 +08:00
|
|
|
Operation *owner = cast<OpResult>().getOwner();
|
|
|
|
if (owner->hasSingleResult)
|
|
|
|
return owner->dropAllUses();
|
|
|
|
return owner->dropAllUses(*this);
|
2019-12-31 12:49:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Replace all uses of 'this' value with the new value, updating anything in
|
|
|
|
/// the IR that uses 'this' to use the other value instead. When this returns
|
|
|
|
/// there are zero uses of 'this'.
|
|
|
|
void Value::replaceAllUsesWith(Value newValue) const {
|
|
|
|
if (BlockArgument arg = dyn_cast<BlockArgument>())
|
|
|
|
return arg.getImpl()->replaceAllUsesWith(newValue);
|
2020-01-29 03:19:20 +08:00
|
|
|
Operation *owner = cast<OpResult>().getOwner();
|
|
|
|
IRMultiObjectWithUseList<OpOperand> *useList = owner;
|
|
|
|
if (owner->hasSingleResult)
|
|
|
|
return useList->replaceAllUsesWith(newValue);
|
2019-12-31 12:49:47 +08:00
|
|
|
useList->replaceAllUsesWith(*this, newValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
// Uses
|
|
|
|
|
|
|
|
auto Value::use_begin() const -> use_iterator {
|
|
|
|
if (BlockArgument arg = dyn_cast<BlockArgument>())
|
|
|
|
return arg.getImpl()->use_begin();
|
2020-01-29 03:19:20 +08:00
|
|
|
Operation *owner = cast<OpResult>().getOwner();
|
|
|
|
return owner->hasSingleResult ? use_iterator(owner->use_begin())
|
|
|
|
: owner->use_begin(*this);
|
2019-12-31 12:49:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns true if this value has exactly one use.
|
|
|
|
bool Value::hasOneUse() const {
|
|
|
|
if (BlockArgument arg = dyn_cast<BlockArgument>())
|
|
|
|
return arg.getImpl()->hasOneUse();
|
2020-01-29 03:19:20 +08:00
|
|
|
Operation *owner = cast<OpResult>().getOwner();
|
|
|
|
return owner->hasSingleResult ? owner->hasOneUse() : owner->hasOneUse(*this);
|
2019-12-31 12:49:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns true if this value has no uses.
|
|
|
|
bool Value::use_empty() const {
|
|
|
|
if (BlockArgument arg = dyn_cast<BlockArgument>())
|
|
|
|
return arg.getImpl()->use_empty();
|
2020-01-29 03:19:20 +08:00
|
|
|
Operation *owner = cast<OpResult>().getOwner();
|
|
|
|
return owner->hasSingleResult ? owner->use_empty() : owner->use_empty(*this);
|
2019-12-31 12:49:47 +08:00
|
|
|
}
|
|
|
|
|
2020-01-03 06:28:37 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// OpResult
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// Returns the operation that owns this result.
|
|
|
|
Operation *OpResult::getOwner() const {
|
|
|
|
// If the result is in-place, the `owner` is the operation.
|
|
|
|
if (LLVM_LIKELY(getKind() != Kind::TrailingOpResult))
|
|
|
|
return reinterpret_cast<Operation *>(ownerAndKind.getPointer());
|
|
|
|
|
|
|
|
// Otherwise, we need to do some arithmetic to get the operation pointer.
|
|
|
|
// Move the trailing owner to the start of the array.
|
|
|
|
auto *trailingIt =
|
|
|
|
static_cast<detail::TrailingOpResult *>(ownerAndKind.getPointer());
|
|
|
|
trailingIt -= trailingIt->trailingResultNumber;
|
|
|
|
|
|
|
|
// This point is the first trailing object after the operation. So all we need
|
|
|
|
// to do here is adjust for the operation size.
|
|
|
|
return reinterpret_cast<Operation *>(trailingIt) - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Return the result number of this result.
|
|
|
|
unsigned OpResult::getResultNumber() const {
|
|
|
|
// If the result is in-place, we can use the kind directly.
|
|
|
|
if (LLVM_LIKELY(getKind() != Kind::TrailingOpResult))
|
|
|
|
return static_cast<unsigned>(ownerAndKind.getInt());
|
|
|
|
// Otherwise, we add the number of inline results to the trailing owner.
|
|
|
|
auto *trailingIt =
|
|
|
|
static_cast<detail::TrailingOpResult *>(ownerAndKind.getPointer());
|
|
|
|
unsigned trailingNumber = trailingIt->trailingResultNumber;
|
|
|
|
return trailingNumber + static_cast<unsigned>(Kind::TrailingOpResult);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Given a number of operation results, returns the number that need to be
|
|
|
|
/// stored as trailing.
|
|
|
|
unsigned OpResult::getNumTrailing(unsigned numResults) {
|
|
|
|
// If we can pack all of the results, there is no need for additional storage.
|
|
|
|
if (numResults <= static_cast<unsigned>(Kind::TrailingOpResult))
|
|
|
|
return 0;
|
|
|
|
return numResults - static_cast<unsigned>(Kind::TrailingOpResult);
|
|
|
|
}
|
|
|
|
|
2019-12-31 12:49:47 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// BlockOperand
|
|
|
|
//===----------------------------------------------------------------------===//
|
2019-12-28 12:33:53 +08:00
|
|
|
|
2019-12-31 12:49:47 +08:00
|
|
|
/// Provide the use list that is attached to the given block.
|
|
|
|
IRObjectWithUseList<BlockOperand> *BlockOperand::getUseList(Block *value) {
|
|
|
|
return value;
|
|
|
|
}
|
2019-12-28 12:33:53 +08:00
|
|
|
|
|
|
|
/// Return which operand this is in the operand list.
|
|
|
|
unsigned BlockOperand::getOperandNumber() {
|
|
|
|
return this - &getOwner()->getBlockOperands()[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// OpOperand
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2019-12-31 12:49:47 +08:00
|
|
|
/// Provide the use list that is attached to the given value.
|
|
|
|
IRObjectWithUseList<OpOperand> *OpOperand::getUseList(Value value) {
|
|
|
|
return value.getUseList();
|
|
|
|
}
|
2019-12-28 12:33:53 +08:00
|
|
|
|
|
|
|
/// Return the current value being used by this operand.
|
2019-12-31 12:49:47 +08:00
|
|
|
Value OpOperand::get() const {
|
|
|
|
return IROperand<OpOperand, detail::OpaqueValue>::get();
|
|
|
|
}
|
2019-12-28 12:33:53 +08:00
|
|
|
|
2020-01-03 01:58:16 +08:00
|
|
|
/// Set the operand to the given value.
|
|
|
|
void OpOperand::set(Value value) {
|
|
|
|
IROperand<OpOperand, detail::OpaqueValue>::set(value);
|
|
|
|
}
|
|
|
|
|
2019-12-28 12:33:53 +08:00
|
|
|
/// Return which operand this is in the operand list.
|
|
|
|
unsigned OpOperand::getOperandNumber() {
|
|
|
|
return this - &getOwner()->getOpOperands()[0];
|
|
|
|
}
|
|
|
|
|
2018-09-06 08:45:19 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2019-12-31 12:49:47 +08:00
|
|
|
// detail::OpaqueValue
|
2018-10-27 14:48:04 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2019-12-31 12:49:47 +08:00
|
|
|
/// Implicit conversion from 'Value'.
|
|
|
|
detail::OpaqueValue::OpaqueValue(Value value)
|
|
|
|
: impl(value.getAsOpaquePointer()) {}
|
2018-12-28 03:07:34 +08:00
|
|
|
|
2019-12-31 12:49:47 +08:00
|
|
|
/// Implicit conversion back to 'Value'.
|
|
|
|
detail::OpaqueValue::operator Value() const {
|
|
|
|
return Value::getFromOpaquePointer(impl);
|
2019-01-08 00:16:49 +08:00
|
|
|
}
|