[LLVM] Fix Maintainers.md formatting (NFC)
[llvm-project.git] / flang / test / Analysis / AliasAnalysis / alias-analysis-2.fir
blobd03348efd2a68c04e920d8cfab96068f152d2dfc
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
5 // CHECK-LABEL: Testing : "_QFPtest"
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
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
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
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
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
35 // A target dummy may alias with another target
36 // CHECK-DAG: func.region0#0 <-> func.region0#1: MayAlias
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
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
50 func.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"} {
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>>
56   %4 = fir.alloca !fir.ptr<f32> {test.ptr = "p2.addr"}
57   fir.store %2 to %4 : !fir.ref<!fir.ptr<f32>>
59   %5 = fir.convert %arg0 : (!fir.ref<f32>) -> !fir.ptr<f32>
60   fir.store %5 to %1 : !fir.ref<!fir.ptr<f32>>
62   %6 = fir.convert %arg1 : (!fir.ref<f32>) -> !fir.ptr<f32>
63   fir.store %6 to %4 : !fir.ref<!fir.ptr<f32>>
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>>>
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>>>
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>>
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>>
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
88 // -----
90 // CHECK-LABEL: Testing : "_QFPtest2"
92 // subroutine test2(v1,p1,p2)
93 //   real, target :: v1
94 //   real, pointer :: p1, p2
95 //   ...
96 // end subroutine
98 // Direct access to dummy POINTER references can modify other dummy POINTER references
99 // CHECK-DAG: func.region0#1 <-> func.region0#2: MayAlias
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
105 func.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
111 // -----
113 // CHECK-LABEL: Testing : "_QFPtest3"
115 // module pointers
116 //   real, pointer :: p
117 // end module
119 // program main
120 //   use pointers
121 //   real, target :: var1 = 1, var2 =2
122 //   p => var1
124 //   call test3(p)
126 // contains
127 //   subroutine test3(p1)
128 //     real, pointer :: p1
129 //     p1 => var2
130 //     print *, p
131 //   end subroutine
132 // end
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
139 // p could be pointing to var2 
140 // var2, being a target, could also be passed as argument arg0 
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
146 // Handling gracefully the difference between !fir.ref<!fir.box<>> and !fir.box<> 
147 // CHECK-DAG: box.addr#0 <-> func.region0#0: NoAlias
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
157 // A global may not alias with a dummy
158 // CHECK-DAG: var2#0 <-> func.region0#1: NoAlias
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
163 // Dummy argument do not alias
164 // CHECK-DAG: func.region0#0 <-> func.region0#1: NoAlias
166 fir.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>>
172 fir.global internal @_QFEvar2 target : f32 {
173   %cst = arith.constant 2.000000e+00 : f32
174   fir.has_value %cst : f32
177 func.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
186 // -----
188 // CHECK-LABEL: Testing : "_QFPtest4"
190 // Same as test3 but check that the alias analysis can follow (hl)fir.declare
191 // operations
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
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
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
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
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
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
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
254 // CHECK-DAG: func.region0#0 <-> func.region0#1: NoAlias
256 fir.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>>
262 fir.global internal @_QFEvar2 target : f32 {
263   %cst = arith.constant 2.000000e+00 : f32
264   fir.has_value %cst : f32
267 func.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