[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:29:13 PST 2026


https://github.com/MattPD updated https://github.com/llvm/llvm-project/pull/176483

>From cfcfdc840e2d788db286d576951521e78c316bd9 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 +++++++++++++++----
 4 files changed, 77 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



More information about the flang-commits mailing list