[flang-commits] [flang] [flang] Allow `VariableAssignBufferization` to handle `hlfir::ExprType` (PR #115136)
via flang-commits
flang-commits at lists.llvm.org
Wed Nov 6 00:50:52 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-fir-hlfir
Author: Kareem Ergawy (ergawy)
<details>
<summary>Changes</summary>
Assume you are 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
```
---
Full diff: https://github.com/llvm/llvm-project/pull/115136.diff
2 Files Affected:
- (modified) flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp (+9-5)
- (modified) flang/test/HLFIR/opt-bufferization.fir (+42)
``````````diff
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp b/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp
index 7553e05b470634..c235e07596224f 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp
@@ -594,15 +594,19 @@ class VariableAssignBufferization
llvm::LogicalResult VariableAssignBufferization::matchAndRewrite(
hlfir::AssignOp assign, mlir::PatternRewriter &rewriter) const {
+
if (assign.isAllocatableAssignment())
return rewriter.notifyMatchFailure(assign, "AssignOp may imply allocation");
hlfir::Entity rhs{assign.getRhs()};
- // TODO: ExprType check is here to avoid conflicts with
- // ElementalAssignBufferization pattern. We need to combine
- // these matchers into a single one that applies to AssignOp.
- if (mlir::isa<hlfir::ExprType>(rhs.getType()))
- return rewriter.notifyMatchFailure(assign, "RHS is not in memory");
+
+ // To avoid conflicts with ElementalAssignBufferization pattern, we avoid
+ // matching RHS when it is an `ExprType` defined by an `ElementalOp`; which is
+ // among the main criteria matched by ElementalAssignBufferization.
+ if (mlir::isa<hlfir::ExprType>(rhs.getType()) &&
+ mlir::isa<hlfir::ElementalOp>(rhs.getDefiningOp()))
+ return rewriter.notifyMatchFailure(
+ assign, "RHS is an ExprType defined by ElementalOp");
if (!rhs.isArray())
return rewriter.notifyMatchFailure(assign,
diff --git a/flang/test/HLFIR/opt-bufferization.fir b/flang/test/HLFIR/opt-bufferization.fir
index faa8f4bcdb7789..57ecc448e173a9 100644
--- a/flang/test/HLFIR/opt-bufferization.fir
+++ b/flang/test/HLFIR/opt-bufferization.fir
@@ -796,3 +796,45 @@ func.func @_QPddx(%arg0: !fir.box<!fir.array<?x?xf64>> {fir.bindc_name = "array"
// CHECK: %[[VAL_61:.*]] = fir.load %[[VAL_26]]#1 : !fir.ref<!fir.array<?x?xf64>>
// CHECK: return %[[VAL_61]] : !fir.array<?x?xf64>
// CHECK: }
+
+// `hlfir.expr` bufferization (when the expresion is not the result of
+// `hlfir.elemental`
+func.func @_QPfoo() {
+ %c1 = arith.constant 1 : index
+ %0 = fir.alloca !fir.array<1xi32> {bindc_name = "iavs", uniq_name = "_QFfooEiavs"}
+ %1 = fir.shape %c1 : (index) -> !fir.shape<1>
+ %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>>)
+ %3 = fir.alloca i32 {bindc_name = "iv", uniq_name = "_QFfooEiv"}
+ %4:2 = hlfir.declare %3 {uniq_name = "_QFfooEiv"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+ %c10_i32 = arith.constant 10 : i32
+ %6 = fir.convert %c10_i32 : (i32) -> index
+ %7 = fir.convert %c1 : (index) -> i32
+ %8:2 = fir.do_loop %arg0 = %c1 to %6 step %c1 iter_args(%arg1 = %7) -> (index, i32) {
+ fir.store %arg1 to %4#1 : !fir.ref<i32>
+ %9 = fir.allocmem !fir.array<1xi32> {bindc_name = ".tmp.arrayctor", uniq_name = ""}
+ %10 = fir.shape %c1 : (index) -> !fir.shape<1>
+ %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>>)
+ %12 = fir.load %4#0 : !fir.ref<i32>
+ %13 = hlfir.designate %11#0 (%c1) : (!fir.heap<!fir.array<1xi32>>, index) -> !fir.ref<i32>
+ hlfir.assign %12 to %13 : i32, !fir.ref<i32>
+ %true = arith.constant true
+ %14 = hlfir.as_expr %11#0 move %true : (!fir.heap<!fir.array<1xi32>>, i1) -> !hlfir.expr<1xi32>
+ hlfir.assign %14 to %2#0 : !hlfir.expr<1xi32>, !fir.ref<!fir.array<1xi32>>
+ hlfir.destroy %14 : !hlfir.expr<1xi32>
+ %15 = arith.addi %arg0, %c1 : index
+ %16 = fir.convert %c1 : (index) -> i32
+ %17 = fir.load %4#1 : !fir.ref<i32>
+ %18 = arith.addi %17, %16 : i32
+ fir.result %15, %18 : index, i32
+ }
+ fir.store %8#1 to %4#1 : !fir.ref<i32>
+ return
+}
+
+// CHECK-LABEL: func.func @_QPfoo
+// CHECK: %[[C1:.*]] = arith.constant 1 : index
+// CHECK: fir.do_loop {{.*}} {
+// CHECK-NOT: hlfir.assign %{{.*}} to %{{.*}}#0 : !hlfir.expr<1xi32>, !fir.ref<!fir.array<1xi32>>
+// CHECK: fir.do_loop %{{.*}} = %[[C1]] to %[[C1]] step %[[C1]] unordered {
+// CHECK: }
+// CHECK: }
``````````
</details>
https://github.com/llvm/llvm-project/pull/115136
More information about the flang-commits
mailing list