xref: /llvm-project/flang/test/Analysis/AliasAnalysis/alias-analysis-2.fir (revision ee407e17a3a4986bab49272665abc9973d78691d)
1// Use --mlir-disable-threading so that the AA queries are serialized
2// as well as its diagnostic output.
3// RUN: fir-opt %s -pass-pipeline='builtin.module(func.func(test-fir-alias-analysis))' -split-input-file --mlir-disable-threading 2>&1 | FileCheck %s
4
5// CHECK-LABEL: Testing : "_QFPtest"
6
7// p1.addr and p2.addr result from 2 different allocas
8// They cannot physically alias
9// CHECK-DAG: p1.addr#0 <-> p2.addr#0: NoAlias
10
11// p1.addr and p2.addr could both be wrapped inside boxes
12// CHECK-DAG: p1.addr#0 <-> boxp1.addr#0: MayAlias
13// CHECK-DAG: p2.addr#0 <-> boxp1.addr#0: MayAlias
14
15// TODO: To really see aliasing, we should be looking at a load of p1.addr
16// p1.addr is just a local address holding the address to the data
17// CHECK-DAG: p1.addr#0 <-> arg2.addr#0: NoAlias
18// CHECK-DAG: p2.addr#0 <-> arg2.addr#0: NoAlias
19
20// p1.addr and p2.addr are the result of an allocation
21// They cannot physically alias with an argument
22// CHECK-DAG: p1.addr#0 <-> func.region0#0: NoAlias
23// CHECK-DAG: p2.addr#0 <-> func.region0#0: NoAlias
24// CHECK-DAG: p1.addr#0 <-> func.region0#1: NoAlias
25// CHECK-DAG: p2.addr#0 <-> func.region0#1: NoAlias
26// CHECK-DAG: p1.addr#0 <-> func.region0#2: NoAlias
27// CHECK-DAG: p2.addr#0 <-> func.region0#2: NoAlias
28
29// All arguments are either pointers or targets
30// A pointer in a box may alias with both
31// CHECK-DAG: boxp1.addr#0 <-> func.region0#0: MayAlias
32// CHECK-DAG: boxp1.addr#0 <-> func.region0#1: MayAlias
33// CHECK-DAG: boxp1.addr#0 <-> func.region0#2: MayAlias
34
35// A target dummy may alias with another target
36// CHECK-DAG: func.region0#0 <-> func.region0#1: MayAlias
37
38// arg2 is a reference to a pointer. Modifying arg2 could
39// modify a target with a pointer component
40// CHECK-DAG: arg2.load#0 <-> func.region0#0: MayAlias
41// CHECK-DAG: arg2.load#0 <-> func.region0#1: MayAlias
42
43// However, the address wrapped by arg2, can alias with any target or
44// pointer arguments
45// CHECK-DAG: arg2.addr#0 <-> func.region0#0: MayAlias
46// CHECK-DAG: arg2.addr#0 <-> func.region0#1: MayAlias
47// CHECK-DAG: arg2.load#0 <-> arg2.addr#0: MustAlias
48// CHECK-DAG: boxp1.addr#0 <-> arg2.addr#0: MayAlias
49
50func.func @_QFPtest(%arg0: !fir.ref<f32> {fir.bindc_name = "v1", fir.target}, %arg1: !fir.ref<f32> {fir.bindc_name = "v2", fir.target}, %arg2: !fir.ref<!fir.box<!fir.ptr<f32>>> ) attributes {test.ptr = "func"} {
51
52  %1 = fir.alloca !fir.ptr<f32> {test.ptr = "p1.addr"}
53  %2 = fir.zero_bits !fir.ptr<f32>
54  fir.store %2 to %1 : !fir.ref<!fir.ptr<f32>>
55
56  %4 = fir.alloca !fir.ptr<f32> {test.ptr = "p2.addr"}
57  fir.store %2 to %4 : !fir.ref<!fir.ptr<f32>>
58
59  %5 = fir.convert %arg0 : (!fir.ref<f32>) -> !fir.ptr<f32>
60  fir.store %5 to %1 : !fir.ref<!fir.ptr<f32>>
61
62  %6 = fir.convert %arg1 : (!fir.ref<f32>) -> !fir.ptr<f32>
63  fir.store %6 to %4 : !fir.ref<!fir.ptr<f32>>
64
65  %0 = fir.alloca !fir.box<!fir.ptr<f32>> {bindc_name = "p1", uniq_name = "_QFtestEp1"}
66  %7 = fir.load %1 : !fir.ref<!fir.ptr<f32>>
67  %8 = fir.embox %7 : (!fir.ptr<f32>) -> !fir.box<!fir.ptr<f32>>
68  fir.store %8 to %0 : !fir.ref<!fir.box<!fir.ptr<f32>>>
69
70  %3 = fir.alloca !fir.box<!fir.ptr<f32>> {bindc_name = "p2", uniq_name = "_QFtestEp2"}
71  %9 = fir.load %4 : !fir.ref<!fir.ptr<f32>>
72  %10 = fir.embox %9 : (!fir.ptr<f32>) -> !fir.box<!fir.ptr<f32>>
73  fir.store %10 to %3 : !fir.ref<!fir.box<!fir.ptr<f32>>>
74
75  %11 = fir.load %0 : !fir.ref<!fir.box<!fir.ptr<f32>>>
76  %12 = fir.box_addr %11 {test.ptr = "boxp1.addr"} : (!fir.box<!fir.ptr<f32>>) -> !fir.ptr<f32>
77  fir.store %12 to %1 : !fir.ref<!fir.ptr<f32>>
78
79  %13 = fir.load %3 : !fir.ref<!fir.box<!fir.ptr<f32>>>
80  %14 = fir.box_addr %13 : (!fir.box<!fir.ptr<f32>>) -> !fir.ptr<f32>
81  fir.store %14 to %4 : !fir.ref<!fir.ptr<f32>>
82
83  %15 = fir.load %arg2 {test.ptr = "arg2.load"} : !fir.ref<!fir.box<!fir.ptr<f32>>>
84  %16 = fir.box_addr %15 {test.ptr = "arg2.addr"} : (!fir.box<!fir.ptr<f32>>) -> !fir.ptr<f32>
85  return
86}
87
88// -----
89
90// CHECK-LABEL: Testing : "_QFPtest2"
91
92// subroutine test2(v1,p1,p2)
93//   real, target :: v1
94//   real, pointer :: p1, p2
95//   ...
96// end subroutine
97
98// Direct access to dummy POINTER references can modify other dummy POINTER references
99// CHECK-DAG: func.region0#1 <-> func.region0#2: MayAlias
100
101// They can also modify targets that have pointer components
102// CHECK-DAG: arg1.load#0 <-> func.region0#0: MayAlias
103// CHECK-DAG: arg2.load#0 <-> func.region0#0: MayAlias
104
105func.func @_QFPtest2(%arg0: !fir.ref<f32> {fir.bindc_name = "v1", fir.target}, %arg1: !fir.ref<!fir.box<!fir.ptr<f32>>>, %arg2: !fir.ref<!fir.box<!fir.ptr<f32>>> ) attributes {test.ptr = "func"} {
106  %0 = fir.load %arg1 {test.ptr = "arg1.load"} : !fir.ref<!fir.box<!fir.ptr<f32>>>
107  %1 = fir.load %arg2 {test.ptr = "arg2.load"} : !fir.ref<!fir.box<!fir.ptr<f32>>>
108  return
109}
110
111// -----
112
113// CHECK-LABEL: Testing : "_QFPtest3"
114
115// module pointers
116//   real, pointer :: p
117// end module
118//
119// program main
120//   use pointers
121//   real, target :: var1 = 1, var2 =2
122//   p => var1
123//
124//   call test3(p)
125//
126// contains
127//   subroutine test3(p1)
128//     real, pointer :: p1
129//     p1 => var2
130//     print *, p
131//   end subroutine
132// end
133
134// The global pointer p may alias with the dummy argument p1
135// but not with the dummy arg1 which is just a regular dummy
136// CHECK-DAG: p#0 <-> func.region0#0: MayAlias
137// CHECK-DAG: p#0 <-> func.region0#1: NoAlias
138
139// p could be pointing to var2
140// var2, being a target, could also be passed as argument arg0
141
142// This was the wrong question to ask. We are asking if the address of box _QMpointersEp can
143// alias with the wrapped scalar _QFEvar2. We meant box_addr of _QMpointersEp
144// CHECK-DAG: p#0 <-> box.addr#0: NoAlias
145
146// Handling gracefully the difference between !fir.ref<!fir.box<>> and !fir.box<>
147// CHECK-DAG: box.addr#0 <-> func.region0#0: NoAlias
148
149// var2, although it is a target, cannot alias with p
150// A modification of p would only make them point to a new target but not modify it
151// CHECK-DAG: var2#0 <-> p#0: NoAlias
152// It can alias with p1, if p1 is a pointer component
153// CHECK-DAG: arg0.load#0 <-> var2#0: MayAlias
154// It is the same as box.addr
155// CHECK-DAG: var2#0 <-> box.addr#0: MustAlias
156
157// A global may not alias with a dummy
158// CHECK-DAG: var2#0 <-> func.region0#1: NoAlias
159
160// A pointer may only alias with a target but arg1 is a regular dummy
161// CHECK-DAG: box.addr#0 <-> func.region0#1: NoAlias
162
163// Dummy argument do not alias
164// CHECK-DAG: func.region0#0 <-> func.region0#1: NoAlias
165
166fir.global @_QMpointersEp : !fir.box<!fir.ptr<f32>> {
167  %0 = fir.zero_bits !fir.ptr<f32>
168  %1 = fir.embox %0 : (!fir.ptr<f32>) -> !fir.box<!fir.ptr<f32>>
169  fir.has_value %1 : !fir.box<!fir.ptr<f32>>
170}
171
172fir.global internal @_QFEvar2 target : f32 {
173  %cst = arith.constant 2.000000e+00 : f32
174  fir.has_value %cst : f32
175}
176
177func.func @_QFPtest3(%arg0: !fir.ref<!fir.box<!fir.ptr<f32>>> {fir.bindc_name = "p1"}, %arg1: !fir.ref<f32>) attributes {test.ptr = "func"} {
178  %3 = fir.load %arg0 {test.ptr = "arg0.load"}: !fir.ref<!fir.box<!fir.ptr<f32>>>
179  %4 = fir.address_of(@_QFEvar2) {test.ptr = "var2"} : !fir.ref<f32>
180  %5 = fir.address_of(@_QMpointersEp) {test.ptr = "p"} : !fir.ref<!fir.box<!fir.ptr<f32>>>
181  %6 = fir.embox %4 : (!fir.ref<f32>) -> !fir.box<!fir.ptr<f32>>
182  %13 = fir.box_addr %6 {test.ptr = "box.addr"} : (!fir.box<!fir.ptr<f32>>) -> !fir.ptr<f32>
183  return
184}
185
186// -----
187
188// CHECK-LABEL: Testing : "_QFPtest4"
189
190// Same as test3 but check that the alias analysis can follow (hl)fir.declare
191// operations
192
193// CHECK-DAG: p#0 <-> func.region0#0: MayAlias
194// CHECK-DAG: p_fir#0 <-> func.region0#0: MayAlias
195// CHECK-DAG: p_hlfir#0 <-> func.region0#0: MayAlias
196// CHECK-DAG: p_hlfir#1 <-> func.region0#0: MayAlias
197
198// CHECK-DAG: p#0 <-> func.region0#1: NoAlias
199// CHECK-DAG: p_fir#0 <-> func.region0#1: NoAlias
200// CHECK-DAG: p_hlfir#0 <-> func.region0#1: NoAlias
201// CHECK-DAG: p_hlfir#1 <-> func.region0#1: NoAlias
202
203// CHECK-DAG: var2#0 <-> p#0: NoAlias
204// CHECK-DAG: var2#0 <-> p_fir#0: NoAlias
205// CHECK-DAG: var2#0 <-> p_hlfir#0: NoAlias
206// CHECK-DAG: var2#0 <-> p_hlfir#1: NoAlias
207// CHECK-DAG: var2_fir#0 <-> p#0: NoAlias
208// CHECK-DAG: var2_fir#0 <-> p_fir#0: NoAlias
209// CHECK-DAG: var2_fir#0 <-> p_hlfir#0: NoAlias
210// CHECK-DAG: var2_fir#0 <-> p_hlfir#1: NoAlias
211// CHECK-DAG: var2_hlfir#0 <-> p#0: NoAlias
212// CHECK-DAG: var2_hlfir#0 <-> p_fir#0: NoAlias
213// CHECK-DAG: var2_hlfir#0 <-> p_hlfir#0: NoAlias
214// CHECK-DAG: var2_hlfir#0 <-> p_hlfir#1: NoAlias
215// CHECK-DAG: var2_hlfir#1 <-> p#0: NoAlias
216// CHECK-DAG: var2_hlfir#1 <-> p_fir#0: NoAlias
217// CHECK-DAG: var2_hlfir#1 <-> p_hlfir#0: NoAlias
218// CHECK-DAG: var2_hlfir#1 <-> p_hlfir#1: NoAlias
219
220// The data cannot alias with the box references
221// CHECK-DAG: var2#0 <-> func.region0#0: NoAlias
222// CHECK-DAG: var2_fir#0 <-> func.region0#0: NoAlias
223// CHECK-DAG: var2_hlfir#0 <-> func.region0#0: NoAlias
224// CHECK-DAG: var2_hlfir#1 <-> func.region0#0: NoAlias
225
226// But it can alias with the box's own data
227// CHECK-DAG: arg0.load#0 <-> var2#0: MayAlias
228// CHECK-DAG: arg0.load#0 <-> var2_fir#0: MayAlias
229// CHECK-DAG: arg0.load#0 <-> var2_hlfir#0: MayAlias
230// CHECK-DAG: arg0.load#0 <-> var2_hlfir#1: MayAlias
231
232// CHECK-DAG: var2#0 <-> box.addr#0: MustAlias
233// CHECK-DAG: var2#0 <-> box.addr_fir#0: MustAlias
234// CHECK-DAG: var2#0 <-> box.addr_hlfir#0: MustAlias
235// CHECK-DAG: var2#0 <-> box.addr_hlfir#1: MustAlias
236// CHECK-DAG: var2_fir#0 <-> box.addr#0: MustAlias
237// CHECK-DAG: var2_fir#0 <-> box.addr_fir#0: MustAlias
238// CHECK-DAG: var2_fir#0 <-> box.addr_hlfir#0: MustAlias
239// CHECK-DAG: var2_fir#0 <-> box.addr_hlfir#1: MustAlias
240// CHECK-DAG: var2_hlfir#0 <-> box.addr#0: MustAlias
241// CHECK-DAG: var2_hlfir#0 <-> box.addr_fir#0: MustAlias
242// CHECK-DAG: var2_hlfir#0 <-> box.addr_hlfir#0: MustAlias
243// CHECK-DAG: var2_hlfir#0 <-> box.addr_hlfir#1: MustAlias
244// CHECK-DAG: var2_hlfir#1 <-> box.addr#0: MustAlias
245// CHECK-DAG: var2_hlfir#1 <-> box.addr_fir#0: MustAlias
246// CHECK-DAG: var2_hlfir#1 <-> box.addr_hlfir#0: MustAlias
247// CHECK-DAG: var2_hlfir#1 <-> box.addr_hlfir#1: MustAlias
248
249// CHECK-DAG: var2#0 <-> func.region0#1: NoAlias
250// CHECK-DAG: var2_fir#0 <-> func.region0#1: NoAlias
251// CHECK-DAG: var2_hlfir#0 <-> func.region0#1: NoAlias
252// CHECK-DAG: var2_hlfir#1 <-> func.region0#1: NoAlias
253
254// CHECK-DAG: func.region0#0 <-> func.region0#1: NoAlias
255
256fir.global @_QMpointersEp : !fir.box<!fir.ptr<f32>> {
257  %0 = fir.zero_bits !fir.ptr<f32>
258  %1 = fir.embox %0 : (!fir.ptr<f32>) -> !fir.box<!fir.ptr<f32>>
259  fir.has_value %1 : !fir.box<!fir.ptr<f32>>
260}
261
262fir.global internal @_QFEvar2 target : f32 {
263  %cst = arith.constant 2.000000e+00 : f32
264  fir.has_value %cst : f32
265}
266
267func.func @_QFPtest4(%arg0: !fir.ref<!fir.box<!fir.ptr<f32>>> {fir.bindc_name = "p1"}, %arg1: !fir.ref<f32>) attributes {test.ptr = "func"} {
268  %3 = fir.load %arg0 {test.ptr = "arg0.load"} : !fir.ref<!fir.box<!fir.ptr<f32>>>
269  %4 = fir.address_of(@_QFEvar2) {test.ptr = "var2"} : !fir.ref<f32>
270  %fir_decl_var2 = fir.declare %4 {uniq_name = "var2_fir", test.ptr = "var2_fir"}: (!fir.ref<f32>) -> !fir.ref<f32>
271  %hlfir_decl_var2:2 = hlfir.declare %4 {uniq_name = "var2_hlfir", test.ptr = "var2_hlfir"}: (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
272  %5 = fir.address_of(@_QMpointersEp) {test.ptr = "p"} : !fir.ref<!fir.box<!fir.ptr<f32>>>
273  %fir_decl_p = fir.declare %5 {uniq_name = "p_fir", test.ptr = "p_fir"}: (!fir.ref<!fir.box<!fir.ptr<f32>>>) -> !fir.ref<!fir.box<!fir.ptr<f32>>>
274  %hlfir_decl_p:2 = hlfir.declare %5 {uniq_name = "p_hlfir", test.ptr = "p_hlfir"}: (!fir.ref<!fir.box<!fir.ptr<f32>>>) -> (!fir.ref<!fir.box<!fir.ptr<f32>>>, !fir.ref<!fir.box<!fir.ptr<f32>>>)
275  %13 = fir.convert %4 {test.ptr = "box.addr"} : (!fir.ref<f32>) -> !fir.ptr<f32>
276  %fir_decl_convert = fir.declare %13 {uniq_name = "box_addr_fir", test.ptr = "box.addr_fir"}: (!fir.ptr<f32>) -> !fir.ptr<f32>
277  %hlfir_decl_convert:2 = hlfir.declare %13 {uniq_name = "box_addr_hlfir", test.ptr = "box.addr_hlfir"}: (!fir.ptr<f32>) -> (!fir.ptr<f32>, !fir.ptr<f32>)
278  return
279}
280