1// Test for the array-value-copy pass 2// RUN: fir-opt --split-input-file --array-value-copy %s | FileCheck %s 3 4// Test simple fir.array_load/fir.array_fetch conversion to fir.array_coor 5func.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 12} 13 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> 26 27// ----- 28 29// Test simple fir.array_load/fir.array_update conversion without copy-in/copy-out 30func.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 39} 40 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> 48 49// ----- 50 51// Test simple fir.array_load/fir.array_update conversion without copy-in/copy-out 52func.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 66} 67 68// ----- 69 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// ``` 80 81func.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 102} 103 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>> 134 135// ----- 136 137// Test fir.array_load/fir.array_fetch/fir.array_update conversion with 138// an introduced copy-in/copy-out on a multidimensional array. 139 140func.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 173} 174 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>> 215 216// ----- 217 218// Test fir.array_modify conversion with no overlap. 219func.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 237} 238 239func.func private @user_defined_assignment(!fir.ref<f32>, !fir.ref<f32>) 240 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>) -> () 253 254// ----- 255 256// Test fir.array_modify conversion with an overlap. 257// Test user_defined_assignment(arg0(:), arg0(100:1:-1)) 258func.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 278} 279 280func.func private @user_defined_assignment(!fir.ref<f32>, !fir.ref<f32>) 281 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: } 315 316// ----- 317 318// Test array of types with no overlap 319func.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 362} 363 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 371 372// ----- 373 374// Test fir.array_load/boxed array 375func.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 397} 398 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>> 429 430// ----- 431 432// Test simple fir.array_update with Fortran.offsets attribute. 433func.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 442} 443 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> 449 450// ----- 451 452// Test fir.array_fetch on derived type members in an array of derived types. 453func.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 480} 481 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> 491 492// ----- 493 494// Test simple fir.array_load/fir.array_update conversion without copy-in/copy-out with a `fir.box` 495func.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 504} 505 506// ----- 507 508// Test array operation with conditional update. 509 510func.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 525} 526 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: } 537