[flang-commits] [flang] 92bdc6a - [flang] allow allocation of scalar TYPE(*) descriptors

Jean Perier via flang-commits flang-commits at lists.llvm.org
Fri Mar 31 00:14:04 PDT 2023


Author: Jean Perier
Date: 2023-03-31T09:13:06+02:00
New Revision: 92bdc6ad01936cdb7fab389ad94d6f0ae4832021

URL: https://github.com/llvm/llvm-project/commit/92bdc6ad01936cdb7fab389ad94d6f0ae4832021
DIFF: https://github.com/llvm/llvm-project/commit/92bdc6ad01936cdb7fab389ad94d6f0ae4832021.diff

LOG: [flang] allow allocation of scalar TYPE(*) descriptors

Currently, it is OK to have alloca/store/and reboxed to
fir.box<!fir.array<?xnone>> and fir.class<none>, but not simple
fir.box<none>.
This restriction is a legacy from a time where it was thought TYPE(*)
descriptor size would not be statically known, but the way polymorphism
was implemented actually allows knowing its size: a scalar descriptor
with an addendum (in case it is a derived type).
Note that this assumes fir.box<none> are always scalars. There are currently
a few cast from ranked descriptor to !fir.box<None> around runtime calls.
These are simple casts before runtime call, so there are no load/stores
to the resulting fir.box<None> and it is OK.
When assumed rank are supported, some legacy usage of fir.box<none> as the "any"
descriptor in the runtime interface will be replaced to avoid any issues there.

This change will be required to fix an undefined behavior with NULL() that
requires allocation of a fir.box<None>.

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

Added: 
    

Modified: 
    flang/include/flang/Optimizer/Dialect/FIRType.h
    flang/lib/Optimizer/Dialect/FIRType.cpp
    flang/test/Fir/alloc.fir
    flang/test/Fir/convert-to-llvm.fir
    flang/test/Fir/rebox.fir

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Optimizer/Dialect/FIRType.h b/flang/include/flang/Optimizer/Dialect/FIRType.h
index 942c789bcb899..10435db031665 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRType.h
+++ b/flang/include/flang/Optimizer/Dialect/FIRType.h
@@ -173,7 +173,9 @@ inline bool isa_char_string(mlir::Type t) {
 
 /// Is `t` a box type for which it is not possible to deduce the box size?
 /// It is not possible to deduce the size of a box that describes an entity
-/// of unknown rank or type.
+/// of unknown rank.
+/// Unknown type are always considered to have the size of derived type box
+/// (since they may hold one), and are not considered to be unknown size.
 bool isa_unknown_size_box(mlir::Type t);
 
 /// Returns true iff `t` is a fir.char type and has an unknown length.

diff  --git a/flang/lib/Optimizer/Dialect/FIRType.cpp b/flang/lib/Optimizer/Dialect/FIRType.cpp
index c15244d349906..75d71890a7394 100644
--- a/flang/lib/Optimizer/Dialect/FIRType.cpp
+++ b/flang/lib/Optimizer/Dialect/FIRType.cpp
@@ -403,13 +403,9 @@ void fir::printFirType(FIROpsDialect *, mlir::Type ty,
 }
 
 bool fir::isa_unknown_size_box(mlir::Type t) {
-  if (auto boxTy = t.dyn_cast<fir::BoxType>()) {
-    auto eleTy = boxTy.getEleTy();
-    if (auto actualEleTy = fir::dyn_cast_ptrEleTy(eleTy))
-      eleTy = actualEleTy;
-    if (eleTy.isa<mlir::NoneType>())
-      return true;
-    if (auto seqTy = eleTy.dyn_cast<fir::SequenceType>())
+  if (auto boxTy = t.dyn_cast<fir::BaseBoxType>()) {
+    auto valueType = fir::unwrapPassByRefType(boxTy);
+    if (auto seqTy = valueType.dyn_cast<fir::SequenceType>())
       if (seqTy.hasUnknownShape())
         return true;
   }

diff  --git a/flang/test/Fir/alloc.fir b/flang/test/Fir/alloc.fir
index 4e6faefa31d71..ca624c0d1f9d6 100644
--- a/flang/test/Fir/alloc.fir
+++ b/flang/test/Fir/alloc.fir
@@ -333,3 +333,19 @@ func.func @allocmem_array_with_holes_dynchar(%arg0: index, %arg1: index) -> !fir
   return %1 : !fir.heap<!fir.array<3x?x4x!fir.char<2,?>>>
 }
 
+// CHECK-LABEL: define void @alloca_unlimited_polymorphic_box
+// CHECK:    %[[VAL_0:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, i64 1
+// CHECK:    %[[VAL_1:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, i64 1
+// CHECK:    %[[VAL_2:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, i64 1
+// CHECK:    %[[VAL_3:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, i64 1
+
+func.func @alloca_unlimited_polymorphic_box() {
+  %0 = fir.alloca !fir.class<none>
+  %1 = fir.alloca !fir.class<!fir.array<?xnone>>
+  %2 = fir.alloca !fir.box<none>
+  %3 = fir.alloca !fir.box<!fir.array<?xnone>>
+  return
+}
+// Note: allocmem of fir.box are not possible (fir::HeapType::verify does not
+// accept box types), so there is no equivalent of
+// alloca_unlimited_polymorphic_box for allocmem.

diff  --git a/flang/test/Fir/convert-to-llvm.fir b/flang/test/Fir/convert-to-llvm.fir
index cbfb2283ccbc6..75f6a6c659d40 100644
--- a/flang/test/Fir/convert-to-llvm.fir
+++ b/flang/test/Fir/convert-to-llvm.fir
@@ -862,6 +862,25 @@ func.func @test_store_box(%array : !fir.ref<!fir.box<!fir.array<?x?xf32>>>, %box
 // CHECK-NEXT:  llvm.return
 // CHECK-NEXT:  }
 
+
+func.func @store_unlimited_polymorphic_box(%arg0 : !fir.class<none>, %arg1 : !fir.class<!fir.array<?xnone>>, %arg2 : !fir.box<none>, %arg3 : !fir.box<!fir.array<?xnone>>, %arg0r : !fir.ref<!fir.class<none>>, %arg1r : !fir.ref<!fir.class<!fir.array<?xnone>>>, %arg2r : !fir.ref<!fir.box<none>>, %arg3r : !fir.ref<!fir.box<!fir.array<?xnone>>>) {
+  fir.store %arg0 to %arg0r : !fir.ref<!fir.class<none>>
+  fir.store %arg1 to %arg1r : !fir.ref<!fir.class<!fir.array<?xnone>>>
+  fir.store %arg2 to %arg2r : !fir.ref<!fir.box<none>>
+  fir.store %arg3 to %arg3r : !fir.ref<!fir.box<!fir.array<?xnone>>>
+  return
+}
+// CHECK-LABEL:   llvm.func @store_unlimited_polymorphic_box(
+// CHECK:  %[[VAL_8:.*]] = llvm.load %{{.*}} : !llvm.ptr<struct<(ptr<struct<()>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, ptr<i{{.*}}>, array<1 x i{{.*}}>)>>
+// CHECK:  llvm.store %[[VAL_8]], %{{.*}} : !llvm.ptr<struct<(ptr<struct<()>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, ptr<i{{.*}}>, array<1 x i{{.*}}>)>>
+// CHECK:  %[[VAL_9:.*]] = llvm.load %{{.*}} : !llvm.ptr<struct<(ptr<struct<()>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i{{.*}}>>, ptr<i{{.*}}>, array<1 x i{{.*}}>)>>
+// CHECK:  llvm.store %[[VAL_9]], %{{.*}} : !llvm.ptr<struct<(ptr<struct<()>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i{{.*}}>>, ptr<i{{.*}}>, array<1 x i{{.*}}>)>>
+// CHECK:  %[[VAL_10:.*]] = llvm.load %{{.*}} : !llvm.ptr<struct<(ptr<struct<()>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, ptr<i{{.*}}>, array<1 x i{{.*}}>)>>
+// CHECK:  llvm.store %[[VAL_10]], %{{.*}} : !llvm.ptr<struct<(ptr<struct<()>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, ptr<i{{.*}}>, array<1 x i{{.*}}>)>>
+// CHECK:  %[[VAL_11:.*]] = llvm.load %{{.*}}: !llvm.ptr<struct<(ptr<struct<()>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i{{.*}}>>, ptr<i{{.*}}>, array<1 x i{{.*}}>)>>
+// CHECK:  llvm.store %[[VAL_11]], %{{.*}} : !llvm.ptr<struct<(ptr<struct<()>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i{{.*}}>>, ptr<i{{.*}}>, array<1 x i{{.*}}>)>>
+
+
 // -----
 
 // Test `fir.load` --> `llvm.load` conversion

diff  --git a/flang/test/Fir/rebox.fir b/flang/test/Fir/rebox.fir
index 60f4d59b5f732..76cace9646827 100644
--- a/flang/test/Fir/rebox.fir
+++ b/flang/test/Fir/rebox.fir
@@ -132,3 +132,24 @@ func.func @test_rebox_4(%arg0: !fir.box<!fir.array<?x!fir.char<1,?>>>) {
   return
 }
 func.func private @bar_test_rebox_4(!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,10>>>>)
+
+
+// Test reboxing of unlimited polymorphic.
+
+func.func @rebox_unlimited_polymorphic_box(%arg0 : !fir.class<!fir.array<?xnone>>, %arg1 : !fir.box<!fir.array<?xnone>>, %arg0r : !fir.ref<!fir.class<!fir.array<?xnone>>>, %arg1r : !fir.ref<!fir.box<!fir.array<?xnone>>>) {
+  %c1 = arith.constant 1 : index
+  %c10 = arith.constant 10 : index
+  %1 = fir.slice %c1, %c10, %c1 : (index, index, index) -> !fir.slice<1>
+  %2 = fir.rebox %arg0 [%1] : (!fir.class<!fir.array<?xnone>>, !fir.slice<1>) -> !fir.class<!fir.array<?xnone>>
+  %3 = fir.rebox %arg1 [%1] : (!fir.box<!fir.array<?xnone>>, !fir.slice<1>) -> !fir.box<!fir.array<?xnone>>
+  fir.store %2 to %arg0r : !fir.ref<!fir.class<!fir.array<?xnone>>>
+  fir.store %3 to %arg1r : !fir.ref<!fir.box<!fir.array<?xnone>>>
+  return
+}
+// CHECK-LABEL: define void @rebox_unlimited_polymorphic_box
+// CHECK:  %[[VAL_16:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }
+// CHECK:  %[[VAL_17:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }
+// ...
+// CHECK:  store { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] } %{{.*}}, ptr %[[VAL_17]]
+// ...
+// CHECK:  store { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] } %{{.*}}, ptr %[[VAL_16]]


        


More information about the flang-commits mailing list