[flang-commits] [flang] [flang] Lowering a ArrayCoorOp to arithmetic computations when a fir memref is a block argument (PR #182139)
via flang-commits
flang-commits at lists.llvm.org
Wed Feb 18 12:57:32 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-fir-hlfir
Author: Susan Tan (ス-ザン タン) (SusanTan)
<details>
<summary>Changes</summary>
Remove the special-case that handled `fir.array_coor` with a block-argument base by converting the element ref result (!fir.ref<i32> -> memref<i32>) and leaving fir.array_coor alive.
Instead, we now always convert the base (!fir.ref<!fir.array<...>> -> memref<...>) and compute the memref indices from the fir.array_coor operands, so loads/stores become memref.load/store base[indices] and fir.array_coor can be erased when it’s only used by memory ops.
---
Full diff: https://github.com/llvm/llvm-project/pull/182139.diff
3 Files Affected:
- (modified) flang/lib/Optimizer/Transforms/FIRToMemRef.cpp (+14-15)
- (added) flang/test/Transforms/FIRToMemRef/array-coor-block-arg.mlir (+28)
- (modified) flang/test/Transforms/FIRToMemRef/no-declare.mlir (+7-6)
``````````diff
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
``````````
</details>
https://github.com/llvm/llvm-project/pull/182139
More information about the flang-commits
mailing list