mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-28 16:56:09 +00:00

The MLIR classes Type/Attribute/Operation/Op/Value support cast/dyn_cast/isa/dyn_cast_or_null functionality through llvm's doCast functionality in addition to defining methods with the same name. This change begins the migration of uses of the method to the corresponding function call as has been decided as more consistent. Note that there still exist classes that only define methods directly, such as AffineExpr, and this does not include work currently to support a functional cast/isa call. Context: - https://mlir.llvm.org/deprecation/ at "Use the free function variants for dyn_cast/cast/isa/…" - Original discussion at https://discourse.llvm.org/t/preferred-casting-style-going-forward/68443 Implementation: This patch updates all remaining uses of the deprecated functionality in mlir/. This was done with clang-tidy as described below and further modifications to GPUBase.td and OpenMPOpsInterfaces.td. Steps are described per line, as comments are removed by git: 0. Retrieve the change from the following to build clang-tidy with an additional check: main...tpopp:llvm-project:tidy-cast-check 1. Build clang-tidy 2. Run clang-tidy over your entire codebase while disabling all checks and enabling the one relevant one. Run on all header files also. 3. Delete .inc files that were also modified, so the next build rebuilds them to a pure state. ``` ninja -C $BUILD_DIR clang-tidy run-clang-tidy -clang-tidy-binary=$BUILD_DIR/bin/clang-tidy -checks='-*,misc-cast-functions'\ -header-filter=mlir/ mlir/* -fix rm -rf $BUILD_DIR/tools/mlir/**/*.inc ``` Differential Revision: https://reviews.llvm.org/D151542
220 lines
8.2 KiB
C++
220 lines
8.2 KiB
C++
//===- Value.cpp - MLIR Value Classes -------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "mlir/IR/Value.h"
|
|
#include "mlir/IR/Block.h"
|
|
#include "mlir/IR/BuiltinTypes.h"
|
|
#include "mlir/IR/Operation.h"
|
|
#include "llvm/ADT/SmallPtrSet.h"
|
|
|
|
using namespace mlir;
|
|
using namespace mlir::detail;
|
|
|
|
/// If this value is the result of an Operation, return the operation that
|
|
/// defines it.
|
|
Operation *Value::getDefiningOp() const {
|
|
if (auto result = llvm::dyn_cast<OpResult>(*this))
|
|
return result.getOwner();
|
|
return nullptr;
|
|
}
|
|
|
|
Location Value::getLoc() const {
|
|
if (auto *op = getDefiningOp())
|
|
return op->getLoc();
|
|
|
|
return llvm::cast<BlockArgument>(*this).getLoc();
|
|
}
|
|
|
|
void Value::setLoc(Location loc) {
|
|
if (auto *op = getDefiningOp())
|
|
return op->setLoc(loc);
|
|
|
|
return llvm::cast<BlockArgument>(*this).setLoc(loc);
|
|
}
|
|
|
|
/// Return the Region in which this Value is defined.
|
|
Region *Value::getParentRegion() {
|
|
if (auto *op = getDefiningOp())
|
|
return op->getParentRegion();
|
|
return llvm::cast<BlockArgument>(*this).getOwner()->getParent();
|
|
}
|
|
|
|
/// Return the Block in which this Value is defined.
|
|
Block *Value::getParentBlock() {
|
|
if (Operation *op = getDefiningOp())
|
|
return op->getBlock();
|
|
return llvm::cast<BlockArgument>(*this).getOwner();
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Value::UseLists
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// 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 (OpOperand &use : llvm::make_early_inc_range(getUses())) {
|
|
if (exceptions.count(use.getOwner()) == 0)
|
|
use.set(newValue);
|
|
}
|
|
}
|
|
|
|
/// Replace all uses of 'this' value with 'newValue', updating anything in the
|
|
/// IR that uses 'this' to use the other value instead except if the user is
|
|
/// 'exceptedUser'.
|
|
void Value::replaceAllUsesExcept(Value newValue,
|
|
Operation *exceptedUser) const {
|
|
for (OpOperand &use : llvm::make_early_inc_range(getUses())) {
|
|
if (use.getOwner() != exceptedUser)
|
|
use.set(newValue);
|
|
}
|
|
}
|
|
|
|
/// 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);
|
|
}
|
|
|
|
/// 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;
|
|
});
|
|
}
|
|
|
|
/// Shuffles the use-list order according to the provided indices.
|
|
void Value::shuffleUseList(ArrayRef<unsigned> indices) {
|
|
getImpl()->shuffleUseList(indices);
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// OpResult
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// Returns the parent operation of this trailing result.
|
|
Operation *OpResultImpl::getOwner() const {
|
|
// We need to do some arithmetic to get the operation pointer. Results are
|
|
// stored in reverse order before the operation, so move the trailing owner up
|
|
// to the start of the array. A rough diagram of the memory layout is:
|
|
//
|
|
// | Out-of-Line results | Inline results | Operation |
|
|
//
|
|
// Given that the results are reverse order we use the result number to know
|
|
// how far to jump to get to the operation. So if we are currently the 0th
|
|
// result, the layout would be:
|
|
//
|
|
// | Inline result 0 | Operation
|
|
//
|
|
// ^-- To get the base address of the operation, we add the result count + 1.
|
|
if (const auto *result = dyn_cast<InlineOpResult>(this)) {
|
|
result += result->getResultNumber() + 1;
|
|
return reinterpret_cast<Operation *>(const_cast<InlineOpResult *>(result));
|
|
}
|
|
|
|
// Out-of-line results are stored in an array just before the inline results.
|
|
const OutOfLineOpResult *outOfLineIt = (const OutOfLineOpResult *)(this);
|
|
outOfLineIt += (outOfLineIt->outOfLineIndex + 1);
|
|
|
|
// Move the owner past the inline results to get to the operation.
|
|
const auto *inlineIt = reinterpret_cast<const InlineOpResult *>(outOfLineIt);
|
|
inlineIt += getMaxInlineResults();
|
|
return reinterpret_cast<Operation *>(const_cast<InlineOpResult *>(inlineIt));
|
|
}
|
|
|
|
OpResultImpl *OpResultImpl::getNextResultAtOffset(intptr_t offset) {
|
|
if (offset == 0)
|
|
return this;
|
|
// We need to do some arithmetic to get the next result given that results are
|
|
// in reverse order, and that we need to account for the different types of
|
|
// results. As a reminder, the rough diagram of the memory layout is:
|
|
//
|
|
// | Out-of-Line results | Inline results | Operation |
|
|
//
|
|
// So an example operation with two results would look something like:
|
|
//
|
|
// | Inline result 1 | Inline result 0 | Operation |
|
|
//
|
|
|
|
// Handle the case where this result is an inline result.
|
|
OpResultImpl *result = this;
|
|
if (auto *inlineResult = dyn_cast<InlineOpResult>(this)) {
|
|
// Check to see how many results there are after this one before the start
|
|
// of the out-of-line results. If the desired offset is less than the number
|
|
// remaining, we can directly use the offset from the current result
|
|
// pointer. The following diagrams highlight the two situations.
|
|
//
|
|
// | Out-of-Line results | Inline results | Operation |
|
|
// ^- Say we are here.
|
|
// ^- If our destination is here, we can use the
|
|
// offset directly.
|
|
//
|
|
intptr_t leftBeforeTrailing =
|
|
getMaxInlineResults() - inlineResult->getResultNumber() - 1;
|
|
if (leftBeforeTrailing >= offset)
|
|
return inlineResult - offset;
|
|
|
|
// Otherwise, adjust the current result pointer to the end (start in memory)
|
|
// of the inline result array.
|
|
//
|
|
// | Out-of-Line results | Inline results | Operation |
|
|
// ^- Say we are here.
|
|
// ^- If our destination is here, we need to first jump to
|
|
// the end (start in memory) of the inline result array.
|
|
//
|
|
result = inlineResult - leftBeforeTrailing;
|
|
offset -= leftBeforeTrailing;
|
|
}
|
|
|
|
// If we land here, the current result is an out-of-line result and we can
|
|
// offset directly.
|
|
return reinterpret_cast<OutOfLineOpResult *>(result) - offset;
|
|
}
|
|
|
|
/// Given a number of operation results, returns the number that need to be
|
|
/// stored inline.
|
|
unsigned OpResult::getNumInline(unsigned numResults) {
|
|
return std::min(numResults, OpResultImpl::getMaxInlineResults());
|
|
}
|
|
|
|
/// 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.
|
|
unsigned maxInline = OpResultImpl::getMaxInlineResults();
|
|
return numResults <= maxInline ? 0 : numResults - maxInline;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// BlockOperand
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// Provide the use list that is attached to the given block.
|
|
IRObjectWithUseList<BlockOperand> *BlockOperand::getUseList(Block *value) {
|
|
return value;
|
|
}
|
|
|
|
/// Return which operand this is in the operand list.
|
|
unsigned BlockOperand::getOperandNumber() {
|
|
return this - &getOwner()->getBlockOperands()[0];
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// OpOperand
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// Return which operand this is in the operand list.
|
|
unsigned OpOperand::getOperandNumber() {
|
|
return this - &getOwner()->getOpOperands()[0];
|
|
}
|