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"
|
2020-04-20 15:17:45 +08:00
|
|
|
#include "llvm/ADT/SmallPtrSet.h"
|
2020-04-24 07:23:34 +08:00
|
|
|
|
2018-08-02 01:43:18 +08:00
|
|
|
using namespace mlir;
|
2020-04-24 07:23:34 +08:00
|
|
|
using namespace mlir::detail;
|
2018-08-02 01:43:18 +08:00
|
|
|
|
2020-01-03 06:28:37 +08:00
|
|
|
/// Construct a value.
|
2020-04-24 07:23:34 +08:00
|
|
|
Value::Value(BlockArgumentImpl *impl)
|
2020-01-03 06:28:37 +08:00
|
|
|
: 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;
|
|
|
|
}
|
|
|
|
|
2020-04-24 07:23:34 +08:00
|
|
|
// If we can't pack the result directly, grab the use list from the parent op.
|
|
|
|
unsigned trailingNo = resultNo - OpResult::getMaxInlineResults();
|
|
|
|
ownerAndKind = {op->getTrailingResult(trailingNo), Kind::TrailingOpResult};
|
2020-01-03 06:28:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// 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();
|
[mlir][DialectConversion] Enable deeper integration of type conversions
This revision adds support for much deeper type conversion integration into the conversion process, and enables auto-generating cast operations when necessary. Type conversions are now largely automatically managed by the conversion infra when using a ConversionPattern with a provided TypeConverter. This removes the need for patterns to do type cast wrapping themselves and moves the burden to the infra. This makes it much easier to perform partial lowerings when type conversions are involved, as any lingering type conversions will be automatically resolved/legalized by the conversion infra.
To support this new integration, a few changes have been made to the type materialization API on TypeConverter. Materialization has been split into three separate categories:
* Argument Materialization: This type of materialization is used when converting the type of block arguments when calling `convertRegionTypes`. This is useful for contextually inserting additional conversion operations when converting a block argument type, such as when converting the types of a function signature.
* Source Materialization: This type of materialization is used to convert a legal type of the converter into a non-legal type, generally a source type. This may be called when uses of a non-legal type persist after the conversion process has finished.
* Target Materialization: This type of materialization is used to convert a non-legal, or source, type into a legal, or target, type. This type of materialization is used when applying a pattern on an operation, but the types of the operands have not yet been converted.
Differential Revision: https://reviews.llvm.org/D82831
2020-07-24 10:38:30 +08:00
|
|
|
|
|
|
|
// Use the location of the parent operation if this is a block argument.
|
|
|
|
// TODO: Should we just add locations to block arguments?
|
|
|
|
Operation *parentOp = cast<BlockArgument>().getOwner()->getParentOp();
|
|
|
|
return parentOp ? parentOp->getLoc() : UnknownLoc::get(getContext());
|
2019-04-02 01:42:34 +08:00
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2020-05-05 10:54:36 +08:00
|
|
|
/// Return the Block in which this Value is defined.
|
|
|
|
Block *Value::getParentBlock() {
|
|
|
|
if (Operation *op = getDefiningOp())
|
|
|
|
return op->getBlock();
|
|
|
|
return cast<BlockArgument>().getOwner();
|
|
|
|
}
|
|
|
|
|
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();
|
2020-04-24 07:23:34 +08:00
|
|
|
if (getKind() != Kind::TrailingOpResult) {
|
|
|
|
OpResult result = cast<OpResult>();
|
|
|
|
return result.getOwner()->getInlineResult(result.getResultNumber());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise this is a trailing operation result, which contains a use list.
|
|
|
|
return reinterpret_cast<TrailingOpResult *>(ownerAndKind.getPointer());
|
2019-12-31 12:49:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Drop all uses of this object from their respective owners.
|
2020-04-24 07:23:34 +08:00
|
|
|
void Value::dropAllUses() const { return getUseList()->dropAllUses(); }
|
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 {
|
2020-04-24 07:23:34 +08:00
|
|
|
return getUseList()->replaceAllUsesWith(newValue);
|
2019-12-31 12:49:47 +08:00
|
|
|
}
|
|
|
|
|
2020-04-20 15:17:45 +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 except if the user is
|
|
|
|
/// listed in 'exceptions' .
|
|
|
|
void Value::replaceAllUsesExcept(
|
|
|
|
Value newValue, const SmallPtrSetImpl<Operation *> &exceptions) const {
|
|
|
|
for (auto &use : llvm::make_early_inc_range(getUses())) {
|
|
|
|
if (exceptions.count(use.getOwner()) == 0)
|
|
|
|
use.set(newValue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-25 03:25:05 +08:00
|
|
|
/// Replace all uses of 'this' value with 'newValue' if the given callback
|
|
|
|
/// returns true.
|
|
|
|
void Value::replaceUsesWithIf(Value newValue,
|
|
|
|
function_ref<bool(OpOperand &)> shouldReplace) {
|
|
|
|
for (OpOperand &use : llvm::make_early_inc_range(getUses()))
|
|
|
|
if (shouldReplace(use))
|
|
|
|
use.set(newValue);
|
|
|
|
}
|
|
|
|
|
2020-05-05 10:54:36 +08:00
|
|
|
/// Returns true if the value is used outside of the given block.
|
|
|
|
bool Value::isUsedOutsideOfBlock(Block *block) {
|
|
|
|
return llvm::any_of(getUsers(), [block](Operation *user) {
|
|
|
|
return user->getBlock() != block;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-12-31 12:49:47 +08:00
|
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
// Uses
|
|
|
|
|
|
|
|
auto Value::use_begin() const -> use_iterator {
|
2020-04-24 07:23:34 +08:00
|
|
|
return getUseList()->use_begin();
|
2019-12-31 12:49:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns true if this value has exactly one use.
|
2020-04-24 07:23:34 +08:00
|
|
|
bool Value::hasOneUse() const { return getUseList()->hasOneUse(); }
|
2019-12-31 12:49:47 +08:00
|
|
|
|
|
|
|
/// Returns true if this value has no uses.
|
2020-04-24 07:23:34 +08:00
|
|
|
bool Value::use_empty() const { return getUseList()->use_empty(); }
|
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.
|
2020-04-24 07:23:34 +08:00
|
|
|
void *owner = ownerAndKind.getPointer();
|
2020-01-03 06:28:37 +08:00
|
|
|
if (LLVM_LIKELY(getKind() != Kind::TrailingOpResult))
|
2020-04-24 07:23:34 +08:00
|
|
|
return static_cast<Operation *>(owner);
|
2020-01-03 06:28:37 +08:00
|
|
|
|
2020-04-24 07:23:34 +08:00
|
|
|
// Otherwise, query the trailing result for the owner.
|
|
|
|
return static_cast<TrailingOpResult *>(owner)->getOwner();
|
2020-01-03 06:28:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// 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());
|
2020-04-24 07:23:34 +08:00
|
|
|
// Otherwise, query the trailing result.
|
|
|
|
auto *result = static_cast<TrailingOpResult *>(ownerAndKind.getPointer());
|
|
|
|
return result->getResultNumber();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Given a number of operation results, returns the number that need to be
|
|
|
|
/// stored inline.
|
|
|
|
unsigned OpResult::getNumInline(unsigned numResults) {
|
|
|
|
return std::min(numResults, getMaxInlineResults());
|
2020-01-03 06:28:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// 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.
|
2020-04-24 07:23:34 +08:00
|
|
|
unsigned maxInline = getMaxInlineResults();
|
|
|
|
return numResults <= maxInline ? 0 : numResults - maxInline;
|
2020-01-03 06:28:37 +08:00
|
|
|
}
|
|
|
|
|
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 {
|
2020-04-24 07:23:34 +08:00
|
|
|
return IROperand<OpOperand, OpaqueValue>::get();
|
2019-12-31 12:49:47 +08:00
|
|
|
}
|
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) {
|
2020-04-24 07:23:34 +08:00
|
|
|
IROperand<OpOperand, OpaqueValue>::set(value);
|
2020-01-03 01:58:16 +08:00
|
|
|
}
|
|
|
|
|
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
|
|
|
//===----------------------------------------------------------------------===//
|
2020-04-24 07:23:34 +08:00
|
|
|
// OpaqueValue
|
2018-10-27 14:48:04 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2019-12-31 12:49:47 +08:00
|
|
|
/// Implicit conversion from 'Value'.
|
2020-04-24 07:23:34 +08:00
|
|
|
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'.
|
2020-04-24 07:23:34 +08:00
|
|
|
OpaqueValue::operator Value() const {
|
2019-12-31 12:49:47 +08:00
|
|
|
return Value::getFromOpaquePointer(impl);
|
2019-01-08 00:16:49 +08:00
|
|
|
}
|