From 07f32fb9c6e6e937005d63497c7a1e5247bb50e0 Mon Sep 17 00:00:00 2001 From: Jean Perier Date: Mon, 15 Sep 2025 06:24:25 -0700 Subject: [PATCH] [flang][openacc] implement firsprivate of scalar derived type --- flang/lib/Lower/OpenACC.cpp | 9 ++ ...tprivate-derived-allocatable-component.f90 | 67 +++++++++++++ ...firstprivate-derived-pointer-component.f90 | 76 ++++++++++++++ .../acc-firstprivate-derived-user-assign.f90 | 99 +++++++++++++++++++ .../OpenACC/acc-firstprivate-derived.f90 | 85 ++++++++++++++++ 5 files changed, 336 insertions(+) create mode 100644 flang/test/Lower/OpenACC/acc-firstprivate-derived-allocatable-component.f90 create mode 100644 flang/test/Lower/OpenACC/acc-firstprivate-derived-pointer-component.f90 create mode 100644 flang/test/Lower/OpenACC/acc-firstprivate-derived-user-assign.f90 create mode 100644 flang/test/Lower/OpenACC/acc-firstprivate-derived.f90 diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp index d8a0e4d8a8fa0..bcaad61131c4f 100644 --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -1253,6 +1253,15 @@ mlir::acc::FirstprivateRecipeOp Fortran::lower::createOrGetFirstprivateRecipe( auto right = genDesignateWithTriplets(firBuilder, loc, rightEntity, triplets, shape); hlfir::AssignOp::create(firBuilder, loc, left, right); + } else { + // Copy scalar derived type. + // The temporary_lhs flag allows indicating that user defined assignments + // should not be called while copying components, and that the LHS and RHS + // are known to not alias since the LHS is a created object. + hlfir::AssignOp::create( + builder, loc, recipe.getCopyRegion().getArgument(0), + recipe.getCopyRegion().getArgument(1), /*realloc=*/false, + /*keep_lhs_length_if_realloc=*/false, /*temporary_lhs=*/true); } mlir::acc::TerminatorOp::create(builder, loc); diff --git a/flang/test/Lower/OpenACC/acc-firstprivate-derived-allocatable-component.f90 b/flang/test/Lower/OpenACC/acc-firstprivate-derived-allocatable-component.f90 new file mode 100644 index 0000000000000..b07ca21a43aa7 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-firstprivate-derived-allocatable-component.f90 @@ -0,0 +1,67 @@ +! Test lowering of firstprivate on derived type with allocatable components. +! The runtime is called to handled the deep copy of the allocatable components. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s +! RUN: bbc -fopenacc -emit-fir %s -o - | FileCheck %s --check-prefix=FIR-CHECK + +module m_firstprivate_derived_alloc_comp + type point + real, allocatable :: x(:) + end type point + contains + subroutine test(a) + type(point) :: a + + !$acc parallel loop firstprivate(a) + do i = 1, n + a%x(10) = 1 + enddo + end + end module + +! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_rec__QMm_firstprivate_derived_alloc_compTpoint : !fir.ref>>}>> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>>}>>): +! CHECK: acc.yield %[[VAL_0]] : !fir.ref>>}>> +! +! CHECK: } copy { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>>}>>, %[[VAL_1:.*]]: !fir.ref>>}>>): +! CHECK: hlfir.assign %[[VAL_0]] to %[[VAL_1]] temporary_lhs : !fir.ref>>}>>, !fir.ref>>}>> +! CHECK: acc.terminator +! CHECK: } +! +! CHECK-LABEL: func.func @_QMm_firstprivate_derived_alloc_compPtest( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>}>> {fir.bindc_name = "a"}) { +! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {uniq_name = "_QMm_firstprivate_derived_alloc_compFtestEa"} : (!fir.ref>>}>>, !fir.dscope) -> (!fir.ref>>}>>, !fir.ref>>}>>) +! CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QMm_firstprivate_derived_alloc_compFtestEi"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QMm_firstprivate_derived_alloc_compFtestEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_4:.*]] = fir.alloca i32 {bindc_name = "n", uniq_name = "_QMm_firstprivate_derived_alloc_compFtestEn"} +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QMm_firstprivate_derived_alloc_compFtestEn"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_6:.*]] = acc.firstprivate varPtr(%[[VAL_1]]#0 : !fir.ref>>}>>) -> !fir.ref>>}>> {name = "a"} +! CHECK: acc.parallel combined(loop) firstprivate(@firstprivatization_ref_rec__QMm_firstprivate_derived_alloc_compTpoint -> %[[VAL_6]] : !fir.ref>>}>>) { +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_10:.*]] = acc.private varPtr(%[[VAL_3]]#0 : !fir.ref) -> !fir.ref {implicit = true, name = "i"} +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QMm_firstprivate_derived_alloc_compFtestEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: acc.loop combined(parallel) private(@privatization_ref_i32 -> %[[VAL_10]] : !fir.ref) control(%[[VAL_12:.*]] : i32) = (%[[VAL_7]] : i32) to (%[[VAL_8]] : i32) step (%[[VAL_9]] : i32) { +! CHECK: fir.store %[[VAL_12]] to %[[VAL_11]]#0 : !fir.ref +! CHECK: %[[VAL_13:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: %[[VAL_14:.*]] = hlfir.designate %[[VAL_1]]#0{"x"} {fortran_attrs = #fir.var_attrs} : (!fir.ref>>}>>) -> !fir.ref>>> +! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_14]] : !fir.ref>>> +! CHECK: %[[VAL_16:.*]] = arith.constant 10 : index +! CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_15]] (%[[VAL_16]]) : (!fir.box>>, index) -> !fir.ref +! CHECK: hlfir.assign %[[VAL_13]] to %[[VAL_17]] : f32, !fir.ref +! CHECK: acc.yield +! CHECK: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} +! CHECK: acc.yield +! CHECK: } +! CHECK: return +! CHECK: } + + +! FIR-CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_rec__QMm_firstprivate_derived_alloc_compTpoint : !fir.ref>>}>> init { +! FIR-CHECK: } copy { +! FIR-CHECK: fir.call @_FortranAAssignTemporary( +! FIR-CHECK: acc.terminator +! FIR-CHECK: } diff --git a/flang/test/Lower/OpenACC/acc-firstprivate-derived-pointer-component.f90 b/flang/test/Lower/OpenACC/acc-firstprivate-derived-pointer-component.f90 new file mode 100644 index 0000000000000..8973b4b0085c2 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-firstprivate-derived-pointer-component.f90 @@ -0,0 +1,76 @@ +! Test lowering of firstprivate on derived type with pointer components. +! No deep copy must be done. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s +! RUN: bbc -fopenacc -emit-fir %s -o - | FileCheck %s --check-prefix=FIR-CHECK + +module m_firstprivate_derived_ptr_comp + type point + real, pointer :: x(:) + end type point + contains + subroutine test(a) + type(point) :: a + + !$acc parallel loop firstprivate(a) + do i = 1, n + a%x(10) = 1 + enddo + end + end module + +! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_rec__QMm_firstprivate_derived_ptr_compTpoint : !fir.ref>>}>> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>>}>>): +! CHECK: acc.yield %[[VAL_0]] : !fir.ref>>}>> +! +! CHECK: } copy { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>>}>>, %[[VAL_1:.*]]: !fir.ref>>}>>): +! CHECK: hlfir.assign %[[VAL_0]] to %[[VAL_1]] temporary_lhs : !fir.ref>>}>>, !fir.ref>>}>> +! CHECK: acc.terminator +! CHECK: } +! +! CHECK-LABEL: func.func @_QMm_firstprivate_derived_ptr_compPtest( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>}>> {fir.bindc_name = "a"}) { +! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {uniq_name = "_QMm_firstprivate_derived_ptr_compFtestEa"} : (!fir.ref>>}>>, !fir.dscope) -> (!fir.ref>>}>>, !fir.ref>>}>>) +! CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QMm_firstprivate_derived_ptr_compFtestEi"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QMm_firstprivate_derived_ptr_compFtestEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_4:.*]] = fir.alloca i32 {bindc_name = "n", uniq_name = "_QMm_firstprivate_derived_ptr_compFtestEn"} +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QMm_firstprivate_derived_ptr_compFtestEn"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_6:.*]] = acc.firstprivate varPtr(%[[VAL_1]]#0 : !fir.ref>>}>>) -> !fir.ref>>}>> {name = "a"} +! CHECK: acc.parallel combined(loop) firstprivate(@firstprivatization_ref_rec__QMm_firstprivate_derived_ptr_compTpoint -> %[[VAL_6]] : !fir.ref>>}>>) { +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_10:.*]] = acc.private varPtr(%[[VAL_3]]#0 : !fir.ref) -> !fir.ref {implicit = true, name = "i"} +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QMm_firstprivate_derived_ptr_compFtestEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: acc.loop combined(parallel) private(@privatization_ref_i32 -> %[[VAL_10]] : !fir.ref) control(%[[VAL_12:.*]] : i32) = (%[[VAL_7]] : i32) to (%[[VAL_8]] : i32) step (%[[VAL_9]] : i32) { +! CHECK: fir.store %[[VAL_12]] to %[[VAL_11]]#0 : !fir.ref +! CHECK: %[[VAL_13:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: %[[VAL_14:.*]] = hlfir.designate %[[VAL_1]]#0{"x"} {fortran_attrs = #fir.var_attrs} : (!fir.ref>>}>>) -> !fir.ref>>> +! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_14]] : !fir.ref>>> +! CHECK: %[[VAL_16:.*]] = arith.constant 10 : index +! CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_15]] (%[[VAL_16]]) : (!fir.box>>, index) -> !fir.ref +! CHECK: hlfir.assign %[[VAL_13]] to %[[VAL_17]] : f32, !fir.ref +! CHECK: acc.yield +! CHECK: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} +! CHECK: acc.yield +! CHECK: } +! CHECK: return +! CHECK: } + + +! FIR-CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_rec__QMm_firstprivate_derived_ptr_compTpoint : !fir.ref>>}>> init { +! FIR-CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>>}>>): +! FIR-CHECK: acc.yield %[[VAL_0]] : !fir.ref>>}>> +! +! FIR-CHECK-LABEL: } copy { +! FIR-CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>>}>>, %[[VAL_1:.*]]: !fir.ref>>}>>): +! FIR-CHECK: %[[VAL_2:.*]] = fir.field_index x, !fir.type<_QMm_firstprivate_derived_ptr_compTpoint{x:!fir.box>>}> +! FIR-CHECK: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_0]], x : (!fir.ref>>}>>) -> !fir.ref>>> +! FIR-CHECK: %[[VAL_4:.*]] = fir.field_index x, !fir.type<_QMm_firstprivate_derived_ptr_compTpoint{x:!fir.box>>}> +! FIR-CHECK: %[[VAL_5:.*]] = fir.coordinate_of %[[VAL_1]], x : (!fir.ref>>}>>) -> !fir.ref>>> +! FIR-CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_3]] : !fir.ref>>> +! FIR-CHECK: fir.store %[[VAL_6]] to %[[VAL_5]] : !fir.ref>>> +! FIR-CHECK: acc.terminator +! FIR-CHECK: } diff --git a/flang/test/Lower/OpenACC/acc-firstprivate-derived-user-assign.f90 b/flang/test/Lower/OpenACC/acc-firstprivate-derived-user-assign.f90 new file mode 100644 index 0000000000000..02065b7c03664 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-firstprivate-derived-user-assign.f90 @@ -0,0 +1,99 @@ +! Test lowering of firstprivate on derived type with user defined assignments, +! The user defined assignments should not be called when making firstprivate +! copies. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s +! RUN: bbc -fopenacc -emit-fir %s -o - | FileCheck %s --check-prefix=FIR-CHECK + +module m_firstprivate_derived_user_def + type point + real :: x, y, z + contains + procedure :: user_copy + generic :: assignment(=) => user_copy + end type point + contains + + subroutine user_copy(lhs, rhs) + class(point), intent(out) :: lhs + class(point), intent(in) :: rhs + print *, "hello, I am a side effect" + lhs%x = rhs%x + lhs%y = rhs%y + lhs%z = rhs%z + end subroutine + + subroutine test() + type(point) :: a + + !$acc parallel loop firstprivate(a) + do i = 1, n + a%x = 1 + enddo + end + end module + +! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_rec__QMm_firstprivate_derived_user_defTpoint : !fir.ref> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>): +! CHECK: acc.yield %[[VAL_0]] : !fir.ref> +! +! CHECK: } copy { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>, %[[VAL_1:.*]]: !fir.ref>): +! CHECK: hlfir.assign %[[VAL_0]] to %[[VAL_1]] temporary_lhs : !fir.ref>, !fir.ref> +! CHECK: acc.terminator +! CHECK: } +! +! CHECK-LABEL: func.func @_QMm_firstprivate_derived_user_defPtest() { +! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}> {bindc_name = "a", uniq_name = "_QMm_firstprivate_derived_user_defFtestEa"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QMm_firstprivate_derived_user_defFtestEa"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QMm_firstprivate_derived_user_defFtestEi"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QMm_firstprivate_derived_user_defFtestEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {bindc_name = "n", uniq_name = "_QMm_firstprivate_derived_user_defFtestEn"} +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QMm_firstprivate_derived_user_defFtestEn"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_7:.*]] = acc.firstprivate varPtr(%[[VAL_2]]#0 : !fir.ref>) -> !fir.ref> {name = "a"} +! CHECK: acc.parallel combined(loop) firstprivate(@firstprivatization_ref_rec__QMm_firstprivate_derived_user_defTpoint -> %[[VAL_7]] : !fir.ref>) { +! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref +! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_11:.*]] = acc.private varPtr(%[[VAL_4]]#0 : !fir.ref) -> !fir.ref {implicit = true, name = "i"} +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_11]] {uniq_name = "_QMm_firstprivate_derived_user_defFtestEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: acc.loop combined(parallel) private(@privatization_ref_i32 -> %[[VAL_11]] : !fir.ref) control(%[[VAL_13:.*]] : i32) = (%[[VAL_8]] : i32) to (%[[VAL_9]] : i32) step (%[[VAL_10]] : i32) { +! CHECK: fir.store %[[VAL_13]] to %[[VAL_12]]#0 : !fir.ref +! CHECK: %[[VAL_14:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: %[[VAL_15:.*]] = hlfir.designate %[[VAL_2]]#0{"x"} : (!fir.ref>) -> !fir.ref +! CHECK: hlfir.assign %[[VAL_14]] to %[[VAL_15]] : f32, !fir.ref +! CHECK: acc.yield +! CHECK: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} +! CHECK: acc.yield +! CHECK: } +! CHECK: return +! CHECK: } + + +! FIR-CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_rec__QMm_firstprivate_derived_user_defTpoint : !fir.ref> init { +! FIR-CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>): +! FIR-CHECK: acc.yield %[[VAL_0]] : !fir.ref> +! FIR- +! FIR-CHECK: } copy { +! FIR-CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>, %[[VAL_1:.*]]: !fir.ref>): +! 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.ref +! 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.ref +! FIR-CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_3]] : !fir.ref +! FIR-CHECK: fir.store %[[VAL_6]] to %[[VAL_5]] : !fir.ref +! 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.ref +! 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.ref +! FIR-CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_8]] : !fir.ref +! FIR-CHECK: fir.store %[[VAL_11]] to %[[VAL_10]] : !fir.ref +! 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.ref +! 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.ref +! FIR-CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_13]] : !fir.ref +! FIR-CHECK: fir.store %[[VAL_16]] to %[[VAL_15]] : !fir.ref +! 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 new file mode 100644 index 0000000000000..b4580355159ea --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-firstprivate-derived.f90 @@ -0,0 +1,85 @@ +! Test lowering of firstprivate on simple derived types (no allocatable/pointer +! components, no user defined procedures). + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s +! RUN: bbc -fopenacc -emit-fir %s -o - | FileCheck %s --check-prefix=FIR-CHECK + +module m_firstprivate_derived + type point + real :: x, y, z + end type point + contains + subroutine test() + type(point) :: a + + !$acc parallel loop firstprivate(a) + do i = 1, n + a%x = 1 + enddo + end + end module + +! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_rec__QMm_firstprivate_derivedTpoint : !fir.ref> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>): +! CHECK: acc.yield %[[VAL_0]] : !fir.ref> +! +! CHECK: } copy { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>, %[[VAL_1:.*]]: !fir.ref>): +! CHECK: hlfir.assign %[[VAL_0]] to %[[VAL_1]] temporary_lhs : !fir.ref>, !fir.ref> +! CHECK: acc.terminator +! CHECK: } +! +! CHECK-LABEL: func.func @_QMm_firstprivate_derivedPtest() { +! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}> {bindc_name = "a", uniq_name = "_QMm_firstprivate_derivedFtestEa"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QMm_firstprivate_derivedFtestEa"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QMm_firstprivate_derivedFtestEi"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QMm_firstprivate_derivedFtestEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {bindc_name = "n", uniq_name = "_QMm_firstprivate_derivedFtestEn"} +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QMm_firstprivate_derivedFtestEn"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_7:.*]] = acc.firstprivate varPtr(%[[VAL_2]]#0 : !fir.ref>) -> !fir.ref> {name = "a"} +! CHECK: acc.parallel combined(loop) firstprivate(@firstprivatization_ref_rec__QMm_firstprivate_derivedTpoint -> %[[VAL_7]] : !fir.ref>) { +! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref +! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_11:.*]] = acc.private varPtr(%[[VAL_4]]#0 : !fir.ref) -> !fir.ref {implicit = true, name = "i"} +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_11]] {uniq_name = "_QMm_firstprivate_derivedFtestEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: acc.loop combined(parallel) private(@privatization_ref_i32 -> %[[VAL_11]] : !fir.ref) control(%[[VAL_13:.*]] : i32) = (%[[VAL_8]] : i32) to (%[[VAL_9]] : i32) step (%[[VAL_10]] : i32) { +! CHECK: fir.store %[[VAL_13]] to %[[VAL_12]]#0 : !fir.ref +! CHECK: %[[VAL_14:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: %[[VAL_15:.*]] = hlfir.designate %[[VAL_2]]#0{"x"} : (!fir.ref>) -> !fir.ref +! CHECK: hlfir.assign %[[VAL_14]] to %[[VAL_15]] : f32, !fir.ref +! CHECK: acc.yield +! CHECK: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} +! CHECK: acc.yield +! CHECK: } +! CHECK: return +! CHECK: } + + +! FIR-CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_rec__QMm_firstprivate_derivedTpoint : !fir.ref> init { +! FIR-CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>): +! FIR-CHECK: acc.yield %[[VAL_0]] : !fir.ref> +! FIR- +! FIR-CHECK: } copy { +! FIR-CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>, %[[VAL_1:.*]]: !fir.ref>): +! 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.ref +! 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.ref +! FIR-CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_3]] : !fir.ref +! FIR-CHECK: fir.store %[[VAL_6]] to %[[VAL_5]] : !fir.ref +! 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.ref +! 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.ref +! FIR-CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_8]] : !fir.ref +! FIR-CHECK: fir.store %[[VAL_11]] to %[[VAL_10]] : !fir.ref +! 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.ref +! 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.ref +! FIR-CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_13]] : !fir.ref +! FIR-CHECK: fir.store %[[VAL_16]] to %[[VAL_15]] : !fir.ref +! FIR-CHECK: acc.terminator +! FIR-CHECK: }