[flang-commits] [flang] Reapply "[flang] Lowering a ArrayCoorOp to arithmetic computations" (PR #182585)

Susan Tan ス-ザン タン via flang-commits flang-commits at lists.llvm.org
Fri Feb 20 12:09:58 PST 2026


https://github.com/SusanTan created https://github.com/llvm/llvm-project/pull/182585

Reapplying the changes. Reverted it wrongly yesterdya.

This reverts commit 3c6523dcb8ebc0396f69c578285599b66e16dce7.

>From f2ee231a9b81f735ad2a32fbac50ed673875ce95 Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Fri, 20 Feb 2026 11:57:41 -0800
Subject: [PATCH] =?UTF-8?q?Reapply=20"[flang]=20Lowering=20a=20ArrayCoorOp?=
 =?UTF-8?q?=20to=20arithmetic=20computations=20whe=E2=80=A6=20(#182365)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This reverts commit 3c6523dcb8ebc0396f69c578285599b66e16dce7.
---
 .../lib/Optimizer/Transforms/FIRToMemRef.cpp  | 29 +++++++++----------
 .../FIRToMemRef/array-coor-block-arg.mlir     | 28 ++++++++++++++++++
 .../Transforms/FIRToMemRef/no-declare.mlir    | 13 +++++----
 3 files changed, 49 insertions(+), 21 deletions(-)
 create mode 100644 flang/test/Transforms/FIRToMemRef/array-coor-block-arg.mlir

diff --git a/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp b/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp
index bf125eb8d04ef..e8c30e62430c0 100644
--- a/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp
+++ b/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp
@@ -459,22 +459,22 @@ FIRToMemRef::convertArrayCoorOp(Operation *memOp, fir::ArrayCoorOp arrayCoorOp,
   if (typeConverter.isEmptyArray(firMemref.getType()))
     return failure();
 
-  if (auto blockArg = dyn_cast<BlockArgument>(firMemref)) {
-    Value elemRef = arrayCoorOp.getResult();
-    rewriter.setInsertionPointAfter(arrayCoorOp);
-    Location loc = arrayCoorOp->getLoc();
-    Type elemMemrefTy = typeConverter.convertMemrefType(elemRef.getType());
-    Value converted =
-        fir::ConvertOp::create(rewriter, loc, elemMemrefTy, elemRef);
-    SmallVector<Value> indices;
-    return std::pair{converted, indices};
-  }
-
-  Operation *memref = firMemref.getDefiningOp();
+  Location loc = arrayCoorOp->getLoc();
 
+  // Prefer lowering the array-coordinates computation to a memref + indices.
+  // This allows erasing fir.array_coor when it is only used by load/store even
+  // if the base address is a block argument (e.g. region arguments).
+  Operation *memref = nullptr;
   FailureOr<Value> converted;
-  if (enableFIRConvertOptimizations && isMarshalLike(memref) &&
-      !fir::isa_fir_type(firMemref.getType())) {
+  if (auto blockArg = dyn_cast<BlockArgument>(firMemref)) {
+    rewriter.setInsertionPoint(arrayCoorOp);
+    Type memrefTy = typeConverter.convertMemrefType(blockArg.getType());
+    converted =
+        fir::ConvertOp::create(rewriter, loc, memrefTy, blockArg).getResult();
+    rewriter.setInsertionPointAfter(arrayCoorOp);
+  } else if ((memref = firMemref.getDefiningOp()) &&
+             enableFIRConvertOptimizations && isMarshalLike(memref) &&
+             !fir::isa_fir_type(firMemref.getType())) {
     converted = firMemref;
     rewriter.setInsertionPoint(arrayCoorOp);
   } else {
@@ -504,7 +504,6 @@ FIRToMemRef::convertArrayCoorOp(Operation *memOp, fir::ArrayCoorOp arrayCoorOp,
     rewriter.setInsertionPointAfter(arrayCoorOp);
   }
 
-  Location loc = arrayCoorOp->getLoc();
   Value one = arith::ConstantIndexOp::create(rewriter, loc, 1);
   FailureOr<SmallVector<Value>> failureOrIndices =
       getMemrefIndices(arrayCoorOp, memref, rewriter, *converted, one);
diff --git a/flang/test/Transforms/FIRToMemRef/array-coor-block-arg.mlir b/flang/test/Transforms/FIRToMemRef/array-coor-block-arg.mlir
new file mode 100644
index 0000000000000..7e0acbae78af4
--- /dev/null
+++ b/flang/test/Transforms/FIRToMemRef/array-coor-block-arg.mlir
@@ -0,0 +1,28 @@
+// Verify fir.array_coor lowering when the base is a block argument.
+// This used to take a shortcut (convert the element ref result) which kept the
+// fir.array_coor alive. We prefer converting the base to a memref and
+// computing indices so that fir.array_coor can be erased when only used by
+// load/store.
+//
+// RUN: fir-opt %s --fir-to-memref --allow-unregistered-dialect | FileCheck %s
+
+func.func @block_arg_memref(%arg0: !fir.ref<!fir.array<32xi32>>) {
+  %c32 = arith.constant 32 : index
+  %c1 = arith.constant 1 : index
+  %c1_i32 = arith.constant 1 : i32
+  %shape = fir.shape %c32 : (index) -> !fir.shape<1>
+  %elt = fir.array_coor %arg0(%shape) %c1 : (!fir.ref<!fir.array<32xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
+  fir.store %c1_i32 to %elt : !fir.ref<i32>
+  return
+}
+
+// CHECK-LABEL: func.func @block_arg_memref
+// CHECK:       [[BASE:%.+]] = fir.convert %arg0 : (!fir.ref<!fir.array<32xi32>>) -> memref<32xi32>
+// CHECK:       [[ONE:%.+]] = arith.constant 1 : index
+// CHECK:       [[SUB:%.+]] = arith.subi %c1, [[ONE]] : index
+// CHECK:       [[MUL:%.+]] = arith.muli [[SUB]], [[ONE]] : index
+// CHECK:       [[SUB2:%.+]] = arith.subi [[ONE]], [[ONE]] : index
+// CHECK:       [[IDX:%.+]] = arith.addi [[MUL]], [[SUB2]] : index
+// CHECK:       memref.store {{%.+}}, [[BASE]][[[IDX]]] : memref<32xi32>
+// CHECK-NOT:   fir.array_coor
+
diff --git a/flang/test/Transforms/FIRToMemRef/no-declare.mlir b/flang/test/Transforms/FIRToMemRef/no-declare.mlir
index 664da0a0b38a2..3971e2552ce56 100644
--- a/flang/test/Transforms/FIRToMemRef/no-declare.mlir
+++ b/flang/test/Transforms/FIRToMemRef/no-declare.mlir
@@ -5,15 +5,15 @@
 // CHECK-LABEL:   func.func @nodeclare
 // CHECK:         %[[C1:.*]] = arith.constant 1 : index
 // CHECK:         %[[SHAPE:.*]] = fir.shape %[[C1]] : (index) -> !fir.shape<1>
-// CHECK:         %[[COOR:.*]] = fir.array_coor %arg0(%[[SHAPE]]) %[[C1]] : (!fir.ref<!fir.array<1xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
-// CHECK:         %[[C0:.*]] = fir.convert %[[COOR]] : (!fir.ref<i32>) -> memref<i32>
-// CHECK:         %[[C1M:.*]] = fir.convert %[[COOR]] : (!fir.ref<i32>) -> memref<i32>
-// CHECK:         %[[L0:.*]] = memref.load %[[C1M]][] : memref<i32>
+// CHECK:         %[[M0:.*]] = fir.convert %arg0 : (!fir.ref<!fir.array<1xi32>>) -> memref<1xi32>
+// CHECK:         %[[M1:.*]] = fir.convert %arg0 : (!fir.ref<!fir.array<1xi32>>) -> memref<1xi32>
+// CHECK:         %[[L0:.*]] = memref.load %[[M0]][%{{.*}}] : memref<1xi32>
 // CHECK:         %[[CARG1:.*]] = fir.convert %arg1 : (!fir.ref<i32>) -> memref<i32>
 // CHECK:         memref.store %[[L0]], %[[CARG1]][] : memref<i32>
-// CHECK:         %[[L1:.*]] = memref.load %[[C0]][] : memref<i32>
+// CHECK:         %[[L1:.*]] = memref.load %[[M1]][%{{.*}}] : memref<1xi32>
 // CHECK:         %[[CARG2:.*]] = fir.convert %arg2 : (!fir.ref<i32>) -> memref<i32>
 // CHECK:         memref.store %[[L1]], %[[CARG2]][] : memref<i32>
+// CHECK-NOT:     fir.array_coor
 
 func.func @nodeclare(%arg0: !fir.ref<!fir.array<1xi32>> {fir.bindc_name = "a"}, %arg1: !fir.ref<i32> {fir.bindc_name = "b"}, %arg2: !fir.ref<i32> {fir.bindc_name = "c"}) attributes {fir.internal_name = ""} {
   %c1 = arith.constant 1 : index
@@ -27,8 +27,9 @@ func.func @nodeclare(%arg0: !fir.ref<!fir.array<1xi32>> {fir.bindc_name = "a"},
 }
 
 // CHECK-LABEL:   func.func @nodeclare_regions
-// CHECK-COUNT-4: fir.convert %{{.*}} : (!fir.ref<i32>) -> memref<i32>
+// CHECK-COUNT-4: fir.convert %{{.*}} : (!fir.ref<!fir.array<6xi32>>) -> memref<6xi32>
 // CHECK-COUNT-1: fir.convert %{{.*}} : (i32) -> f32
+// CHECK-NOT:     fir.array_coor
 
 func.func @nodeclare_regions(%arg0: !fir.ref<!fir.array<10xf32>> {fir.bindc_name = "h11"}, %arg1: !fir.ref<!fir.array<6xi32>> {fir.bindc_name = "rslt"}) attributes {fir.internal_name = "_QPsub11"} {
   %cst = arith.constant 1.100000e+01 : f32



More information about the flang-commits mailing list