[all-commits] [llvm/llvm-project] 73026a: [flang] Changed lowering for allocatable assignmen...

Slava Zakharin via All-commits all-commits at lists.llvm.org
Fri Jul 8 09:47:50 PDT 2022


  Branch: refs/heads/main
  Home:   https://github.com/llvm/llvm-project
  Commit: 73026a4fbf7095613df4f8c205912cfc1485ed7d
      https://github.com/llvm/llvm-project/commit/73026a4fbf7095613df4f8c205912cfc1485ed7d
  Author: Slava Zakharin <szakharin at nvidia.com>
  Date:   2022-07-08 (Fri, 08 Jul 2022)

  Changed paths:
    M flang/include/flang/Optimizer/Builder/MutableBox.h
    M flang/lib/Lower/ConvertExpr.cpp
    M flang/lib/Optimizer/Builder/MutableBox.cpp
    M flang/lib/Optimizer/Transforms/ArrayValueCopy.cpp
    M flang/test/Lower/allocatable-assignment.f90

  Log Message:
  -----------
  [flang] Changed lowering for allocatable assignment to make array-value-copy correct.

Array-value-copy fails to generate a temporary array for case like this:
subroutine bug(b)
  real, allocatable :: b(:)
  b = b(2:1:-1)
end subroutine

Since LHS may need to be reallocated, lowering produces the following FIR:
%rhs_load = fir.array_load %b %slice

%lhs_mem = fir.if %b_is_allocated_with_right_shape {
   fir.result %b
} else {
   %new_storage = fir.allocmem %rhs_shape
   fir.result %new_storage
}

%lhs = fir.array_load %lhs_mem
%loop = fir.do_loop {
 ....
}
fir.array_merge_store %lhs, %loop to %lhs_mem
// deallocate old storage if reallocation occured,
// and update b descriptor if needed.

Since %b in array_load and %lhs_mem in array_merge_store are not the same SSA
values, array-value-copy does not detect the conflict and does not produce
a temporary array. This causes incorrect result in runtime.

The suggested change in lowering is to generate this:
%rhs_load = fir.array_load %b %slice
%lhs_mem = fir.if %b_is_allocated_with_right_shape {
   %lhs = fir.array_load %b
   %loop = fir.do_loop {
      ....
   }
   fir.array_merge_store %lhs, %loop to %b
   fir.result %b
} else {
   %new_storage = fir.allocmem %rhs_shape
   %lhs = fir.array_load %new_storage
   %loop = fir.do_loop {
      ....
   }
   fir.array_merge_store %lhs, %loop to %new_storage
   fir.result %new_storage
}
// deallocate old storage if reallocation occured,
// and update b descriptor if needed.

Note that there are actually 3 branches in FIR, so the assignment loops
are currently produced in three copies, which is a code-size issue.
It is possible to generate just two branches with two copies of the loops,
but it is not addressed in this change-set.

Differential Revision: https://reviews.llvm.org/D129314




More information about the All-commits mailing list