xref: /llvm-project/mlir/test/Analysis/DataFlow/test-last-modified.mlir (revision a9d0f5e2f09aef88426a1bf14aeffaaa753f0f13)
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