llvm::SmallVector<mlir::Value> reductionOperands, privateOperands,
firstprivateOperands;
- llvm::SmallVector<mlir::Attribute> privatizations;
+ llvm::SmallVector<mlir::Attribute> 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
&clause.u)) {
genObjectList(firstprivateClause->v, converter, semanticsContext, stmtCtx,
firstprivateOperands);
- } else if (std::get_if<Fortran::parser::AccClause::Reduction>(&clause.u)) {
- TODO(clauseLocation, "compute construct reduction clause lowering");
+ } else if (const auto *reductionClause =
+ std::get_if<Fortran::parser::AccClause::Reduction>(
+ &clause.u)) {
+ genReductions(reductionClause->v, converter, semanticsContext, stmtCtx,
+ reductionOperands, reductionRecipes);
}
}
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();
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
! 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 {
+! CHECK: acc.loop reduction(@reduction_add_f32 -> %{{.*}} : !fir.ref<f32>, @reduction_mul_i32 -> %{{.*}} : !fir.ref<i32>) {
+! CHECK: fir.do_loop
+! CHECK: acc.yield
+! CHECK-NEXT: }{{$}}
+! CHECK: acc.terminator
! CHECK-NEXT: }{{$}}
end subroutine
integer :: gangStatic = 8
integer :: vectorLength = 128
integer, parameter :: tileSize = 2
+ integer :: reduction_i
+ real :: reduction_r
!$acc loop
!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<f32>, @reduction_mul_i32 -> %{{.*}} : !fir.ref<i32>) {
+! CHECK: fir.do_loop
+! CHECK: acc.yield
+! CHECK-NEXT: }{{$}}
+
end program
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
! 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<f32>, @reduction_mul_i32 -> %{{.*}} : !fir.ref<i32>) {
+! CHECK: acc.loop reduction(@reduction_add_f32 -> %{{.*}} : !fir.ref<f32>, @reduction_mul_i32 -> %{{.*}} : !fir.ref<i32>) {
+! CHECK: fir.do_loop
+! CHECK: acc.yield
+! CHECK-NEXT: }{{$}}
+! CHECK: acc.yield
! CHECK-NEXT: }{{$}}
end subroutine acc_parallel_loop
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"}
! 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<f32>, @reduction_mul_i32 -> %{{.*}} : !fir.ref<i32>) {
+! CHECK: acc.yield
+! CHECK-NEXT: }{{$}}
+
end subroutine acc_parallel
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
! 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<f32>, @reduction_mul_i32 -> %{{.*}} : !fir.ref<i32>) {
+! CHECK: acc.loop reduction(@reduction_add_f32 -> %{{.*}} : !fir.ref<f32>, @reduction_mul_i32 -> %{{.*}} : !fir.ref<i32>) {
+! CHECK: fir.do_loop
+! CHECK: acc.yield
+! CHECK-NEXT: }{{$}}
+! CHECK: acc.yield
! CHECK-NEXT: }{{$}}
end subroutine acc_serial_loop
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"}
! 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<f32>, @reduction_mul_i32 -> %{{.*}} : !fir.ref<i32>) {
+! CHECK: acc.yield
+! CHECK-NEXT: }{{$}}
+
end subroutine
return failure();
if (failed(checkSymOperandList<mlir::acc::ReductionRecipeOp>(
*this, getReductionRecipes(), getReductionOperands(), "reduction",
- "reductions")))
+ "reductions", false)))
return failure();
return checkDataOperands<acc::ParallelOp>(*this, getDataClauseOperands());
}
return failure();
if (failed(checkSymOperandList<mlir::acc::ReductionRecipeOp>(
*this, getReductionRecipes(), getReductionOperands(), "reduction",
- "reductions")))
+ "reductions", false)))
return failure();
return checkDataOperands<acc::SerialOp>(*this, getDataClauseOperands());
}