Skip to content

Commit 1f9a2a5

Browse files
Rework module nesting in VM conversion. (#7873)
Introduces an explicit `vm.toplevel` attribute when setting up the nesting and then uses this as a signal that a nested module should be considered legal and left alone. The heuristic previously in use was to attempt to infer this based on parents. This turned out to be fragile if nesting a new module in an existing module (i.e. to extract a partial program and compile it without intending to create a layering issue). I was going to clean the attribute up at the end but opted to leave it there as it was a good debugging aid as I tried to figure out what was going on. Moved the one nesting test to a new nesting.mlir test case and reworked it to use a non-root based pipeline, which is more realistic for this scenario. Also, verified that what this test was doing was wrong (checks on "module" were inadvertently matching "vm.module", which was not the desired outcome). I believe the current tested behavior is desired.
1 parent 5dcb798 commit 1f9a2a5

File tree

8 files changed

+41
-25
lines changed

8 files changed

+41
-25
lines changed

iree/compiler/Dialect/HAL/Target/VMVX/test/smoketest.mlir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ stream.executable public @add_dispatch_0 {
4747
// CHECK-SAME: interface = @io,
4848
// CHECK-SAME: ordinal = 0 : index
4949
// CHECK-SAME: }
50-
// CHECK: module {
50+
// CHECK: module attributes {vm.toplevel} {
5151
// CHECK-NEXT: vm.module public @module {
5252
// CHECK-NEXT: vm.func private @add_dispatch_0(
5353
// CHECK-SAME: %[[SCRATCHPAD:.+]]: !vm.buffer, %[[CONSTANTS:.+]]: !vm.buffer,

iree/compiler/Dialect/VM/Conversion/ConversionTarget.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,25 @@ VMConversionTarget::nestModuleForConversion(mlir::ModuleOp outerModuleOp) {
2424
outerModuleOp.getBodyRegion().getBlocks().push_back(new Block());
2525
outerModuleOp.push_back(innerModuleOp);
2626
}
27+
28+
outerModuleOp->setAttr("vm.toplevel",
29+
UnitAttr::get(outerModuleOp.getContext()));
2730
return std::make_pair(outerModuleOp, innerModuleOp);
2831
}
2932

33+
// static
34+
bool VMConversionTarget::isTopLevelModule(mlir::ModuleOp moduleOp) {
35+
return !moduleOp->getParentOp() || moduleOp->hasAttr("vm.toplevel");
36+
}
37+
3038
VMConversionTarget::VMConversionTarget(MLIRContext *context)
3139
: ConversionTarget(*context) {
3240
addLegalDialect<IREE::VM::VMDialect>();
3341

3442
// NOTE: we need to allow the outermost std.module to be legal to support the
3543
// double-nesting (module { vm.module { ... } }).
36-
addDynamicallyLegalOp<mlir::ModuleOp>(+[](mlir::ModuleOp op) {
37-
return !op->getParentOp() || !isa<ModuleOp>(op->getParentOp());
38-
});
44+
addDynamicallyLegalOp<mlir::ModuleOp>(
45+
+[](mlir::ModuleOp op) { return isTopLevelModule(op); });
3946
}
4047

4148
} // namespace iree_compiler

iree/compiler/Dialect/VM/Conversion/ConversionTarget.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,14 @@ class VMConversionTarget : public ConversionTarget {
2727
// Example:
2828
// module { func @foo() { ... } }
2929
// ->
30-
// module { module { func @foo() { ... } } }
30+
// module attributes {vm.toplevel} { module { func @foo() { ... } } }
3131
static std::pair<mlir::ModuleOp, mlir::ModuleOp> nestModuleForConversion(
3232
mlir::ModuleOp outerModuleOp);
3333

34+
// Returns whether this is the outer module as setup via
35+
// nestModuleForConversion. Use for patterns which need to distinguish.
36+
static bool isTopLevelModule(mlir::ModuleOp moduleOp);
37+
3438
VMConversionTarget(MLIRContext *context);
3539
};
3640

iree/compiler/Dialect/VM/Conversion/StandardToVM/ConvertStandardToVM.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "iree/compiler/Dialect/VM/Conversion/StandardToVM/ConvertStandardToVM.h"
88

99
#include "iree/compiler/Dialect/Util/IR/UtilTypes.h"
10+
#include "iree/compiler/Dialect/VM/Conversion/ConversionTarget.h"
1011
#include "iree/compiler/Dialect/VM/Conversion/TargetOptions.h"
1112
#include "iree/compiler/Dialect/VM/Conversion/TypeConverter.h"
1213
#include "iree/compiler/Dialect/VM/IR/VMOps.h"
@@ -32,7 +33,7 @@ class ModuleOpConversion : public OpConversionPattern<ModuleOp> {
3233
ConversionPatternRewriter &rewriter) const override {
3334
// Do not attempt to convert the top level module.
3435
// This mechanism can only support rewriting non top-level modules.
35-
if (!srcOp->getParentOp() || !isa<ModuleOp>(srcOp->getParentOp())) {
36+
if (VMConversionTarget::isTopLevelModule(srcOp)) {
3637
return failure();
3738
}
3839

iree/compiler/Dialect/VM/Conversion/StandardToVM/test/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ iree_lit_test_suite(
2424
"control_flow_ops.mlir",
2525
"conversion_ops.mlir",
2626
"func_attrs.mlir",
27+
"nesting.mlir",
2728
"structural_ops.mlir",
2829
],
2930
include = ["*.mlir"],

iree/compiler/Dialect/VM/Conversion/StandardToVM/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ iree_lit_test_suite(
2121
"control_flow_ops.mlir"
2222
"conversion_ops.mlir"
2323
"func_attrs.mlir"
24+
"nesting.mlir"
2425
"structural_ops.mlir"
2526
DATA
2627
iree::tools::IreeFileCheck
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: iree-opt -split-input-file -pass-pipeline='builtin.module(test-iree-convert-std-to-vm)' %s | IreeFileCheck %s
2+
3+
// Note that checks are ambiguous between "module" and "vm.module" so we rely
4+
// on vm.module printing as `vm.module public @foo`
5+
6+
// CHECK-LABEL: module @outerBuiltinModule
7+
module @outerBuiltinModule {
8+
// CHECK-NEXT: module @innerBuiltinModule attributes {vm.toplevel}
9+
module @innerBuiltinModule attributes {vm.toplevel} {
10+
// CHECK-NEXT: vm.module public @outerVmModule
11+
module @outerVmModule {
12+
// CHECK-NEXT: vm.module public @deeplyNested
13+
module @deeplyNested {
14+
// CHECK: vm.func private @foo
15+
func @foo() {
16+
return
17+
}
18+
}
19+
}
20+
}
21+
}

iree/compiler/Dialect/VM/Conversion/StandardToVM/test/structural_ops.mlir

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -40,22 +40,3 @@ module {
4040
}
4141

4242
}
43-
44-
// -----
45-
46-
// CHECK: module
47-
module {
48-
// CHECK: module
49-
module {
50-
// CHECK: module
51-
module {
52-
// CHECK-LABEL: vm.module public @deeplyNested
53-
module @deeplyNested {
54-
// CHECK: vm.func private @foo
55-
func @foo() {
56-
return
57-
}
58-
}
59-
}
60-
}
61-
}

0 commit comments

Comments
 (0)