brintos

brintos / llvm-project-archived public Read only

0
0
Text · 19.1 KiB · b447094 Raw
576 lines · plain
1// RUN: mlir-opt -allow-unregistered-dialect %s -pass-pipeline='builtin.module(func.func(cse))' -split-input-file | FileCheck %s2 3// CHECK-LABEL: @simple_constant4func.func @simple_constant() -> (i32, i32) {5  // CHECK-NEXT: %[[VAR_c1_i32:.*]] = arith.constant 1 : i326  %0 = arith.constant 1 : i327 8  // CHECK-NEXT: return %[[VAR_c1_i32]], %[[VAR_c1_i32]] : i32, i329  %1 = arith.constant 1 : i3210  return %0, %1 : i32, i3211}12 13// -----14 15// CHECK: #[[$MAP:.*]] = affine_map<(d0) -> (d0 mod 2)>16#map0 = affine_map<(d0) -> (d0 mod 2)>17 18// CHECK-LABEL: @basic19func.func @basic() -> (index, index) {20  // CHECK: %[[VAR_c0:[0-9a-zA-Z_]+]] = arith.constant 0 : index21  %c0 = arith.constant 0 : index22  %c1 = arith.constant 0 : index23 24  // CHECK-NEXT: %[[VAR_0:[0-9a-zA-Z_]+]] = affine.apply #[[$MAP]](%[[VAR_c0]])25  %0 = affine.apply #map0(%c0)26  %1 = affine.apply #map0(%c1)27 28  // CHECK-NEXT: return %[[VAR_0]], %[[VAR_0]] : index, index29  return %0, %1 : index, index30}31 32// -----33 34// CHECK-LABEL: @many35func.func @many(f32, f32) -> (f32) {36^bb0(%a : f32, %b : f32):37  // CHECK-NEXT: %[[VAR_0:[0-9a-zA-Z_]+]] = arith.addf %{{.*}}, %{{.*}} : f3238  %c = arith.addf %a, %b : f3239  %d = arith.addf %a, %b : f3240  %e = arith.addf %a, %b : f3241  %f = arith.addf %a, %b : f3242 43  // CHECK-NEXT: %[[VAR_1:[0-9a-zA-Z_]+]] = arith.addf %[[VAR_0]], %[[VAR_0]] : f3244  %g = arith.addf %c, %d : f3245  %h = arith.addf %e, %f : f3246  %i = arith.addf %c, %e : f3247 48  // CHECK-NEXT: %[[VAR_2:[0-9a-zA-Z_]+]] = arith.addf %[[VAR_1]], %[[VAR_1]] : f3249  %j = arith.addf %g, %h : f3250  %k = arith.addf %h, %i : f3251 52  // CHECK-NEXT: %[[VAR_3:[0-9a-zA-Z_]+]] = arith.addf %[[VAR_2]], %[[VAR_2]] : f3253  %l = arith.addf %j, %k : f3254 55  // CHECK-NEXT: return %[[VAR_3]] : f3256  return %l : f3257}58 59// -----60 61/// Check that operations are not eliminated if they have different operands.62// CHECK-LABEL: @different_ops63func.func @different_ops() -> (i32, i32) {64  // CHECK: %[[VAR_c0_i32:[0-9a-zA-Z_]+]] = arith.constant 0 : i3265  // CHECK: %[[VAR_c1_i32:[0-9a-zA-Z_]+]] = arith.constant 1 : i3266  %0 = arith.constant 0 : i3267  %1 = arith.constant 1 : i3268 69  // CHECK-NEXT: return %[[VAR_c0_i32]], %[[VAR_c1_i32]] : i32, i3270  return %0, %1 : i32, i3271}72 73// -----74 75/// Check that operations are not eliminated if they have different result76/// types.77// CHECK-LABEL: @different_results78func.func @different_results(%arg0: tensor<*xf32>) -> (tensor<?x?xf32>, tensor<4x?xf32>) {79  // CHECK: %[[VAR_0:[0-9a-zA-Z_]+]] = tensor.cast %{{.*}} : tensor<*xf32> to tensor<?x?xf32>80  // CHECK-NEXT: %[[VAR_1:[0-9a-zA-Z_]+]] = tensor.cast %{{.*}} : tensor<*xf32> to tensor<4x?xf32>81  %0 = tensor.cast %arg0 : tensor<*xf32> to tensor<?x?xf32>82  %1 = tensor.cast %arg0 : tensor<*xf32> to tensor<4x?xf32>83 84  // CHECK-NEXT: return %[[VAR_0]], %[[VAR_1]] : tensor<?x?xf32>, tensor<4x?xf32>85  return %0, %1 : tensor<?x?xf32>, tensor<4x?xf32>86}87 88// -----89 90/// Check that operations are not eliminated if they have different attributes.91// CHECK-LABEL: @different_attributes92func.func @different_attributes(index, index) -> (i1, i1, i1) {93^bb0(%a : index, %b : index):94  // CHECK: %[[VAR_0:[0-9a-zA-Z_]+]] = arith.cmpi slt, %{{.*}}, %{{.*}} : index95  %0 = arith.cmpi slt, %a, %b : index96 97  // CHECK-NEXT: %[[VAR_1:[0-9a-zA-Z_]+]] = arith.cmpi ne, %{{.*}}, %{{.*}} : index98  /// Predicate 1 means inequality comparison.99  %1 = arith.cmpi ne, %a, %b : index100  %2 = "arith.cmpi"(%a, %b) {predicate = 1} : (index, index) -> i1101 102  // CHECK-NEXT: return %[[VAR_0]], %[[VAR_1]], %[[VAR_1]] : i1, i1, i1103  return %0, %1, %2 : i1, i1, i1104}105 106// -----107 108/// Check that operations with side effects are not eliminated.109// CHECK-LABEL: @side_effect110func.func @side_effect() -> (memref<2x1xf32>, memref<2x1xf32>) {111  // CHECK: %[[VAR_0:[0-9a-zA-Z_]+]] = memref.alloc() : memref<2x1xf32>112  %0 = memref.alloc() : memref<2x1xf32>113 114  // CHECK-NEXT: %[[VAR_1:[0-9a-zA-Z_]+]] = memref.alloc() : memref<2x1xf32>115  %1 = memref.alloc() : memref<2x1xf32>116 117  // CHECK-NEXT: return %[[VAR_0]], %[[VAR_1]] : memref<2x1xf32>, memref<2x1xf32>118  return %0, %1 : memref<2x1xf32>, memref<2x1xf32>119}120 121// -----122 123/// Check that operation definitions are properly propagated down the dominance124/// tree.125// CHECK-LABEL: @down_propagate_for126func.func @down_propagate_for() {127  // CHECK: %[[VAR_c1_i32:[0-9a-zA-Z_]+]] = arith.constant 1 : i32128  %0 = arith.constant 1 : i32129 130  // CHECK-NEXT: affine.for {{.*}} = 0 to 4 {131  affine.for %i = 0 to 4 {132    // CHECK-NEXT: "foo"(%[[VAR_c1_i32]], %[[VAR_c1_i32]]) : (i32, i32) -> ()133    %1 = arith.constant 1 : i32134    "foo"(%0, %1) : (i32, i32) -> ()135  }136  return137}138 139// -----140 141// CHECK-LABEL: @down_propagate142func.func @down_propagate() -> i32 {143  // CHECK-NEXT: %[[VAR_c1_i32:[0-9a-zA-Z_]+]] = arith.constant 1 : i32144  %0 = arith.constant 1 : i32145 146  // CHECK-NEXT: %[[VAR_true:[0-9a-zA-Z_]+]] = arith.constant true147  %cond = arith.constant true148 149  // CHECK-NEXT: cf.cond_br %[[VAR_true]], ^bb1, ^bb2(%[[VAR_c1_i32]] : i32)150  cf.cond_br %cond, ^bb1, ^bb2(%0 : i32)151 152^bb1: // CHECK: ^bb1:153  // CHECK-NEXT: cf.br ^bb2(%[[VAR_c1_i32]] : i32)154  %1 = arith.constant 1 : i32155  cf.br ^bb2(%1 : i32)156 157^bb2(%arg : i32):158  return %arg : i32159}160 161// -----162 163/// Check that operation definitions are NOT propagated up the dominance tree.164// CHECK-LABEL: @up_propagate_for165func.func @up_propagate_for() -> i32 {166  // CHECK: affine.for {{.*}} = 0 to 4 {167  affine.for %i = 0 to 4 {168    // CHECK-NEXT: %[[VAR_c1_i32_0:[0-9a-zA-Z_]+]] = arith.constant 1 : i32169    // CHECK-NEXT: "foo"(%[[VAR_c1_i32_0]]) : (i32) -> ()170    %0 = arith.constant 1 : i32171    "foo"(%0) : (i32) -> ()172  }173 174  // CHECK: %[[VAR_c1_i32:[0-9a-zA-Z_]+]] = arith.constant 1 : i32175  // CHECK-NEXT: return %[[VAR_c1_i32]] : i32176  %1 = arith.constant 1 : i32177  return %1 : i32178}179 180// -----181 182// CHECK-LABEL: func @up_propagate183func.func @up_propagate() -> i32 {184  // CHECK-NEXT:  %[[VAR_c0_i32:[0-9a-zA-Z_]+]] = arith.constant 0 : i32185  %0 = arith.constant 0 : i32186 187  // CHECK-NEXT: %[[VAR_true:[0-9a-zA-Z_]+]] = arith.constant true188  %cond = arith.constant true189 190  // CHECK-NEXT: cf.cond_br %[[VAR_true]], ^bb1, ^bb2(%[[VAR_c0_i32]] : i32)191  cf.cond_br %cond, ^bb1, ^bb2(%0 : i32)192 193^bb1: // CHECK: ^bb1:194  // CHECK-NEXT: %[[VAR_c1_i32:[0-9a-zA-Z_]+]] = arith.constant 1 : i32195  %1 = arith.constant 1 : i32196 197  // CHECK-NEXT: cf.br ^bb2(%[[VAR_c1_i32]] : i32)198  cf.br ^bb2(%1 : i32)199 200^bb2(%arg : i32): // CHECK: ^bb2201  // CHECK-NEXT: %[[VAR_c1_i32_0:[0-9a-zA-Z_]+]] = arith.constant 1 : i32202  %2 = arith.constant 1 : i32203 204  // CHECK-NEXT: %[[VAR_1:[0-9a-zA-Z_]+]] = arith.addi %{{.*}}, %[[VAR_c1_i32_0]] : i32205  %add = arith.addi %arg, %2 : i32206 207  // CHECK-NEXT: return %[[VAR_1]] : i32208  return %add : i32209}210 211// -----212 213/// The same test as above except that we are testing on a cfg embedded within214/// an operation region.215// CHECK-LABEL: func @up_propagate_region216func.func @up_propagate_region() -> i32 {217  // CHECK-NEXT: {{.*}} "foo.region"218  %0 = "foo.region"() ({219    // CHECK-NEXT:  %[[VAR_c0_i32:[0-9a-zA-Z_]+]] = arith.constant 0 : i32220    // CHECK-NEXT: %[[VAR_true:[0-9a-zA-Z_]+]] = arith.constant true221    // CHECK-NEXT: cf.cond_br222 223    %1 = arith.constant 0 : i32224    %true = arith.constant true225    cf.cond_br %true, ^bb1, ^bb2(%1 : i32)226 227  ^bb1: // CHECK: ^bb1:228    // CHECK-NEXT: %[[VAR_c1_i32:[0-9a-zA-Z_]+]] = arith.constant 1 : i32229    // CHECK-NEXT: cf.br230 231    %c1_i32 = arith.constant 1 : i32232    cf.br ^bb2(%c1_i32 : i32)233 234  ^bb2(%arg : i32): // CHECK: ^bb2(%[[VAR_1:.*]]: i32):235    // CHECK-NEXT: %[[VAR_c1_i32_0:[0-9a-zA-Z_]+]] = arith.constant 1 : i32236    // CHECK-NEXT: %[[VAR_2:[0-9a-zA-Z_]+]] = arith.addi %[[VAR_1]], %[[VAR_c1_i32_0]] : i32237    // CHECK-NEXT: "foo.yield"(%[[VAR_2]]) : (i32) -> ()238 239    %c1_i32_0 = arith.constant 1 : i32240    %2 = arith.addi %arg, %c1_i32_0 : i32241    "foo.yield" (%2) : (i32) -> ()242  }) : () -> (i32)243  return %0 : i32244}245 246// -----247 248/// This test checks that nested regions that are isolated from above are249/// properly handled.250// CHECK-LABEL: @nested_isolated251func.func @nested_isolated() -> i32 {252  // CHECK-NEXT: arith.constant 1253  %0 = arith.constant 1 : i32254 255  // CHECK-NEXT: builtin.module256  // CHECK-NEXT: @nested_func257  builtin.module {258    func.func @nested_func() {259      // CHECK-NEXT: arith.constant 1260      %foo = arith.constant 1 : i32261      "foo.yield"(%foo) : (i32) -> ()262    }263  }264 265  // CHECK: "foo.region"266  "foo.region"() ({267    // CHECK-NEXT: arith.constant 1268    %foo = arith.constant 1 : i32269    "foo.yield"(%foo) : (i32) -> ()270  }) : () -> ()271 272  return %0 : i32273}274 275// -----276 277/// This test is checking that CSE gracefully handles values in graph regions278/// where the use occurs before the def, and one of the defs could be CSE'd with279/// the other.280// CHECK-LABEL: @use_before_def281func.func @use_before_def() {282  // CHECK-NEXT: test.graph_region283  test.graph_region {284    // CHECK-NEXT: arith.addi285    %0 = arith.addi %1, %2 : i32286 287    // CHECK-NEXT: arith.constant 1288    // CHECK-NEXT: arith.constant 1289    %1 = arith.constant 1 : i32290    %2 = arith.constant 1 : i32291 292    // CHECK-NEXT: "foo.yield"(%{{.*}}) : (i32) -> ()293    "foo.yield"(%0) : (i32) -> ()294  }295  return296}297 298// -----299 300/// This test is checking that CSE is removing duplicated read op that follow301/// other.302// CHECK-LABEL: @remove_direct_duplicated_read_op303func.func @remove_direct_duplicated_read_op() -> i32 {304  // CHECK-NEXT: %[[READ_VALUE:.*]] = "test.op_with_memread"() : () -> i32305  %0 = "test.op_with_memread"() : () -> (i32)306  %1 = "test.op_with_memread"() : () -> (i32)307  // CHECK-NEXT: %{{.*}} = arith.addi %[[READ_VALUE]], %[[READ_VALUE]] : i32308  %2 = arith.addi %0, %1 : i32309  return %2 : i32310}311 312// -----313 314/// This test is checking that CSE is removing duplicated read op that follow315/// other.316// CHECK-LABEL: @remove_multiple_duplicated_read_op317func.func @remove_multiple_duplicated_read_op() -> i64 {318  // CHECK: %[[READ_VALUE:.*]] = "test.op_with_memread"() : () -> i64319  %0 = "test.op_with_memread"() : () -> (i64)320  %1 = "test.op_with_memread"() : () -> (i64)321  // CHECK-NEXT: %{{.*}} = arith.addi %{{.*}}, %[[READ_VALUE]] : i64322  %2 = arith.addi %0, %1 : i64323  %3 = "test.op_with_memread"() : () -> (i64)324  // CHECK-NEXT: %{{.*}} = arith.addi %{{.*}}, %{{.*}} : i64325  %4 = arith.addi %2, %3 : i64326  %5 = "test.op_with_memread"() : () -> (i64)327  // CHECK-NEXT: %{{.*}} = arith.addi %{{.*}}, %{{.*}} : i64328  %6 = arith.addi %4, %5 : i64329  // CHECK-NEXT: return %{{.*}} : i64330  return %6 : i64331}332 333// -----334 335/// This test is checking that CSE is not removing duplicated read op that336/// have write op in between.337// CHECK-LABEL: @dont_remove_duplicated_read_op_with_sideeffecting338func.func @dont_remove_duplicated_read_op_with_sideeffecting() -> i32 {339  // CHECK-NEXT: %[[READ_VALUE0:.*]] = "test.op_with_memread"() : () -> i32340  %0 = "test.op_with_memread"() : () -> (i32)341  "test.op_with_memwrite"() : () -> ()342  // CHECK: %[[READ_VALUE1:.*]] = "test.op_with_memread"() : () -> i32343  %1 = "test.op_with_memread"() : () -> (i32)344  // CHECK-NEXT: %{{.*}} = arith.addi %[[READ_VALUE0]], %[[READ_VALUE1]] : i32345  %2 = arith.addi %0, %1 : i32346  return %2 : i32347}348 349// -----350 351// Check that an operation with a single region can CSE.352func.func @cse_single_block_ops(%a : tensor<?x?xf32>, %b : tensor<?x?xf32>)353  -> (tensor<?x?xf32>, tensor<?x?xf32>) {354  %0 = test.cse_of_single_block_op inputs(%a, %b) {355    ^bb0(%arg0 : f32):356    test.region_yield %arg0 : f32357  } : tensor<?x?xf32>, tensor<?x?xf32> -> tensor<?x?xf32>358  %1 = test.cse_of_single_block_op inputs(%a, %b) {359    ^bb0(%arg0 : f32):360    test.region_yield %arg0 : f32361  } : tensor<?x?xf32>, tensor<?x?xf32> -> tensor<?x?xf32>362  return %0, %1 : tensor<?x?xf32>, tensor<?x?xf32>363}364// CHECK-LABEL: func @cse_single_block_ops365//       CHECK:   %[[OP:.+]] = test.cse_of_single_block_op366//   CHECK-NOT:   test.cse_of_single_block_op367//       CHECK:   return %[[OP]], %[[OP]]368 369// -----370 371// Operations with different number of bbArgs dont CSE.372func.func @no_cse_varied_bbargs(%a : tensor<?x?xf32>, %b : tensor<?x?xf32>)373  -> (tensor<?x?xf32>, tensor<?x?xf32>) {374  %0 = test.cse_of_single_block_op inputs(%a, %b) {375    ^bb0(%arg0 : f32, %arg1 : f32):376    test.region_yield %arg0 : f32377  } : tensor<?x?xf32>, tensor<?x?xf32> -> tensor<?x?xf32>378  %1 = test.cse_of_single_block_op inputs(%a, %b) {379    ^bb0(%arg0 : f32):380    test.region_yield %arg0 : f32381  } : tensor<?x?xf32>, tensor<?x?xf32> -> tensor<?x?xf32>382  return %0, %1 : tensor<?x?xf32>, tensor<?x?xf32>383}384// CHECK-LABEL: func @no_cse_varied_bbargs385//       CHECK:   %[[OP0:.+]] = test.cse_of_single_block_op386//       CHECK:   %[[OP1:.+]] = test.cse_of_single_block_op387//       CHECK:   return %[[OP0]], %[[OP1]]388 389// -----390 391// Operations with different regions dont CSE392func.func @no_cse_region_difference_simple(%a : tensor<?x?xf32>, %b : tensor<?x?xf32>)393  -> (tensor<?x?xf32>, tensor<?x?xf32>) {394  %0 = test.cse_of_single_block_op inputs(%a, %b) {395    ^bb0(%arg0 : f32, %arg1 : f32):396    test.region_yield %arg0 : f32397  } : tensor<?x?xf32>, tensor<?x?xf32> -> tensor<?x?xf32>398  %1 = test.cse_of_single_block_op inputs(%a, %b) {399    ^bb0(%arg0 : f32, %arg1 : f32):400    test.region_yield %arg1 : f32401  } : tensor<?x?xf32>, tensor<?x?xf32> -> tensor<?x?xf32>402  return %0, %1 : tensor<?x?xf32>, tensor<?x?xf32>403}404// CHECK-LABEL: func @no_cse_region_difference_simple405//       CHECK:   %[[OP0:.+]] = test.cse_of_single_block_op406//       CHECK:   %[[OP1:.+]] = test.cse_of_single_block_op407//       CHECK:   return %[[OP0]], %[[OP1]]408 409// -----410 411// Operation with identical region with multiple statements CSE.412func.func @cse_single_block_ops_identical_bodies(%a : tensor<?x?xf32>, %b : tensor<?x?xf32>, %c : f32, %d : i1)413  -> (tensor<?x?xf32>, tensor<?x?xf32>) {414  %0 = test.cse_of_single_block_op inputs(%a, %b) {415    ^bb0(%arg0 : f32, %arg1 : f32):416    %1 = arith.divf %arg0, %arg1 : f32417    %2 = arith.remf %arg0, %c : f32418    %3 = arith.select %d, %1, %2 : f32419    test.region_yield %3 : f32420  } : tensor<?x?xf32>, tensor<?x?xf32> -> tensor<?x?xf32>421  %1 = test.cse_of_single_block_op inputs(%a, %b) {422    ^bb0(%arg0 : f32, %arg1 : f32):423    %1 = arith.divf %arg0, %arg1 : f32424    %2 = arith.remf %arg0, %c : f32425    %3 = arith.select %d, %1, %2 : f32426    test.region_yield %3 : f32427  } : tensor<?x?xf32>, tensor<?x?xf32> -> tensor<?x?xf32>428  return %0, %1 : tensor<?x?xf32>, tensor<?x?xf32>429}430// CHECK-LABEL: func @cse_single_block_ops_identical_bodies431//       CHECK:   %[[OP:.+]] = test.cse_of_single_block_op432//   CHECK-NOT:   test.cse_of_single_block_op433//       CHECK:   return %[[OP]], %[[OP]]434 435// -----436 437// Operation with non-identical regions dont CSE.438func.func @no_cse_single_block_ops_different_bodies(%a : tensor<?x?xf32>, %b : tensor<?x?xf32>, %c : f32, %d : i1)439  -> (tensor<?x?xf32>, tensor<?x?xf32>) {440  %0 = test.cse_of_single_block_op inputs(%a, %b) {441    ^bb0(%arg0 : f32, %arg1 : f32):442    %1 = arith.divf %arg0, %arg1 : f32443    %2 = arith.remf %arg0, %c : f32444    %3 = arith.select %d, %1, %2 : f32445    test.region_yield %3 : f32446  } : tensor<?x?xf32>, tensor<?x?xf32> -> tensor<?x?xf32>447  %1 = test.cse_of_single_block_op inputs(%a, %b) {448    ^bb0(%arg0 : f32, %arg1 : f32):449    %1 = arith.divf %arg0, %arg1 : f32450    %2 = arith.remf %arg0, %c : f32451    %3 = arith.select %d, %2, %1 : f32452    test.region_yield %3 : f32453  } : tensor<?x?xf32>, tensor<?x?xf32> -> tensor<?x?xf32>454  return %0, %1 : tensor<?x?xf32>, tensor<?x?xf32>455}456// CHECK-LABEL: func @no_cse_single_block_ops_different_bodies457//       CHECK:   %[[OP0:.+]] = test.cse_of_single_block_op458//       CHECK:   %[[OP1:.+]] = test.cse_of_single_block_op459//       CHECK:   return %[[OP0]], %[[OP1]]460 461// -----462 463func.func @failing_issue_59135(%arg0: tensor<2x2xi1>, %arg1: f32, %arg2 : tensor<2xi1>) -> (tensor<2xi1>, tensor<2xi1>) {464  %false_2 = arith.constant false465  %true_5 = arith.constant true466  %9 = test.cse_of_single_block_op inputs(%arg2) {467  ^bb0(%out: i1):468    %true_144 = arith.constant true469    test.region_yield %true_144 : i1470  } : tensor<2xi1> -> tensor<2xi1>471  %15 = test.cse_of_single_block_op inputs(%arg2) {472  ^bb0(%out: i1):473    %true_144 = arith.constant true474    test.region_yield %true_144 : i1475  } : tensor<2xi1> -> tensor<2xi1>476  %93 = arith.maxsi %false_2, %true_5 : i1477  return %9, %15 : tensor<2xi1>, tensor<2xi1>478}479// CHECK-LABEL: func @failing_issue_59135480//       CHECK:   %[[TRUE:.+]] = arith.constant true481//       CHECK:   %[[OP:.+]] = test.cse_of_single_block_op482//       CHECK:     test.region_yield %[[TRUE]]483//       CHECK:   return %[[OP]], %[[OP]]484 485// -----486 487func.func @cse_multiple_regions(%c: i1, %t: tensor<5xf32>) -> (tensor<5xf32>, tensor<5xf32>) {488  %r1 = scf.if %c -> (tensor<5xf32>) {489    %0 = tensor.empty() : tensor<5xf32>490    scf.yield %0 : tensor<5xf32>491  } else {492    scf.yield %t : tensor<5xf32>493  }494  %r2 = scf.if %c -> (tensor<5xf32>) {495    %0 = tensor.empty() : tensor<5xf32>496    scf.yield %0 : tensor<5xf32>497  } else {498    scf.yield %t : tensor<5xf32>499  }500  return %r1, %r2 : tensor<5xf32>, tensor<5xf32>501}502// CHECK-LABEL: func @cse_multiple_regions503//       CHECK:   %[[if:.*]] = scf.if {{.*}} {504//       CHECK:     tensor.empty505//       CHECK:     scf.yield506//       CHECK:   } else {507//       CHECK:     scf.yield508//       CHECK:   }509//   CHECK-NOT:   scf.if510//       CHECK:   return %[[if]], %[[if]]511 512// -----513 514// CHECK-LABEL: @cse_recursive_effects_success515func.func @cse_recursive_effects_success() -> (i32, i32, i32) {516  // CHECK-NEXT: %[[READ_VALUE:.*]] = "test.op_with_memread"() : () -> i32517  %0 = "test.op_with_memread"() : () -> (i32)518 519  // do something with recursive effects, containing no side effects520  %true = arith.constant true521  // CHECK-NEXT: %[[TRUE:.+]] = arith.constant true522  // CHECK-NEXT: %[[IF:.+]] = scf.if %[[TRUE]] -> (i32) {523  %1 = scf.if %true -> (i32) {524    %c42 = arith.constant 42 : i32525    scf.yield %c42 : i32526    // CHECK-NEXT: %[[C42:.+]] = arith.constant 42 : i32527    // CHECK-NEXT: scf.yield %[[C42]]528    // CHECK-NEXT: } else {529  } else {530    %c24 = arith.constant 24 : i32531    scf.yield %c24 : i32532    // CHECK-NEXT: %[[C24:.+]] = arith.constant 24 : i32533    // CHECK-NEXT: scf.yield %[[C24]]534    // CHECK-NEXT: }535  }536 537  // %2 can be removed538  // CHECK-NEXT: return %[[READ_VALUE]], %[[READ_VALUE]], %[[IF]] : i32, i32, i32539  %2 = "test.op_with_memread"() : () -> (i32)540  return %0, %2, %1 : i32, i32, i32541}542 543// -----544 545// CHECK-LABEL: @cse_recursive_effects_failure546func.func @cse_recursive_effects_failure() -> (i32, i32, i32) {547  // CHECK-NEXT: %[[READ_VALUE:.*]] = "test.op_with_memread"() : () -> i32548  %0 = "test.op_with_memread"() : () -> (i32)549 550  // do something with recursive effects, containing a write effect551  %true = arith.constant true552  // CHECK-NEXT: %[[TRUE:.+]] = arith.constant true553  // CHECK-NEXT: %[[IF:.+]] = scf.if %[[TRUE]] -> (i32) {554  %1 = scf.if %true -> (i32) {555    "test.op_with_memwrite"() : () -> ()556    // CHECK-NEXT: "test.op_with_memwrite"() : () -> ()557    %c42 = arith.constant 42 : i32558    scf.yield %c42 : i32559    // CHECK-NEXT: %[[C42:.+]] = arith.constant 42 : i32560    // CHECK-NEXT: scf.yield %[[C42]]561    // CHECK-NEXT: } else {562  } else {563    %c24 = arith.constant 24 : i32564    scf.yield %c24 : i32565    // CHECK-NEXT: %[[C24:.+]] = arith.constant 24 : i32566    // CHECK-NEXT: scf.yield %[[C24]]567    // CHECK-NEXT: }568  }569 570  // %2 can not be be removed because of the write571  // CHECK-NEXT: %[[READ_VALUE2:.*]] = "test.op_with_memread"() : () -> i32572  // CHECK-NEXT: return %[[READ_VALUE]], %[[READ_VALUE2]], %[[IF]] : i32, i32, i32573  %2 = "test.op_with_memread"() : () -> (i32)574  return %0, %2, %1 : i32, i32, i32575}576