From 89c923655aad6de837e386aa6e1dfa72c16e2697 Mon Sep 17 00:00:00 2001 From: Valentin Clement Date: Thu, 13 Oct 2022 10:39:29 +0200 Subject: [PATCH] [flang] Embox derived-type directly to fir.class without fir.convert non-polymorphic derived-type can call type-bound procedure with passed-object. In that case, the derived-type is emboxed in order to be passed to the call. Until now the emboxing was done to a fir.box followed by a fir.convert. This patch update the createBox function so that we can directly embox to a fir.class and avoid the extra fir.convert. Reviewed By: PeteSteinfeld Differential Revision: https://reviews.llvm.org/D135790 --- flang/include/flang/Optimizer/Builder/FIRBuilder.h | 3 ++- flang/lib/Lower/ConvertExpr.cpp | 6 ++++-- flang/lib/Optimizer/Builder/FIRBuilder.cpp | 9 +++++++-- flang/test/Lower/polymorphic.f90 | 9 ++++----- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/flang/include/flang/Optimizer/Builder/FIRBuilder.h b/flang/include/flang/Optimizer/Builder/FIRBuilder.h index fe1350d..5cfd2ef 100644 --- a/flang/include/flang/Optimizer/Builder/FIRBuilder.h +++ b/flang/include/flang/Optimizer/Builder/FIRBuilder.h @@ -310,7 +310,8 @@ public: /// a memory reference type. /// Array entities are boxed with a shape and possibly a shift. Character /// entities are boxed with a LEN parameter. - mlir::Value createBox(mlir::Location loc, const fir::ExtendedValue &exv); + mlir::Value createBox(mlir::Location loc, const fir::ExtendedValue &exv, + bool isPolymorphic = false); /// Create constant i1 with value 1. if \p b is true or 0. otherwise mlir::Value createBool(mlir::Location loc, bool b) { diff --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp index 70986ee..634244c 100644 --- a/flang/lib/Lower/ConvertExpr.cpp +++ b/flang/lib/Lower/ConvertExpr.cpp @@ -3410,8 +3410,10 @@ public: // actually a variable. mlir::Value box = Fortran::evaluate::IsVariable(*expr) - ? builder.createBox(loc, genBoxArg(*expr)) - : builder.createBox(getLoc(), genTempExtAddr(*expr)); + ? builder.createBox(loc, genBoxArg(*expr), + fir::isPolymorphicType(argTy)) + : builder.createBox(getLoc(), genTempExtAddr(*expr), + fir::isPolymorphicType(argTy)); caller.placeInput(arg, box); } } else if (arg.passBy == PassBy::AddressAndLength) { diff --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp index e4b3b91e..00b1e0e 100644 --- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp +++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp @@ -325,7 +325,9 @@ fir::FirOpBuilder::convertWithSemantics(mlir::Location loc, mlir::Type toTy, return create(loc, toTy, val); } - if (fir::isPolymorphicType(fromTy) && fir::isPolymorphicType(toTy)) { + if (fir::isPolymorphicType(fromTy) && + (fir::isAllocatableType(fromTy) || fir::isPointerType(fromTy)) && + fir::isPolymorphicType(toTy)) { return create(loc, toTy, val, mlir::Value{}, /*slice=*/mlir::Value{}); } @@ -463,7 +465,8 @@ mlir::Value fir::FirOpBuilder::createSlice(mlir::Location loc, } mlir::Value fir::FirOpBuilder::createBox(mlir::Location loc, - const fir::ExtendedValue &exv) { + const fir::ExtendedValue &exv, + bool isPolymorphic) { mlir::Value itemAddr = fir::getBase(exv); if (itemAddr.getType().isa()) return itemAddr; @@ -474,6 +477,8 @@ mlir::Value fir::FirOpBuilder::createBox(mlir::Location loc, llvm_unreachable("not a memory reference type"); } mlir::Type boxTy = fir::BoxType::get(elementType); + if (isPolymorphic) + boxTy = fir::ClassType::get(elementType); return exv.match( [&](const fir::ArrayBoxValue &box) -> mlir::Value { mlir::Value s = createShape(loc, exv); diff --git a/flang/test/Lower/polymorphic.f90 b/flang/test/Lower/polymorphic.f90 index 6c69031..6177845 100644 --- a/flang/test/Lower/polymorphic.f90 +++ b/flang/test/Lower/polymorphic.f90 @@ -33,7 +33,7 @@ module polymorphic_test class(p1) :: this end subroutine - ! Test passing fir.convert accept fir.box
-> fir.class
+ ! Test embox of fir.type to fir.class to be passed-object. subroutine check() type(p1) :: t1 type(p2) :: t2 @@ -44,10 +44,9 @@ module polymorphic_test ! CHECK-LABEL: func.func @_QMpolymorphic_testPcheck() ! CHECK: %[[DT1:.*]] = fir.alloca !fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}> {bindc_name = "t1", uniq_name = "_QMpolymorphic_testFcheckEt1"} ! CHECK: %[[DT2:.*]] = fir.alloca !fir.type<_QMpolymorphic_testTp2{a:i32,b:i32,c:f32}> {bindc_name = "t2", uniq_name = "_QMpolymorphic_testFcheckEt2"} -! CHECK: %[[BOX1:.*]] = fir.embox %[[DT1]] : (!fir.ref>) -> !fir.box> -! CHECK: %[[CLASS1:.*]] = fir.convert %[[BOX1]] : (!fir.box>) -> !fir.class> +! CHECK: %[[CLASS1:.*]] = fir.embox %[[DT1]] : (!fir.ref>) -> !fir.class> ! CHECK: fir.call @_QMpolymorphic_testPprint(%[[CLASS1]]) : (!fir.class>) -> () -! CHECK: %[[BOX2:.*]] = fir.embox %[[DT2]] : (!fir.ref>) -> !fir.box> -! CHECK: %[[CLASS2:.*]] = fir.convert %[[BOX2]] : (!fir.box>) -> !fir.class> +! CHECK: %[[BOX2:.*]] = fir.embox %[[DT2]] : (!fir.ref>) -> !fir.class> +! CHECK: %[[CLASS2:.*]] = fir.convert %[[BOX2]] : (!fir.class>) -> !fir.class> ! CHECK: fir.call @_QMpolymorphic_testPprint(%[[CLASS2]]) : (!fir.class>) -> () end module -- 2.7.4