[flang-commits] [flang] d30b4e5 - [flang][openacc] Lower serial and serial loop construct

Valentin Clement via flang-commits flang-commits at lists.llvm.org
Thu Apr 13 15:36:17 PDT 2023


Author: Valentin Clement
Date: 2023-04-13T15:36:11-07:00
New Revision: d30b4e515a0cf509e56b88ddd7ddb87b9e601508

URL: https://github.com/llvm/llvm-project/commit/d30b4e515a0cf509e56b88ddd7ddb87b9e601508
DIFF: https://github.com/llvm/llvm-project/commit/d30b4e515a0cf509e56b88ddd7ddb87b9e601508.diff

LOG: [flang][openacc] Lower serial and serial loop construct

Lower the parse tree to acc dialects operations. Make use
of the parallel construct lowering and make it suitable
for all compute constructs lowering.

Reviewed By: PeteSteinfeld

Differential Revision: https://reviews.llvm.org/D148273

Added: 
    flang/test/Lower/OpenACC/acc-serial-loop.f90
    flang/test/Lower/OpenACC/acc-serial.f90

Modified: 
    flang/lib/Lower/OpenACC.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 0b8b2e2fa31b5..8c5f11923e5ac 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -397,12 +397,13 @@ static void genACC(Fortran::lower::AbstractConverter &converter,
   }
 }
 
-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 <typename Op>
+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 @@ createParallelOp(Fortran::lower::AbstractConverter &converter,
   llvm::SmallVector<int32_t, 8> 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<Op, mlir::acc::ParallelOp>) {
+    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 @@ createParallelOp(Fortran::lower::AbstractConverter &converter,
   addOperands(operands, operandSegments, privateOperands);
   addOperands(operands, operandSegments, firstprivateOperands);
 
-  mlir::acc::ParallelOp parallelOp =
-      createRegionOp<mlir::acc::ParallelOp, mlir::acc::YieldOp>(
-          firOpBuilder, currentLocation, operands, operandSegments);
+  Op computeOp = createRegionOp<Op, mlir::acc::YieldOp>(
+      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 @@ genACC(Fortran::lower::AbstractConverter &converter,
   Fortran::lower::StatementContext stmtCtx;
 
   if (blockDirective.v == llvm::acc::ACCD_parallel) {
-    genACCParallelOp(converter, currentLocation, semanticsContext, stmtCtx,
-                     accClauseList);
+    createComputeOp<mlir::acc::ParallelOp>(
+        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<mlir::acc::SerialOp>(
+        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 @@ genACC(Fortran::lower::AbstractConverter &converter,
   }
 }
 
-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 @@ genACC(Fortran::lower::AbstractConverter &converter,
   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<mlir::acc::ParallelOp>(
+        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<mlir::acc::SerialOp>(
+        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
index 0000000000000..e952554c7f48d
--- /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<!fir.ptr<f32>> {bindc_name = "f", uniq_name = "{{.*}}Ef"}
+!CHECK: [[G:%.*]] = fir.alloca !fir.box<!fir.ptr<f32>> {bindc_name = "g", uniq_name = "{{.*}}Eg"}
+!CHECK: [[IFCONDITION:%.*]] = fir.address_of(@{{.*}}ifcondition) : !fir.ref<!fir.logical<4>>
+
+  !$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<i32>
+!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<i32>
+!CHECK:      [[WAIT5:%.*]] = fir.load %{{.*}} : !fir.ref<i32>
+!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<!fir.logical<4>>
+!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<!fir.logical<4>>) -> 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.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) {
+!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.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) {
+!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<!fir.array<10xf32>>) copyin_readonly([[B]] : !fir.ref<!fir.array<10xf32>>) {
+!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<!fir.array<10xf32>>) copyout_zero([[B]] : !fir.ref<!fir.array<10xf32>>) {
+!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<!fir.array<10xf32>>) create_zero([[A]] : !fir.ref<!fir.array<10xf32>>) {
+!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.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) {
+!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.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) {
+!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.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) {
+!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.box<!fir.ptr<f32>>>, !fir.ref<!fir.box<!fir.ptr<f32>>>) {
+!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<!fir.array<10xf32>>) private([[A]] : !fir.ref<!fir.array<10xf32>>) {
+!CHECK:        acc.loop private([[A]]: !fir.ref<!fir.array<10xf32>>) {
+!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<i32>
+!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<i32>
+!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
index 0000000000000..5bc19984fef50
--- /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<!fir.ptr<f32>> {bindc_name = "d", uniq_name = "{{.*}}Ed"}
+! CHECK: [[E:%.*]] = fir.alloca !fir.box<!fir.ptr<f32>> {bindc_name = "e", uniq_name = "{{.*}}Ee"}
+! CHECK: [[IFCONDITION:%.*]] = fir.address_of(@{{.*}}ifcondition) : !fir.ref<!fir.logical<4>>
+
+  !$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<i32>
+! 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<i32>
+! CHECK:      [[WAIT5:%.*]] = fir.load %{{.*}} : !fir.ref<i32>
+! 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<!fir.logical<4>>
+! 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<!fir.logical<4>>) -> 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.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>) {
+! 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.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>) {
+! CHECK:        acc.yield
+! CHECK-NEXT: }{{$}}
+
+  !$acc serial copyin(a) copyin(readonly: b, c)
+  !$acc end serial
+
+! CHECK:      acc.serial copyin([[A]] : !fir.ref<!fir.array<10x10xf32>>) copyin_readonly([[B]], [[C]] : !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>) {
+! 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.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>) copyout_zero([[B]] : !fir.ref<!fir.array<10x10xf32>>) {
+! 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.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>) create_zero([[C]] : !fir.ref<!fir.array<10x10xf32>>) {
+! 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<!fir.array<10x10xf32>>) no_create([[A]], [[B]] : !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>) {
+! CHECK:        acc.yield
+! CHECK-NEXT: }{{$}}
+
+  !$acc serial present(a, b, c)
+  !$acc end serial
+
+! CHECK:      acc.serial present([[A]], [[B]], [[C]] : !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>) {
+! CHECK:        acc.yield
+! CHECK-NEXT: }{{$}}
+
+  !$acc serial deviceptr(a) deviceptr(c)
+  !$acc end serial
+
+! CHECK:      acc.serial deviceptr([[A]], [[C]] : !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>) {
+! CHECK:        acc.yield
+! CHECK-NEXT: }{{$}}
+
+  !$acc serial attach(d, e)
+  !$acc end serial
+
+! CHECK:      acc.serial attach([[D]], [[E]] : !fir.ref<!fir.box<!fir.ptr<f32>>>, !fir.ref<!fir.box<!fir.ptr<f32>>>) {
+! CHECK:        acc.yield
+! CHECK-NEXT: }{{$}}
+
+  !$acc serial private(a) firstprivate(b) private(c)
+  !$acc end serial
+
+! CHECK:      acc.serial firstprivate([[B]] : !fir.ref<!fir.array<10x10xf32>>) private([[A]], [[C]] : !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>) {
+! CHECK:        acc.yield
+! CHECK-NEXT: }{{$}}
+
+end subroutine


        


More information about the flang-commits mailing list