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