blob: 89390812ada900e7d2e6c7180a4f3dd8ccbed7d4 [file] [edit]
! User-defined reduction on allocatable scalar/1-D/2-D integer variables must
! lower to boxed by-ref ops.
! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=45 %s -o - | FileCheck %s
subroutine test_udr_allocatable()
implicit none
integer :: i
integer, allocatable :: a, b(:), c(:,:)
!$omp declare reduction (foo : integer : omp_out = omp_out + omp_in) &
!$omp & initializer (omp_priv = 0)
allocate(a, b(4), c(3,2))
a = 0
b = 0
c = 0
!$omp parallel do reduction(foo : a)
do i = 1, 10
a = a + i
end do
!$omp parallel do reduction(foo : b)
do i = 1, 10
b = b + i
end do
!$omp parallel do reduction(foo : c)
do i = 1, 10
c = c + i
end do
end subroutine
! The 2-D allocatable: boxed by-ref op, iterated combiner, cleanup freemem.
! CHECK-LABEL: omp.declare_reduction @{{.*}}foo_byref_box_heap_UxUxi32 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>
! CHECK-SAME: attributes {byref_element_type = !fir.array<?x?xi32>}
! CHECK: alloc {
! CHECK: fir.alloca !fir.box<!fir.heap<!fir.array<?x?xi32>>>
! CHECK: omp.yield
! CHECK: } init {
! CHECK: arith.constant 0 : i32
! CHECK: omp.yield
! CHECK: } combiner {
! CHECK: ^bb0(%[[ARG0_2D:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>, %[[ARG1_2D:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>):
! CHECK: %[[LHS_BOX_2D:.*]] = fir.load %[[ARG0_2D]]
! CHECK: %[[RHS_BOX_2D:.*]] = fir.load %[[ARG1_2D]]
! CHECK: fir.shape_shift
! CHECK: fir.do_loop {{.*}} unordered {
! CHECK: fir.do_loop {{.*}} unordered {
! CHECK: fir.array_coor %[[LHS_BOX_2D]]
! CHECK: fir.array_coor %[[RHS_BOX_2D]]
! CHECK: arith.addi
! CHECK: fir.store
! CHECK: }
! CHECK: }
! CHECK: omp.yield(%[[ARG0_2D]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>)
! CHECK: } cleanup {
! CHECK: fir.freemem
! CHECK: omp.yield
! The 1-D allocatable.
! CHECK-LABEL: omp.declare_reduction @{{.*}}foo_byref_box_heap_Uxi32 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
! CHECK-SAME: attributes {byref_element_type = !fir.array<?xi32>}
! CHECK: alloc {
! CHECK: fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>>
! CHECK: omp.yield
! CHECK: } init {
! CHECK: arith.constant 0 : i32
! CHECK: omp.yield
! CHECK: } combiner {
! CHECK: ^bb0(%[[ARG0_1D:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, %[[ARG1_1D:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>):
! CHECK: %[[LHS_BOX_1D:.*]] = fir.load %[[ARG0_1D]]
! CHECK: %[[RHS_BOX_1D:.*]] = fir.load %[[ARG1_1D]]
! CHECK: fir.shape_shift
! CHECK: fir.do_loop {{.*}} unordered {
! CHECK: fir.array_coor %[[LHS_BOX_1D]]
! CHECK: fir.array_coor %[[RHS_BOX_1D]]
! CHECK: arith.addi
! CHECK: fir.store
! CHECK: }
! CHECK: omp.yield(%[[ARG0_1D]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>)
! CHECK: } cleanup {
! CHECK: fir.freemem
! CHECK: omp.yield
! The scalar allocatable.
! CHECK-LABEL: omp.declare_reduction @{{.*}}foo_byref_box_heap_i32 : !fir.ref<!fir.box<!fir.heap<i32>>>
! CHECK-SAME: attributes {byref_element_type = i32}
! CHECK: alloc {
! CHECK: fir.alloca !fir.box<!fir.heap<i32>>
! CHECK: omp.yield
! CHECK: } init {
! CHECK: arith.constant 0 : i32
! CHECK: omp.yield
! CHECK: } combiner {
! CHECK: ^bb0(%[[ARG0_S:.*]]: !fir.ref<!fir.box<!fir.heap<i32>>>, %[[ARG1_S:.*]]: !fir.ref<!fir.box<!fir.heap<i32>>>):
! CHECK: %[[LHS_BOX_S:.*]] = fir.load %[[ARG0_S]]
! CHECK: %[[RHS_BOX_S:.*]] = fir.load %[[ARG1_S]]
! CHECK: %[[LHS_ADDR_S:.*]] = fir.box_addr %[[LHS_BOX_S]]
! CHECK: %[[RHS_ADDR_S:.*]] = fir.box_addr %[[RHS_BOX_S]]
! CHECK: fir.load %[[LHS_ADDR_S]]
! CHECK: fir.load %[[RHS_ADDR_S]]
! CHECK: arith.addi
! CHECK: fir.store %{{.*}} to %[[LHS_ADDR_S]]
! CHECK: omp.yield(%[[ARG0_S]] : !fir.ref<!fir.box<!fir.heap<i32>>>)
! CHECK: } cleanup {
! CHECK: fir.freemem
! CHECK: omp.yield
! The base element-typed by-value op that the boxed ops wrap.
! CHECK-LABEL: omp.declare_reduction @{{.*}}foo_i32 : i32
! CHECK: init {
! CHECK: %[[C0_BASE:.*]] = arith.constant 0 : i32
! CHECK: omp.yield(%[[C0_BASE]] : i32)
! CHECK: } combiner {
! CHECK: ^bb0(%[[LHS_BASE:.*]]: i32, %[[RHS_BASE:.*]]: i32):
! CHECK: arith.addi
! CHECK: omp.yield
! Each loop binds the boxed op matching its variable's shape.
! CHECK-LABEL: func.func @_QPtest_udr_allocatable
! CHECK: omp.wsloop {{.*}} reduction(byref @{{.*}}foo_byref_box_heap_i32 %{{.*}} -> %{{.*}} : !fir.ref<!fir.box<!fir.heap<i32>>>)
! CHECK: omp.wsloop {{.*}} reduction(byref @{{.*}}foo_byref_box_heap_Uxi32 %{{.*}} -> %{{.*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>)
! CHECK: omp.wsloop {{.*}} reduction(byref @{{.*}}foo_byref_box_heap_UxUxi32 %{{.*}} -> %{{.*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>)