Skip to content

Commit 87b2682

Browse files
authored
[flang][hlfir] use fir.type_info to skip runtime call if nofinal is set (#68397)
HLFIR was always calling Destroy runtime when doing derived type scalar assignments because the IR did not contain the info of whether finalization was needed or not. This info is now available in fir.type_info which allow skipping the runtime call when not needed. Also, when finalization is needed, simply use Assign runtime. This makes no difference from a semantic point of view with the current code that generated a call to Destroy and did the assignment inline, but if some piece of runtime must be called anyway, it is simpler to just call Assign that deals with everything.
1 parent f47914a commit 87b2682

File tree

4 files changed

+56
-20
lines changed

4 files changed

+56
-20
lines changed

flang/lib/Optimizer/Builder/FIRBuilder.cpp

+11-7
Original file line numberDiff line numberDiff line change
@@ -1261,6 +1261,15 @@ static bool recordTypeCanBeMemCopied(fir::RecordType recordType) {
12611261
return true;
12621262
}
12631263

1264+
static bool mayHaveFinalizer(fir::RecordType recordType,
1265+
fir::FirOpBuilder &builder) {
1266+
if (auto typeInfo = builder.getModule().lookupSymbol<fir::TypeInfoOp>(
1267+
recordType.getName()))
1268+
return !typeInfo.getNoFinal();
1269+
// No info, be pessimistic.
1270+
return true;
1271+
}
1272+
12641273
void fir::factory::genRecordAssignment(fir::FirOpBuilder &builder,
12651274
mlir::Location loc,
12661275
const fir::ExtendedValue &lhs,
@@ -1277,7 +1286,8 @@ void fir::factory::genRecordAssignment(fir::FirOpBuilder &builder,
12771286
fir::getBase(rhs).getType().isa<fir::BaseBoxType>();
12781287
auto recTy = baseTy.dyn_cast<fir::RecordType>();
12791288
assert(recTy && "must be a record type");
1280-
if (hasBoxOperands || !recordTypeCanBeMemCopied(recTy)) {
1289+
if ((needFinalization && mayHaveFinalizer(recTy, builder)) ||
1290+
hasBoxOperands || !recordTypeCanBeMemCopied(recTy)) {
12811291
auto to = fir::getBase(builder.createBox(loc, lhs));
12821292
auto from = fir::getBase(builder.createBox(loc, rhs));
12831293
// The runtime entry point may modify the LHS descriptor if it is
@@ -1294,12 +1304,6 @@ void fir::factory::genRecordAssignment(fir::FirOpBuilder &builder,
12941304
return;
12951305
}
12961306

1297-
// Finalize LHS on intrinsic assignment.
1298-
if (needFinalization) {
1299-
mlir::Value box = builder.createBox(loc, lhs);
1300-
fir::runtime::genDerivedTypeDestroy(builder, loc, box);
1301-
}
1302-
13031307
// Otherwise, the derived type has compile time constant size and for which
13041308
// the component by component assignment can be replaced by a memory copy.
13051309
// Since we do not know the size of the derived type in lowering, do a
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Test hlfir.assign code generation to FIR of derived type requiring
2+
// or not finalization.
3+
4+
// RUN: fir-opt %s -convert-hlfir-to-fir | FileCheck %s
5+
6+
!t_simple = !fir.type<simple{i:i32}>
7+
fir.type_info @simple noinit nodestroy nofinal : !t_simple
8+
9+
func.func @test_simple(%a: !fir.ref<!t_simple>, %b: !fir.ref<!t_simple>) {
10+
hlfir.assign %b to %a : !fir.ref<!t_simple>, !fir.ref<!t_simple>
11+
return
12+
}
13+
// CHECK-LABEL: func.func @test_simple(
14+
// CHECK-NOT: Destroy
15+
// CHECK: %[[VAL_1:.*]] = fir.coordinate_of %{{.*}}, %{{.*}} : (!fir.ref<!fir.type<simple{i:i32}>>, !fir.field) -> !fir.ref<i32>
16+
// CHECK: %[[VAL_3:.*]] = fir.coordinate_of %{{.*}}, %{{.*}} : (!fir.ref<!fir.type<simple{i:i32}>>, !fir.field) -> !fir.ref<i32>
17+
// CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_1]] : !fir.ref<i32>
18+
// CHECK: fir.store %[[VAL_4]] to %[[VAL_3]] : !fir.ref<i32>
19+
20+
21+
!t_with_final = !fir.type<with_final{i:i32}>
22+
fir.type_info @with_final noinit : !t_with_final
23+
24+
func.func @test_with_final(%a: !fir.ref<!t_with_final>, %b: !fir.ref<!t_with_final>) {
25+
hlfir.assign %b to %a : !fir.ref<!t_with_final>, !fir.ref<!t_with_final>
26+
return
27+
}
28+
// CHECK-LABEL: func.func @test_with_final(
29+
// CHECK: fir.call @_FortranAAssign

flang/test/HLFIR/assign-codegen.fir

+10-9
Original file line numberDiff line numberDiff line change
@@ -347,28 +347,29 @@ func.func @_QFPtest_scalar_lhs_finalization(%arg0: !fir.ref<!fir.type<_QMa8vTt1{
347347
// CHECK-LABEL: func.func @_QFPtest_scalar_lhs_finalization(
348348
// CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.type<_QMa8vTt1{val:i32}>> {fir.bindc_name = "s1"},
349349
// CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.type<_QMa8vTt1{val:i32}>> {fir.bindc_name = "s2"}) {
350+
// CHECK: %[[BOX:.*]] = fir.alloca !fir.box<!fir.type<_QMa8vTt1{val:i32}>>
350351
// CHECK: %[[VAL_2:.*]] = fir.declare %[[VAL_0]] {uniq_name = "_QFFtest_scalar_lhs_finalizationEs1"} : (!fir.ref<!fir.type<_QMa8vTt1{val:i32}>>) -> !fir.ref<!fir.type<_QMa8vTt1{val:i32}>>
351352
// CHECK: %[[VAL_3:.*]] = fir.declare %[[VAL_1]] {uniq_name = "_QFFtest_scalar_lhs_finalizationEs2"} : (!fir.ref<!fir.type<_QMa8vTt1{val:i32}>>) -> !fir.ref<!fir.type<_QMa8vTt1{val:i32}>>
353+
352354
// CHECK: %[[VAL_4:.*]] = fir.embox %[[VAL_2]] : (!fir.ref<!fir.type<_QMa8vTt1{val:i32}>>) -> !fir.box<!fir.type<_QMa8vTt1{val:i32}>>
353-
// CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (!fir.box<!fir.type<_QMa8vTt1{val:i32}>>) -> !fir.box<none>
354-
// CHECK: %[[VAL_6:.*]] = fir.call @_FortranADestroy(%[[VAL_5]]) : (!fir.box<none>) -> none
355-
// CHECK: %[[VAL_7:.*]] = fir.field_index val, !fir.type<_QMa8vTt1{val:i32}>
356-
// CHECK: %[[VAL_8:.*]] = fir.coordinate_of %[[VAL_3]], %[[VAL_7]] : (!fir.ref<!fir.type<_QMa8vTt1{val:i32}>>, !fir.field) -> !fir.ref<i32>
357-
// CHECK: %[[VAL_9:.*]] = fir.field_index val, !fir.type<_QMa8vTt1{val:i32}>
358-
// CHECK: %[[VAL_10:.*]] = fir.coordinate_of %[[VAL_2]], %[[VAL_9]] : (!fir.ref<!fir.type<_QMa8vTt1{val:i32}>>, !fir.field) -> !fir.ref<i32>
359-
// CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_8]] : !fir.ref<i32>
360-
// CHECK: fir.store %[[VAL_11]] to %[[VAL_10]] : !fir.ref<i32>
355+
// CHECK: %[[VAL_5:.*]] = fir.embox %[[VAL_3]] : (!fir.ref<!fir.type<_QMa8vTt1{val:i32}>>) -> !fir.box<!fir.type<_QMa8vTt1{val:i32}>>
356+
// CHECK: fir.store %[[VAL_4]] to %[[BOX]] : !fir.ref<!fir.box<!fir.type<_QMa8vTt1{val:i32}>>>
357+
// CHECK: %[[VAL_10:.*]] = fir.convert %[[BOX]] : (!fir.ref<!fir.box<!fir.type<_QMa8vTt1{val:i32}>>>) -> !fir.ref<!fir.box<none>>
358+
// CHECK: %[[VAL_11:.*]] = fir.convert %[[VAL_5]] : (!fir.box<!fir.type<_QMa8vTt1{val:i32}>>) -> !fir.box<none>
359+
// CHECK: %[[VAL_12:.*]] = fir.convert %{{.*}} : (!fir.ref<!fir.char<1,{{.*}}>>) -> !fir.ref<i8>
360+
// CHECK: %[[VAL_13:.*]] = fir.call @_FortranAAssign(%[[VAL_10]], %[[VAL_11]], %[[VAL_12]], %{{.*}}) : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> none
361361
// CHECK: return
362362
// CHECK: }
363363

364-
// Check that Destroy() is not called for temporary LHS.
364+
// Check that Assign() or Destroy() is not called for temporary LHS.
365365
func.func @_QFPtest_scalar_temp_lhs_no_finalization(%arg0: !fir.ref<!fir.type<_QMa8vTt1{val:i32}>> {fir.bindc_name = "s1"}, %arg1: !fir.ref<!fir.type<_QMa8vTt1{val:i32}>> {fir.bindc_name = "s2"}) {
366366
%0:2 = hlfir.declare %arg0 {uniq_name = "_QFFtest_scalar_lhs_finalizationEs1"} : (!fir.ref<!fir.type<_QMa8vTt1{val:i32}>>) -> (!fir.ref<!fir.type<_QMa8vTt1{val:i32}>>, !fir.ref<!fir.type<_QMa8vTt1{val:i32}>>)
367367
%1:2 = hlfir.declare %arg1 {uniq_name = "_QFFtest_scalar_lhs_finalizationEs2"} : (!fir.ref<!fir.type<_QMa8vTt1{val:i32}>>) -> (!fir.ref<!fir.type<_QMa8vTt1{val:i32}>>, !fir.ref<!fir.type<_QMa8vTt1{val:i32}>>)
368368
hlfir.assign %1#0 to %0#0 temporary_lhs : !fir.ref<!fir.type<_QMa8vTt1{val:i32}>>, !fir.ref<!fir.type<_QMa8vTt1{val:i32}>>
369369
return
370370
}
371371
// CHECK-LABEL: func.func @_QFPtest_scalar_temp_lhs_no_finalization(
372+
// CHECK-NOT: fir.call @_FortranAAssign
372373
// CHECK-NOT: fir.call @_FortranADestroy
373374

374375
func.func @test_upoly_expr_assignment(%arg0: !fir.class<!fir.array<?xnone>> {fir.bindc_name = "y"}) {

flang/test/Lower/derived-type-finalization.f90

+6-4
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,12 @@ subroutine test_lhs_allocatable()
5555
end subroutine
5656

5757
! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_lhs() {
58+
! CHECK: %[[BOXREF:.*]] = fir.alloca !fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
5859
! CHECK: %[[LHS:.*]] = fir.alloca !fir.type<_QMderived_type_finalizationTt1{a:i32}> {bindc_name = "lhs", uniq_name = "_QMderived_type_finalizationFtest_lhsElhs"}
59-
! CHECK: %[[RHS:.*]] = fir.alloca !fir.type<_QMderived_type_finalizationTt1{a:i32}> {bindc_name = "rhs", uniq_name = "_QMderived_type_finalizationFtest_lhsErhs"}
6060
! CHECK: %[[EMBOX:.*]] = fir.embox %[[LHS]] : (!fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
61-
! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[EMBOX]] : (!fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<none>
62-
! CHECK: %{{.*}} = fir.call @_FortranADestroy(%[[BOX_NONE]]) {{.*}} : (!fir.box<none>) -> none
61+
! CHECK: fir.store %[[EMBOX]] to %[[BOXREF]] : !fir.ref<!fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>
62+
! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[BOXREF]] : (!fir.ref<!fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>) -> !fir.ref<!fir.box<none>>
63+
! CHECK: %{{.*}} = fir.call @_FortranAAssign(%[[BOX_NONE]], {{.*}}
6364

6465
! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_lhs_allocatable() {
6566
! CHECK: %[[LHS:.*]] = fir.alloca !fir.box<!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>> {bindc_name = "lhs", uniq_name = "_QMderived_type_finalizationFtest_lhs_allocatableElhs"}
@@ -210,7 +211,8 @@ function no_func_ret_finalize() result(ty)
210211
end function
211212

212213
! CHECK-LABEL: func.func @_QMderived_type_finalizationPno_func_ret_finalize() -> !fir.type<_QMderived_type_finalizationTt1{a:i32}> {
213-
! CHECK: %{{.*}} = fir.call @_FortranADestroy
214+
! CHECK: %{{.*}} = fir.call @_FortranAAssign
215+
! CHECK-NOT: fir.call @_FortranADestroy
214216
! CHECK: return %{{.*}} : !fir.type<_QMderived_type_finalizationTt1{a:i32}>
215217

216218
function copy(a) result(ty)

0 commit comments

Comments
 (0)