[PATCH] D115077: [fir] Add array operations documentation

Valentin Clement via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 22 14:07:32 PST 2021


clementval added inline comments.


================
Comment at: flang/docs/FIRArrayOperations.md:195
+  %new_v = fir.array_amend %v, %2 : (!fir.array<?x?xT>, !fir.ref<T>) -> !fir.array<?x?xT>
+```
+
----------------
mehdi_amini wrote:
> clementval wrote:
> > mehdi_amini wrote:
> > > clementval wrote:
> > > > mehdi_amini wrote:
> > > > > I wonder why array_amend is needed at all actually.
> > > > > When can't it just be replaced with a load of the `ref<T>` and an `array_update`?
> > > > In some cases we do not want to load derived types/characters because they may have non-compile time constant sizes (cannot be loaded/might be big aggregates for which load/store is problematic (cause long LLVM compile time + asserts at a certain point).
> > > Can you document this with an example illustrating such a case?
> > Here is an example with character assignment. 
> > 
> > Fortran
> > ```
> > subroutine foo(c1, c2, n)
> >   integer(8) :: n
> >   character(n) :: c1(:), c2(:)
> >   c1 = c2
> > end subroutine
> > ```
> > 
> > That would results in a cleaned-up FIR that looks like this:
> > 
> > ```
> > func @_QPfoo(%arg0: !fir.box<!fir.array<?x!fir.char<1,?>>>, %arg1: !fir.box<!fir.array<?x!fir.char<1,?>>>, %arg2: !fir.ref<i64>) {
> >     %0 = fir.load %arg2 : !fir.ref<i64>
> >     %c0 = arith.constant 0 : index
> >     %1:3 = fir.box_dims %arg0, %c0 : (!fir.box<!fir.array<?x!fir.char<1,?>>>, index) -> (index, index, index)
> >     %2 = fir.array_load %arg0 : (!fir.box<!fir.array<?x!fir.char<1,?>>>) -> !fir.array<?x!fir.char<1,?>>
> >     %3 = fir.array_load %arg1 : (!fir.box<!fir.array<?x!fir.char<1,?>>>) -> !fir.array<?x!fir.char<1,?>>
> >     %c1 = arith.constant 1 : index
> >     %4 = arith.subi %1#1, %c1 : index
> >     %5 = fir.do_loop %arg3 = %c0 to %4 step %c1 unordered iter_args(%arg4 = %2) -> (!fir.array<?x!fir.char<1,?>>) {
> >       %6 = fir.array_access %3, %arg3 : (!fir.array<?x!fir.char<1,?>>, index) -> !fir.ref<!fir.char<1,?>>
> >       %7 = fir.array_access %arg4, %arg3 : (!fir.array<?x!fir.char<1,?>>, index) -> !fir.ref<!fir.char<1,?>>
> >       %false = arith.constant false
> >       %8 = fir.convert %7 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8>
> >       %9 = fir.convert %6 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8>
> >       fir.call @llvm.memmove.p0i8.p0i8.i64(%8, %9, %0, %false) : (!fir.ref<i8>, !fir.ref<i8>, i64, i1) -> ()
> >       %10 = fir.array_amend %arg4, %7 : (!fir.array<?x!fir.char<1,?>>, !fir.ref<!fir.char<1,?>>) -> !fir.array<?x!fir.char<1,?>>
> >       fir.result %10 : !fir.array<?x!fir.char<1,?>>
> >     }
> >     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,?>>>
> >     return
> >   }
> >   func private @llvm.memmove.p0i8.p0i8.i64(!fir.ref<i8>, !fir.ref<i8>, i64, i1)
> > } 
> > ```
> > 
> > We do not want to start loading `!fir.ref<!fir.char<1,?>>` here because it has dynamic length, and even if constant, could be way too long.
> Uh, I'm not totally understanding all the pieces here, in particular you're converting the references to `!fir.char<1,?>` to simple i8 reference and use the N arguments for the memmove size, but at the same time you're saying that they are dynamic length.
> 
> >  if constant, could be way too long.
> 
> You're saying that basically `array_amend` is a fused form of `load`+`update` because the optimizer bails out and can't reconstruct the fused form later in the lowering?
> 
> 
> All of this may be fine: it just deserves a lot of documentation I think.
`array_update` serves two purposes: it is an array access, and it denotes the array as being changed. The lhs is distinguished from everything on the rhs.

Fortran arrays are implicitly memory bound as are some other Fortran type/kind entities. For entities that can be atomically promoted to the value domain, we use `array_fetch` and `array_update`. For those type/kinds that cannot be promoted to values, we must leave them in a memory reference domain, and we use `array_access` and `array_amend`.

`array_access` and `array_amend` split the two purposes of `array_update` into two distinct ops. `array_access` captures the array access semantics and `array_amend` denotes which `array_access` is the lhs.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D115077/new/

https://reviews.llvm.org/D115077



More information about the llvm-commits mailing list