[flang-commits] [flang] Use alias analysis in lowering record assignments (PR #176483)
via flang-commits
flang-commits at lists.llvm.org
Fri Jan 16 14:54:21 PST 2026
https://github.com/MattPD updated https://github.com/llvm/llvm-project/pull/176483
>From 1a353622543fe58dc1ac0fcc4b23353844ed3082 Mon Sep 17 00:00:00 2001
From: "Matt P. Dziubinski" <matt-p.dziubinski at hpe.com>
Date: Fri, 16 Jan 2026 15:30:31 -0600
Subject: [PATCH] Use alias analysis in lowering record assignments
---
flang/lib/Optimizer/Builder/FIRBuilder.cpp | 9 ++-
.../acc-firstprivate-derived-user-assign.f90 | 28 +++------
.../OpenACC/acc-firstprivate-derived.f90 | 28 +++------
.../test/Lower/derived-type-finalization.f90 | 62 +++++++++++++++----
flang/unittests/Optimizer/CMakeLists.txt | 1 +
5 files changed, 78 insertions(+), 50 deletions(-)
diff --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
index fcceb3a5b32c7..6b63e4c46f8a0 100644
--- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp
+++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "flang/Optimizer/Builder/FIRBuilder.h"
+#include "flang/Optimizer/Analysis/AliasAnalysis.h"
#include "flang/Optimizer/Builder/BoxValue.h"
#include "flang/Optimizer/Builder/Character.h"
#include "flang/Optimizer/Builder/Complex.h"
@@ -1566,8 +1567,14 @@ void fir::factory::genRecordAssignment(fir::FirOpBuilder &builder,
mlir::isa<fir::BaseBoxType>(fir::getBase(rhs).getType());
auto recTy = mlir::dyn_cast<fir::RecordType>(baseTy);
assert(recTy && "must be a record type");
+
+ // Use alias analysis to guard the fast path.
+ fir::AliasAnalysis aa;
+ bool disjoint = aa.alias(fir::getBase(lhs), fir::getBase(rhs)) ==
+ mlir::AliasResult::NoAlias;
+
if ((needFinalization && mayHaveFinalizer(recTy, builder)) ||
- hasBoxOperands || !recordTypeCanBeMemCopied(recTy)) {
+ hasBoxOperands || !recordTypeCanBeMemCopied(recTy) || !disjoint) {
auto to = fir::getBase(builder.createBox(loc, lhs));
auto from = fir::getBase(builder.createBox(loc, rhs));
// The runtime entry point may modify the LHS descriptor if it is
diff --git a/flang/test/Lower/OpenACC/acc-firstprivate-derived-user-assign.f90 b/flang/test/Lower/OpenACC/acc-firstprivate-derived-user-assign.f90
index 98ae36f1eef2a..d910df6458748 100644
--- a/flang/test/Lower/OpenACC/acc-firstprivate-derived-user-assign.f90
+++ b/flang/test/Lower/OpenACC/acc-firstprivate-derived-user-assign.f90
@@ -79,23 +79,15 @@ subroutine test()
! FIR-CHECK: acc.yield %[[VAL_1]] : !fir.ref<!fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>>
! FIR-CHECK: } copy {
! FIR-CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>>, %[[VAL_1:.*]]: !fir.ref<!fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>>):
-! FIR-CHECK: %[[VAL_2:.*]] = fir.field_index x, !fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>
-! FIR-CHECK: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_0]], x : (!fir.ref<!fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>>) -> !fir.ref<f32>
-! FIR-CHECK: %[[VAL_4:.*]] = fir.field_index x, !fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>
-! FIR-CHECK: %[[VAL_5:.*]] = fir.coordinate_of %[[VAL_1]], x : (!fir.ref<!fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>>) -> !fir.ref<f32>
-! FIR-CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_3]] : !fir.ref<f32>
-! FIR-CHECK: fir.store %[[VAL_6]] to %[[VAL_5]] : !fir.ref<f32>
-! FIR-CHECK: %[[VAL_7:.*]] = fir.field_index y, !fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>
-! FIR-CHECK: %[[VAL_8:.*]] = fir.coordinate_of %[[VAL_0]], y : (!fir.ref<!fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>>) -> !fir.ref<f32>
-! FIR-CHECK: %[[VAL_9:.*]] = fir.field_index y, !fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>
-! FIR-CHECK: %[[VAL_10:.*]] = fir.coordinate_of %[[VAL_1]], y : (!fir.ref<!fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>>) -> !fir.ref<f32>
-! FIR-CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_8]] : !fir.ref<f32>
-! FIR-CHECK: fir.store %[[VAL_11]] to %[[VAL_10]] : !fir.ref<f32>
-! FIR-CHECK: %[[VAL_12:.*]] = fir.field_index z, !fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>
-! FIR-CHECK: %[[VAL_13:.*]] = fir.coordinate_of %[[VAL_0]], z : (!fir.ref<!fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>>) -> !fir.ref<f32>
-! FIR-CHECK: %[[VAL_14:.*]] = fir.field_index z, !fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>
-! FIR-CHECK: %[[VAL_15:.*]] = fir.coordinate_of %[[VAL_1]], z : (!fir.ref<!fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>>) -> !fir.ref<f32>
-! FIR-CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_13]] : !fir.ref<f32>
-! FIR-CHECK: fir.store %[[VAL_16]] to %[[VAL_15]] : !fir.ref<f32>
+! FIR-CHECK: %[[TMPBOX:.*]] = fir.alloca !fir.box<!fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>>
+! FIR-CHECK: %[[DST_BOX:.*]] = fir.embox %[[VAL_1]] : (!fir.ref<!fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>>) -> !fir.box<!fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>>
+! FIR-CHECK: %[[SRC_BOX:.*]] = fir.embox %[[VAL_0]] : (!fir.ref<!fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>>) -> !fir.box<!fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>>
+! FIR-CHECK: fir.store %[[DST_BOX]] to %[[TMPBOX]] : !fir.ref<!fir.box<!fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>>>
+! FIR-CHECK: %[[FNAME:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]+}}>>
+! FIR-CHECK: %[[C29:.*]] = arith.constant 29 : i32
+! FIR-CHECK: %[[TMPBOX_NONE:.*]] = fir.convert %[[TMPBOX]] : (!fir.ref<!fir.box<!fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>>>) -> !fir.ref<!fir.box<none>>
+! FIR-CHECK: %[[SRC_NONE:.*]] = fir.convert %[[SRC_BOX]] : (!fir.box<!fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>>) -> !fir.box<none>
+! FIR-CHECK: %[[FNAME_I8:.*]] = fir.convert %[[FNAME]] : (!fir.ref<!fir.char<1,{{[0-9]+}}>>) -> !fir.ref<i8>
+! FIR-CHECK: fir.call @_FortranAAssignTemporary(%[[TMPBOX_NONE]], %[[SRC_NONE]], %[[FNAME_I8]], %[[C29]]) : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> ()
! FIR-CHECK: acc.terminator
! FIR-CHECK: }
diff --git a/flang/test/Lower/OpenACC/acc-firstprivate-derived.f90 b/flang/test/Lower/OpenACC/acc-firstprivate-derived.f90
index 3b59a0353b199..15f0d5582c466 100644
--- a/flang/test/Lower/OpenACC/acc-firstprivate-derived.f90
+++ b/flang/test/Lower/OpenACC/acc-firstprivate-derived.f90
@@ -65,23 +65,15 @@ subroutine test()
! FIR-CHECK: acc.yield %[[VAL_1]] : !fir.ref<!fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>>
! FIR-CHECK: } copy {
! FIR-CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>>, %[[VAL_1:.*]]: !fir.ref<!fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>>):
-! FIR-CHECK: %[[VAL_2:.*]] = fir.field_index x, !fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>
-! FIR-CHECK: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_0]], x : (!fir.ref<!fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>>) -> !fir.ref<f32>
-! FIR-CHECK: %[[VAL_4:.*]] = fir.field_index x, !fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>
-! FIR-CHECK: %[[VAL_5:.*]] = fir.coordinate_of %[[VAL_1]], x : (!fir.ref<!fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>>) -> !fir.ref<f32>
-! FIR-CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_3]] : !fir.ref<f32>
-! FIR-CHECK: fir.store %[[VAL_6]] to %[[VAL_5]] : !fir.ref<f32>
-! FIR-CHECK: %[[VAL_7:.*]] = fir.field_index y, !fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>
-! FIR-CHECK: %[[VAL_8:.*]] = fir.coordinate_of %[[VAL_0]], y : (!fir.ref<!fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>>) -> !fir.ref<f32>
-! FIR-CHECK: %[[VAL_9:.*]] = fir.field_index y, !fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>
-! FIR-CHECK: %[[VAL_10:.*]] = fir.coordinate_of %[[VAL_1]], y : (!fir.ref<!fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>>) -> !fir.ref<f32>
-! FIR-CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_8]] : !fir.ref<f32>
-! FIR-CHECK: fir.store %[[VAL_11]] to %[[VAL_10]] : !fir.ref<f32>
-! FIR-CHECK: %[[VAL_12:.*]] = fir.field_index z, !fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>
-! FIR-CHECK: %[[VAL_13:.*]] = fir.coordinate_of %[[VAL_0]], z : (!fir.ref<!fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>>) -> !fir.ref<f32>
-! FIR-CHECK: %[[VAL_14:.*]] = fir.field_index z, !fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>
-! FIR-CHECK: %[[VAL_15:.*]] = fir.coordinate_of %[[VAL_1]], z : (!fir.ref<!fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>>) -> !fir.ref<f32>
-! FIR-CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_13]] : !fir.ref<f32>
-! FIR-CHECK: fir.store %[[VAL_16]] to %[[VAL_15]] : !fir.ref<f32>
+! FIR-CHECK: %[[TMPBOX:.*]] = fir.alloca !fir.box<!fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>>
+! FIR-CHECK: %[[DST_BOX:.*]] = fir.embox %[[VAL_1]] : (!fir.ref<!fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>>) -> !fir.box<!fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>>
+! FIR-CHECK: %[[SRC_BOX:.*]] = fir.embox %[[VAL_0]] : (!fir.ref<!fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>>) -> !fir.box<!fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>>
+! FIR-CHECK: fir.store %[[DST_BOX]] to %[[TMPBOX]] : !fir.ref<!fir.box<!fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>>>
+! FIR-CHECK: %[[FNAME:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]+}}>>
+! FIR-CHECK: %[[C15:.*]] = arith.constant 15 : i32
+! FIR-CHECK: %[[TMPBOX_NONE:.*]] = fir.convert %[[TMPBOX]] : (!fir.ref<!fir.box<!fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>>>) -> !fir.ref<!fir.box<none>>
+! FIR-CHECK: %[[SRC_NONE:.*]] = fir.convert %[[SRC_BOX]] : (!fir.box<!fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>>) -> !fir.box<none>
+! FIR-CHECK: %[[FNAME_I8:.*]] = fir.convert %[[FNAME]] : (!fir.ref<!fir.char<1,{{[0-9]+}}>>) -> !fir.ref<i8>
+! FIR-CHECK: fir.call @_FortranAAssignTemporary(%[[TMPBOX_NONE]], %[[SRC_NONE]], %[[FNAME_I8]], %[[C15]]) : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> ()
! FIR-CHECK: acc.terminator
! FIR-CHECK: }
diff --git a/flang/test/Lower/derived-type-finalization.f90 b/flang/test/Lower/derived-type-finalization.f90
index 71cef34899603..1f318f0829017 100644
--- a/flang/test/Lower/derived-type-finalization.f90
+++ b/flang/test/Lower/derived-type-finalization.f90
@@ -63,17 +63,32 @@ subroutine test_lhs_allocatable()
! CHECK: fir.call @_FortranAAssign(%[[BOX_NONE]], {{.*}}
! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_lhs_allocatable() {
-! 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"}
-! CHECK: %[[LHS_ADDR:.*]] = fir.alloca !fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>> {uniq_name = "_QMderived_type_finalizationFtest_lhs_allocatableElhs.addr"}
+! CHECK: %[[TMPBOX:.*]] = fir.alloca !fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
+! CHECK: %[[LHSBOX:.*]] = fir.alloca !fir.box<!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>> {bindc_name = "lhs", uniq_name = "_QMderived_type_finalizationFtest_lhs_allocatableElhs"}
+! CHECK: %[[LHSADDR:.*]] = fir.alloca !fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>> {uniq_name = "_QMderived_type_finalizationFtest_lhs_allocatableElhs.addr"}
! CHECK: %[[RHS:.*]] = fir.alloca !fir.type<_QMderived_type_finalizationTt1{a:i32}> {bindc_name = "rhs", uniq_name = "_QMderived_type_finalizationFtest_lhs_allocatableErhs"}
-! CHECK: %[[LHS_ADDR_LOAD:.*]] = fir.load %[[LHS_ADDR]] : !fir.ref<!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>
-! CHECK: %[[ADDR_I64:.*]] = fir.convert %[[LHS_ADDR_LOAD]] : (!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> i64
-! CHECK: %[[C0:.*]] = arith.constant 0 : i64
-! CHECK: %[[IS_NULL:.*]] = arith.cmpi ne, %[[ADDR_I64]], %[[C0]] : i64
+! CHECK: %[[LHSADDR_LD:.*]] = fir.load %[[LHSADDR]] :
+! CHECK: %[[LHSADDR_I64:.*]] = fir.convert %[[LHSADDR_LD]] : (!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> i64
+! CHECK: %[[IS_NULL:.*]] = arith.cmpi ne, %[[LHSADDR_I64]], %{{.*}} : i64
! CHECK: fir.if %[[IS_NULL]] {
-! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[LHS]] : (!fir.ref<!fir.box<!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>>) -> !fir.box<none>
-! CHECK: fir.call @_FortranADestroy(%[[BOX_NONE]]) {{.*}} : (!fir.box<none>) -> ()
+! CHECK: %[[LHSBOX_NONE:.*]] = fir.convert %[[LHSBOX]] : (!fir.ref<!fir.box<!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranADestroy(%[[LHSBOX_NONE]]) {{.*}} : (!fir.box<none>) -> ()
+! CHECK: }
+! CHECK: %[[DST_HEAP:.*]] = fir.if {{.*}} -> (!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) {
+! CHECK: %[[NEW_ALLOC:.*]] = fir.allocmem !fir.type<_QMderived_type_finalizationTt1{a:i32}> {{.*}}
+! CHECK: fir.call @_FortranAInitialize
+! CHECK: fir.result %[[NEW_ALLOC]]
+! CHECK: } else {
+! CHECK: fir.result %[[EXISTING_HEAP:.*]] : !fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
! CHECK: }
+! CHECK: %[[DST_BOX:.*]] = fir.embox %{{.*}}#1 : (!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
+! CHECK: %[[SRC_BOX:.*]] = fir.embox %[[RHS]] : (!fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
+! CHECK: fir.store %[[DST_BOX]] to %[[TMPBOX]] :
+! CHECK: %[[DST_NONE_REF:.*]] = fir.convert %[[TMPBOX]] : (!fir.ref<!fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %[[SRC_NONE:.*]] = fir.convert %[[SRC_BOX]] : (!fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranAAssign(%[[DST_NONE_REF]], %[[SRC_NONE]], {{.*}}) {{.*}} : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> ()
+! CHECK: fir.call @_FortranADestroy(%{{.*}}) {{.*}} : (!fir.box<none>) -> ()
+! CHECK: fir.call @_FortranAAllocatableDeallocate
! 7.5.6.3 point 2. Finalization on explicit deallocation.
subroutine test_deallocate()
@@ -155,13 +170,34 @@ subroutine test_fct_ref()
end subroutine
! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_fct_ref() {
+! CHECK: %[[TMPBOX:.*]] = fir.alloca !fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
! CHECK: %[[RESULT:.*]] = fir.alloca !fir.type<_QMderived_type_finalizationTt1{a:i32}> {bindc_name = ".result"}
+! CHECK: %[[TYBOX:.*]] = fir.alloca !fir.box<!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>> {bindc_name = "ty", uniq_name = "_QMderived_type_finalizationFtest_fct_refEty"}
+! CHECK: %[[TYADDR:.*]] = fir.alloca !fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>> {uniq_name = "_QMderived_type_finalizationFtest_fct_refEty.addr"}
! CHECK: %[[CALL_RES:.*]] = fir.call @_QMderived_type_finalizationPret_type()
-! CHECK: fir.save_result %[[CALL_RES]] to %[[RESULT]] : !fir.type<_QMderived_type_finalizationTt1{a:i32}>, !fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
-! CHECK: %[[EMBOX:.*]] = fir.embox %[[RESULT]] : (!fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
-! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[EMBOX]] : (!fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<none>
-! CHECK: fir.call @_FortranADestroy(%[[BOX_NONE]]) {{.*}} : (!fir.box<none>) -> ()
-! CHECK: return
+! CHECK: fir.save_result %[[CALL_RES]] to %[[RESULT]] :
+! CHECK: %[[TYADDR_LD:.*]] = fir.load %[[TYADDR]] :
+! CHECK: %[[TYADDR_I64:.*]] = fir.convert %[[TYADDR_LD]] : (!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> i64
+! CHECK: %[[IS_NULL:.*]] = arith.cmpi ne, %[[TYADDR_I64]], %{{.*}} : i64
+! CHECK: fir.if %[[IS_NULL]] {
+! CHECK: %[[TYBOX_NONE:.*]] = fir.convert %[[TYBOX]] : (!fir.ref<!fir.box<!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranADestroy(%[[TYBOX_NONE]]) {{.*}} : (!fir.box<none>) -> ()
+! CHECK: }
+! CHECK: %[[DST_HEAP:.*]] = fir.if {{.*}} -> (!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) {
+! CHECK: %[[NEW_ALLOC:.*]] = fir.allocmem !fir.type<_QMderived_type_finalizationTt1{a:i32}> {{.*}}
+! CHECK: fir.call @_FortranAInitialize
+! CHECK: fir.result %[[NEW_ALLOC]]
+! CHECK: } else {
+! CHECK: fir.result %[[EXISTING_HEAP:.*]] : !fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
+! CHECK: }
+! CHECK: %[[DST_BOX:.*]] = fir.embox %{{.*}}#1 : (!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
+! CHECK: %[[SRC_BOX:.*]] = fir.embox %[[RESULT]] : (!fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
+! CHECK: fir.store %[[DST_BOX]] to %[[TMPBOX]] :
+! CHECK: %[[DST_NONE_REF:.*]] = fir.convert %[[TMPBOX]] : (!fir.ref<!fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %[[SRC_NONE:.*]] = fir.convert %[[SRC_BOX]] : (!fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranAAssign(%[[DST_NONE_REF]], %[[SRC_NONE]], {{.*}}) {{.*}} : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> ()
+! CHECK: fir.call @_FortranADestroy(%{{.*}}) {{.*}} : (!fir.box<none>) -> ()
+! CHECK: fir.call @_FortranAAllocatableDeallocate
subroutine test_finalize_intent_out(t)
type(t1), intent(out) :: t
diff --git a/flang/unittests/Optimizer/CMakeLists.txt b/flang/unittests/Optimizer/CMakeLists.txt
index 3a04008b9b795..c390add457632 100644
--- a/flang/unittests/Optimizer/CMakeLists.txt
+++ b/flang/unittests/Optimizer/CMakeLists.txt
@@ -8,6 +8,7 @@ set(LLVM_LINK_COMPONENTS
set(LIBS
CUFDialect
FIRBuilder
+ FIRAnalysis
FIRCodeGenDialect
FIRDialect
FIRDialectSupport
More information about the flang-commits
mailing list