291 lines · plain
1// Test array-copy-value pass (copy elision) with array assignment2// involving Fortran pointers. Focus in only on wether copy ellision3// is made or not.4// RUN: fir-opt %s --array-value-copy -split-input-file | FileCheck --check-prefixes=ALL,NOOPT %s5// RUN: fir-opt %s --array-value-copy="optimize-conflicts=true" -split-input-file | FileCheck --check-prefixes=ALL,OPT %s6 7// Test `pointer(:) = array(:)`8// ALL-LABEL: func @maybe_overlap9// ALL: %[[ALLOC:.*]] = fir.allocmem !fir.array<100xf32>10// ALL: fir.do_loop11// ALL: fir.do_loop12// ALL: fir.do_loop13// ALL: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<100xf32>>14func.func @maybe_overlap(%arg0: !fir.ptr<!fir.array<100xf32>>, %arg1 : !fir.ref<!fir.array<100xf32>> {fir.target}) {15 %c100 = arith.constant 100 : index16 %c99 = arith.constant 99 : index17 %c1 = arith.constant 1 : index18 %c0 = arith.constant 0 : index19 %0 = fir.alloca f3220 %1 = fir.shape %c100 : (index) -> !fir.shape<1>21 %2 = fir.array_load %arg0(%1) : (!fir.ptr<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>22 %3 = fir.array_load %arg1(%1) : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>23 %4 = fir.do_loop %arg2 = %c0 to %c99 step %c1 unordered iter_args(%arg3 = %2) -> (!fir.array<100xf32>) {24 %5 = fir.array_fetch %3, %arg2 : (!fir.array<100xf32>, index) -> f3225 %6 = fir.array_update %arg3, %5, %arg2 : (!fir.array<100xf32>, f32, index) -> !fir.array<100xf32>26 fir.result %6 : !fir.array<100xf32>27 }28 fir.array_merge_store %2, %4 to %arg0 : !fir.array<100xf32>, !fir.array<100xf32>, !fir.ptr<!fir.array<100xf32>>29 return30}31 32// -----33 34// Test `pointer(:) = array(:)`35// ALL-LABEL: func @no_overlap136// OPT-NOT: fir.allocmem37// NOOPT: %[[ALLOC:.*]] = fir.allocmem !fir.array<100xf32>38// NOOPT: fir.do_loop39// NOOPT: fir.do_loop40// NOOPT: fir.do_loop41// NOOPT: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<100xf32>>42func.func @no_overlap1(%arg0: !fir.ptr<!fir.array<100xf32>>, %arg1 : !fir.ref<!fir.array<100xf32>>) {43 %c100 = arith.constant 100 : index44 %c99 = arith.constant 99 : index45 %c1 = arith.constant 1 : index46 %c0 = arith.constant 0 : index47 %0 = fir.alloca f3248 %1 = fir.shape %c100 : (index) -> !fir.shape<1>49 %2 = fir.array_load %arg0(%1) : (!fir.ptr<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>50 %3 = fir.array_load %arg1(%1) : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>51 %4 = fir.do_loop %arg2 = %c0 to %c99 step %c1 unordered iter_args(%arg3 = %2) -> (!fir.array<100xf32>) {52 %5 = fir.array_fetch %3, %arg2 : (!fir.array<100xf32>, index) -> f3253 %6 = fir.array_update %arg3, %5, %arg2 : (!fir.array<100xf32>, f32, index) -> !fir.array<100xf32>54 fir.result %6 : !fir.array<100xf32>55 }56 fir.array_merge_store %2, %4 to %arg0 : !fir.array<100xf32>, !fir.array<100xf32>, !fir.ptr<!fir.array<100xf32>>57 return58}59 60// -----61 62// Test `pointer(:) = pointer(:)`63// ALL-LABEL: func @no_overlap64// ALL-NOT: fir.allocmem65// ALL: fir.do_loop66// ALL: fir.array_coor67// ALL: fir.array_coor68// ALL: fir.store69func.func @no_overlap(%arg0: !fir.ptr<!fir.array<100xf32>>, %arg1: !fir.ref<!fir.array<100xf32>>) {70 %c100 = arith.constant 100 : index71 %c99 = arith.constant 99 : index72 %c1 = arith.constant 1 : index73 %c0 = arith.constant 0 : index74 %0 = fir.alloca f3275 %1 = fir.shape %c100 : (index) -> !fir.shape<1>76 %2 = fir.array_load %arg0(%1) : (!fir.ptr<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>77 %3 = fir.do_loop %arg2 = %c0 to %c99 step %c1 unordered iter_args(%arg3 = %2) -> (!fir.array<100xf32>) {78 %4 = fir.array_fetch %2, %arg2 : (!fir.array<100xf32>, index) -> f3279 %5 = fir.array_update %arg3, %4, %arg2 : (!fir.array<100xf32>, f32, index) -> !fir.array<100xf32>80 fir.result %5 : !fir.array<100xf32>81 }82 fir.array_merge_store %2, %3 to %arg0 : !fir.array<100xf32>, !fir.array<100xf32>, !fir.ptr<!fir.array<100xf32>>83 return84}85 86// -----87 88// Test `array(:) = pointer(:)`89// ALL-LABEL: func @maybe_overlap_290// ALL: %[[ALLOC:.*]] = fir.allocmem !fir.array<100xf32>91// ALL: fir.do_loop92// ALL: fir.do_loop93// ALL: fir.do_loop94// ALL: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<100xf32>>95func.func @maybe_overlap_2(%arg0: !fir.ptr<!fir.array<100xf32>>, %arg1: !fir.ref<!fir.array<100xf32>> {fir.target}) {96 %c100 = arith.constant 100 : index97 %c99 = arith.constant 99 : index98 %c1 = arith.constant 1 : index99 %c0 = arith.constant 0 : index100 %0 = fir.alloca f32101 %1 = fir.shape %c100 : (index) -> !fir.shape<1>102 %2 = fir.array_load %arg0(%1) : (!fir.ptr<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>103 %3 = fir.array_load %arg1(%1) : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>104 %4 = fir.do_loop %arg2 = %c0 to %c99 step %c1 unordered iter_args(%arg3 = %3) -> (!fir.array<100xf32>) {105 %5 = fir.array_fetch %2, %arg2 : (!fir.array<100xf32>, index) -> f32106 %6 = fir.array_update %arg3, %5, %arg2 : (!fir.array<100xf32>, f32, index) -> !fir.array<100xf32>107 fir.result %6 : !fir.array<100xf32>108 }109 fir.array_merge_store %3, %4 to %arg1 : !fir.array<100xf32>, !fir.array<100xf32>, !fir.ref<!fir.array<100xf32>>110 return111}112 113// -----114 115// Test `array(:) = pointer(:)`116// ALL-LABEL: func @no_overlap_2117// OPT-NOT: fir.allocmem118// NOOPT: %[[ALLOC:.*]] = fir.allocmem !fir.array<100xf32>119// NOOPT: fir.do_loop120// NOOPT: fir.do_loop121// NOOPT: fir.do_loop122// NOOPT: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<100xf32>>123func.func @no_overlap_2(%arg0: !fir.ptr<!fir.array<100xf32>>, %arg1: !fir.ref<!fir.array<100xf32>>) {124 %c100 = arith.constant 100 : index125 %c99 = arith.constant 99 : index126 %c1 = arith.constant 1 : index127 %c0 = arith.constant 0 : index128 %0 = fir.alloca f32129 %1 = fir.shape %c100 : (index) -> !fir.shape<1>130 %2 = fir.array_load %arg0(%1) : (!fir.ptr<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>131 %3 = fir.array_load %arg1(%1) : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>132 %4 = fir.do_loop %arg2 = %c0 to %c99 step %c1 unordered iter_args(%arg3 = %3) -> (!fir.array<100xf32>) {133 %5 = fir.array_fetch %2, %arg2 : (!fir.array<100xf32>, index) -> f32134 %6 = fir.array_update %arg3, %5, %arg2 : (!fir.array<100xf32>, f32, index) -> !fir.array<100xf32>135 fir.result %6 : !fir.array<100xf32>136 }137 fir.array_merge_store %3, %4 to %arg1 : !fir.array<100xf32>, !fir.array<100xf32>, !fir.ref<!fir.array<100xf32>>138 return139}140 141// -----142 143// Test `pointer1(:) = pointer2(:)`144// ALL-LABEL: func @maybe_overlap_3145// ALL: %[[ALLOC:.*]] = fir.allocmem !fir.array<100xf32>146// ALL: fir.do_loop147// ALL: fir.do_loop148// ALL: fir.do_loop149// ALL: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<100xf32>>150func.func @maybe_overlap_3(%arg0: !fir.ptr<!fir.array<100xf32>>, %arg1: !fir.ptr<!fir.array<100xf32>>) {151 %c100 = arith.constant 100 : index152 %c99 = arith.constant 99 : index153 %c1 = arith.constant 1 : index154 %c0 = arith.constant 0 : index155 %0 = fir.alloca f32156 %1 = fir.shape %c100 : (index) -> !fir.shape<1>157 %2 = fir.array_load %arg0(%1) : (!fir.ptr<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>158 %3 = fir.array_load %arg1(%1) : (!fir.ptr<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>159 %4 = fir.do_loop %arg2 = %c0 to %c99 step %c1 unordered iter_args(%arg3 = %3) -> (!fir.array<100xf32>) {160 %5 = fir.array_fetch %2, %arg2 : (!fir.array<100xf32>, index) -> f32161 %6 = fir.array_update %arg3, %5, %arg2 : (!fir.array<100xf32>, f32, index) -> !fir.array<100xf32>162 fir.result %6 : !fir.array<100xf32>163 }164 fir.array_merge_store %3, %4 to %arg1 : !fir.array<100xf32>, !fir.array<100xf32>, !fir.ptr<!fir.array<100xf32>>165 return166}167 168// -----169 170// Test derived_target(:)%i = integer_pointer(:)171// The integer pointer may be aliasing the derived target component.172// ALL-LABEL: func @derived_whose_component_may_be_aliased173// ALL: %[[ALLOC:.*]] = fir.allocmem !fir.array<4x!fir.type<some_type{i:i32}>>174// ALL-COUNT-3: fir.do_loop175// ALL: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<4x!fir.type<some_type{i:i32}>>>176func.func @derived_whose_component_may_be_aliased(%arg0: !fir.box<!fir.array<4x!fir.type<some_type{i:i32}>>> {fir.target}, %arg1: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) {177 %c4 = arith.constant 4 : index178 %0 = fir.field_index i, !fir.type<some_type{i:i32}>179 %c1 = arith.constant 1 : index180 %1 = fir.slice %c1, %c4, %c1 path %0 : (index, index, index, !fir.field) -> !fir.slice<1>181 %2 = fir.array_load %arg0 [%1] : (!fir.box<!fir.array<4x!fir.type<some_type{i:i32}>>>, !fir.slice<1>) -> !fir.array<4xi32>182 %3 = fir.load %arg1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>183 %c0 = arith.constant 0 : index184 %4:3 = fir.box_dims %3, %c0 : (!fir.box<!fir.ptr<!fir.array<?xi32>>>, index) -> (index, index, index)185 %5 = fir.shift %4#0 : (index) -> !fir.shift<1>186 %6 = fir.array_load %3(%5) : (!fir.box<!fir.ptr<!fir.array<?xi32>>>, !fir.shift<1>) -> !fir.array<?xi32>187 %7 = arith.subi %c4, %c1 : index188 %8 = fir.do_loop %arg2 = %c0 to %7 step %c1 unordered iter_args(%arg3 = %2) -> (!fir.array<4xi32>) {189 %9 = fir.array_fetch %6, %arg2 : (!fir.array<?xi32>, index) -> i32190 %10 = fir.array_update %arg3, %9, %arg2 : (!fir.array<4xi32>, i32, index) -> !fir.array<4xi32>191 fir.result %10 : !fir.array<4xi32>192 }193 fir.array_merge_store %2, %8 to %arg0[%1] : !fir.array<4xi32>, !fir.array<4xi32>, !fir.box<!fir.array<4x!fir.type<some_type{i:i32}>>>, !fir.slice<1>194 return195}196 197// -----198 199// Test real_target = complex_target(:)%re200// The real pointer may be aliasing the complex real part.201// ALL-LABEL: func @complex_real_aliasing202// ALL: %[[ALLOC:.*]] = fir.allocmem !fir.array<?xf32>203// ALL-COUNT-3: fir.do_loop204// ALL: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<?xf32>>205func.func @complex_real_aliasing(%arg0: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, %arg1: !fir.ref<!fir.array<4xcomplex<f32>>> {fir.target}) {206 %c4 = arith.constant 4 : index207 %0 = fir.load %arg0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>208 %c0 = arith.constant 0 : index209 %1:3 = fir.box_dims %0, %c0 : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, index) -> (index, index, index)210 %2 = fir.shift %1#0 : (index) -> !fir.shift<1>211 %3 = fir.array_load %0(%2) : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, !fir.shift<1>) -> !fir.array<?xf32>212 %c0_i32 = arith.constant 0 : i32213 %4 = fir.shape %c4 : (index) -> !fir.shape<1>214 %c1 = arith.constant 1 : index215 %5 = fir.slice %c1, %c4, %c1 path %c0_i32 : (index, index, index, i32) -> !fir.slice<1>216 %6 = fir.array_load %arg1(%4) [%5] : (!fir.ref<!fir.array<4xcomplex<f32>>>, !fir.shape<1>, !fir.slice<1>) -> !fir.array<4xf32>217 %7 = arith.subi %c4, %c1 : index218 %8 = fir.do_loop %arg2 = %c0 to %7 step %c1 unordered iter_args(%arg3 = %3) -> (!fir.array<?xf32>) {219 %9 = fir.array_fetch %6, %arg2 : (!fir.array<4xf32>, index) -> f32220 %10 = fir.array_update %arg3, %9, %arg2 : (!fir.array<?xf32>, f32, index) -> !fir.array<?xf32>221 fir.result %10 : !fir.array<?xf32>222 }223 fir.array_merge_store %3, %8 to %0 : !fir.array<?xf32>, !fir.array<?xf32>, !fir.box<!fir.ptr<!fir.array<?xf32>>>224 return225}226 227// -----228 229// Test `array(:) = pointer(:)`230// ALL-LABEL: func @maybe_overlap_3231// ALL: %[[ALLOC:.*]] = fir.allocmem !fir.array<100xf32>232// ALL: fir.do_loop233// ALL: fir.do_loop234// ALL: fir.do_loop235// ALL: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<100xf32>>236fir.global @_QMdataEglob target : !fir.array<100xf32> {237 %0 = fir.undefined !fir.array<100xf32>238 fir.has_value %0 : !fir.array<100xf32>239}240 241func.func @maybe_overlap_3(%arg0: !fir.ptr<!fir.array<100xf32>>, %arg1: !fir.ref<!fir.array<100xf32>> {fir.target}) {242 %c100 = arith.constant 100 : index243 %c99 = arith.constant 99 : index244 %c1 = arith.constant 1 : index245 %c0 = arith.constant 0 : index246 %0 = fir.address_of(@_QMdataEglob) : !fir.ref<!fir.array<100xf32>>247 %1 = fir.shape %c100 : (index) -> !fir.shape<1>248 %2 = fir.array_load %arg0(%1) : (!fir.ptr<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>249 %3 = fir.array_load %0(%1) : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>250 %4 = fir.do_loop %arg2 = %c0 to %c99 step %c1 unordered iter_args(%arg3 = %3) -> (!fir.array<100xf32>) {251 %5 = fir.array_fetch %2, %arg2 : (!fir.array<100xf32>, index) -> f32252 %6 = fir.array_update %arg3, %5, %arg2 : (!fir.array<100xf32>, f32, index) -> !fir.array<100xf32>253 fir.result %6 : !fir.array<100xf32>254 }255 fir.array_merge_store %3, %4 to %0 : !fir.array<100xf32>, !fir.array<100xf32>, !fir.ref<!fir.array<100xf32>>256 return257}258 259// -----260 261// Test `array(:) = pointer(:)`262// ALL-LABEL: func @no_overlap_3263// OPT-NOT: fir.allocmem264// NOOPT: %[[ALLOC:.*]] = fir.allocmem !fir.array<100xf32>265// NOOPT: fir.do_loop266// NOOPT: fir.do_loop267// NOOPT: fir.do_loop268// NOOPT: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<100xf32>>269fir.global @_QMdataEglob : !fir.array<100xf32> {270 %0 = fir.undefined !fir.array<100xf32>271 fir.has_value %0 : !fir.array<100xf32>272}273 274func.func @no_overlap_3(%arg0: !fir.ptr<!fir.array<100xf32>>, %arg1: !fir.ref<!fir.array<100xf32>> {fir.target}) {275 %c100 = arith.constant 100 : index276 %c99 = arith.constant 99 : index277 %c1 = arith.constant 1 : index278 %c0 = arith.constant 0 : index279 %0 = fir.address_of(@_QMdataEglob) : !fir.ref<!fir.array<100xf32>>280 %1 = fir.shape %c100 : (index) -> !fir.shape<1>281 %2 = fir.array_load %arg0(%1) : (!fir.ptr<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>282 %3 = fir.array_load %0(%1) : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>283 %4 = fir.do_loop %arg2 = %c0 to %c99 step %c1 unordered iter_args(%arg3 = %3) -> (!fir.array<100xf32>) {284 %5 = fir.array_fetch %2, %arg2 : (!fir.array<100xf32>, index) -> f32285 %6 = fir.array_update %arg3, %5, %arg2 : (!fir.array<100xf32>, f32, index) -> !fir.array<100xf32>286 fir.result %6 : !fir.array<100xf32>287 }288 fir.array_merge_store %3, %4 to %0 : !fir.array<100xf32>, !fir.array<100xf32>, !fir.ref<!fir.array<100xf32>>289 return290}291