xref: /llvm-project/mlir/test/Transforms/cse.mlir (revision c315c01a7ea92b562f8b63159e113abaf0b50e5a)
1*c315c01aSMatthias Springer// RUN: mlir-opt -allow-unregistered-dialect %s -pass-pipeline='builtin.module(func.func(cse))' -split-input-file | FileCheck %s
27669a259SRiver Riddle
38d62a609SMLIR Team// CHECK-LABEL: @simple_constant
4cda6aa78SRiver Riddlefunc.func @simple_constant() -> (i32, i32) {
5435debeaSNicolas Vasilache  // CHECK-NEXT: %[[VAR_c1_i32:.*]] = arith.constant 1 : i32
6a54f4eaeSMogball  %0 = arith.constant 1 : i32
77669a259SRiver Riddle
8435debeaSNicolas Vasilache  // CHECK-NEXT: return %[[VAR_c1_i32]], %[[VAR_c1_i32]] : i32, i32
9a54f4eaeSMogball  %1 = arith.constant 1 : i32
107669a259SRiver Riddle  return %0, %1 : i32, i32
117669a259SRiver Riddle}
127669a259SRiver Riddle
13*c315c01aSMatthias Springer// -----
14*c315c01aSMatthias Springer
15*c315c01aSMatthias Springer// CHECK: #[[$MAP:.*]] = affine_map<(d0) -> (d0 mod 2)>
16*c315c01aSMatthias Springer#map0 = affine_map<(d0) -> (d0 mod 2)>
17*c315c01aSMatthias Springer
188d62a609SMLIR Team// CHECK-LABEL: @basic
19cda6aa78SRiver Riddlefunc.func @basic() -> (index, index) {
20435debeaSNicolas Vasilache  // CHECK: %[[VAR_c0:[0-9a-zA-Z_]+]] = arith.constant 0 : index
21a54f4eaeSMogball  %c0 = arith.constant 0 : index
22a54f4eaeSMogball  %c1 = arith.constant 0 : index
237669a259SRiver Riddle
24435debeaSNicolas Vasilache  // CHECK-NEXT: %[[VAR_0:[0-9a-zA-Z_]+]] = affine.apply #[[$MAP]](%[[VAR_c0]])
253227dee1SRiver Riddle  %0 = affine.apply #map0(%c0)
263227dee1SRiver Riddle  %1 = affine.apply #map0(%c1)
277669a259SRiver Riddle
28435debeaSNicolas Vasilache  // CHECK-NEXT: return %[[VAR_0]], %[[VAR_0]] : index, index
297669a259SRiver Riddle  return %0, %1 : index, index
307669a259SRiver Riddle}
317669a259SRiver Riddle
32*c315c01aSMatthias Springer// -----
33*c315c01aSMatthias Springer
348d62a609SMLIR Team// CHECK-LABEL: @many
35cda6aa78SRiver Riddlefunc.func @many(f32, f32) -> (f32) {
368ef2552dSChris Lattner^bb0(%a : f32, %b : f32):
37435debeaSNicolas Vasilache  // CHECK-NEXT: %[[VAR_0:[0-9a-zA-Z_]+]] = arith.addf %{{.*}}, %{{.*}} : f32
38a54f4eaeSMogball  %c = arith.addf %a, %b : f32
39a54f4eaeSMogball  %d = arith.addf %a, %b : f32
40a54f4eaeSMogball  %e = arith.addf %a, %b : f32
41a54f4eaeSMogball  %f = arith.addf %a, %b : f32
427669a259SRiver Riddle
43435debeaSNicolas Vasilache  // CHECK-NEXT: %[[VAR_1:[0-9a-zA-Z_]+]] = arith.addf %[[VAR_0]], %[[VAR_0]] : f32
44a54f4eaeSMogball  %g = arith.addf %c, %d : f32
45a54f4eaeSMogball  %h = arith.addf %e, %f : f32
46a54f4eaeSMogball  %i = arith.addf %c, %e : f32
477669a259SRiver Riddle
48435debeaSNicolas Vasilache  // CHECK-NEXT: %[[VAR_2:[0-9a-zA-Z_]+]] = arith.addf %[[VAR_1]], %[[VAR_1]] : f32
49a54f4eaeSMogball  %j = arith.addf %g, %h : f32
50a54f4eaeSMogball  %k = arith.addf %h, %i : f32
517669a259SRiver Riddle
52435debeaSNicolas Vasilache  // CHECK-NEXT: %[[VAR_3:[0-9a-zA-Z_]+]] = arith.addf %[[VAR_2]], %[[VAR_2]] : f32
53a54f4eaeSMogball  %l = arith.addf %j, %k : f32
547669a259SRiver Riddle
55435debeaSNicolas Vasilache  // CHECK-NEXT: return %[[VAR_3]] : f32
567669a259SRiver Riddle  return %l : f32
577669a259SRiver Riddle}
587669a259SRiver Riddle
59*c315c01aSMatthias Springer// -----
60*c315c01aSMatthias Springer
617669a259SRiver Riddle/// Check that operations are not eliminated if they have different operands.
628d62a609SMLIR Team// CHECK-LABEL: @different_ops
63cda6aa78SRiver Riddlefunc.func @different_ops() -> (i32, i32) {
64435debeaSNicolas Vasilache  // CHECK: %[[VAR_c0_i32:[0-9a-zA-Z_]+]] = arith.constant 0 : i32
65435debeaSNicolas Vasilache  // CHECK: %[[VAR_c1_i32:[0-9a-zA-Z_]+]] = arith.constant 1 : i32
66a54f4eaeSMogball  %0 = arith.constant 0 : i32
67a54f4eaeSMogball  %1 = arith.constant 1 : i32
687669a259SRiver Riddle
69435debeaSNicolas Vasilache  // CHECK-NEXT: return %[[VAR_c0_i32]], %[[VAR_c1_i32]] : i32, i32
707669a259SRiver Riddle  return %0, %1 : i32, i32
717669a259SRiver Riddle}
727669a259SRiver Riddle
73*c315c01aSMatthias Springer// -----
74*c315c01aSMatthias Springer
757669a259SRiver Riddle/// Check that operations are not eliminated if they have different result
767669a259SRiver Riddle/// types.
778d62a609SMLIR Team// CHECK-LABEL: @different_results
78cda6aa78SRiver Riddlefunc.func @different_results(%arg0: tensor<*xf32>) -> (tensor<?x?xf32>, tensor<4x?xf32>) {
79435debeaSNicolas Vasilache  // CHECK: %[[VAR_0:[0-9a-zA-Z_]+]] = tensor.cast %{{.*}} : tensor<*xf32> to tensor<?x?xf32>
80435debeaSNicolas Vasilache  // CHECK-NEXT: %[[VAR_1:[0-9a-zA-Z_]+]] = tensor.cast %{{.*}} : tensor<*xf32> to tensor<4x?xf32>
81129d6e55SSean Silva  %0 = tensor.cast %arg0 : tensor<*xf32> to tensor<?x?xf32>
82129d6e55SSean Silva  %1 = tensor.cast %arg0 : tensor<*xf32> to tensor<4x?xf32>
837669a259SRiver Riddle
84435debeaSNicolas Vasilache  // CHECK-NEXT: return %[[VAR_0]], %[[VAR_1]] : tensor<?x?xf32>, tensor<4x?xf32>
857669a259SRiver Riddle  return %0, %1 : tensor<?x?xf32>, tensor<4x?xf32>
867669a259SRiver Riddle}
877669a259SRiver Riddle
88*c315c01aSMatthias Springer// -----
89*c315c01aSMatthias Springer
907669a259SRiver Riddle/// Check that operations are not eliminated if they have different attributes.
918d62a609SMLIR Team// CHECK-LABEL: @different_attributes
92cda6aa78SRiver Riddlefunc.func @different_attributes(index, index) -> (i1, i1, i1) {
938ef2552dSChris Lattner^bb0(%a : index, %b : index):
94435debeaSNicolas Vasilache  // CHECK: %[[VAR_0:[0-9a-zA-Z_]+]] = arith.cmpi slt, %{{.*}}, %{{.*}} : index
95a54f4eaeSMogball  %0 = arith.cmpi slt, %a, %b : index
967669a259SRiver Riddle
97435debeaSNicolas Vasilache  // CHECK-NEXT: %[[VAR_1:[0-9a-zA-Z_]+]] = arith.cmpi ne, %{{.*}}, %{{.*}} : index
987669a259SRiver Riddle  /// Predicate 1 means inequality comparison.
99a54f4eaeSMogball  %1 = arith.cmpi ne, %a, %b : index
100a54f4eaeSMogball  %2 = "arith.cmpi"(%a, %b) {predicate = 1} : (index, index) -> i1
1017669a259SRiver Riddle
102435debeaSNicolas Vasilache  // CHECK-NEXT: return %[[VAR_0]], %[[VAR_1]], %[[VAR_1]] : i1, i1, i1
1037669a259SRiver Riddle  return %0, %1, %2 : i1, i1, i1
1047669a259SRiver Riddle}
1057669a259SRiver Riddle
106*c315c01aSMatthias Springer// -----
107*c315c01aSMatthias Springer
1087669a259SRiver Riddle/// Check that operations with side effects are not eliminated.
1098d62a609SMLIR Team// CHECK-LABEL: @side_effect
110cda6aa78SRiver Riddlefunc.func @side_effect() -> (memref<2x1xf32>, memref<2x1xf32>) {
111435debeaSNicolas Vasilache  // CHECK: %[[VAR_0:[0-9a-zA-Z_]+]] = memref.alloc() : memref<2x1xf32>
112e2310704SJulian Gross  %0 = memref.alloc() : memref<2x1xf32>
1137669a259SRiver Riddle
114435debeaSNicolas Vasilache  // CHECK-NEXT: %[[VAR_1:[0-9a-zA-Z_]+]] = memref.alloc() : memref<2x1xf32>
115e2310704SJulian Gross  %1 = memref.alloc() : memref<2x1xf32>
1167669a259SRiver Riddle
117435debeaSNicolas Vasilache  // CHECK-NEXT: return %[[VAR_0]], %[[VAR_1]] : memref<2x1xf32>, memref<2x1xf32>
1187669a259SRiver Riddle  return %0, %1 : memref<2x1xf32>, memref<2x1xf32>
1197669a259SRiver Riddle}
1207669a259SRiver Riddle
121*c315c01aSMatthias Springer// -----
122*c315c01aSMatthias Springer
1237669a259SRiver Riddle/// Check that operation definitions are properly propagated down the dominance
1247669a259SRiver Riddle/// tree.
1258d62a609SMLIR Team// CHECK-LABEL: @down_propagate_for
126cda6aa78SRiver Riddlefunc.func @down_propagate_for() {
127435debeaSNicolas Vasilache  // CHECK: %[[VAR_c1_i32:[0-9a-zA-Z_]+]] = arith.constant 1 : i32
128a54f4eaeSMogball  %0 = arith.constant 1 : i32
1297669a259SRiver Riddle
13089bc449cSRiver Riddle  // CHECK-NEXT: affine.for {{.*}} = 0 to 4 {
131832567b3SRiver Riddle  affine.for %i = 0 to 4 {
132435debeaSNicolas Vasilache    // CHECK-NEXT: "foo"(%[[VAR_c1_i32]], %[[VAR_c1_i32]]) : (i32, i32) -> ()
133a54f4eaeSMogball    %1 = arith.constant 1 : i32
1347669a259SRiver Riddle    "foo"(%0, %1) : (i32, i32) -> ()
1357669a259SRiver Riddle  }
1367669a259SRiver Riddle  return
1377669a259SRiver Riddle}
1387669a259SRiver Riddle
139*c315c01aSMatthias Springer// -----
140*c315c01aSMatthias Springer
1418d62a609SMLIR Team// CHECK-LABEL: @down_propagate
142cda6aa78SRiver Riddlefunc.func @down_propagate() -> i32 {
143435debeaSNicolas Vasilache  // CHECK-NEXT: %[[VAR_c1_i32:[0-9a-zA-Z_]+]] = arith.constant 1 : i32
144a54f4eaeSMogball  %0 = arith.constant 1 : i32
1457669a259SRiver Riddle
146435debeaSNicolas Vasilache  // CHECK-NEXT: %[[VAR_true:[0-9a-zA-Z_]+]] = arith.constant true
147a54f4eaeSMogball  %cond = arith.constant true
1487669a259SRiver Riddle
149435debeaSNicolas Vasilache  // CHECK-NEXT: cf.cond_br %[[VAR_true]], ^bb1, ^bb2(%[[VAR_c1_i32]] : i32)
150ace01605SRiver Riddle  cf.cond_br %cond, ^bb1, ^bb2(%0 : i32)
1517669a259SRiver Riddle
15237579ae8SChris Lattner^bb1: // CHECK: ^bb1:
153435debeaSNicolas Vasilache  // CHECK-NEXT: cf.br ^bb2(%[[VAR_c1_i32]] : i32)
154a54f4eaeSMogball  %1 = arith.constant 1 : i32
155ace01605SRiver Riddle  cf.br ^bb2(%1 : i32)
1567669a259SRiver Riddle
15737579ae8SChris Lattner^bb2(%arg : i32):
1587669a259SRiver Riddle  return %arg : i32
1597669a259SRiver Riddle}
1607669a259SRiver Riddle
161*c315c01aSMatthias Springer// -----
162*c315c01aSMatthias Springer
1637669a259SRiver Riddle/// Check that operation definitions are NOT propagated up the dominance tree.
1648d62a609SMLIR Team// CHECK-LABEL: @up_propagate_for
165cda6aa78SRiver Riddlefunc.func @up_propagate_for() -> i32 {
16689bc449cSRiver Riddle  // CHECK: affine.for {{.*}} = 0 to 4 {
167832567b3SRiver Riddle  affine.for %i = 0 to 4 {
168435debeaSNicolas Vasilache    // CHECK-NEXT: %[[VAR_c1_i32_0:[0-9a-zA-Z_]+]] = arith.constant 1 : i32
169435debeaSNicolas Vasilache    // CHECK-NEXT: "foo"(%[[VAR_c1_i32_0]]) : (i32) -> ()
170a54f4eaeSMogball    %0 = arith.constant 1 : i32
1717669a259SRiver Riddle    "foo"(%0) : (i32) -> ()
1727669a259SRiver Riddle  }
1737669a259SRiver Riddle
174435debeaSNicolas Vasilache  // CHECK: %[[VAR_c1_i32:[0-9a-zA-Z_]+]] = arith.constant 1 : i32
175435debeaSNicolas Vasilache  // CHECK-NEXT: return %[[VAR_c1_i32]] : i32
176a54f4eaeSMogball  %1 = arith.constant 1 : i32
1777669a259SRiver Riddle  return %1 : i32
1787669a259SRiver Riddle}
1797669a259SRiver Riddle
180*c315c01aSMatthias Springer// -----
181*c315c01aSMatthias Springer
1828d62a609SMLIR Team// CHECK-LABEL: func @up_propagate
183cda6aa78SRiver Riddlefunc.func @up_propagate() -> i32 {
184435debeaSNicolas Vasilache  // CHECK-NEXT:  %[[VAR_c0_i32:[0-9a-zA-Z_]+]] = arith.constant 0 : i32
185a54f4eaeSMogball  %0 = arith.constant 0 : i32
1867669a259SRiver Riddle
187435debeaSNicolas Vasilache  // CHECK-NEXT: %[[VAR_true:[0-9a-zA-Z_]+]] = arith.constant true
188a54f4eaeSMogball  %cond = arith.constant true
1897669a259SRiver Riddle
190435debeaSNicolas Vasilache  // CHECK-NEXT: cf.cond_br %[[VAR_true]], ^bb1, ^bb2(%[[VAR_c0_i32]] : i32)
191ace01605SRiver Riddle  cf.cond_br %cond, ^bb1, ^bb2(%0 : i32)
1927669a259SRiver Riddle
19337579ae8SChris Lattner^bb1: // CHECK: ^bb1:
194435debeaSNicolas Vasilache  // CHECK-NEXT: %[[VAR_c1_i32:[0-9a-zA-Z_]+]] = arith.constant 1 : i32
195a54f4eaeSMogball  %1 = arith.constant 1 : i32
1967669a259SRiver Riddle
197435debeaSNicolas Vasilache  // CHECK-NEXT: cf.br ^bb2(%[[VAR_c1_i32]] : i32)
198ace01605SRiver Riddle  cf.br ^bb2(%1 : i32)
1997669a259SRiver Riddle
20037579ae8SChris Lattner^bb2(%arg : i32): // CHECK: ^bb2
201435debeaSNicolas Vasilache  // CHECK-NEXT: %[[VAR_c1_i32_0:[0-9a-zA-Z_]+]] = arith.constant 1 : i32
202a54f4eaeSMogball  %2 = arith.constant 1 : i32
2037669a259SRiver Riddle
204435debeaSNicolas Vasilache  // CHECK-NEXT: %[[VAR_1:[0-9a-zA-Z_]+]] = arith.addi %{{.*}}, %[[VAR_c1_i32_0]] : i32
205a54f4eaeSMogball  %add = arith.addi %arg, %2 : i32
2067669a259SRiver Riddle
207435debeaSNicolas Vasilache  // CHECK-NEXT: return %[[VAR_1]] : i32
2087669a259SRiver Riddle  return %add : i32
209cdbfd484SRiver Riddle}
210cdbfd484SRiver Riddle
211*c315c01aSMatthias Springer// -----
212*c315c01aSMatthias Springer
213cdbfd484SRiver Riddle/// The same test as above except that we are testing on a cfg embedded within
214cdbfd484SRiver Riddle/// an operation region.
2158d62a609SMLIR Team// CHECK-LABEL: func @up_propagate_region
216cda6aa78SRiver Riddlefunc.func @up_propagate_region() -> i32 {
217435debeaSNicolas Vasilache  // CHECK-NEXT: {{.*}} "foo.region"
218d3380a50SAlex Zinenko  %0 = "foo.region"() ({
219435debeaSNicolas Vasilache    // CHECK-NEXT:  %[[VAR_c0_i32:[0-9a-zA-Z_]+]] = arith.constant 0 : i32
220435debeaSNicolas Vasilache    // CHECK-NEXT: %[[VAR_true:[0-9a-zA-Z_]+]] = arith.constant true
221ace01605SRiver Riddle    // CHECK-NEXT: cf.cond_br
222cdbfd484SRiver Riddle
223a54f4eaeSMogball    %1 = arith.constant 0 : i32
224a54f4eaeSMogball    %true = arith.constant true
225ace01605SRiver Riddle    cf.cond_br %true, ^bb1, ^bb2(%1 : i32)
226cdbfd484SRiver Riddle
22789bc449cSRiver Riddle  ^bb1: // CHECK: ^bb1:
228435debeaSNicolas Vasilache    // CHECK-NEXT: %[[VAR_c1_i32:[0-9a-zA-Z_]+]] = arith.constant 1 : i32
229ace01605SRiver Riddle    // CHECK-NEXT: cf.br
230cdbfd484SRiver Riddle
231a54f4eaeSMogball    %c1_i32 = arith.constant 1 : i32
232ace01605SRiver Riddle    cf.br ^bb2(%c1_i32 : i32)
233cdbfd484SRiver Riddle
234435debeaSNicolas Vasilache  ^bb2(%arg : i32): // CHECK: ^bb2(%[[VAR_1:.*]]: i32):
235435debeaSNicolas Vasilache    // CHECK-NEXT: %[[VAR_c1_i32_0:[0-9a-zA-Z_]+]] = arith.constant 1 : i32
236435debeaSNicolas Vasilache    // CHECK-NEXT: %[[VAR_2:[0-9a-zA-Z_]+]] = arith.addi %[[VAR_1]], %[[VAR_c1_i32_0]] : i32
237435debeaSNicolas Vasilache    // CHECK-NEXT: "foo.yield"(%[[VAR_2]]) : (i32) -> ()
238cdbfd484SRiver Riddle
239a54f4eaeSMogball    %c1_i32_0 = arith.constant 1 : i32
240a54f4eaeSMogball    %2 = arith.addi %arg, %c1_i32_0 : i32
241cdbfd484SRiver Riddle    "foo.yield" (%2) : (i32) -> ()
242d3380a50SAlex Zinenko  }) : () -> (i32)
243cdbfd484SRiver Riddle  return %0 : i32
2447669a259SRiver Riddle}
245b67cab4cSRiver Riddle
246*c315c01aSMatthias Springer// -----
247*c315c01aSMatthias Springer
248b67cab4cSRiver Riddle/// This test checks that nested regions that are isolated from above are
249b67cab4cSRiver Riddle/// properly handled.
250b67cab4cSRiver Riddle// CHECK-LABEL: @nested_isolated
251cda6aa78SRiver Riddlefunc.func @nested_isolated() -> i32 {
252a54f4eaeSMogball  // CHECK-NEXT: arith.constant 1
253a54f4eaeSMogball  %0 = arith.constant 1 : i32
254b67cab4cSRiver Riddle
2557d055af1SJoshua Cao  // CHECK-NEXT: builtin.module
256b67cab4cSRiver Riddle  // CHECK-NEXT: @nested_func
2577d055af1SJoshua Cao  builtin.module {
25836550692SRiver Riddle    func.func @nested_func() {
259a54f4eaeSMogball      // CHECK-NEXT: arith.constant 1
260a54f4eaeSMogball      %foo = arith.constant 1 : i32
261b67cab4cSRiver Riddle      "foo.yield"(%foo) : (i32) -> ()
262b67cab4cSRiver Riddle    }
2637d055af1SJoshua Cao  }
264b67cab4cSRiver Riddle
265b67cab4cSRiver Riddle  // CHECK: "foo.region"
266b67cab4cSRiver Riddle  "foo.region"() ({
267a54f4eaeSMogball    // CHECK-NEXT: arith.constant 1
268a54f4eaeSMogball    %foo = arith.constant 1 : i32
269b67cab4cSRiver Riddle    "foo.yield"(%foo) : (i32) -> ()
270b67cab4cSRiver Riddle  }) : () -> ()
271b67cab4cSRiver Riddle
272b67cab4cSRiver Riddle  return %0 : i32
273b67cab4cSRiver Riddle}
2749c61c76bSAndrew Young
275*c315c01aSMatthias Springer// -----
276*c315c01aSMatthias Springer
2779c61c76bSAndrew Young/// This test is checking that CSE gracefully handles values in graph regions
2789c61c76bSAndrew Young/// where the use occurs before the def, and one of the defs could be CSE'd with
2799c61c76bSAndrew Young/// the other.
2809c61c76bSAndrew Young// CHECK-LABEL: @use_before_def
281cda6aa78SRiver Riddlefunc.func @use_before_def() {
2829c61c76bSAndrew Young  // CHECK-NEXT: test.graph_region
2839c61c76bSAndrew Young  test.graph_region {
284435debeaSNicolas Vasilache    // CHECK-NEXT: arith.addi
285a54f4eaeSMogball    %0 = arith.addi %1, %2 : i32
2869c61c76bSAndrew Young
287a54f4eaeSMogball    // CHECK-NEXT: arith.constant 1
288a54f4eaeSMogball    // CHECK-NEXT: arith.constant 1
289a54f4eaeSMogball    %1 = arith.constant 1 : i32
290a54f4eaeSMogball    %2 = arith.constant 1 : i32
2919c61c76bSAndrew Young
292435debeaSNicolas Vasilache    // CHECK-NEXT: "foo.yield"(%{{.*}}) : (i32) -> ()
2939c61c76bSAndrew Young    "foo.yield"(%0) : (i32) -> ()
2949c61c76bSAndrew Young  }
2959c61c76bSAndrew Young  return
2969c61c76bSAndrew Young}
29702da9643SValentin Clement
298*c315c01aSMatthias Springer// -----
299*c315c01aSMatthias Springer
30002da9643SValentin Clement/// This test is checking that CSE is removing duplicated read op that follow
30102da9643SValentin Clement/// other.
30202da9643SValentin Clement// CHECK-LABEL: @remove_direct_duplicated_read_op
303cda6aa78SRiver Riddlefunc.func @remove_direct_duplicated_read_op() -> i32 {
30402da9643SValentin Clement  // CHECK-NEXT: %[[READ_VALUE:.*]] = "test.op_with_memread"() : () -> i32
30502da9643SValentin Clement  %0 = "test.op_with_memread"() : () -> (i32)
30602da9643SValentin Clement  %1 = "test.op_with_memread"() : () -> (i32)
30702da9643SValentin Clement  // CHECK-NEXT: %{{.*}} = arith.addi %[[READ_VALUE]], %[[READ_VALUE]] : i32
30802da9643SValentin Clement  %2 = arith.addi %0, %1 : i32
30902da9643SValentin Clement  return %2 : i32
31002da9643SValentin Clement}
31102da9643SValentin Clement
312*c315c01aSMatthias Springer// -----
313*c315c01aSMatthias Springer
31402da9643SValentin Clement/// This test is checking that CSE is removing duplicated read op that follow
31502da9643SValentin Clement/// other.
31602da9643SValentin Clement// CHECK-LABEL: @remove_multiple_duplicated_read_op
317cda6aa78SRiver Riddlefunc.func @remove_multiple_duplicated_read_op() -> i64 {
31802da9643SValentin Clement  // CHECK: %[[READ_VALUE:.*]] = "test.op_with_memread"() : () -> i64
31902da9643SValentin Clement  %0 = "test.op_with_memread"() : () -> (i64)
32002da9643SValentin Clement  %1 = "test.op_with_memread"() : () -> (i64)
32102da9643SValentin Clement  // CHECK-NEXT: %{{.*}} = arith.addi %{{.*}}, %[[READ_VALUE]] : i64
32202da9643SValentin Clement  %2 = arith.addi %0, %1 : i64
32302da9643SValentin Clement  %3 = "test.op_with_memread"() : () -> (i64)
32402da9643SValentin Clement  // CHECK-NEXT: %{{.*}} = arith.addi %{{.*}}, %{{.*}} : i64
32502da9643SValentin Clement  %4 = arith.addi %2, %3 : i64
32602da9643SValentin Clement  %5 = "test.op_with_memread"() : () -> (i64)
32702da9643SValentin Clement  // CHECK-NEXT: %{{.*}} = arith.addi %{{.*}}, %{{.*}} : i64
32802da9643SValentin Clement  %6 = arith.addi %4, %5 : i64
32902da9643SValentin Clement  // CHECK-NEXT: return %{{.*}} : i64
33002da9643SValentin Clement  return %6 : i64
33102da9643SValentin Clement}
33202da9643SValentin Clement
333*c315c01aSMatthias Springer// -----
334*c315c01aSMatthias Springer
33502da9643SValentin Clement/// This test is checking that CSE is not removing duplicated read op that
33602da9643SValentin Clement/// have write op in between.
33702da9643SValentin Clement// CHECK-LABEL: @dont_remove_duplicated_read_op_with_sideeffecting
338cda6aa78SRiver Riddlefunc.func @dont_remove_duplicated_read_op_with_sideeffecting() -> i32 {
33902da9643SValentin Clement  // CHECK-NEXT: %[[READ_VALUE0:.*]] = "test.op_with_memread"() : () -> i32
34002da9643SValentin Clement  %0 = "test.op_with_memread"() : () -> (i32)
34102da9643SValentin Clement  "test.op_with_memwrite"() : () -> ()
34202da9643SValentin Clement  // CHECK: %[[READ_VALUE1:.*]] = "test.op_with_memread"() : () -> i32
34302da9643SValentin Clement  %1 = "test.op_with_memread"() : () -> (i32)
34402da9643SValentin Clement  // CHECK-NEXT: %{{.*}} = arith.addi %[[READ_VALUE0]], %[[READ_VALUE1]] : i32
34502da9643SValentin Clement  %2 = arith.addi %0, %1 : i32
34602da9643SValentin Clement  return %2 : i32
34702da9643SValentin Clement}
348bd514967SValentin Clement
349*c315c01aSMatthias Springer// -----
350*c315c01aSMatthias Springer
351fcaf6dd5SMahesh Ravishankar// Check that an operation with a single region can CSE.
352fcaf6dd5SMahesh Ravishankarfunc.func @cse_single_block_ops(%a : tensor<?x?xf32>, %b : tensor<?x?xf32>)
353fcaf6dd5SMahesh Ravishankar  -> (tensor<?x?xf32>, tensor<?x?xf32>) {
354fcaf6dd5SMahesh Ravishankar  %0 = test.cse_of_single_block_op inputs(%a, %b) {
355fcaf6dd5SMahesh Ravishankar    ^bb0(%arg0 : f32):
356fcaf6dd5SMahesh Ravishankar    test.region_yield %arg0 : f32
357fcaf6dd5SMahesh Ravishankar  } : tensor<?x?xf32>, tensor<?x?xf32> -> tensor<?x?xf32>
358fcaf6dd5SMahesh Ravishankar  %1 = test.cse_of_single_block_op inputs(%a, %b) {
359fcaf6dd5SMahesh Ravishankar    ^bb0(%arg0 : f32):
360fcaf6dd5SMahesh Ravishankar    test.region_yield %arg0 : f32
361fcaf6dd5SMahesh Ravishankar  } : tensor<?x?xf32>, tensor<?x?xf32> -> tensor<?x?xf32>
362fcaf6dd5SMahesh Ravishankar  return %0, %1 : tensor<?x?xf32>, tensor<?x?xf32>
363fcaf6dd5SMahesh Ravishankar}
364fcaf6dd5SMahesh Ravishankar// CHECK-LABEL: func @cse_single_block_ops
365fcaf6dd5SMahesh Ravishankar//       CHECK:   %[[OP:.+]] = test.cse_of_single_block_op
366fcaf6dd5SMahesh Ravishankar//   CHECK-NOT:   test.cse_of_single_block_op
367fcaf6dd5SMahesh Ravishankar//       CHECK:   return %[[OP]], %[[OP]]
368fcaf6dd5SMahesh Ravishankar
369*c315c01aSMatthias Springer// -----
370*c315c01aSMatthias Springer
371fcaf6dd5SMahesh Ravishankar// Operations with different number of bbArgs dont CSE.
372fcaf6dd5SMahesh Ravishankarfunc.func @no_cse_varied_bbargs(%a : tensor<?x?xf32>, %b : tensor<?x?xf32>)
373fcaf6dd5SMahesh Ravishankar  -> (tensor<?x?xf32>, tensor<?x?xf32>) {
374fcaf6dd5SMahesh Ravishankar  %0 = test.cse_of_single_block_op inputs(%a, %b) {
375fcaf6dd5SMahesh Ravishankar    ^bb0(%arg0 : f32, %arg1 : f32):
376fcaf6dd5SMahesh Ravishankar    test.region_yield %arg0 : f32
377fcaf6dd5SMahesh Ravishankar  } : tensor<?x?xf32>, tensor<?x?xf32> -> tensor<?x?xf32>
378fcaf6dd5SMahesh Ravishankar  %1 = test.cse_of_single_block_op inputs(%a, %b) {
379fcaf6dd5SMahesh Ravishankar    ^bb0(%arg0 : f32):
380fcaf6dd5SMahesh Ravishankar    test.region_yield %arg0 : f32
381fcaf6dd5SMahesh Ravishankar  } : tensor<?x?xf32>, tensor<?x?xf32> -> tensor<?x?xf32>
382fcaf6dd5SMahesh Ravishankar  return %0, %1 : tensor<?x?xf32>, tensor<?x?xf32>
383fcaf6dd5SMahesh Ravishankar}
384fcaf6dd5SMahesh Ravishankar// CHECK-LABEL: func @no_cse_varied_bbargs
385fcaf6dd5SMahesh Ravishankar//       CHECK:   %[[OP0:.+]] = test.cse_of_single_block_op
386fcaf6dd5SMahesh Ravishankar//       CHECK:   %[[OP1:.+]] = test.cse_of_single_block_op
387fcaf6dd5SMahesh Ravishankar//       CHECK:   return %[[OP0]], %[[OP1]]
388fcaf6dd5SMahesh Ravishankar
389*c315c01aSMatthias Springer// -----
390*c315c01aSMatthias Springer
391fcaf6dd5SMahesh Ravishankar// Operations with different regions dont CSE
392fcaf6dd5SMahesh Ravishankarfunc.func @no_cse_region_difference_simple(%a : tensor<?x?xf32>, %b : tensor<?x?xf32>)
393fcaf6dd5SMahesh Ravishankar  -> (tensor<?x?xf32>, tensor<?x?xf32>) {
394fcaf6dd5SMahesh Ravishankar  %0 = test.cse_of_single_block_op inputs(%a, %b) {
395fcaf6dd5SMahesh Ravishankar    ^bb0(%arg0 : f32, %arg1 : f32):
396fcaf6dd5SMahesh Ravishankar    test.region_yield %arg0 : f32
397fcaf6dd5SMahesh Ravishankar  } : tensor<?x?xf32>, tensor<?x?xf32> -> tensor<?x?xf32>
398fcaf6dd5SMahesh Ravishankar  %1 = test.cse_of_single_block_op inputs(%a, %b) {
399fcaf6dd5SMahesh Ravishankar    ^bb0(%arg0 : f32, %arg1 : f32):
400fcaf6dd5SMahesh Ravishankar    test.region_yield %arg1 : f32
401fcaf6dd5SMahesh Ravishankar  } : tensor<?x?xf32>, tensor<?x?xf32> -> tensor<?x?xf32>
402fcaf6dd5SMahesh Ravishankar  return %0, %1 : tensor<?x?xf32>, tensor<?x?xf32>
403fcaf6dd5SMahesh Ravishankar}
404fcaf6dd5SMahesh Ravishankar// CHECK-LABEL: func @no_cse_region_difference_simple
405fcaf6dd5SMahesh Ravishankar//       CHECK:   %[[OP0:.+]] = test.cse_of_single_block_op
406fcaf6dd5SMahesh Ravishankar//       CHECK:   %[[OP1:.+]] = test.cse_of_single_block_op
407fcaf6dd5SMahesh Ravishankar//       CHECK:   return %[[OP0]], %[[OP1]]
408fcaf6dd5SMahesh Ravishankar
409*c315c01aSMatthias Springer// -----
410*c315c01aSMatthias Springer
411fcaf6dd5SMahesh Ravishankar// Operation with identical region with multiple statements CSE.
412fcaf6dd5SMahesh Ravishankarfunc.func @cse_single_block_ops_identical_bodies(%a : tensor<?x?xf32>, %b : tensor<?x?xf32>, %c : f32, %d : i1)
413fcaf6dd5SMahesh Ravishankar  -> (tensor<?x?xf32>, tensor<?x?xf32>) {
414fcaf6dd5SMahesh Ravishankar  %0 = test.cse_of_single_block_op inputs(%a, %b) {
415fcaf6dd5SMahesh Ravishankar    ^bb0(%arg0 : f32, %arg1 : f32):
416fcaf6dd5SMahesh Ravishankar    %1 = arith.divf %arg0, %arg1 : f32
417fcaf6dd5SMahesh Ravishankar    %2 = arith.remf %arg0, %c : f32
418fcaf6dd5SMahesh Ravishankar    %3 = arith.select %d, %1, %2 : f32
419fcaf6dd5SMahesh Ravishankar    test.region_yield %3 : f32
420fcaf6dd5SMahesh Ravishankar  } : tensor<?x?xf32>, tensor<?x?xf32> -> tensor<?x?xf32>
421fcaf6dd5SMahesh Ravishankar  %1 = test.cse_of_single_block_op inputs(%a, %b) {
422fcaf6dd5SMahesh Ravishankar    ^bb0(%arg0 : f32, %arg1 : f32):
423fcaf6dd5SMahesh Ravishankar    %1 = arith.divf %arg0, %arg1 : f32
424fcaf6dd5SMahesh Ravishankar    %2 = arith.remf %arg0, %c : f32
425fcaf6dd5SMahesh Ravishankar    %3 = arith.select %d, %1, %2 : f32
426fcaf6dd5SMahesh Ravishankar    test.region_yield %3 : f32
427fcaf6dd5SMahesh Ravishankar  } : tensor<?x?xf32>, tensor<?x?xf32> -> tensor<?x?xf32>
428fcaf6dd5SMahesh Ravishankar  return %0, %1 : tensor<?x?xf32>, tensor<?x?xf32>
429fcaf6dd5SMahesh Ravishankar}
430fcaf6dd5SMahesh Ravishankar// CHECK-LABEL: func @cse_single_block_ops_identical_bodies
431fcaf6dd5SMahesh Ravishankar//       CHECK:   %[[OP:.+]] = test.cse_of_single_block_op
432fcaf6dd5SMahesh Ravishankar//   CHECK-NOT:   test.cse_of_single_block_op
433fcaf6dd5SMahesh Ravishankar//       CHECK:   return %[[OP]], %[[OP]]
434fcaf6dd5SMahesh Ravishankar
435*c315c01aSMatthias Springer// -----
436*c315c01aSMatthias Springer
437fcaf6dd5SMahesh Ravishankar// Operation with non-identical regions dont CSE.
438fcaf6dd5SMahesh Ravishankarfunc.func @no_cse_single_block_ops_different_bodies(%a : tensor<?x?xf32>, %b : tensor<?x?xf32>, %c : f32, %d : i1)
439fcaf6dd5SMahesh Ravishankar  -> (tensor<?x?xf32>, tensor<?x?xf32>) {
440fcaf6dd5SMahesh Ravishankar  %0 = test.cse_of_single_block_op inputs(%a, %b) {
441fcaf6dd5SMahesh Ravishankar    ^bb0(%arg0 : f32, %arg1 : f32):
442fcaf6dd5SMahesh Ravishankar    %1 = arith.divf %arg0, %arg1 : f32
443fcaf6dd5SMahesh Ravishankar    %2 = arith.remf %arg0, %c : f32
444fcaf6dd5SMahesh Ravishankar    %3 = arith.select %d, %1, %2 : f32
445fcaf6dd5SMahesh Ravishankar    test.region_yield %3 : f32
446fcaf6dd5SMahesh Ravishankar  } : tensor<?x?xf32>, tensor<?x?xf32> -> tensor<?x?xf32>
447fcaf6dd5SMahesh Ravishankar  %1 = test.cse_of_single_block_op inputs(%a, %b) {
448fcaf6dd5SMahesh Ravishankar    ^bb0(%arg0 : f32, %arg1 : f32):
449fcaf6dd5SMahesh Ravishankar    %1 = arith.divf %arg0, %arg1 : f32
450fcaf6dd5SMahesh Ravishankar    %2 = arith.remf %arg0, %c : f32
451fcaf6dd5SMahesh Ravishankar    %3 = arith.select %d, %2, %1 : f32
452fcaf6dd5SMahesh Ravishankar    test.region_yield %3 : f32
453fcaf6dd5SMahesh Ravishankar  } : tensor<?x?xf32>, tensor<?x?xf32> -> tensor<?x?xf32>
454fcaf6dd5SMahesh Ravishankar  return %0, %1 : tensor<?x?xf32>, tensor<?x?xf32>
455fcaf6dd5SMahesh Ravishankar}
456fcaf6dd5SMahesh Ravishankar// CHECK-LABEL: func @no_cse_single_block_ops_different_bodies
457fcaf6dd5SMahesh Ravishankar//       CHECK:   %[[OP0:.+]] = test.cse_of_single_block_op
458fcaf6dd5SMahesh Ravishankar//       CHECK:   %[[OP1:.+]] = test.cse_of_single_block_op
459fcaf6dd5SMahesh Ravishankar//       CHECK:   return %[[OP0]], %[[OP1]]
460fcaf6dd5SMahesh Ravishankar
461*c315c01aSMatthias Springer// -----
462*c315c01aSMatthias Springer
463242d5b2bSMahesh Ravishankarfunc.func @failing_issue_59135(%arg0: tensor<2x2xi1>, %arg1: f32, %arg2 : tensor<2xi1>) -> (tensor<2xi1>, tensor<2xi1>) {
464242d5b2bSMahesh Ravishankar  %false_2 = arith.constant false
465242d5b2bSMahesh Ravishankar  %true_5 = arith.constant true
466242d5b2bSMahesh Ravishankar  %9 = test.cse_of_single_block_op inputs(%arg2) {
467242d5b2bSMahesh Ravishankar  ^bb0(%out: i1):
468242d5b2bSMahesh Ravishankar    %true_144 = arith.constant true
469242d5b2bSMahesh Ravishankar    test.region_yield %true_144 : i1
470242d5b2bSMahesh Ravishankar  } : tensor<2xi1> -> tensor<2xi1>
471242d5b2bSMahesh Ravishankar  %15 = test.cse_of_single_block_op inputs(%arg2) {
472242d5b2bSMahesh Ravishankar  ^bb0(%out: i1):
473242d5b2bSMahesh Ravishankar    %true_144 = arith.constant true
474242d5b2bSMahesh Ravishankar    test.region_yield %true_144 : i1
475242d5b2bSMahesh Ravishankar  } : tensor<2xi1> -> tensor<2xi1>
476242d5b2bSMahesh Ravishankar  %93 = arith.maxsi %false_2, %true_5 : i1
477242d5b2bSMahesh Ravishankar  return %9, %15 : tensor<2xi1>, tensor<2xi1>
478242d5b2bSMahesh Ravishankar}
479242d5b2bSMahesh Ravishankar// CHECK-LABEL: func @failing_issue_59135
480242d5b2bSMahesh Ravishankar//       CHECK:   %[[TRUE:.+]] = arith.constant true
481242d5b2bSMahesh Ravishankar//       CHECK:   %[[OP:.+]] = test.cse_of_single_block_op
482242d5b2bSMahesh Ravishankar//       CHECK:     test.region_yield %[[TRUE]]
483242d5b2bSMahesh Ravishankar//       CHECK:   return %[[OP]], %[[OP]]
484aa4e54f2SMatthias Springer
485*c315c01aSMatthias Springer// -----
486*c315c01aSMatthias Springer
487aa4e54f2SMatthias Springerfunc.func @cse_multiple_regions(%c: i1, %t: tensor<5xf32>) -> (tensor<5xf32>, tensor<5xf32>) {
488aa4e54f2SMatthias Springer  %r1 = scf.if %c -> (tensor<5xf32>) {
489aa4e54f2SMatthias Springer    %0 = tensor.empty() : tensor<5xf32>
490aa4e54f2SMatthias Springer    scf.yield %0 : tensor<5xf32>
491aa4e54f2SMatthias Springer  } else {
492aa4e54f2SMatthias Springer    scf.yield %t : tensor<5xf32>
493aa4e54f2SMatthias Springer  }
494aa4e54f2SMatthias Springer  %r2 = scf.if %c -> (tensor<5xf32>) {
495aa4e54f2SMatthias Springer    %0 = tensor.empty() : tensor<5xf32>
496aa4e54f2SMatthias Springer    scf.yield %0 : tensor<5xf32>
497aa4e54f2SMatthias Springer  } else {
498aa4e54f2SMatthias Springer    scf.yield %t : tensor<5xf32>
499aa4e54f2SMatthias Springer  }
500aa4e54f2SMatthias Springer  return %r1, %r2 : tensor<5xf32>, tensor<5xf32>
501aa4e54f2SMatthias Springer}
502aa4e54f2SMatthias Springer// CHECK-LABEL: func @cse_multiple_regions
503aa4e54f2SMatthias Springer//       CHECK:   %[[if:.*]] = scf.if {{.*}} {
504aa4e54f2SMatthias Springer//       CHECK:     tensor.empty
505aa4e54f2SMatthias Springer//       CHECK:     scf.yield
506aa4e54f2SMatthias Springer//       CHECK:   } else {
507aa4e54f2SMatthias Springer//       CHECK:     scf.yield
508aa4e54f2SMatthias Springer//       CHECK:   }
509aa4e54f2SMatthias Springer//   CHECK-NOT:   scf.if
510aa4e54f2SMatthias Springer//       CHECK:   return %[[if]], %[[if]]
511dea33c80STom Eccles
512*c315c01aSMatthias Springer// -----
513*c315c01aSMatthias Springer
514dea33c80STom Eccles// CHECK-LABEL: @cse_recursive_effects_success
515dea33c80STom Ecclesfunc.func @cse_recursive_effects_success() -> (i32, i32, i32) {
516dea33c80STom Eccles  // CHECK-NEXT: %[[READ_VALUE:.*]] = "test.op_with_memread"() : () -> i32
517dea33c80STom Eccles  %0 = "test.op_with_memread"() : () -> (i32)
518dea33c80STom Eccles
519dea33c80STom Eccles  // do something with recursive effects, containing no side effects
520dea33c80STom Eccles  %true = arith.constant true
521dea33c80STom Eccles  // CHECK-NEXT: %[[TRUE:.+]] = arith.constant true
522dea33c80STom Eccles  // CHECK-NEXT: %[[IF:.+]] = scf.if %[[TRUE]] -> (i32) {
523dea33c80STom Eccles  %1 = scf.if %true -> (i32) {
524dea33c80STom Eccles    %c42 = arith.constant 42 : i32
525dea33c80STom Eccles    scf.yield %c42 : i32
526dea33c80STom Eccles    // CHECK-NEXT: %[[C42:.+]] = arith.constant 42 : i32
527dea33c80STom Eccles    // CHECK-NEXT: scf.yield %[[C42]]
528dea33c80STom Eccles    // CHECK-NEXT: } else {
529dea33c80STom Eccles  } else {
530dea33c80STom Eccles    %c24 = arith.constant 24 : i32
531dea33c80STom Eccles    scf.yield %c24 : i32
532dea33c80STom Eccles    // CHECK-NEXT: %[[C24:.+]] = arith.constant 24 : i32
533dea33c80STom Eccles    // CHECK-NEXT: scf.yield %[[C24]]
534dea33c80STom Eccles    // CHECK-NEXT: }
535dea33c80STom Eccles  }
536dea33c80STom Eccles
537dea33c80STom Eccles  // %2 can be removed
538dea33c80STom Eccles  // CHECK-NEXT: return %[[READ_VALUE]], %[[READ_VALUE]], %[[IF]] : i32, i32, i32
539dea33c80STom Eccles  %2 = "test.op_with_memread"() : () -> (i32)
540dea33c80STom Eccles  return %0, %2, %1 : i32, i32, i32
541dea33c80STom Eccles}
542dea33c80STom Eccles
543*c315c01aSMatthias Springer// -----
544*c315c01aSMatthias Springer
545dea33c80STom Eccles// CHECK-LABEL: @cse_recursive_effects_failure
546dea33c80STom Ecclesfunc.func @cse_recursive_effects_failure() -> (i32, i32, i32) {
547dea33c80STom Eccles  // CHECK-NEXT: %[[READ_VALUE:.*]] = "test.op_with_memread"() : () -> i32
548dea33c80STom Eccles  %0 = "test.op_with_memread"() : () -> (i32)
549dea33c80STom Eccles
550dea33c80STom Eccles  // do something with recursive effects, containing a write effect
551dea33c80STom Eccles  %true = arith.constant true
552dea33c80STom Eccles  // CHECK-NEXT: %[[TRUE:.+]] = arith.constant true
553dea33c80STom Eccles  // CHECK-NEXT: %[[IF:.+]] = scf.if %[[TRUE]] -> (i32) {
554dea33c80STom Eccles  %1 = scf.if %true -> (i32) {
555dea33c80STom Eccles    "test.op_with_memwrite"() : () -> ()
556dea33c80STom Eccles    // CHECK-NEXT: "test.op_with_memwrite"() : () -> ()
557dea33c80STom Eccles    %c42 = arith.constant 42 : i32
558dea33c80STom Eccles    scf.yield %c42 : i32
559dea33c80STom Eccles    // CHECK-NEXT: %[[C42:.+]] = arith.constant 42 : i32
560dea33c80STom Eccles    // CHECK-NEXT: scf.yield %[[C42]]
561dea33c80STom Eccles    // CHECK-NEXT: } else {
562dea33c80STom Eccles  } else {
563dea33c80STom Eccles    %c24 = arith.constant 24 : i32
564dea33c80STom Eccles    scf.yield %c24 : i32
565dea33c80STom Eccles    // CHECK-NEXT: %[[C24:.+]] = arith.constant 24 : i32
566dea33c80STom Eccles    // CHECK-NEXT: scf.yield %[[C24]]
567dea33c80STom Eccles    // CHECK-NEXT: }
568dea33c80STom Eccles  }
569dea33c80STom Eccles
570dea33c80STom Eccles  // %2 can not be be removed because of the write
571dea33c80STom Eccles  // CHECK-NEXT: %[[READ_VALUE2:.*]] = "test.op_with_memread"() : () -> i32
572dea33c80STom Eccles  // CHECK-NEXT: return %[[READ_VALUE]], %[[READ_VALUE2]], %[[IF]] : i32, i32, i32
573dea33c80STom Eccles  %2 = "test.op_with_memread"() : () -> (i32)
574dea33c80STom Eccles  return %0, %2, %1 : i32, i32, i32
575dea33c80STom Eccles}
576