1*69825f36SValentin Clement (バレンタイン クレメン)<!--===- docs/FIRArrayOperations.md 2*69825f36SValentin Clement (バレンタイン クレメン) 3*69825f36SValentin Clement (バレンタイン クレメン) Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*69825f36SValentin Clement (バレンタイン クレメン) See https://llvm.org/LICENSE.txt for license information. 5*69825f36SValentin Clement (バレンタイン クレメン) SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*69825f36SValentin Clement (バレンタイン クレメン) 7*69825f36SValentin Clement (バレンタイン クレメン)--> 8*69825f36SValentin Clement (バレンタイン クレメン) 9*69825f36SValentin Clement (バレンタイン クレメン)# Design: FIR Array operations 10*69825f36SValentin Clement (バレンタイン クレメン) 11*69825f36SValentin Clement (バレンタイン クレメン)```eval_rst 12*69825f36SValentin Clement (バレンタイン クレメン).. contents:: 13*69825f36SValentin Clement (バレンタイン クレメン) :local: 14*69825f36SValentin Clement (バレンタイン クレメン)``` 15*69825f36SValentin Clement (バレンタイン クレメン) 16*69825f36SValentin Clement (バレンタイン クレメン)## General 17*69825f36SValentin Clement (バレンタイン クレメン) 18*69825f36SValentin Clement (バレンタイン クレメン)The array operations in FIR model the copy-in/copy-out semantics over Fortran 19*69825f36SValentin Clement (バレンタイン クレメン)statements. 20*69825f36SValentin Clement (バレンタイン クレメン) 21*69825f36SValentin Clement (バレンタイン クレメン)Fortran language semantics sometimes require the compiler to make a temporary 22*69825f36SValentin Clement (バレンタイン クレメン)copy of an array or array slice. Situations where this can occur include: 23*69825f36SValentin Clement (バレンタイン クレメン) 24*69825f36SValentin Clement (バレンタイン クレメン)* Passing a non-contiguous array to a procedure that does not declare it as 25*69825f36SValentin Clement (バレンタイン クレメン) assumed-shape. 26*69825f36SValentin Clement (バレンタイン クレメン)* Array expressions, especially those involving `RESHAPE`, `PACK`, and `MERGE`. 27*69825f36SValentin Clement (バレンタイン クレメン)* Assignments of arrays where the array appears on both the left and right-hand 28*69825f36SValentin Clement (バレンタイン クレメン) sides of the assignment. 29*69825f36SValentin Clement (バレンタイン クレメン)* Assignments of `POINTER` arrays. 30*69825f36SValentin Clement (バレンタイン クレメン) 31*69825f36SValentin Clement (バレンタイン クレメン)There are currently the following operations: 32*69825f36SValentin Clement (バレンタイン クレメン)- `fir.array_load` 33*69825f36SValentin Clement (バレンタイン クレメン)- `fir.array_merge_store` 34*69825f36SValentin Clement (バレンタイン クレメン)- `fir.array_fetch` 35*69825f36SValentin Clement (バレンタイン クレメン)- `fir.array_update` 36*69825f36SValentin Clement (バレンタイン クレメン)- `fir.array_access` 37*69825f36SValentin Clement (バレンタイン クレメン)- `fir.array_amend` 38*69825f36SValentin Clement (バレンタイン クレメン) 39*69825f36SValentin Clement (バレンタイン クレメン)`array_load`(s) and `array_merge_store` are a pairing that brackets the lifetime 40*69825f36SValentin Clement (バレンタイン クレメン)of the array copies. 41*69825f36SValentin Clement (バレンタイン クレメン) 42*69825f36SValentin Clement (バレンタイン クレメン)`array_fetch` and `array_update` are defined to work as getter/setter pairs on 43*69825f36SValentin Clement (バレンタイン クレメン)values of elements from loaded array copies. These have "GEP-like" syntax and 44*69825f36SValentin Clement (バレンタイン クレメン)semantics. 45*69825f36SValentin Clement (バレンタイン クレメン) 46*69825f36SValentin Clement (バレンタイン クレメン)Fortran arrays are implicitly memory bound as are some other Fortran type/kind 47*69825f36SValentin Clement (バレンタイン クレメン)entities. For entities that can be atomically promoted to the value domain, 48*69825f36SValentin Clement (バレンタイン クレメン)we use `array_fetch` and `array_update`. 49*69825f36SValentin Clement (バレンタイン クレメン) 50*69825f36SValentin Clement (バレンタイン クレメン)`array_access` and `array_amend` are defined to work as getter/setter pairs on 51*69825f36SValentin Clement (バレンタイン クレメン)references to elements in loaded array copies. `array_access` has "GEP-like" 52*69825f36SValentin Clement (バレンタイン クレメン)syntax. `array_amend` annotates which loaded array copy is being written to. 53*69825f36SValentin Clement (バレンタイン クレメン)It is invalid to update an array copy without `array_amend`; doing so will 54*69825f36SValentin Clement (バレンタイン クレメン)result in undefined behavior. 55*69825f36SValentin Clement (バレンタイン クレメン)For those type/kinds that cannot be promoted to values, we must leave them in a 56*69825f36SValentin Clement (バレンタイン クレメン)memory reference domain, and we use `array_access` and `array_amend`. 57*69825f36SValentin Clement (バレンタイン クレメン) 58*69825f36SValentin Clement (バレンタイン クレメン)## array_load 59*69825f36SValentin Clement (バレンタイン クレメン) 60*69825f36SValentin Clement (バレンタイン クレメン)This operation taken with `array_merge_store` captures Fortran's 61*69825f36SValentin Clement (バレンタイン クレメン)copy-in/copy-out semantics. One way to think of this is that array_load 62*69825f36SValentin Clement (バレンタイン クレメン)creates a snapshot copy of the entire array. This copy can then be used 63*69825f36SValentin Clement (バレンタイン クレメン)as the "original value" of the array while the array's new value is 64*69825f36SValentin Clement (バレンタイン クレメン)computed. The `array_merge_store` operation is the copy-out semantics, which 65*69825f36SValentin Clement (バレンタイン クレメン)merge the updates with the original array value to produce the final array 66*69825f36SValentin Clement (バレンタイン クレメン)result. This abstracts the copy operations as opposed to always creating 67*69825f36SValentin Clement (バレンタイン クレメン)copies or requiring dependence analysis be performed on the syntax trees 68*69825f36SValentin Clement (バレンタイン クレメン)and before lowering to the IR. 69*69825f36SValentin Clement (バレンタイン クレメン) 70*69825f36SValentin Clement (バレンタイン クレメン)Load an entire array as a single SSA value. 71*69825f36SValentin Clement (バレンタイン クレメン) 72*69825f36SValentin Clement (バレンタイン クレメン)```fortran 73*69825f36SValentin Clement (バレンタイン クレメン) real :: a(o:n,p:m) 74*69825f36SValentin Clement (バレンタイン クレメン) ... 75*69825f36SValentin Clement (バレンタイン クレメン) ... = ... a ... 76*69825f36SValentin Clement (バレンタイン クレメン)``` 77*69825f36SValentin Clement (バレンタイン クレメン) 78*69825f36SValentin Clement (バレンタイン クレメン)One can use `fir.array_load` to produce an ssa-value that captures an 79*69825f36SValentin Clement (バレンタイン クレメン)immutable value of the entire array `a`, as in the Fortran array expression 80*69825f36SValentin Clement (バレンタイン クレメン)shown above. Subsequent changes to the memory containing the array do not 81*69825f36SValentin Clement (バレンタイン クレメン)alter its composite value. This operation lets one load an array as a 82*69825f36SValentin Clement (バレンタイン クレメン)value while applying a runtime shape, shift, or slice to the memory 83*69825f36SValentin Clement (バレンタイン クレメン)reference, and its semantics guarantee immutability. 84*69825f36SValentin Clement (バレンタイン クレメン) 85*69825f36SValentin Clement (バレンタイン クレメン)```mlir 86*69825f36SValentin Clement (バレンタイン クレメン)%s = fir.shape_shift %lb1, %ex1, %lb2, %ex2 : (index, index, index, index) -> !fir.shape<2> 87*69825f36SValentin Clement (バレンタイン クレメン)// load the entire array 'a' 88*69825f36SValentin Clement (バレンタイン クレメン)%v = fir.array_load %a(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32> 89*69825f36SValentin Clement (バレンタイン クレメン)// a fir.store here into array %a does not change %v 90*69825f36SValentin Clement (バレンタイン クレメン)``` 91*69825f36SValentin Clement (バレンタイン クレメン) 92*69825f36SValentin Clement (バレンタイン クレメン)# array_merge_store 93*69825f36SValentin Clement (バレンタイン クレメン) 94*69825f36SValentin Clement (バレンタイン クレメン)The `array_merge_store` operation stores a merged array value to memory. 95*69825f36SValentin Clement (バレンタイン クレメン) 96*69825f36SValentin Clement (バレンタイン クレメン) 97*69825f36SValentin Clement (バレンタイン クレメン)```fortran 98*69825f36SValentin Clement (バレンタイン クレメン) real :: a(n,m) 99*69825f36SValentin Clement (バレンタイン クレメン) ... 100*69825f36SValentin Clement (バレンタイン クレメン) a = ... 101*69825f36SValentin Clement (バレンタイン クレメン)``` 102*69825f36SValentin Clement (バレンタイン クレメン) 103*69825f36SValentin Clement (バレンタイン クレメン)One can use `fir.array_merge_store` to merge/copy the value of `a` in an 104*69825f36SValentin Clement (バレンタイン クレメン)array expression as shown above. 105*69825f36SValentin Clement (バレンタイン クレメン) 106*69825f36SValentin Clement (バレンタイン クレメン)```mlir 107*69825f36SValentin Clement (バレンタイン クレメン) %v = fir.array_load %a(%shape) : ... 108*69825f36SValentin Clement (バレンタイン クレメン) %r = fir.array_update %v, %f, %i, %j : (!fir.array<?x?xf32>, f32, index, index) -> !fir.array<?x?xf32> 109*69825f36SValentin Clement (バレンタイン クレメン) fir.array_merge_store %v, %r to %a : !fir.ref<!fir.array<?x?xf32>> 110*69825f36SValentin Clement (バレンタイン クレメン)``` 111*69825f36SValentin Clement (バレンタイン クレメン) 112*69825f36SValentin Clement (バレンタイン クレメン)This operation merges the original loaded array value, `%v`, with the 113*69825f36SValentin Clement (バレンタイン クレメン)chained updates, `%r`, and stores the result to the array at address, `%a`. 114*69825f36SValentin Clement (バレンタイン クレメン) 115*69825f36SValentin Clement (バレンタイン クレメン)This operation taken with `array_load`'s captures Fortran's 116*69825f36SValentin Clement (バレンタイン クレメン)copy-in/copy-out semantics. The first operands of `array_merge_store` is the 117*69825f36SValentin Clement (バレンタイン クレメン)result of the initial `array_load` operation. While this value could be 118*69825f36SValentin Clement (バレンタイン クレメン)retrieved by reference chasiing through the different array operations it is 119*69825f36SValentin Clement (バレンタイン クレメン)useful to have it on hand directly for analysis passes since this directly 120*69825f36SValentin Clement (バレンタイン クレメン)defines the "bounds" of the Fortran statement represented by these operations. 121*69825f36SValentin Clement (バレンタイン クレメン)The intention is to allow copy-in/copy-out regions to be easily delineated, 122*69825f36SValentin Clement (バレンタイン クレメン)analyzed, and optimized. 123*69825f36SValentin Clement (バレンタイン クレメン) 124*69825f36SValentin Clement (バレンタイン クレメン)## array_fetch 125*69825f36SValentin Clement (バレンタイン クレメン) 126*69825f36SValentin Clement (バレンタイン クレメン)The `array_fetch` operation fetches the value of an element in an array value. 127*69825f36SValentin Clement (バレンタイン クレメン) 128*69825f36SValentin Clement (バレンタイン クレメン)```fortran 129*69825f36SValentin Clement (バレンタイン クレメン) real :: a(n,m) 130*69825f36SValentin Clement (バレンタイン クレメン) ... 131*69825f36SValentin Clement (バレンタイン クレメン) ... a ... 132*69825f36SValentin Clement (バレンタイン クレメン) ... a(r,s+1) ... 133*69825f36SValentin Clement (バレンタイン クレメン)``` 134*69825f36SValentin Clement (バレンタイン クレメン) 135*69825f36SValentin Clement (バレンタイン クレメン)One can use `fir.array_fetch` to fetch the (implied) value of `a(i,j)` in 136*69825f36SValentin Clement (バレンタイン クレメン)an array expression as shown above. It can also be used to extract the 137*69825f36SValentin Clement (バレンタイン クレメン)element `a(r,s+1)` in the second expression. 138*69825f36SValentin Clement (バレンタイン クレメン) 139*69825f36SValentin Clement (バレンタイン クレメン)```mlir 140*69825f36SValentin Clement (バレンタイン クレメン) %s = fir.shape %n, %m : (index, index) -> !fir.shape<2> 141*69825f36SValentin Clement (バレンタイン クレメン) // load the entire array 'a' 142*69825f36SValentin Clement (バレンタイン クレメン) %v = fir.array_load %a(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32> 143*69825f36SValentin Clement (バレンタイン クレメン) // fetch the value of one of the array value's elements 144*69825f36SValentin Clement (バレンタイン クレメン) %1 = fir.array_fetch %v, %i, %j : (!fir.array<?x?xf32>, index, index) -> f32 145*69825f36SValentin Clement (バレンタイン クレメン)``` 146*69825f36SValentin Clement (バレンタイン クレメン) 147*69825f36SValentin Clement (バレンタイン クレメン)It is only possible to use `array_fetch` on an `array_load` result value or a 148*69825f36SValentin Clement (バレンタイン クレメン)value that can be trace back transitively to an `array_load` as the dominating 149*69825f36SValentin Clement (バレンタイン クレメン)source. Other array operation such as `array_update` can be in between. 150*69825f36SValentin Clement (バレンタイン クレメン) 151*69825f36SValentin Clement (バレンタイン クレメン)## array_update 152*69825f36SValentin Clement (バレンタイン クレメン) 153*69825f36SValentin Clement (バレンタイン クレメン)The `array_update` operation is used to update the value of an element in an 154*69825f36SValentin Clement (バレンタイン クレメン)array value. A new array value is returned where all element values of the input 155*69825f36SValentin Clement (バレンタイン クレメン)array are identical except for the selected element which is the value passed in 156*69825f36SValentin Clement (バレンタイン クレメン)the update. 157*69825f36SValentin Clement (バレンタイン クレメン) 158*69825f36SValentin Clement (バレンタイン クレメン)```fortran 159*69825f36SValentin Clement (バレンタイン クレメン) real :: a(n,m) 160*69825f36SValentin Clement (バレンタイン クレメン) ... 161*69825f36SValentin Clement (バレンタイン クレメン) a = ... 162*69825f36SValentin Clement (バレンタイン クレメン)``` 163*69825f36SValentin Clement (バレンタイン クレメン) 164*69825f36SValentin Clement (バレンタイン クレメン)One can use `fir.array_update` to update the (implied) value of `a(i,j)` 165*69825f36SValentin Clement (バレンタイン クレメン)in an array expression as shown above. 166*69825f36SValentin Clement (バレンタイン クレメン) 167*69825f36SValentin Clement (バレンタイン クレメン)```mlir 168*69825f36SValentin Clement (バレンタイン クレメン) %s = fir.shape %n, %m : (index, index) -> !fir.shape<2> 169*69825f36SValentin Clement (バレンタイン クレメン) // load the entire array 'a' 170*69825f36SValentin Clement (バレンタイン クレメン) %v = fir.array_load %a(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32> 171*69825f36SValentin Clement (バレンタイン クレメン) // update the value of one of the array value's elements 172*69825f36SValentin Clement (バレンタイン クレメン) // %r_{ij} = %f if (i,j) = (%i,%j), %v_{ij} otherwise 173*69825f36SValentin Clement (バレンタイン クレメン) %r = fir.array_update %v, %f, %i, %j : (!fir.array<?x?xf32>, f32, index, index) -> !fir.array<?x?xf32> 174*69825f36SValentin Clement (バレンタイン クレメン) fir.array_merge_store %v, %r to %a : !fir.ref<!fir.array<?x?xf32>> 175*69825f36SValentin Clement (バレンタイン クレメン)``` 176*69825f36SValentin Clement (バレンタイン クレメン) 177*69825f36SValentin Clement (バレンタイン クレメン)An array value update behaves as if a mapping function from the indices 178*69825f36SValentin Clement (バレンタイン クレメン)to the new value has been added, replacing the previous mapping. These 179*69825f36SValentin Clement (バレンタイン クレメン)mappings can be added to the ssa-value, but will not be materialized in 180*69825f36SValentin Clement (バレンタイン クレメン)memory until the `fir.array_merge_store` is performed. 181*69825f36SValentin Clement (バレンタイン クレメン)`fir.array_update` can be seen as an array access with a notion that the array 182*69825f36SValentin Clement (バレンタイン クレメン)will be changed at the accessed position when `fir.array_merge_store` is 183*69825f36SValentin Clement (バレンタイン クレメン)performed. 184*69825f36SValentin Clement (バレンタイン クレメン) 185*69825f36SValentin Clement (バレンタイン クレメン)## array_access 186*69825f36SValentin Clement (バレンタイン クレメン) 187*69825f36SValentin Clement (バレンタイン クレメン)The `array_access` provides a reference to a single element from an array value. 188*69825f36SValentin Clement (バレンタイン クレメン)This is *not* a view in the immutable array, otherwise it couldn't be stored to. 189*69825f36SValentin Clement (バレンタイン クレメン)It can be see as a logical copy of the element and its position in the array. 190*69825f36SValentin Clement (バレンタイン クレメン)Tis reference can be written to and modified withoiut changing the original 191*69825f36SValentin Clement (バレンタイン クレメン)array. 192*69825f36SValentin Clement (バレンタイン クレメン) 193*69825f36SValentin Clement (バレンタイン クレメン)The `array_access` operation is used to fetch the memory reference of an element 194*69825f36SValentin Clement (バレンタイン クレメン)in an array value. 195*69825f36SValentin Clement (バレンタイン クレメン) 196*69825f36SValentin Clement (バレンタイン クレメン)```fortran 197*69825f36SValentin Clement (バレンタイン クレメン) real :: a(n,m) 198*69825f36SValentin Clement (バレンタイン クレメン) ... 199*69825f36SValentin Clement (バレンタイン クレメン) ... a ... 200*69825f36SValentin Clement (バレンタイン クレメン) ... a(r,s+1) ... 201*69825f36SValentin Clement (バレンタイン クレメン)``` 202*69825f36SValentin Clement (バレンタイン クレメン) 203*69825f36SValentin Clement (バレンタイン クレメン)One can use `fir.array_access` to recover the implied memory reference to 204*69825f36SValentin Clement (バレンタイン クレメン)the element `a(i,j)` in an array expression `a` as shown above. It can also 205*69825f36SValentin Clement (バレンタイン クレメン)be used to recover the reference element `a(r,s+1)` in the second 206*69825f36SValentin Clement (バレンタイン クレメン)expression. 207*69825f36SValentin Clement (バレンタイン クレメン) 208*69825f36SValentin Clement (バレンタイン クレメン)```mlir 209*69825f36SValentin Clement (バレンタイン クレメン) %s = fir.shape %n, %m : (index, index) -> !fir.shape<2> 210*69825f36SValentin Clement (バレンタイン クレメン) // load the entire array 'a' 211*69825f36SValentin Clement (バレンタイン クレメン) %v = fir.array_load %a(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32> 212*69825f36SValentin Clement (バレンタイン クレメン) // fetch the value of one of the array value's elements 213*69825f36SValentin Clement (バレンタイン クレメン) %1 = fir.array_access %v, %i, %j : (!fir.array<?x?xf32>, index, index) -> !fir.ref<f32> 214*69825f36SValentin Clement (バレンタイン クレメン)``` 215*69825f36SValentin Clement (バレンタイン クレメン) 216*69825f36SValentin Clement (バレンタイン クレメン)It is only possible to use `array_access` on an `array_load` result value or a 217*69825f36SValentin Clement (バレンタイン クレメン)value that can be trace back transitively to an `array_load` as the dominating 218*69825f36SValentin Clement (バレンタイン クレメン)source. Other array operation such as `array_amend` can be in between. 219*69825f36SValentin Clement (バレンタイン クレメン) 220*69825f36SValentin Clement (バレンタイン クレメン)`array_access` if mainly used with `character`'s arrays and arrays of derived 221*69825f36SValentin Clement (バレンタイン クレメン)types where because they might have a non-compile time sizes that would be 222*69825f36SValentin Clement (バレンタイン クレメン)useless too load entirely or too big to load. 223*69825f36SValentin Clement (バレンタイン クレメン) 224*69825f36SValentin Clement (バレンタイン クレメン)Here is a simple example with a `character` array assignment. 225*69825f36SValentin Clement (バレンタイン クレメン) 226*69825f36SValentin Clement (バレンタイン クレメン)Fortran 227*69825f36SValentin Clement (バレンタイン クレメン)``` 228*69825f36SValentin Clement (バレンタイン クレメン)subroutine foo(c1, c2, n) 229*69825f36SValentin Clement (バレンタイン クレメン) integer(8) :: n 230*69825f36SValentin Clement (バレンタイン クレメン) character(n) :: c1(:), c2(:) 231*69825f36SValentin Clement (バレンタイン クレメン) c1 = c2 232*69825f36SValentin Clement (バレンタイン クレメン)end subroutine 233*69825f36SValentin Clement (バレンタイン クレメン)``` 234*69825f36SValentin Clement (バレンタイン クレメン) 235*69825f36SValentin Clement (バレンタイン クレメン)It results in this cleaned-up FIR: 236*69825f36SValentin Clement (バレンタイン クレメン)``` 237*69825f36SValentin Clement (バレンタイン クレメン)func @_QPfoo(%arg0: !fir.box<!fir.array<?x!fir.char<1,?>>>, %arg1: !fir.box<!fir.array<?x!fir.char<1,?>>>, %arg2: !fir.ref<i64>) { 238*69825f36SValentin Clement (バレンタイン クレメン) %0 = fir.load %arg2 : !fir.ref<i64> 239*69825f36SValentin Clement (バレンタイン クレメン) %c0 = arith.constant 0 : index 240*69825f36SValentin Clement (バレンタイン クレメン) %1:3 = fir.box_dims %arg0, %c0 : (!fir.box<!fir.array<?x!fir.char<1,?>>>, index) -> (index, index, index) 241*69825f36SValentin Clement (バレンタイン クレメン) %2 = fir.array_load %arg0 : (!fir.box<!fir.array<?x!fir.char<1,?>>>) -> !fir.array<?x!fir.char<1,?>> 242*69825f36SValentin Clement (バレンタイン クレメン) %3 = fir.array_load %arg1 : (!fir.box<!fir.array<?x!fir.char<1,?>>>) -> !fir.array<?x!fir.char<1,?>> 243*69825f36SValentin Clement (バレンタイン クレメン) %c1 = arith.constant 1 : index 244*69825f36SValentin Clement (バレンタイン クレメン) %4 = arith.subi %1#1, %c1 : index 245*69825f36SValentin Clement (バレンタイン クレメン) %5 = fir.do_loop %arg3 = %c0 to %4 step %c1 unordered iter_args(%arg4 = %2) -> (!fir.array<?x!fir.char<1,?>>) { 246*69825f36SValentin Clement (バレンタイン クレメン) %6 = fir.array_access %3, %arg3 : (!fir.array<?x!fir.char<1,?>>, index) -> !fir.ref<!fir.char<1,?>> 247*69825f36SValentin Clement (バレンタイン クレメン) %7 = fir.array_access %arg4, %arg3 : (!fir.array<?x!fir.char<1,?>>, index) -> !fir.ref<!fir.char<1,?>> 248*69825f36SValentin Clement (バレンタイン クレメン) %false = arith.constant false 249*69825f36SValentin Clement (バレンタイン クレメン) %8 = fir.convert %7 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8> 250*69825f36SValentin Clement (バレンタイン クレメン) %9 = fir.convert %6 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8> 251*69825f36SValentin Clement (バレンタイン クレメン) fir.call @llvm.memmove.p0i8.p0i8.i64(%8, %9, %0, %false) : (!fir.ref<i8>, !fir.ref<i8>, i64, i1) -> () 252*69825f36SValentin Clement (バレンタイン クレメン) %10 = fir.array_amend %arg4, %7 : (!fir.array<?x!fir.char<1,?>>, !fir.ref<!fir.char<1,?>>) -> !fir.array<?x!fir.char<1,?>> 253*69825f36SValentin Clement (バレンタイン クレメン) fir.result %10 : !fir.array<?x!fir.char<1,?>> 254*69825f36SValentin Clement (バレンタイン クレメン) } 255*69825f36SValentin Clement (バレンタイン クレメン) fir.array_merge_store %2, %5 to %arg0 : !fir.array<?x!fir.char<1,?>>, !fir.array<?x!fir.char<1,?>>, !fir.box<!fir.array<?x!fir.char<1,?>>> 256*69825f36SValentin Clement (バレンタイン クレメン) return 257*69825f36SValentin Clement (バレンタイン クレメン) } 258*69825f36SValentin Clement (バレンタイン クレメン) func private @llvm.memmove.p0i8.p0i8.i64(!fir.ref<i8>, !fir.ref<i8>, i64, i1) 259*69825f36SValentin Clement (バレンタイン クレメン)} 260*69825f36SValentin Clement (バレンタイン クレメン)``` 261*69825f36SValentin Clement (バレンタイン クレメン) 262*69825f36SValentin Clement (バレンタイン クレメン)`fir.array_access` and `fir.array_amend` split the two purposes of 263*69825f36SValentin Clement (バレンタイン クレメン)`fir.array_update` into two distinct operations to work on type/kind that must 264*69825f36SValentin Clement (バレンタイン クレメン)reside in the memory reference domain. `fir.array_access` captures the array 265*69825f36SValentin Clement (バレンタイン クレメン)access semantics and `fir.array_amend` denotes which `fir.array_access` is the 266*69825f36SValentin Clement (バレンタイン クレメン)lhs. 267*69825f36SValentin Clement (バレンタイン クレメン) 268*69825f36SValentin Clement (バレンタイン クレメン)We do not want to start loading the entire `!fir.ref<!fir.char<1,?>>` here since 269*69825f36SValentin Clement (バレンタイン クレメン)it has dynamic length, and even if constant, could be too long to do so. 270*69825f36SValentin Clement (バレンタイン クレメン) 271*69825f36SValentin Clement (バレンタイン クレメン)## array_amend 272*69825f36SValentin Clement (バレンタイン クレメン) 273*69825f36SValentin Clement (バレンタイン クレメン)The `array_amend` operation marks an array value as having been changed via a 274*69825f36SValentin Clement (バレンタイン クレメン)reference obtain by an `array_access`. It acts as a logical transaction log 275*69825f36SValentin Clement (バレンタイン クレメン)that is used to merge the final result back with an `array_merge_store` 276*69825f36SValentin Clement (バレンタイン クレメン)operation. 277*69825f36SValentin Clement (バレンタイン クレメン) 278*69825f36SValentin Clement (バレンタイン クレメン)```mlir 279*69825f36SValentin Clement (バレンタイン クレメン) // fetch the value of one of the array value's elements 280*69825f36SValentin Clement (バレンタイン クレメン) %1 = fir.array_access %v, %i, %j : (!fir.array<?x?xT>, index, index) -> !fir.ref<T> 281*69825f36SValentin Clement (バレンタイン クレメン) // modify the element by storing data using %1 as a reference 282*69825f36SValentin Clement (バレンタイン クレメン) %2 = ... %1 ... 283*69825f36SValentin Clement (バレンタイン クレメン) // mark the array value 284*69825f36SValentin Clement (バレンタイン クレメン) %new_v = fir.array_amend %v, %2 : (!fir.array<?x?xT>, !fir.ref<T>) -> !fir.array<?x?xT> 285*69825f36SValentin Clement (バレンタイン クレメン)``` 286*69825f36SValentin Clement (バレンタイン クレメン) 287*69825f36SValentin Clement (バレンタイン クレメン)## Example 288*69825f36SValentin Clement (バレンタイン クレメン) 289*69825f36SValentin Clement (バレンタイン クレメン)Here is an example of a FIR code using several array operations together. The 290*69825f36SValentin Clement (バレンタイン クレメン)example below is a simplified version of the FIR code comiing from the 291*69825f36SValentin Clement (バレンタイン クレメン)following Fortran code snippet. 292*69825f36SValentin Clement (バレンタイン クレメン) 293*69825f36SValentin Clement (バレンタイン クレメン)```fortran 294*69825f36SValentin Clement (バレンタイン クレメン)subroutine s(a,l,u) 295*69825f36SValentin Clement (バレンタイン クレメン) type t 296*69825f36SValentin Clement (バレンタイン クレメン) integer m 297*69825f36SValentin Clement (バレンタイン クレメン) end type t 298*69825f36SValentin Clement (バレンタイン クレメン) type(t) :: a(:) 299*69825f36SValentin Clement (バレンタイン クレメン) integer :: l, u 300*69825f36SValentin Clement (バレンタイン クレメン) forall (i=l:u) 301*69825f36SValentin Clement (バレンタイン クレメン) a(i) = a(u-i+1) 302*69825f36SValentin Clement (バレンタイン クレメン) end forall 303*69825f36SValentin Clement (バレンタイン クレメン)end 304*69825f36SValentin Clement (バレンタイン クレメン)``` 305*69825f36SValentin Clement (バレンタイン クレメン) 306*69825f36SValentin Clement (バレンタイン クレメン)``` 307*69825f36SValentin Clement (バレンタイン クレメン)func @_QPs(%arg0: !fir.box<!fir.array<?x!fir.type<_QFsTt{m:i32}>>>, %arg1: !fir.ref<i32>, %arg2: !fir.ref<i32>) { 308*69825f36SValentin Clement (バレンタイン クレメン) %l = fir.load %arg1 : !fir.ref<i32> 309*69825f36SValentin Clement (バレンタイン クレメン) %l_index = fir.convert %l : (i32) -> index 310*69825f36SValentin Clement (バレンタイン クレメン) %u = fir.load %arg2 : !fir.ref<i32> 311*69825f36SValentin Clement (バレンタイン クレメン) %u_index = fir.convert %u : (i32) -> index 312*69825f36SValentin Clement (バレンタイン クレメン) %c1 = arith.constant 1 : index 313*69825f36SValentin Clement (バレンタイン クレメン) // This is the "copy-in" array used on the RHS of the expression. It will be indexed into and loaded at each iteration. 314*69825f36SValentin Clement (バレンタイン クレメン) %array_a_src = fir.array_load %arg0 : (!fir.box<!fir.array<?x!fir.type<_QFsTt{m:i32}>>>) -> !fir.array<?x!fir.type<_QFsTt{m:i32}>> 315*69825f36SValentin Clement (バレンタイン クレメン) 316*69825f36SValentin Clement (バレンタイン クレメン) // This is the "seed" for the "copy-out" array on the LHS. It'll flow from iteration to iteration and gets 317*69825f36SValentin Clement (バレンタイン クレメン) // updated at each iteration. 318*69825f36SValentin Clement (バレンタイン クレメン) %array_a_dest_init = fir.array_load %arg0 : (!fir.box<!fir.array<?x!fir.type<_QFsTt{m:i32}>>>) -> !fir.array<?x!fir.type<_QFsTt{m:i32}>> 319*69825f36SValentin Clement (バレンタイン クレメン) 320*69825f36SValentin Clement (バレンタイン クレメン) %array_a_final = fir.do_loop %i = %l_index to %u_index step %c1 unordered iter_args(%array_a_dest = %array_a_dest_init) -> (!fir.array<?x!fir.type<_QFsTt{m:i32}>>) { 321*69825f36SValentin Clement (バレンタイン クレメン) // Compute indexing for the RHS and array the element. 322*69825f36SValentin Clement (バレンタイン クレメン) %u_minus_i = arith.subi %u_index, %i : index // u-i 323*69825f36SValentin Clement (バレンタイン クレメン) %u_minus_i_plus_one = arith.addi %u_minus_i, %c1: index // u-i+1 324*69825f36SValentin Clement (バレンタイン クレメン) %a_src_ref = fir.array_access %array_a_src, %u_minus_i_plus_one {Fortran.offsets} : (!fir.array<?x!fir.type<_QFsTt{m:i32}>>, index) -> !fir.ref<!fir.type<_QFsTt{m:i32}>> 325*69825f36SValentin Clement (バレンタイン クレメン) %a_src_elt = fir.load %a_src_ref : !fir.ref<!fir.type<_QFsTt{m:i32}>> 326*69825f36SValentin Clement (バレンタイン クレメン) 327*69825f36SValentin Clement (バレンタイン クレメン) // Get the reference to the element in the array on the LHS 328*69825f36SValentin Clement (バレンタイン クレメン) %a_dst_ref = fir.array_access %array_a_dest, %i {Fortran.offsets} : (!fir.array<?x!fir.type<_QFsTt{m:i32}>>, index) -> !fir.ref<!fir.type<_QFsTt{m:i32}>> 329*69825f36SValentin Clement (バレンタイン クレメン) 330*69825f36SValentin Clement (バレンタイン クレメン) // Store the value, and update the array 331*69825f36SValentin Clement (バレンタイン クレメン) fir.store %a_src_elt to %a_dst_ref : !fir.ref<!fir.type<_QFsTt{m:i32}>> 332*69825f36SValentin Clement (バレンタイン クレメン) %updated_array_a = fir.array_amend %array_a_dest, %a_dst_ref : (!fir.array<?x!fir.type<_QFsTt{m:i32}>>, !fir.ref<!fir.type<_QFsTt{m:i32}>>) -> !fir.array<?x!fir.type<_QFsTt{m:i32}>> 333*69825f36SValentin Clement (バレンタイン クレメン) 334*69825f36SValentin Clement (バレンタイン クレメン) // Forward the current updated array to the next iteration. 335*69825f36SValentin Clement (バレンタイン クレメン) fir.result %updated_array_a : !fir.array<?x!fir.type<_QFsTt{m:i32}>> 336*69825f36SValentin Clement (バレンタイン クレメン) } 337*69825f36SValentin Clement (バレンタイン クレメン) // Store back the result by merging the initial value loaded before the loop 338*69825f36SValentin Clement (バレンタイン クレメン) // with the final one produced by the loop. 339*69825f36SValentin Clement (バレンタイン クレメン) fir.array_merge_store %array_a_dest_init, %array_a_final to %arg0 : !fir.array<?x!fir.type<_QFsTt{m:i32}>>, !fir.array<?x!fir.type<_QFsTt{m:i32}>>, !fir.box<!fir.array<?x!fir.type<_QFsTt{m:i32}>>> 340*69825f36SValentin Clement (バレンタイン クレメン) return 341*69825f36SValentin Clement (バレンタイン クレメン)} 342*69825f36SValentin Clement (バレンタイン クレメン)``` 343