Skip to content

Commit fb45a63

Browse files
[mlir][transf] Traits and interf. of alternatives, foreach, and yield.
This PR revisits the traits and interfaces of the `alternatives`, `foreach`, and `yield`ops. First, it adds the `ReturnLike` trait to `transform.yield`. This is required in the one-shot bufferization pass since the merging of llvm#110332, which analyses any `FunctionOpInterface` and expects them to have a `ReturnLike` terminator. This uncovered problems with `alternatives` and `foreach`, which implemented the `BranchRegionOpInterface`. That interface verifies that the operands and results passed across the control flow edges from the parent op to its regions and back are equal (or compatible). Which results are passed back from regions to the parent op depend on the terminator and/or whether it is `ReturnLike`. Making `yield` a `ReturnLike` op, those checks fail without other changes. We explored and rejected the possibility to fix the implementation of `RegionBranchOpInterface` of the two concerned ops in llvm#111408. The problem is that the interface expects the result passed from a region to the parent op to *be* the result of the op, whereas in the two ops they *contribute* to the result: in `alternatives` only the operand yielded from one of the regions becomes the result whereas the others are ignored, and in `foreach` the operands from all iterations are fused into a new value that becomes the result of the op. Signed-off-by: Ingo Müller <[email protected]>
1 parent d4c1789 commit fb45a63

File tree

2 files changed

+7
-73
lines changed

2 files changed

+7
-73
lines changed

mlir/include/mlir/Dialect/Transform/IR/TransformOps.td

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,7 @@ include "mlir/Dialect/Transform/IR/TransformDialect.td"
2424
include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td"
2525

2626
def AlternativesOp : TransformDialectOp<"alternatives",
27-
[DeclareOpInterfaceMethods<RegionBranchOpInterface,
28-
["getEntrySuccessorOperands", "getSuccessorRegions",
29-
"getRegionInvocationBounds"]>,
30-
DeclareOpInterfaceMethods<TransformOpInterface>,
27+
[DeclareOpInterfaceMethods<TransformOpInterface>,
3128
DeclareOpInterfaceMethods<MemoryEffectsOpInterface>,
3229
IsolatedFromAbove, PossibleTopLevelTransformOpTrait,
3330
SingleBlockImplicitTerminator<"::mlir::transform::YieldOp">]> {
@@ -37,8 +34,8 @@ def AlternativesOp : TransformDialectOp<"alternatives",
3734
sequence of transform operations to be applied to the same payload IR. The
3835
regions are visited in order of appearance, and transforms in them are
3936
applied in their respective order of appearance. If one of these transforms
40-
fails to apply, the remaining ops in the same region are skipped an the next
41-
region is attempted. If all transformations in a region succeed, the
37+
fails to apply, the remaining ops in the same region are skipped and the
38+
next region is attempted. If all transformations in a region succeed, the
4239
remaining regions are skipped and the entire "alternatives" transformation
4340
succeeds. If all regions contained a failing transformation, the entire
4441
"alternatives" transformation fails.
@@ -610,8 +607,6 @@ def ForeachMatchOp : TransformDialectOp<"foreach_match", [
610607
def ForeachOp : TransformDialectOp<"foreach",
611608
[DeclareOpInterfaceMethods<TransformOpInterface>,
612609
DeclareOpInterfaceMethods<MemoryEffectsOpInterface>,
613-
DeclareOpInterfaceMethods<RegionBranchOpInterface, [
614-
"getSuccessorRegions", "getEntrySuccessorOperands"]>,
615610
SingleBlockImplicitTerminator<"::mlir::transform::YieldOp">
616611
]> {
617612
let summary = "Executes the body for each element of the payload";
@@ -1358,7 +1353,8 @@ def VerifyOp : TransformDialectOp<"verify",
13581353
}
13591354

13601355
def YieldOp : TransformDialectOp<"yield",
1361-
[Terminator, DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> {
1356+
[Terminator, ReturnLike,
1357+
DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> {
13621358
let summary = "Yields operation handles from a transform IR region";
13631359
let description = [{
13641360
This terminator operation yields operation handles from regions of the

mlir/lib/Dialect/Transform/IR/TransformOps.cpp

Lines changed: 2 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -94,38 +94,6 @@ ensurePayloadIsSeparateFromTransform(transform::TransformOpInterface transform,
9494
// AlternativesOp
9595
//===----------------------------------------------------------------------===//
9696

97-
OperandRange
98-
transform::AlternativesOp::getEntrySuccessorOperands(RegionBranchPoint point) {
99-
if (!point.isParent() && getOperation()->getNumOperands() == 1)
100-
return getOperation()->getOperands();
101-
return OperandRange(getOperation()->operand_end(),
102-
getOperation()->operand_end());
103-
}
104-
105-
void transform::AlternativesOp::getSuccessorRegions(
106-
RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> &regions) {
107-
for (Region &alternative : llvm::drop_begin(
108-
getAlternatives(),
109-
point.isParent() ? 0
110-
: point.getRegionOrNull()->getRegionNumber() + 1)) {
111-
regions.emplace_back(&alternative, !getOperands().empty()
112-
? alternative.getArguments()
113-
: Block::BlockArgListType());
114-
}
115-
if (!point.isParent())
116-
regions.emplace_back(getOperation()->getResults());
117-
}
118-
119-
void transform::AlternativesOp::getRegionInvocationBounds(
120-
ArrayRef<Attribute> operands, SmallVectorImpl<InvocationBounds> &bounds) {
121-
(void)operands;
122-
// The region corresponding to the first alternative is always executed, the
123-
// remaining may or may not be executed.
124-
bounds.reserve(getNumRegions());
125-
bounds.emplace_back(1, 1);
126-
bounds.resize(getNumRegions(), InvocationBounds(0, 1));
127-
}
128-
12997
static void forwardEmptyOperands(Block *block, transform::TransformState &state,
13098
transform::TransformResults &results) {
13199
for (const auto &res : block->getParentOp()->getOpResults())
@@ -1500,28 +1468,6 @@ void transform::ForeachOp::getEffects(
15001468
producesHandle(getOperation()->getOpResults(), effects);
15011469
}
15021470

1503-
void transform::ForeachOp::getSuccessorRegions(
1504-
RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> &regions) {
1505-
Region *bodyRegion = &getBody();
1506-
if (point.isParent()) {
1507-
regions.emplace_back(bodyRegion, bodyRegion->getArguments());
1508-
return;
1509-
}
1510-
1511-
// Branch back to the region or the parent.
1512-
assert(point == getBody() && "unexpected region index");
1513-
regions.emplace_back(bodyRegion, bodyRegion->getArguments());
1514-
regions.emplace_back();
1515-
}
1516-
1517-
OperandRange
1518-
transform::ForeachOp::getEntrySuccessorOperands(RegionBranchPoint point) {
1519-
// Each block argument handle is mapped to a subset (one op to be precise)
1520-
// of the payload of the corresponding `targets` operand of ForeachOp.
1521-
assert(point == getBody() && "unexpected region index");
1522-
return getOperation()->getOperands();
1523-
}
1524-
15251471
transform::YieldOp transform::ForeachOp::getYieldOp() {
15261472
return cast<transform::YieldOp>(getBody().front().getTerminator());
15271473
}
@@ -2702,16 +2648,8 @@ transform::SequenceOp::getEntrySuccessorOperands(RegionBranchPoint point) {
27022648

27032649
void transform::SequenceOp::getSuccessorRegions(
27042650
RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> &regions) {
2705-
if (point.isParent()) {
2706-
Region *bodyRegion = &getBody();
2707-
regions.emplace_back(bodyRegion, getNumOperands() != 0
2708-
? bodyRegion->getArguments()
2709-
: Block::BlockArgListType());
2710-
return;
2711-
}
2712-
2713-
assert(point == getBody() && "unexpected region index");
2714-
regions.emplace_back(getOperation()->getResults());
2651+
if (point.getRegionOrNull() == &getBody())
2652+
regions.emplace_back(getResults());
27152653
}
27162654

27172655
void transform::SequenceOp::getRegionInvocationBounds(

0 commit comments

Comments
 (0)