[flang-commits] [flang] 6fb01a9 - [flang][OpenMP] Add semantic checks for ordered construct
via flang-commits
flang-commits at lists.llvm.org
Fri Sep 17 06:54:08 PDT 2021
Author: PeixinQiao
Date: 2021-09-17T21:53:07+08:00
New Revision: 6fb01a94708ffcd0aed63d0697d4ca08ed937dff
URL: https://github.com/llvm/llvm-project/commit/6fb01a94708ffcd0aed63d0697d4ca08ed937dff
DIFF: https://github.com/llvm/llvm-project/commit/6fb01a94708ffcd0aed63d0697d4ca08ed937dff.diff
LOG: [flang][OpenMP] Add semantic checks for ordered construct
This patch implements the following semantic checks according to
OpenMP Version 5.1 Ordered construct restriction:
```
At most one threads clause can appear on an ordered construct; At most
one simd clause can appear on an ordered construct; At most one
depend(source) clause can appear on an ordered construct; Either
depend(sink:vec) clauses or depend(source) clauses may appear on an
ordered construct, but not both.
```
This patch also implements the following semantic checks according to
the syntax and descriptions in OpenMP Version 5.1 Ordered construct:
```
The dependence types of sink or source are only allowed on an ordered
construct. The depend(*) clauses are not allowed when ordered construct
is a block construct with an ordered region. The threads or simd clauses
are not allowed when the ordered construct is a standalone construct
with no ordered region.
```
Co-authored-by: Sameeran Joshi <sameeranjayant.joshi at amd.com>
Reviewed By: kiranchandramohan
Differential Revision: https://reviews.llvm.org/D108512
Added:
flang/test/Semantics/omp-ordered01.f90
Modified:
flang/lib/Semantics/check-omp-structure.cpp
flang/lib/Semantics/check-omp-structure.h
flang/lib/Semantics/resolve-directives.cpp
flang/test/Semantics/omp-clause-validity01.f90
llvm/include/llvm/Frontend/OpenMP/OMP.td
Removed:
################################################################################
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index bf166463997c1..3b58f97b2dba2 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -771,6 +771,25 @@ void OmpStructureChecker::Leave(const parser::OpenMPBlockConstruct &) {
dirContext_.pop_back();
}
+void OmpStructureChecker::ChecksOnOrderedAsBlock() {
+ if (FindClause(llvm::omp::Clause::OMPC_depend)) {
+ context_.Say(GetContext().clauseSource,
+ "DEPEND(*) clauses are not allowed when ORDERED construct is a block"
+ " construct with an ORDERED region"_err_en_US);
+ }
+}
+
+void OmpStructureChecker::Leave(const parser::OmpBeginBlockDirective &) {
+ switch (GetContext().directive) {
+ case llvm::omp::Directive::OMPD_ordered:
+ // [5.1] 2.19.9 Ordered Construct Restriction
+ ChecksOnOrderedAsBlock();
+ break;
+ default:
+ break;
+ }
+}
+
void OmpStructureChecker::Enter(const parser::OpenMPSectionsConstruct &x) {
const auto &beginSectionsDir{
std::get<parser::OmpBeginSectionsDirective>(x.t)};
@@ -911,6 +930,48 @@ void OmpStructureChecker::CheckBarrierNesting(
}
}
+void OmpStructureChecker::ChecksOnOrderedAsStandalone() {
+ if (FindClause(llvm::omp::Clause::OMPC_threads) ||
+ FindClause(llvm::omp::Clause::OMPC_simd)) {
+ context_.Say(GetContext().clauseSource,
+ "THREADS, SIMD clauses are not allowed when ORDERED construct is a "
+ "standalone construct with no ORDERED region"_err_en_US);
+ }
+
+ bool isSinkPresent{false};
+ int dependSourceCount{0};
+ auto clauseAll = FindClauses(llvm::omp::Clause::OMPC_depend);
+ for (auto itr = clauseAll.first; itr != clauseAll.second; ++itr) {
+ const auto &dependClause{
+ std::get<parser::OmpClause::Depend>(itr->second->u)};
+ if (std::get_if<parser::OmpDependClause::Source>(&dependClause.v.u)) {
+ dependSourceCount++;
+ if (isSinkPresent) {
+ context_.Say(itr->second->source,
+ "DEPEND(SOURCE) is not allowed when DEPEND(SINK: vec) is present "
+ "on ORDERED directive"_err_en_US);
+ }
+ if (dependSourceCount > 1) {
+ context_.Say(itr->second->source,
+ "At most one DEPEND(SOURCE) clause can appear on the ORDERED "
+ "directive"_err_en_US);
+ }
+ } else if (std::get_if<parser::OmpDependClause::Sink>(&dependClause.v.u)) {
+ isSinkPresent = true;
+ if (dependSourceCount > 0) {
+ context_.Say(itr->second->source,
+ "DEPEND(SINK: vec) is not allowed when DEPEND(SOURCE) is present "
+ "on ORDERED directive"_err_en_US);
+ }
+ } else {
+ context_.Say(itr->second->source,
+ "Only DEPEND(SOURCE) or DEPEND(SINK: vec) are allowed when ORDERED "
+ "construct is a standalone construct with no ORDERED "
+ "region"_err_en_US);
+ }
+ }
+}
+
void OmpStructureChecker::Enter(
const parser::OpenMPSimpleStandaloneConstruct &x) {
const auto &dir{std::get<parser::OmpSimpleStandaloneDirective>(x.t)};
@@ -920,6 +981,14 @@ void OmpStructureChecker::Enter(
void OmpStructureChecker::Leave(
const parser::OpenMPSimpleStandaloneConstruct &) {
+ switch (GetContext().directive) {
+ case llvm::omp::Directive::OMPD_ordered:
+ // [5.1] 2.19.9 Ordered Construct Restriction
+ ChecksOnOrderedAsStandalone();
+ break;
+ default:
+ break;
+ }
dirContext_.pop_back();
}
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index a610a531f8c9b..d82bf0032a243 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -135,6 +135,7 @@ class OmpStructureChecker
void Enter(const parser::OpenMPBlockConstruct &);
void Leave(const parser::OpenMPBlockConstruct &);
+ void Leave(const parser::OmpBeginBlockDirective &);
void Enter(const parser::OmpEndBlockDirective &);
void Leave(const parser::OmpEndBlockDirective &);
@@ -238,7 +239,9 @@ class OmpStructureChecker
const parser::DefinedOperator::IntrinsicOperator &);
void CheckReductionTypeList(const parser::OmpClause::Reduction &);
void CheckMasterNesting(const parser::OpenMPBlockConstruct &x);
+ void ChecksOnOrderedAsBlock();
void CheckBarrierNesting(const parser::OpenMPSimpleStandaloneConstruct &x);
+ void ChecksOnOrderedAsStandalone();
void CheckReductionArraySection(const parser::OmpObjectList &ompObjectList);
void CheckIntentInPointerAndDefinable(
const parser::OmpObjectList &, const llvm::omp::Clause);
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 120f4db423e4b..6df35af6e78c2 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -298,6 +298,9 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
GetContext().withinConstruct = true;
}
+ bool Pre(const parser::OpenMPSimpleStandaloneConstruct &);
+ void Post(const parser::OpenMPSimpleStandaloneConstruct &) { PopContext(); }
+
bool Pre(const parser::OpenMPLoopConstruct &);
void Post(const parser::OpenMPLoopConstruct &) { PopContext(); }
void Post(const parser::OmpBeginLoopDirective &) {
@@ -414,6 +417,18 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
return false;
}
+ bool Pre(const parser::OmpDependClause &x) {
+ if (const auto *dependSink{
+ std::get_if<parser::OmpDependClause::Sink>(&x.u)}) {
+ const auto &dependSinkVec{dependSink->v};
+ for (const auto &dependSinkElement : dependSinkVec) {
+ const auto &name{std::get<parser::Name>(dependSinkElement.t)};
+ ResolveName(&name);
+ }
+ }
+ return false;
+ }
+
void Post(const parser::Name &);
// Keep track of labels in the statements that causes jumps to target labels
@@ -1132,6 +1147,27 @@ void OmpAttributeVisitor::Post(const parser::OpenMPBlockConstruct &x) {
PopContext();
}
+bool OmpAttributeVisitor::Pre(
+ const parser::OpenMPSimpleStandaloneConstruct &x) {
+ const auto &standaloneDir{
+ std::get<parser::OmpSimpleStandaloneDirective>(x.t)};
+ switch (standaloneDir.v) {
+ case llvm::omp::Directive::OMPD_barrier:
+ case llvm::omp::Directive::OMPD_ordered:
+ case llvm::omp::Directive::OMPD_target_enter_data:
+ case llvm::omp::Directive::OMPD_target_exit_data:
+ case llvm::omp::Directive::OMPD_target_update:
+ case llvm::omp::Directive::OMPD_taskwait:
+ case llvm::omp::Directive::OMPD_taskyield:
+ PushContext(standaloneDir.source, standaloneDir.v);
+ break;
+ default:
+ break;
+ }
+ ClearDataSharingAttributeObjects();
+ return true;
+}
+
bool OmpAttributeVisitor::Pre(const parser::OpenMPLoopConstruct &x) {
const auto &beginLoopDir{std::get<parser::OmpBeginLoopDirective>(x.t)};
const auto &beginDir{std::get<parser::OmpLoopDirective>(beginLoopDir.t)};
diff --git a/flang/test/Semantics/omp-clause-validity01.f90 b/flang/test/Semantics/omp-clause-validity01.f90
index f6150a2901b2b..a4712a27c4400 100644
--- a/flang/test/Semantics/omp-clause-validity01.f90
+++ b/flang/test/Semantics/omp-clause-validity01.f90
@@ -480,8 +480,6 @@
! !$omp target enter data map(to:arrayA) map(alloc:arrayB)
! !$omp target update from(arrayA) to(arrayB)
! !$omp target exit data map(from:arrayA) map(delete:arrayB)
- !$omp ordered depend(source)
- ! !$omp ordered depend(sink:i-1)
!$omp flush (c)
!$omp flush acq_rel
!$omp flush release
diff --git a/flang/test/Semantics/omp-ordered01.f90 b/flang/test/Semantics/omp-ordered01.f90
new file mode 100644
index 0000000000000..948ad41de1a76
--- /dev/null
+++ b/flang/test/Semantics/omp-ordered01.f90
@@ -0,0 +1,80 @@
+! RUN: %python %S/test_errors.py %s %flang -fopenmp
+! OpenMP Version 5.1
+! Check OpenMP construct validity for the following directives:
+! 2.19.9 Ordered Construct
+
+program main
+ integer :: i, N = 10
+ real :: a, arrayA(10), arrayB(10), arrayC(10)
+ real, external :: foo, bar, baz
+
+ !$omp do ordered
+ do i = 1, N
+ !ERROR: At most one THREADS clause can appear on the ORDERED directive
+ !$omp ordered threads threads
+ arrayA(i) = i
+ !$omp end ordered
+ end do
+ !$omp end do
+
+ !$omp simd
+ do i = 1, N
+ !ERROR: At most one SIMD clause can appear on the ORDERED directive
+ !$omp ordered simd simd
+ arrayA(i) = i
+ !$omp end ordered
+ end do
+ !$omp end simd
+
+ !$omp do simd ordered
+ do i = 1, N
+ !ERROR: At most one SIMD clause can appear on the ORDERED directive
+ !$omp ordered simd simd
+ arrayA(i) = i
+ !$omp end ordered
+ end do
+ !$omp end do simd
+
+ !$omp do ordered(1)
+ do i = 2, N
+ !ERROR: Only DEPEND(SOURCE) or DEPEND(SINK: vec) are allowed when ORDERED construct is a standalone construct with no ORDERED region
+ !ERROR: At most one DEPEND(SOURCE) clause can appear on the ORDERED directive
+ !$omp ordered depend(source) depend(inout: arrayA) depend(source)
+ arrayA(i) = foo(i)
+ !ERROR: DEPEND(SOURCE) is not allowed when DEPEND(SINK: vec) is present on ORDERED directive
+ !ERROR: DEPEND(SOURCE) is not allowed when DEPEND(SINK: vec) is present on ORDERED directive
+ !ERROR: At most one DEPEND(SOURCE) clause can appear on the ORDERED directive
+ !$omp ordered depend(sink: i - 1) depend(source) depend(source)
+ arrayB(i) = bar(arrayA(i), arrayB(i-1))
+ !ERROR: Only DEPEND(SOURCE) or DEPEND(SINK: vec) are allowed when ORDERED construct is a standalone construct with no ORDERED region
+ !ERROR: Only DEPEND(SOURCE) or DEPEND(SINK: vec) are allowed when ORDERED construct is a standalone construct with no ORDERED region
+ !$omp ordered depend(out: arrayC) depend(in: arrayB)
+ arrayC(i) = baz(arrayB(i-1))
+ end do
+ !$omp end do
+
+ !$omp do ordered(1)
+ do i = 2, N
+ !ERROR: DEPEND(*) clauses are not allowed when ORDERED construct is a block construct with an ORDERED region
+ !$omp ordered depend(source)
+ arrayA(i) = foo(i)
+ !$omp end ordered
+ !ERROR: DEPEND(*) clauses are not allowed when ORDERED construct is a block construct with an ORDERED region
+ !$omp ordered depend(sink: i - 1)
+ arrayB(i) = bar(arrayA(i), arrayB(i-1))
+ !$omp end ordered
+ end do
+ !$omp end do
+
+contains
+ subroutine work1()
+ !ERROR: THREADS, SIMD clauses are not allowed when ORDERED construct is a standalone construct with no ORDERED region
+ !$omp ordered simd
+ end subroutine work1
+
+ subroutine work2()
+ !ERROR: THREADS, SIMD clauses are not allowed when ORDERED construct is a standalone construct with no ORDERED region
+ !$omp ordered threads
+ end subroutine work2
+
+end program main
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index 5ed279c2d1526..010a35b60c52e 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -491,10 +491,12 @@ def OMP_Flush : Directive<"flush"> {
}
def OMP_Ordered : Directive<"ordered"> {
let allowedClauses = [
- VersionedClause<OMPC_Threads>,
- VersionedClause<OMPC_Simd>,
VersionedClause<OMPC_Depend>
];
+ let allowedOnceClauses = [
+ VersionedClause<OMPC_Threads>,
+ VersionedClause<OMPC_Simd>
+ ];
}
def OMP_Atomic : Directive<"atomic"> {
let allowedClauses = [
More information about the flang-commits
mailing list