142 lines · plain
1// RUN: mlir-opt %s --test-walk-pattern-rewrite-driver="dump-notifications=true" \2// RUN: --allow-unregistered-dialect --split-input-file | FileCheck %s3 4// The following op is updated in-place and will not be added back to the worklist.5// CHECK-LABEL: func.func @inplace_update()6// CHECK: "test.any_attr_of_i32_str"() <{attr = 1 : i32}> : () -> ()7// CHECK: "test.any_attr_of_i32_str"() <{attr = 2 : i32}> : () -> ()8func.func @inplace_update() {9 "test.any_attr_of_i32_str"() {attr = 0 : i32} : () -> ()10 "test.any_attr_of_i32_str"() {attr = 1 : i32} : () -> ()11 return12}13 14// Check that the driver does not fold visited ops.15// CHECK-LABEL: func.func @add_no_fold()16// CHECK: arith.constant17// CHECK: arith.constant18// CHECK: %[[RES:.+]] = arith.addi19// CHECK: return %[[RES]]20func.func @add_no_fold() -> i32 {21 %c0 = arith.constant 0 : i3222 %c1 = arith.constant 1 : i3223 %res = arith.addi %c0, %c1 : i3224 return %res : i3225}26 27// Check that the driver handles rewriter.moveBefore.28// CHECK-LABEL: func.func @move_before(29// CHECK: "test.move_before_parent_op"30// CHECK: "test.any_attr_of_i32_str"() <{attr = 1 : i32}> : () -> ()31// CHECK: scf.if32// CHECK: return33func.func @move_before(%cond : i1) {34 scf.if %cond {35 "test.move_before_parent_op"() ({36 "test.any_attr_of_i32_str"() {attr = 0 : i32} : () -> ()37 }) : () -> ()38 }39 return40}41 42// Check that the driver handles rewriter.moveAfter. In this case, we expect43// the moved op to be visited twice.44// CHECK-LABEL: func.func @move_after(45// CHECK: scf.if46// CHECK: }47// CHECK: "test.move_after_parent_op"48// CHECK: "test.any_attr_of_i32_str"() <{attr = 2 : i32}> : () -> ()49// CHECK: return50func.func @move_after(%cond : i1) {51 scf.if %cond {52 "test.move_after_parent_op"() ({53 "test.any_attr_of_i32_str"() {attr = 0 : i32} : () -> ()54 }) : () -> ()55 }56 return57}58 59// Check that the driver handles rewriter.moveAfter. In this case, we expect60// the moved op to be visited twice since we advance its position to the next61// node after the parent.62// CHECK-LABEL: func.func @move_forward_and_revisit(63// CHECK: scf.if64// CHECK: }65// CHECK: arith.addi66// CHECK: "test.move_after_parent_op"67// CHECK: "test.any_attr_of_i32_str"() <{attr = 2 : i32}> : () -> ()68// CHECK: arith.addi69// CHECK: return70func.func @move_forward_and_revisit(%cond : i1) {71 scf.if %cond {72 "test.move_after_parent_op"() ({73 "test.any_attr_of_i32_str"() {attr = 0 : i32} : () -> ()74 }) {advance = 1 : i32} : () -> ()75 }76 %a = arith.addi %cond, %cond : i177 %b = arith.addi %a, %cond : i178 return79}80 81// Operation inserted just after the currently visited one won't be visited.82// CHECK-LABEL: func.func @insert_just_after83// CHECK: "test.clone_me"() ({84// CHECK: "test.any_attr_of_i32_str"() <{attr = 1 : i32}> : () -> ()85// CHECK: }) {was_cloned} : () -> ()86// CHECK: "test.clone_me"() ({87// CHECK: "test.any_attr_of_i32_str"() <{attr = 1 : i32}> : () -> ()88// CHECK: }) : () -> ()89// CHECK: return90func.func @insert_just_after(%cond : i1) {91 "test.clone_me"() ({92 "test.any_attr_of_i32_str"() {attr = 0 : i32} : () -> ()93 }) : () -> ()94 return95}96 97// Check that we can replace the current operation with a new one.98// Note that the new op won't be visited.99// CHECK-LABEL: func.func @replace_with_new_op100// CHECK: %[[NEW:.+]] = "test.new_op"101// CHECK: %[[RES:.+]] = arith.addi %[[NEW]], %[[NEW]]102// CHECK: return %[[RES]]103func.func @replace_with_new_op() -> i32 {104 %a = "test.replace_with_new_op"() : () -> (i32)105 %res = arith.addi %a, %a : i32106 return %res : i32107}108 109// Check that we can erase nested blocks.110// CHECK-LABEL: func.func @erase_nested_block111// CHECK: %[[RES:.+]] = "test.erase_first_block"112// CHECK-NEXT: foo.bar113// CHECK: return %[[RES]]114func.func @erase_nested_block() -> i32 {115 %a = "test.erase_first_block"() ({116 "foo.foo"() : () -> ()117 ^bb1:118 "foo.bar"() : () -> ()119 }): () -> (i32)120 return %a : i32121}122 123 124// CHECK-LABEL: func.func @unreachable_replace_with_new_op125// CHECK: "test.new_op"126// CHECK: "test.replace_with_new_op"127// CHECK-SAME: unreachable128// CHECK: "test.new_op"129func.func @unreachable_replace_with_new_op() {130 "test.br"()[^bb1] : () -> ()131^bb1:132 %a = "test.replace_with_new_op"() : () -> (i32)133 "test.br"()[^end] : () -> () // Test jumping over the unreachable block is visited as well.134^unreachable:135 %b = "test.replace_with_new_op"() {test.unreachable} : () -> (i32)136 return137^end:138 %c = "test.replace_with_new_op"() : () -> (i32)139 return140}141 142