Break circular dependency between FIR dialect and utilities
[llvm-project.git] / flang / test / Fir / array-value-copy.fir
blob58db8b3ae4cd233c084fb8fd3ac42933def8c66d
1 // Test for the array-value-copy pass
2 // RUN: fir-opt --split-input-file --array-value-copy %s | FileCheck %s
4 // Test simple fir.array_load/fir.array_fetch conversion to fir.array_coor
5 func.func @array_fetch_conversion(%arr1 : !fir.ref<!fir.array<?x?xf32>>, %m: index, %n: index) {
6   %c10 = arith.constant 10 : index
7   %c20 = arith.constant 20 : index
8   %s = fir.shape %m, %n : (index, index) -> !fir.shape<2>
9   %av1 = fir.array_load %arr1(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32>
10   %f = fir.array_fetch %av1, %c10, %c20 : (!fir.array<?x?xf32>, index, index) -> f32
11   return
14 // CHECK-LABEL: func @array_fetch_conversion(
15 // CHECK-SAME:                               %[[ARRAY:.*]]: !fir.ref<!fir.array<?x?xf32>>,
16 // CHECK-SAME:                               %[[ARG1:.*]]: index,
17 // CHECK-SAME:                               %[[ARG2:.*]]: index) {
18 // CHECK:         %{{.*}} = fir.shape %[[ARG1]], %[[ARG2]] : (index, index) -> !fir.shape<2>
19 // CHECK:         %{{.*}} = fir.undefined !fir.array<?x?xf32>
20 // CHECK:         %[[VAL_0:.*]] = arith.addi %{{.*}}, %{{.*}} : index
21 // CHECK:         %[[VAL_1:.*]] = arith.addi %{{.*}}, %{{.*}} : index
22 // CHECK-NOT:     fir.array_load
23 // CHECK-NOT:     fir.array_fetch
24 // CHECK:         %{{.*}} = fir.array_coor %arg0(%0) %[[VAL_0]], %[[VAL_1]] : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>, index, index) -> !fir.ref<f32>
25 // CHECK:         %{{.*}} = fir.load %4 : !fir.ref<f32>
27 // -----
29 // Test simple fir.array_load/fir.array_update conversion without copy-in/copy-out
30 func.func @array_update_conversion(%arr1 : !fir.box<!fir.array<?x?xf32>>, %m: index, %n: index) {
31   %c10 = arith.constant 10 : index
32   %c20 = arith.constant 20 : index
33   %c1 = arith.constant 1 : index
34   %f = arith.constant 2.0 : f32
35   %s = fir.shape %m, %n : (index, index) -> !fir.shape<2>
36   %av1 = fir.array_load %arr1(%s) : (!fir.box<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32>
37   %av2 = fir.array_update %av1, %f, %c1, %c1 : (!fir.array<?x?xf32>, f32, index, index) -> !fir.array<?x?xf32>
38   return
41 // CHECK-LABEL: func @array_update_conversion
42 // CHECK-NOT:     fir.array_load
43 // CHECK-NOT:     fir.array_update
44 // CHECK:         %{{.*}} = arith.addi %{{.*}}, %{{.*}} : index
45 // CHECK:         %{{.*}} = arith.addi %{{.*}}, %{{.*}} : index
46 // CHECK:         %[[ARRAY_COOR:.*]] = fir.array_coor{{.*}}-> !fir.ref<f32>
47 // CHECK:         fir.store %{{.*}} to %[[ARRAY_COOR]] : !fir.ref<f32>
49 // -----
51 // Test simple fir.array_load/fir.array_update conversion without copy-in/copy-out
52 func.func @array_update_conversion(%arr1 : !fir.box<!fir.array<?x?xf32>>, %m: index, %n: index, %cond: i1) {
53   %c10 = arith.constant 10 : index
54   %c20 = arith.constant 20 : index
55   %c1 = arith.constant 1 : index
56   %f = arith.constant 2.0 : f32
57   %g = arith.constant 4.0 : f32
58   %s = fir.shape %m, %n : (index, index) -> !fir.shape<2>
59   %av1 = fir.array_load %arr1(%s) : (!fir.box<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32>
60   fir.if %cond {
61     %av2 = fir.array_update %av1, %f, %c1, %c1 : (!fir.array<?x?xf32>, f32, index, index) -> !fir.array<?x?xf32>
62   } else {
63     %av2 = fir.array_update %av1, %g, %c1, %c1 : (!fir.array<?x?xf32>, f32, index, index) -> !fir.array<?x?xf32>
64   }
65   return
68 // -----
70 // Test fir.array_load/fir.array_fetch/fir.array_update conversion with
71 // an introduced copy-in/copy-out.
72 // 
73 // This test corresponds to a simplified FIR version of the following Fortran
74 // code.
75 // ```
76 //   integer :: i(10)
77 //   i = i(10:1:-1)
78 //  end
79 // ```
81 func.func @conversion_with_temporary(%arr0 : !fir.ref<!fir.array<10xi32>>) {
82   %c10 = arith.constant 10 : index
83   %1 = fir.shape %c10 : (index) -> !fir.shape<1>
84   %2 = fir.array_load %arr0(%1) : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> !fir.array<10xi32>
85   %c10_i64 = arith.constant 10 : i64
86   %3 = fir.convert %c10_i64 : (i64) -> index
87   %c1_i64 = arith.constant 1 : i64
88   %c-1_i64 = arith.constant -1 : i64
89   %4 = fir.shape %c10 : (index) -> !fir.shape<1>
90   %5 = fir.slice %c10_i64, %c1_i64, %c-1_i64 : (i64, i64, i64) -> !fir.slice<1>
91   %6 = fir.array_load %arr0(%4) [%5] : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.slice<1>) -> !fir.array<10xi32>
92   %c1 = arith.constant 1 : index
93   %c0 = arith.constant 0 : index
94   %7 = arith.subi %3, %c1 : index
95   %8 = fir.do_loop %arg0 = %c0 to %7 step %c1 unordered iter_args(%arg1 = %2) -> (!fir.array<10xi32>) {
96     %9 = fir.array_fetch %6, %arg0 : (!fir.array<10xi32>, index) -> i32
97     %10 = fir.array_update %arg1, %9, %arg0 : (!fir.array<10xi32>, i32, index) -> !fir.array<10xi32>
98     fir.result %10 : !fir.array<10xi32>
99   }
100   fir.array_merge_store %2, %8 to %arr0 : !fir.array<10xi32>, !fir.array<10xi32>, !fir.ref<!fir.array<10xi32>>
101   return
104 // CHECK-LABEL: func @conversion_with_temporary(
105 // CHECK-SAME:                                  %[[ARR0:.*]]: !fir.ref<!fir.array<10xi32>>)
106 // Allocation of temporary array.
107 // CHECK:         %[[TEMP:.*]] = fir.allocmem !fir.array<10xi32>
108 // Copy of original array to temp.
109 // CHECK:         fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
110 // CHECK:           %[[COOR0:.*]] = fir.array_coor %[[ARR0]](%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
111 // CHECK:           %[[COOR1:.*]] = fir.array_coor %[[TEMP]](%{{.*}}) %{{.*}} : (!fir.heap<!fir.array<10xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
112 // CHECK:           %[[LOAD0:.*]] = fir.load %[[COOR0]] : !fir.ref<i32>
113 // CHECK:           fir.store %[[LOAD0]] to %[[COOR1]] : !fir.ref<i32>
114 // CHECK:         }
115 // Perform the assignment i = i(10:1:-1) using the temporary array.
116 // CHECK:         %{{.*}} = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} unordered iter_args(%{{.*}} = %{{.*}}) -> (!fir.array<10xi32>) {
117 // CHECK-NOT:       %{{.*}} = fir.array_fetch
118 // CHECK-NOT:       %{{.*}} = fir.array_update
119 // CHECK:           %[[COOR0:.*]] = fir.array_coor %[[ARR0]](%{{.*}}) [%{{.*}}] %{{.*}} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.slice<1>, index) -> !fir.ref<i32>
120 // CHECK:           %[[LOAD0:.*]] = fir.load %[[COOR0]] : !fir.ref<i32>
121 // CHECK:           %[[COOR1:.*]] = fir.array_coor %[[TEMP]](%{{.*}}) %{{.*}} : (!fir.heap<!fir.array<10xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
122 // CHECK:           fir.store %[[LOAD0]] to %[[COOR1]] : !fir.ref<i32>
123 // CHECK:           fir.result %{{.*}} : !fir.array<10xi32>
124 // CHECK:         }
125 // Copy the result back to the original array.
126 // CHECK:         fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
127 // CHECK:           %[[COOR0:.*]] = fir.array_coor %[[TEMP]](%{{.*}}) %{{.*}} : (!fir.heap<!fir.array<10xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
128 // CHECK:           %[[COOR1:.*]] = fir.array_coor %[[ARR0]](%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
129 // CHECK:           %[[LOAD0:.*]] = fir.load %[[COOR0:.*]] : !fir.ref<i32>
130 // CHECK:           fir.store %[[LOAD0]] to %[[COOR1]] : !fir.ref<i32>
131 // CHECK:         }
132 // Free temporary array.
133 // CHECK:         fir.freemem %[[TEMP]] : !fir.heap<!fir.array<10xi32>>
135 // -----
137 // Test fir.array_load/fir.array_fetch/fir.array_update conversion with
138 // an introduced copy-in/copy-out on a multidimensional array.
140 func.func @conversion_with_temporary_multidim(%0: !fir.ref<!fir.array<10x5xi32>>) {
141   %c10 = arith.constant 10 : index
142   %c5 = arith.constant 5 : index
143   %1 = fir.shape %c10, %c5 : (index, index) -> !fir.shape<2>
144   %2 = fir.array_load %0(%1) : (!fir.ref<!fir.array<10x5xi32>>, !fir.shape<2>) -> !fir.array<10x5xi32>
145   %c10_i64 = arith.constant 10 : i64
146   %3 = fir.convert %c10_i64 : (i64) -> index
147   %c5_i64 = arith.constant 5 : i64
148   %4 = fir.convert %c5_i64 : (i64) -> index
149   %c1 = arith.constant 1 : index
150   %c10_i64_0 = arith.constant 10 : i64
151   %c1_i64 = arith.constant 1 : i64
152   %c-1_i64 = arith.constant -1 : i64
153   %5 = arith.addi %c1, %c5 : index
154   %6 = arith.subi %5, %c1 : index
155   %c1_i64_1 = arith.constant 1 : i64
156   %7 = fir.shape %c10, %c5 : (index, index) -> !fir.shape<2>
157   %8 = fir.slice %c10_i64_0, %c1_i64, %c-1_i64, %c1, %6, %c1_i64_1 : (i64, i64, i64, index, index, i64) -> !fir.slice<2>
158   %9 = fir.array_load %0(%7) [%8] : (!fir.ref<!fir.array<10x5xi32>>, !fir.shape<2>, !fir.slice<2>) -> !fir.array<10x5xi32>
159   %c1_2 = arith.constant 1 : index
160   %c0 = arith.constant 0 : index
161   %10 = arith.subi %3, %c1_2 : index
162   %11 = arith.subi %4, %c1_2 : index
163   %12 = fir.do_loop %arg0 = %c0 to %11 step %c1_2 unordered iter_args(%arg1 = %2) -> (!fir.array<10x5xi32>) {
164     %13 = fir.do_loop %arg2 = %c0 to %10 step %c1_2 unordered iter_args(%arg3 = %arg1) -> (!fir.array<10x5xi32>) {
165       %14 = fir.array_fetch %9, %arg2, %arg0 : (!fir.array<10x5xi32>, index, index) -> i32
166       %15 = fir.array_update %arg3, %14, %arg2, %arg0 : (!fir.array<10x5xi32>, i32, index, index) -> !fir.array<10x5xi32>
167       fir.result %15 : !fir.array<10x5xi32>
168     }
169     fir.result %13 : !fir.array<10x5xi32>
170   }
171   fir.array_merge_store %2, %12 to %0 : !fir.array<10x5xi32>, !fir.array<10x5xi32>, !fir.ref<!fir.array<10x5xi32>>
172   return
175 // CHECK-LABEL: func @conversion_with_temporary_multidim(
176 // CHECK-SAME:                                           %[[ARR0:.*]]: !fir.ref<!fir.array<10x5xi32>>) {
177 // CHECK:         %[[CST10:.*]] = arith.constant 10 : index
178 // CHECK:         %[[CST5:.*]] = arith.constant 5 : index
179 // CHECK:         %[[TEMP:.*]] = fir.allocmem !fir.array<10x5xi32>
180 // CHECK:         %[[IDX5:.*]] = fir.convert %[[CST5]] : (index) -> index
181 // CHECK:         %[[UB5:.*]] = arith.subi %[[IDX5]], %{{.*}} : index
182 // CHECK:         fir.do_loop %[[INDUC0:.*]] = %{{.*}} to %[[UB5]] step %{{.*}} {
183 // CHECK:           %[[IDX10:.*]] = fir.convert %[[CST10]] : (index) -> index
184 // CHECK:           %[[UB10:.*]] = arith.subi %[[IDX10]], %{{.*}} : index
185 // CHECK:           fir.do_loop %[[INDUC1:.*]] = %{{.*}} to %[[UB10]] step %{{.*}} {
186 // CHECK:             %[[IDX1:.*]] = arith.addi %[[INDUC1]], %{{.*}} : index
187 // CHECK:             %[[IDX2:.*]] = arith.addi %[[INDUC0]], %{{.*}} : index
188 // CHECK:             %[[COOR0:.*]] = fir.array_coor %[[ARR0]](%{{.*}}) %[[IDX1:.*]], %[[IDX2:.*]] : (!fir.ref<!fir.array<10x5xi32>>, !fir.shape<2>, index, index) -> !fir.ref<i32>
189 // CHECK:             %[[COOR1:.*]] = fir.array_coor %[[TEMP]](%{{.*}}) %{{.*}}, %{{.*}} : (!fir.heap<!fir.array<10x5xi32>>, !fir.shape<2>, index, index) -> !fir.ref<i32>
190 // CHECK:             %[[LOAD0:.*]] = fir.load %[[COOR0]] : !fir.ref<i32>
191 // CHECK:             fir.store %[[LOAD0]] to %[[COOR1]] : !fir.ref<i32>
192 // CHECK:         %{{.*}} = fir.do_loop %[[INDUC0:.*]] = %{{.*}} to %{{.*}} step %{{.*}} unordered iter_args(%{{.*}} = %{{.*}}) -> (!fir.array<10x5xi32>) {
193 // CHECK:           %{{.*}} = fir.do_loop %[[INDUC1:.*]] = %{{.*}} to %{{.*}} step %{{.*}} unordered iter_args(%{{.*}} = %{{.*}}) -> (!fir.array<10x5xi32>) {
194 // CHECK:             %[[IDX1:.*]] = arith.addi %[[INDUC1]], %{{.*}} : index
195 // CHECK:             %[[IDX2:.*]] = arith.addi %[[INDUC0]], %{{.*}} : index
196 // CHECK-NOT:         %{{.*}} = fir.array_fetch
197 // CHECK-NOT:         %{{.*}} = fir.array_update
198 // CHECK:             %[[COOR0:.*]] = fir.array_coor %[[ARR0]](%{{.*}}) [%{{.*}}] %[[IDX1]], %[[IDX2]] : (!fir.ref<!fir.array<10x5xi32>>, !fir.shape<2>, !fir.slice<2>, index, index) -> !fir.ref<i32>
199 // CHECK:             %[[LOAD0:.*]] = fir.load %[[COOR0]] : !fir.ref<i32>
200 // CHECK:             %[[COOR1:.*]] = fir.array_coor %[[TEMP]](%{{.*}}) %{{.*}}, %{{.*}} : (!fir.heap<!fir.array<10x5xi32>>, !fir.shape<2>, index, index) -> !fir.ref<i32>
201 // CHECK:             fir.store %[[LOAD0]] to %[[COOR1]] : !fir.ref<i32>
202 // CHECK:         %[[IDX5:.*]] = fir.convert %[[CST5]] : (index) -> index
203 // CHECK:         %[[UB5:.*]] = arith.subi %[[IDX5]], %{{.*}} : index
204 // CHECK:         fir.do_loop %[[INDUC0:.*]] = %{{.*}} to %[[UB5]] step %{{.*}} {
205 // CHECK:           %[[IDX10:.*]] = fir.convert %[[CST10]] : (index) -> index
206 // CHECK:           %[[UB10:.*]] = arith.subi %[[IDX10]], %{{.*}} : index
207 // CHECK:           fir.do_loop %[[INDUC1:.*]] = %{{.*}} to %[[UB10]] step %{{.*}} {
208 // CHECK:             %[[IDX1:.*]] = arith.addi %[[INDUC1]], %{{.*}} : index
209 // CHECK:             %[[IDX2:.*]] = arith.addi %[[INDUC0]], %{{.*}} : index  
210 // CHECK:             %[[COOR0:.*]] = fir.array_coor %[[TEMP]](%{{.*}}) %[[IDX1]], %[[IDX2]] : (!fir.heap<!fir.array<10x5xi32>>, !fir.shape<2>, index, index) -> !fir.ref<i32>
211 // CHECK:             %[[COOR1:.*]] = fir.array_coor %[[ARR0]](%{{.*}}) %{{.*}}, %{{.*}} : (!fir.ref<!fir.array<10x5xi32>>, !fir.shape<2>, index, index) -> !fir.ref<i32>
212 // CHECK:             %[[LOAD0:.*]] = fir.load %[[COOR0]] : !fir.ref<i32>
213 // CHECK:             fir.store %[[LOAD0]] to %[[COOR1]] : !fir.ref<i32>
214 // CHECK:         fir.freemem %[[TEMP]] : !fir.heap<!fir.array<10x5xi32>>
216 // -----
218 // Test fir.array_modify conversion with no overlap.
219 func.func @array_modify_no_overlap(%arg0: !fir.ref<!fir.array<100xf32>>, %arg1: !fir.ref<!fir.array<100xf32>>) {
220   %c100 = arith.constant 100 : index
221   %c99 = arith.constant 99 : index
222   %c1 = arith.constant 1 : index
223   %c0 = arith.constant 0 : index
224   %0 = fir.alloca f32
225   %1 = fir.shape %c100 : (index) -> !fir.shape<1>
226   %2 = fir.array_load %arg0(%1) : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
227   %3 = fir.array_load %arg1(%1) : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
228   %4 = fir.do_loop %arg2 = %c0 to %c99 step %c1 unordered iter_args(%arg3 = %2) -> (!fir.array<100xf32>) {
229     %5 = fir.array_fetch %3, %arg2 : (!fir.array<100xf32>, index) -> f32
230     %6:2 = fir.array_modify %arg3, %arg2 : (!fir.array<100xf32>, index) -> (!fir.ref<f32>, !fir.array<100xf32>)
231     fir.store %5 to %0 : !fir.ref<f32>
232     fir.call @user_defined_assignment(%6#0, %0) : (!fir.ref<f32>, !fir.ref<f32>) -> ()
233     fir.result %6#1 : !fir.array<100xf32>
234   }
235   fir.array_merge_store %2, %4 to %arg0 : !fir.array<100xf32>, !fir.array<100xf32>, !fir.ref<!fir.array<100xf32>>
236   return
239 func.func private @user_defined_assignment(!fir.ref<f32>, !fir.ref<f32>)
241 // CHECK-LABEL:   func @array_modify_no_overlap(
242 // CHECK-SAME:                                  %[[ARR0:.*]]: !fir.ref<!fir.array<100xf32>>,
243 // CHECK-SAME:                                  %[[ARR1:.*]]: !fir.ref<!fir.array<100xf32>>) {
244 // CHECK:           %[[VAR0:.*]] = fir.alloca f32
245 // CHECK-COUNT-1:   %{{.*}} = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} unordered iter_args(%{{.*}} = %{{.*}}) -> (!fir.array<100xf32>) {
246 // CHECK-NOT:       %{{.*}} = fir.array_fetch
247 // CHECK-NOT:       %{{.*}} = fir.array_modify
248 // CHECK:           %[[COOR0:.*]] = fir.array_coor %arg1(%1) %5 : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
249 // CHECK:           %[[LOAD0:.*]] = fir.load %[[COOR0]] : !fir.ref<f32>
250 // CHECK:           %[[COOR1:.*]] = fir.array_coor %[[ARR0]](%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
251 // CHECK:           fir.store %[[LOAD0]] to %[[VAR0]] : !fir.ref<f32>
252 // CHECK:           fir.call @{{.*}}(%[[COOR1]], %[[VAR0]]) : (!fir.ref<f32>, !fir.ref<f32>) -> ()
254 // -----
256 // Test fir.array_modify conversion with an overlap.
257 // Test user_defined_assignment(arg0(:), arg0(100:1:-1))
258 func.func @array_modify_overlap(%arg0: !fir.ref<!fir.array<100xf32>>) {
259   %c100 = arith.constant 100 : index
260   %c99 = arith.constant 99 : index
261   %c1 = arith.constant 1 : index
262   %c-1 = arith.constant -1 : index
263   %c0 = arith.constant 0 : index
264   %0 = fir.alloca f32
265   %1 = fir.shape %c100 : (index) -> !fir.shape<1>
266   %2 = fir.array_load %arg0(%1) : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
267   %3 = fir.slice %c100, %c1, %c-1 : (index, index, index) -> !fir.slice<1>
268   %4 = fir.array_load %arg0(%1) [%3] : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.slice<1>) -> !fir.array<100xf32>
269   %5 = fir.do_loop %arg1 = %c0 to %c99 step %c1 unordered iter_args(%arg2 = %2) -> (!fir.array<100xf32>) {
270     %6 = fir.array_fetch %4, %arg1 : (!fir.array<100xf32>, index) -> f32
271     %7:2 = fir.array_modify %arg2, %arg1 : (!fir.array<100xf32>, index) -> (!fir.ref<f32>, !fir.array<100xf32>)
272     fir.store %6 to %0 : !fir.ref<f32>
273     fir.call @user_defined_assignment(%7#0, %0) : (!fir.ref<f32>, !fir.ref<f32>) -> ()
274     fir.result %7#1 : !fir.array<100xf32>
275   }
276   fir.array_merge_store %2, %5 to %arg0 : !fir.array<100xf32>, !fir.array<100xf32>, !fir.ref<!fir.array<100xf32>>
277   return
280 func.func private @user_defined_assignment(!fir.ref<f32>, !fir.ref<f32>)
282 // CHECK-LABEL:   func @array_modify_overlap(
283 // CHECK-SAME:                               %[[ARR0:.*]]: !fir.ref<!fir.array<100xf32>>) {
284 // CHECK:           %[[VAR0:.*]] = fir.alloca f32
285 // Allocate the temporary array.
286 // CHECK:           %[[TEMP:.*]] = fir.allocmem !fir.array<100xf32>
287 // Copy original array to temp.
288 // CHECK:           fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
289 // CHECK:             %[[COOR0:.*]] = fir.array_coor %[[ARR0]](%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
290 // CHECK:             %[[COOR1:.*]] = fir.array_coor %[[TEMP]](%{{.*}}) %{{.*}} : (!fir.heap<!fir.array<100xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
291 // CHECK:             %[[LOAD0:.*]] = fir.load %[[COOR0]] : !fir.ref<f32>
292 // CHECK:             fir.store %[[LOAD0]] to %[[COOR1]] : !fir.ref<f32>
293 // CHECK:           }
294 // CHECK:           %[[VAL_21:.*]] = fir.undefined !fir.array<100xf32>
295 // CHECK:           %[[VAL_23:.*]] = fir.undefined !fir.array<100xf32>
296 // CHECK-NOT:         %{{.*}} = fir.array_fetch
297 // CHECK-NOT:         %{{.*}} = fir.array_modify
298 // CHECK:             %[[COOR0:.*]] = fir.array_coor %[[ARR0]](%{{.*}}) {{\[}}%{{.*}}] %{{.*}} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.slice<1>, index) -> !fir.ref<f32>
299 // CHECK:             %[[LOAD0:.*]] = fir.load %[[COOR0]] : !fir.ref<f32>
300 // CHECK:             %[[COOR1:.*]] = fir.array_coor %[[TEMP]](%{{.*}}) %{{.*}} : (!fir.heap<!fir.array<100xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
301 // CHECK:             fir.store %[[LOAD0]] to %[[VAR0]] : !fir.ref<f32>
302 // CHECK:             fir.call @user_defined_assignment(%[[COOR1]], %[[VAR0]]) : (!fir.ref<f32>, !fir.ref<f32>) -> ()
303 // CHECK:           }
304 // Copy back result to original array from temp.
305 // CHECK:           fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
306 // CHECK:             %[[COOR0:.*]] = fir.array_coor %[[TEMP]](%{{.*}}) %{{.*}} : (!fir.heap<!fir.array<100xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
307 // CHECK:             %[[COOR1:.*]] = fir.array_coor %[[ARR0]](%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
308 // CHECK:             %[[LOAD0:.*]] = fir.load %[[COOR0]] : !fir.ref<f32>
309 // CHECK:             fir.store %[[LOAD0]] to %[[COOR1]] : !fir.ref<f32>
310 // CHECK:           }
311 // Free the temporary array.
312 // CHECK:           fir.freemem %[[TEMP]] : !fir.heap<!fir.array<100xf32>>
313 // CHECK:           return
314 // CHECK:         }
316 // -----
318 // Test array of types with no overlap
319 func.func @array_of_types() {
320   %0 = fir.alloca i32 {bindc_name = "j", uniq_name = "_QEj"}
321   %1 = fir.address_of(@_QEtypes) : !fir.ref<!fir.array<10x!fir.type<_QTd{i:!fir.array<10xi32>}>>>
322   %c1_i32 = arith.constant 1 : i32
323   %2 = fir.convert %c1_i32 : (i32) -> index
324   %c10_i32 = arith.constant 10 : i32
325   %3 = fir.convert %c10_i32 : (i32) -> index
326   %c1 = arith.constant 1 : index
327   %4 = fir.do_loop %arg0 = %2 to %3 step %c1 -> index {
328     %6 = fir.convert %arg0 : (index) -> i32
329     fir.store %6 to %0 : !fir.ref<i32>
330     %c1_0 = arith.constant 1 : index
331     %7 = fir.load %0 : !fir.ref<i32>
332     %8 = fir.convert %7 : (i32) -> i64
333     %c1_i64 = arith.constant 1 : i64
334     %9 = arith.subi %8, %c1_i64 : i64
335     %10 = fir.coordinate_of %1, %9 : (!fir.ref<!fir.array<10x!fir.type<_QTd{i:!fir.array<10xi32>}>>>, i64) -> !fir.ref<!fir.type<_QTd{i:!fir.array<10xi32>}>>
336     %11 = fir.field_index i, !fir.type<_QTd{i:!fir.array<10xi32>}>
337     %12 = fir.coordinate_of %10, %11 : (!fir.ref<!fir.type<_QTd{i:!fir.array<10xi32>}>>, !fir.field) -> !fir.ref<!fir.array<10xi32>>
338     %c10 = arith.constant 10 : index
339     %13 = arith.addi %c1_0, %c10 : index
340     %14 = arith.subi %13, %c1_0 : index
341     %c1_i64_1 = arith.constant 1 : i64
342     %15 = fir.shape %c10 : (index) -> !fir.shape<1>
343     %16 = fir.slice %c1_0, %14, %c1_i64_1 : (index, index, i64) -> !fir.slice<1>
344     %17 = fir.array_load %12(%15) [%16] : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.slice<1>) -> !fir.array<10xi32>
345     %c10_i64 = arith.constant 10 : i64
346     %18 = fir.convert %c10_i64 : (i64) -> index
347     %c0_i32 = arith.constant 0 : i32
348     %c1_2 = arith.constant 1 : index
349     %c0 = arith.constant 0 : index
350     %19 = arith.subi %18, %c1_2 : index
351     %20 = fir.do_loop %arg1 = %c0 to %19 step %c1_2 unordered iter_args(%arg2 = %17) -> (!fir.array<10xi32>) {
352       %22 = fir.array_update %arg2, %c0_i32, %arg1 : (!fir.array<10xi32>, i32, index) -> !fir.array<10xi32>
353       fir.result %22 : !fir.array<10xi32>
354     }
355     fir.array_merge_store %17, %20 to %12[%16] : !fir.array<10xi32>, !fir.array<10xi32>, !fir.ref<!fir.array<10xi32>>, !fir.slice<1>
356     %21 = arith.addi %arg0, %c1 : index
357     fir.result %21 : index
358   }
359   %5 = fir.convert %4 : (index) -> i32
360   fir.store %5 to %0 : !fir.ref<i32>
361   return
364 // CHECK-LABEL: func @array_of_types() {
365 // CHECK:         %{{.*}} = fir.do_loop %{{.*}} = %{{.*}}  to %{{.*}}  step %{{.*}}  -> index {
366 // CHECK:           %{{.*}} = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} unordered iter_args(%arg2 = %17) -> (!fir.array<10xi32>) {
367 // CHECK-NOT:         %{{.*}} = fir.array_update
368 // CHECK:             %[[COOR0:.*]] = fir.array_coor %{{.*}}(%{{.*}}) [%{{.*}}] %{{.*}} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.slice<1>, index) -> !fir.ref<i32>
369 // CHECK:             fir.store %{{.*}} to %[[COOR0]] : !fir.ref<i32>
370 // CHECK-NOT:         fir.array_merge_store
372 // -----
374 // Test fir.array_load/boxed array
375 func.func @conversion_with_temporary_boxed_array(%arr0 : !fir.box<!fir.array<10xi32>>) {
376   %c10 = arith.constant 10 : index
377   %1:3 = fir.box_dims %arr0, %c10 : (!fir.box<!fir.array<10xi32>>, index) -> (index, index, index)
378   %shift = fir.shift %1#0 : (index) -> !fir.shift<1>
379   %2 = fir.array_load %arr0(%shift) : (!fir.box<!fir.array<10xi32>>, !fir.shift<1>) -> !fir.array<10xi32>
380   %c10_i64 = arith.constant 10 : i64
381   %3 = fir.convert %c10_i64 : (i64) -> index
382   %c1_i64 = arith.constant 1 : i64
383   %c-1_i64 = arith.constant -1 : i64
384   %4 = fir.shape %c10 : (index) -> !fir.shape<1>
385   %5 = fir.slice %c10_i64, %c1_i64, %c-1_i64 : (i64, i64, i64) -> !fir.slice<1>
386   %6 = fir.array_load %arr0(%4) [%5] : (!fir.box<!fir.array<10xi32>>, !fir.shape<1>, !fir.slice<1>) -> !fir.array<10xi32>
387   %c1 = arith.constant 1 : index
388   %c0 = arith.constant 0 : index
389   %7 = arith.subi %3, %c1 : index
390   %8 = fir.do_loop %arg0 = %c0 to %7 step %c1 unordered iter_args(%arg1 = %2) -> (!fir.array<10xi32>) {
391     %9 = fir.array_fetch %6, %arg0 : (!fir.array<10xi32>, index) -> i32
392     %10 = fir.array_update %arg1, %9, %arg0 : (!fir.array<10xi32>, i32, index) -> !fir.array<10xi32>
393     fir.result %10 : !fir.array<10xi32>
394   }
395   fir.array_merge_store %2, %8 to %arr0 : !fir.array<10xi32>, !fir.array<10xi32>, !fir.box<!fir.array<10xi32>>
396   return
399 // CHECK-LABEL: func @conversion_with_temporary_boxed_array(
400 // CHECK-SAME:                                              %[[ARR0:.*]]: !fir.box<!fir.array<10xi32>>)
401 // Allocation of temporary array.
402 // CHECK:         %[[TEMP:.*]] = fir.allocmem !fir.array<10xi32>
403 // Copy of original array to temp.
404 // CHECK:         fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
405 // CHECK:           %[[COOR0:.*]] = fir.array_coor %[[ARR0]](%{{.*}}) %{{.*}} : (!fir.box<!fir.array<10xi32>>, !fir.shapeshift<1>, index) -> !fir.ref<i32>
406 // CHECK:           %[[COOR1:.*]] = fir.array_coor %[[TEMP]](%{{.*}}) %{{.*}} : (!fir.heap<!fir.array<10xi32>>, !fir.shapeshift<1>, index) -> !fir.ref<i32>
407 // CHECK:           %[[LOAD0:.*]] = fir.load %[[COOR0]] : !fir.ref<i32>
408 // CHECK:           fir.store %[[LOAD0]] to %[[COOR1]] : !fir.ref<i32>
409 // CHECK:         }
410 // Perform the assignment i = i(10:1:-1) using the temporary array.
411 // CHECK:         %{{.*}} = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} unordered iter_args(%{{.*}} = %{{.*}}) -> (!fir.array<10xi32>) {
412 // CHECK-NOT:       %{{.*}} = fir.array_fetch
413 // CHECK-NOT:       %{{.*}} = fir.update
414 // CHECK:           %[[COOR0:.*]] = fir.array_coor %[[ARR0]](%{{.*}}) [%{{.*}}] %{{.*}} : (!fir.box<!fir.array<10xi32>>, !fir.shape<1>, !fir.slice<1>, index) -> !fir.ref<i32>
415 // CHECK:           %[[LOAD0:.*]] = fir.load %[[COOR0]] : !fir.ref<i32>
416 // CHECK:           %[[COOR1:.*]] = fir.array_coor %[[TEMP]](%{{.*}}) %{{.*}} : (!fir.heap<!fir.array<10xi32>>, !fir.shapeshift<1>, index) -> !fir.ref<i32>
417 // CHECK:           fir.store %[[LOAD0]] to %[[COOR1]] : !fir.ref<i32>
418 // CHECK:           fir.result %{{.*}} : !fir.array<10xi32>
419 // CHECK:         }
420 // Copy the result back to the original array.
421 // CHECK:         fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
422 // CHECK:           %[[COOR0:.*]] = fir.array_coor %[[TEMP]](%{{.*}}) %{{.*}} : (!fir.heap<!fir.array<10xi32>>, !fir.shapeshift<1>, index) -> !fir.ref<i32>
423 // CHECK:           %[[COOR1:.*]] = fir.array_coor %[[ARR0]](%{{.*}}) %{{.*}} : (!fir.box<!fir.array<10xi32>>, !fir.shapeshift<1>, index) -> !fir.ref<i32>
424 // CHECK:           %[[LOAD0:.*]] = fir.load %[[COOR0:.*]] : !fir.ref<i32>
425 // CHECK:           fir.store %[[LOAD0]] to %[[COOR1]] : !fir.ref<i32>
426 // CHECK:         }
427 // Free temporary array.
428 // CHECK:         fir.freemem %[[TEMP]] : !fir.heap<!fir.array<10xi32>>
430 // -----
432 // Test simple fir.array_update with Fortran.offsets attribute.
433 func.func @array_update_conversion(%arr1 : !fir.box<!fir.array<?x?xf32>>, %m: index, %n: index) {
434   %c10 = arith.constant 10 : index
435   %c20 = arith.constant 20 : index
436   %c1 = arith.constant 1 : index
437   %f = arith.constant 2.0 : f32
438   %s = fir.shape %m, %n : (index, index) -> !fir.shape<2>
439   %av1 = fir.array_load %arr1(%s) : (!fir.box<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32>
440   %av2 = fir.array_update %av1, %f, %c1, %c1 {Fortran.offsets} : (!fir.array<?x?xf32>, f32, index, index) -> !fir.array<?x?xf32>
441   return
444 // CHECK-LABEL: func @array_update_conversion
445 // CHECK-NOT:     fir.array_update
446 // CHECK-NOT:     %{{.*}} = arith.addi %{{.*}}, %{{.*}} : index
447 // CHECK:         %[[ARRAY_COOR:.*]] = fir.array_coor{{.*}}-> !fir.ref<f32>
448 // CHECK:         fir.store %{{.*}} to %[[ARRAY_COOR]] : !fir.ref<f32>
450 // -----
452 // Test fir.array_fetch on derived type members in an array of derived types.
453 func.func @array_fetch_derived_type(%0 : !fir.ref<!fir.array<10x!fir.type<_QTu{mt:!fir.type<_QTt{mem:i32}>}>>>) {
454   %1 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QEi"}
455   %c1_i32 = arith.constant 1 : i32
456   %2 = fir.convert %c1_i32 : (i32) -> index
457   %c10_i32 = arith.constant 10 : i32
458   %3 = fir.convert %c10_i32 : (i32) -> index
459   %c1 = arith.constant 1 : index
460   %shape = fir.shape %2 : (index) -> !fir.shape<1>
461   %arr0 = fir.array_load %0(%shape) : (!fir.ref<!fir.array<10x!fir.type<_QTu{mt:!fir.type<_QTt{mem:i32}>}>>>, !fir.shape<1>) -> !fir.array<10x!fir.type<_QTu{mt:!fir.type<_QTt{mem:i32}>}>>
462   %4 = fir.do_loop %arg0 = %2 to %3 step %c1 -> index {
463     %6 = fir.convert %arg0 : (index) -> i32
464     fir.store %6 to %1 : !fir.ref<i32>
465     %c1_i32_0 = arith.constant 1 : i32
466     %7 = fir.load %1 : !fir.ref<i32>
467     %8 = fir.convert %7 : (i32) -> i64
468     %c1_i64 = arith.constant 1 : i64
469     %9 = arith.subi %8, %c1_i64 : i64
470     %11 = fir.field_index mt, !fir.type<_QTu{mt:!fir.type<_QTt{mem:i32}>}>
471     %12 = fir.field_index mem, !fir.type<_QTt{mem:i32}>
472     %idx = fir.convert %9 : (i64) -> index
473     %res = fir.array_fetch %arr0, %idx, %11, %12 : (!fir.array<10x!fir.type<_QTu{mt:!fir.type<_QTt{mem:i32}>}>>, index, !fir.field, !fir.field) -> i32
474     %14 = arith.addi %arg0, %c1 : index
475     fir.result %14 : index
476   }
477   %5 = fir.convert %4 : (index) -> i32
478   fir.store %5 to %1 : !fir.ref<i32>
479   return
482 // CHECK-LABEL: func @array_fetch_derived_type(
483 // CHECK-SAME:                                 %[[ARR0:.*]]: !fir.ref<!fir.array<10x!fir.type<_QTu{mt:!fir.type<_QTt{mem:i32}>}>>>) {
484 // CHECK:         %{{.*}} = fir.do_loop
485 // CHECK:           %[[FIELD_MT:.*]] = fir.field_index mt, !fir.type<_QTu{mt:!fir.type<_QTt{mem:i32}>}>
486 // CHECK:           %[[FIELD_MEM:.*]] = fir.field_index mem, !fir.type<_QTt{mem:i32}>
487 // CHECK-NOT:       %{{.*}} = fir.array_fetch
488 // CHECK:           %[[COOR0:.*]] = fir.array_coor %[[ARR0]](%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<10x!fir.type<_QTu{mt:!fir.type<_QTt{mem:i32}>}>>>, !fir.shape<1>, index) -> !fir.ref<!fir.type<_QTu{mt:!fir.type<_QTt{mem:i32}>}>>
489 // CHECK:           %[[COOR_OF:.*]] = fir.coordinate_of %[[COOR0]], %[[FIELD_MT]], %[[FIELD_MEM]] : (!fir.ref<!fir.type<_QTu{mt:!fir.type<_QTt{mem:i32}>}>>, !fir.field, !fir.field) -> !fir.ref<i32>
490 // CHECK:           %{{.*}} = fir.load %[[COOR_OF]] : !fir.ref<i32>
492 // -----
494 // Test simple fir.array_load/fir.array_update conversion without copy-in/copy-out with a `fir.box`
495 func.func @array_update_conversion(%arr1 : !fir.box<!fir.array<?x?xf32>>, %m: index, %n: index) {
496   %c10 = arith.constant 10 : index
497   %c20 = arith.constant 20 : index
498   %c1 = arith.constant 1 : index
499   %f = arith.constant 2.0 : f32
500   %s = fir.shape %m, %n : (index, index) -> !fir.shape<2>
501   %av1 = fir.array_load %arr1(%s) : (!fir.box<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32>
502   %av2 = fir.array_update %av1, %f, %c1, %c1 : (!fir.array<?x?xf32>, f32, index, index) -> !fir.array<?x?xf32>
503   return
506 // -----
508 // Test array operation with conditional update.
510 func.func @array_operation_with_cond_update(%arg0: !fir.ref<!fir.array<100xf32>>, %cond1: i1) {
511   %c100 = arith.constant 100 : index
512   %c1 = arith.constant 1 : index
513   %c-1 = arith.constant -1 : index
514   %f = arith.constant 2.0 : f32
515   %1 = fir.shape %c100 : (index) -> !fir.shape<1>
516   %2 = fir.array_load %arg0(%1) : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
517   %arg2 = fir.if %cond1 -> !fir.array<100xf32> {
518     fir.result %2 : !fir.array<100xf32>
519   } else {
520     %r = fir.array_update %2, %f, %c1 : (!fir.array<100xf32>, f32, index) -> !fir.array<100xf32>
521     fir.result %r : !fir.array<100xf32>
522   }
523   fir.array_merge_store %2, %arg2 to %arg0 : !fir.array<100xf32>, !fir.array<100xf32>, !fir.ref<!fir.array<100xf32>>
524   return
527 // CHECK-LABEL: func @array_operation_with_cond_update(
528 // CHECK-SAME:                                         %[[ARG0:.*]]: !fir.ref<!fir.array<100xf32>>, %[[COND:.*]]: i1) {
529 // CHECK:         %[[ARRAY_LOAD:.*]] = fir.undefined !fir.array<100xf32>
530 // CHECK:         %[[IF_RES:.*]] = fir.if %[[COND]] -> (!fir.array<100xf32>) {
531 // CHECK:           fir.result %[[ARRAY_LOAD]] : !fir.array<100xf32>
532 // CHECK:         } else {
533 // CHECK:           %[[UPDATE0:.*]] = fir.array_coor %[[ARG0]](%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
534 // CHECK:           fir.store %{{.*}} to %{{.*}} : !fir.ref<f32>
535 // CHECK:           fir.result %[[ARRAY_LOAD]] : !fir.array<100xf32>
536 // CHECK:    }