[flang-commits] [flang] [flang][OpenMP] Support user-defined declare reduction with derived types (PR #184897)

Tom Eccles via flang-commits flang-commits at lists.llvm.org
Thu Mar 19 09:48:29 PDT 2026


================
@@ -0,0 +1,71 @@
+! Test declare reduction with a derived type that has a FINAL subroutine
+! and a non-trivial user-defined initializer, to verify that initialization
+! and finalization are generated correctly.
+!
+! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
+
+module m
+  implicit none
+
+  type :: t
+    integer :: x = -999
+  contains
+    final :: cleanup
+  end type t
+
+contains
+
+  subroutine cleanup(this)
+    type(t), intent(inout) :: this
+    this%x = 0
+  end subroutine cleanup
+
+end module m
+
+program test
+  use m
+  implicit none
+
+  type(t) :: a
+
+  !$omp declare reduction(plus_t:t: omp_out%x = omp_out%x + omp_in%x) &
+  !$omp&  initializer(omp_priv = t(100))
+
+  a = t(200)
+
+  !$omp parallel reduction(plus_t:a)
+  a%x = a%x + 1
+  !$omp end parallel
+
+end program test
+
+! Verify the declare_reduction has alloc, init, and combiner regions.
+!
+! CHECK: omp.declare_reduction @plus_t{{.*}} : !fir.ref<[[TY:!fir.type<_QMmTt\{x:i32\}>]]>
+!
+! -- alloc region
+! CHECK:        alloc {
+! CHECK:          %[[ALLOCA:.*]] = fir.alloca [[TY]]
+! CHECK:          omp.yield(%[[ALLOCA]] : !fir.ref<[[TY]]>)
+!
+! -- init region: should store the user-provided init value T(100)
+! CHECK:        } init {
+! CHECK:        ^bb0(%[[INIT_ARG0:.*]]: !fir.ref<[[TY]]>, %[[INIT_ARG1:.*]]: !fir.ref<[[TY]]>):
+! CHECK:          %{{.*}}:2 = hlfir.declare %[[INIT_ARG0]] {uniq_name = "omp_orig"}
+! CHECK:          %{{.*}}:2 = hlfir.declare %[[INIT_ARG1]] {uniq_name = "omp_priv"}
+! CHECK:          fir.store %{{.*}} to %{{.*}}
----------------
tblah wrote:

It would be interesting to check which value is stored. Is it storing the default value of -999 or calling the constructor in the initializer clause of declare_reduction (resulting in 200)? I think the correct value is 200. It would be good to balance that with a second test which ensures it uses the default constructor for the type when there is no initializer clause.

An allocatable component would be interesting too because (I think) the box needs to be initialized correctly, and the data free'ed at the appropriate time.

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


More information about the flang-commits mailing list