Skip to content

Commit 3c585bd

Browse files
authored
[flang] Allow VariableAssignBufferization to handle hlfir::ExprType (#115136)
Given the following input: ```fortran 1. subroutine ComputeDifferencesKernel 2. implicit none 3. integer :: i 4. integer, dimension(1) :: a 5. 6. do i = 1, 10 7. a = [ i ] 8. end do 9. end subroutine ComputeDifferencesKernel ``` Currently, the assignment in line 7 ends up as a call to the Fortran runtime function: `AAssign` since the corresponding `hlfir.assign` is not optimized away by `VariableAssignBufferization`. The reason this assignment is not optimized away is that `VariableAssignBufferization` does not match whenever the RHS of the assignment is a `hlfir.expr` value. However, this behavior is introduced only to prevent clashes between `VariableAssignBufferization` and `ElementalAssignBufferization` which optimizes away assignemnts that result from `hlfir.elemental` ops. This patch relaxes that restriction by checking whether the RHS of an `hlfir.assign` is the result of `hlfir.elemental` or not. If not, we can safely proceed with `VariableAssignBufferization`. Note that in the above example, we won't get a `hlfir.elemental` in the IR. We would get if we changed line 7 to something like: ```fortran 7. a = [ i ] + b ``` In which case, `ElementalAssignBufferization` will kick in instead.
1 parent e65c542 commit 3c585bd

File tree

2 files changed

+50
-5
lines changed

2 files changed

+50
-5
lines changed

flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp

+8-5
Original file line numberDiff line numberDiff line change
@@ -598,11 +598,14 @@ llvm::LogicalResult VariableAssignBufferization::matchAndRewrite(
598598
return rewriter.notifyMatchFailure(assign, "AssignOp may imply allocation");
599599

600600
hlfir::Entity rhs{assign.getRhs()};
601-
// TODO: ExprType check is here to avoid conflicts with
602-
// ElementalAssignBufferization pattern. We need to combine
603-
// these matchers into a single one that applies to AssignOp.
604-
if (mlir::isa<hlfir::ExprType>(rhs.getType()))
605-
return rewriter.notifyMatchFailure(assign, "RHS is not in memory");
601+
602+
// To avoid conflicts with ElementalAssignBufferization pattern, we avoid
603+
// matching RHS when it is an `ExprType` defined by an `ElementalOp`; which is
604+
// among the main criteria matched by ElementalAssignBufferization.
605+
if (mlir::isa<hlfir::ExprType>(rhs.getType()) &&
606+
mlir::isa<hlfir::ElementalOp>(rhs.getDefiningOp()))
607+
return rewriter.notifyMatchFailure(
608+
assign, "RHS is an ExprType defined by ElementalOp");
606609

607610
if (!rhs.isArray())
608611
return rewriter.notifyMatchFailure(assign,

flang/test/HLFIR/opt-bufferization.fir

+42
Original file line numberDiff line numberDiff line change
@@ -796,3 +796,45 @@ func.func @_QPddx(%arg0: !fir.box<!fir.array<?x?xf64>> {fir.bindc_name = "array"
796796
// CHECK: %[[VAL_61:.*]] = fir.load %[[VAL_26]]#1 : !fir.ref<!fir.array<?x?xf64>>
797797
// CHECK: return %[[VAL_61]] : !fir.array<?x?xf64>
798798
// CHECK: }
799+
800+
// `hlfir.expr` bufferization (when the expresion is not the result of
801+
// `hlfir.elemental`)
802+
func.func @_QPfoo() {
803+
%c1 = arith.constant 1 : index
804+
%0 = fir.alloca !fir.array<1xi32> {bindc_name = "iavs", uniq_name = "_QFfooEiavs"}
805+
%1 = fir.shape %c1 : (index) -> !fir.shape<1>
806+
%2:2 = hlfir.declare %0(%1) {uniq_name = "_QFfooEiavs"} : (!fir.ref<!fir.array<1xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<1xi32>>, !fir.ref<!fir.array<1xi32>>)
807+
%3 = fir.alloca i32 {bindc_name = "iv", uniq_name = "_QFfooEiv"}
808+
%4:2 = hlfir.declare %3 {uniq_name = "_QFfooEiv"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
809+
%c10_i32 = arith.constant 10 : i32
810+
%6 = fir.convert %c10_i32 : (i32) -> index
811+
%7 = fir.convert %c1 : (index) -> i32
812+
%8:2 = fir.do_loop %arg0 = %c1 to %6 step %c1 iter_args(%arg1 = %7) -> (index, i32) {
813+
fir.store %arg1 to %4#1 : !fir.ref<i32>
814+
%9 = fir.allocmem !fir.array<1xi32> {bindc_name = ".tmp.arrayctor", uniq_name = ""}
815+
%10 = fir.shape %c1 : (index) -> !fir.shape<1>
816+
%11:2 = hlfir.declare %9(%10) {uniq_name = ".tmp.arrayctor"} : (!fir.heap<!fir.array<1xi32>>, !fir.shape<1>) -> (!fir.heap<!fir.array<1xi32>>, !fir.heap<!fir.array<1xi32>>)
817+
%12 = fir.load %4#0 : !fir.ref<i32>
818+
%13 = hlfir.designate %11#0 (%c1) : (!fir.heap<!fir.array<1xi32>>, index) -> !fir.ref<i32>
819+
hlfir.assign %12 to %13 : i32, !fir.ref<i32>
820+
%true = arith.constant true
821+
%14 = hlfir.as_expr %11#0 move %true : (!fir.heap<!fir.array<1xi32>>, i1) -> !hlfir.expr<1xi32>
822+
hlfir.assign %14 to %2#0 : !hlfir.expr<1xi32>, !fir.ref<!fir.array<1xi32>>
823+
hlfir.destroy %14 : !hlfir.expr<1xi32>
824+
%15 = arith.addi %arg0, %c1 : index
825+
%16 = fir.convert %c1 : (index) -> i32
826+
%17 = fir.load %4#1 : !fir.ref<i32>
827+
%18 = arith.addi %17, %16 : i32
828+
fir.result %15, %18 : index, i32
829+
}
830+
fir.store %8#1 to %4#1 : !fir.ref<i32>
831+
return
832+
}
833+
834+
// CHECK-LABEL: func.func @_QPfoo
835+
// CHECK: %[[C1:.*]] = arith.constant 1 : index
836+
// CHECK: fir.do_loop {{.*}} {
837+
// CHECK-NOT: hlfir.assign %{{.*}} to %{{.*}}#0 : !hlfir.expr<1xi32>, !fir.ref<!fir.array<1xi32>>
838+
// CHECK: fir.do_loop %{{.*}} = %[[C1]] to %[[C1]] step %[[C1]] unordered {
839+
// CHECK: }
840+
// CHECK: }

0 commit comments

Comments
 (0)