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 @@ -397,12 +397,13 @@ } } -static mlir::acc::ParallelOp -createParallelOp(Fortran::lower::AbstractConverter &converter, - mlir::Location currentLocation, - Fortran::semantics::SemanticsContext &semanticsContext, - Fortran::lower::StatementContext &stmtCtx, - const Fortran::parser::AccClauseList &accClauseList) { +template +static Op +createComputeOp(Fortran::lower::AbstractConverter &converter, + mlir::Location currentLocation, + Fortran::semantics::SemanticsContext &semanticsContext, + Fortran::lower::StatementContext &stmtCtx, + const Fortran::parser::AccClauseList &accClauseList) { // Parallel operation operands mlir::Value async; @@ -550,9 +551,11 @@ llvm::SmallVector operandSegments; addOperand(operands, operandSegments, async); addOperands(operands, operandSegments, waitOperands); - addOperand(operands, operandSegments, numGangs); - addOperand(operands, operandSegments, numWorkers); - addOperand(operands, operandSegments, vectorLength); + if constexpr (std::is_same_v) { + addOperand(operands, operandSegments, numGangs); + addOperand(operands, operandSegments, numWorkers); + addOperand(operands, operandSegments, vectorLength); + } addOperand(operands, operandSegments, ifCond); addOperand(operands, operandSegments, selfCond); addOperands(operands, operandSegments, reductionOperands); @@ -570,28 +573,17 @@ addOperands(operands, operandSegments, privateOperands); addOperands(operands, operandSegments, firstprivateOperands); - mlir::acc::ParallelOp parallelOp = - createRegionOp( - firOpBuilder, currentLocation, operands, operandSegments); + Op computeOp = createRegionOp( + firOpBuilder, currentLocation, operands, operandSegments); if (addAsyncAttr) - parallelOp.setAsyncAttrAttr(firOpBuilder.getUnitAttr()); + computeOp.setAsyncAttrAttr(firOpBuilder.getUnitAttr()); if (addWaitAttr) - parallelOp.setWaitAttrAttr(firOpBuilder.getUnitAttr()); + computeOp.setWaitAttrAttr(firOpBuilder.getUnitAttr()); if (addSelfAttr) - parallelOp.setSelfAttrAttr(firOpBuilder.getUnitAttr()); + computeOp.setSelfAttrAttr(firOpBuilder.getUnitAttr()); - return parallelOp; -} - -static void -genACCParallelOp(Fortran::lower::AbstractConverter &converter, - mlir::Location currentLocation, - Fortran::semantics::SemanticsContext &semanticsContext, - Fortran::lower::StatementContext &stmtCtx, - const Fortran::parser::AccClauseList &accClauseList) { - createParallelOp(converter, currentLocation, semanticsContext, stmtCtx, - accClauseList); + return computeOp; } static void genACCDataOp(Fortran::lower::AbstractConverter &converter, @@ -696,13 +688,14 @@ Fortran::lower::StatementContext stmtCtx; if (blockDirective.v == llvm::acc::ACCD_parallel) { - genACCParallelOp(converter, currentLocation, semanticsContext, stmtCtx, - accClauseList); + createComputeOp( + converter, currentLocation, semanticsContext, stmtCtx, accClauseList); } else if (blockDirective.v == llvm::acc::ACCD_data) { genACCDataOp(converter, currentLocation, semanticsContext, stmtCtx, accClauseList); } else if (blockDirective.v == llvm::acc::ACCD_serial) { - TODO(currentLocation, "serial construct lowering"); + createComputeOp( + converter, currentLocation, semanticsContext, stmtCtx, accClauseList); } else if (blockDirective.v == llvm::acc::ACCD_kernels) { TODO(currentLocation, "kernels construct lowering"); } else if (blockDirective.v == llvm::acc::ACCD_host_data) { @@ -710,18 +703,6 @@ } } -static void -genACCParallelLoopOps(Fortran::lower::AbstractConverter &converter, - mlir::Location currentLocation, - Fortran::semantics::SemanticsContext &semanticsContext, - Fortran::lower::StatementContext &stmtCtx, - const Fortran::parser::AccClauseList &accClauseList) { - createParallelOp(converter, currentLocation, semanticsContext, stmtCtx, - accClauseList); - createLoopOp(converter, currentLocation, semanticsContext, stmtCtx, - accClauseList); -} - static void genACC(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semanticsContext, @@ -741,10 +722,15 @@ if (combinedDirective.v == llvm::acc::ACCD_kernels_loop) { TODO(currentLocation, "OpenACC Kernels Loop construct not lowered yet!"); } else if (combinedDirective.v == llvm::acc::ACCD_parallel_loop) { - genACCParallelLoopOps(converter, currentLocation, semanticsContext, stmtCtx, - accClauseList); + createComputeOp( + converter, currentLocation, semanticsContext, stmtCtx, accClauseList); + createLoopOp(converter, currentLocation, semanticsContext, stmtCtx, + accClauseList); } else if (combinedDirective.v == llvm::acc::ACCD_serial_loop) { - TODO(currentLocation, "OpenACC Serial Loop construct not lowered yet!"); + createComputeOp( + converter, currentLocation, semanticsContext, stmtCtx, accClauseList); + createLoopOp(converter, currentLocation, semanticsContext, stmtCtx, + accClauseList); } else { llvm::report_fatal_error("Unknown combined construct encountered"); } diff --git a/flang/test/Lower/OpenACC/acc-serial-loop.f90 b/flang/test/Lower/OpenACC/acc-serial-loop.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-serial-loop.f90 @@ -0,0 +1,613 @@ +! This test checks lowering of Openacc serial loop combined directive. + +! RUN: bbc -fopenacc -emit-fir %s -o - | FileCheck %s + +subroutine acc_serial_loop + integer :: i, j + + integer :: async = 1 + integer :: wait1 = 1 + integer :: wait2 = 2 + integer :: numGangs = 1 + integer :: numWorkers = 10 + integer :: vectorLength = 128 + logical :: ifCondition = .TRUE. + integer, parameter :: n = 10 + real, dimension(n) :: a, b, c + real, dimension(n, n) :: d, e + real, pointer :: f, g + + integer :: gangNum = 8 + integer :: gangStatic = 8 + integer :: vectorNum = 128 + integer, parameter :: tileSize = 2 + +!CHECK: [[A:%.*]] = fir.alloca !fir.array<10xf32> {{{.*}}uniq_name = "{{.*}}Ea"} +!CHECK: [[B:%.*]] = fir.alloca !fir.array<10xf32> {{{.*}}uniq_name = "{{.*}}Eb"} +!CHECK: [[C:%.*]] = fir.alloca !fir.array<10xf32> {{{.*}}uniq_name = "{{.*}}Ec"} +!CHECK: [[F:%.*]] = fir.alloca !fir.box> {bindc_name = "f", uniq_name = "{{.*}}Ef"} +!CHECK: [[G:%.*]] = fir.alloca !fir.box> {bindc_name = "g", uniq_name = "{{.*}}Eg"} +!CHECK: [[IFCONDITION:%.*]] = fir.address_of(@{{.*}}ifcondition) : !fir.ref> + + !$acc serial loop + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: acc.serial { +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop async + DO i = 1, n + a(i) = b(i) + END DO + !$acc end serial loop + +!CHECK: acc.serial { +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: } attributes {asyncAttr} + + !$acc serial loop async(1) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: [[ASYNC1:%.*]] = arith.constant 1 : i32 +!CHECK: acc.serial async([[ASYNC1]] : i32) { +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop async(async) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: [[ASYNC2:%.*]] = fir.load %{{.*}} : !fir.ref +!CHECK: acc.serial async([[ASYNC2]] : i32) { +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop wait + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: acc.serial { +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: } attributes {waitAttr} + + !$acc serial loop wait(1) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: [[WAIT1:%.*]] = arith.constant 1 : i32 +!CHECK: acc.serial wait([[WAIT1]] : i32) { +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop wait(1, 2) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: [[WAIT2:%.*]] = arith.constant 1 : i32 +!CHECK: [[WAIT3:%.*]] = arith.constant 2 : i32 +!CHECK: acc.serial wait([[WAIT2]], [[WAIT3]] : i32, i32) { +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop wait(wait1, wait2) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: [[WAIT4:%.*]] = fir.load %{{.*}} : !fir.ref +!CHECK: [[WAIT5:%.*]] = fir.load %{{.*}} : !fir.ref +!CHECK: acc.serial wait([[WAIT4]], [[WAIT5]] : i32, i32) { +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop if(.TRUE.) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: [[IF1:%.*]] = arith.constant true +!CHECK: acc.serial if([[IF1]]) { +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop if(ifCondition) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: [[IFCOND:%.*]] = fir.load %{{.*}} : !fir.ref> +!CHECK: [[IF2:%.*]] = fir.convert [[IFCOND]] : (!fir.logical<4>) -> i1 +!CHECK: acc.serial if([[IF2]]) { +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop self(.TRUE.) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: [[SELF1:%.*]] = arith.constant true +!CHECK: acc.serial self([[SELF1]]) { +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop self + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: acc.serial { +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: } attributes {selfAttr} + + !$acc serial loop self(ifCondition) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: [[SELF2:%.*]] = fir.convert [[IFCONDITION]] : (!fir.ref>) -> i1 +!CHECK: acc.serial self([[SELF2]]) { +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop copy(a, b) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: acc.serial copy([[A]], [[B]] : !fir.ref>, !fir.ref>) { +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop copy(a) copy(b) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: acc.serial copy([[A]], [[B]] : !fir.ref>, !fir.ref>) { +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop copyin(a) copyin(readonly: b) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: acc.serial copyin([[A]] : !fir.ref>) copyin_readonly([[B]] : !fir.ref>) { +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop copyout(a) copyout(zero: b) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: acc.serial copyout([[A]] : !fir.ref>) copyout_zero([[B]] : !fir.ref>) { +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop create(b) create(zero: a) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: acc.serial create([[B]] : !fir.ref>) create_zero([[A]] : !fir.ref>) { +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop no_create(a, b) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: acc.serial no_create([[A]], [[B]] : !fir.ref>, !fir.ref>) { +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop present(a, b) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: acc.serial present([[A]], [[B]] : !fir.ref>, !fir.ref>) { +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop deviceptr(a) deviceptr(b) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: acc.serial deviceptr([[A]], [[B]] : !fir.ref>, !fir.ref>) { +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop attach(f, g) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: acc.serial attach([[F]], [[G]] : !fir.ref>>, !fir.ref>>) { +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop private(a) firstprivate(b) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: acc.serial firstprivate([[B]] : !fir.ref>) private([[A]] : !fir.ref>) { +!CHECK: acc.loop private([[A]]: !fir.ref>) { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop seq + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: acc.serial { +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: } attributes {seq} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop auto + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: acc.serial { +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: } attributes {auto} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop independent + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: acc.serial { +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: } attributes {independent} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop gang + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: acc.serial { +!CHECK: acc.loop gang { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop gang(num: 8) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: acc.serial { +!CHECK: [[GANGNUM1:%.*]] = arith.constant 8 : i32 +!CHECK-NEXT: acc.loop gang(num=[[GANGNUM1]]: i32) { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop gang(num: gangNum) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: acc.serial { +!CHECK: [[GANGNUM2:%.*]] = fir.load %{{.*}} : !fir.ref +!CHECK-NEXT: acc.loop gang(num=[[GANGNUM2]]: i32) { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop gang(num: gangNum, static: gangStatic) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: acc.serial { +!CHECK: acc.loop gang(num=%{{.*}}: i32, static=%{{.*}}: i32) { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop vector + DO i = 1, n + a(i) = b(i) + END DO +!CHECK: acc.serial { +!CHECK: acc.loop vector { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop vector(128) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: acc.serial { +!CHECK: [[CONSTANT128:%.*]] = arith.constant 128 : i32 +!CHECK: acc.loop vector([[CONSTANT128]]: i32) { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop vector(vectorLength) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: acc.serial { +!CHECK: [[VECTORLENGTH:%.*]] = fir.load %{{.*}} : !fir.ref +!CHECK: acc.loop vector([[VECTORLENGTH]]: i32) { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop worker + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: acc.serial { +!CHECK: acc.loop worker { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop worker(128) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: acc.serial { +!CHECK: [[WORKER128:%.*]] = arith.constant 128 : i32 +!CHECK: acc.loop worker([[WORKER128]]: i32) { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop collapse(2) + DO i = 1, n + DO j = 1, n + d(i, j) = e(i, j) + END DO + END DO + +!CHECK: acc.serial { +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: } attributes {collapse = 2 : i64} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop + DO i = 1, n + !$acc loop + DO j = 1, n + d(i, j) = e(i, j) + END DO + END DO + +!CHECK: acc.serial { +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: acc.loop { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop tile(2) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: acc.serial { +!CHECK: [[TILESIZE:%.*]] = arith.constant 2 : i32 +!CHECK: acc.loop tile([[TILESIZE]]: i32) { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop tile(*) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: acc.serial { +!CHECK: [[TILESIZEM1:%.*]] = arith.constant -1 : i32 +!CHECK: acc.loop tile([[TILESIZEM1]]: i32) { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop tile(2, 2) + DO i = 1, n + DO j = 1, n + d(i, j) = e(i, j) + END DO + END DO + +!CHECK: acc.serial { +!CHECK: [[TILESIZE1:%.*]] = arith.constant 2 : i32 +!CHECK: [[TILESIZE2:%.*]] = arith.constant 2 : i32 +!CHECK: acc.loop tile([[TILESIZE1]]: i32, [[TILESIZE2]]: i32) { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop tile(tileSize) + DO i = 1, n + a(i) = b(i) + END DO + +!CHECK: acc.serial { +!CHECK: acc.loop tile(%{{.*}}: i32) { +!CHECK: fir.do_loop +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} +!CHECK: acc.yield +!CHECK-NEXT: }{{$}} + + !$acc serial loop tile(tileSize, tileSize) + DO i = 1, n + DO j = 1, n + d(i, j) = e(i, j) + END DO + END DO + +!CHECK: acc.serial { +!CHECK: acc.loop tile(%{{.*}}: i32, %{{.*}}: i32) { +!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 new file mode 100644 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-serial.f90 @@ -0,0 +1,198 @@ +! This test checks lowering of OpenACC serial directive. + +! RUN: bbc -fopenacc -emit-fir %s -o - | FileCheck %s + +subroutine acc_serial + integer :: i, j + + integer :: async = 1 + integer :: wait1 = 1 + integer :: wait2 = 2 + integer :: numGangs = 1 + integer :: numWorkers = 10 + integer :: vectorLength = 128 + logical :: ifCondition = .TRUE. + real, dimension(10, 10) :: a, b, c + real, pointer :: d, e + +! CHECK: [[A:%.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ea"} +! CHECK: [[B:%.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Eb"} +! CHECK: [[C:%.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ec"} +! CHECK: [[D:%.*]] = fir.alloca !fir.box> {bindc_name = "d", uniq_name = "{{.*}}Ed"} +! CHECK: [[E:%.*]] = fir.alloca !fir.box> {bindc_name = "e", uniq_name = "{{.*}}Ee"} +! CHECK: [[IFCONDITION:%.*]] = fir.address_of(@{{.*}}ifcondition) : !fir.ref> + + !$acc serial + !$acc end serial + +! CHECK: acc.serial { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial async + !$acc end serial + +! CHECK: acc.serial { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {asyncAttr} + + !$acc serial async(1) + !$acc end serial + +! CHECK: [[ASYNC1:%.*]] = arith.constant 1 : i32 +! CHECK: acc.serial async([[ASYNC1]] : i32) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial async(async) + !$acc end serial + +! CHECK: [[ASYNC2:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.serial async([[ASYNC2]] : i32) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial wait + !$acc end serial + +! CHECK: acc.serial { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {waitAttr} + + !$acc serial wait(1) + !$acc end serial + +! CHECK: [[WAIT1:%.*]] = arith.constant 1 : i32 +! CHECK: acc.serial wait([[WAIT1]] : i32) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial wait(1, 2) + !$acc end serial + +! CHECK: [[WAIT2:%.*]] = arith.constant 1 : i32 +! CHECK: [[WAIT3:%.*]] = arith.constant 2 : i32 +! CHECK: acc.serial wait([[WAIT2]], [[WAIT3]] : i32, i32) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial wait(wait1, wait2) + !$acc end serial + +! CHECK: [[WAIT4:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: [[WAIT5:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.serial wait([[WAIT4]], [[WAIT5]] : i32, i32) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial if(.TRUE.) + !$acc end serial + +! CHECK: [[IF1:%.*]] = arith.constant true +! CHECK: acc.serial if([[IF1]]) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial if(ifCondition) + !$acc end serial + +! CHECK: [[IFCOND:%.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK: [[IF2:%.*]] = fir.convert [[IFCOND]] : (!fir.logical<4>) -> i1 +! CHECK: acc.serial if([[IF2]]) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial self(.TRUE.) + !$acc end serial + +! CHECK: [[SELF1:%.*]] = arith.constant true +! CHECK: acc.serial self([[SELF1]]) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial self + !$acc end serial + +! CHECK: acc.serial { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {selfAttr} + + !$acc serial self(ifCondition) + !$acc end serial + +! CHECK: [[SELF2:%.*]] = fir.convert [[IFCONDITION]] : (!fir.ref>) -> i1 +! CHECK: acc.serial self([[SELF2]]) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial copy(a, b, c) + !$acc end serial + +! CHECK: acc.serial copy([[A]], [[B]], [[C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial copy(a) copy(b) copy(c) + !$acc end serial + +! CHECK: acc.serial copy([[A]], [[B]], [[C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial copyin(a) copyin(readonly: b, c) + !$acc end serial + +! CHECK: acc.serial copyin([[A]] : !fir.ref>) copyin_readonly([[B]], [[C]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial copyout(a) copyout(zero: b) copyout(c) + !$acc end serial + +! CHECK: acc.serial copyout([[A]], [[C]] : !fir.ref>, !fir.ref>) copyout_zero([[B]] : !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial create(a, b) create(zero: c) + !$acc end serial + +! CHECK: acc.serial create([[A]], [[B]] : !fir.ref>, !fir.ref>) create_zero([[C]] : !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial no_create(a, b) create(zero: c) + !$acc end serial + +! CHECK: acc.serial create_zero([[C]] : !fir.ref>) no_create([[A]], [[B]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial present(a, b, c) + !$acc end serial + +! CHECK: acc.serial present([[A]], [[B]], [[C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial deviceptr(a) deviceptr(c) + !$acc end serial + +! CHECK: acc.serial deviceptr([[A]], [[C]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial attach(d, e) + !$acc end serial + +! CHECK: acc.serial attach([[D]], [[E]] : !fir.ref>>, !fir.ref>>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial private(a) firstprivate(b) private(c) + !$acc end serial + +! CHECK: acc.serial firstprivate([[B]] : !fir.ref>) private([[A]], [[C]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + +end subroutine