xref: /llvm-project/flang/docs/FIRArrayOperations.md (revision 7ca4012e115a39c09647bbd28105ea7e5edcd441)
169825f36SValentin Clement (バレンタイン クレメン)<!--===- docs/FIRArrayOperations.md
269825f36SValentin Clement (バレンタイン クレメン)
369825f36SValentin Clement (バレンタイン クレメン)   Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
469825f36SValentin Clement (バレンタイン クレメン)   See https://llvm.org/LICENSE.txt for license information.
569825f36SValentin Clement (バレンタイン クレメン)   SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
669825f36SValentin Clement (バレンタイン クレメン)
769825f36SValentin Clement (バレンタイン クレメン)-->
869825f36SValentin Clement (バレンタイン クレメン)
969825f36SValentin Clement (バレンタイン クレメン)# Design: FIR Array operations
1069825f36SValentin Clement (バレンタイン クレメン)
11b7ff0320Scor3ntin```{contents}
12b7ff0320Scor3ntin---
13b7ff0320Scor3ntinlocal:
14b7ff0320Scor3ntin---
1569825f36SValentin Clement (バレンタイン クレメン)```
1669825f36SValentin Clement (バレンタイン クレメン)
1769825f36SValentin Clement (バレンタイン クレメン)## General
1869825f36SValentin Clement (バレンタイン クレメン)
1969825f36SValentin Clement (バレンタイン クレメン)The array operations in FIR model the copy-in/copy-out semantics over Fortran
2069825f36SValentin Clement (バレンタイン クレメン)statements.
2169825f36SValentin Clement (バレンタイン クレメン)
2269825f36SValentin Clement (バレンタイン クレメン)Fortran language semantics sometimes require the compiler to make a temporary
2369825f36SValentin Clement (バレンタイン クレメン)copy of an array or array slice. Situations where this can occur include:
2469825f36SValentin Clement (バレンタイン クレメン)
2569825f36SValentin Clement (バレンタイン クレメン)* Passing a non-contiguous array to a procedure that does not declare it as
2669825f36SValentin Clement (バレンタイン クレメン)  assumed-shape.
2769825f36SValentin Clement (バレンタイン クレメン)* Array expressions, especially those involving `RESHAPE`, `PACK`, and `MERGE`.
2869825f36SValentin Clement (バレンタイン クレメン)* Assignments of arrays where the array appears on both the left and right-hand
2969825f36SValentin Clement (バレンタイン クレメン)  sides of the assignment.
3069825f36SValentin Clement (バレンタイン クレメン)* Assignments of `POINTER` arrays.
3169825f36SValentin Clement (バレンタイン クレメン)
3269825f36SValentin Clement (バレンタイン クレメン)There are currently the following operations:
3369825f36SValentin Clement (バレンタイン クレメン)- `fir.array_load`
3469825f36SValentin Clement (バレンタイン クレメン)- `fir.array_merge_store`
3569825f36SValentin Clement (バレンタイン クレメン)- `fir.array_fetch`
3669825f36SValentin Clement (バレンタイン クレメン)- `fir.array_update`
3769825f36SValentin Clement (バレンタイン クレメン)- `fir.array_access`
3869825f36SValentin Clement (バレンタイン クレメン)- `fir.array_amend`
3969825f36SValentin Clement (バレンタイン クレメン)
4069825f36SValentin Clement (バレンタイン クレメン)`array_load`(s) and `array_merge_store` are a pairing that brackets the lifetime
4169825f36SValentin Clement (バレンタイン クレメン)of the array copies.
4269825f36SValentin Clement (バレンタイン クレメン)
4369825f36SValentin Clement (バレンタイン クレメン)`array_fetch` and `array_update` are defined to work as getter/setter pairs on
4469825f36SValentin Clement (バレンタイン クレメン)values of elements from loaded array copies. These have "GEP-like" syntax and
4569825f36SValentin Clement (バレンタイン クレメン)semantics.
4669825f36SValentin Clement (バレンタイン クレメン)
4769825f36SValentin Clement (バレンタイン クレメン)Fortran arrays are implicitly memory bound as are some other Fortran type/kind
4869825f36SValentin Clement (バレンタイン クレメン)entities. For entities that can be atomically promoted to the value domain,
4969825f36SValentin Clement (バレンタイン クレメン)we use `array_fetch` and `array_update`.
5069825f36SValentin Clement (バレンタイン クレメン)
5169825f36SValentin Clement (バレンタイン クレメン)`array_access` and `array_amend` are defined to work as getter/setter pairs on
5269825f36SValentin Clement (バレンタイン クレメン)references to elements in loaded array copies. `array_access` has "GEP-like"
5369825f36SValentin Clement (バレンタイン クレメン)syntax. `array_amend` annotates which loaded array copy is being written to.
5469825f36SValentin Clement (バレンタイン クレメン)It is invalid to update an array copy without `array_amend`; doing so will
5569825f36SValentin Clement (バレンタイン クレメン)result in undefined behavior.
5669825f36SValentin Clement (バレンタイン クレメン)For those type/kinds that cannot be promoted to values, we must leave them in a
5769825f36SValentin Clement (バレンタイン クレメン)memory reference domain, and we use `array_access` and `array_amend`.
5869825f36SValentin Clement (バレンタイン クレメン)
5969825f36SValentin Clement (バレンタイン クレメン)## array_load
6069825f36SValentin Clement (バレンタイン クレメン)
6169825f36SValentin Clement (バレンタイン クレメン)This operation taken with `array_merge_store` captures Fortran's
6269825f36SValentin Clement (バレンタイン クレメン)copy-in/copy-out semantics. One way to think of this is that array_load
6369825f36SValentin Clement (バレンタイン クレメン)creates a snapshot copy of the entire array. This copy can then be used
6469825f36SValentin Clement (バレンタイン クレメン)as the "original value" of the array while the array's new value is
6569825f36SValentin Clement (バレンタイン クレメン)computed. The `array_merge_store` operation is the copy-out semantics, which
6669825f36SValentin Clement (バレンタイン クレメン)merge the updates with the original array value to produce the final array
6769825f36SValentin Clement (バレンタイン クレメン)result. This abstracts the copy operations as opposed to always creating
6869825f36SValentin Clement (バレンタイン クレメン)copies or requiring dependence analysis be performed on the syntax trees
6969825f36SValentin Clement (バレンタイン クレメン)and before lowering to the IR.
7069825f36SValentin Clement (バレンタイン クレメン)
7169825f36SValentin Clement (バレンタイン クレメン)Load an entire array as a single SSA value.
7269825f36SValentin Clement (バレンタイン クレメン)
7369825f36SValentin Clement (バレンタイン クレメン)```fortran
7469825f36SValentin Clement (バレンタイン クレメン)  real :: a(o:n,p:m)
7569825f36SValentin Clement (バレンタイン クレメン)  ...
7669825f36SValentin Clement (バレンタイン クレメン)  ... = ... a ...
7769825f36SValentin Clement (バレンタイン クレメン)```
7869825f36SValentin Clement (バレンタイン クレメン)
7969825f36SValentin Clement (バレンタイン クレメン)One can use `fir.array_load` to produce an ssa-value that captures an
8069825f36SValentin Clement (バレンタイン クレメン)immutable value of the entire array `a`, as in the Fortran array expression
8169825f36SValentin Clement (バレンタイン クレメン)shown above. Subsequent changes to the memory containing the array do not
8269825f36SValentin Clement (バレンタイン クレメン)alter its composite value. This operation lets one load an array as a
8369825f36SValentin Clement (バレンタイン クレメン)value while applying a runtime shape, shift, or slice to the memory
8469825f36SValentin Clement (バレンタイン クレメン)reference, and its semantics guarantee immutability.
8569825f36SValentin Clement (バレンタイン クレメン)
86c226d6c8SCorentin Jabot```
87d9404d6dSPeixin-Qiao%s = fir.shape_shift %lb1, %ex1, %lb2, %ex2 : (index, index, index, index) -> !fir.shapeshift<2>
8869825f36SValentin Clement (バレンタイン クレメン)// load the entire array 'a'
89d9404d6dSPeixin-Qiao%v = fir.array_load %a(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shapeshift<2>) -> !fir.array<?x?xf32>
9069825f36SValentin Clement (バレンタイン クレメン)// a fir.store here into array %a does not change %v
9169825f36SValentin Clement (バレンタイン クレメン)```
9269825f36SValentin Clement (バレンタイン クレメン)
93*7ca4012eSTarun Prabhu## array_merge_store
9469825f36SValentin Clement (バレンタイン クレメン)
9569825f36SValentin Clement (バレンタイン クレメン)The `array_merge_store` operation stores a merged array value to memory.
9669825f36SValentin Clement (バレンタイン クレメン)
9769825f36SValentin Clement (バレンタイン クレメン)
9869825f36SValentin Clement (バレンタイン クレメン)```fortran
9969825f36SValentin Clement (バレンタイン クレメン)  real :: a(n,m)
10069825f36SValentin Clement (バレンタイン クレメン)  ...
10169825f36SValentin Clement (バレンタイン クレメン)  a = ...
10269825f36SValentin Clement (バレンタイン クレメン)```
10369825f36SValentin Clement (バレンタイン クレメン)
10469825f36SValentin Clement (バレンタイン クレメン)One can use `fir.array_merge_store` to merge/copy the value of `a` in an
10569825f36SValentin Clement (バレンタイン クレメン)array expression as shown above.
10669825f36SValentin Clement (バレンタイン クレメン)
107c226d6c8SCorentin Jabot```
10869825f36SValentin Clement (バレンタイン クレメン)  %v = fir.array_load %a(%shape) : ...
10969825f36SValentin Clement (バレンタイン クレメン)  %r = fir.array_update %v, %f, %i, %j : (!fir.array<?x?xf32>, f32, index, index) -> !fir.array<?x?xf32>
11069825f36SValentin Clement (バレンタイン クレメン)  fir.array_merge_store %v, %r to %a : !fir.ref<!fir.array<?x?xf32>>
11169825f36SValentin Clement (バレンタイン クレメン)```
11269825f36SValentin Clement (バレンタイン クレメン)
11369825f36SValentin Clement (バレンタイン クレメン)This operation merges the original loaded array value, `%v`, with the
11469825f36SValentin Clement (バレンタイン クレメン)chained updates, `%r`, and stores the result to the array at address, `%a`.
11569825f36SValentin Clement (バレンタイン クレメン)
11669825f36SValentin Clement (バレンタイン クレメン)This operation taken with `array_load`'s captures Fortran's
11769825f36SValentin Clement (バレンタイン クレメン)copy-in/copy-out semantics. The first operands of `array_merge_store` is the
11869825f36SValentin Clement (バレンタイン クレメン)result of the initial `array_load` operation. While this value could be
1199e37b1e5SGabriel Ravierretrieved by reference chasing through the different array operations it is
12069825f36SValentin Clement (バレンタイン クレメン)useful to have it on hand directly for analysis passes since this directly
12169825f36SValentin Clement (バレンタイン クレメン)defines the "bounds" of the Fortran statement represented by these operations.
12269825f36SValentin Clement (バレンタイン クレメン)The intention is to allow copy-in/copy-out regions to be easily delineated,
12369825f36SValentin Clement (バレンタイン クレメン)analyzed, and optimized.
12469825f36SValentin Clement (バレンタイン クレメン)
12569825f36SValentin Clement (バレンタイン クレメン)## array_fetch
12669825f36SValentin Clement (バレンタイン クレメン)
12769825f36SValentin Clement (バレンタイン クレメン)The `array_fetch` operation fetches the value of an element in an array value.
12869825f36SValentin Clement (バレンタイン クレメン)
12969825f36SValentin Clement (バレンタイン クレメン)```fortran
13069825f36SValentin Clement (バレンタイン クレメン)  real :: a(n,m)
13169825f36SValentin Clement (バレンタイン クレメン)  ...
13269825f36SValentin Clement (バレンタイン クレメン)  ... a ...
13369825f36SValentin Clement (バレンタイン クレメン)  ... a(r,s+1) ...
13469825f36SValentin Clement (バレンタイン クレメン)```
13569825f36SValentin Clement (バレンタイン クレメン)
13669825f36SValentin Clement (バレンタイン クレメン)One can use `fir.array_fetch` to fetch the (implied) value of `a(i,j)` in
13769825f36SValentin Clement (バレンタイン クレメン)an array expression as shown above. It can also be used to extract the
13869825f36SValentin Clement (バレンタイン クレメン)element `a(r,s+1)` in the second expression.
13969825f36SValentin Clement (バレンタイン クレメン)
140c226d6c8SCorentin Jabot```
14169825f36SValentin Clement (バレンタイン クレメン)  %s = fir.shape %n, %m : (index, index) -> !fir.shape<2>
14269825f36SValentin Clement (バレンタイン クレメン)  // load the entire array 'a'
14369825f36SValentin Clement (バレンタイン クレメン)  %v = fir.array_load %a(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32>
14469825f36SValentin Clement (バレンタイン クレメン)  // fetch the value of one of the array value's elements
14569825f36SValentin Clement (バレンタイン クレメン)  %1 = fir.array_fetch %v, %i, %j : (!fir.array<?x?xf32>, index, index) -> f32
14669825f36SValentin Clement (バレンタイン クレメン)```
14769825f36SValentin Clement (バレンタイン クレメン)
14869825f36SValentin Clement (バレンタイン クレメン)It is only possible to use `array_fetch` on an `array_load` result value or a
14969825f36SValentin Clement (バレンタイン クレメン)value that can be trace back transitively to an `array_load` as the dominating
15069825f36SValentin Clement (バレンタイン クレメン)source. Other array operation such as `array_update` can be in between.
15169825f36SValentin Clement (バレンタイン クレメン)
15269825f36SValentin Clement (バレンタイン クレメン)## array_update
15369825f36SValentin Clement (バレンタイン クレメン)
15469825f36SValentin Clement (バレンタイン クレメン)The `array_update` operation is used to update the value of an element in an
15569825f36SValentin Clement (バレンタイン クレメン)array value. A new array value is returned where all element values of the input
15669825f36SValentin Clement (バレンタイン クレメン)array are identical except for the selected element which is the value passed in
15769825f36SValentin Clement (バレンタイン クレメン)the update.
15869825f36SValentin Clement (バレンタイン クレメン)
15969825f36SValentin Clement (バレンタイン クレメン)```fortran
16069825f36SValentin Clement (バレンタイン クレメン)  real :: a(n,m)
16169825f36SValentin Clement (バレンタイン クレメン)  ...
16269825f36SValentin Clement (バレンタイン クレメン)  a = ...
16369825f36SValentin Clement (バレンタイン クレメン)```
16469825f36SValentin Clement (バレンタイン クレメン)
16569825f36SValentin Clement (バレンタイン クレメン)One can use `fir.array_update` to update the (implied) value of `a(i,j)`
16669825f36SValentin Clement (バレンタイン クレメン)in an array expression as shown above.
16769825f36SValentin Clement (バレンタイン クレメン)
168c226d6c8SCorentin Jabot```
16969825f36SValentin Clement (バレンタイン クレメン)  %s = fir.shape %n, %m : (index, index) -> !fir.shape<2>
17069825f36SValentin Clement (バレンタイン クレメン)  // load the entire array 'a'
17169825f36SValentin Clement (バレンタイン クレメン)  %v = fir.array_load %a(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32>
17269825f36SValentin Clement (バレンタイン クレメン)  // update the value of one of the array value's elements
17369825f36SValentin Clement (バレンタイン クレメン)  // %r_{ij} = %f  if (i,j) = (%i,%j),   %v_{ij} otherwise
17469825f36SValentin Clement (バレンタイン クレメン)  %r = fir.array_update %v, %f, %i, %j : (!fir.array<?x?xf32>, f32, index, index) -> !fir.array<?x?xf32>
17569825f36SValentin Clement (バレンタイン クレメン)  fir.array_merge_store %v, %r to %a : !fir.ref<!fir.array<?x?xf32>>
17669825f36SValentin Clement (バレンタイン クレメン)```
17769825f36SValentin Clement (バレンタイン クレメン)
17869825f36SValentin Clement (バレンタイン クレメン)An array value update behaves as if a mapping function from the indices
17969825f36SValentin Clement (バレンタイン クレメン)to the new value has been added, replacing the previous mapping. These
18069825f36SValentin Clement (バレンタイン クレメン)mappings can be added to the ssa-value, but will not be materialized in
18169825f36SValentin Clement (バレンタイン クレメン)memory until the `fir.array_merge_store` is performed.
18269825f36SValentin Clement (バレンタイン クレメン)`fir.array_update` can be seen as an array access with a notion that the array
18369825f36SValentin Clement (バレンタイン クレメン)will be changed at the accessed position when `fir.array_merge_store` is
18469825f36SValentin Clement (バレンタイン クレメン)performed.
18569825f36SValentin Clement (バレンタイン クレメン)
18669825f36SValentin Clement (バレンタイン クレメン)## array_access
18769825f36SValentin Clement (バレンタイン クレメン)
18869825f36SValentin Clement (バレンタイン クレメン)The `array_access` provides a reference to a single element from an array value.
18969825f36SValentin Clement (バレンタイン クレメン)This is *not* a view in the immutable array, otherwise it couldn't be stored to.
19069825f36SValentin Clement (バレンタイン クレメン)It can be see as a logical copy of the element and its position in the array.
19169825f36SValentin Clement (バレンタイン クレメン)Tis reference can be written to and modified withoiut changing the original
19269825f36SValentin Clement (バレンタイン クレメン)array.
19369825f36SValentin Clement (バレンタイン クレメン)
19469825f36SValentin Clement (バレンタイン クレメン)The `array_access` operation is used to fetch the memory reference of an element
19569825f36SValentin Clement (バレンタイン クレメン)in an array value.
19669825f36SValentin Clement (バレンタイン クレメン)
19769825f36SValentin Clement (バレンタイン クレメン)```fortran
19869825f36SValentin Clement (バレンタイン クレメン)  real :: a(n,m)
19969825f36SValentin Clement (バレンタイン クレメン)  ...
20069825f36SValentin Clement (バレンタイン クレメン)  ... a ...
20169825f36SValentin Clement (バレンタイン クレメン)  ... a(r,s+1) ...
20269825f36SValentin Clement (バレンタイン クレメン)```
20369825f36SValentin Clement (バレンタイン クレメン)
20469825f36SValentin Clement (バレンタイン クレメン)One can use `fir.array_access` to recover the implied memory reference to
20569825f36SValentin Clement (バレンタイン クレメン)the element `a(i,j)` in an array expression `a` as shown above. It can also
20669825f36SValentin Clement (バレンタイン クレメン)be used to recover the reference element `a(r,s+1)` in the second
20769825f36SValentin Clement (バレンタイン クレメン)expression.
20869825f36SValentin Clement (バレンタイン クレメン)
209c226d6c8SCorentin Jabot```
21069825f36SValentin Clement (バレンタイン クレメン)  %s = fir.shape %n, %m : (index, index) -> !fir.shape<2>
21169825f36SValentin Clement (バレンタイン クレメン)  // load the entire array 'a'
21269825f36SValentin Clement (バレンタイン クレメン)  %v = fir.array_load %a(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32>
21369825f36SValentin Clement (バレンタイン クレメン)  // fetch the value of one of the array value's elements
21469825f36SValentin Clement (バレンタイン クレメン)  %1 = fir.array_access %v, %i, %j : (!fir.array<?x?xf32>, index, index) -> !fir.ref<f32>
21569825f36SValentin Clement (バレンタイン クレメン)```
21669825f36SValentin Clement (バレンタイン クレメン)
21769825f36SValentin Clement (バレンタイン クレメン)It is only possible to use `array_access` on an `array_load` result value or a
21869825f36SValentin Clement (バレンタイン クレメン)value that can be trace back transitively to an `array_load` as the dominating
21969825f36SValentin Clement (バレンタイン クレメン)source. Other array operation such as `array_amend` can be in between.
22069825f36SValentin Clement (バレンタイン クレメン)
22169825f36SValentin Clement (バレンタイン クレメン)`array_access` if mainly used with `character`'s arrays and arrays of derived
22269825f36SValentin Clement (バレンタイン クレメン)types where because they might have a non-compile time sizes that would be
22369825f36SValentin Clement (バレンタイン クレメン)useless too load entirely or too big to load.
22469825f36SValentin Clement (バレンタイン クレメン)
22569825f36SValentin Clement (バレンタイン クレメン)Here is a simple example with a `character` array assignment.
22669825f36SValentin Clement (バレンタイン クレメン)
22769825f36SValentin Clement (バレンタイン クレメン)Fortran
22869825f36SValentin Clement (バレンタイン クレメン)```
22969825f36SValentin Clement (バレンタイン クレメン)subroutine foo(c1, c2, n)
23069825f36SValentin Clement (バレンタイン クレメン)  integer(8) :: n
23169825f36SValentin Clement (バレンタイン クレメン)  character(n) :: c1(:), c2(:)
23269825f36SValentin Clement (バレンタイン クレメン)  c1 = c2
23369825f36SValentin Clement (バレンタイン クレメン)end subroutine
23469825f36SValentin Clement (バレンタイン クレメン)```
23569825f36SValentin Clement (バレンタイン クレメン)
23669825f36SValentin Clement (バレンタイン クレメン)It results in this cleaned-up FIR:
23769825f36SValentin Clement (バレンタイン クレメン)```
23869825f36SValentin 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>) {
23969825f36SValentin Clement (バレンタイン クレメン)    %0 = fir.load %arg2 : !fir.ref<i64>
24069825f36SValentin Clement (バレンタイン クレメン)    %c0 = arith.constant 0 : index
24169825f36SValentin Clement (バレンタイン クレメン)    %1:3 = fir.box_dims %arg0, %c0 : (!fir.box<!fir.array<?x!fir.char<1,?>>>, index) -> (index, index, index)
24269825f36SValentin Clement (バレンタイン クレメン)    %2 = fir.array_load %arg0 : (!fir.box<!fir.array<?x!fir.char<1,?>>>) -> !fir.array<?x!fir.char<1,?>>
24369825f36SValentin Clement (バレンタイン クレメン)    %3 = fir.array_load %arg1 : (!fir.box<!fir.array<?x!fir.char<1,?>>>) -> !fir.array<?x!fir.char<1,?>>
24469825f36SValentin Clement (バレンタイン クレメン)    %c1 = arith.constant 1 : index
24569825f36SValentin Clement (バレンタイン クレメン)    %4 = arith.subi %1#1, %c1 : index
24669825f36SValentin Clement (バレンタイン クレメン)    %5 = fir.do_loop %arg3 = %c0 to %4 step %c1 unordered iter_args(%arg4 = %2) -> (!fir.array<?x!fir.char<1,?>>) {
24769825f36SValentin Clement (バレンタイン クレメン)      %6 = fir.array_access %3, %arg3 : (!fir.array<?x!fir.char<1,?>>, index) -> !fir.ref<!fir.char<1,?>>
24869825f36SValentin Clement (バレンタイン クレメン)      %7 = fir.array_access %arg4, %arg3 : (!fir.array<?x!fir.char<1,?>>, index) -> !fir.ref<!fir.char<1,?>>
24969825f36SValentin Clement (バレンタイン クレメン)      %false = arith.constant false
25069825f36SValentin Clement (バレンタイン クレメン)      %8 = fir.convert %7 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8>
25169825f36SValentin Clement (バレンタイン クレメン)      %9 = fir.convert %6 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8>
25269825f36SValentin Clement (バレンタイン クレメン)      fir.call @llvm.memmove.p0i8.p0i8.i64(%8, %9, %0, %false) : (!fir.ref<i8>, !fir.ref<i8>, i64, i1) -> ()
25369825f36SValentin Clement (バレンタイン クレメン)      %10 = fir.array_amend %arg4, %7 : (!fir.array<?x!fir.char<1,?>>, !fir.ref<!fir.char<1,?>>) -> !fir.array<?x!fir.char<1,?>>
25469825f36SValentin Clement (バレンタイン クレメン)      fir.result %10 : !fir.array<?x!fir.char<1,?>>
25569825f36SValentin Clement (バレンタイン クレメン)    }
25669825f36SValentin 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,?>>>
25769825f36SValentin Clement (バレンタイン クレメン)    return
25869825f36SValentin Clement (バレンタイン クレメン)  }
25969825f36SValentin Clement (バレンタイン クレメン)  func private @llvm.memmove.p0i8.p0i8.i64(!fir.ref<i8>, !fir.ref<i8>, i64, i1)
26069825f36SValentin Clement (バレンタイン クレメン)}
26169825f36SValentin Clement (バレンタイン クレメン)```
26269825f36SValentin Clement (バレンタイン クレメン)
26369825f36SValentin Clement (バレンタイン クレメン)`fir.array_access` and `fir.array_amend` split the two purposes of
26469825f36SValentin Clement (バレンタイン クレメン)`fir.array_update` into two distinct operations to work on type/kind that must
26569825f36SValentin Clement (バレンタイン クレメン)reside in the memory reference domain. `fir.array_access` captures the array
26669825f36SValentin Clement (バレンタイン クレメン)access semantics and `fir.array_amend` denotes which `fir.array_access` is the
26769825f36SValentin Clement (バレンタイン クレメン)lhs.
26869825f36SValentin Clement (バレンタイン クレメン)
26969825f36SValentin Clement (バレンタイン クレメン)We do not want to start loading the entire `!fir.ref<!fir.char<1,?>>` here since
27069825f36SValentin Clement (バレンタイン クレメン)it has dynamic length, and even if constant, could be too long to do so.
27169825f36SValentin Clement (バレンタイン クレメン)
27269825f36SValentin Clement (バレンタイン クレメン)## array_amend
27369825f36SValentin Clement (バレンタイン クレメン)
27469825f36SValentin Clement (バレンタイン クレメン)The `array_amend` operation marks an array value as having been changed via a
27569825f36SValentin Clement (バレンタイン クレメン)reference obtain by an `array_access`. It acts as a logical transaction log
27669825f36SValentin Clement (バレンタイン クレメン)that is used to merge the final result back with an `array_merge_store`
27769825f36SValentin Clement (バレンタイン クレメン)operation.
27869825f36SValentin Clement (バレンタイン クレメン)
279c226d6c8SCorentin Jabot```
28069825f36SValentin Clement (バレンタイン クレメン)  // fetch the value of one of the array value's elements
28169825f36SValentin Clement (バレンタイン クレメン)  %1 = fir.array_access %v, %i, %j : (!fir.array<?x?xT>, index, index) -> !fir.ref<T>
28269825f36SValentin Clement (バレンタイン クレメン)  // modify the element by storing data using %1 as a reference
28369825f36SValentin Clement (バレンタイン クレメン)  %2 = ... %1 ...
28469825f36SValentin Clement (バレンタイン クレメン)  // mark the array value
28569825f36SValentin Clement (バレンタイン クレメン)  %new_v = fir.array_amend %v, %2 : (!fir.array<?x?xT>, !fir.ref<T>) -> !fir.array<?x?xT>
28669825f36SValentin Clement (バレンタイン クレメン)```
28769825f36SValentin Clement (バレンタイン クレメン)
28869825f36SValentin Clement (バレンタイン クレメン)## Example
28969825f36SValentin Clement (バレンタイン クレメン)
29069825f36SValentin Clement (バレンタイン クレメン)Here is an example of a FIR code using several array operations together. The
29169825f36SValentin Clement (バレンタイン クレメン)example below is a simplified version of the FIR code comiing from the
29269825f36SValentin Clement (バレンタイン クレメン)following Fortran code snippet.
29369825f36SValentin Clement (バレンタイン クレメン)
29469825f36SValentin Clement (バレンタイン クレメン)```fortran
29569825f36SValentin Clement (バレンタイン クレメン)subroutine s(a,l,u)
29669825f36SValentin Clement (バレンタイン クレメン)  type t
29769825f36SValentin Clement (バレンタイン クレメン)    integer m
29869825f36SValentin Clement (バレンタイン クレメン)  end type t
29969825f36SValentin Clement (バレンタイン クレメン)  type(t) :: a(:)
30069825f36SValentin Clement (バレンタイン クレメン)  integer :: l, u
30169825f36SValentin Clement (バレンタイン クレメン)  forall (i=l:u)
30269825f36SValentin Clement (バレンタイン クレメン)    a(i) = a(u-i+1)
30369825f36SValentin Clement (バレンタイン クレメン)  end forall
30469825f36SValentin Clement (バレンタイン クレメン)end
30569825f36SValentin Clement (バレンタイン クレメン)```
30669825f36SValentin Clement (バレンタイン クレメン)
30769825f36SValentin Clement (バレンタイン クレメン)```
30869825f36SValentin Clement (バレンタイン クレメン)func @_QPs(%arg0: !fir.box<!fir.array<?x!fir.type<_QFsTt{m:i32}>>>, %arg1: !fir.ref<i32>, %arg2: !fir.ref<i32>) {
30969825f36SValentin Clement (バレンタイン クレメン)  %l = fir.load %arg1 : !fir.ref<i32>
31069825f36SValentin Clement (バレンタイン クレメン)  %l_index = fir.convert %l : (i32) -> index
31169825f36SValentin Clement (バレンタイン クレメン)  %u = fir.load %arg2 : !fir.ref<i32>
31269825f36SValentin Clement (バレンタイン クレメン)  %u_index = fir.convert %u : (i32) -> index
31369825f36SValentin Clement (バレンタイン クレメン)  %c1 = arith.constant 1 : index
31469825f36SValentin Clement (バレンタイン クレメン)  // This is the "copy-in" array used on the RHS of the expression. It will be indexed into and loaded at each iteration.
31569825f36SValentin 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}>>
31669825f36SValentin Clement (バレンタイン クレメン)
31769825f36SValentin Clement (バレンタイン クレメン)  // This is the "seed" for the "copy-out" array on the LHS. It'll flow from iteration to iteration and gets
31869825f36SValentin Clement (バレンタイン クレメン)  // updated at each iteration.
31969825f36SValentin 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}>>
32069825f36SValentin Clement (バレンタイン クレメン)
32169825f36SValentin 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}>>) {
32269825f36SValentin Clement (バレンタイン クレメン)    // Compute indexing for the RHS and array the element.
32369825f36SValentin Clement (バレンタイン クレメン)    %u_minus_i = arith.subi %u_index, %i : index // u-i
32469825f36SValentin Clement (バレンタイン クレメン)    %u_minus_i_plus_one = arith.addi %u_minus_i, %c1: index // u-i+1
32569825f36SValentin 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}>>
32669825f36SValentin Clement (バレンタイン クレメン)    %a_src_elt = fir.load %a_src_ref : !fir.ref<!fir.type<_QFsTt{m:i32}>>
32769825f36SValentin Clement (バレンタイン クレメン)
32869825f36SValentin Clement (バレンタイン クレメン)    // Get the reference to the element in the array on the LHS
32969825f36SValentin 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}>>
33069825f36SValentin Clement (バレンタイン クレメン)
33169825f36SValentin Clement (バレンタイン クレメン)    // Store the value, and update the array
33269825f36SValentin Clement (バレンタイン クレメン)    fir.store %a_src_elt to %a_dst_ref : !fir.ref<!fir.type<_QFsTt{m:i32}>>
33369825f36SValentin 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}>>
33469825f36SValentin Clement (バレンタイン クレメン)
33569825f36SValentin Clement (バレンタイン クレメン)    // Forward the current updated array to the next iteration.
33669825f36SValentin Clement (バレンタイン クレメン)    fir.result %updated_array_a : !fir.array<?x!fir.type<_QFsTt{m:i32}>>
33769825f36SValentin Clement (バレンタイン クレメン)  }
33869825f36SValentin Clement (バレンタイン クレメン)  // Store back the result by merging the initial value loaded before the loop
33969825f36SValentin Clement (バレンタイン クレメン)  // with the final one produced by the loop.
34069825f36SValentin 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}>>>
34169825f36SValentin Clement (バレンタイン クレメン)  return
34269825f36SValentin Clement (バレンタイン クレメン)}
34369825f36SValentin Clement (バレンタイン クレメン)```
344