[flang-commits] [flang] [flang][lowering] Implement component-wise initialization for derived types (PR #187465)

via flang-commits flang-commits at lists.llvm.org
Fri Apr 3 07:09:02 PDT 2026


================
@@ -0,0 +1,111 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+
+! Test for precise component-wise initialization of derived types
+! to avoid generating large, fully-initialized global templates (sparse initialization).
+
+module my_types
+  ! Clean internal type: contains only allocatable and pointer components, 
+  ! without any explicit initialization.
+  type :: InnerClean
+    real, pointer :: p
+    real, allocatable :: arr(:)
+  end type InnerClean
+
+  ! ============================================================================
+  ! Test Case 1: Type meeting all criteria for precise component-wise init (Target)
+  ! No arrays of derived types, no explicit initialization.
+  ! ============================================================================
+  type :: TargetType
+    real, pointer :: q
+    real(8) :: uninit_buffer(80, 100)      ! Large uninitialized array; should be bypassed.
+    type(InnerClean) :: nested_scalar      ! Scalar derived type; should be expanded recursively.
+  end type TargetType
+
+  ! ============================================================================
+  ! Test Case 2: Type triggering fallback A (contains an array of derived type)
+  ! ============================================================================
+  type :: FallbackArrayType
+    type(InnerClean) :: nested_arr(10)     ! Array of derived type; must trigger fallback.
+  end type FallbackArrayType
+
+  ! ============================================================================
+  ! Test Case 3: Type triggering fallback B (contains explicit initialization)
+  ! ============================================================================
+  type :: FallbackExplicitType
+    real, pointer :: p
+    integer :: flag = 999                  ! Explicit initialization; must trigger gatekeeper!
+  end type FallbackExplicitType
+end module my_types
+
+
+! ------------------------------------------------------------------------------
+! Test 1: FIR generation for precise component-wise initialization
+! ------------------------------------------------------------------------------
+subroutine test_target()
+  use my_types
+  type(TargetType) :: my_var
+  call do_something_target(my_var)
+end subroutine test_target
+
+! CHECK-LABEL: func.func @_QPtest_target()
+! Match the alloca and the subsequent declare
+! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.type<_QMmy_typesTtargettype{{.*}}>
+! CHECK: %[[MY_VAR:.*]] = fir.declare %[[ALLOCA]]
+
+! 1. Check initialization of the outermost pointer 'q'
+! CHECK: %[[Q_ADDR:.*]] = fir.coordinate_of %[[MY_VAR]], q
+! CHECK: fir.store %{{.*}} to %[[Q_ADDR]]
+
+! 2. Check recursive precise initialization of the scalar derived type 'nested_scalar'
+! CHECK: %[[NESTED_ADDR:.*]] = fir.coordinate_of %[[MY_VAR]], nested_scalar
+
+! -> Check internal pointer 'p'
+! CHECK: %[[P_ADDR:.*]] = fir.coordinate_of %[[NESTED_ADDR]], p
+! CHECK: fir.store %{{.*}} to %[[P_ADDR]]
+
+! -> Check internal allocatable array 'arr'
+! CHECK: %[[ARR_ADDR:.*]] = fir.coordinate_of %[[NESTED_ADDR]], arr
+! CHECK: fir.store %{{.*}} to %[[ARR_ADDR]]
+
+! CRITICAL 1: Ensure NO expensive runtime calls are generated.
+! CHECK-NOT: fir.call @_FortranAInitialize
+
+! CRITICAL 2: Ensure NO large global initialization templates are generated for TargetType.
+! CHECK-NOT: fir.global internal @_QQ_QMmy_typesTtargettype.DerivedInit
+
+
+! ------------------------------------------------------------------------------
+! Test 2: Fallback mechanism for arrays of derived types
+! ------------------------------------------------------------------------------
+subroutine test_fallback_array()
+  use my_types
+  type(FallbackArrayType) :: var_array
+  call do_something_array(var_array)
+end subroutine test_fallback_array
+
+! CHECK-LABEL: func.func @_QPtest_fallback_array()
+! CHECK: %[[ALLOCA_ARR:.*]] = fir.alloca !fir.type<_QMmy_typesTfallbackarraytype{{.*}}>
+! CHECK: %[[VAR_ARRAY:.*]] = fir.declare %[[ALLOCA_ARR]]
+! 
+! Ensure FallbackArrayType falls back to the highly optimized memcpy from a global template,
+! entirely avoiding the runtime loop initialization.
+! CHECK: %[[GLOBAL_INIT_ARR:.*]] = fir.address_of(@_QQ_QMmy_typesTfallbackarraytype.DerivedInit)
+! CHECK: fir.copy %[[GLOBAL_INIT_ARR]] to %[[VAR_ARRAY]]
+
+
+! ------------------------------------------------------------------------------
+! Test 3: Fallback mechanism for explicit initialization
+! ------------------------------------------------------------------------------
+subroutine test_fallback_explicit()
+  use my_types
+  type(FallbackExplicitType) :: var_explicit
+  call do_something_explicit(var_explicit)
+end subroutine test_fallback_explicit
+
+! CHECK-LABEL: func.func @_QPtest_fallback_explicit()
+! CHECK: %[[ALLOCA_EXP:.*]] = fir.alloca !fir.type<_QMmy_typesTfallbackexplicittype{{.*}}>
+! CHECK: %[[VAR_EXPLICIT:.*]] = fir.declare %[[ALLOCA_EXP]]
+! 
+! Ensure types with explicit initialization trigger the gatekeeper and fall back to the old logic.
+! CHECK: %[[GLOBAL_INIT_EXP:.*]] = fir.address_of(@_QQ_QMmy_typesTfallbackexplicittype.DerivedInit)
+! CHECK: fir.copy %[[GLOBAL_INIT_EXP]] to %[[VAR_EXPLICIT]]
----------------
jeanPerier wrote:

nit missing new line.

https://github.com/llvm/llvm-project/pull/187465


More information about the flang-commits mailing list