[flang-commits] [flang] [flang] fix fir.ref<fir.box<..>> type conversion in FIRToMemRefTypeConverter (PR #204271)
Susan Tan ス-ザン タン via flang-commits
flang-commits at lists.llvm.org
Tue Jun 16 18:49:49 PDT 2026
https://github.com/SusanTan updated https://github.com/llvm/llvm-project/pull/204271
>From 13367fab9d6f3598faf89c1a541aa8376048b116 Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Tue, 16 Jun 2026 18:17:14 -0700
Subject: [PATCH 1/3] fix converter bug
---
.../Transforms/FIRToMemRefTypeConverter.h | 28 +++++++++++++------
1 file changed, 20 insertions(+), 8 deletions(-)
diff --git a/flang/include/flang/Optimizer/Transforms/FIRToMemRefTypeConverter.h b/flang/include/flang/Optimizer/Transforms/FIRToMemRefTypeConverter.h
index fd434b1f09c9b..fe9fee94b95df 100644
--- a/flang/include/flang/Optimizer/Transforms/FIRToMemRefTypeConverter.h
+++ b/flang/include/flang/Optimizer/Transforms/FIRToMemRefTypeConverter.h
@@ -66,15 +66,27 @@ class FIRToMemRefTypeConverter : public mlir::TypeConverter {
/// Return true if the given FIR type can be converted to a MemRef-typed
/// descriptor (i.e. is a supported base element for MemRef converting).
bool convertibleMemrefType(mlir::Type ty) {
- if (auto refTy = mlir::dyn_cast<fir::ReferenceType>(ty))
- return convertibleMemrefType(refTy.getElementType());
- else if (auto pointerTy = mlir::dyn_cast<fir::PointerType>(ty))
- return convertibleMemrefType(pointerTy.getElementType());
- else if (auto heapTy = mlir::dyn_cast<fir::HeapType>(ty))
- return convertibleMemrefType(heapTy.getElementType());
- else if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(ty))
+ // !fir.box<T> is a descriptor value and maps to a strided memref:
+ // !fir.box<!fir.array<?xi32>> → memref<?xi32, strided<[?], offset:?>>
+ // !fir.ref<!fir.box<T>> is a pointer-to-descriptor (e.g. an assumed-shape
+ // dummy argument or allocatable on entry). There is no memref equivalent:
+ // memref descriptors are SSA values, not addressable memory objects.
+ // Passing ref<box<T>> to convertBaseType would assert on the invalid
+ // element type.
+ mlir::Type indirectElTy;
+ if (auto t = mlir::dyn_cast<fir::ReferenceType>(ty))
+ indirectElTy = t.getElementType();
+ else if (auto t = mlir::dyn_cast<fir::PointerType>(ty))
+ indirectElTy = t.getElementType();
+ else if (auto t = mlir::dyn_cast<fir::HeapType>(ty))
+ indirectElTy = t.getElementType();
+ if (indirectElTy)
+ return !mlir::isa<fir::BoxType>(indirectElTy) &&
+ convertibleMemrefType(indirectElTy);
+
+ if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(ty))
return convertibleMemrefType(seqTy.getElementType());
- else if (auto boxTy = mlir::dyn_cast<fir::BoxType>(ty))
+ if (auto boxTy = mlir::dyn_cast<fir::BoxType>(ty))
return convertibleMemrefType(boxTy.getElementType());
setConvertScalarTypesOnly(true);
>From 6a4feea1785635d7e33b318261ca084ced098ee8 Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Tue, 16 Jun 2026 18:42:03 -0700
Subject: [PATCH 2/3] add conversion
---
.../Transforms/FIRToMemRefTypeConverter.h | 43 +++++++++----------
1 file changed, 20 insertions(+), 23 deletions(-)
diff --git a/flang/include/flang/Optimizer/Transforms/FIRToMemRefTypeConverter.h b/flang/include/flang/Optimizer/Transforms/FIRToMemRefTypeConverter.h
index fe9fee94b95df..d3e11f0138047 100644
--- a/flang/include/flang/Optimizer/Transforms/FIRToMemRefTypeConverter.h
+++ b/flang/include/flang/Optimizer/Transforms/FIRToMemRefTypeConverter.h
@@ -66,27 +66,15 @@ class FIRToMemRefTypeConverter : public mlir::TypeConverter {
/// Return true if the given FIR type can be converted to a MemRef-typed
/// descriptor (i.e. is a supported base element for MemRef converting).
bool convertibleMemrefType(mlir::Type ty) {
- // !fir.box<T> is a descriptor value and maps to a strided memref:
- // !fir.box<!fir.array<?xi32>> → memref<?xi32, strided<[?], offset:?>>
- // !fir.ref<!fir.box<T>> is a pointer-to-descriptor (e.g. an assumed-shape
- // dummy argument or allocatable on entry). There is no memref equivalent:
- // memref descriptors are SSA values, not addressable memory objects.
- // Passing ref<box<T>> to convertBaseType would assert on the invalid
- // element type.
- mlir::Type indirectElTy;
- if (auto t = mlir::dyn_cast<fir::ReferenceType>(ty))
- indirectElTy = t.getElementType();
- else if (auto t = mlir::dyn_cast<fir::PointerType>(ty))
- indirectElTy = t.getElementType();
- else if (auto t = mlir::dyn_cast<fir::HeapType>(ty))
- indirectElTy = t.getElementType();
- if (indirectElTy)
- return !mlir::isa<fir::BoxType>(indirectElTy) &&
- convertibleMemrefType(indirectElTy);
-
- if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(ty))
+ if (auto refTy = mlir::dyn_cast<fir::ReferenceType>(ty))
+ return convertibleMemrefType(refTy.getElementType());
+ else if (auto pointerTy = mlir::dyn_cast<fir::PointerType>(ty))
+ return convertibleMemrefType(pointerTy.getElementType());
+ else if (auto heapTy = mlir::dyn_cast<fir::HeapType>(ty))
+ return convertibleMemrefType(heapTy.getElementType());
+ else if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(ty))
return convertibleMemrefType(seqTy.getElementType());
- if (auto boxTy = mlir::dyn_cast<fir::BoxType>(ty))
+ else if (auto boxTy = mlir::dyn_cast<fir::BoxType>(ty))
return convertibleMemrefType(boxTy.getElementType());
setConvertScalarTypesOnly(true);
@@ -188,14 +176,23 @@ class FIRToMemRefTypeConverter : public mlir::TypeConverter {
return mlir::MemRefType::get({}, ty);
};
+ // For indirect wrappers (ref/ptr/heap), if the element is a box forward to
+ // the box conversion path to produce a strided memref. Otherwise use the
+ // scalar/array path via convertBaseType.
+ auto convertIndirectType = [&](mlir::Type elTy) -> mlir::MemRefType {
+ if (mlir::isa<fir::BoxType>(elTy))
+ return convertMemrefType(elTy);
+ return convertBaseType(elTy);
+ };
+
if (auto refTy = mlir::dyn_cast<fir::ReferenceType>(firTy))
- return convertBaseType(refTy.getElementType());
+ return convertIndirectType(refTy.getElementType());
if (auto pointerTy = mlir::dyn_cast<fir::PointerType>(firTy))
- return convertBaseType(pointerTy.getElementType());
+ return convertIndirectType(pointerTy.getElementType());
if (auto heapTy = mlir::dyn_cast<fir::HeapType>(firTy))
- return convertBaseType(heapTy.getElementType());
+ return convertIndirectType(heapTy.getElementType());
if (auto boxTy = mlir::dyn_cast<fir::BoxType>(firTy)) {
auto elTy = boxTy.getElementType();
>From 3f514557f71142adbf8abf50c2c62957f8d85cb1 Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Tue, 16 Jun 2026 18:49:18 -0700
Subject: [PATCH 3/3] pointer-to-descriptor, used for assumed-shape dummy
arguments and allocatable reduction variables) was left unhandled:
convertibleMemrefType recursed through the ref wrapper and returned true, but
convertMemrefType then called convertBaseType on the inner fir.BoxType, which
has no scalar handling and asserted. Fix convertMemrefType so that indirect
wrappers (ref/ptr/heap) whose element type is a box are forwarded to the box
conversion path, producing the same strided memref as the box itself. No
change to convertibleMemrefType is needed. Add a test in
pointer-like-interface-cast.mlir exercising the
---
.../Transforms/FIRToMemRefTypeConverter.h | 15 ++++++++++++---
.../Fir/OpenACC/pointer-like-interface-cast.mlir | 14 ++++++++++++++
2 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/flang/include/flang/Optimizer/Transforms/FIRToMemRefTypeConverter.h b/flang/include/flang/Optimizer/Transforms/FIRToMemRefTypeConverter.h
index fd434b1f09c9b..d3e11f0138047 100644
--- a/flang/include/flang/Optimizer/Transforms/FIRToMemRefTypeConverter.h
+++ b/flang/include/flang/Optimizer/Transforms/FIRToMemRefTypeConverter.h
@@ -176,14 +176,23 @@ class FIRToMemRefTypeConverter : public mlir::TypeConverter {
return mlir::MemRefType::get({}, ty);
};
+ // For indirect wrappers (ref/ptr/heap), if the element is a box forward to
+ // the box conversion path to produce a strided memref. Otherwise use the
+ // scalar/array path via convertBaseType.
+ auto convertIndirectType = [&](mlir::Type elTy) -> mlir::MemRefType {
+ if (mlir::isa<fir::BoxType>(elTy))
+ return convertMemrefType(elTy);
+ return convertBaseType(elTy);
+ };
+
if (auto refTy = mlir::dyn_cast<fir::ReferenceType>(firTy))
- return convertBaseType(refTy.getElementType());
+ return convertIndirectType(refTy.getElementType());
if (auto pointerTy = mlir::dyn_cast<fir::PointerType>(firTy))
- return convertBaseType(pointerTy.getElementType());
+ return convertIndirectType(pointerTy.getElementType());
if (auto heapTy = mlir::dyn_cast<fir::HeapType>(firTy))
- return convertBaseType(heapTy.getElementType());
+ return convertIndirectType(heapTy.getElementType());
if (auto boxTy = mlir::dyn_cast<fir::BoxType>(firTy)) {
auto elTy = boxTy.getElementType();
diff --git a/flang/test/Fir/OpenACC/pointer-like-interface-cast.mlir b/flang/test/Fir/OpenACC/pointer-like-interface-cast.mlir
index c0ebd8ae1fbc3..8437388bc50c4 100644
--- a/flang/test/Fir/OpenACC/pointer-like-interface-cast.mlir
+++ b/flang/test/Fir/OpenACC/pointer-like-interface-cast.mlir
@@ -66,3 +66,17 @@ func.func @test_fir_llvm_ptr_to_index() {
// CHECK: Generated: %{{.*}} = fir.convert %{{.*}} : (!fir.llvm_ptr<i8>) -> index
return
}
+
+// -----
+
+// !fir.alloca !fir.box<...> produces a !fir.ref<!fir.box<...>> — the
+// pointer-to-descriptor type used for assumed-shape dummy arguments and
+// allocatable reduction variables. getAsMemRefType must yield the same
+// strided memref as the box itself rather than asserting.
+func.func @test_fir_ref_box_array_to_strided_memref() {
+ %0 = fir.alloca !fir.box<!fir.array<?xi32>> {test.cast, cast_dest = memref<?xi32, strided<[?], offset: ?>>}
+ // CHECK: Successfully generated cast for operation: %{{.*}} = fir.alloca !fir.box<!fir.array<?xi32>>{{.*}}
+ // CHECK: Cast result type: memref<?xi32, strided<[?], offset: ?>>
+ // CHECK: Generated: %{{.*}} = fir.convert %{{.*}} : (!fir.ref<!fir.box<!fir.array<?xi32>>>) -> memref<?xi32, strided<[?], offset: ?>>
+ return
+}
More information about the flang-commits
mailing list