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