Skip to content

Commit 90e710b

Browse files
[mlir][scf] Add no_inline attribute to scf.execute_region (#151352)
Enabling users to explicitly specify which regions should be preserved, uncovers additional opportunities to utilize `scf.execute_region` op.
1 parent 7cdc978 commit 90e710b

File tree

3 files changed

+49
-8
lines changed

3 files changed

+49
-8
lines changed

mlir/include/mlir/Dialect/SCF/IR/SCFOps.td

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ def ExecuteRegionOp : SCF_Op<"execute_region", [
8787
be accessed inside the op. The op's region can have multiple blocks and the
8888
blocks can have multiple distinct terminators. Values returned from this op's
8989
region define the op's results.
90+
The optional 'no_inline' flag can be set to request the ExecuteRegionOp to be
91+
preserved as much as possible and not being inlined in the parent block until
92+
an explicit lowering step.
9093

9194
Example:
9295

@@ -98,6 +101,14 @@ def ExecuteRegionOp : SCF_Op<"execute_region", [
98101
}
99102
}
100103

104+
// the same as above but with no_inline attribute
105+
scf.for %i = 0 to 128 step %c1 {
106+
%y = scf.execute_region -> i32 no_inline {
107+
%x = load %A[%i] : memref<128xi32>
108+
scf.yield %x : i32
109+
}
110+
}
111+
101112
affine.for %i = 0 to 100 {
102113
"foo"() : () -> ()
103114
%v = scf.execute_region -> i64 {
@@ -119,6 +130,10 @@ def ExecuteRegionOp : SCF_Op<"execute_region", [
119130
```
120131
}];
121132

133+
let arguments = (ins
134+
UnitAttr:$no_inline
135+
);
136+
122137
let results = (outs Variadic<AnyType>);
123138

124139
let regions = (region AnyRegion:$region);

mlir/lib/Dialect/SCF/IR/SCF.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,9 @@ ParseResult ExecuteRegionOp::parse(OpAsmParser &parser,
137137
if (parser.parseOptionalArrowTypeList(result.types))
138138
return failure();
139139

140+
if (succeeded(parser.parseOptionalKeyword("no_inline")))
141+
result.addAttribute("no_inline", parser.getBuilder().getUnitAttr());
142+
140143
// Introduce the body region and parse it.
141144
Region *body = result.addRegion();
142145
if (parser.parseRegion(*body, /*arguments=*/{}, /*argTypes=*/{}) ||
@@ -148,8 +151,9 @@ ParseResult ExecuteRegionOp::parse(OpAsmParser &parser,
148151

149152
void ExecuteRegionOp::print(OpAsmPrinter &p) {
150153
p.printOptionalArrowTypeList(getResultTypes());
151-
152154
p << ' ';
155+
if (getNoInline())
156+
p << "no_inline ";
153157
p.printRegion(getRegion(),
154158
/*printEntryBlockArgs=*/false,
155159
/*printBlockTerminators=*/true);
@@ -184,7 +188,7 @@ struct SingleBlockExecuteInliner : public OpRewritePattern<ExecuteRegionOp> {
184188

185189
LogicalResult matchAndRewrite(ExecuteRegionOp op,
186190
PatternRewriter &rewriter) const override {
187-
if (!op.getRegion().hasOneBlock())
191+
if (!op.getRegion().hasOneBlock() || op.getNoInline())
188192
return failure();
189193
replaceOpWithRegion(rewriter, op, op.getRegion());
190194
return success();

mlir/test/Dialect/SCF/canonicalize.mlir

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,8 +1440,8 @@ func.func @propagate_into_execute_region() {
14401440

14411441
// -----
14421442

1443-
// CHECK-LABEL: func @execute_region_elim
1444-
func.func @execute_region_elim() {
1443+
// CHECK-LABEL: func @execute_region_inline
1444+
func.func @execute_region_inline() {
14451445
affine.for %i = 0 to 100 {
14461446
"test.foo"() : () -> ()
14471447
%v = scf.execute_region -> i64 {
@@ -1461,8 +1461,30 @@ func.func @execute_region_elim() {
14611461

14621462
// -----
14631463

1464-
// CHECK-LABEL: func @func_execute_region_elim
1465-
func.func @func_execute_region_elim() {
1464+
// CHECK-LABEL: func @execute_region_no_inline
1465+
func.func @execute_region_no_inline() {
1466+
affine.for %i = 0 to 100 {
1467+
"test.foo"() : () -> ()
1468+
%v = scf.execute_region -> i64 no_inline {
1469+
%x = "test.val"() : () -> i64
1470+
scf.yield %x : i64
1471+
}
1472+
"test.bar"(%v) : (i64) -> ()
1473+
}
1474+
return
1475+
}
1476+
1477+
// CHECK-NEXT: affine.for %arg0 = 0 to 100 {
1478+
// CHECK-NEXT: "test.foo"() : () -> ()
1479+
// CHECK-NEXT: scf.execute_region
1480+
// CHECK-NEXT: %[[VAL:.*]] = "test.val"() : () -> i64
1481+
// CHECK-NEXT: scf.yield %[[VAL]] : i64
1482+
// CHECK-NEXT: }
1483+
1484+
// -----
1485+
1486+
// CHECK-LABEL: func @func_execute_region_inline
1487+
func.func @func_execute_region_inline() {
14661488
"test.foo"() : () -> ()
14671489
%v = scf.execute_region -> i64 {
14681490
%c = "test.cmp"() : () -> i1
@@ -1496,8 +1518,8 @@ func.func @func_execute_region_elim() {
14961518

14971519
// -----
14981520

1499-
// CHECK-LABEL: func @func_execute_region_elim_multi_yield
1500-
func.func @func_execute_region_elim_multi_yield() {
1521+
// CHECK-LABEL: func @func_execute_region_inline_multi_yield
1522+
func.func @func_execute_region_inline_multi_yield() {
15011523
"test.foo"() : () -> ()
15021524
%v = scf.execute_region -> i64 {
15031525
%c = "test.cmp"() : () -> i1

0 commit comments

Comments
 (0)