357 lines · plain
1// RUN: mlir-opt \2// RUN: -test-strict-pattern-driver="strictness=AnyOp" \3// RUN: --split-input-file %s | FileCheck %s --check-prefix=CHECK-AN4 5// RUN: mlir-opt \6// RUN: -test-strict-pattern-driver="strictness=ExistingAndNewOps" \7// RUN: --split-input-file %s | FileCheck %s --check-prefix=CHECK-EN8 9// RUN: mlir-opt \10// RUN: -test-strict-pattern-driver="strictness=ExistingOps" \11// RUN: --split-input-file %s | FileCheck %s --check-prefix=CHECK-EX12 13// CHECK-EN-LABEL: func @test_erase14// CHECK-EN-SAME: pattern_driver_all_erased = true, pattern_driver_changed = true}15// CHECK-EN: "test.arg0"16// CHECK-EN: "test.arg1"17// CHECK-EN-NOT: "test.erase_op"18func.func @test_erase() {19 %0 = "test.arg0"() : () -> (i32)20 %1 = "test.arg1"() : () -> (i32)21 %erase = "test.erase_op"(%0, %1) : (i32, i32) -> (i32)22 return23}24 25// -----26 27// CHECK-EN: notifyOperationInserted: test.insert_same_op, was unlinked28// CHECK-EN-LABEL: func @test_insert_same_op29// CHECK-EN-SAME: {pattern_driver_all_erased = false, pattern_driver_changed = true}30// CHECK-EN: "test.insert_same_op"() {skip = true}31// CHECK-EN: "test.insert_same_op"() {skip = true}32func.func @test_insert_same_op() {33 %0 = "test.insert_same_op"() : () -> (i32)34 return35}36 37// -----38 39// CHECK-EN: notifyOperationInserted: test.new_op, was unlinked40// CHECK-EN-LABEL: func @test_replace_with_new_op41// CHECK-EN-SAME: {pattern_driver_all_erased = true, pattern_driver_changed = true}42// CHECK-EN: %[[n:.*]] = "test.new_op"43// CHECK-EN: "test.dummy_user"(%[[n]])44// CHECK-EN: "test.dummy_user"(%[[n]])45func.func @test_replace_with_new_op() {46 %0 = "test.replace_with_new_op"() : () -> (i32)47 %1 = "test.dummy_user"(%0) : (i32) -> (i32)48 %2 = "test.dummy_user"(%0) : (i32) -> (i32)49 return50}51 52// -----53 54// CHECK-EN: notifyOperationInserted: test.erase_op, was unlinked55// CHECK-EN: notifyOperationErased: test.replace_with_new_op56// CHECK-EN: notifyOperationErased: test.erase_op57// CHECK-EN-LABEL: func @test_replace_with_erase_op58// CHECK-EN-SAME: {pattern_driver_all_erased = true, pattern_driver_changed = true}59// CHECK-EN-NOT: "test.replace_with_new_op"60// CHECK-EN-NOT: "test.erase_op"61 62// CHECK-EX-LABEL: func @test_replace_with_erase_op63// CHECK-EX-SAME: {pattern_driver_all_erased = true, pattern_driver_changed = true}64// CHECK-EX-NOT: "test.replace_with_new_op"65// CHECK-EX: "test.erase_op"66func.func @test_replace_with_erase_op() {67 "test.replace_with_new_op"() {create_erase_op} : () -> ()68 return69}70 71// -----72 73// CHECK-AN-LABEL: func @test_trigger_rewrite_through_block74// CHECK-AN: "test.change_block_op"()[^[[BB0:.*]], ^[[BB0]]]75// CHECK-AN: return76// CHECK-AN: ^[[BB1:[^:]*]]:77// CHECK-AN: "test.implicit_change_op"()[^[[BB1]]]78func.func @test_trigger_rewrite_through_block() {79 return80^bb1:81 // Uses bb1. ChangeBlockOp replaces that and all other usages of bb1 with bb2.82 "test.change_block_op"() [^bb1, ^bb2] : () -> ()83^bb2:84 return85^bb3:86 // Also uses bb1. ChangeBlockOp replaces that usage with bb2. This triggers87 // this op being put on the worklist, which triggers ImplicitChangeOp, which,88 // in turn, replaces the successor with bb3.89 "test.implicit_change_op"() [^bb1] : () -> ()90}91 92// -----93 94// CHECK-AN: notifyOperationErased: test.foo_b95// CHECK-AN: notifyOperationErased: test.foo_a96// CHECK-AN: notifyOperationErased: test.graph_region97// CHECK-AN: notifyOperationErased: test.erase_op98// CHECK-AN-LABEL: func @test_remove_graph_region()99// CHECK-AN-NEXT: return100func.func @test_remove_graph_region() {101 "test.erase_op"() ({102 test.graph_region {103 %0 = "test.foo_a"(%1) : (i1) -> (i1)104 %1 = "test.foo_b"(%0) : (i1) -> (i1)105 }106 }) : () -> ()107 return108}109 110// -----111 112// CHECK-AN: notifyOperationErased: cf.br113// CHECK-AN: notifyOperationErased: test.bar114// CHECK-AN: notifyOperationErased: cf.br115// CHECK-AN: notifyOperationErased: test.foo116// CHECK-AN: notifyOperationErased: cf.br117// CHECK-AN: notifyOperationErased: test.dummy_op118// CHECK-AN: notifyOperationErased: test.erase_op119// CHECK-AN-LABEL: func @test_remove_cyclic_blocks()120// CHECK-AN-NEXT: return121func.func @test_remove_cyclic_blocks() {122 "test.erase_op"() ({123 %x = "test.dummy_op"() : () -> (i1)124 cf.br ^bb1(%x: i1)125 ^bb1(%arg0: i1):126 "test.foo"(%x) : (i1) -> ()127 cf.br ^bb2(%arg0: i1)128 ^bb2(%arg1: i1):129 "test.bar"(%x) : (i1) -> ()130 cf.br ^bb1(%arg1: i1)131 }) : () -> ()132 return133}134 135// -----136 137// CHECK-AN: notifyOperationErased: test.dummy_op138// CHECK-AN: notifyOperationErased: test.bar139// CHECK-AN: notifyOperationErased: test.qux140// CHECK-AN: notifyOperationErased: test.qux_unreachable141// CHECK-AN: notifyOperationErased: test.nested_dummy142// CHECK-AN: notifyOperationErased: cf.br143// CHECK-AN: notifyOperationErased: test.foo144// CHECK-AN: notifyOperationErased: test.erase_op145// CHECK-AN-LABEL: func @test_remove_dead_blocks()146// CHECK-AN-NEXT: return147func.func @test_remove_dead_blocks() {148 "test.erase_op"() ({149 "test.dummy_op"() : () -> (i1)150 // The following blocks are not reachable. Still, ^bb2 should be deleted151 // befire ^bb1.152 ^bb1(%arg0: i1):153 "test.foo"() : () -> ()154 cf.br ^bb2(%arg0: i1)155 ^bb2(%arg1: i1):156 "test.nested_dummy"() ({157 "test.qux"() : () -> ()158 // The following block is unreachable.159 ^bb3:160 "test.qux_unreachable"() : () -> ()161 }) : () -> ()162 "test.bar"() : () -> ()163 }) : () -> ()164 return165}166 167// -----168 169// test.nested_* must be deleted before test.foo.170// test.bar must be deleted before test.foo.171 172// CHECK-AN: notifyOperationErased: cf.br173// CHECK-AN: notifyOperationErased: test.bar174// CHECK-AN: notifyOperationErased: cf.br175// CHECK-AN: notifyOperationErased: test.nested_b176// CHECK-AN: notifyOperationErased: test.nested_a177// CHECK-AN: notifyOperationErased: test.nested_d178// CHECK-AN: notifyOperationErased: cf.br179// CHECK-AN: notifyOperationErased: test.nested_e180// CHECK-AN: notifyOperationErased: cf.br181// CHECK-AN: notifyOperationErased: test.nested_c182// CHECK-AN: notifyOperationErased: test.foo183// CHECK-AN: notifyOperationErased: cf.br184// CHECK-AN: notifyOperationErased: test.dummy_op185// CHECK-AN: notifyOperationErased: test.erase_op186// CHECK-AN-LABEL: func @test_remove_nested_ops()187// CHECK-AN-NEXT: return188func.func @test_remove_nested_ops() {189 "test.erase_op"() ({190 %x = "test.dummy_op"() : () -> (i1)191 cf.br ^bb1(%x: i1)192 ^bb1(%arg0: i1):193 "test.foo"() ({194 "test.nested_a"() : () -> ()195 "test.nested_b"() : () -> ()196 ^dead1:197 "test.nested_c"() : () -> ()198 cf.br ^dead3199 ^dead2:200 "test.nested_d"() : () -> ()201 ^dead3:202 "test.nested_e"() : () -> ()203 cf.br ^dead2204 }) : () -> ()205 cf.br ^bb2(%arg0: i1)206 ^bb2(%arg1: i1):207 "test.bar"(%x) : (i1) -> ()208 cf.br ^bb1(%arg1: i1)209 }) : () -> ()210 return211}212 213// -----214 215// CHECK-AN: notifyOperationErased: test.qux216// CHECK-AN: notifyOperationErased: cf.br217// CHECK-AN: notifyOperationErased: test.foo218// CHECK-AN: notifyOperationErased: cf.br219// CHECK-AN: notifyOperationErased: test.bar220// CHECK-AN: notifyOperationErased: cf.cond_br221// CHECK-AN-LABEL: func @test_remove_diamond(222// CHECK-AN-NEXT: return223func.func @test_remove_diamond(%c: i1) {224 "test.erase_op"() ({225 cf.cond_br %c, ^bb1, ^bb2226 ^bb1:227 "test.foo"() : () -> ()228 cf.br ^bb3229 ^bb2:230 "test.bar"() : () -> ()231 cf.br ^bb3232 ^bb3:233 "test.qux"() : () -> ()234 }) : () -> ()235 return236}237 238// -----239 240// CHECK-AN: notifyOperationInserted: test.move_before_parent_op, previous = test.dummy_terminator241// CHECK-AN-LABEL: func @test_move_op_before(242// CHECK-AN: test.move_before_parent_op243// CHECK-AN: test.op_with_region244// CHECK-AN: test.dummy_terminator245func.func @test_move_op_before() {246 "test.op_with_region"() ({247 "test.move_before_parent_op"() : () -> ()248 "test.dummy_terminator"() : () ->()249 }) : () -> ()250 return251}252 253// -----254 255// CHECK-AN: notifyOperationInserted: test.op_1, previous = test.op_2256// CHECK-AN: notifyOperationInserted: test.op_2, previous = test.op_3257// CHECK-AN: notifyOperationInserted: test.op_3, was last in block258// CHECK-AN-LABEL: func @test_inline_block_before(259// CHECK-AN: test.op_1260// CHECK-AN: test.op_2261// CHECK-AN: test.op_3262// CHECK-AN: test.inline_blocks_into_parent263// CHECK-AN: return264func.func @test_inline_block_before() {265 "test.inline_blocks_into_parent"() ({266 "test.op_1"() : () -> ()267 "test.op_2"() : () -> ()268 "test.op_3"() : () -> ()269 }) : () -> ()270 return271}272 273// -----274 275// CHECK-AN: notifyBlockInserted into test.op_with_region: was unlinked276// CHECK-AN: notifyOperationInserted: test.op_3, was last in block277// CHECK-AN: notifyOperationInserted: test.op_2, was last in block278// CHECK-AN: notifyOperationInserted: test.split_block_here, was last in block279// CHECK-AN: notifyOperationInserted: test.new_op, was unlinked280// CHECK-AN: notifyOperationErased: test.split_block_here281// CHECK-AN-LABEL: func @test_split_block(282// CHECK-AN: "test.op_with_region"() ({283// CHECK-AN: test.op_1284// CHECK-AN: ^{{.*}}:285// CHECK-AN: test.new_op286// CHECK-AN: test.op_2287// CHECK-AN: test.op_3288// CHECK-AN: }) : () -> ()289func.func @test_split_block() {290 "test.op_with_region"() ({291 "test.op_1"() : () -> ()292 "test.split_block_here"() : () -> ()293 "test.op_2"() : () -> ()294 "test.op_3"() : () -> ()295 }) : () -> ()296 return297}298 299// -----300 301// CHECK-AN: notifyOperationInserted: test.clone_me, was unlinked302// CHECK-AN: notifyBlockInserted into test.clone_me: was unlinked303// CHECK-AN: notifyBlockInserted into test.clone_me: was unlinked304// CHECK-AN: notifyOperationInserted: test.foo, was unlinked305// CHECK-AN: notifyOperationInserted: test.bar, was unlinked306// CHECK-AN-LABEL: func @clone_op(307// CHECK-AN: "test.clone_me"() ({308// CHECK-AN: "test.foo"() : () -> ()309// CHECK-AN: ^bb1: // no predecessors310// CHECK-AN: "test.bar"() : () -> ()311// CHECK-AN: }) {was_cloned} : () -> ()312// CHECK-AN: "test.clone_me"() ({313// CHECK-AN: "test.foo"() : () -> ()314// CHECK-AN: ^bb1: // no predecessors315// CHECK-AN: "test.bar"() : () -> ()316// CHECK-AN: }) : () -> ()317func.func @clone_op() {318 "test.clone_me"() ({319 ^bb0:320 "test.foo"() : () -> ()321 ^bb1:322 "test.bar"() : () -> ()323 }) : () -> ()324 return325}326 327 328// -----329 330// CHECK-AN: notifyBlockInserted into func.func: was unlinked331// CHECK-AN: notifyOperationInserted: test.op_1, was unlinked332// CHECK-AN: notifyBlockInserted into func.func: was unlinked333// CHECK-AN: notifyOperationInserted: test.op_2, was unlinked334// CHECK-AN: notifyBlockInserted into test.op_2: was unlinked335// CHECK-AN: notifyOperationInserted: test.op_3, was unlinked336// CHECK-AN: notifyOperationInserted: test.op_4, was unlinked337// CHECK-AN-LABEL: func @test_clone_region_before(338// CHECK-AN: "test.op_1"() : () -> ()339// CHECK-AN: ^{{.*}}:340// CHECK-AN: "test.op_2"() ({341// CHECK-AN: "test.op_3"() : () -> ()342// CHECK-AN: }) : () -> ()343// CHECK-AN: "test.op_4"() : () -> ()344// CHECK-AN: ^{{.*}}:345// CHECK-AN: "test.clone_region_before"() ({346func.func @test_clone_region_before() {347 "test.clone_region_before"() ({348 "test.op_1"() : () -> ()349 ^bb0:350 "test.op_2"() ({351 "test.op_3"() : () -> ()352 }) : () -> ()353 "test.op_4"() : () -> ()354 }) : () -> ()355 return356}357