Skip to content

[mlir][Symbol] Add verification that symbol's parent is a SymbolTable #80590

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions mlir/include/mlir/IR/SymbolInterfaces.td
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,11 @@ def Symbol : OpInterface<"SymbolOpInterface"> {
if (concreteOp.isDeclaration() && concreteOp.isPublic())
return concreteOp.emitOpError("symbol declaration cannot have public "
"visibility");
auto parent = $_op->getParentOp();
if (parent && !parent->hasTrait<OpTrait::SymbolTable>() && parent->isRegistered()) {
return concreteOp.emitOpError("symbol's parent must have the SymbolTable "
"trait");
}
return success();
}];

Expand Down
2 changes: 1 addition & 1 deletion mlir/test/Dialect/LLVMIR/global.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ llvm.mlir.global internal constant @constant(37.0) : !llvm.label
// -----

func.func @foo() {
// expected-error @+1 {{must appear at the module level}}
// expected-error @+1 {{op symbol's parent must have the SymbolTable trait}}
llvm.mlir.global internal @bar(42) : i32

return
Expand Down
6 changes: 4 additions & 2 deletions mlir/test/Dialect/Linalg/transform-op-replace.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
%0 = transform.structured.match ops{["func.func"]} in %arg1 : (!transform.any_op) -> !transform.any_op
transform.structured.replace %0 {
func.func @foo() {
"dummy_op"() : () -> ()
builtin.module {
func.func @foo() {
"dummy_op"() : () -> ()
}
}
} : (!transform.any_op) -> !transform.any_op
transform.yield
Expand Down
3 changes: 1 addition & 2 deletions mlir/test/Dialect/Transform/ops-invalid.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -433,10 +433,9 @@ module {
// -----

module attributes { transform.with_named_sequence} {
// expected-note @below {{ancestor transform op}}
transform.sequence failures(suppress) {
^bb0(%arg0: !transform.any_op):
// expected-error @below {{cannot be defined inside another transform op}}
// expected-error @below {{op symbol's parent must have the SymbolTable trai}}
transform.named_sequence @nested() {
transform.yield
}
Expand Down
4 changes: 2 additions & 2 deletions mlir/test/IR/invalid-func-op.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func.func @func_op() {
// -----

func.func @func_op() {
// expected-error@+1 {{entry block must have 1 arguments to match function signature}}
// expected-error@+1 {{op symbol's parent must have the SymbolTable trait}}
func.func @mixed_named_arguments(f32) {
^entry:
return
Expand All @@ -42,7 +42,7 @@ func.func @func_op() {
// -----

func.func @func_op() {
// expected-error@+1 {{type of entry block argument #0('i32') must match the type of the corresponding argument in function signature('f32')}}
// expected-error@+1 {{op symbol's parent must have the SymbolTable trait}}
func.func @mixed_named_arguments(f32) {
^entry(%arg : i32):
return
Expand Down
7 changes: 3 additions & 4 deletions mlir/test/IR/region.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -87,18 +87,17 @@ func.func @named_region_has_wrong_number_of_blocks() {
// CHECK: test.single_no_terminator_op
"test.single_no_terminator_op"() (
{
func.func @foo1() { return }
func.func @foo2() { return }
%foo = arith.constant 1 : i32
}
) : () -> ()

// CHECK: test.variadic_no_terminator_op
"test.variadic_no_terminator_op"() (
{
func.func @foo1() { return }
%foo = arith.constant 1 : i32
},
{
func.func @foo2() { return }
%bar = arith.constant 1 : i32
}
) : () -> ()

Expand Down
33 changes: 16 additions & 17 deletions mlir/test/IR/traits.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -572,15 +572,13 @@ func.func @failedHasDominanceScopeOutsideDominanceFreeScope() -> () {

// Ensure that SSACFG regions of operations in GRAPH regions are
// checked for dominance
func.func @illegalInsideDominanceFreeScope() -> () {
func.func @illegalInsideDominanceFreeScope(%cond: i1) -> () {
test.graph_region {
func.func @test() -> i1 {
^bb1:
scf.if %cond {
// expected-error @+1 {{operand #0 does not dominate this use}}
%2:3 = "bar"(%1) : (i64) -> (i1,i1,i1)
// expected-note @+1 {{operand defined here}}
%1 = "baz"(%2#0) : (i1) -> (i64)
return %2#1 : i1
%1 = "baz"(%2#0) : (i1) -> (i64)
}
"terminator"() : () -> ()
}
Expand All @@ -591,20 +589,21 @@ func.func @illegalInsideDominanceFreeScope() -> () {

// Ensure that SSACFG regions of operations in GRAPH regions are
// checked for dominance
func.func @illegalCDFGInsideDominanceFreeScope() -> () {
func.func @illegalCFGInsideDominanceFreeScope(%cond: i1) -> () {
test.graph_region {
func.func @test() -> i1 {
^bb1:
// expected-error @+1 {{operand #0 does not dominate this use}}
%2:3 = "bar"(%1) : (i64) -> (i1,i1,i1)
cf.br ^bb4
^bb2:
cf.br ^bb2
^bb4:
%1 = "foo"() : ()->i64 // expected-note {{operand defined here}}
return %2#1 : i1
scf.if %cond {
"test.ssacfg_region"() ({
^bb1:
// expected-error @+1 {{operand #0 does not dominate this use}}
%2:3 = "bar"(%1) : (i64) -> (i1,i1,i1)
cf.br ^bb4
^bb2:
cf.br ^bb2
^bb4:
%1 = "foo"() : ()->i64 // expected-note {{operand defined here}}
}) : () -> ()
}
"terminator"() : () -> ()
"terminator"() : () -> ()
}
return
}
Expand Down
14 changes: 7 additions & 7 deletions mlir/test/Transforms/canonicalize-dce.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,15 @@ func.func @f(%arg0: f32, %pred: i1) {

// Test case: Recursively DCE into enclosed regions.

// CHECK: func @f(%arg0: f32)
// CHECK-NEXT: func @g(%arg1: f32)
// CHECK-NEXT: return
// CHECK: func.func @f(%arg0: f32)
// CHECK-NOT: arith.addf

func.func @f(%arg0: f32) {
func.func @g(%arg1: f32) {
%0 = "arith.addf"(%arg1, %arg1) : (f32, f32) -> f32
return
}
"test.region"() (
{
%0 = "arith.addf"(%arg0, %arg0) : (f32, f32) -> f32
}
) : () -> ()
return
}

Expand Down
13 changes: 6 additions & 7 deletions mlir/test/Transforms/canonicalize.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -424,16 +424,15 @@ func.func @write_only_alloca_fold(%v: f32) {
// CHECK-LABEL: func @dead_block_elim
func.func @dead_block_elim() {
// CHECK-NOT: ^bb
func.func @nested() {
return
builtin.module {
func.func @nested() {
return

^bb1:
return
^bb1:
return
}
}
return

^bb1:
return
}

// CHECK-LABEL: func @dyn_shape_fold(%arg0: index, %arg1: index)
Expand Down
11 changes: 7 additions & 4 deletions mlir/test/Transforms/constant-fold.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -756,12 +756,15 @@ func.func @cmpf_inf() -> (i1, i1, i1, i1, i1, i1, i1, i1, i1, i1, i1, i1, i1, i1

// CHECK-LABEL: func @nested_isolated_region
func.func @nested_isolated_region() {
// CHECK-NEXT: builtin.module {
// CHECK-NEXT: func @isolated_op
// CHECK-NEXT: arith.constant 2
func.func @isolated_op() {
%0 = arith.constant 1 : i32
%2 = arith.addi %0, %0 : i32
"foo.yield"(%2) : (i32) -> ()
builtin.module {
func.func @isolated_op() {
%0 = arith.constant 1 : i32
%2 = arith.addi %0, %0 : i32
"foo.yield"(%2) : (i32) -> ()
}
}

// CHECK: "foo.unknown_region"
Expand Down
11 changes: 7 additions & 4 deletions mlir/test/Transforms/cse.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -228,11 +228,14 @@ func.func @nested_isolated() -> i32 {
// CHECK-NEXT: arith.constant 1
%0 = arith.constant 1 : i32

// CHECK-NEXT: builtin.module
// CHECK-NEXT: @nested_func
func.func @nested_func() {
// CHECK-NEXT: arith.constant 1
%foo = arith.constant 1 : i32
"foo.yield"(%foo) : (i32) -> ()
builtin.module {
func.func @nested_func() {
// CHECK-NEXT: arith.constant 1
%foo = arith.constant 1 : i32
"foo.yield"(%foo) : (i32) -> ()
}
}

// CHECK: "foo.region"
Expand Down
8 changes: 5 additions & 3 deletions mlir/test/Transforms/test-legalizer-full.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,11 @@ func.func @recursively_legal_invalid_op() {
}
/// Operation that is dynamically legal, i.e. the function has a pattern
/// applied to legalize the argument type before it becomes recursively legal.
func.func @dynamic_func(%arg: i64) attributes {test.recursively_legal} {
%ignored = "test.illegal_op_f"() : () -> (i32)
"test.return"() : () -> ()
builtin.module {
func.func @dynamic_func(%arg: i64) attributes {test.recursively_legal} {
%ignored = "test.illegal_op_f"() : () -> (i32)
"test.return"() : () -> ()
}
}

"test.return"() : () -> ()
Expand Down
36 changes: 4 additions & 32 deletions mlir/test/python/ir/value.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,28 +167,15 @@ def testValuePrintAsOperand():
print(value2)

topFn = func.FuncOp("test", ([i32, i32], []))
entry_block1 = Block.create_at_start(topFn.operation.regions[0], [i32, i32])
entry_block = Block.create_at_start(topFn.operation.regions[0], [i32, i32])

with InsertionPoint(entry_block1):
with InsertionPoint(entry_block):
value3 = Operation.create("custom.op3", results=[i32]).results[0]
# CHECK: Value(%[[VAL3:.*]] = "custom.op3"() : () -> i32)
print(value3)
value4 = Operation.create("custom.op4", results=[i32]).results[0]
# CHECK: Value(%[[VAL4:.*]] = "custom.op4"() : () -> i32)
print(value4)

f = func.FuncOp("test", ([i32, i32], []))
entry_block2 = Block.create_at_start(f.operation.regions[0], [i32, i32])
with InsertionPoint(entry_block2):
value5 = Operation.create("custom.op5", results=[i32]).results[0]
# CHECK: Value(%[[VAL5:.*]] = "custom.op5"() : () -> i32)
print(value5)
value6 = Operation.create("custom.op6", results=[i32]).results[0]
# CHECK: Value(%[[VAL6:.*]] = "custom.op6"() : () -> i32)
print(value6)

func.ReturnOp([])

func.ReturnOp([])

# CHECK: %[[VAL1]]
Expand All @@ -215,32 +202,17 @@ def testValuePrintAsOperand():
# CHECK: %1
print(value4.get_name(use_local_scope=True))

# CHECK: %[[VAL5]]
print(value5.get_name())
# CHECK: %[[VAL6]]
print(value6.get_name())

# CHECK: %[[ARG0:.*]]
print(entry_block1.arguments[0].get_name())
print(entry_block.arguments[0].get_name())
# CHECK: %[[ARG1:.*]]
print(entry_block1.arguments[1].get_name())

# CHECK: %[[ARG2:.*]]
print(entry_block2.arguments[0].get_name())
# CHECK: %[[ARG3:.*]]
print(entry_block2.arguments[1].get_name())
print(entry_block.arguments[1].get_name())

# CHECK: module {
# CHECK: %[[VAL1]] = "custom.op1"() : () -> i32
# CHECK: %[[VAL2]] = "custom.op2"() : () -> i32
# CHECK: func.func @test(%[[ARG0]]: i32, %[[ARG1]]: i32) {
# CHECK: %[[VAL3]] = "custom.op3"() : () -> i32
# CHECK: %[[VAL4]] = "custom.op4"() : () -> i32
# CHECK: func @test(%[[ARG2]]: i32, %[[ARG3]]: i32) {
# CHECK: %[[VAL5]] = "custom.op5"() : () -> i32
# CHECK: %[[VAL6]] = "custom.op6"() : () -> i32
# CHECK: return
# CHECK: }
# CHECK: return
# CHECK: }
# CHECK: }
Expand Down