[flang-commits] [flang] [flang] Fixed assumed-type temporary allocation for -frepack-arrays. (PR #147618)
Slava Zakharin via flang-commits
flang-commits at lists.llvm.org
Tue Jul 8 16:51:11 PDT 2025
https://github.com/vzakhari created https://github.com/llvm/llvm-project/pull/147618
After #142609, repacking of assumed-type arrays under -frepack-arrays
become broken, because the code tried to pass a `!fir.box`
source_box to `fir.embox`, which is not allowed.
It might be okay to cast the original box to class for using it
in `fir.embox`.
>From e2ebd285b37cdf57e30f1a569eddf2c715704a67 Mon Sep 17 00:00:00 2001
From: Slava Zakharin <szakharin at nvidia.com>
Date: Tue, 8 Jul 2025 16:43:24 -0700
Subject: [PATCH] [flang] Fixed assumed-type temporary allocation for
-frepack-arrays.
After #142609, repacking of assumed-type arrays under -frepack-arrays
become broken, because the code tried to pass a `!fir.box`
source_box to `fir.embox`, which is not allowed.
It might be okay to cast the original box to class for using it
in `fir.embox`.
---
flang/lib/Optimizer/Builder/MutableBox.cpp | 9 +++
flang/test/Transforms/lower-repack-arrays.fir | 78 +++++++++++++++++++
2 files changed, 87 insertions(+)
diff --git a/flang/lib/Optimizer/Builder/MutableBox.cpp b/flang/lib/Optimizer/Builder/MutableBox.cpp
index d944a4c98473e..8c4e12913f714 100644
--- a/flang/lib/Optimizer/Builder/MutableBox.cpp
+++ b/flang/lib/Optimizer/Builder/MutableBox.cpp
@@ -987,6 +987,15 @@ mlir::Value fir::factory::getAndEstablishBoxStorage(
mlir::Value boxStorage = builder.createTemporary(loc, boxTy);
mlir::Value nullAddr =
builder.createNullConstant(loc, boxTy.getBaseAddressType());
+ if (polymorphicMold && fir::isAssumedType(polymorphicMold.getType())) {
+ // An assumed-type (!fir.box) entity cannot be used as a mold
+ // in fir.embox, so we have to represent it as an unlimited
+ // polymorphic entity (!fir.class).
+ mlir::Type newMoldType = fir::wrapInClassOrBoxType(
+ mlir::cast<fir::BaseBoxType>(polymorphicMold.getType()).getEleTy(),
+ /*isPolymorphic=*/true);
+ polymorphicMold = builder.createConvert(loc, newMoldType, polymorphicMold);
+ }
mlir::Value box =
builder.create<fir::EmboxOp>(loc, boxTy, nullAddr, shape,
/*emptySlice=*/mlir::Value{},
diff --git a/flang/test/Transforms/lower-repack-arrays.fir b/flang/test/Transforms/lower-repack-arrays.fir
index 458869cce45fd..d96cfc609533a 100644
--- a/flang/test/Transforms/lower-repack-arrays.fir
+++ b/flang/test/Transforms/lower-repack-arrays.fir
@@ -1091,3 +1091,81 @@ func.func @_QPtest7_stack(%arg0: !fir.class<!fir.array<?x?xnone>> {fir.bindc_nam
// CHECK: }
// CHECK: return
// CHECK: }
+
+// Test assumed type array.
+// The temporary allocation requires creating a fir.box with the mold
+// being the !fir.box<!fir.array<?xnone>>. We have to cast it to
+// !fir.class<!fir.array<?xnone>> to make the fir.embox's source_box
+// operand valid.
+// CHECK-LABEL: func.func @_QPrepack_assumed_type(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?xnone>> {fir.bindc_name = "x"}) {
+// CHECK: %[[VAL_0:.*]] = arith.constant
+// CHECK: %[[VAL_1:.*]] = arith.constant
+// CHECK: %[[VAL_2:.*]] = arith.constant 0 : index
+// CHECK: %[[VAL_3:.*]] = arith.constant false
+// CHECK: %[[VAL_4:.*]] = fir.alloca !fir.class<!fir.heap<!fir.array<?xnone>>>
+// CHECK: %[[VAL_5:.*]] = fir.dummy_scope : !fir.dscope
+// CHECK: %[[VAL_6:.*]] = fir.is_present %[[ARG0]] : (!fir.box<!fir.array<?xnone>>) -> i1
+// CHECK: %[[VAL_7:.*]] = fir.if %[[VAL_6]] -> (!fir.box<!fir.array<?xnone>>) {
+// CHECK: %[[VAL_8:.*]] = fir.is_contiguous_box %[[ARG0]] whole : (!fir.box<!fir.array<?xnone>>) -> i1
+// CHECK: %[[VAL_9:.*]] = arith.cmpi eq, %[[VAL_8]], %[[VAL_3]] : i1
+// CHECK: %[[VAL_10:.*]] = fir.box_addr %[[ARG0]] : (!fir.box<!fir.array<?xnone>>) -> !fir.ref<!fir.box<!fir.array<?xnone>>>
+// CHECK: %[[VAL_11:.*]] = fir.is_present %[[VAL_10]] : (!fir.ref<!fir.box<!fir.array<?xnone>>>) -> i1
+// CHECK: %[[VAL_12:.*]] = arith.andi %[[VAL_9]], %[[VAL_11]] : i1
+// CHECK: %[[VAL_13:.*]] = fir.if %[[VAL_12]] weights([0, 1]) -> (!fir.box<!fir.array<?xnone>>) {
+// CHECK: %[[VAL_14:.*]]:3 = fir.box_dims %[[ARG0]], %[[VAL_2]] : (!fir.box<!fir.array<?xnone>>, index) -> (index, index, index)
+// CHECK: %[[VAL_15:.*]] = fir.shape %[[VAL_14]]#1 : (index) -> !fir.shape<1>
+// CHECK: %[[VAL_16:.*]] = fir.zero_bits !fir.heap<!fir.array<?xnone>>
+// CHECK: %[[VAL_17:.*]] = fir.convert %[[ARG0]] : (!fir.box<!fir.array<?xnone>>) -> !fir.class<!fir.array<?xnone>>
+// CHECK: %[[VAL_18:.*]] = fir.embox %[[VAL_16]](%[[VAL_15]]) source_box %[[VAL_17]] : (!fir.heap<!fir.array<?xnone>>, !fir.shape<1>, !fir.class<!fir.array<?xnone>>) -> !fir.class<!fir.heap<!fir.array<?xnone>>>
+// CHECK: fir.store %[[VAL_18]] to %[[VAL_4]] : !fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>>>
+// CHECK: %[[VAL_19:.*]] = fir.zero_bits !fir.ref<none>
+// CHECK: %[[VAL_20:.*]] = fir.address_of(@{{_QQcl.*}}) : !fir.ref<!fir.char<1,{{.*}}>>
+// CHECK: %[[VAL_21:.*]] = fir.absent !fir.box<none>
+// CHECK: %[[VAL_22:.*]] = fir.convert %[[VAL_4]] : (!fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>>>) -> !fir.ref<!fir.box<none>>
+// CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_19]] : (!fir.ref<none>) -> !fir.ref<i64>
+// CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_20]] : (!fir.ref<!fir.char<1,{{.*}}>>) -> !fir.ref<i8>
+// CHECK: %[[VAL_25:.*]] = fir.call @_FortranAAllocatableAllocate(%[[VAL_22]], %[[VAL_23]], %[[VAL_3]], %[[VAL_21]], %[[VAL_24]], %[[VAL_1]]) : (!fir.ref<!fir.box<none>>, !fir.ref<i64>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
+// CHECK: %[[VAL_26:.*]] = fir.load %[[VAL_4]] : !fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>>>
+// CHECK: %[[VAL_27:.*]] = fir.declare %[[VAL_26]] {uniq_name = ".repacked"} : (!fir.class<!fir.heap<!fir.array<?xnone>>>) -> !fir.class<!fir.heap<!fir.array<?xnone>>>
+// CHECK: %[[VAL_28:.*]] = fir.address_of(@{{_QQcl.*}}) : !fir.ref<!fir.char<1,{{.*}}>>
+// CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_27]] : (!fir.class<!fir.heap<!fir.array<?xnone>>>) -> !fir.box<none>
+// CHECK: %[[VAL_30:.*]] = fir.convert %[[ARG0]] : (!fir.box<!fir.array<?xnone>>) -> !fir.box<none>
+// CHECK: %[[VAL_31:.*]] = fir.convert %[[VAL_28]] : (!fir.ref<!fir.char<1,{{.*}}>>) -> !fir.ref<i8>
+// CHECK: fir.call @_FortranAShallowCopyDirect(%[[VAL_29]], %[[VAL_30]], %[[VAL_31]], %[[VAL_1]]) : (!fir.box<none>, !fir.box<none>, !fir.ref<i8>, i32) -> ()
+// CHECK: %[[VAL_32:.*]] = fir.shift %[[VAL_14]]#0 : (index) -> !fir.shift<1>
+// CHECK: %[[VAL_33:.*]] = fir.rebox %[[VAL_27]](%[[VAL_32]]) : (!fir.class<!fir.heap<!fir.array<?xnone>>>, !fir.shift<1>) -> !fir.box<!fir.array<?xnone>>
+// CHECK: fir.result %[[VAL_33]] : !fir.box<!fir.array<?xnone>>
+// CHECK: } else {
+// CHECK: fir.result %[[ARG0]] : !fir.box<!fir.array<?xnone>>
+// CHECK: }
+// CHECK: fir.result %[[VAL_13]] : !fir.box<!fir.array<?xnone>>
+// CHECK: } else {
+// CHECK: fir.result %[[ARG0]] : !fir.box<!fir.array<?xnone>>
+// CHECK: }
+// CHECK: %[[VAL_34:.*]] = fir.declare %[[VAL_7]] dummy_scope %[[VAL_5]] {uniq_name = "_QFrepack_assumed_typeEx"} : (!fir.box<!fir.array<?xnone>>, !fir.dscope) -> !fir.box<!fir.array<?xnone>>
+// CHECK: %[[VAL_35:.*]] = fir.is_present %[[ARG0]] : (!fir.box<!fir.array<?xnone>>) -> i1
+// CHECK: fir.if %[[VAL_35]] {
+// CHECK: %[[VAL_36:.*]] = fir.box_addr %[[VAL_7]] : (!fir.box<!fir.array<?xnone>>) -> !fir.heap<!fir.array<?xnone>>
+// CHECK: %[[VAL_37:.*]] = fir.box_addr %[[ARG0]] : (!fir.box<!fir.array<?xnone>>) -> !fir.heap<!fir.array<?xnone>>
+// CHECK: %[[VAL_38:.*]] = fir.convert %[[VAL_36]] : (!fir.heap<!fir.array<?xnone>>) -> index
+// CHECK: %[[VAL_39:.*]] = fir.convert %[[VAL_37]] : (!fir.heap<!fir.array<?xnone>>) -> index
+// CHECK: %[[VAL_40:.*]] = arith.cmpi ne, %[[VAL_38]], %[[VAL_39]] : index
+// CHECK: fir.if %[[VAL_40]] weights([0, 1]) {
+// CHECK: %[[VAL_41:.*]] = fir.address_of(@_QQclX2b7d3b4eb2a9b0772619a406c28937e5) : !fir.ref<!fir.char<1,{{.*}}>>
+// CHECK: %[[VAL_42:.*]] = fir.convert %[[ARG0]] : (!fir.box<!fir.array<?xnone>>) -> !fir.box<none>
+// CHECK: %[[VAL_43:.*]] = fir.convert %[[VAL_7]] : (!fir.box<!fir.array<?xnone>>) -> !fir.box<none>
+// CHECK: %[[VAL_44:.*]] = fir.convert %[[VAL_41]] : (!fir.ref<!fir.char<1,{{.*}}>>) -> !fir.ref<i8>
+// CHECK: fir.call @_FortranAShallowCopyDirect(%[[VAL_42]], %[[VAL_43]], %[[VAL_44]], %[[VAL_0]]) : (!fir.box<none>, !fir.box<none>, !fir.ref<i8>, i32) -> ()
+// CHECK: fir.freemem %[[VAL_36]] : !fir.heap<!fir.array<?xnone>>
+// CHECK: }
+// CHECK: }
+// CHECK: return
+// CHECK: }
+func.func @_QPrepack_assumed_type(%arg0: !fir.box<!fir.array<?xnone>> {fir.bindc_name = "x"}) {
+ %0 = fir.dummy_scope : !fir.dscope
+ %1 = fir.pack_array %arg0 heap whole : (!fir.box<!fir.array<?xnone>>) -> !fir.box<!fir.array<?xnone>>
+ %2 = fir.declare %1 dummy_scope %0 {uniq_name = "_QFrepack_assumed_typeEx"} : (!fir.box<!fir.array<?xnone>>, !fir.dscope) -> !fir.box<!fir.array<?xnone>>
+ fir.unpack_array %1 to %arg0 heap : !fir.box<!fir.array<?xnone>>
+ return
+}
More information about the flang-commits
mailing list