534 lines · plain
1// Test for the array-value-copy pass2// RUN: fir-opt --split-input-file --array-value-copy %s | FileCheck %s3 4// Test simple fir.array_load/fir.array_fetch conversion to fir.array_coor5func.func @array_fetch_conversion(%arr1 : !fir.ref<!fir.array<?x?xf32>>, %m: index, %n: index) {6 %c10 = arith.constant 10 : index7 %c20 = arith.constant 20 : index8 %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) -> f3211 return12}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 %{{.*}}, %{{.*}} : index21// CHECK: %[[VAL_1:.*]] = arith.addi %{{.*}}, %{{.*}} : index22// CHECK-NOT: fir.array_load23// CHECK-NOT: fir.array_fetch24// 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-out30func.func @array_update_conversion(%arr1 : !fir.box<!fir.array<?x?xf32>>, %m: index, %n: index) {31 %c10 = arith.constant 10 : index32 %c20 = arith.constant 20 : index33 %c1 = arith.constant 1 : index34 %f = arith.constant 2.0 : f3235 %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 return39}40 41// CHECK-LABEL: func @array_update_conversion42// CHECK-NOT: fir.array_load43// CHECK-NOT: fir.array_update44// CHECK: %{{.*}} = arith.addi %{{.*}}, %{{.*}} : index45// CHECK: %{{.*}} = arith.addi %{{.*}}, %{{.*}} : index46// 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-out52func.func @array_update_conversion(%arr1 : !fir.box<!fir.array<?x?xf32>>, %m: index, %n: index, %cond: i1) {53 %c10 = arith.constant 10 : index54 %c20 = arith.constant 20 : index55 %c1 = arith.constant 1 : index56 %f = arith.constant 2.0 : f3257 %g = arith.constant 4.0 : f3258 %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 return66}67 68// -----69 70// Test fir.array_load/fir.array_fetch/fir.array_update conversion with71// an introduced copy-in/copy-out.72// 73// This test corresponds to a simplified FIR version of the following Fortran74// code.75// ```76// integer :: i(10)77// i = i(10:1:-1)78// end79// ```80 81func.func @conversion_with_temporary(%arr0 : !fir.ref<!fir.array<10xi32>>) {82 %c10 = arith.constant 10 : index83 %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 : i6486 %3 = fir.convert %c10_i64 : (i64) -> index87 %c1_i64 = arith.constant 1 : i6488 %c-1_i64 = arith.constant -1 : i6489 %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 : index93 %c0 = arith.constant 0 : index94 %7 = arith.subi %3, %c1 : index95 %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) -> i3297 %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 return102}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_fetch118// CHECK-NOT: %{{.*}} = fir.array_update119// 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 with138// 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 : index142 %c5 = arith.constant 5 : index143 %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 : i64146 %3 = fir.convert %c10_i64 : (i64) -> index147 %c5_i64 = arith.constant 5 : i64148 %4 = fir.convert %c5_i64 : (i64) -> index149 %c1 = arith.constant 1 : index150 %c10_i64_0 = arith.constant 10 : i64151 %c1_i64 = arith.constant 1 : i64152 %c-1_i64 = arith.constant -1 : i64153 %5 = arith.addi %c1, %c5 : index154 %6 = arith.subi %5, %c1 : index155 %c1_i64_1 = arith.constant 1 : i64156 %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 : index160 %c0 = arith.constant 0 : index161 %10 = arith.subi %3, %c1_2 : index162 %11 = arith.subi %4, %c1_2 : index163 %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) -> i32166 %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 return173}174 175// CHECK-LABEL: func @conversion_with_temporary_multidim(176// CHECK-SAME: %[[ARR0:.*]]: !fir.ref<!fir.array<10x5xi32>>) {177// CHECK: %[[CST10:.*]] = arith.constant 10 : index178// CHECK: %[[CST5:.*]] = arith.constant 5 : index179// CHECK: %[[TEMP:.*]] = fir.allocmem !fir.array<10x5xi32>180// CHECK: %[[IDX5:.*]] = fir.convert %[[CST5]] : (index) -> index181// CHECK: %[[UB5:.*]] = arith.subi %[[IDX5]], %{{.*}} : index182// CHECK: fir.do_loop %[[INDUC0:.*]] = %{{.*}} to %[[UB5]] step %{{.*}} {183// CHECK: %[[IDX10:.*]] = fir.convert %[[CST10]] : (index) -> index184// CHECK: %[[UB10:.*]] = arith.subi %[[IDX10]], %{{.*}} : index185// CHECK: fir.do_loop %[[INDUC1:.*]] = %{{.*}} to %[[UB10]] step %{{.*}} {186// CHECK: %[[IDX1:.*]] = arith.addi %[[INDUC1]], %{{.*}} : index187// CHECK: %[[IDX2:.*]] = arith.addi %[[INDUC0]], %{{.*}} : index188// 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]], %{{.*}} : index195// CHECK: %[[IDX2:.*]] = arith.addi %[[INDUC0]], %{{.*}} : index196// CHECK-NOT: %{{.*}} = fir.array_fetch197// CHECK-NOT: %{{.*}} = fir.array_update198// 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) -> index203// CHECK: %[[UB5:.*]] = arith.subi %[[IDX5]], %{{.*}} : index204// CHECK: fir.do_loop %[[INDUC0:.*]] = %{{.*}} to %[[UB5]] step %{{.*}} {205// CHECK: %[[IDX10:.*]] = fir.convert %[[CST10]] : (index) -> index206// CHECK: %[[UB10:.*]] = arith.subi %[[IDX10]], %{{.*}} : index207// CHECK: fir.do_loop %[[INDUC1:.*]] = %{{.*}} to %[[UB10]] step %{{.*}} {208// CHECK: %[[IDX1:.*]] = arith.addi %[[INDUC1]], %{{.*}} : index209// 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 : index221 %c99 = arith.constant 99 : index222 %c1 = arith.constant 1 : index223 %c0 = arith.constant 0 : index224 %0 = fir.alloca f32225 %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) -> f32230 %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 return237}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 f32245// CHECK-COUNT-1: %{{.*}} = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} unordered iter_args(%{{.*}} = %{{.*}}) -> (!fir.array<100xf32>) {246// CHECK-NOT: %{{.*}} = fir.array_fetch247// CHECK-NOT: %{{.*}} = fir.array_modify248// 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 : index260 %c99 = arith.constant 99 : index261 %c1 = arith.constant 1 : index262 %c-1 = arith.constant -1 : index263 %c0 = arith.constant 0 : index264 %0 = fir.alloca f32265 %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) -> f32271 %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 return278}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 f32285// 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_fetch297// CHECK-NOT: %{{.*}} = fir.array_modify298// 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: return314// CHECK: }315 316// -----317 318// Test array of types with no overlap319func.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 : i32323 %2 = fir.convert %c1_i32 : (i32) -> index324 %c10_i32 = arith.constant 10 : i32325 %3 = fir.convert %c10_i32 : (i32) -> index326 %c1 = arith.constant 1 : index327 %4 = fir.do_loop %arg0 = %2 to %3 step %c1 -> index {328 %6 = fir.convert %arg0 : (index) -> i32329 fir.store %6 to %0 : !fir.ref<i32>330 %c1_0 = arith.constant 1 : index331 %7 = fir.load %0 : !fir.ref<i32>332 %8 = fir.convert %7 : (i32) -> i64333 %c1_i64 = arith.constant 1 : i64334 %9 = arith.subi %8, %c1_i64 : i64335 %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 %12 = fir.coordinate_of %10, i : (!fir.ref<!fir.type<_QTd{i:!fir.array<10xi32>}>>) -> !fir.ref<!fir.array<10xi32>>337 %c10 = arith.constant 10 : index338 %13 = arith.addi %c1_0, %c10 : index339 %14 = arith.subi %13, %c1_0 : index340 %c1_i64_1 = arith.constant 1 : i64341 %15 = fir.shape %c10 : (index) -> !fir.shape<1>342 %16 = fir.slice %c1_0, %14, %c1_i64_1 : (index, index, i64) -> !fir.slice<1>343 %17 = fir.array_load %12(%15) [%16] : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.slice<1>) -> !fir.array<10xi32>344 %c10_i64 = arith.constant 10 : i64345 %18 = fir.convert %c10_i64 : (i64) -> index346 %c0_i32 = arith.constant 0 : i32347 %c1_2 = arith.constant 1 : index348 %c0 = arith.constant 0 : index349 %19 = arith.subi %18, %c1_2 : index350 %20 = fir.do_loop %arg1 = %c0 to %19 step %c1_2 unordered iter_args(%arg2 = %17) -> (!fir.array<10xi32>) {351 %22 = fir.array_update %arg2, %c0_i32, %arg1 : (!fir.array<10xi32>, i32, index) -> !fir.array<10xi32>352 fir.result %22 : !fir.array<10xi32>353 }354 fir.array_merge_store %17, %20 to %12[%16] : !fir.array<10xi32>, !fir.array<10xi32>, !fir.ref<!fir.array<10xi32>>, !fir.slice<1>355 %21 = arith.addi %arg0, %c1 : index356 fir.result %21 : index357 }358 %5 = fir.convert %4 : (index) -> i32359 fir.store %5 to %0 : !fir.ref<i32>360 return361}362 363// CHECK-LABEL: func @array_of_types() {364// CHECK: %{{.*}} = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} -> index {365// CHECK: %{{.*}} = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} unordered iter_args(%{{.*}} = %{{.*}}) -> (!fir.array<10xi32>) {366// CHECK-NOT: %{{.*}} = fir.array_update367// CHECK: %[[COOR0:.*]] = fir.array_coor %{{.*}}(%{{.*}}) [%{{.*}}] %{{.*}} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.slice<1>, index) -> !fir.ref<i32>368// CHECK: fir.store %{{.*}} to %[[COOR0]] : !fir.ref<i32>369// CHECK-NOT: fir.array_merge_store370 371// -----372 373// Test fir.array_load/boxed array374func.func @conversion_with_temporary_boxed_array(%arr0 : !fir.box<!fir.array<10xi32>>) {375 %c10 = arith.constant 10 : index376 %1:3 = fir.box_dims %arr0, %c10 : (!fir.box<!fir.array<10xi32>>, index) -> (index, index, index)377 %shift = fir.shift %1#0 : (index) -> !fir.shift<1>378 %2 = fir.array_load %arr0(%shift) : (!fir.box<!fir.array<10xi32>>, !fir.shift<1>) -> !fir.array<10xi32>379 %c10_i64 = arith.constant 10 : i64380 %3 = fir.convert %c10_i64 : (i64) -> index381 %c1_i64 = arith.constant 1 : i64382 %c-1_i64 = arith.constant -1 : i64383 %4 = fir.shape %c10 : (index) -> !fir.shape<1>384 %5 = fir.slice %c10_i64, %c1_i64, %c-1_i64 : (i64, i64, i64) -> !fir.slice<1>385 %6 = fir.array_load %arr0(%4) [%5] : (!fir.box<!fir.array<10xi32>>, !fir.shape<1>, !fir.slice<1>) -> !fir.array<10xi32>386 %c1 = arith.constant 1 : index387 %c0 = arith.constant 0 : index388 %7 = arith.subi %3, %c1 : index389 %8 = fir.do_loop %arg0 = %c0 to %7 step %c1 unordered iter_args(%arg1 = %2) -> (!fir.array<10xi32>) {390 %9 = fir.array_fetch %6, %arg0 : (!fir.array<10xi32>, index) -> i32391 %10 = fir.array_update %arg1, %9, %arg0 : (!fir.array<10xi32>, i32, index) -> !fir.array<10xi32>392 fir.result %10 : !fir.array<10xi32>393 }394 fir.array_merge_store %2, %8 to %arr0 : !fir.array<10xi32>, !fir.array<10xi32>, !fir.box<!fir.array<10xi32>>395 return396}397 398// CHECK-LABEL: func @conversion_with_temporary_boxed_array(399// CHECK-SAME: %[[ARR0:.*]]: !fir.box<!fir.array<10xi32>>)400// Allocation of temporary array.401// CHECK: %[[TEMP:.*]] = fir.allocmem !fir.array<10xi32>402// Copy of original array to temp.403// CHECK: fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {404// CHECK: %[[COOR0:.*]] = fir.array_coor %[[ARR0]](%{{.*}}) %{{.*}} : (!fir.box<!fir.array<10xi32>>, !fir.shapeshift<1>, index) -> !fir.ref<i32>405// CHECK: %[[COOR1:.*]] = fir.array_coor %[[TEMP]](%{{.*}}) %{{.*}} : (!fir.heap<!fir.array<10xi32>>, !fir.shapeshift<1>, index) -> !fir.ref<i32>406// CHECK: %[[LOAD0:.*]] = fir.load %[[COOR0]] : !fir.ref<i32>407// CHECK: fir.store %[[LOAD0]] to %[[COOR1]] : !fir.ref<i32>408// CHECK: }409// Perform the assignment i = i(10:1:-1) using the temporary array.410// CHECK: %{{.*}} = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} unordered iter_args(%{{.*}} = %{{.*}}) -> (!fir.array<10xi32>) {411// CHECK-NOT: %{{.*}} = fir.array_fetch412// CHECK-NOT: %{{.*}} = fir.update413// CHECK: %[[COOR0:.*]] = fir.array_coor %[[ARR0]](%{{.*}}) [%{{.*}}] %{{.*}} : (!fir.box<!fir.array<10xi32>>, !fir.shape<1>, !fir.slice<1>, index) -> !fir.ref<i32>414// CHECK: %[[LOAD0:.*]] = fir.load %[[COOR0]] : !fir.ref<i32>415// CHECK: %[[COOR1:.*]] = fir.array_coor %[[TEMP]](%{{.*}}) %{{.*}} : (!fir.heap<!fir.array<10xi32>>, !fir.shapeshift<1>, index) -> !fir.ref<i32>416// CHECK: fir.store %[[LOAD0]] to %[[COOR1]] : !fir.ref<i32>417// CHECK: fir.result %{{.*}} : !fir.array<10xi32>418// CHECK: }419// Copy the result back to the original array.420// CHECK: fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {421// CHECK: %[[COOR0:.*]] = fir.array_coor %[[TEMP]](%{{.*}}) %{{.*}} : (!fir.heap<!fir.array<10xi32>>, !fir.shapeshift<1>, index) -> !fir.ref<i32>422// CHECK: %[[COOR1:.*]] = fir.array_coor %[[ARR0]](%{{.*}}) %{{.*}} : (!fir.box<!fir.array<10xi32>>, !fir.shapeshift<1>, index) -> !fir.ref<i32>423// CHECK: %[[LOAD0:.*]] = fir.load %[[COOR0:.*]] : !fir.ref<i32>424// CHECK: fir.store %[[LOAD0]] to %[[COOR1]] : !fir.ref<i32>425// CHECK: }426// Free temporary array.427// CHECK: fir.freemem %[[TEMP]] : !fir.heap<!fir.array<10xi32>>428 429// -----430 431// Test simple fir.array_update with Fortran.offsets attribute.432func.func @array_update_conversion(%arr1 : !fir.box<!fir.array<?x?xf32>>, %m: index, %n: index) {433 %c10 = arith.constant 10 : index434 %c20 = arith.constant 20 : index435 %c1 = arith.constant 1 : index436 %f = arith.constant 2.0 : f32437 %s = fir.shape %m, %n : (index, index) -> !fir.shape<2>438 %av1 = fir.array_load %arr1(%s) : (!fir.box<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32>439 %av2 = fir.array_update %av1, %f, %c1, %c1 {Fortran.offsets} : (!fir.array<?x?xf32>, f32, index, index) -> !fir.array<?x?xf32>440 return441}442 443// CHECK-LABEL: func @array_update_conversion444// CHECK-NOT: fir.array_update445// CHECK-NOT: %{{.*}} = arith.addi %{{.*}}, %{{.*}} : index446// CHECK: %[[ARRAY_COOR:.*]] = fir.array_coor{{.*}}-> !fir.ref<f32>447// CHECK: fir.store %{{.*}} to %[[ARRAY_COOR]] : !fir.ref<f32>448 449// -----450 451// Test fir.array_fetch on derived type members in an array of derived types.452func.func @array_fetch_derived_type(%0 : !fir.ref<!fir.array<10x!fir.type<_QTu{mt:!fir.type<_QTt{mem:i32}>}>>>) {453 %1 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QEi"}454 %c1_i32 = arith.constant 1 : i32455 %2 = fir.convert %c1_i32 : (i32) -> index456 %c10_i32 = arith.constant 10 : i32457 %3 = fir.convert %c10_i32 : (i32) -> index458 %c1 = arith.constant 1 : index459 %shape = fir.shape %2 : (index) -> !fir.shape<1>460 %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}>}>>461 %4 = fir.do_loop %arg0 = %2 to %3 step %c1 -> index {462 %6 = fir.convert %arg0 : (index) -> i32463 fir.store %6 to %1 : !fir.ref<i32>464 %c1_i32_0 = arith.constant 1 : i32465 %7 = fir.load %1 : !fir.ref<i32>466 %8 = fir.convert %7 : (i32) -> i64467 %c1_i64 = arith.constant 1 : i64468 %9 = arith.subi %8, %c1_i64 : i64469 %11 = fir.field_index mt, !fir.type<_QTu{mt:!fir.type<_QTt{mem:i32}>}>470 %12 = fir.field_index mem, !fir.type<_QTt{mem:i32}>471 %idx = fir.convert %9 : (i64) -> index472 %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) -> i32473 %14 = arith.addi %arg0, %c1 : index474 fir.result %14 : index475 }476 %5 = fir.convert %4 : (index) -> i32477 fir.store %5 to %1 : !fir.ref<i32>478 return479}480 481// CHECK-LABEL: func @array_fetch_derived_type(482// CHECK-SAME: %[[ARR0:.*]]: !fir.ref<!fir.array<10x!fir.type<_QTu{mt:!fir.type<_QTt{mem:i32}>}>>>) {483// CHECK: %{{.*}} = fir.do_loop484// CHECK-NOT: %{{.*}} = fir.array_fetch485// 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}>}>>486// CHECK: %[[COOR_OF:.*]] = fir.coordinate_of %[[COOR0]], mt, mem : (!fir.ref<!fir.type<_QTu{mt:!fir.type<_QTt{mem:i32}>}>>) -> !fir.ref<i32>487// CHECK: %{{.*}} = fir.load %[[COOR_OF]] : !fir.ref<i32>488 489// -----490 491// Test simple fir.array_load/fir.array_update conversion without copy-in/copy-out with a `fir.box`492func.func @array_update_conversion(%arr1 : !fir.box<!fir.array<?x?xf32>>, %m: index, %n: index) {493 %c10 = arith.constant 10 : index494 %c20 = arith.constant 20 : index495 %c1 = arith.constant 1 : index496 %f = arith.constant 2.0 : f32497 %s = fir.shape %m, %n : (index, index) -> !fir.shape<2>498 %av1 = fir.array_load %arr1(%s) : (!fir.box<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32>499 %av2 = fir.array_update %av1, %f, %c1, %c1 : (!fir.array<?x?xf32>, f32, index, index) -> !fir.array<?x?xf32>500 return501}502 503// -----504 505// Test array operation with conditional update.506 507func.func @array_operation_with_cond_update(%arg0: !fir.ref<!fir.array<100xf32>>, %cond1: i1) {508 %c100 = arith.constant 100 : index509 %c1 = arith.constant 1 : index510 %c-1 = arith.constant -1 : index511 %f = arith.constant 2.0 : f32512 %1 = fir.shape %c100 : (index) -> !fir.shape<1>513 %2 = fir.array_load %arg0(%1) : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>514 %arg2 = fir.if %cond1 -> !fir.array<100xf32> {515 fir.result %2 : !fir.array<100xf32>516 } else {517 %r = fir.array_update %2, %f, %c1 : (!fir.array<100xf32>, f32, index) -> !fir.array<100xf32>518 fir.result %r : !fir.array<100xf32>519 }520 fir.array_merge_store %2, %arg2 to %arg0 : !fir.array<100xf32>, !fir.array<100xf32>, !fir.ref<!fir.array<100xf32>>521 return522}523 524// CHECK-LABEL: func @array_operation_with_cond_update(525// CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<100xf32>>, %[[COND:.*]]: i1) {526// CHECK: %[[ARRAY_LOAD:.*]] = fir.undefined !fir.array<100xf32>527// CHECK: %[[IF_RES:.*]] = fir.if %[[COND]] -> (!fir.array<100xf32>) {528// CHECK: fir.result %[[ARRAY_LOAD]] : !fir.array<100xf32>529// CHECK: } else {530// CHECK: %[[UPDATE0:.*]] = fir.array_coor %[[ARG0]](%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>531// CHECK: fir.store %{{.*}} to %{{.*}} : !fir.ref<f32>532// CHECK: fir.result %[[ARRAY_LOAD]] : !fir.array<100xf32>533// CHECK: }534