[flang-commits] [flang] f88bc7d - [flang] Handle dynamic type in move_alloc
Valentin Clement via flang-commits
flang-commits at lists.llvm.org
Wed Mar 1 00:45:12 PST 2023
Author: Valentin Clement
Date: 2023-03-01T09:45:02+01:00
New Revision: f88bc7d426ed564e6e24ed1a24263045410ad425
URL: https://github.com/llvm/llvm-project/commit/f88bc7d426ed564e6e24ed1a24263045410ad425
DIFF: https://github.com/llvm/llvm-project/commit/f88bc7d426ed564e6e24ed1a24263045410ad425.diff
LOG: [flang] Handle dynamic type in move_alloc
Update move_alloc to carry over the dyanmic type of `from` to `to`
and reset the dynamic type of `from` to its declared type when it
is polymorphic.
Reviewed By: PeteSteinfeld
Differential Revision: https://reviews.llvm.org/D144997
Added:
Modified:
flang/include/flang/Runtime/allocatable.h
flang/lib/Optimizer/Builder/Runtime/Allocatable.cpp
flang/runtime/allocatable.cpp
flang/test/Lower/Intrinsics/move_alloc.f90
flang/test/Lower/polymorphic.f90
flang/unittests/Optimizer/Builder/Runtime/AllocatableTest.cpp
flang/unittests/Runtime/Allocatable.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/Runtime/allocatable.h b/flang/include/flang/Runtime/allocatable.h
index 998d7469b5f94..58bbd27c1b97f 100644
--- a/flang/include/flang/Runtime/allocatable.h
+++ b/flang/include/flang/Runtime/allocatable.h
@@ -95,8 +95,9 @@ int RTNAME(AllocatableAllocateSource)(Descriptor &, const Descriptor &source,
// with the other APIs for allocatables.) The destination descriptor
// must be initialized.
std::int32_t RTNAME(MoveAlloc)(Descriptor &to, Descriptor &from,
- bool hasStat = false, const Descriptor *errMsg = nullptr,
- const char *sourceFile = nullptr, int sourceLine = 0);
+ const typeInfo::DerivedType *, bool hasStat = false,
+ const Descriptor *errMsg = nullptr, const char *sourceFile = nullptr,
+ int sourceLine = 0);
// Deallocates an allocatable. Finalizes elements &/or components as needed.
// The allocatable is left in an initialized state suitable for reallocation
diff --git a/flang/lib/Optimizer/Builder/Runtime/Allocatable.cpp b/flang/lib/Optimizer/Builder/Runtime/Allocatable.cpp
index 675faf123e35e..221d32b9490f9 100644
--- a/flang/lib/Optimizer/Builder/Runtime/Allocatable.cpp
+++ b/flang/lib/Optimizer/Builder/Runtime/Allocatable.cpp
@@ -22,9 +22,20 @@ mlir::Value fir::runtime::genMoveAlloc(fir::FirOpBuilder &builder,
mlir::FunctionType fTy{func.getFunctionType()};
mlir::Value sourceFile{fir::factory::locationToFilename(builder, loc)};
mlir::Value sourceLine{
- fir::factory::locationToLineNo(builder, loc, fTy.getInput(5))};
+ fir::factory::locationToLineNo(builder, loc, fTy.getInput(6))};
+ mlir::Value declaredTypeDesc;
+ if (fir::isPolymorphicType(from.getType())) {
+ fir::ClassType clTy =
+ fir::dyn_cast_ptrEleTy(from.getType()).dyn_cast<fir::ClassType>();
+ mlir::Type derivedType = fir::unwrapInnerType(clTy.getEleTy());
+ declaredTypeDesc =
+ builder.create<fir::TypeDescOp>(loc, mlir::TypeAttr::get(derivedType));
+ } else {
+ declaredTypeDesc = builder.createNullConstant(loc);
+ }
llvm::SmallVector<mlir::Value> args{fir::runtime::createArguments(
- builder, loc, fTy, to, from, hasStat, errMsg, sourceFile, sourceLine)};
+ builder, loc, fTy, to, from, declaredTypeDesc, hasStat, errMsg,
+ sourceFile, sourceLine)};
return builder.create<fir::CallOp>(loc, func, args).getResult(0);
}
diff --git a/flang/runtime/allocatable.cpp b/flang/runtime/allocatable.cpp
index b428ee6fcbd73..4c1abdbdb5c5e 100644
--- a/flang/runtime/allocatable.cpp
+++ b/flang/runtime/allocatable.cpp
@@ -41,7 +41,8 @@ void RTNAME(AllocatableInitDerived)(Descriptor &descriptor,
derivedType, nullptr, rank, nullptr, CFI_attribute_allocatable);
}
-std::int32_t RTNAME(MoveAlloc)(Descriptor &to, Descriptor &from, bool hasStat,
+std::int32_t RTNAME(MoveAlloc)(Descriptor &to, Descriptor &from,
+ const typeInfo::DerivedType *derivedType, bool hasStat,
const Descriptor *errMsg, const char *sourceFile, int sourceLine) {
Terminator terminator{sourceFile, sourceLine};
@@ -63,7 +64,24 @@ std::int32_t RTNAME(MoveAlloc)(Descriptor &to, Descriptor &from, bool hasStat,
if (from.IsAllocated()) {
to = from;
from.raw().base_addr = nullptr;
+
+ // Carry over the dynamic type.
+ if (auto *toAddendum{to.Addendum()}) {
+ if (const auto *fromAddendum{from.Addendum()}) {
+ if (const auto *derived{fromAddendum->derivedType()}) {
+ toAddendum->set_derivedType(derived);
+ }
+ }
+ }
+
+ // Reset from dynamic type if needed.
+ if (auto *fromAddendum{from.Addendum()}) {
+ if (derivedType) {
+ fromAddendum->set_derivedType(derivedType);
+ }
+ }
}
+
return StatOk;
}
diff --git a/flang/test/Lower/Intrinsics/move_alloc.f90 b/flang/test/Lower/Intrinsics/move_alloc.f90
index 6618150ec415c..f8abc6416cd36 100644
--- a/flang/test/Lower/Intrinsics/move_alloc.f90
+++ b/flang/test/Lower/Intrinsics/move_alloc.f90
@@ -12,7 +12,7 @@ subroutine to_from_only
! CHECK-DAG: %[[a2:.*]] = fir.convert %[[a1]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
! CHECK-DAG: %[[b2:.*]] = fir.convert %[[b1]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
call move_alloc(from, to)
- ! CHECK: fir.call @_FortranAMoveAlloc(%[[b2]], %[[a2]], %[[false]], %[[errMsg]], %{{.*}}, %{{.*}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
+ ! CHECK: fir.call @_FortranAMoveAlloc(%[[b2]], %[[a2]], %{{.*}}, %[[false]], %[[errMsg]], %{{.*}}, %{{.*}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.ref<!fir.box<none>>, !fir.ref<none>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
! CHECK-DAG: %[[a3:.*]] = fir.load %[[a1:.*]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
! CHECK-DAG: %[[a4:.*]] = fir.box_addr %[[a3]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
! CHECK-DAG: %[[b3:.*]] = fir.load %[[b1]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
@@ -32,7 +32,7 @@ subroutine to_from_stat
! CHECK-DAG: %[[a2:.*]] = fir.convert %[[a1]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
! CHECK-DAG: %[[b2:.*]] = fir.convert %[[b1]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
call move_alloc(from, to, stat)
- ! CHECK: %[[stat:.*]] = fir.call @_FortranAMoveAlloc(%[[b2]], %[[a2]], %[[true]], %[[errMsg]], %{{.*}}, %{{.*}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
+ ! CHECK: %[[stat:.*]] = fir.call @_FortranAMoveAlloc(%[[b2]], %[[a2]], %{{.*}}, %[[true]], %[[errMsg]], %{{.*}}, %{{.*}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.ref<!fir.box<none>>, !fir.ref<none>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
! CHECK-DAG: %[[a3:.*]] = fir.load %[[a1:.*]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
! CHECK-DAG: %[[a4:.*]] = fir.box_addr %[[a3]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
! CHECK-DAG: %[[b3:.*]] = fir.load %[[b1]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
@@ -55,7 +55,7 @@ subroutine to_from_stat_errmsg
! CHECK-DAG: %[[a2:.*]] = fir.convert %[[a1]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
! CHECK-DAG: %[[b2:.*]] = fir.convert %[[b1]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
call move_alloc(from, to, stat, errMsg)
- ! CHECK: %[[stat:.*]] = fir.call @_FortranAMoveAlloc(%[[b2]], %[[a2]], %[[true]], %[[errMsg3]], %{{.*}}, %{{.*}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
+ ! CHECK: %[[stat:.*]] = fir.call @_FortranAMoveAlloc(%[[b2]], %[[a2]], %{{.*}}, %[[true]], %[[errMsg3]], %{{.*}}, %{{.*}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.ref<!fir.box<none>>, !fir.ref<none>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
! CHECK-DAG: %[[a3:.*]] = fir.load %[[a1:.*]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
! CHECK-DAG: %[[a4:.*]] = fir.box_addr %[[a3]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
! CHECK-DAG: %[[b3:.*]] = fir.load %[[b1]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
diff --git a/flang/test/Lower/polymorphic.f90 b/flang/test/Lower/polymorphic.f90
index da48b61d71fb4..f2e7cac545625 100644
--- a/flang/test/Lower/polymorphic.f90
+++ b/flang/test/Lower/polymorphic.f90
@@ -987,6 +987,20 @@ subroutine test_char_to_up_pointer(c)
! CHECK: fir.store %[[EMBOX]] to %[[NEW_BOX]] : !fir.ref<!fir.class<!fir.ptr<none>>>
! CHECK: fir.call @_QMpolymorphic_testPup_pointer(%[[NEW_BOX]]) {{.*}} : (!fir.ref<!fir.class<!fir.ptr<none>>>) -> ()
+ subroutine move_alloc_poly(a, b)
+ class(p1), allocatable :: a, b
+
+ call move_alloc(a, b)
+ end subroutine
+
+! CHECK-LABEL: func.func @_QMpolymorphic_testPmove_alloc_poly(
+! CHECK-SAME: %[[A:.*]]: !fir.ref<!fir.class<!fir.heap<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>>> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref<!fir.class<!fir.heap<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>>> {fir.bindc_name = "b"}) {
+! CHECK: %[[TYPE_DESC:.*]] = fir.type_desc !fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>
+! CHECK: %[[B_CONV:.*]] = fir.convert %[[B]] : (!fir.ref<!fir.class<!fir.heap<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %[[A_CONV:.*]] = fir.convert %[[A]] : (!fir.ref<!fir.class<!fir.heap<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %[[TYPE_DESC_CONV:.*]] = fir.convert %[[TYPE_DESC]] : (!fir.tdesc<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>) -> !fir.ref<none>
+! CHECK: %{{.*}} = fir.call @_FortranAMoveAlloc(%[[B_CONV]], %[[A_CONV]], %[[TYPE_DESC_CONV]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}} : (!fir.ref<!fir.box<none>>, !fir.ref<!fir.box<none>>, !fir.ref<none>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
+
end module
program test
diff --git a/flang/unittests/Optimizer/Builder/Runtime/AllocatableTest.cpp b/flang/unittests/Optimizer/Builder/Runtime/AllocatableTest.cpp
index 20dd80dc8f8a1..1db43cacc90f0 100644
--- a/flang/unittests/Optimizer/Builder/Runtime/AllocatableTest.cpp
+++ b/flang/unittests/Optimizer/Builder/Runtime/AllocatableTest.cpp
@@ -22,5 +22,5 @@ TEST_F(RuntimeCallTest, genMoveAlloc) {
mlir::Value errMsg = firBuilder->create<fir::UndefOp>(loc, seqTy);
mlir::Value hasStat = firBuilder->createBool(loc, false);
fir::runtime::genMoveAlloc(*firBuilder, loc, to, from, hasStat, errMsg);
- checkCallOpFromResultBox(to, "_FortranAMoveAlloc", 4);
+ checkCallOpFromResultBox(to, "_FortranAMoveAlloc", 5);
}
diff --git a/flang/unittests/Runtime/Allocatable.cpp b/flang/unittests/Runtime/Allocatable.cpp
index b6bc759a0ecf5..8e1ec467b89f1 100644
--- a/flang/unittests/Runtime/Allocatable.cpp
+++ b/flang/unittests/Runtime/Allocatable.cpp
@@ -32,13 +32,13 @@ TEST(AllocatableTest, MoveAlloc) {
EXPECT_FALSE(b->IsAllocated());
// Simple move_alloc
- RTNAME(MoveAlloc)(*b, *a, false, nullptr, __FILE__, __LINE__);
+ RTNAME(MoveAlloc)(*b, *a, nullptr, false, nullptr, __FILE__, __LINE__);
EXPECT_FALSE(a->IsAllocated());
EXPECT_TRUE(b->IsAllocated());
// move_alloc with stat
std::int32_t stat{
- RTNAME(MoveAlloc)(*a, *b, true, nullptr, __FILE__, __LINE__)};
+ RTNAME(MoveAlloc)(*a, *b, nullptr, true, nullptr, __FILE__, __LINE__)};
EXPECT_TRUE(a->IsAllocated());
EXPECT_FALSE(b->IsAllocated());
EXPECT_EQ(stat, 0);
@@ -47,23 +47,26 @@ TEST(AllocatableTest, MoveAlloc) {
auto errMsg{Descriptor::Create(
sizeof(char), 64, nullptr, 0, nullptr, CFI_attribute_allocatable)};
errMsg->Allocate();
- RTNAME(MoveAlloc)(*b, *a, false, errMsg.get(), __FILE__, __LINE__);
+ RTNAME(MoveAlloc)(*b, *a, nullptr, false, errMsg.get(), __FILE__, __LINE__);
EXPECT_FALSE(a->IsAllocated());
EXPECT_TRUE(b->IsAllocated());
// move_alloc with stat and errMsg
- stat = RTNAME(MoveAlloc)(*a, *b, true, errMsg.get(), __FILE__, __LINE__);
+ stat = RTNAME(MoveAlloc)(
+ *a, *b, nullptr, true, errMsg.get(), __FILE__, __LINE__);
EXPECT_TRUE(a->IsAllocated());
EXPECT_FALSE(b->IsAllocated());
EXPECT_EQ(stat, 0);
// move_alloc with the same deallocated array
- stat = RTNAME(MoveAlloc)(*b, *b, true, errMsg.get(), __FILE__, __LINE__);
+ stat = RTNAME(MoveAlloc)(
+ *b, *b, nullptr, true, errMsg.get(), __FILE__, __LINE__);
EXPECT_FALSE(b->IsAllocated());
EXPECT_EQ(stat, 0);
// move_alloc with the same allocated array should fail
- stat = RTNAME(MoveAlloc)(*a, *a, true, errMsg.get(), __FILE__, __LINE__);
+ stat = RTNAME(MoveAlloc)(
+ *a, *a, nullptr, true, errMsg.get(), __FILE__, __LINE__);
EXPECT_EQ(stat, 109);
std::string_view errStr{errMsg->OffsetElement(), errMsg->ElementBytes()};
auto trim_pos = errStr.find_last_not_of(' ');
More information about the flang-commits
mailing list