[flang-commits] [flang] [flang] get rid of descriptor in scalar type is (PR #188762)
via flang-commits
flang-commits at lists.llvm.org
Fri Mar 27 03:07:01 PDT 2026
https://github.com/jeanPerier updated https://github.com/llvm/llvm-project/pull/188762
>From ca04e01c5bec22417652976be1b56a125daeb455 Mon Sep 17 00:00:00 2001
From: Jean Perier <jperier at nvidia.com>
Date: Thu, 26 Mar 2026 07:38:35 -0700
Subject: [PATCH 1/2] [flang] get rid of descriptor in scalar type is
---
.../include/flang/Optimizer/Dialect/FIRType.h | 13 +++-
flang/lib/Lower/Bridge.cpp | 77 +++++++------------
flang/lib/Optimizer/Dialect/FIRType.cpp | 49 +++++++++---
.../acc-data-operands-remapping-selector.f90 | 24 ++++++
flang/test/Lower/polymorphic.f90 | 6 +-
flang/test/Lower/select-type.f90 | 16 ++--
flang/test/Lower/volatile-allocatable.f90 | 9 ++-
7 files changed, 117 insertions(+), 77 deletions(-)
create mode 100644 flang/test/Lower/OpenACC/acc-data-operands-remapping-selector.f90
diff --git a/flang/include/flang/Optimizer/Dialect/FIRType.h b/flang/include/flang/Optimizer/Dialect/FIRType.h
index a94842d82cef3..ef3328e9799bb 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRType.h
+++ b/flang/include/flang/Optimizer/Dialect/FIRType.h
@@ -48,7 +48,9 @@ class BaseBoxType : public mlir::Type {
mlir::Type getEleTy() const;
/// Get the raw address type of the memory described by the box.
- mlir::Type getBaseAddressType() const;
+ /// When \p dropHeapOrPtr is true, the returned type is always and
+ /// fir::ReferenceType.
+ mlir::Type getBaseAddressType(bool dropHeapOrPtr = false) const;
/// Unwrap element type from fir.heap, fir.ptr and fir.array.
mlir::Type unwrapInnerType() const;
@@ -68,11 +70,20 @@ class BaseBoxType : public mlir::Type {
/// Is this a box describing volatile memory?
bool isVolatile() const;
+ /// Is this a box describing an array or assumed-rank?
+ bool isArray() const;
+
/// Return the same type, except for the shape, that is taken the shape
/// of shapeMold.
BaseBoxType getBoxTypeWithNewShape(mlir::Type shapeMold) const;
BaseBoxType getBoxTypeWithNewShape(int rank) const;
+ /// Return a box type with the same attributes and shape, except that the
+ /// element type that is changed to the provided one. The returned box will be
+ /// a fir.class if \p polymorphic is true and a fir.box otherwise.
+ BaseBoxType getBoxTypeWithNewElementType(mlir::Type elementType,
+ bool polymorphic) const;
+
/// Return the same type, except for the attribute (fir.heap/fir.ptr).
BaseBoxType getBoxTypeWithNewAttr(Attribute attr) const;
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 7459f814a0d4d..1cd4d64d40336 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -4503,10 +4503,6 @@ class FirConverter : public Fortran::lower::AbstractConverter {
bool hasLocalScope = false;
llvm::SmallVector<const Fortran::semantics::Scope *> typeCaseScopes;
- const auto selectorIsVolatile = [&selector]() {
- return fir::isa_volatile_type(fir::getBase(selector).getType());
- };
-
const auto &typeCaseList =
std::get<std::list<Fortran::parser::SelectTypeConstruct::TypeCase>>(
selectTypeConstruct.t);
@@ -4634,10 +4630,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
};
mlir::Type baseTy = fir::getBase(selector).getType();
- bool isPointer = fir::isPointerType(baseTy);
- bool isAllocatable = fir::isAllocatableType(baseTy);
- bool isArray =
- mlir::isa<fir::SequenceType>(fir::dyn_cast_ptrOrBoxEleTy(baseTy));
+ auto selectorBoxType = llvm::cast<fir::BaseBoxType>(baseTy);
+ bool isArray = selectorBoxType.isArray();
const fir::BoxValue *selectorBox = selector.getBoxOf<fir::BoxValue>();
if (std::holds_alternative<Fortran::parser::Default>(guard.u)) {
// CLASS DEFAULT
@@ -4647,72 +4641,55 @@ class FirConverter : public Fortran::lower::AbstractConverter {
// TYPE IS
fir::ExactTypeAttr attr =
mlir::dyn_cast<fir::ExactTypeAttr>(typeGuardAttr);
- mlir::Value exactValue;
- mlir::Type addrTy = attr.getType();
- if (isArray) {
- auto seqTy = mlir::dyn_cast<fir::SequenceType>(
- fir::dyn_cast_ptrOrBoxEleTy(baseTy));
- addrTy = fir::SequenceType::get(seqTy.getShape(), attr.getType());
- }
- if (isPointer)
- addrTy = fir::PointerType::get(addrTy);
- if (isAllocatable)
- addrTy = fir::HeapType::get(addrTy);
+ fir::BaseBoxType newBoxType =
+ selectorBoxType.getBoxTypeWithNewElementType(
+ attr.getType(), /*polymorphic=*/false);
+ mlir::Type addrTy =
+ newBoxType.getBaseAddressType(/*dropHeapOrPtr=*/true);
+
+ mlir::Value rawPointer = fir::BoxAddrOp::create(
+ *builder, loc, addrTy, fir::getBase(selector));
if (std::holds_alternative<Fortran::parser::IntrinsicTypeSpec>(
typeSpec->u)) {
- mlir::Type refTy =
- fir::ReferenceType::get(addrTy, selectorIsVolatile());
- if (isPointer || isAllocatable)
- refTy = addrTy;
- exactValue = fir::BoxAddrOp::create(*builder, loc, refTy,
- fir::getBase(selector));
const Fortran::semantics::IntrinsicTypeSpec *intrinsic =
typeSpec->declTypeSpec->AsIntrinsic();
if (isArray) {
- mlir::Value exact = fir::ConvertOp::create(
- *builder, loc,
- fir::BoxType::get(addrTy, selectorIsVolatile()),
- fir::getBase(selector));
- addAssocEntitySymbol(selectorBox->clone(exact));
+ mlir::Value boxCast = fir::ConvertOp::create(
+ *builder, loc, newBoxType, fir::getBase(selector));
+ addAssocEntitySymbol(selectorBox->clone(boxCast));
} else if (intrinsic->category() ==
Fortran::common::TypeCategory::Character) {
auto charTy = mlir::dyn_cast<fir::CharacterType>(attr.getType());
mlir::Value charLen =
fir::factory::CharacterExprHelper(*builder, loc)
.readLengthFromBox(fir::getBase(selector), charTy);
- addAssocEntitySymbol(fir::CharBoxValue(exactValue, charLen));
+ addAssocEntitySymbol(fir::CharBoxValue(rawPointer, charLen));
} else {
- addAssocEntitySymbol(exactValue);
+ addAssocEntitySymbol(rawPointer);
}
} else if (std::holds_alternative<Fortran::parser::DerivedTypeSpec>(
typeSpec->u)) {
- exactValue = fir::ConvertOp::create(
- *builder, loc, fir::BoxType::get(addrTy, selectorIsVolatile()),
- fir::getBase(selector));
- addAssocEntitySymbol(selectorBox->clone(exactValue));
+ if (isArray) {
+ mlir::Value boxCast = fir::ConvertOp::create(
+ *builder, loc, newBoxType, fir::getBase(selector));
+ addAssocEntitySymbol(selectorBox->clone(boxCast));
+ } else {
+ addAssocEntitySymbol(rawPointer);
+ }
}
} else if (std::holds_alternative<Fortran::parser::DerivedTypeSpec>(
guard.u)) {
// CLASS IS
fir::SubclassAttr attr =
mlir::dyn_cast<fir::SubclassAttr>(typeGuardAttr);
- mlir::Type addrTy = attr.getType();
- if (isArray) {
- auto seqTy = mlir::dyn_cast<fir::SequenceType>(
- fir::dyn_cast_ptrOrBoxEleTy(baseTy));
- addrTy = fir::SequenceType::get(seqTy.getShape(), attr.getType());
- }
- if (isPointer)
- addrTy = fir::PointerType::get(addrTy);
- if (isAllocatable)
- addrTy = fir::HeapType::get(addrTy);
- mlir::Type classTy =
- fir::ClassType::get(addrTy, selectorIsVolatile());
- if (classTy == baseTy) {
+ fir::BaseBoxType newClassType =
+ selectorBoxType.getBoxTypeWithNewElementType(
+ attr.getType(), /*polymorphic=*/true);
+ if (newClassType == baseTy) {
addAssocEntitySymbol(selector);
} else {
mlir::Value derived = fir::ConvertOp::create(
- *builder, loc, classTy, fir::getBase(selector));
+ *builder, loc, newClassType, fir::getBase(selector));
addAssocEntitySymbol(selectorBox->clone(derived));
}
}
diff --git a/flang/lib/Optimizer/Dialect/FIRType.cpp b/flang/lib/Optimizer/Dialect/FIRType.cpp
index ccdc8e45feede..9c058289075fa 100644
--- a/flang/lib/Optimizer/Dialect/FIRType.cpp
+++ b/flang/lib/Optimizer/Dialect/FIRType.cpp
@@ -684,30 +684,39 @@ std::string getTypeAsString(mlir::Type ty, const fir::KindMapping &kindMap,
return buf;
}
-mlir::Type changeElementType(mlir::Type type, mlir::Type newElementType,
- bool turnBoxIntoClass) {
+static mlir::Type changeElementTypeImpl(mlir::Type type,
+ mlir::Type newElementType,
+ bool turnBoxIntoClass,
+ bool turnClassIntoBox) {
return llvm::TypeSwitch<mlir::Type, mlir::Type>(type)
.Case([&](fir::SequenceType seqTy) -> mlir::Type {
return fir::SequenceType::get(seqTy.getShape(), newElementType);
})
- .Case<fir::ReferenceType, fir::ClassType>([&](auto t) -> mlir::Type {
+ .Case<fir::ReferenceType>([&](auto t) -> mlir::Type {
using FIRT = decltype(t);
- auto newEleTy =
- changeElementType(t.getEleTy(), newElementType, turnBoxIntoClass);
+ auto newEleTy = changeElementTypeImpl(
+ t.getEleTy(), newElementType, turnBoxIntoClass, turnClassIntoBox);
return FIRT::get(newEleTy, t.isVolatile());
})
.Case<fir::PointerType, fir::HeapType>([&](auto t) -> mlir::Type {
using FIRT = decltype(t);
- return FIRT::get(
- changeElementType(t.getEleTy(), newElementType, turnBoxIntoClass));
+ return FIRT::get(changeElementTypeImpl(
+ t.getEleTy(), newElementType, turnBoxIntoClass, turnClassIntoBox));
})
.Case([&](fir::BoxType t) -> mlir::Type {
mlir::Type newInnerType =
- changeElementType(t.getEleTy(), newElementType, false);
+ changeElementTypeImpl(t.getEleTy(), newElementType, false, false);
if (turnBoxIntoClass)
return fir::ClassType::get(newInnerType, t.isVolatile());
return fir::BoxType::get(newInnerType, t.isVolatile());
})
+ .Case([&](fir::ClassType t) -> mlir::Type {
+ mlir::Type newInnerType =
+ changeElementTypeImpl(t.getEleTy(), newElementType, false, false);
+ if (turnClassIntoBox)
+ return fir::BoxType::get(newInnerType, t.isVolatile());
+ return fir::ClassType::get(newInnerType, t.isVolatile());
+ })
.Default([&](mlir::Type t) -> mlir::Type {
assert((fir::isa_trivial(t) || llvm::isa<fir::RecordType>(t) ||
llvm::isa<mlir::NoneType>(t)) &&
@@ -716,6 +725,12 @@ mlir::Type changeElementType(mlir::Type type, mlir::Type newElementType,
});
}
+mlir::Type changeElementType(mlir::Type type, mlir::Type newElementType,
+ bool turnBoxIntoClass) {
+ return changeElementTypeImpl(type, newElementType, turnBoxIntoClass,
+ /*turnClassIntoBox=*/false);
+}
+
} // namespace fir
namespace {
@@ -1432,11 +1447,11 @@ mlir::Type BaseBoxType::getEleTy() const {
[](auto type) { return type.getEleTy(); });
}
-mlir::Type BaseBoxType::getBaseAddressType() const {
+mlir::Type BaseBoxType::getBaseAddressType(bool dropHeapOrPtr) const {
mlir::Type eleTy = getEleTy();
- if (fir::isa_ref_type(eleTy))
+ if (!dropHeapOrPtr && fir::isa_ref_type(eleTy))
return eleTy;
- return fir::ReferenceType::get(eleTy, isVolatile());
+ return fir::ReferenceType::get(getElementOrSequenceType(), isVolatile());
}
mlir::Type BaseBoxType::unwrapInnerType() const {
@@ -1500,6 +1515,14 @@ fir::BaseBoxType fir::BaseBoxType::getBoxTypeWithNewShape(int rank) const {
return mlir::cast<fir::BaseBoxType>(changeTypeShape(*this, newShape));
}
+fir::BaseBoxType
+fir::BaseBoxType::getBoxTypeWithNewElementType(mlir::Type elementType,
+ bool polymorphic) const {
+ return llvm::cast<fir::BaseBoxType>(changeElementTypeImpl(
+ *this, elementType, /*turnBoxIntoClass=*/polymorphic,
+ /*turnClassIntoBox=*/!polymorphic));
+}
+
fir::BaseBoxType fir::BaseBoxType::getBoxTypeWithNewAttr(
fir::BaseBoxType::Attribute attr) const {
mlir::Type baseType = fir::unwrapRefType(getEleTy());
@@ -1539,6 +1562,10 @@ bool fir::BaseBoxType::isPointerOrAllocatable() const {
bool BaseBoxType::isVolatile() const { return fir::isa_volatile_type(*this); }
+bool BaseBoxType::isArray() const {
+ return llvm::isa<fir::SequenceType>(getElementOrSequenceType());
+}
+
//===----------------------------------------------------------------------===//
// FIROpsDialect
//===----------------------------------------------------------------------===//
diff --git a/flang/test/Lower/OpenACC/acc-data-operands-remapping-selector.f90 b/flang/test/Lower/OpenACC/acc-data-operands-remapping-selector.f90
new file mode 100644
index 0000000000000..5d7f5ee9a5ae6
--- /dev/null
+++ b/flang/test/Lower/OpenACC/acc-data-operands-remapping-selector.f90
@@ -0,0 +1,24 @@
+! Test remapping of select type selector.
+! RUN: %flang_fc1 -fopenacc -emit-hlfir %s -o - | FileCheck %s
+
+module copyin_selector
+ type t
+ integer :: i
+ end type
+contains
+subroutine foo(x)
+ class(*) :: x
+ select type(x)
+ type is (t)
+ !$acc parallel copyin(x)
+ call bar(x)
+ !$acc end parallel
+ end select
+end subroutine
+end module
+! CHECK-LABEL: func.func @_QMcopyin_selectorPfoo(
+! CHECK: fir.select_type
+! CHECK: %[[COPYIN:.*]] = acc.copyin varPtr(%{{.*}} : !fir.ref<!fir.type<_QMcopyin_selectorTt{i:i32}>>) -> !fir.ref<!fir.type<_QMcopyin_selectorTt{i:i32}>> {name = "x"}
+! CHECK: acc.parallel dataOperands(%[[COPYIN]] : !fir.ref<!fir.type<_QMcopyin_selectorTt{i:i32}>>) {
+! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[COPYIN]] {uniq_name = "_QMcopyin_selectorFfooEx"} : (!fir.ref<!fir.type<_QMcopyin_selectorTt{i:i32}>>) -> (!fir.ref<!fir.type<_QMcopyin_selectorTt{i:i32}>>, !fir.ref<!fir.type<_QMcopyin_selectorTt{i:i32}>>)
+! CHECK: fir.call @_QPbar(%[[DECL]]#0)
diff --git a/flang/test/Lower/polymorphic.f90 b/flang/test/Lower/polymorphic.f90
index d8e800771c433..6e84bec14420b 100644
--- a/flang/test/Lower/polymorphic.f90
+++ b/flang/test/Lower/polymorphic.f90
@@ -1014,10 +1014,10 @@ subroutine test_parent_comp_in_select_type(s)
! CHECK: %[[LOAD_S:.*]] = fir.load %[[S]] : !fir.ref<!fir.class<!fir.heap<!fir.type<_QMpolymorphic_testTp1{{(,sequence)?}}{a:i32,b:i32}>>>>
! CHECK: fir.select_type %[[LOAD_S]] : !fir.class<!fir.heap<!fir.type<_QMpolymorphic_testTp1{{(,sequence)?}}{a:i32,b:i32}>>> [#fir.type_is<!fir.type<_QMpolymorphic_testTp2{{(,sequence)?}}{a:i32,b:i32,c:f32}>>, ^bb1, unit, ^bb2]
! CHECK: ^bb1:
-! CHECK: %[[CONV_S:.*]] = fir.convert %[[LOAD_S]] : (!fir.class<!fir.heap<!fir.type<_QMpolymorphic_testTp1{{(,sequence)?}}{a:i32,b:i32}>>>) -> !fir.box<!fir.heap<!fir.type<_QMpolymorphic_testTp2{{(,sequence)?}}{a:i32,b:i32,c:f32}>>>
-! CHECK: %[[REBOX_P1:.*]] = fir.rebox %[[CONV_S]] : (!fir.box<!fir.heap<!fir.type<_QMpolymorphic_testTp2{{(,sequence)?}}{a:i32,b:i32,c:f32}>>>) -> !fir.box<!fir.type<_QMpolymorphic_testTp1{{(,sequence)?}}{a:i32,b:i32}>>
+! CHECK: %[[CONV_S:.*]] = fir.box_addr %[[LOAD_S]] : (!fir.class<!fir.heap<!fir.type<_QMpolymorphic_testTp1{{(,sequence)?}}{a:i32,b:i32}>>>) -> !fir.ref<!fir.type<_QMpolymorphic_testTp2{{(,sequence)?}}{a:i32,b:i32,c:f32}>>
+! CHECK: %[[EMBOX_P1:.*]] = fir.embox %[[CONV_S]] : (!fir.ref<!fir.type<_QMpolymorphic_testTp2{{(,sequence)?}}{a:i32,b:i32,c:f32}>>) -> !fir.box<!fir.type<_QMpolymorphic_testTp1{{(,sequence)?}}{a:i32,b:i32}>>
! CHECK: %[[LOAD_P:.*]] = fir.load %[[P]] : !fir.ref<!fir.class<!fir.heap<!fir.type<_QMpolymorphic_testTp1{{(,sequence)?}}{a:i32,b:i32}>>>>
-! CHECK: %[[LHS_CONV:.*]] = fir.convert %[[REBOX_P1]] : (!fir.box<!fir.type<_QMpolymorphic_testTp1{{(,sequence)?}}{a:i32,b:i32}>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %[[LHS_CONV:.*]] = fir.convert %[[EMBOX_P1]] : (!fir.box<!fir.type<_QMpolymorphic_testTp1{{(,sequence)?}}{a:i32,b:i32}>>) -> !fir.ref<!fir.box<none>>
! CHECK: %[[RHS_CONV:.*]] = fir.convert %[[LOAD_P]] : (!fir.class<!fir.heap<!fir.type<_QMpolymorphic_testTp1{{(,sequence)?}}{a:i32,b:i32}>>>) -> !fir.box<none>
! CHECK: fir.call @_FortranAAssign(%[[LHS_CONV]], %[[RHS_CONV]], %{{.*}}, %{{.*}}) {{.*}} : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> ()
diff --git a/flang/test/Lower/select-type.f90 b/flang/test/Lower/select-type.f90
index 246b653390b59..871b084950688 100644
--- a/flang/test/Lower/select-type.f90
+++ b/flang/test/Lower/select-type.f90
@@ -660,15 +660,15 @@ subroutine select_type10(a)
! CHECK: %[[SELECTOR:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.class<!fir.ptr<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>>
! CHECK: fir.select_type %[[SELECTOR]] : !fir.class<!fir.ptr<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>> [#fir.type_is<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>, ^bb{{.*}}, #fir.type_is<!fir.type<_QMselect_type_lower_testTp2{a:i32,b:i32,c:i32}>>, ^bb{{.*}}, #fir.class_is<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>, ^bb{{.*}}, unit, ^bb{{.*}}]
! CHECK: ^bb{{.*}}:
-! CHECK: %[[EXACT_BOX:.*]] = fir.convert %[[SELECTOR]] : (!fir.class<!fir.ptr<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>) -> !fir.box<!fir.ptr<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>
+! CHECK: %[[EXACT_BOX:.*]] = fir.box_addr %[[SELECTOR]] : (!fir.class<!fir.ptr<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>) -> !fir.ref<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>
! CHECK: %[[C1:.*]] = arith.constant 1 : i32
-! CHECK: %[[COORD_A:.*]] = fir.coordinate_of %[[EXACT_BOX]], a : (!fir.box<!fir.ptr<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>) -> !fir.ref<i32>
+! CHECK: %[[COORD_A:.*]] = fir.coordinate_of %[[EXACT_BOX]], a : (!fir.ref<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>) -> !fir.ref<i32>
! CHECK: fir.store %[[C1]] to %[[COORD_A]] : !fir.ref<i32>
! CHECK: cf.br ^bb{{.*}}
! CHECK: ^bb{{.*}}:
-! CHECK: %[[EXACT_BOX:.*]] = fir.convert %[[SELECTOR]] : (!fir.class<!fir.ptr<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>) -> !fir.box<!fir.ptr<!fir.type<_QMselect_type_lower_testTp2{a:i32,b:i32,c:i32}>>>
+! CHECK: %[[EXACT_BOX:.*]] = fir.box_addr %[[SELECTOR]] : (!fir.class<!fir.ptr<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>) -> !fir.ref<!fir.type<_QMselect_type_lower_testTp2{a:i32,b:i32,c:i32}>>
! CHECK: %[[C3:.*]] = arith.constant 3 : i32
-! CHECK: %[[COORD_C:.*]] = fir.coordinate_of %[[EXACT_BOX]], c : (!fir.box<!fir.ptr<!fir.type<_QMselect_type_lower_testTp2{a:i32,b:i32,c:i32}>>>) -> !fir.ref<i32>
+! CHECK: %[[COORD_C:.*]] = fir.coordinate_of %[[EXACT_BOX]], c : (!fir.ref<!fir.type<_QMselect_type_lower_testTp2{a:i32,b:i32,c:i32}>>) -> !fir.ref<i32>
! CHECK: fir.store %[[C3]] to %[[COORD_C]] : !fir.ref<i32>
! CHECK: cf.br ^bb{{.*}}
! CHECK: ^bb{{.*}}
@@ -693,15 +693,15 @@ subroutine select_type11(a)
! CHECK: %[[SELECTOR:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.class<!fir.heap<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>>
! CHECK: fir.select_type %[[SELECTOR]] : !fir.class<!fir.heap<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>> [#fir.type_is<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>, ^bb1, #fir.type_is<!fir.type<_QMselect_type_lower_testTp2{a:i32,b:i32,c:i32}>>, ^bb2, unit, ^bb3]
! CHECK: ^bb{{.*}}:
-! CHECK: %[[EXACT_BOX:.*]] = fir.convert %[[SELECTOR]] : (!fir.class<!fir.heap<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>) -> !fir.box<!fir.heap<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>
+! CHECK: %[[EXACT_BOX:.*]] = fir.box_addr %[[SELECTOR]] : (!fir.class<!fir.heap<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>) -> !fir.ref<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>
! CHECK: %[[C1:.*]] = arith.constant 1 : i32
-! CHECK: %[[COORD_A:.*]] = fir.coordinate_of %[[EXACT_BOX]], a : (!fir.box<!fir.heap<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>) -> !fir.ref<i32>
+! CHECK: %[[COORD_A:.*]] = fir.coordinate_of %[[EXACT_BOX]], a : (!fir.ref<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>) -> !fir.ref<i32>
! CHECK: fir.store %[[C1]] to %[[COORD_A]] : !fir.ref<i32>
! CHECK: cf.br ^bb{{.*}}
! CHECK: ^bb{{.*}}:
-! CHECK: %[[EXACT_BOX:.*]] = fir.convert %[[SELECTOR]] : (!fir.class<!fir.heap<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>) -> !fir.box<!fir.heap<!fir.type<_QMselect_type_lower_testTp2{a:i32,b:i32,c:i32}>>>
+! CHECK: %[[EXACT_BOX:.*]] = fir.box_addr %[[SELECTOR]] : (!fir.class<!fir.heap<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>) -> !fir.ref<!fir.type<_QMselect_type_lower_testTp2{a:i32,b:i32,c:i32}>>
! CHECK: %[[C3:.*]] = arith.constant 3 : i32
-! CHECK: %[[COORD_C:.*]] = fir.coordinate_of %[[EXACT_BOX]], c : (!fir.box<!fir.heap<!fir.type<_QMselect_type_lower_testTp2{a:i32,b:i32,c:i32}>>>) -> !fir.ref<i32>
+! CHECK: %[[COORD_C:.*]] = fir.coordinate_of %[[EXACT_BOX]], c : (!fir.ref<!fir.type<_QMselect_type_lower_testTp2{a:i32,b:i32,c:i32}>>) -> !fir.ref<i32>
! CHECK: fir.store %[[C3]] to %[[COORD_C]] : !fir.ref<i32>
! CHECK: cf.br ^bb{{.*}}
diff --git a/flang/test/Lower/volatile-allocatable.f90 b/flang/test/Lower/volatile-allocatable.f90
index 4c0bea60ecaa1..496dfbd8c498c 100644
--- a/flang/test/Lower/volatile-allocatable.f90
+++ b/flang/test/Lower/volatile-allocatable.f90
@@ -127,8 +127,9 @@ subroutine test_unlimited_polymorphic()
! CHECK: %{{.+}} = fir.call @_FortranAAllocatableAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.ref<i64>, i1, !fir.box<none>, !fir.ref<i8>, i32, {{.*}}) -> i32
! CHECK: fir.call @_FortranAAllocatableInitDerivedForAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.ref<none>, i32, i32) -> ()
! CHECK: %{{.+}} = fir.call @_FortranAAllocatableAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.ref<i64>, i1, !fir.box<none>, !fir.ref<i8>, i32, {{.*}}) -> i32
-! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFtest_scalar_volatileEv1"} : (!fir.box<!fir.heap<!fir.type<{{.*}}>>, volatile>) -> (!fir.box<!fir.type<{{.*}}>, volatile>, !fir.box<!fir.type<{{.*}}>, volatile>)
-! CHECK: %{{.+}} = hlfir.designate %{{.+}}#0{"j"} : (!fir.box<!fir.type<{{.*}}>, volatile>) -> !fir.ref<i32, volatile>
+! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} {fortran_attrs = #fir.var_attrs<volatile>, uniq_name =
+! "_QFtest_scalar_volatileEv1"} : (!fir.ref<!fir.type<{{.*}}, volatile>) -> (!fir.ref<!fir.type<{{.*}}>, volatile>, !fir.ref<!fir.type<{{.*}}>, volatile>)
+! CHECK: %{{.+}} = hlfir.designate %{{.+}}#0{"j"} : (!fir.ref<!fir.type<{{.*}}>, volatile>) -> !fir.ref<i32, volatile>
! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQro._QMderived_typesText_type.0"} : (!fir.ref<!fir.type<{{.*}}>>) -> (!fir.ref<!fir.type<{{.*}}>>, !fir.ref<!fir.type<{{.*}}>>)
! CHECK: %{{.+}} = fir.call @_FortranAAllocatableAllocateSource(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} typeparams %{{.+}} {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX766F6C6174696C6520636861726163746572"} : (!fir.ref<!fir.char<1,18>>, index) -> (!fir.ref<!fir.char<1,18>>, !fir.ref<!fir.char<1,18>>)
@@ -178,10 +179,10 @@ subroutine test_unlimited_polymorphic()
! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} {fortran_attrs = #fir.var_attrs<allocatable, volatile>, uniq_name = "_QFtest_unlimited_polymorphicEupa"} : (!fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>, volatile>, volatile>) -> (!fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>, volatile>, volatile>, !fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>, volatile>, volatile>)
! CHECK: fir.call @_FortranAAllocatableInitIntrinsicForAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, i32, i32, i32, i32) -> ()
! CHECK: %{{.+}} = fir.call @_FortranAAllocatableAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.ref<i64>, i1, !fir.box<none>, !fir.ref<i8>, i32, {{.*}}) -> i32
-! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFtest_unlimited_polymorphicEup"} : (!fir.heap<i32>) -> (!fir.heap<i32>, !fir.heap<i32>)
+! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFtest_unlimited_polymorphicEup"} : (!fir.ref<i32, volatile>) -> (!fir.ref<i32, volatile>, !fir.ref<i32, volatile>)
! CHECK: fir.call @_FortranAAllocatableInitCharacterForAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, i64, i32, i32, i32) -> ()
! CHECK: %{{.+}} = fir.call @_FortranAAllocatableAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.ref<i64>, i1, !fir.box<none>, !fir.ref<i8>, i32, {{.*}}) -> i32
-! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} typeparams %{{.+}} {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFtest_unlimited_polymorphicEup"} : (!fir.heap<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.heap<!fir.char<1,?>>)
+! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} typeparams %{{.+}} {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFtest_unlimited_polymorphicEup"} : (!fir.ref<!fir.char<1,?>, volatile>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>, volatile>)
! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} typeparams %{{.+}} {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX636C617373282A29"} : (!fir.ref<!fir.char<1,8>>, index) -> (!fir.ref<!fir.char<1,8>>, !fir.ref<!fir.char<1,8>>)
! CHECK: fir.call @_FortranAAllocatableInitIntrinsicForAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, i32, i32, i32, i32) -> ()
! CHECK: fir.call @_FortranAAllocatableSetBounds(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, i32, i64, i64) -> ()
>From 2ea7a17c4cca8bcc789ed7c94279205789c931d9 Mon Sep 17 00:00:00 2001
From: Jean Perier <jperier at nvidia.com>
Date: Fri, 27 Mar 2026 03:02:53 -0700
Subject: [PATCH 2/2] address comments
---
flang/include/flang/Optimizer/Dialect/FIRType.h | 2 +-
flang/lib/Lower/Bridge.cpp | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/flang/include/flang/Optimizer/Dialect/FIRType.h b/flang/include/flang/Optimizer/Dialect/FIRType.h
index ef3328e9799bb..05f6a0746876f 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRType.h
+++ b/flang/include/flang/Optimizer/Dialect/FIRType.h
@@ -48,7 +48,7 @@ class BaseBoxType : public mlir::Type {
mlir::Type getEleTy() const;
/// Get the raw address type of the memory described by the box.
- /// When \p dropHeapOrPtr is true, the returned type is always and
+ /// When \p dropHeapOrPtr is true, the returned type is always a
/// fir::ReferenceType.
mlir::Type getBaseAddressType(bool dropHeapOrPtr = false) const;
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 1cd4d64d40336..647bc741e7edc 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -4631,7 +4631,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
mlir::Type baseTy = fir::getBase(selector).getType();
auto selectorBoxType = llvm::cast<fir::BaseBoxType>(baseTy);
- bool isArray = selectorBoxType.isArray();
+ const bool isArray = selectorBoxType.isArray();
const fir::BoxValue *selectorBox = selector.getBoxOf<fir::BoxValue>();
if (std::holds_alternative<Fortran::parser::Default>(guard.u)) {
// CLASS DEFAULT
More information about the flang-commits
mailing list