1// RUN: mlir-opt -test-last-modified %s 2>&1 | FileCheck %s 2 3// CHECK-LABEL: test_tag: test_simple_mod 4// CHECK: operand #0 5// CHECK-NEXT: - a 6// CHECK: operand #1 7// CHECK-NEXT: - b 8func.func @test_simple_mod(%arg0: memref<i32>, %arg1: memref<i32>) -> (memref<i32>, memref<i32>) { 9 %c0 = arith.constant 0 : i32 10 %c1 = arith.constant 1 : i32 11 memref.store %c0, %arg0[] {tag_name = "a"} : memref<i32> 12 memref.store %c1, %arg1[] {tag_name = "b"} : memref<i32> 13 return {tag = "test_simple_mod"} %arg0, %arg1 : memref<i32>, memref<i32> 14} 15 16// CHECK-LABEL: test_tag: test_simple_mod_overwrite_a 17// CHECK: operand #1 18// CHECK-NEXT: - a 19// CHECK-LABEL: test_tag: test_simple_mod_overwrite_b 20// CHECK: operand #0 21// CHECK-NEXT: - b 22func.func @test_simple_mod_overwrite(%arg0: memref<i32>) -> memref<i32> { 23 %c0 = arith.constant 0 : i32 24 memref.store %c0, %arg0[] {tag = "test_simple_mod_overwrite_a", tag_name = "a"} : memref<i32> 25 %c1 = arith.constant 1 : i32 26 memref.store %c1, %arg0[] {tag_name = "b"} : memref<i32> 27 return {tag = "test_simple_mod_overwrite_b"} %arg0 : memref<i32> 28} 29 30// CHECK-LABEL: test_tag: test_mod_control_flow 31// CHECK: operand #0 32// CHECK-NEXT: - b 33// CHECK-NEXT: - a 34func.func @test_mod_control_flow(%cond: i1, %ptr: memref<i32>) -> memref<i32> { 35 cf.cond_br %cond, ^a, ^b 36 37^a: 38 %c0 = arith.constant 0 : i32 39 memref.store %c0, %ptr[] {tag_name = "a"} : memref<i32> 40 cf.br ^c 41 42^b: 43 %c1 = arith.constant 1 : i32 44 memref.store %c1, %ptr[] {tag_name = "b"} : memref<i32> 45 cf.br ^c 46 47^c: 48 return {tag = "test_mod_control_flow"} %ptr : memref<i32> 49} 50 51// CHECK-LABEL: test_tag: test_mod_dead_branch 52// CHECK: operand #0 53// CHECK-NEXT: - a 54func.func @test_mod_dead_branch(%arg: i32, %ptr: memref<i32>) -> memref<i32> { 55 %0 = arith.subi %arg, %arg : i32 56 %1 = arith.constant -1 : i32 57 %2 = arith.cmpi sgt, %0, %1 : i32 58 cf.cond_br %2, ^a, ^b 59 60^a: 61 %c0 = arith.constant 0 : i32 62 memref.store %c0, %ptr[] {tag_name = "a"} : memref<i32> 63 cf.br ^c 64 65^b: 66 %c1 = arith.constant 1 : i32 67 memref.store %c1, %ptr[] {tag_name = "b"} : memref<i32> 68 cf.br ^c 69 70^c: 71 return {tag = "test_mod_dead_branch"} %ptr : memref<i32> 72} 73 74// CHECK-LABEL: test_tag: test_mod_region_control_flow 75// CHECK: operand #0 76// CHECK-NEXT: then 77// CHECK-NEXT: else 78func.func @test_mod_region_control_flow(%cond: i1, %ptr: memref<i32>) -> memref<i32> { 79 scf.if %cond { 80 %c0 = arith.constant 0 : i32 81 memref.store %c0, %ptr[] {tag_name = "then"}: memref<i32> 82 } else { 83 %c1 = arith.constant 1 : i32 84 memref.store %c1, %ptr[] {tag_name = "else"} : memref<i32> 85 } 86 return {tag = "test_mod_region_control_flow"} %ptr : memref<i32> 87} 88 89// CHECK-LABEL: test_tag: test_mod_dead_region 90// CHECK: operand #0 91// CHECK-NEXT: else 92func.func @test_mod_dead_region(%ptr: memref<i32>) -> memref<i32> { 93 %false = arith.constant false 94 scf.if %false { 95 %c0 = arith.constant 0 : i32 96 memref.store %c0, %ptr[] {tag_name = "then"}: memref<i32> 97 } else { 98 %c1 = arith.constant 1 : i32 99 memref.store %c1, %ptr[] {tag_name = "else"} : memref<i32> 100 } 101 return {tag = "test_mod_dead_region"} %ptr : memref<i32> 102} 103 104// CHECK-LABEL: test_tag: unknown_memory_effects_a 105// CHECK: operand #1 106// CHECK-NEXT: - a 107// CHECK-LABEL: test_tag: unknown_memory_effects_b 108// CHECK: operand #0 109// CHECK-NEXT: - <unknown> 110func.func @unknown_memory_effects(%ptr: memref<i32>) -> memref<i32> { 111 %c0 = arith.constant 0 : i32 112 memref.store %c0, %ptr[] {tag = "unknown_memory_effects_a", tag_name = "a"} : memref<i32> 113 "test.unknown_effects"() : () -> () 114 return {tag = "unknown_memory_effects_b"} %ptr : memref<i32> 115} 116 117// CHECK-LABEL: test_tag: store_with_a_region_before::before: 118// CHECK: operand #0 119// CHECK: - pre 120// CHECK: test_tag: inside_region: 121// CHECK: operand #0 122// CHECK: - region 123// CHECK: test_tag: after: 124// CHECK: operand #0 125// CHECK: - region 126// CHECK: test_tag: return: 127// CHECK: operand #0 128// CHECK: - post 129func.func @store_with_a_region_before(%arg0: memref<f32>) -> memref<f32> { 130 %0 = arith.constant 0.0 : f32 131 %1 = arith.constant 1.0 : f32 132 memref.store %0, %arg0[] {tag_name = "pre"} : memref<f32> 133 memref.load %arg0[] {tag = "store_with_a_region_before::before"} : memref<f32> 134 test.store_with_a_region %arg0 attributes { tag_name = "region", store_before_region = true } { 135 memref.load %arg0[] {tag = "inside_region"} : memref<f32> 136 test.store_with_a_region_terminator 137 } : memref<f32> 138 memref.load %arg0[] {tag = "after"} : memref<f32> 139 memref.store %1, %arg0[] {tag_name = "post"} : memref<f32> 140 return {tag = "return"} %arg0 : memref<f32> 141} 142 143// CHECK-LABEL: test_tag: store_with_a_region_after::before: 144// CHECK: operand #0 145// CHECK: - pre 146// CHECK: test_tag: inside_region: 147// CHECK: operand #0 148// CHECK: - pre 149// CHECK: test_tag: after: 150// CHECK: operand #0 151// CHECK: - region 152// CHECK: test_tag: return: 153// CHECK: operand #0 154// CHECK: - post 155func.func @store_with_a_region_after(%arg0: memref<f32>) -> memref<f32> { 156 %0 = arith.constant 0.0 : f32 157 %1 = arith.constant 1.0 : f32 158 memref.store %0, %arg0[] {tag_name = "pre"} : memref<f32> 159 memref.load %arg0[] {tag = "store_with_a_region_after::before"} : memref<f32> 160 test.store_with_a_region %arg0 attributes { tag_name = "region", store_before_region = false } { 161 memref.load %arg0[] {tag = "inside_region"} : memref<f32> 162 test.store_with_a_region_terminator 163 } : memref<f32> 164 memref.load %arg0[] {tag = "after"} : memref<f32> 165 memref.store %1, %arg0[] {tag_name = "post"} : memref<f32> 166 return {tag = "return"} %arg0 : memref<f32> 167} 168 169// CHECK-LABEL: test_tag: store_with_a_region_before_containing_a_store::before: 170// CHECK: operand #0 171// CHECK: - pre 172// CHECK: test_tag: enter_region: 173// CHECK: operand #0 174// CHECK: - region 175// CHECK: test_tag: exit_region: 176// CHECK: operand #0 177// CHECK: - inner 178// CHECK: test_tag: after: 179// CHECK: operand #0 180// CHECK: - inner 181// CHECK: test_tag: return: 182// CHECK: operand #0 183// CHECK: - post 184func.func @store_with_a_region_before_containing_a_store(%arg0: memref<f32>) -> memref<f32> { 185 %0 = arith.constant 0.0 : f32 186 %1 = arith.constant 1.0 : f32 187 memref.store %0, %arg0[] {tag_name = "pre"} : memref<f32> 188 memref.load %arg0[] {tag = "store_with_a_region_before_containing_a_store::before"} : memref<f32> 189 test.store_with_a_region %arg0 attributes { tag_name = "region", store_before_region = true } { 190 memref.load %arg0[] {tag = "enter_region"} : memref<f32> 191 %2 = arith.constant 2.0 : f32 192 memref.store %2, %arg0[] {tag_name = "inner"} : memref<f32> 193 memref.load %arg0[] {tag = "exit_region"} : memref<f32> 194 test.store_with_a_region_terminator 195 } : memref<f32> 196 memref.load %arg0[] {tag = "after"} : memref<f32> 197 memref.store %1, %arg0[] {tag_name = "post"} : memref<f32> 198 return {tag = "return"} %arg0 : memref<f32> 199} 200 201// CHECK-LABEL: test_tag: store_with_a_region_after_containing_a_store::before: 202// CHECK: operand #0 203// CHECK: - pre 204// CHECK: test_tag: enter_region: 205// CHECK: operand #0 206// CHECK: - pre 207// CHECK: test_tag: exit_region: 208// CHECK: operand #0 209// CHECK: - inner 210// CHECK: test_tag: after: 211// CHECK: operand #0 212// CHECK: - region 213// CHECK: test_tag: return: 214// CHECK: operand #0 215// CHECK: - post 216func.func @store_with_a_region_after_containing_a_store(%arg0: memref<f32>) -> memref<f32> { 217 %0 = arith.constant 0.0 : f32 218 %1 = arith.constant 1.0 : f32 219 memref.store %0, %arg0[] {tag_name = "pre"} : memref<f32> 220 memref.load %arg0[] {tag = "store_with_a_region_after_containing_a_store::before"} : memref<f32> 221 test.store_with_a_region %arg0 attributes { tag_name = "region", store_before_region = false } { 222 memref.load %arg0[] {tag = "enter_region"} : memref<f32> 223 %2 = arith.constant 2.0 : f32 224 memref.store %2, %arg0[] {tag_name = "inner"} : memref<f32> 225 memref.load %arg0[] {tag = "exit_region"} : memref<f32> 226 test.store_with_a_region_terminator 227 } : memref<f32> 228 memref.load %arg0[] {tag = "after"} : memref<f32> 229 memref.store %1, %arg0[] {tag_name = "post"} : memref<f32> 230 return {tag = "return"} %arg0 : memref<f32> 231} 232 233// CHECK-LABEL: test_tag: store_with_a_loop_region_before::before: 234// CHECK: operand #0 235// CHECK: - pre 236// CHECK: test_tag: inside_region: 237// CHECK: operand #0 238// CHECK: - region 239// CHECK: test_tag: after: 240// CHECK: operand #0 241// CHECK: - region 242// CHECK: test_tag: return: 243// CHECK: operand #0 244// CHECK: - post 245func.func @store_with_a_loop_region_before(%arg0: memref<f32>) -> memref<f32> { 246 %0 = arith.constant 0.0 : f32 247 %1 = arith.constant 1.0 : f32 248 memref.store %0, %arg0[] {tag_name = "pre"} : memref<f32> 249 memref.load %arg0[] {tag = "store_with_a_loop_region_before::before"} : memref<f32> 250 test.store_with_a_loop_region %arg0 attributes { tag_name = "region", store_before_region = true } { 251 memref.load %arg0[] {tag = "inside_region"} : memref<f32> 252 test.store_with_a_region_terminator 253 } : memref<f32> 254 memref.load %arg0[] {tag = "after"} : memref<f32> 255 memref.store %1, %arg0[] {tag_name = "post"} : memref<f32> 256 return {tag = "return"} %arg0 : memref<f32> 257} 258 259// CHECK-LABEL: test_tag: store_with_a_loop_region_after::before: 260// CHECK: operand #0 261// CHECK: - pre 262// CHECK: test_tag: inside_region: 263// CHECK: operand #0 264// CHECK: - pre 265// CHECK: test_tag: after: 266// CHECK: operand #0 267// CHECK: - region 268// CHECK: test_tag: return: 269// CHECK: operand #0 270// CHECK: - post 271func.func @store_with_a_loop_region_after(%arg0: memref<f32>) -> memref<f32> { 272 %0 = arith.constant 0.0 : f32 273 %1 = arith.constant 1.0 : f32 274 memref.store %0, %arg0[] {tag_name = "pre"} : memref<f32> 275 memref.load %arg0[] {tag = "store_with_a_loop_region_after::before"} : memref<f32> 276 test.store_with_a_loop_region %arg0 attributes { tag_name = "region", store_before_region = false } { 277 memref.load %arg0[] {tag = "inside_region"} : memref<f32> 278 test.store_with_a_region_terminator 279 } : memref<f32> 280 memref.load %arg0[] {tag = "after"} : memref<f32> 281 memref.store %1, %arg0[] {tag_name = "post"} : memref<f32> 282 return {tag = "return"} %arg0 : memref<f32> 283} 284 285// CHECK-LABEL: test_tag: store_with_a_loop_region_before_containing_a_store::before: 286// CHECK: operand #0 287// CHECK: - pre 288// CHECK: test_tag: enter_region: 289// CHECK: operand #0 290// CHECK-DAG: - region 291// CHECK-DAG: - inner 292// CHECK: test_tag: exit_region: 293// CHECK: operand #0 294// CHECK: - inner 295// CHECK: test_tag: after: 296// CHECK: operand #0 297// CHECK-DAG: - region 298// CHECK-DAG: - inner 299// CHECK: test_tag: return: 300// CHECK: operand #0 301// CHECK: - post 302func.func @store_with_a_loop_region_before_containing_a_store(%arg0: memref<f32>) -> memref<f32> { 303 %0 = arith.constant 0.0 : f32 304 %1 = arith.constant 1.0 : f32 305 memref.store %0, %arg0[] {tag_name = "pre"} : memref<f32> 306 memref.load %arg0[] {tag = "store_with_a_loop_region_before_containing_a_store::before"} : memref<f32> 307 test.store_with_a_loop_region %arg0 attributes { tag_name = "region", store_before_region = true } { 308 memref.load %arg0[] {tag = "enter_region"} : memref<f32> 309 %2 = arith.constant 2.0 : f32 310 memref.store %2, %arg0[] {tag_name = "inner"} : memref<f32> 311 memref.load %arg0[] {tag = "exit_region"} : memref<f32> 312 test.store_with_a_region_terminator 313 } : memref<f32> 314 memref.load %arg0[] {tag = "after"} : memref<f32> 315 memref.store %1, %arg0[] {tag_name = "post"} : memref<f32> 316 return {tag = "return"} %arg0 : memref<f32> 317} 318 319// CHECK-LABEL: test_tag: store_with_a_loop_region_after_containing_a_store::before: 320// CHECK: operand #0 321// CHECK: - pre 322// CHECK: test_tag: enter_region: 323// CHECK: operand #0 324// CHECK-DAG: - pre 325// CHECK-DAG: - inner 326// CHECK: test_tag: exit_region: 327// CHECK: operand #0 328// CHECK: - inner 329// CHECK: test_tag: after: 330// CHECK: operand #0 331// CHECK: - region 332// CHECK: test_tag: return: 333// CHECK: operand #0 334// CHECK: - post 335func.func @store_with_a_loop_region_after_containing_a_store(%arg0: memref<f32>) -> memref<f32> { 336 %0 = arith.constant 0.0 : f32 337 %1 = arith.constant 1.0 : f32 338 memref.store %0, %arg0[] {tag_name = "pre"} : memref<f32> 339 memref.load %arg0[] {tag = "store_with_a_loop_region_after_containing_a_store::before"} : memref<f32> 340 test.store_with_a_loop_region %arg0 attributes { tag_name = "region", store_before_region = false } { 341 memref.load %arg0[] {tag = "enter_region"} : memref<f32> 342 %2 = arith.constant 2.0 : f32 343 memref.store %2, %arg0[] {tag_name = "inner"} : memref<f32> 344 memref.load %arg0[] {tag = "exit_region"} : memref<f32> 345 test.store_with_a_region_terminator 346 } : memref<f32> 347 memref.load %arg0[] {tag = "after"} : memref<f32> 348 memref.store %1, %arg0[] {tag_name = "post"} : memref<f32> 349 return {tag = "return"} %arg0 : memref<f32> 350} 351