diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -997,7 +997,7 @@ llvm::SmallVector reductionOperands, privateOperands, firstprivateOperands; - llvm::SmallVector privatizations; + llvm::SmallVector privatizations, reductionRecipes; // Async, wait and self clause have optional values but can be present with // no value as well. When there is no value, the op has an attribute to @@ -1151,8 +1151,11 @@ &clause.u)) { genObjectList(firstprivateClause->v, converter, semanticsContext, stmtCtx, firstprivateOperands); - } else if (std::get_if(&clause.u)) { - TODO(clauseLocation, "compute construct reduction clause lowering"); + } else if (const auto *reductionClause = + std::get_if( + &clause.u)) { + genReductions(reductionClause->v, converter, semanticsContext, stmtCtx, + reductionOperands, reductionRecipes); } } @@ -1194,6 +1197,9 @@ if (!privatizations.empty()) computeOp.setPrivatizationsAttr( mlir::ArrayAttr::get(builder.getContext(), privatizations)); + if (!reductionRecipes.empty()) + computeOp.setReductionRecipesAttr( + mlir::ArrayAttr::get(builder.getContext(), reductionRecipes)); } auto insPt = builder.saveInsertionPoint(); diff --git a/flang/test/Lower/OpenACC/acc-kernels-loop.f90 b/flang/test/Lower/OpenACC/acc-kernels-loop.f90 --- a/flang/test/Lower/OpenACC/acc-kernels-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-kernels-loop.f90 @@ -16,6 +16,8 @@ real, dimension(n) :: a, b, c real, dimension(n, n) :: d, e real, pointer :: f, g + integer :: reduction_i + real :: reduction_r integer :: gangNum = 8 integer :: gangStatic = 8 @@ -709,6 +711,20 @@ ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop reduction(+:reduction_r) reduction(*:reduction_i) + do i = 1, n + reduction_r = reduction_r + a(i) + reduction_i = 1 + end do + +! CHECK: acc.kernels reduction(@reduction_add_f32 -> %{{.*}} : !fir.ref, @reduction_mul_i32 -> %{{.*}} : !fir.ref) { +! CHECK: acc.loop reduction(@reduction_add_f32 -> %{{.*}} : !fir.ref, @reduction_mul_i32 -> %{{.*}} : !fir.ref) { +! CHECK: fir.do_loop +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield ! CHECK-NEXT: }{{$}} end subroutine diff --git a/flang/test/Lower/OpenACC/acc-loop.f90 b/flang/test/Lower/OpenACC/acc-loop.f90 --- a/flang/test/Lower/OpenACC/acc-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-loop.f90 @@ -17,6 +17,8 @@ integer :: gangStatic = 8 integer :: vectorLength = 128 integer, parameter :: tileSize = 2 + integer :: reduction_i + real :: reduction_r !$acc loop @@ -270,4 +272,15 @@ !CHECK: acc.yield !CHECK-NEXT: }{{$}} + !$acc loop reduction(+:reduction_r) reduction(*:reduction_i) + do i = 1, n + reduction_r = reduction_r + a(i) + reduction_i = 1 + end do + +! CHECK: acc.loop reduction(@reduction_add_f32 -> %{{.*}} : !fir.ref, @reduction_mul_i32 -> %{{.*}} : !fir.ref) { +! CHECK: fir.do_loop +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + end program diff --git a/flang/test/Lower/OpenACC/acc-parallel-loop.f90 b/flang/test/Lower/OpenACC/acc-parallel-loop.f90 --- a/flang/test/Lower/OpenACC/acc-parallel-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-parallel-loop.f90 @@ -23,6 +23,8 @@ real, dimension(n) :: a, b, c real, dimension(n, n) :: d, e real, pointer :: f, g + integer :: reduction_i + real :: reduction_r integer :: gangNum = 8 integer :: gangStatic = 8 @@ -729,6 +731,20 @@ ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop reduction(+:reduction_r) reduction(*:reduction_i) + do i = 1, n + reduction_r = reduction_r + a(i) + reduction_i = 1 + end do + +! CHECK: acc.parallel reduction(@reduction_add_f32 -> %{{.*}} : !fir.ref, @reduction_mul_i32 -> %{{.*}} : !fir.ref) { +! CHECK: acc.loop reduction(@reduction_add_f32 -> %{{.*}} : !fir.ref, @reduction_mul_i32 -> %{{.*}} : !fir.ref) { +! CHECK: fir.do_loop +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield ! CHECK-NEXT: }{{$}} end subroutine acc_parallel_loop diff --git a/flang/test/Lower/OpenACC/acc-parallel.f90 b/flang/test/Lower/OpenACC/acc-parallel.f90 --- a/flang/test/Lower/OpenACC/acc-parallel.f90 +++ b/flang/test/Lower/OpenACC/acc-parallel.f90 @@ -21,6 +21,8 @@ logical :: ifCondition = .TRUE. real, dimension(10, 10) :: a, b, c real, pointer :: d, e + integer :: reduction_i + real :: reduction_r !CHECK: %[[A:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ea"} !CHECK: %[[B:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Eb"} @@ -302,4 +304,11 @@ ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} +!$acc parallel reduction(+:reduction_r) reduction(*:reduction_i) +!$acc end parallel + +! CHECK: acc.parallel reduction(@reduction_add_f32 -> %{{.*}} : !fir.ref, @reduction_mul_i32 -> %{{.*}} : !fir.ref) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + end subroutine acc_parallel diff --git a/flang/test/Lower/OpenACC/acc-serial-loop.f90 b/flang/test/Lower/OpenACC/acc-serial-loop.f90 --- a/flang/test/Lower/OpenACC/acc-serial-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-serial-loop.f90 @@ -23,6 +23,8 @@ real, dimension(n) :: a, b, c real, dimension(n, n) :: d, e real, pointer :: f, g + integer :: reduction_i + real :: reduction_r integer :: gangNum = 8 integer :: gangStatic = 8 @@ -645,6 +647,20 @@ ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop reduction(+:reduction_r) reduction(*:reduction_i) + do i = 1, n + reduction_r = reduction_r + a(i) + reduction_i = 1 + end do + +! CHECK: acc.serial reduction(@reduction_add_f32 -> %{{.*}} : !fir.ref, @reduction_mul_i32 -> %{{.*}} : !fir.ref) { +! CHECK: acc.loop reduction(@reduction_add_f32 -> %{{.*}} : !fir.ref, @reduction_mul_i32 -> %{{.*}} : !fir.ref) { +! CHECK: fir.do_loop +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield ! CHECK-NEXT: }{{$}} end subroutine acc_serial_loop diff --git a/flang/test/Lower/OpenACC/acc-serial.f90 b/flang/test/Lower/OpenACC/acc-serial.f90 --- a/flang/test/Lower/OpenACC/acc-serial.f90 +++ b/flang/test/Lower/OpenACC/acc-serial.f90 @@ -21,6 +21,8 @@ logical :: ifCondition = .TRUE. real, dimension(10, 10) :: a, b, c real, pointer :: d, e + integer :: reduction_i + real :: reduction_r ! CHECK: %[[A:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ea"} ! CHECK: %[[B:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Eb"} @@ -245,4 +247,11 @@ ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} +!$acc serial reduction(+:reduction_r) reduction(*:reduction_i) +!$acc end serial + +! CHECK: acc.serial reduction(@reduction_add_f32 -> %{{.*}} : !fir.ref, @reduction_mul_i32 -> %{{.*}} : !fir.ref) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + end subroutine diff --git a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp --- a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp +++ b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp @@ -558,7 +558,7 @@ return failure(); if (failed(checkSymOperandList( *this, getReductionRecipes(), getReductionOperands(), "reduction", - "reductions"))) + "reductions", false))) return failure(); return checkDataOperands(*this, getDataClauseOperands()); } @@ -586,7 +586,7 @@ return failure(); if (failed(checkSymOperandList( *this, getReductionRecipes(), getReductionOperands(), "reduction", - "reductions"))) + "reductions", false))) return failure(); return checkDataOperands(*this, getDataClauseOperands()); }