[flang-commits] [flang] 42f5110 - [flang][OpenMP] Add semantic check for teams nesting
Arnamoy Bhattacharyya via flang-commits
flang-commits at lists.llvm.org
Fri Aug 13 07:41:47 PDT 2021
Author: Peixin Qiao
Date: 2021-08-13T10:42:47-04:00
New Revision: 42f51107016ca869dc8d408c827bf61c2efcbc99
URL: https://github.com/llvm/llvm-project/commit/42f51107016ca869dc8d408c827bf61c2efcbc99
DIFF: https://github.com/llvm/llvm-project/commit/42f51107016ca869dc8d408c827bf61c2efcbc99.diff
LOG: [flang][OpenMP] Add semantic check for teams nesting
This patch implements the following check for TEAMS construct:
```
OpenMP Version 5.0 Teams construct restriction: A teams region can
only be strictly nested within the implicit parallel region or a target
region. If a teams construct is nested within a target construct, that
target construct must contain no statements, declarations or directives
outside of the teams construct.
```
Also add one test case for the check.
Reviewed By: kiranchandramohan, clementval
Differential Revision: https://reviews.llvm.org/D106335
Added:
flang/test/Semantics/omp-nested-teams.f90
Modified:
flang/lib/Semantics/check-directive-structure.h
flang/lib/Semantics/check-omp-structure.cpp
flang/lib/Semantics/check-omp-structure.h
flang/test/Semantics/omp-firstprivate01.f90
flang/test/Semantics/omp-nested-master.f90
flang/test/Semantics/omp-nested-simd.f90
Removed:
################################################################################
diff --git a/flang/lib/Semantics/check-directive-structure.h b/flang/lib/Semantics/check-directive-structure.h
index 05b1a94a2d76..6ef60230cca5 100644
--- a/flang/lib/Semantics/check-directive-structure.h
+++ b/flang/lib/Semantics/check-directive-structure.h
@@ -203,12 +203,6 @@ class DirectiveStructureChecker : public virtual BaseChecker {
GetContext().actualClauses.push_back(type);
}
- void EnterSIMDNest() { simdNest_++; }
-
- void ExitSIMDNest() { simdNest_--; }
-
- int GetSIMDNest() { return simdNest_; }
-
// Check if the given clause is present in the current context
const PC *FindClause(C type) {
auto it{GetContext().clauseInfo.find(type)};
@@ -320,7 +314,6 @@ class DirectiveStructureChecker : public virtual BaseChecker {
directiveClausesMap_;
std::string ClauseSetToString(const common::EnumSet<C, ClauseEnumSize> set);
- int simdNest_{0};
};
template <typename D, typename C, typename PC, std::size_t ClauseEnumSize>
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 34499e6d5f97..a5eefe2b3450 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -285,7 +285,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPConstruct &x) {
// called individually for each construct. Therefore a
// dirContext_ size `1` means the current construct is nested
if (dirContext_.size() >= 1) {
- if (GetSIMDNest() > 0) {
+ if (GetDirectiveNest(SIMDNest) > 0) {
CheckSIMDNest(x);
}
}
@@ -306,7 +306,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) {
PushContextAndClauseSets(beginDir.source, beginDir.v);
if (llvm::omp::simdSet.test(GetContext().directive)) {
- EnterSIMDNest();
+ EnterDirectiveNest(SIMDNest);
}
if (beginDir.v == llvm::omp::Directive::OMPD_do) {
@@ -585,7 +585,7 @@ void OmpStructureChecker::CheckDistLinear(
void OmpStructureChecker::Leave(const parser::OpenMPLoopConstruct &) {
if (llvm::omp::simdSet.test(GetContext().directive)) {
- ExitSIMDNest();
+ ExitDirectiveNest(SIMDNest);
}
dirContext_.pop_back();
}
@@ -625,11 +625,35 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) {
if (GetContext().directive == llvm::omp::Directive::OMPD_master) {
CheckMasterNesting(x);
}
+ // A teams region can only be strictly nested within the implicit parallel
+ // region or a target region.
+ if (GetContext().directive == llvm::omp::Directive::OMPD_teams &&
+ GetContextParent().directive != llvm::omp::Directive::OMPD_target) {
+ context_.Say(parser::FindSourceLocation(x),
+ "%s region can only be strictly nested within the implicit parallel "
+ "region or TARGET region"_err_en_US,
+ ContextDirectiveAsFortran());
+ }
+ // If a teams construct is nested within a target construct, that target
+ // construct must contain no statements, declarations or directives outside
+ // of the teams construct.
+ if (GetContext().directive == llvm::omp::Directive::OMPD_teams &&
+ GetContextParent().directive == llvm::omp::Directive::OMPD_target &&
+ !GetDirectiveNest(TargetBlockOnlyTeams)) {
+ context_.Say(GetContextParent().directiveSource,
+ "TARGET construct with nested TEAMS region contains statements or "
+ "directives outside of the TEAMS construct"_err_en_US);
+ }
}
CheckNoBranching(block, beginDir.v, beginDir.source);
switch (beginDir.v) {
+ case llvm::omp::Directive::OMPD_target:
+ if (CheckTargetBlockOnlyTeams(block)) {
+ EnterDirectiveNest(TargetBlockOnlyTeams);
+ }
+ break;
case llvm::omp::OMPD_workshare:
case llvm::omp::OMPD_parallel_workshare:
CheckWorkshareBlockStmts(block, beginDir.source);
@@ -683,6 +707,9 @@ void OmpStructureChecker::CheckIfDoOrderedClause(
}
void OmpStructureChecker::Leave(const parser::OpenMPBlockConstruct &) {
+ if (GetDirectiveNest(TargetBlockOnlyTeams)) {
+ ExitDirectiveNest(TargetBlockOnlyTeams);
+ }
dirContext_.pop_back();
}
@@ -1921,6 +1948,30 @@ void OmpStructureChecker::CheckPrivateSymbolsInOuterCxt(
}
}
+bool OmpStructureChecker::CheckTargetBlockOnlyTeams(
+ const parser::Block &block) {
+ bool nestedTeams{false};
+ auto it{block.begin()};
+
+ if (const auto *ompConstruct{parser::Unwrap<parser::OpenMPConstruct>(*it)}) {
+ if (const auto *ompBlockConstruct{
+ std::get_if<parser::OpenMPBlockConstruct>(&ompConstruct->u)}) {
+ const auto &beginBlockDir{
+ std::get<parser::OmpBeginBlockDirective>(ompBlockConstruct->t)};
+ const auto &beginDir{
+ std::get<parser::OmpBlockDirective>(beginBlockDir.t)};
+ if (beginDir.v == llvm::omp::Directive::OMPD_teams) {
+ nestedTeams = true;
+ }
+ }
+ }
+
+ if (nestedTeams && ++it == block.end()) {
+ return true;
+ }
+ return false;
+}
+
void OmpStructureChecker::CheckWorkshareBlockStmts(
const parser::Block &block, parser::CharBlock source) {
OmpWorkshareBlockChecker ompWorkshareBlockChecker{context_, source};
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 2eebb8f70508..03cd1f8d3f29 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -218,6 +218,7 @@ class OmpStructureChecker
void SetLoopInfo(const parser::OpenMPLoopConstruct &x);
void CheckIsLoopIvPartOfClause(
llvmOmpClause clause, const parser::OmpObjectList &ompObjectList);
+ bool CheckTargetBlockOnlyTeams(const parser::Block &);
void CheckWorkshareBlockStmts(const parser::Block &, parser::CharBlock);
void CheckLoopItrVariableIsInt(const parser::OpenMPLoopConstruct &x);
@@ -248,6 +249,12 @@ class OmpStructureChecker
void CheckPredefinedAllocatorRestriction(
const parser::CharBlock &source, const parser::Name &name);
bool isPredefinedAllocator{false};
+ void EnterDirectiveNest(const int index) { directiveNest_[index]++; }
+ void ExitDirectiveNest(const int index) { directiveNest_[index]--; }
+ int GetDirectiveNest(const int index) { return directiveNest_[index]; }
+
+ enum directiveNestType { SIMDNest, TargetBlockOnlyTeams, LastType };
+ int directiveNest_[LastType + 1] = {0};
};
} // namespace Fortran::semantics
#endif // FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_
diff --git a/flang/test/Semantics/omp-firstprivate01.f90 b/flang/test/Semantics/omp-firstprivate01.f90
index d03cfc253c22..c461cefb54a5 100644
--- a/flang/test/Semantics/omp-firstprivate01.f90
+++ b/flang/test/Semantics/omp-firstprivate01.f90
@@ -12,6 +12,7 @@ program omp_firstprivate
a = 10
b = 20
+ !ERROR: TARGET construct with nested TEAMS region contains statements or directives outside of the TEAMS construct
!$omp target
!$omp teams private(a, b)
!ERROR: FIRSTPRIVATE variable 'a' is PRIVATE in outer context
diff --git a/flang/test/Semantics/omp-nested-master.f90 b/flang/test/Semantics/omp-nested-master.f90
index cb391d568ba2..9debac680fc1 100644
--- a/flang/test/Semantics/omp-nested-master.f90
+++ b/flang/test/Semantics/omp-nested-master.f90
@@ -87,6 +87,7 @@ program omp_nest_master
!$omp ordered
do i = 1, 10
+ !ERROR: TEAMS region can only be strictly nested within the implicit parallel region or TARGET region
!$omp teams
!$omp distribute
do k =1, 10
@@ -102,6 +103,7 @@ program omp_nest_master
!$omp critical
do i = 1, 10
+ !ERROR: TEAMS region can only be strictly nested within the implicit parallel region or TARGET region
!$omp teams
!$omp distribute
do k =1, 10
@@ -117,6 +119,7 @@ program omp_nest_master
!$omp taskloop
do i = 1, 10
+ !ERROR: TEAMS region can only be strictly nested within the implicit parallel region or TARGET region
!$omp teams
!$omp distribute
do k =1, 10
@@ -133,6 +136,7 @@ program omp_nest_master
!$omp task
do i = 1, 10
+ !ERROR: TEAMS region can only be strictly nested within the implicit parallel region or TARGET region
!$omp teams
!$omp distribute
do k =1, 10
diff --git a/flang/test/Semantics/omp-nested-simd.f90 b/flang/test/Semantics/omp-nested-simd.f90
index 1b5bb9c5ccee..bb1a219771a4 100644
--- a/flang/test/Semantics/omp-nested-simd.f90
+++ b/flang/test/Semantics/omp-nested-simd.f90
@@ -42,6 +42,7 @@ SUBROUTINE NESTED_BAD(N)
DO J = 1,N
print *, "Hi"
!ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause.
+ !ERROR: TEAMS region can only be strictly nested within the implicit parallel region or TARGET region
!$omp teams
DO K = 1,N
print *, 'Hello'
@@ -65,12 +66,6 @@ SUBROUTINE NESTED_BAD(N)
end do
!$omp end task
!ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause.
- !$omp teams
- do J = 1, N
- K = 2
- end do
- !$omp end teams
- !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause.
!$omp target
do J = 1, N
K = 2
@@ -104,12 +99,6 @@ SUBROUTINE NESTED_BAD(N)
end do
!$omp end task
!ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause.
- !$omp teams
- do J = 1, N
- K = 2
- end do
- !$omp end teams
- !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause.
!$omp target
do J = 1, N
K = 2
@@ -144,12 +133,6 @@ SUBROUTINE NESTED_BAD(N)
end do
!$omp end task
!ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause.
- !$omp teams
- do J = 1, N
- K = 2
- end do
- !$omp end teams
- !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause.
!$omp target
do J = 1, N
K = 2
@@ -184,12 +167,6 @@ SUBROUTINE NESTED_BAD(N)
end do
!$omp end task
!ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause.
- !$omp teams
- do J = 1, N
- K = 2
- end do
- !$omp end teams
- !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause.
!$omp target
do J = 1, N
K = 2
diff --git a/flang/test/Semantics/omp-nested-teams.f90 b/flang/test/Semantics/omp-nested-teams.f90
new file mode 100644
index 000000000000..4a773b3b9454
--- /dev/null
+++ b/flang/test/Semantics/omp-nested-teams.f90
@@ -0,0 +1,113 @@
+! RUN: %S/test_errors.sh %s %t %flang -fopenmp
+! REQUIRES: shell
+
+! OpenMP Version 5.0
+! Check OpenMP construct validity for the following directives:
+! 2.7 Teams Construct
+
+program main
+ integer :: i, j, N = 10
+ real :: a, b, c
+
+ !$omp teams
+ a = 3.14
+ !$omp end teams
+
+ !$omp target
+ !$omp teams
+ a = 3.14
+ !$omp end teams
+ !$omp end target
+
+ !$omp target
+ !$omp parallel
+ !ERROR: TEAMS region can only be strictly nested within the implicit parallel region or TARGET region
+ !$omp teams
+ a = 3.14
+ !$omp end teams
+ !$omp end parallel
+ !$omp end target
+
+ !$omp parallel
+ !ERROR: TEAMS region can only be strictly nested within the implicit parallel region or TARGET region
+ !$omp teams
+ a = 3.14
+ !$omp end teams
+ !$omp end parallel
+
+ !$omp do
+ do i = 1, N
+ !ERROR: TEAMS region can only be strictly nested within the implicit parallel region or TARGET region
+ !$omp teams
+ a = 3.14
+ !$omp end teams
+ end do
+
+ !$omp master
+ !ERROR: TEAMS region can only be strictly nested within the implicit parallel region or TARGET region
+ !$omp teams
+ a = 3.14
+ !$omp end teams
+ !$omp end master
+
+ !$omp target parallel
+ !ERROR: TEAMS region can only be strictly nested within the implicit parallel region or TARGET region
+ !$omp teams
+ a = 3.14
+ !$omp end teams
+ !$omp end target parallel
+
+ !$omp target
+ !$omp teams
+ !ERROR: Only `DISTRIBUTE` or `PARALLEL` regions are allowed to be strictly nested inside `TEAMS` region.
+ !ERROR: TEAMS region can only be strictly nested within the implicit parallel region or TARGET region
+ !$omp teams
+ a = 3.14
+ !$omp end teams
+ !$omp end teams
+ !$omp end target
+
+ !$omp target teams
+ !ERROR: TEAMS region can only be strictly nested within the implicit parallel region or TARGET region
+ !$omp teams
+ a = 3.14
+ !$omp end teams
+ !$omp end target teams
+
+ !ERROR: TARGET construct with nested TEAMS region contains statements or directives outside of the TEAMS construct
+ !$omp target
+ do i = 1, N
+ !$omp teams
+ a = 3.14
+ !$omp end teams
+ enddo
+ !$omp end target
+
+ !ERROR: TARGET construct with nested TEAMS region contains statements or directives outside of the TEAMS construct
+ !$omp target
+ if (i .GT. 1) then
+ if (j .GT. 1) then
+ !$omp teams
+ a = 3.14
+ !$omp end teams
+ end if
+ end if
+ !$omp end target
+
+ !ERROR: TARGET construct with nested TEAMS region contains statements or directives outside of the TEAMS construct
+ !$omp target
+ b = 3.14
+ !$omp teams
+ a = 3.14
+ !$omp end teams
+ !$omp end target
+
+ !ERROR: TARGET construct with nested TEAMS region contains statements or directives outside of the TEAMS construct
+ !$omp target
+ !$omp teams
+ a = 3.14
+ !$omp end teams
+ c = 3.14
+ !$omp end target
+
+end program main
More information about the flang-commits
mailing list