diff options
| author | Markus Böck <markus.boeck02@gmail.com> | 2022-04-08 08:17:36 +0200 |
|---|---|---|
| committer | Markus Böck <markus.boeck02@gmail.com> | 2022-04-08 08:28:16 +0200 |
| commit | 0c789db541c236abf47265331a2f2b0945aa7b93 (patch) | |
| tree | fe1b58d9c1f48fb2424eef76e0f8667f360f43c3 /mlir/lib/Interfaces/ControlFlowInterfaces.cpp | |
| parent | 795b07f5498c7e5783237418f34d7ea69e801f87 (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.cpp | 33 |
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; } |
