[flang-commits] [flang] [flang] Allow `VariableAssignBufferization` to handle `hlfir::ExprType` (PR #115136)

Kareem Ergawy via flang-commits flang-commits at lists.llvm.org
Thu Nov 7 21:02:19 PST 2024


https://github.com/ergawy updated https://github.com/llvm/llvm-project/pull/115136

>From 37f581f36511dcb3a32e8c16847e0589bf1fd187 Mon Sep 17 00:00:00 2001
From: ergawy <kareem.ergawy at amd.com>
Date: Wed, 6 Nov 2024 02:41:35 -0600
Subject: [PATCH] [flang] Allow `VariableAssignBufferization` to handle
 `hlfir::ExprType`

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
```
---
 .../Transforms/OptimizedBufferization.cpp     | 13 +++---
 flang/test/HLFIR/opt-bufferization.fir        | 42 +++++++++++++++++++
 2 files changed, 50 insertions(+), 5 deletions(-)

diff --git a/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp b/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp
index 7553e05b470634..d05a3258cf293c 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp
@@ -598,11 +598,14 @@ llvm::LogicalResult VariableAssignBufferization::matchAndRewrite(
     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..87afb3cc924533 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:           }



More information about the flang-commits mailing list