summaryrefslogtreecommitdiff
path: root/mlir/lib/Interfaces/ControlFlowInterfaces.cpp
diff options
context:
space:
mode:
authorMarkus Böck <markus.boeck02@gmail.com>2022-04-08 08:17:36 +0200
committerMarkus Böck <markus.boeck02@gmail.com>2022-04-08 08:28:16 +0200
commit0c789db541c236abf47265331a2f2b0945aa7b93 (patch)
treefe1b58d9c1f48fb2424eef76e0f8667f360f43c3 /mlir/lib/Interfaces/ControlFlowInterfaces.cpp
parent795b07f5498c7e5783237418f34d7ea69e801f87 (diff)
[mlir] Add support for operation-produced successor arguments in BranchOpInterface
This patch revamps the BranchOpInterface a bit and allows a proper implementation of what was previously `getMutableSuccessorOperands` for operations, which internally produce arguments to some of the block arguments. A motivating example for this would be an invoke op with a error handling path: ``` invoke %function(%0) label ^success ^error(%1 : i32) ^error(%e: !error, %arg0 : i32): ... ``` The advantages of this are that any users of `BranchOpInterface` can still argue over remaining block argument operands (such as `%1` in the example above), as well as make use of the modifying capabilities to add more operands, erase an operand etc. The way this patch implements that functionality is via a new class called `SuccessorOperands`, which is now returned by `getSuccessorOperands`. It basically contains an `unsigned` denoting how many operator produced operands exist, as well as a `MutableOperandRange`, which are the usual forwarded operands we are used to. The produced operands are assumed to the first few block arguments, followed by the forwarded operands afterwards. The role of `SuccessorOperands` is to provide various utility functions to modify and query the successor arguments from a `BranchOpInterface`. Differential Revision: https://reviews.llvm.org/D123062
Diffstat (limited to 'mlir/lib/Interfaces/ControlFlowInterfaces.cpp')
-rw-r--r--mlir/lib/Interfaces/ControlFlowInterfaces.cpp33
1 files changed, 20 insertions, 13 deletions
diff --git a/mlir/lib/Interfaces/ControlFlowInterfaces.cpp b/mlir/lib/Interfaces/ControlFlowInterfaces.cpp
index 02845c011472..69ed30ae7bdd 100644
--- a/mlir/lib/Interfaces/ControlFlowInterfaces.cpp
+++ b/mlir/lib/Interfaces/ControlFlowInterfaces.cpp
@@ -18,6 +18,14 @@ using namespace mlir;
#include "mlir/Interfaces/ControlFlowInterfaces.cpp.inc"
+SuccessorOperands::SuccessorOperands(MutableOperandRange forwardedOperands)
+ : producedOperandCount(0), forwardedOperands(forwardedOperands) {}
+
+SuccessorOperands::SuccessorOperands(unsigned int producedOperandCount,
+ MutableOperandRange forwardedOperands)
+ : producedOperandCount(producedOperandCount),
+ forwardedOperands(std::move(forwardedOperands)) {}
+
//===----------------------------------------------------------------------===//
// BranchOpInterface
//===----------------------------------------------------------------------===//
@@ -26,32 +34,31 @@ using namespace mlir;
/// successor if 'operandIndex' is within the range of 'operands', or None if
/// `operandIndex` isn't a successor operand index.
Optional<BlockArgument>
-detail::getBranchSuccessorArgument(Optional<OperandRange> operands,
+detail::getBranchSuccessorArgument(const SuccessorOperands &operands,
unsigned operandIndex, Block *successor) {
+ OperandRange forwardedOperands = operands.getForwardedOperands();
// Check that the operands are valid.
- if (!operands || operands->empty())
+ if (forwardedOperands.empty())
return llvm::None;
// Check to ensure that this operand is within the range.
- unsigned operandsStart = operands->getBeginOperandIndex();
+ unsigned operandsStart = forwardedOperands.getBeginOperandIndex();
if (operandIndex < operandsStart ||
- operandIndex >= (operandsStart + operands->size()))
+ operandIndex >= (operandsStart + forwardedOperands.size()))
return llvm::None;
// Index the successor.
- unsigned argIndex = operandIndex - operandsStart;
+ unsigned argIndex =
+ operands.getProducedOperandCount() + operandIndex - operandsStart;
return successor->getArgument(argIndex);
}
/// Verify that the given operands match those of the given successor block.
LogicalResult
detail::verifyBranchSuccessorOperands(Operation *op, unsigned succNo,
- Optional<OperandRange> operands) {
- if (!operands)
- return success();
-
+ const SuccessorOperands &operands) {
// Check the count.
- unsigned operandCount = operands->size();
+ unsigned operandCount = operands.size();
Block *destBB = op->getSuccessor(succNo);
if (operandCount != destBB->getNumArguments())
return op->emitError() << "branch has " << operandCount
@@ -60,10 +67,10 @@ detail::verifyBranchSuccessorOperands(Operation *op, unsigned succNo,
<< destBB->getNumArguments();
// Check the types.
- auto operandIt = operands->begin();
- for (unsigned i = 0; i != operandCount; ++i, ++operandIt) {
+ for (unsigned i = operands.getProducedOperandCount(); i != operandCount;
+ ++i) {
if (!cast<BranchOpInterface>(op).areTypesCompatible(
- (*operandIt).getType(), destBB->getArgument(i).getType()))
+ operands[i].getType(), destBB->getArgument(i).getType()))
return op->emitError() << "type mismatch for bb argument #" << i
<< " of successor #" << succNo;
}