Skip to content

Commit

Permalink
[flang][OpenMP] Add parser support for order clause
Browse files Browse the repository at this point in the history
Added parser support for OpenMP 5.0 & 5.1 feature
ORDER([order-modifier :]concurrent) clause for all
applicable and supported OpenMP directives.

Reviewed By: kiranchandramohan, abidmalikwaterloo

Differential Revision: https://reviews.llvm.org/D142524
  • Loading branch information
kavitha-natarajan committed Feb 21, 2023
1 parent c9fd858 commit a7d352c
Show file tree
Hide file tree
Showing 8 changed files with 384 additions and 28 deletions.
4 changes: 4 additions & 0 deletions flang/include/flang/Parser/dump-parse-tree.h
Expand Up @@ -514,6 +514,10 @@ class ParseTreeDumper {
}
NODE(parser, OmpObject)
NODE(parser, OmpObjectList)
NODE(parser, OmpOrderClause)
NODE_ENUM(OmpOrderClause, Type)
NODE(parser, OmpOrderModifier)
NODE_ENUM(OmpOrderModifier, Kind)
NODE(parser, OmpProcBindClause)
NODE_ENUM(OmpProcBindClause, Type)
NODE(parser, OmpReductionClause)
Expand Down
13 changes: 13 additions & 0 deletions flang/include/flang/Parser/parse-tree.h
Expand Up @@ -3417,6 +3417,19 @@ struct OmpAlignedClause {
std::tuple<std::list<Name>, std::optional<ScalarIntConstantExpr>> t;
};

// 2.9.5 order-clause -> ORDER ([order-modifier :]concurrent)
struct OmpOrderModifier {
UNION_CLASS_BOILERPLATE(OmpOrderModifier);
ENUM_CLASS(Kind, Reproducible, Unconstrained)
std::variant<Kind> u;
};

struct OmpOrderClause {
TUPLE_CLASS_BOILERPLATE(OmpOrderClause);
ENUM_CLASS(Type, Concurrent)
std::tuple<std::optional<OmpOrderModifier>, Type> t;
};

// 2.15.3.7 linear-modifier -> REF | VAL | UVAL
struct OmpLinearModifier {
ENUM_CLASS(Type, Ref, Val, Uval)
Expand Down
12 changes: 12 additions & 0 deletions flang/lib/Parser/openmp-parsers.cpp
Expand Up @@ -185,6 +185,16 @@ TYPE_CONTEXT_PARSER("Omp LINEAR clause"_en_US,
TYPE_PARSER(construct<OmpAlignedClause>(
nonemptyList(name), maybe(":" >> scalarIntConstantExpr)))

// 2.9.5 ORDER ([order-modifier :]concurrent)
TYPE_PARSER(construct<OmpOrderModifier>(
"REPRODUCIBLE" >> pure(OmpOrderModifier::Kind::Reproducible)) ||
construct<OmpOrderModifier>(
"UNCONSTRAINED" >> pure(OmpOrderModifier::Kind::Unconstrained)))

TYPE_PARSER(construct<OmpOrderClause>(
maybe(Parser<OmpOrderModifier>{} / ":"),
"CONCURRENT" >> pure(OmpOrderClause::Type::Concurrent)))

TYPE_PARSER(
construct<OmpObject>(designator) || construct<OmpObject>("/" >> name / "/"))

Expand Down Expand Up @@ -258,6 +268,8 @@ TYPE_PARSER(
parenthesized(scalarIntExpr))) ||
"NUM_THREADS" >> construct<OmpClause>(construct<OmpClause::NumThreads>(
parenthesized(scalarIntExpr))) ||
"ORDER" >> construct<OmpClause>(construct<OmpClause::Order>(
parenthesized(Parser<OmpOrderClause>{}))) ||
"ORDERED" >> construct<OmpClause>(construct<OmpClause::Ordered>(
maybe(parenthesized(scalarIntConstantExpr)))) ||
"PARTIAL" >> construct<OmpClause>(construct<OmpClause::Partial>(
Expand Down
6 changes: 6 additions & 0 deletions flang/lib/Parser/unparse.cpp
Expand Up @@ -2046,6 +2046,10 @@ class UnparseVisitor {
Put(":");
Walk(std::get<OmpObjectList>(x.t));
}
void Unparse(const OmpOrderClause &x) {
Walk(std::get<std::optional<OmpOrderModifier>>(x.t), ":");
Walk(std::get<OmpOrderClause::Type>(x.t));
}
void Unparse(const OmpDependSinkVecLength &x) {
Walk(std::get<DefinedOperator>(x.t));
Walk(std::get<ScalarIntConstantExpr>(x.t));
Expand Down Expand Up @@ -2619,6 +2623,8 @@ class UnparseVisitor {
WALK_NESTED_ENUM(OmpDeviceTypeClause, Type) // OMP DEVICE_TYPE
WALK_NESTED_ENUM(OmpIfClause, DirectiveNameModifier) // OMP directive-modifier
WALK_NESTED_ENUM(OmpCancelType, Type) // OMP cancel-type
WALK_NESTED_ENUM(OmpOrderClause, Type) // OMP order-type
WALK_NESTED_ENUM(OmpOrderModifier, Kind) // OMP order-modifier
#undef WALK_NESTED_ENUM

void Done() const { CHECK(indent_ == 0); }
Expand Down
53 changes: 53 additions & 0 deletions flang/test/Examples/omp-order-clause.f90
@@ -0,0 +1,53 @@
! REQUIRES: plugins, examples, shell

! RUN: %flang_fc1 -load %llvmshlibdir/flangOmpReport.so -plugin flang-omp-report -fopenmp %s -o - | FileCheck %s

! Check for ORDER([order-modifier :]concurrent) clause on OpenMP constructs

subroutine test_order()
integer :: i, j = 1
!$omp do order(concurrent)
do i=1,10
j = j + 1
end do
!$omp end do
end subroutine

!CHECK: - file: {{.*}}
!CHECK: line: 9
!CHECK: construct: do
!CHECK: clauses:
!CHECK: - clause: order
!CHECK: details: concurrent

subroutine test_order_reproducible()
integer :: i, j = 1
!$omp simd order(reproducible:concurrent)
do i=1,10
j = j + 1
end do
!$omp end simd
end subroutine

!CHECK: - file: {{.*}}
!CHECK: line: 25
!CHECK: construct: simd
!CHECK: clauses:
!CHECK: - clause: order
!CHECK: details: 'reproducible:concurrent'

subroutine test_order_unconstrained()
integer :: i, j = 1
!$omp target teams distribute parallel do simd order(unconstrained:concurrent)
do i=1,10
j = j + 1
end do
!$omp end target teams distribute parallel do simd
end subroutine

!CHECK: - file: {{.*}}
!CHECK: line: 41
!CHECK: construct: target teams distribute parallel do simd
!CHECK: clauses:
!CHECK: - clause: order
!CHECK: details: 'unconstrained:concurrent'
254 changes: 254 additions & 0 deletions flang/test/Parser/omp-order-clause01.f90
@@ -0,0 +1,254 @@
! RUN: %flang_fc1 -fdebug-unparse -fopenmp %s | FileCheck --ignore-case %s
! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s

! Check for ORDER([order-modifier :]concurrent) clause on OpenMP constructs

subroutine test_do_order()
integer :: i, j = 1
!CHECK: !$omp do order(concurrent)
!$omp do order(concurrent)
do i=1,10
j = j + 1
end do
!$omp end do
end subroutine

!PARSE-TREE: OpenMPConstruct -> OpenMPLoopConstruct
!PARSE-TREE-NEXT: OmpBeginLoopDirective
!PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = do
!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
!PARSE-TREE-NEXT: Type = Concurrent

subroutine test_simd_order_reproducible()
integer :: i, j = 1
!CHECK: !$omp simd order(reproducible:concurrent)
!$omp simd order(reproducible:concurrent)
do i=1,10
j = j + 1
end do
!$omp end simd
end subroutine

!PARSE-TREE: OpenMPConstruct -> OpenMPLoopConstruct
!PARSE-TREE-NEXT: OmpBeginLoopDirective
!PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = simd
!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
!PARSE-TREE-NEXT: Kind = Reproducible
!PARSE-TREE-NEXT: Type = Concurrent

subroutine test_do_simd_order_unconstrained()
integer :: i, j = 1
!CHECK: !$omp do simd order(unconstrained:concurrent)
!$omp do simd order(unconstrained:concurrent)
do i=1,10
j = j + 1
end do
!$omp end do simd
end subroutine

!PARSE-TREE: OpenMPConstruct -> OpenMPLoopConstruct
!PARSE-TREE-NEXT: OmpBeginLoopDirective
!PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = do simd
!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
!PARSE-TREE-NEXT: Kind = Unconstrained
!PARSE-TREE-NEXT: Type = Concurrent

subroutine test_parallel_do_order()
integer :: i, j = 1
!CHECK: !$omp parallel do order(concurrent)
!$omp parallel do order(concurrent)
do i=1,10
j = j + 1
end do
!$omp end parallel do
end subroutine

!PARSE-TREE: OpenMPConstruct -> OpenMPLoopConstruct
!PARSE-TREE-NEXT: OmpBeginLoopDirective
!PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = parallel do
!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
!PARSE-TREE-NEXT: Type = Concurrent

subroutine test_parallel_do_simd_order_reproducible()
integer :: i, j = 1
!CHECK: !$omp parallel do simd order(reproducible:concurrent)
!$omp parallel do simd order(reproducible:concurrent)
do i=1,10
j = j + 1
end do
!$omp end parallel do simd
end subroutine

!PARSE-TREE: OpenMPConstruct -> OpenMPLoopConstruct
!PARSE-TREE-NEXT: OmpBeginLoopDirective
!PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = parallel do simd
!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
!PARSE-TREE-NEXT: Kind = Reproducible
!PARSE-TREE-NEXT: Type = Concurrent

subroutine test_target_simd_order_unconstrained()
integer :: i, j = 1
!CHECK: !$omp target simd order(unconstrained:concurrent)
!$omp target simd order(unconstrained:concurrent)
do i=1,10
j = j + 1
end do
!$omp end target simd
end subroutine

!PARSE-TREE: OpenMPConstruct -> OpenMPLoopConstruct
!PARSE-TREE-NEXT: OmpBeginLoopDirective
!PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = target simd
!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
!PARSE-TREE-NEXT: Kind = Unconstrained
!PARSE-TREE-NEXT: Type = Concurrent

subroutine test_target_parallel_do_order()
integer :: i, j = 1
!CHECK: !$omp target parallel do order(concurrent)
!$omp target parallel do order(concurrent)
do i=1,10
j = j + 1
end do
!$omp end target parallel do
end subroutine

!PARSE-TREE: OpenMPConstruct -> OpenMPLoopConstruct
!PARSE-TREE-NEXT: OmpBeginLoopDirective
!PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = target parallel do
!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
!PARSE-TREE-NEXT: Type = Concurrent

subroutine test_target_parallel_do_simd_order_reproducible()
integer :: i, j = 1
!CHECK: !$omp target parallel do simd order(reproducible:concurrent)
!$omp target parallel do simd order(reproducible:concurrent)
do i=1,10
j = j + 1
end do
!$omp end target parallel do simd
end subroutine

!PARSE-TREE: OpenMPConstruct -> OpenMPLoopConstruct
!PARSE-TREE-NEXT: OmpBeginLoopDirective
!PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = target parallel do simd
!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
!PARSE-TREE-NEXT: Kind = Reproducible
!PARSE-TREE-NEXT: Type = Concurrent

subroutine test_teams_distribute_simd_order_unconstrained()
integer :: i, j = 1
!CHECK: !$omp teams distribute simd order(unconstrained:concurrent)
!$omp teams distribute simd order(unconstrained:concurrent)
do i=1,10
j = j + 1
end do
!$omp end teams distribute simd
end subroutine

!PARSE-TREE: OpenMPConstruct -> OpenMPLoopConstruct
!PARSE-TREE-NEXT: OmpBeginLoopDirective
!PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = teams distribute simd
!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
!PARSE-TREE-NEXT: Kind = Unconstrained
!PARSE-TREE-NEXT: Type = Concurrent

subroutine test_teams_distribute_parallel_do_order()
integer :: i, j = 1
!CHECK: !$omp teams distribute parallel do order(concurrent)
!$omp teams distribute parallel do order(concurrent)
do i=1,10
j = j + 1
end do
!$omp end teams distribute parallel do
end subroutine

!PARSE-TREE: OpenMPConstruct -> OpenMPLoopConstruct
!PARSE-TREE-NEXT: OmpBeginLoopDirective
!PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = teams distribute parallel do
!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
!PARSE-TREE-NEXT: Type = Concurrent

subroutine test_teams_distribute_parallel_do_simd_order_reproducible()
integer :: i, j = 1
!CHECK: !$omp teams distribute parallel do simd order(reproducible:concurrent)
!$omp teams distribute parallel do simd order(reproducible:concurrent)
do i=1,10
j = j + 1
end do
!$omp end teams distribute parallel do simd
end subroutine

!PARSE-TREE: OpenMPConstruct -> OpenMPLoopConstruct
!PARSE-TREE-NEXT: OmpBeginLoopDirective
!PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = teams distribute parallel do simd
!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
!PARSE-TREE-NEXT: Kind = Reproducible
!PARSE-TREE-NEXT: Type = Concurrent

subroutine test_target_teams_distribute_simd_order_unconstrained()
integer :: i, j = 1
!CHECK: !$omp target teams distribute simd order(unconstrained:concurrent)
!$omp target teams distribute simd order(unconstrained:concurrent)
do i=1,10
j = j + 1
end do
!$omp end target teams distribute simd
end subroutine

!PARSE-TREE: OpenMPConstruct -> OpenMPLoopConstruct
!PARSE-TREE-NEXT: OmpBeginLoopDirective
!PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = target teams distribute simd
!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
!PARSE-TREE-NEXT: Kind = Unconstrained
!PARSE-TREE-NEXT: Type = Concurrent

subroutine test_target_teams_distribute_parallel_do_order()
integer :: i, j = 1
!CHECK: !$omp target teams distribute parallel do order(concurrent)
!$omp target teams distribute parallel do order(concurrent)
do i=1,10
j = j + 1
end do
!$omp end target teams distribute parallel do
end subroutine

!PARSE-TREE: OpenMPConstruct -> OpenMPLoopConstruct
!PARSE-TREE-NEXT: OmpBeginLoopDirective
!PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = target teams distribute parallel do
!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
!PARSE-TREE-NEXT: Type = Concurrent

subroutine test_target_teams_distribute_parallel_do_simd_order_reproducible()
integer :: i, j = 1
!CHECK: !$omp target teams distribute parallel do simd order(reproducible:concurrent)
!$omp target teams distribute parallel do simd order(reproducible:concurrent)
do i=1,10
j = j + 1
end do
!$omp end target teams distribute parallel do simd
end subroutine

!PARSE-TREE: OpenMPConstruct -> OpenMPLoopConstruct
!PARSE-TREE-NEXT: OmpBeginLoopDirective
!PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = target teams distribute parallel do simd
!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
!PARSE-TREE-NEXT: Kind = Reproducible
!PARSE-TREE-NEXT: Type = Concurrent

subroutine test_taskloop_simd_order_unconstrained()
integer :: i, j = 1
!CHECK: !$omp taskloop simd order(unconstrained:concurrent)
!$omp taskloop simd order(unconstrained:concurrent)
do i=1,10
j = j + 1
end do
!$omp end taskloop simd
end subroutine

!PARSE-TREE: OpenMPConstruct -> OpenMPLoopConstruct
!PARSE-TREE-NEXT: OmpBeginLoopDirective
!PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = taskloop simd
!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
!PARSE-TREE-NEXT: Kind = Unconstrained
!PARSE-TREE-NEXT: Type = Concurrent
10 changes: 10 additions & 0 deletions flang/test/Semantics/OpenMP/omp-order-clause01.f90
@@ -0,0 +1,10 @@
! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp

subroutine omp_order()
integer :: i, j = 1
!ERROR: At most one ORDER clause can appear on the SIMD directive
!$omp simd order(concurrent) order(concurrent)
do i=1,10
j = j + 1
end do
end subroutine omp_order

0 comments on commit a7d352c

Please sign in to comment.