[flang-commits] [flang] 959caaa - [flang] Add conditional rebox when passing fir.box to optional fir.class
Valentin Clement via flang-commits
flang-commits at lists.llvm.org
Mon Jan 23 06:42:16 PST 2023
Author: Valentin Clement
Date: 2023-01-23T15:42:04+01:00
New Revision: 959caaaa7b2954ccc16f60b05d998e336bf36b38
URL: https://github.com/llvm/llvm-project/commit/959caaaa7b2954ccc16f60b05d998e336bf36b38
DIFF: https://github.com/llvm/llvm-project/commit/959caaaa7b2954ccc16f60b05d998e336bf36b38.diff
LOG: [flang] Add conditional rebox when passing fir.box to optional fir.class
When a `!fir.box<>` is passed as an actual argument to an optional
`!fir.class<>` dummy it needs a `fir.rebox` in order to propagate
the dynamic type information.
The `fir.rebox` needs to happen only on present argument.
Reviewed By: jeanPerier
Differential Revision: https://reviews.llvm.org/D142340
Added:
Modified:
flang/lib/Lower/ConvertExpr.cpp
flang/lib/Optimizer/CodeGen/CodeGen.cpp
flang/test/Lower/polymorphic.f90
Removed:
################################################################################
diff --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp
index d64b28cf7873d..2df4d90482518 100644
--- a/flang/lib/Lower/ConvertExpr.cpp
+++ b/flang/lib/Lower/ConvertExpr.cpp
@@ -2709,11 +2709,16 @@ class ScalarExprLowering {
// select op requires the same type for its two argument, convert
// !fir.box<none> to !fir.class<none> when the argument is
// polymorphic.
- if (fir::isBoxNone(box.getType()) && fir::isPolymorphicType(argTy))
+ if (fir::isBoxNone(box.getType()) && fir::isPolymorphicType(argTy)) {
box = builder.createConvert(
loc,
fir::ClassType::get(mlir::NoneType::get(builder.getContext())),
box);
+ } else if (box.getType().isa<fir::BoxType>() &&
+ fir::isPolymorphicType(argTy)) {
+ box = builder.create<fir::ReboxOp>(loc, argTy, box, mlir::Value{},
+ /*slice=*/mlir::Value{});
+ }
// Need the box types to be exactly similar for the selectOp.
mlir::Value convertedBox = builder.createConvert(loc, argTy, box);
@@ -2728,6 +2733,34 @@ class ScalarExprLowering {
fir::isPolymorphicType(argTy))
: builder.createBox(getLoc(), genTempExtAddr(*expr),
fir::isPolymorphicType(argTy));
+
+ if (box.getType().isa<fir::BoxType>() &&
+ fir::isPolymorphicType(argTy)) {
+ // Rebox can only be performed on a present argument.
+ if (arg.isOptional()) {
+ mlir::Value isPresent = genActualIsPresentTest(builder, loc, box);
+ box =
+ builder
+ .genIfOp(loc, {argTy}, isPresent, /*withElseRegion=*/true)
+ .genThen([&]() {
+ auto rebox = builder
+ .create<fir::ReboxOp>(
+ loc, argTy, box, mlir::Value{},
+ /*slice=*/mlir::Value{})
+ .getResult();
+ builder.create<fir::ResultOp>(loc, rebox);
+ })
+ .genElse([&]() {
+ auto absent = builder.create<fir::AbsentOp>(loc, argTy)
+ .getResult();
+ builder.create<fir::ResultOp>(loc, absent);
+ })
+ .getResults()[0];
+ } else {
+ box = builder.create<fir::ReboxOp>(loc, argTy, box, mlir::Value{},
+ /*slice=*/mlir::Value{});
+ }
+ }
caller.placeInput(arg, box);
}
} else if (arg.passBy == PassBy::AddressAndLength) {
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index 31b6498931b9b..dd5dee8b3a8af 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -1346,6 +1346,10 @@ struct EmboxCommonConversion : public FIROpConversion<OP> {
static bool isDerivedType(fir::BaseBoxType boxTy) {
return static_cast<bool>(unwrapIfDerived(boxTy));
}
+ static bool hasAddendum(fir::BaseBoxType boxTy) {
+ return static_cast<bool>(unwrapIfDerived(boxTy)) ||
+ fir::isUnlimitedPolymorphicType(boxTy);
+ }
// Get the element size and CFI type code of the boxed value.
std::tuple<mlir::Value, mlir::Value> getSizeAndTypeCode(
@@ -1647,6 +1651,7 @@ struct EmboxCommonConversion : public FIROpConversion<OP> {
mlir::Value typeDesc = {}) const {
auto loc = box.getLoc();
auto boxTy = box.getType().dyn_cast<fir::BaseBoxType>();
+ auto inputBoxTy = box.getBox().getType().dyn_cast<fir::BaseBoxType>();
llvm::SmallVector<mlir::Value> typeparams = lenParams;
if (!box.getSubstr().empty() && fir::hasDynamicSize(boxTy.getEleTy()))
typeparams.push_back(box.getSubstr()[1]);
@@ -1654,17 +1659,22 @@ struct EmboxCommonConversion : public FIROpConversion<OP> {
auto [eleSize, cfiTy] =
getSizeAndTypeCode(loc, rewriter, boxTy.getEleTy(), typeparams);
- // Reboxing a polymorphic entities. eleSize and type code need to
+ // Reboxing to a polymorphic entity. eleSize and type code need to
// be retrived from the initial box and propagated to the new box.
- if (fir::isPolymorphicType(boxTy) &&
- fir::isPolymorphicType(box.getBox().getType())) {
+ // If the initial box has an addendum, the type desc must be propagated as
+ // well.
+ if (fir::isPolymorphicType(boxTy)) {
mlir::Type idxTy = this->lowerTy().indexType();
eleSize =
this->getElementSizeFromBox(loc, idxTy, boxTy, loweredBox, rewriter);
cfiTy = this->getValueFromBox(loc, boxTy, loweredBox, cfiTy.getType(),
rewriter, kTypePosInBox);
- typeDesc = this->loadTypeDescAddress(loc, box.getBox().getType(),
- loweredBox, rewriter);
+ // TODO: For initial box that are unlimited polymorphic entities, this
+ // code must be made conditional because unlimited polymorphic entities
+ // with intrinsic type spec does not have addendum.
+ if (hasAddendum(inputBoxTy))
+ typeDesc = this->loadTypeDescAddress(loc, box.getBox().getType(),
+ loweredBox, rewriter);
}
auto mod = box->template getParentOfType<mlir::ModuleOp>();
diff --git a/flang/test/Lower/polymorphic.f90 b/flang/test/Lower/polymorphic.f90
index ac6ae85bfdf23..52e4498a8d765 100644
--- a/flang/test/Lower/polymorphic.f90
+++ b/flang/test/Lower/polymorphic.f90
@@ -789,6 +789,41 @@ subroutine test_call_with_null()
! CHECK: %[[ARG:.*]] = arith.select %[[IS_ALLOCATED_OR_ASSOCIATED]], %[[CLASS_NONE]], %[[ABSENT]] : !fir.class<none>
! CHECK: fir.call @_QMpolymorphic_testPsub_with_poly_optional(%[[ARG]]) {{.*}} : (!fir.class<none>) -> ()
+ subroutine sub_with_poly_array_optional(a)
+ class(*), optional :: a(:)
+ end subroutine
+
+ subroutine test_call_with_pointer_to_optional()
+ real, pointer :: p(:)
+ call sub_with_poly_array_optional(p)
+ end subroutine
+
+! CHECK-LABEL: func.func @_QMpolymorphic_testPtest_call_with_pointer_to_optional() {
+! CHECK: %[[P:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?xf32>>> {bindc_name = "p", uniq_name = "_QMpolymorphic_testFtest_call_with_pointer_to_optionalEp"}
+! CHECK: %[[IS_ALLOCATED_OR_ASSOCIATED:.*]] = arith.cmpi ne
+! CHECK: %[[ABSENT:.*]] = fir.absent !fir.class<!fir.array<?xnone>>
+! CHECK: %[[LOAD_P:.*]] = fir.load %[[P]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
+! CHECK: %[[REBOX:.*]] = fir.rebox %[[LOAD_P]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>) -> !fir.class<!fir.array<?xnone>>
+! CHECK: %[[ARG:.*]] = arith.select %[[IS_ALLOCATED_OR_ASSOCIATED]], %[[REBOX]], %[[ABSENT]] : !fir.class<!fir.array<?xnone>>
+! CHECK: fir.call @_QMpolymorphic_testPsub_with_poly_array_optional(%[[ARG]]) {{.*}} : (!fir.class<!fir.array<?xnone>>) -> ()
+
+ subroutine sub_with_real_pointer_optional(p)
+ real, optional :: p(:)
+ call sub_with_poly_array_optional(p)
+ end subroutine
+
+! CHECK-LABEL: func.func @_QMpolymorphic_testPsub_with_real_pointer_optional(
+! CHECK-SAME: %[[P:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "p", fir.optional}) {
+! CHECK: %[[IS_PRESENT:.*]] = fir.is_present %[[P]] : (!fir.box<!fir.array<?xf32>>) -> i1
+! CHECK: %[[BOX:.*]] = fir.if %[[IS_PRESENT]] -> (!fir.class<!fir.array<?xnone>>) {
+! CHECK: %[[REBOX:.*]] = fir.rebox %[[P]] : (!fir.box<!fir.array<?xf32>>) -> !fir.class<!fir.array<?xnone>>
+! CHECK: fir.result %[[REBOX]] : !fir.class<!fir.array<?xnone>>
+! CHECK: } else {
+! CHECK: %[[ABSENT:.*]] = fir.absent !fir.class<!fir.array<?xnone>>
+! CHECK: fir.result %[[ABSENT]] : !fir.class<!fir.array<?xnone>>
+! CHECK: }
+! CHECK: fir.call @_QMpolymorphic_testPsub_with_poly_array_optional(%[[BOX]]) {{.*}} : (!fir.class<!fir.array<?xnone>>) -> ()
+
end module
program test
More information about the flang-commits
mailing list