[flang-commits] [flang] 0cf70a3 - [flang] Allow conversion from boxed derived type to fir.class

Valentin Clement via flang-commits flang-commits at lists.llvm.org
Sun Oct 9 23:59:18 PDT 2022


Author: Valentin Clement
Date: 2022-10-10T08:59:09+02:00
New Revision: 0cf70a33f296544088cfce5d777acd85b72280a4

URL: https://github.com/llvm/llvm-project/commit/0cf70a33f296544088cfce5d777acd85b72280a4
DIFF: https://github.com/llvm/llvm-project/commit/0cf70a33f296544088cfce5d777acd85b72280a4.diff

LOG: [flang] Allow conversion from boxed derived type to fir.class

This patch updates the fir.convert operation's verifier to allow
conversion from !fir.box<!fir.type<T>> to !fir.class<!fir.type<T>>.

Other conversion involving fir.class are likely needed but will
be added when lowering needs them.

Reviewed By: PeteSteinfeld

Differential Revision: https://reviews.llvm.org/D135445

Added: 
    

Modified: 
    flang/include/flang/Optimizer/Dialect/FIRType.h
    flang/lib/Optimizer/Dialect/FIROps.cpp
    flang/lib/Optimizer/Dialect/FIRType.cpp
    flang/test/Lower/polymorphic.f90
    flang/unittests/Optimizer/FIRTypesTest.cpp

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Optimizer/Dialect/FIRType.h b/flang/include/flang/Optimizer/Dialect/FIRType.h
index b2f0c6b018c46..1bd6ed1bf06e9 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRType.h
+++ b/flang/include/flang/Optimizer/Dialect/FIRType.h
@@ -38,6 +38,9 @@ class BaseBoxType : public mlir::Type {
   /// Returns the element type of this box type.
   mlir::Type getEleTy() const;
 
+  /// Unwrap element type from fir.heap, fir.ptr and fir.array.
+  mlir::Type unwrapInnerType() const;
+
   /// Methods for support type inquiry through isa, cast, and dyn_cast.
   static bool classof(mlir::Type type);
 };
@@ -273,6 +276,10 @@ bool isPointerType(mlir::Type ty);
 /// Return true iff `ty` is the type of an ALLOCATABLE entity or value.
 bool isAllocatableType(mlir::Type ty);
 
+/// Return true iff `ty` is the type of a boxed record type.
+/// e.g. !fir.box<!fir.type<derived>>
+bool isBoxedRecordType(mlir::Type ty);
+
 /// Return true iff `ty` is the type of an polymorphic entity or
 /// value.
 bool isPolymorphicType(mlir::Type ty);

diff  --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp
index 9666677bcd867..7e59506e97afc 100644
--- a/flang/lib/Optimizer/Dialect/FIROps.cpp
+++ b/flang/lib/Optimizer/Dialect/FIROps.cpp
@@ -916,7 +916,8 @@ mlir::LogicalResult fir::ConvertOp::verify() {
       (isPointerCompatible(inType) && isIntegerCompatible(outType)) ||
       (inType.isa<fir::BoxType>() && outType.isa<fir::BoxType>()) ||
       (inType.isa<fir::BoxProcType>() && outType.isa<fir::BoxProcType>()) ||
-      (fir::isa_complex(inType) && fir::isa_complex(outType)))
+      (fir::isa_complex(inType) && fir::isa_complex(outType)) ||
+      (fir::isBoxedRecordType(inType) && fir::isPolymorphicType(outType)))
     return mlir::success();
   return emitOpError("invalid type conversion");
 }

diff  --git a/flang/lib/Optimizer/Dialect/FIRType.cpp b/flang/lib/Optimizer/Dialect/FIRType.cpp
index 40ebf3760ea3f..67b4d1af7cf17 100644
--- a/flang/lib/Optimizer/Dialect/FIRType.cpp
+++ b/flang/lib/Optimizer/Dialect/FIRType.cpp
@@ -262,6 +262,18 @@ bool isAllocatableType(mlir::Type ty) {
   return false;
 }
 
+bool isBoxedRecordType(mlir::Type ty) {
+  if (auto refTy = fir::dyn_cast_ptrEleTy(ty))
+    ty = refTy;
+  if (auto boxTy = ty.dyn_cast<fir::BoxType>()) {
+    if (boxTy.getEleTy().isa<fir::RecordType>())
+      return true;
+    mlir::Type innerType = boxTy.unwrapInnerType();
+    return innerType && innerType.isa<fir::RecordType>();
+  }
+  return false;
+}
+
 static bool isAssumedType(mlir::Type ty) {
   if (auto boxTy = ty.dyn_cast<fir::BoxType>()) {
     if (boxTy.getEleTy().isa<mlir::NoneType>())
@@ -289,17 +301,8 @@ bool isUnlimitedPolymorphicType(mlir::Type ty) {
   if (auto clTy = ty.dyn_cast<fir::ClassType>()) {
     if (clTy.getEleTy().isa<mlir::NoneType>())
       return true;
-    mlir::Type innerType =
-        llvm::TypeSwitch<mlir::Type, mlir::Type>(clTy.getEleTy())
-            .Case<fir::PointerType, fir::HeapType, fir::SequenceType>(
-                [](auto ty) {
-                  mlir::Type eleTy = ty.getEleTy();
-                  if (auto seqTy = eleTy.dyn_cast<fir::SequenceType>())
-                    return seqTy.getEleTy();
-                  return eleTy;
-                })
-            .Default([](mlir::Type) { return mlir::Type{}; });
-    return innerType.isa<mlir::NoneType>();
+    mlir::Type innerType = clTy.unwrapInnerType();
+    return innerType && innerType.isa<mlir::NoneType>();
   }
   // TYPE(*)
   return isAssumedType(ty);
@@ -982,6 +985,17 @@ mlir::Type BaseBoxType::getEleTy() const {
           [](auto type) { return type.getEleTy(); });
 }
 
+mlir::Type BaseBoxType::unwrapInnerType() const {
+  return llvm::TypeSwitch<mlir::Type, mlir::Type>(getEleTy())
+      .Case<fir::PointerType, fir::HeapType, fir::SequenceType>([](auto ty) {
+        mlir::Type eleTy = ty.getEleTy();
+        if (auto seqTy = eleTy.dyn_cast<fir::SequenceType>())
+          return seqTy.getEleTy();
+        return eleTy;
+      })
+      .Default([](mlir::Type) { return mlir::Type{}; });
+}
+
 //===----------------------------------------------------------------------===//
 // FIROpsDialect
 //===----------------------------------------------------------------------===//

diff  --git a/flang/test/Lower/polymorphic.f90 b/flang/test/Lower/polymorphic.f90
index 03e917b82f177..6c690317352a0 100644
--- a/flang/test/Lower/polymorphic.f90
+++ b/flang/test/Lower/polymorphic.f90
@@ -6,6 +6,8 @@ module polymorphic_test
   type p1
     integer :: a
     integer :: b
+  contains
+    procedure :: print
   end type
 
   type, extends(p1) :: p2
@@ -27,4 +29,25 @@ subroutine component_access(p)
 ! CHECK: %[[LOAD:.*]] = fir.load %[[COORD]] : !fir.ref<i32>
 ! CHECK: %{{.*}} = fir.call @_FortranAioOutputInteger32(%{{.*}}, %[[LOAD]]) : (!fir.ref<i8>, i32) -> i1
 
+  subroutine print(this)
+    class(p1) :: this
+  end subroutine
+
+  ! Test passing fir.convert accept fir.box<DT> -> fir.class<DT>
+  subroutine check()
+    type(p1) :: t1
+    type(p2) :: t2
+    call t1%print()
+    call t2%print()
+  end subroutine
+
+! 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.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>) -> !fir.box<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>
+! CHECK: %[[CLASS1:.*]] = fir.convert %[[BOX1]] : (!fir.box<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>) -> !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>
+! CHECK: fir.call @_QMpolymorphic_testPprint(%[[CLASS1]]) : (!fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>) -> ()
+! CHECK: %[[BOX2:.*]] = fir.embox %[[DT2]] : (!fir.ref<!fir.type<_QMpolymorphic_testTp2{a:i32,b:i32,c:f32}>>) -> !fir.box<!fir.type<_QMpolymorphic_testTp2{a:i32,b:i32,c:f32}>>
+! CHECK: %[[CLASS2:.*]] = fir.convert %[[BOX2]] : (!fir.box<!fir.type<_QMpolymorphic_testTp2{a:i32,b:i32,c:f32}>>) -> !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>
+! CHECK: fir.call @_QMpolymorphic_testPprint(%[[CLASS2]]) : (!fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>) -> ()
 end module

diff  --git a/flang/unittests/Optimizer/FIRTypesTest.cpp b/flang/unittests/Optimizer/FIRTypesTest.cpp
index 1a81c2ff426f7..580415e5c8b2d 100644
--- a/flang/unittests/Optimizer/FIRTypesTest.cpp
+++ b/flang/unittests/Optimizer/FIRTypesTest.cpp
@@ -117,3 +117,32 @@ TEST_F(FIRTypesTest, isUnlimitedPolymorphicTypeTest) {
   EXPECT_FALSE(fir::isUnlimitedPolymorphicType(noneTy));
   EXPECT_FALSE(fir::isUnlimitedPolymorphicType(seqNoneTy));
 }
+
+// Test fir::isBoxedRecordType from flang/Optimizer/Dialect/FIRType.h.
+TEST_F(FIRTypesTest, isBoxedRecordType) {
+  mlir::Type recTy = fir::RecordType::get(&context, "dt");
+  mlir::Type seqRecTy =
+      fir::SequenceType::get({fir::SequenceType::getUnknownExtent()}, recTy);
+  mlir::Type ty = fir::BoxType::get(recTy);
+  EXPECT_TRUE(fir::isBoxedRecordType(ty));
+  EXPECT_TRUE(fir::isBoxedRecordType(fir::ReferenceType::get(ty)));
+
+  // TYPE(T), ALLOCATABLE
+  ty = fir::BoxType::get(fir::HeapType::get(recTy));
+  EXPECT_TRUE(fir::isBoxedRecordType(ty));
+
+  // TYPE(T), POINTER
+  ty = fir::BoxType::get(fir::PointerType::get(recTy));
+  EXPECT_TRUE(fir::isBoxedRecordType(ty));
+
+  // TYPE(T), DIMENSION(10)
+  ty = fir::BoxType::get(fir::SequenceType::get({10}, recTy));
+  EXPECT_TRUE(fir::isBoxedRecordType(ty));
+
+  // TYPE(T), DIMENSION(:)
+  ty = fir::BoxType::get(seqRecTy);
+  EXPECT_TRUE(fir::isBoxedRecordType(ty));
+
+  EXPECT_FALSE(fir::isBoxedRecordType(fir::BoxType::get(
+      fir::ReferenceType::get(mlir::IntegerType::get(&context, 32)))));
+}


        


More information about the flang-commits mailing list