Break circular dependency between FIR dialect and utilities
[llvm-project.git] / flang / test / Fir / array-copies-pointers.fir
blob490c1c1055e1891ec84d90c0df8544dbf25390d2
1 // Test array-copy-value pass (copy elision) with array assignment
2 // involving Fortran pointers. Focus in only on wether copy ellision
3 // is made or not.
4 // RUN: fir-opt %s --array-value-copy -split-input-file | FileCheck --check-prefixes=ALL,NOOPT %s
5 // RUN: fir-opt %s --array-value-copy="optimize-conflicts=true" -split-input-file | FileCheck --check-prefixes=ALL,OPT %s
7 // Test `pointer(:) = array(:)`
8 // ALL-LABEL: func @maybe_overlap
9 // ALL: %[[ALLOC:.*]] = fir.allocmem !fir.array<100xf32>
10 // ALL: fir.do_loop
11 // ALL: fir.do_loop
12 // ALL: fir.do_loop
13 // ALL: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<100xf32>>
14 func.func @maybe_overlap(%arg0: !fir.ptr<!fir.array<100xf32>>, %arg1 : !fir.ref<!fir.array<100xf32>> {fir.target}) {
15   %c100 = arith.constant 100 : index
16   %c99 = arith.constant 99 : index
17   %c1 = arith.constant 1 : index
18   %c0 = arith.constant 0 : index
19   %0 = fir.alloca f32
20   %1 = fir.shape %c100 : (index) -> !fir.shape<1>
21   %2 = fir.array_load %arg0(%1) : (!fir.ptr<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
22   %3 = fir.array_load %arg1(%1) : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
23   %4 = fir.do_loop %arg2 = %c0 to %c99 step %c1 unordered iter_args(%arg3 = %2) -> (!fir.array<100xf32>) {
24     %5 = fir.array_fetch %3, %arg2 : (!fir.array<100xf32>, index) -> f32
25     %6 = fir.array_update %arg3, %5, %arg2 : (!fir.array<100xf32>, f32, index) -> !fir.array<100xf32>
26     fir.result %6 : !fir.array<100xf32>
27   }
28   fir.array_merge_store %2, %4 to %arg0 : !fir.array<100xf32>, !fir.array<100xf32>, !fir.ptr<!fir.array<100xf32>>
29   return
32 // -----
34 // Test `pointer(:) = array(:)`
35 // ALL-LABEL: func @no_overlap1
36 // OPT-NOT: fir.allocmem
37 // NOOPT: %[[ALLOC:.*]] = fir.allocmem !fir.array<100xf32>
38 // NOOPT: fir.do_loop
39 // NOOPT: fir.do_loop
40 // NOOPT: fir.do_loop
41 // NOOPT: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<100xf32>>
42 func.func @no_overlap1(%arg0: !fir.ptr<!fir.array<100xf32>>, %arg1 : !fir.ref<!fir.array<100xf32>>) {
43   %c100 = arith.constant 100 : index
44   %c99 = arith.constant 99 : index
45   %c1 = arith.constant 1 : index
46   %c0 = arith.constant 0 : index
47   %0 = fir.alloca f32
48   %1 = fir.shape %c100 : (index) -> !fir.shape<1>
49   %2 = fir.array_load %arg0(%1) : (!fir.ptr<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
50   %3 = fir.array_load %arg1(%1) : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
51   %4 = fir.do_loop %arg2 = %c0 to %c99 step %c1 unordered iter_args(%arg3 = %2) -> (!fir.array<100xf32>) {
52     %5 = fir.array_fetch %3, %arg2 : (!fir.array<100xf32>, index) -> f32
53     %6 = fir.array_update %arg3, %5, %arg2 : (!fir.array<100xf32>, f32, index) -> !fir.array<100xf32>
54     fir.result %6 : !fir.array<100xf32>
55   }
56   fir.array_merge_store %2, %4 to %arg0 : !fir.array<100xf32>, !fir.array<100xf32>, !fir.ptr<!fir.array<100xf32>>
57   return
60 // -----
62 // Test `pointer(:) = pointer(:)`
63 // ALL-LABEL: func @no_overlap
64 // ALL-NOT: fir.allocmem
65 // ALL:     fir.do_loop
66 // ALL:       fir.array_coor
67 // ALL:       fir.array_coor
68 // ALL:       fir.store
69 func.func @no_overlap(%arg0: !fir.ptr<!fir.array<100xf32>>, %arg1: !fir.ref<!fir.array<100xf32>>) {
70   %c100 = arith.constant 100 : index
71   %c99 = arith.constant 99 : index
72   %c1 = arith.constant 1 : index
73   %c0 = arith.constant 0 : index
74   %0 = fir.alloca f32
75   %1 = fir.shape %c100 : (index) -> !fir.shape<1>
76   %2 = fir.array_load %arg0(%1) : (!fir.ptr<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
77   %3 = fir.do_loop %arg2 = %c0 to %c99 step %c1 unordered iter_args(%arg3 = %2) -> (!fir.array<100xf32>) {
78     %4 = fir.array_fetch %2, %arg2 : (!fir.array<100xf32>, index) -> f32
79     %5 = fir.array_update %arg3, %4, %arg2 : (!fir.array<100xf32>, f32, index) -> !fir.array<100xf32>
80     fir.result %5 : !fir.array<100xf32>
81   }
82   fir.array_merge_store %2, %3 to %arg0 : !fir.array<100xf32>, !fir.array<100xf32>, !fir.ptr<!fir.array<100xf32>>
83   return
86 // -----
88 // Test `array(:) = pointer(:)`
89 // ALL-LABEL: func @maybe_overlap_2
90 // ALL: %[[ALLOC:.*]] = fir.allocmem !fir.array<100xf32>
91 // ALL: fir.do_loop
92 // ALL: fir.do_loop
93 // ALL: fir.do_loop
94 // ALL: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<100xf32>>
95 func.func @maybe_overlap_2(%arg0: !fir.ptr<!fir.array<100xf32>>, %arg1: !fir.ref<!fir.array<100xf32>> {fir.target}) {
96   %c100 = arith.constant 100 : index
97   %c99 = arith.constant 99 : index
98   %c1 = arith.constant 1 : index
99   %c0 = arith.constant 0 : index
100   %0 = fir.alloca f32
101   %1 = fir.shape %c100 : (index) -> !fir.shape<1>
102   %2 = fir.array_load %arg0(%1) : (!fir.ptr<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
103   %3 = fir.array_load %arg1(%1) : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
104   %4 = fir.do_loop %arg2 = %c0 to %c99 step %c1 unordered iter_args(%arg3 = %3) -> (!fir.array<100xf32>) {
105     %5 = fir.array_fetch %2, %arg2 : (!fir.array<100xf32>, index) -> f32
106     %6 = fir.array_update %arg3, %5, %arg2 : (!fir.array<100xf32>, f32, index) -> !fir.array<100xf32>
107     fir.result %6 : !fir.array<100xf32>
108   }
109   fir.array_merge_store %3, %4 to %arg1 : !fir.array<100xf32>, !fir.array<100xf32>, !fir.ref<!fir.array<100xf32>>
110   return
113 // -----
115 // Test `array(:) = pointer(:)`
116 // ALL-LABEL: func @no_overlap_2
117 // OPT-NOT: fir.allocmem
118 // NOOPT: %[[ALLOC:.*]] = fir.allocmem !fir.array<100xf32>
119 // NOOPT: fir.do_loop
120 // NOOPT: fir.do_loop
121 // NOOPT: fir.do_loop
122 // NOOPT: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<100xf32>>
123 func.func @no_overlap_2(%arg0: !fir.ptr<!fir.array<100xf32>>, %arg1: !fir.ref<!fir.array<100xf32>>) {
124   %c100 = arith.constant 100 : index
125   %c99 = arith.constant 99 : index
126   %c1 = arith.constant 1 : index
127   %c0 = arith.constant 0 : index
128   %0 = fir.alloca f32
129   %1 = fir.shape %c100 : (index) -> !fir.shape<1>
130   %2 = fir.array_load %arg0(%1) : (!fir.ptr<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
131   %3 = fir.array_load %arg1(%1) : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
132   %4 = fir.do_loop %arg2 = %c0 to %c99 step %c1 unordered iter_args(%arg3 = %3) -> (!fir.array<100xf32>) {
133     %5 = fir.array_fetch %2, %arg2 : (!fir.array<100xf32>, index) -> f32
134     %6 = fir.array_update %arg3, %5, %arg2 : (!fir.array<100xf32>, f32, index) -> !fir.array<100xf32>
135     fir.result %6 : !fir.array<100xf32>
136   }
137   fir.array_merge_store %3, %4 to %arg1 : !fir.array<100xf32>, !fir.array<100xf32>, !fir.ref<!fir.array<100xf32>>
138   return
141 // -----
143 // Test `pointer1(:) = pointer2(:)`
144 // ALL-LABEL: func @maybe_overlap_3
145 // ALL: %[[ALLOC:.*]] = fir.allocmem !fir.array<100xf32>
146 // ALL: fir.do_loop
147 // ALL: fir.do_loop
148 // ALL: fir.do_loop
149 // ALL: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<100xf32>>
150 func.func @maybe_overlap_3(%arg0: !fir.ptr<!fir.array<100xf32>>, %arg1: !fir.ptr<!fir.array<100xf32>>) {
151   %c100 = arith.constant 100 : index
152   %c99 = arith.constant 99 : index
153   %c1 = arith.constant 1 : index
154   %c0 = arith.constant 0 : index
155   %0 = fir.alloca f32
156   %1 = fir.shape %c100 : (index) -> !fir.shape<1>
157   %2 = fir.array_load %arg0(%1) : (!fir.ptr<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
158   %3 = fir.array_load %arg1(%1) : (!fir.ptr<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
159   %4 = fir.do_loop %arg2 = %c0 to %c99 step %c1 unordered iter_args(%arg3 = %3) -> (!fir.array<100xf32>) {
160     %5 = fir.array_fetch %2, %arg2 : (!fir.array<100xf32>, index) -> f32
161     %6 = fir.array_update %arg3, %5, %arg2 : (!fir.array<100xf32>, f32, index) -> !fir.array<100xf32>
162     fir.result %6 : !fir.array<100xf32>
163   }
164   fir.array_merge_store %3, %4 to %arg1 : !fir.array<100xf32>, !fir.array<100xf32>, !fir.ptr<!fir.array<100xf32>>
165   return
168 // -----
170 // Test derived_target(:)%i = integer_pointer(:)
171 // The integer pointer may be aliasing the derived target component.
172 // ALL-LABEL: func @derived_whose_component_may_be_aliased
173 // ALL: %[[ALLOC:.*]] = fir.allocmem !fir.array<4x!fir.type<some_type{i:i32}>>
174 // ALL-COUNT-3: fir.do_loop
175 // ALL: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<4x!fir.type<some_type{i:i32}>>>
176 func.func @derived_whose_component_may_be_aliased(%arg0: !fir.box<!fir.array<4x!fir.type<some_type{i:i32}>>> {fir.target}, %arg1: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) {
177   %c4 = arith.constant 4 : index
178   %0 = fir.field_index i, !fir.type<some_type{i:i32}>
179   %c1 = arith.constant 1 : index
180   %1 = fir.slice %c1, %c4, %c1 path %0 : (index, index, index, !fir.field) -> !fir.slice<1>
181   %2 = fir.array_load %arg0 [%1] : (!fir.box<!fir.array<4x!fir.type<some_type{i:i32}>>>, !fir.slice<1>) -> !fir.array<4xi32>
182   %3 = fir.load %arg1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
183   %c0 = arith.constant 0 : index
184   %4:3 = fir.box_dims %3, %c0 : (!fir.box<!fir.ptr<!fir.array<?xi32>>>, index) -> (index, index, index)
185   %5 = fir.shift %4#0 : (index) -> !fir.shift<1>
186   %6 = fir.array_load %3(%5) : (!fir.box<!fir.ptr<!fir.array<?xi32>>>, !fir.shift<1>) -> !fir.array<?xi32>
187   %7 = arith.subi %c4, %c1 : index
188   %8 = fir.do_loop %arg2 = %c0 to %7 step %c1 unordered iter_args(%arg3 = %2) -> (!fir.array<4xi32>) {
189     %9 = fir.array_fetch %6, %arg2 : (!fir.array<?xi32>, index) -> i32
190     %10 = fir.array_update %arg3, %9, %arg2 : (!fir.array<4xi32>, i32, index) -> !fir.array<4xi32>
191     fir.result %10 : !fir.array<4xi32>
192   }
193   fir.array_merge_store %2, %8 to %arg0[%1] : !fir.array<4xi32>, !fir.array<4xi32>, !fir.box<!fir.array<4x!fir.type<some_type{i:i32}>>>, !fir.slice<1>
194   return
197 // -----
199 // Test real_target = complex_target(:)%re
200 // The real pointer may be aliasing the complex real part.
201 // ALL-LABEL: func @complex_real_aliasing
202 // ALL: %[[ALLOC:.*]] = fir.allocmem !fir.array<?xf32>
203 // ALL-COUNT-3: fir.do_loop
204 // ALL: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<?xf32>>
205 func.func @complex_real_aliasing(%arg0: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, %arg1: !fir.ref<!fir.array<4x!fir.complex<4>>> {fir.target}) {
206   %c4 = arith.constant 4 : index
207   %0 = fir.load %arg0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
208   %c0 = arith.constant 0 : index
209   %1:3 = fir.box_dims %0, %c0 : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, index) -> (index, index, index)
210   %2 = fir.shift %1#0 : (index) -> !fir.shift<1>
211   %3 = fir.array_load %0(%2) : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, !fir.shift<1>) -> !fir.array<?xf32>
212   %c0_i32 = arith.constant 0 : i32
213   %4 = fir.shape %c4 : (index) -> !fir.shape<1>
214   %c1 = arith.constant 1 : index
215   %5 = fir.slice %c1, %c4, %c1 path %c0_i32 : (index, index, index, i32) -> !fir.slice<1>
216   %6 = fir.array_load %arg1(%4) [%5] : (!fir.ref<!fir.array<4x!fir.complex<4>>>, !fir.shape<1>, !fir.slice<1>) -> !fir.array<4xf32>
217   %7 = arith.subi %c4, %c1 : index
218   %8 = fir.do_loop %arg2 = %c0 to %7 step %c1 unordered iter_args(%arg3 = %3) -> (!fir.array<?xf32>) {
219     %9 = fir.array_fetch %6, %arg2 : (!fir.array<4xf32>, index) -> f32
220     %10 = fir.array_update %arg3, %9, %arg2 : (!fir.array<?xf32>, f32, index) -> !fir.array<?xf32>
221     fir.result %10 : !fir.array<?xf32>
222   }
223   fir.array_merge_store %3, %8 to %0 : !fir.array<?xf32>, !fir.array<?xf32>, !fir.box<!fir.ptr<!fir.array<?xf32>>>
224   return
227 // -----
229 // Test `array(:) = pointer(:)`
230 // ALL-LABEL: func @maybe_overlap_3
231 // ALL: %[[ALLOC:.*]] = fir.allocmem !fir.array<100xf32>
232 // ALL: fir.do_loop
233 // ALL: fir.do_loop
234 // ALL: fir.do_loop
235 // ALL: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<100xf32>>
236 fir.global @_QMdataEglob target : !fir.array<100xf32> {
237   %0 = fir.undefined !fir.array<100xf32>
238   fir.has_value %0 : !fir.array<100xf32>
241 func.func @maybe_overlap_3(%arg0: !fir.ptr<!fir.array<100xf32>>, %arg1: !fir.ref<!fir.array<100xf32>> {fir.target}) {
242   %c100 = arith.constant 100 : index
243   %c99 = arith.constant 99 : index
244   %c1 = arith.constant 1 : index
245   %c0 = arith.constant 0 : index
246   %0 = fir.address_of(@_QMdataEglob) : !fir.ref<!fir.array<100xf32>>
247   %1 = fir.shape %c100 : (index) -> !fir.shape<1>
248   %2 = fir.array_load %arg0(%1) : (!fir.ptr<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
249   %3 = fir.array_load %0(%1) : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
250   %4 = fir.do_loop %arg2 = %c0 to %c99 step %c1 unordered iter_args(%arg3 = %3) -> (!fir.array<100xf32>) {
251     %5 = fir.array_fetch %2, %arg2 : (!fir.array<100xf32>, index) -> f32
252     %6 = fir.array_update %arg3, %5, %arg2 : (!fir.array<100xf32>, f32, index) -> !fir.array<100xf32>
253     fir.result %6 : !fir.array<100xf32>
254   }
255   fir.array_merge_store %3, %4 to %0 : !fir.array<100xf32>, !fir.array<100xf32>, !fir.ref<!fir.array<100xf32>>
256   return
259 // -----
261 // Test `array(:) = pointer(:)`
262 // ALL-LABEL: func @no_overlap_3
263 // OPT-NOT: fir.allocmem
264 // NOOPT: %[[ALLOC:.*]] = fir.allocmem !fir.array<100xf32>
265 // NOOPT: fir.do_loop
266 // NOOPT: fir.do_loop
267 // NOOPT: fir.do_loop
268 // NOOPT: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<100xf32>>
269 fir.global @_QMdataEglob : !fir.array<100xf32> {
270   %0 = fir.undefined !fir.array<100xf32>
271   fir.has_value %0 : !fir.array<100xf32>
274 func.func @no_overlap_3(%arg0: !fir.ptr<!fir.array<100xf32>>, %arg1: !fir.ref<!fir.array<100xf32>> {fir.target}) {
275   %c100 = arith.constant 100 : index
276   %c99 = arith.constant 99 : index
277   %c1 = arith.constant 1 : index
278   %c0 = arith.constant 0 : index
279   %0 = fir.address_of(@_QMdataEglob) : !fir.ref<!fir.array<100xf32>>
280   %1 = fir.shape %c100 : (index) -> !fir.shape<1>
281   %2 = fir.array_load %arg0(%1) : (!fir.ptr<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
282   %3 = fir.array_load %0(%1) : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
283   %4 = fir.do_loop %arg2 = %c0 to %c99 step %c1 unordered iter_args(%arg3 = %3) -> (!fir.array<100xf32>) {
284     %5 = fir.array_fetch %2, %arg2 : (!fir.array<100xf32>, index) -> f32
285     %6 = fir.array_update %arg3, %5, %arg2 : (!fir.array<100xf32>, f32, index) -> !fir.array<100xf32>
286     fir.result %6 : !fir.array<100xf32>
287   }
288   fir.array_merge_store %3, %4 to %0 : !fir.array<100xf32>, !fir.array<100xf32>, !fir.ref<!fir.array<100xf32>>
289   return