brintos

brintos / llvm-project-archived public Read only

0
0
Text · 16.3 KiB · 88a71cc Raw
483 lines · plain
1// RUN: mlir-opt -allow-unregistered-dialect -split-input-file -test-legalize-patterns="allow-pattern-rollback=1" -verify-diagnostics %s | FileCheck %s2// RUN: mlir-opt -allow-unregistered-dialect -split-input-file -test-legalize-patterns="allow-pattern-rollback=1" -verify-diagnostics -profile-actions-to=- %s | FileCheck %s --check-prefix=CHECK-PROFILER3// RUN: mlir-opt -allow-unregistered-dialect -split-input-file -test-legalize-patterns="allow-pattern-rollback=0" -verify-diagnostics %s | FileCheck %s4 5// CHECK-PROFILER: "name": "pass-execution", "cat": "PERF", "ph": "B"6// CHECK-PROFILER: "name": "apply-conversion", "cat": "PERF", "ph": "B"7// CHECK-PROFILER: "name": "apply-pattern", "cat": "PERF", "ph": "B"8// CHECK-PROFILER: "name": "apply-pattern", "cat": "PERF", "ph": "E"9// CHECK-PROFILER: "name": "apply-conversion", "cat": "PERF", "ph": "E"10// CHECK-PROFILER: "name": "pass-execution", "cat": "PERF", "ph": "E"11 12// Note: Listener notifications appear after the pattern application because13// the conversion driver sends all notifications at the end of the conversion14// in bulk.15//      CHECK: notifyOperationInserted: test.legal_op_a, was unlinked16// CHECK-NEXT: notifyOperationReplaced: test.illegal_op_a17// CHECK-NEXT: notifyOperationModified: func.return18// CHECK-NEXT: notifyOperationErased: test.illegal_op_a19// CHECK-LABEL: verifyDirectPattern20func.func @verifyDirectPattern() -> i32 {21  // CHECK-NEXT:  "test.legal_op_a"() <{status = "Success"}22  %result = "test.illegal_op_a"() : () -> (i32)23  // expected-remark@+1 {{op 'func.return' is not legalizable}}24  return %result : i3225}26 27// -----28 29//      CHECK: notifyOperationInserted: test.illegal_op_e, was unlinked30// CHECK-NEXT: notifyOperationReplaced: test.illegal_op_c31// CHECK-NEXT: notifyOperationModified: func.return32// CHECK-NEXT: notifyOperationErased: test.illegal_op_c33// CHECK-NEXT: notifyOperationInserted: test.legal_op_a, was unlinked34// CHECK-NEXT: notifyOperationReplaced: test.illegal_op_e35// Note: func.return is modified a second time when running in no-rollback36//       mode.37//      CHECK: notifyOperationErased: test.illegal_op_e38 39// CHECK-LABEL: verifyLargerBenefit40func.func @verifyLargerBenefit() -> i32 {41  // CHECK-NEXT:  "test.legal_op_a"() <{status = "Success"}42  %result = "test.illegal_op_c"() : () -> (i32)43  // expected-remark@+1 {{op 'func.return' is not legalizable}}44  return %result : i3245}46 47// -----48 49// CHECK: notifyOperationModified: func.func50// Note: No block insertion because this function is external and no block51// signature conversion is performed.52 53// CHECK-LABEL: func private @remap_input_1_to_0()54func.func private @remap_input_1_to_0(i16)55 56// -----57 58// CHECK-LABEL: func @remap_input_1_to_1(%arg0: f64)59func.func @remap_input_1_to_1(%arg0: i64) {60  // CHECK-NEXT: "test.valid"{{.*}} : (f64)61  "test.invalid"(%arg0) : (i64) -> ()62}63 64// CHECK: func @remap_call_1_to_1(%arg0: f64)65func.func @remap_call_1_to_1(%arg0: i64) {66  // CHECK-NEXT: call @remap_input_1_to_1(%arg0) : (f64) -> ()67  call @remap_input_1_to_1(%arg0) : (i64) -> ()68  // expected-remark@+1 {{op 'func.return' is not legalizable}}69  return70}71 72// -----73 74// Block signature conversion: new block is inserted.75// CHECK:      notifyBlockInserted into func.func: was unlinked76 77// Contents of the old block are moved to the new block.78// CHECK-NEXT: notifyOperationInserted: test.return79 80// The old block is erased.81// CHECK-NEXT: notifyBlockErased82 83// The function op gets a new type attribute.84// CHECK-NEXT: notifyOperationModified: func.func85 86// "test.return" is replaced.87// CHECK-NEXT: notifyOperationInserted: test.return, was unlinked88// CHECK-NEXT: notifyOperationReplaced: test.return89// CHECK-NEXT: notifyOperationErased: test.return90 91// CHECK-LABEL: func @remap_input_1_to_N({{.*}}f16, {{.*}}f16)92func.func @remap_input_1_to_N(%arg0: f32) -> f32 {93  // CHECK-NEXT: "test.return"{{.*}} : (f16, f16) -> ()94  "test.return"(%arg0) : (f32) -> ()95}96 97// -----98 99// CHECK-LABEL: func @remap_input_1_to_N_remaining_use(%arg0: f16, %arg1: f16)100func.func @remap_input_1_to_N_remaining_use(%arg0: f32) {101  // CHECK-NEXT: [[CAST:%.*]] = "test.cast"(%arg0, %arg1) : (f16, f16) -> f32102  // CHECK-NEXT: "work"([[CAST]]) : (f32) -> ()103  // expected-remark@+1 {{op 'work' is not legalizable}}104  "work"(%arg0) : (f32) -> ()105}106 107// CHECK-LABEL: func @remap_materialize_1_to_1(%{{.*}}: i43)108func.func @remap_materialize_1_to_1(%arg0: i42) {109  // CHECK: %[[V:.*]] = "test.cast"(%arg0) : (i43) -> i42110  // CHECK: "test.return"(%[[V]])111  "test.return"(%arg0) : (i42) -> ()112}113 114// -----115 116// CHECK-LABEL: func @remap_input_to_self117func.func @remap_input_to_self(%arg0: index) {118  // CHECK-NOT: test.cast119  // CHECK: "work"120  // expected-remark@+1 {{op 'work' is not legalizable}}121  "work"(%arg0) : (index) -> ()122}123 124// CHECK-LABEL: func @remap_multi(%arg0: f64, %arg1: f64) -> (f64, f64)125func.func @remap_multi(%arg0: i64, %unused: i16, %arg1: i64) -> (i64, i64) {126 // CHECK-NEXT: "test.valid"{{.*}} : (f64, f64)127 "test.invalid"(%arg0, %arg1) : (i64, i64) -> ()128}129 130// -----131 132// CHECK-LABEL: func @no_remap_nested133func.func @no_remap_nested() {134  // CHECK-NEXT: "foo.region"135  // expected-remark@+1 {{op 'foo.region' is not legalizable}}136  "foo.region"() ({137    // CHECK-NEXT: ^bb0(%{{.*}}: f64, %{{.*}}: i16, %{{.*}}: f64):138    ^bb0(%i0: f64, %unused: i16, %i1: f64):139      // CHECK-NEXT: "test.valid"{{.*}} : (f64, f64)140      "test.invalid"(%i0, %i1) : (f64, f64) -> ()141  }) : () -> ()142  // expected-remark@+1 {{op 'func.return' is not legalizable}}143  return144}145 146// -----147 148// CHECK-LABEL: func @remap_drop_region149func.func @remap_drop_region() {150  // CHECK-NEXT: return151  // CHECK-NEXT: }152  "test.drop_region_op"() ({153    ^bb1(%i0: i64, %unused: i16, %i1: i64, %2: f32):154      "test.invalid"(%i0, %i1, %2) : (i64, i64, f32) -> ()155  }) : () -> ()156  // expected-remark@+1 {{op 'func.return' is not legalizable}}157  return158}159 160// -----161 162// CHECK-LABEL: func @dropped_input_in_use163func.func @dropped_input_in_use(%arg: i16, %arg2: i64) {164  // CHECK-NEXT: %[[cast:.*]] = "test.cast"() : () -> i16165  // CHECK-NEXT: "work"(%[[cast]]) : (i16)166  // expected-remark@+1 {{op 'work' is not legalizable}}167  "work"(%arg) : (i16) -> ()168}169 170// -----171 172// CHECK-LABEL: func @up_to_date_replacement173func.func @up_to_date_replacement(%arg: i8) -> i8 {174  // CHECK-NEXT: return175  %repl_1 = "test.rewrite"(%arg) : (i8) -> i8176  %repl_2 = "test.rewrite"(%repl_1) : (i8) -> i8177  // expected-remark@+1 {{op 'func.return' is not legalizable}}178  return %repl_2 : i8179}180 181// -----182 183// CHECK-LABEL: func @remove_foldable_op184// CHECK-SAME:                          (%[[ARG_0:[a-z0-9]*]]: i32)185func.func @remove_foldable_op(%arg0 : i32) -> (i32) {186  // CHECK-NEXT: return %[[ARG_0]]187  %0 = "test.op_with_region_fold"(%arg0) ({188    "foo.op_with_region_terminator"() : () -> ()189  }) : (i32) -> (i32)190  // expected-remark@+1 {{op 'func.return' is not legalizable}}191  return %0 : i32192}193 194// -----195 196// CHECK-LABEL: @create_block197func.func @create_block() {198  // Check that we created a block with arguments.199  // CHECK-NOT: test.create_block200  // CHECK: ^{{.*}}(%{{.*}}: i32, %{{.*}}: i32):201  "test.create_block"() : () -> ()202 203  // expected-remark@+1 {{op 'func.return' is not legalizable}}204  return205}206 207// -----208 209//      CHECK: notifyOperationModified: test.recursive_rewrite210// CHECK-NEXT: notifyOperationModified: test.recursive_rewrite211// CHECK-NEXT: notifyOperationModified: test.recursive_rewrite212 213// CHECK-LABEL: @bounded_recursion214func.func @bounded_recursion() {215  // CHECK: test.recursive_rewrite 0216  test.recursive_rewrite 3217  // expected-remark@+1 {{op 'func.return' is not legalizable}}218  return219}220 221// -----222 223// expected-remark@+1 {{applyPartialConversion failed}}224builtin.module {225 226  func.func @fail_to_convert_illegal_op() -> i32 {227    // expected-error@+1 {{failed to legalize operation 'test.illegal_op_f'}}228    %result = "test.illegal_op_f"() : () -> (i32)229    return %result : i32230  }231 232}233 234// -----235 236// CHECK-LABEL: @replace_block_arg_1_to_n237func.func @replace_block_arg_1_to_n() {238  // CHECK: "test.legal_op"239  "test.legal_op"() ({240  ^bb0(%arg0: i32, %arg1: i16):241    // CHECK-NEXT: ^bb0(%[[ARG0:.*]]: i32, %[[ARG1:.*]]: i16):242    // CHECK-NEXT: %[[cast:.*]] = "test.cast"(%[[ARG1]], %[[ARG1]]) : (i16, i16) -> i32243    // CHECK-NEXT: "test.value_replace"(%[[cast]], %[[ARG1]]) {is_legal} : (i32, i16) -> ()244    // CHECK-NEXT: "test.return"(%[[cast]]) : (i32)245    "test.value_replace"(%arg0, %arg1) : (i32, i16) -> ()246    "test.return"(%arg0) : (i32) -> ()247  }) : () -> ()248  "test.return"() : () -> ()249}250 251// -----252 253// CHECK-LABEL: @replace_op_result_1_to_n254func.func @replace_op_result_1_to_n() {255  // CHECK: %[[orig:.*]] = "test.legal_op"() : () -> i32256  // CHECK: %[[repl:.*]] = "test.legal_op"() : () -> i16257  %0 = "test.legal_op"() : () -> i32258  %1 = "test.legal_op"() : () -> i16259 260  // CHECK-NEXT: %[[cast:.*]] = "test.cast"(%[[repl]], %[[repl]]) : (i16, i16) -> i32261  // CHECK-NEXT: "test.value_replace"(%[[cast]], %[[repl]]) {is_legal} : (i32, i16) -> ()262  // CHECK-NEXT: "test.return"(%[[cast]]) : (i32)263  "test.value_replace"(%0, %1) : (i32, i16) -> ()264  "test.return"(%0) : (i32) -> ()265}266 267// -----268 269// Check that a conversion pattern on `test.blackhole` can mark the producer270// for deletion.271// CHECK-LABEL: @blackhole272func.func @blackhole() {273  %input = "test.blackhole_producer"() : () -> (i32)274  "test.blackhole"(%input) : (i32) -> ()275  // expected-remark@+1 {{op 'func.return' is not legalizable}}276  return277}278 279// -----280 281module {282// CHECK-LABEL: func.func private @callee() -> (f16, f16)283func.func private @callee() -> (f32, i24)284 285// CHECK: func.func @caller()286func.func @caller() {287  // f32 is converted to (f16, f16).288  // i24 is converted to ().289  // CHECK: %[[call:.*]]:2 = call @callee() : () -> (f16, f16)290  %0:2 = func.call @callee() : () -> (f32, i24)291 292  // CHECK-DAG: %[[cast1:.*]] = "test.cast"() : () -> i24293  // CHECK-DAG: %[[cast0:.*]] = "test.cast"(%[[call]]#0, %[[call]]#1) : (f16, f16) -> f32294  // CHECK: "test.some_user"(%[[cast0]], %[[cast1]]) : (f32, i24) -> ()295  // expected-remark @below{{'test.some_user' is not legalizable}}296  "test.some_user"(%0#0, %0#1) : (f32, i24) -> ()297  "test.return"() : () -> ()298}299}300 301// -----302 303//      CHECK: func.func @use_of_replaced_bbarg(304// CHECK-SAME:     %[[arg0:.*]]: f64)305//      CHECK:   "test.valid"(%[[arg0]])306func.func @use_of_replaced_bbarg(%arg0: i64) {307  %0 = "test.op_with_region_fold"(%arg0) ({308    "foo.op_with_region_terminator"() : () -> ()309  }) : (i64) -> (i64)310  "test.invalid"(%0) : (i64) -> ()311}312 313// -----314 315// CHECK-LABEL: @fold_legalization316func.func @fold_legalization() -> i32 {317  // CHECK: op_in_place_self_fold318  // CHECK-SAME: folded319  %1 = "test.op_in_place_self_fold"() : () -> (i32)320  "test.return"(%1) : (i32) -> ()321}322 323// -----324 325// CHECK-LABEL: func @convert_detached_signature()326//       CHECK:   "test.legal_op"() ({327//       CHECK:   ^bb0(%arg0: f64):328//       CHECK:     "test.return"() : () -> ()329//       CHECK:   }) : () -> ()330func.func @convert_detached_signature() {331  "test.detached_signature_conversion"() ({332  ^bb0(%arg0: i64):333    "test.return"() : () -> ()334  }) : () -> ()335  "test.return"() : () -> ()336}337 338// -----339 340// CHECK: notifyOperationReplaced: test.erase_op341// CHECK: notifyOperationErased: test.dummy_op_lvl_2342// CHECK: notifyBlockErased343// CHECK: notifyOperationErased: test.dummy_op_lvl_1344// CHECK: notifyBlockErased345// CHECK: notifyOperationErased: test.erase_op346// CHECK: notifyOperationInserted: test.valid, was unlinked347// CHECK: notifyOperationReplaced: test.drop_operands_and_replace_with_valid348// CHECK: notifyOperationErased: test.drop_operands_and_replace_with_valid349 350// CHECK-LABEL: func @circular_mapping()351//  CHECK-NEXT:   "test.valid"() : () -> ()352func.func @circular_mapping() {353  // Regression test that used to crash due to circular354  // unrealized_conversion_cast ops. 355  %0 = "test.erase_op"() ({356    "test.dummy_op_lvl_1"() ({357      "test.dummy_op_lvl_2"() : () -> ()358    }) : () -> ()359  }): () -> (i64)360  "test.drop_operands_and_replace_with_valid"(%0) : (i64) -> ()361}362 363// -----364 365// CHECK-LABEL: func @test_duplicate_block_arg()366//       CHECK:   test.convert_block_args  is_legal duplicate {367//       CHECK:   ^{{.*}}(%[[arg0:.*]]: i64, %[[arg1:.*]]: i64):368//       CHECK:     "test.valid"(%[[arg0]], %[[arg1]])369//       CHECK:   }370func.func @test_duplicate_block_arg() {371  test.convert_block_args duplicate {372  ^bb0(%arg0: i64):373    "test.repetitive_1_to_n_consumer"(%arg0) : (i64) -> ()374  } : () -> ()375  "test.return"() : () -> ()376}377 378// -----379 380// CHECK-LABEL: func @test_remap_block_arg()381//       CHECK:      %[[repl:.*]] = "test.legal_op"() : () -> i32382//       CHECK:      test.convert_block_args %[[repl]]  is_legal replace_with_operand {383//       CHECK-NEXT:   "test.valid"(%[[repl]], %[[repl]])384//       CHECK:      }385func.func @test_remap_block_arg() {386  %0 = "test.legal_op"() : () -> (i32)387  test.convert_block_args %0 replace_with_operand {388  ^bb0(%arg0: i32):389    "test.repetitive_1_to_n_consumer"(%arg0) : (i32) -> ()390  } : (i32) -> ()391  "test.return"() : () -> ()392}393 394// -----395 396// CHECK: notifyOperationInserted: test.step_1397// CHECK: notifyOperationReplaced: test.multiple_1_to_n_replacement398// CHECK: notifyOperationErased: test.multiple_1_to_n_replacement399// CHECK: notifyOperationInserted: test.legal_op400// CHECK: notifyOperationReplaced: test.step_1401// CHECK: notifyOperationErased: test.step_1402 403// CHECK-LABEL: func @test_multiple_1_to_n_replacement()404//       CHECK:   %[[legal_op:.*]]:4 = "test.legal_op"() : () -> (f16, f16, f16, f16)405// Note: There is a bug in the rollback-based conversion driver: it emits a406// "test.cast" : (f16, f16, f16, f16) -> f16, when it should be emitting407// three consecutive casts of (f16, f16) -> f16.408//       CHECK:   "test.valid"(%{{.*}}) : (f16) -> ()409func.func @test_multiple_1_to_n_replacement() {410  %0 = "test.multiple_1_to_n_replacement"() : () -> (f16)411  "test.invalid"(%0) : (f16) -> ()412}413 414// -----415 416// CHECK-LABEL: func @test_lookup_without_converter417//       CHECK:   %[[producer:.*]] = "test.valid_producer"() : () -> i16418//       CHECK:   %[[cast:.*]] = "test.cast"(%[[producer]]) : (i16) -> f64419//       CHECK:   "test.valid_consumer"(%[[cast]]) : (f64) -> ()420//       CHECK:   "test.valid_consumer"(%[[producer]]) : (i16) -> ()421func.func @test_lookup_without_converter() {422  %0 = "test.replace_with_valid_producer"() {type = i16} : () -> (i64)423  "test.replace_with_valid_consumer"(%0) {with_converter} : (i64) -> ()424  // Make sure that the second "replace_with_valid_consumer" lowering does not425  // lookup the materialization that was created for the above op.426  "test.replace_with_valid_consumer"(%0) : (i64) -> ()427  // expected-remark@+1 {{op 'func.return' is not legalizable}}428  return429}430 431// -----432// expected-remark@-1 {{applyPartialConversion failed}}433 434func.func @test_skip_1to1_pattern(%arg0: f32) {435  // expected-error@+1 {{failed to legalize operation 'test.type_consumer'}}436  "test.type_consumer"(%arg0) : (f32) -> ()437  return438}439 440// -----441 442// Demonstrate that the pattern generally works, but only for 1:1 type443// conversions.444 445// CHECK-LABEL: @test_working_1to1_pattern(446func.func @test_working_1to1_pattern(%arg0: f16) {447  // CHECK-NEXT: "test.return"() : () -> ()448  "test.type_consumer"(%arg0) : (f16) -> ()449  "test.return"() : () -> ()450}451 452// -----453 454// The region of "test.post_order_legalization" is converted before the op.455 456// CHECK: notifyBlockInserted into test.post_order_legalization: was unlinked457// CHECK: notifyOperationInserted: test.invalid458// CHECK: notifyBlockErased459// CHECK: notifyOperationInserted: test.valid, was unlinked460// CHECK: notifyOperationReplaced: test.invalid461// CHECK: notifyOperationErased: test.invalid462// CHECK: notifyOperationModified: test.post_order_legalization463 464// CHECK-LABEL: func @test_preorder_legalization465//       CHECK:   "test.post_order_legalization"() ({466//       CHECK:   ^{{.*}}(%[[arg0:.*]]: f64):467// Note: The survival of a not-explicitly-invalid operation does *not* cause468// a conversion failure in when applying a partial conversion.469//       CHECK:     %[[cast:.*]] = "test.cast"(%[[arg0]]) : (f64) -> i64470//       CHECK:     "test.remaining_consumer"(%[[cast]]) : (i64) -> ()471//       CHECK:     "test.valid"(%[[arg0]]) : (f64) -> ()472//       CHECK:   }) {is_legal} : () -> ()473func.func @test_preorder_legalization() {474  "test.post_order_legalization"() ({475  ^bb0(%arg0: i64):476    // expected-remark @+1 {{'test.remaining_consumer' is not legalizable}}477    "test.remaining_consumer"(%arg0) : (i64) -> ()478    "test.invalid"(%arg0) : (i64) -> ()479  }) : () -> ()480  // expected-remark @+1 {{'func.return' is not legalizable}}481  return482}483