[flang-commits] [flang] a40b609 - [flang][OpenMP] Add semantic check for occurrence of constructs nested inside a SIMD region
Arnamoy Bhattacharyya via flang-commits
flang-commits at lists.llvm.org
Thu May 6 12:08:02 PDT 2021
Author: Arnamoy Bhattacharyya
Date: 2021-05-06T15:09:51-04:00
New Revision: a40b609958828960ce55a5e266c157491772a67e
URL: https://github.com/llvm/llvm-project/commit/a40b609958828960ce55a5e266c157491772a67e
DIFF: https://github.com/llvm/llvm-project/commit/a40b609958828960ce55a5e266c157491772a67e.diff
LOG: [flang][OpenMP] Add semantic check for occurrence of constructs nested inside a SIMD region
Reviewed By: kiranchandramohan
Differential Revision: https://reviews.llvm.org/D99757
Added:
flang/test/Semantics/omp-nested-simd.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-do05.f90
flang/test/Semantics/omp-ordered-simd.f90
Removed:
################################################################################
diff --git a/flang/lib/Semantics/check-directive-structure.h b/flang/lib/Semantics/check-directive-structure.h
index 6ef60230cca5..05b1a94a2d76 100644
--- a/flang/lib/Semantics/check-directive-structure.h
+++ b/flang/lib/Semantics/check-directive-structure.h
@@ -203,6 +203,12 @@ 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)};
@@ -314,6 +320,7 @@ 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 868c64651bc3..2903a4105961 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -238,7 +238,16 @@ void OmpStructureChecker::HasInvalidTeamsNesting(
}
void OmpStructureChecker::Enter(const parser::OpenMPConstruct &x) {
- // 2.8.1 TODO: Simd Construct with Ordered Construct Nesting check
+ // Simd Construct with Ordered Construct Nesting check
+ // We cannot use CurrentDirectiveIsNested() here because
+ // PushContextAndClauseSets() has not been called yet, it is
+ // called individually for each construct. Therefore a
+ // dirContext_ size `1` means the current construct is nested
+ if (dirContext_.size() >= 1) {
+ if (GetSIMDNest() > 0) {
+ CheckSIMDNest(x);
+ }
+ }
}
void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) {
@@ -255,6 +264,9 @@ void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) {
}
PushContextAndClauseSets(beginDir.source, beginDir.v);
+ if (llvm::omp::simdSet.test(GetContext().directive)) {
+ EnterSIMDNest();
+ }
if (beginDir.v == llvm::omp::Directive::OMPD_do) {
// 2.7.1 do-clause -> private-clause |
@@ -344,6 +356,78 @@ void OmpStructureChecker::CheckLoopItrVariableIsInt(
}
}
+void OmpStructureChecker::CheckSIMDNest(const parser::OpenMPConstruct &c) {
+ // Check the following:
+ // 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.
+ // TODO: Expand the check to include `LOOP` construct as well when it is
+ // supported.
+
+ // Check if the parent context has the SIMD clause
+ // Please note that we use GetContext() instead of GetContextParent()
+ // because PushContextAndClauseSets() has not been called on the
+ // current context yet.
+ // TODO: Check for declare simd regions.
+ bool eligibleSIMD{false};
+ std::visit(Fortran::common::visitors{
+ // Allow `!$OMP ORDERED SIMD`
+ [&](const parser::OpenMPBlockConstruct &c) {
+ const auto &beginBlockDir{
+ std::get<parser::OmpBeginBlockDirective>(c.t)};
+ const auto &beginDir{
+ std::get<parser::OmpBlockDirective>(beginBlockDir.t)};
+ if (beginDir.v == llvm::omp::Directive::OMPD_ordered) {
+ const auto &clauses{
+ std::get<parser::OmpClauseList>(beginBlockDir.t)};
+ for (const auto &clause : clauses.v) {
+ if (std::get_if<parser::OmpClause::Simd>(&clause.u)) {
+ eligibleSIMD = true;
+ break;
+ }
+ }
+ }
+ },
+ [&](const parser::OpenMPSimpleStandaloneConstruct &c) {
+ const auto &dir{
+ std::get<parser::OmpSimpleStandaloneDirective>(c.t)};
+ if (dir.v == llvm::omp::Directive::OMPD_ordered) {
+ const auto &clauses{std::get<parser::OmpClauseList>(c.t)};
+ for (const auto &clause : clauses.v) {
+ if (std::get_if<parser::OmpClause::Simd>(&clause.u)) {
+ eligibleSIMD = true;
+ break;
+ }
+ }
+ }
+ },
+ // Allowing SIMD construct
+ [&](const parser::OpenMPLoopConstruct &c) {
+ const auto &beginLoopDir{
+ std::get<parser::OmpBeginLoopDirective>(c.t)};
+ const auto &beginDir{
+ std::get<parser::OmpLoopDirective>(beginLoopDir.t)};
+ if ((beginDir.v == llvm::omp::Directive::OMPD_simd) ||
+ (beginDir.v == llvm::omp::Directive::OMPD_do_simd)) {
+ eligibleSIMD = true;
+ }
+ },
+ [&](const parser::OpenMPAtomicConstruct &c) {
+ // Allow `!$OMP ATOMIC`
+ eligibleSIMD = true;
+ },
+ [&](const auto &c) {},
+ },
+ c.u);
+ if (!eligibleSIMD) {
+ context_.Say(parser::FindSourceLocation(c),
+ "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."_err_en_US);
+ }
+}
+
std::int64_t OmpStructureChecker::GetOrdCollapseLevel(
const parser::OpenMPLoopConstruct &x) {
const auto &beginLoopDir{std::get<parser::OmpBeginLoopDirective>(x.t)};
@@ -382,6 +466,9 @@ void OmpStructureChecker::CheckCycleConstraints(
}
void OmpStructureChecker::Leave(const parser::OpenMPLoopConstruct &) {
+ if (llvm::omp::simdSet.test(GetContext().directive)) {
+ ExitSIMDNest();
+ }
dirContext_.pop_back();
}
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 8c76530551a3..fbbe8ae35f7d 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -215,6 +215,7 @@ class OmpStructureChecker
void CheckLoopItrVariableIsInt(const parser::OpenMPLoopConstruct &x);
void CheckDoWhile(const parser::OpenMPLoopConstruct &x);
void CheckCycleConstraints(const parser::OpenMPLoopConstruct &x);
+ void CheckSIMDNest(const parser::OpenMPConstruct &x);
std::int64_t GetOrdCollapseLevel(const parser::OpenMPLoopConstruct &x);
void CheckIfDoOrderedClause(const parser::OmpBlockDirective &blkDirectiv);
bool CheckReductionOperators(const parser::OmpClause::Reduction &);
diff --git a/flang/test/Semantics/omp-do05.f90 b/flang/test/Semantics/omp-do05.f90
index e2e899959d6f..fb9281c4d946 100644
--- a/flang/test/Semantics/omp-do05.f90
+++ b/flang/test/Semantics/omp-do05.f90
@@ -31,6 +31,7 @@ program omp_do
!$omp parallel do simd
do i=1,10
+ !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: A worksharing region may not be closely nested inside a worksharing, explicit task, taskloop, critical, ordered, atomic, or master region
!$omp single
do j=1,10
@@ -55,6 +56,7 @@ program omp_do
!ERROR: `DISTRIBUTE` region has to be strictly nested inside `TEAMS` region.
!$omp distribute parallel do simd
do i=1,10
+ !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: A worksharing region may not be closely nested inside a worksharing, explicit task, taskloop, critical, ordered, atomic, or master region
!$omp single
do j=1,10
@@ -77,6 +79,7 @@ program omp_do
!$omp target parallel do simd
do i=1,10
+ !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: A worksharing region may not be closely nested inside a worksharing, explicit task, taskloop, critical, ordered, atomic, or master region
!$omp single
do j=1,10
@@ -97,8 +100,9 @@ program omp_do
end do
!$omp end target teams distribute parallel do
- !$omp target teams distribute parallel do simd
+ !$omp target teams distribute parallel do simd
do i=1,10
+ !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: A worksharing region may not be closely nested inside a worksharing, explicit task, taskloop, critical, ordered, atomic, or master region
!$omp single
do j=1,10
diff --git a/flang/test/Semantics/omp-nested-simd.f90 b/flang/test/Semantics/omp-nested-simd.f90
new file mode 100644
index 000000000000..b17614cce45f
--- /dev/null
+++ b/flang/test/Semantics/omp-nested-simd.f90
@@ -0,0 +1,214 @@
+! RUN: %S/test_errors.sh %s %t %flang_fc1 -fopenmp
+! OpenMP Version 4.5
+! Various checks with the nesting of SIMD construct
+
+SUBROUTINE NESTED_GOOD(N)
+ INTEGER N, I, J, K, A(10), B(10)
+ !$OMP SIMD
+ DO I = 1,N
+ !$OMP ATOMIC
+ K = K + 1
+ IF (I <= 10) THEN
+ !$OMP ORDERED SIMD
+ DO J = 1,N
+ A(J) = J
+ END DO
+ !$OMP END ORDERED
+ ENDIF
+ END DO
+ !$OMP END SIMD
+
+ !$OMP SIMD
+ DO I = 1,N
+ IF (I <= 10) THEN
+ !$OMP SIMD
+ DO J = 1,N
+ A(J) = J
+ END DO
+ !$OMP END SIMD
+ ENDIF
+ END DO
+ !$OMP END SIMD
+END SUBROUTINE NESTED_GOOD
+
+SUBROUTINE NESTED_BAD(N)
+ INTEGER N, I, J, K, A(10), B(10)
+
+ !$OMP SIMD
+ DO I = 1,N
+ IF (I <= 10) THEN
+ !$OMP ORDERED SIMD
+ 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.
+ !$omp teams
+ DO K = 1,N
+ print *, 'Hello'
+ END DO
+ !$omp end teams
+ END DO
+ !$OMP END ORDERED
+ ENDIF
+ END DO
+ !$OMP END SIMD
+
+ !$OMP SIMD
+ DO I = 1,N
+ !$OMP ATOMIC
+ K = K + 1
+ IF (I <= 10) THEN
+ !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 task
+ do J = 1, N
+ K = 2
+ 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
+ end do
+ !$omp end target
+ !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 DO
+ DO J = 1,N
+ A(J) = J
+ END DO
+ !$OMP END DO
+ !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 PARALLEL DO
+ DO J = 1,N
+ A(J) = J
+ END DO
+ !$OMP END PARALLEL DO
+ ENDIF
+ END DO
+ !$OMP END SIMD
+
+ !$OMP DO SIMD
+ DO I = 1,N
+ !$OMP ATOMIC
+ K = K + 1
+ IF (I <= 10) THEN
+ !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 task
+ do J = 1, N
+ K = 2
+ 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
+ end do
+ !$omp end target
+ !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: A worksharing region may not be closely nested inside a worksharing, explicit task, taskloop, critical, ordered, atomic, or master region
+ !$OMP DO
+ DO J = 1,N
+ A(J) = J
+ END DO
+ !$OMP END DO
+ !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 PARALLEL DO
+ DO J = 1,N
+ A(J) = J
+ END DO
+ !$OMP END PARALLEL DO
+ ENDIF
+ END DO
+ !$OMP END DO SIMD
+
+ !$OMP PARALLEL DO SIMD
+ DO I = 1,N
+ !$OMP ATOMIC
+ K = K + 1
+ IF (I <= 10) THEN
+ !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 task
+ do J = 1, N
+ K = 2
+ 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
+ end do
+ !$omp end target
+ !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: A worksharing region may not be closely nested inside a worksharing, explicit task, taskloop, critical, ordered, atomic, or master region
+ !$OMP DO
+ DO J = 1,N
+ A(J) = J
+ END DO
+ !$OMP END DO
+ !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 PARALLEL DO
+ DO J = 1,N
+ A(J) = J
+ END DO
+ !$OMP END PARALLEL DO
+ ENDIF
+ END DO
+ !$OMP END PARALLEL DO SIMD
+
+ !$OMP TARGET SIMD
+ DO I = 1,N
+ !$OMP ATOMIC
+ K = K + 1
+ IF (I <= 10) THEN
+ !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 task
+ do J = 1, N
+ K = 2
+ 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
+ end do
+ !$omp end target
+ !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 DO
+ DO J = 1,N
+ A(J) = J
+ END DO
+ !$OMP END DO
+ !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 PARALLEL DO
+ DO J = 1,N
+ A(J) = J
+ END DO
+ !$OMP END PARALLEL DO
+ ENDIF
+ END DO
+ !$OMP END TARGET SIMD
+
+
+END SUBROUTINE NESTED_BAD
diff --git a/flang/test/Semantics/omp-ordered-simd.f90 b/flang/test/Semantics/omp-ordered-simd.f90
index 5a3760ea604c..8350a9e13891 100644
--- a/flang/test/Semantics/omp-ordered-simd.f90
+++ b/flang/test/Semantics/omp-ordered-simd.f90
@@ -25,6 +25,7 @@ SUBROUTINE ORDERED_BAD(N)
!$OMP DO SIMD
DO I = 1,N
IF (I <= 10) THEN
+ !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: The ORDERED clause must be present on the loop construct if any ORDERED region ever binds to a loop region arising from the loop construct.
!$OMP ORDERED
CALL WORK(I)
More information about the flang-commits
mailing list