diff --git a/flang/include/flang/Optimizer/Dialect/FIRType.h b/flang/include/flang/Optimizer/Dialect/FIRType.h --- a/flang/include/flang/Optimizer/Dialect/FIRType.h +++ b/flang/include/flang/Optimizer/Dialect/FIRType.h @@ -173,7 +173,9 @@ /// 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 --- a/flang/lib/Optimizer/Dialect/FIRType.cpp +++ b/flang/lib/Optimizer/Dialect/FIRType.cpp @@ -403,13 +403,9 @@ } bool fir::isa_unknown_size_box(mlir::Type t) { - if (auto boxTy = t.dyn_cast()) { - auto eleTy = boxTy.getEleTy(); - if (auto actualEleTy = fir::dyn_cast_ptrEleTy(eleTy)) - eleTy = actualEleTy; - if (eleTy.isa()) - return true; - if (auto seqTy = eleTy.dyn_cast()) + if (auto boxTy = t.dyn_cast()) { + auto valueType = fir::unwrapPassByRefType(boxTy); + if (auto seqTy = valueType.dyn_cast()) if (seqTy.hasUnknownShape()) return true; } diff --git a/flang/test/Fir/alloc.fir b/flang/test/Fir/alloc.fir --- a/flang/test/Fir/alloc.fir +++ b/flang/test/Fir/alloc.fir @@ -333,3 +333,19 @@ return %1 : !fir.heap>> } +// 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 + %1 = fir.alloca !fir.class> + %2 = fir.alloca !fir.box + %3 = fir.alloca !fir.box> + 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 --- a/flang/test/Fir/convert-to-llvm.fir +++ b/flang/test/Fir/convert-to-llvm.fir @@ -862,6 +862,25 @@ // CHECK-NEXT: llvm.return // CHECK-NEXT: } + +func.func @store_unlimited_polymorphic_box(%arg0 : !fir.class, %arg1 : !fir.class>, %arg2 : !fir.box, %arg3 : !fir.box>, %arg0r : !fir.ref>, %arg1r : !fir.ref>>, %arg2r : !fir.ref>, %arg3r : !fir.ref>>) { + fir.store %arg0 to %arg0r : !fir.ref> + fir.store %arg1 to %arg1r : !fir.ref>> + fir.store %arg2 to %arg2r : !fir.ref> + fir.store %arg3 to %arg3r : !fir.ref>> + return +} +// CHECK-LABEL: llvm.func @store_unlimited_polymorphic_box( +// CHECK: %[[VAL_8:.*]] = llvm.load %{{.*}} : !llvm.ptr>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, ptr, array<1 x i{{.*}}>)>> +// CHECK: llvm.store %[[VAL_8]], %{{.*}} : !llvm.ptr>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, ptr, array<1 x i{{.*}}>)>> +// CHECK: %[[VAL_9:.*]] = llvm.load %{{.*}} : !llvm.ptr>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i{{.*}}>>, ptr, array<1 x i{{.*}}>)>> +// CHECK: llvm.store %[[VAL_9]], %{{.*}} : !llvm.ptr>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i{{.*}}>>, ptr, array<1 x i{{.*}}>)>> +// CHECK: %[[VAL_10:.*]] = llvm.load %{{.*}} : !llvm.ptr>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, ptr, array<1 x i{{.*}}>)>> +// CHECK: llvm.store %[[VAL_10]], %{{.*}} : !llvm.ptr>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, ptr, array<1 x i{{.*}}>)>> +// CHECK: %[[VAL_11:.*]] = llvm.load %{{.*}}: !llvm.ptr>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i{{.*}}>>, ptr, array<1 x i{{.*}}>)>> +// CHECK: llvm.store %[[VAL_11]], %{{.*}} : !llvm.ptr>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i{{.*}}>>, ptr, array<1 x i{{.*}}>)>> + + // ----- // Test `fir.load` --> `llvm.load` conversion diff --git a/flang/test/Fir/rebox.fir b/flang/test/Fir/rebox.fir --- a/flang/test/Fir/rebox.fir +++ b/flang/test/Fir/rebox.fir @@ -132,3 +132,24 @@ return } func.func private @bar_test_rebox_4(!fir.box>>>) + + +// Test reboxing of unlimited polymorphic. + +func.func @rebox_unlimited_polymorphic_box(%arg0 : !fir.class>, %arg1 : !fir.box>, %arg0r : !fir.ref>>, %arg1r : !fir.ref>>) { + %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.slice<1>) -> !fir.class> + %3 = fir.rebox %arg1 [%1] : (!fir.box>, !fir.slice<1>) -> !fir.box> + fir.store %2 to %arg0r : !fir.ref>> + fir.store %3 to %arg1r : !fir.ref>> + 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]]