[flang-commits] [flang] 3883e26 - [flang][OpenMP] Add semantic check for target nesting
via flang-commits
flang-commits at lists.llvm.org
Tue Aug 17 18:46:01 PDT 2021
Author: PeixinQiao
Date: 2021-08-18T09:40:52+08:00
New Revision: 3883e266f4abd33e19a7c656dde19b6f5c7fc134
URL: https://github.com/llvm/llvm-project/commit/3883e266f4abd33e19a7c656dde19b6f5c7fc134
DIFF: https://github.com/llvm/llvm-project/commit/3883e266f4abd33e19a7c656dde19b6f5c7fc134.diff
LOG: [flang][OpenMP] Add semantic check for target nesting
This patch implements the following check for TARGET construct:
```
OpenMP Version 5.0 Target construct restriction: If a target update,
target data, target enter data, or target exit data construct is
encountered during execution of a target region, the behavior is
unspecified.
```
Also add one test case for the check.
Reviewed By: kiranchandramohan, clementval
Differential Revision: https://reviews.llvm.org/D106165
Added:
flang/test/Semantics/omp-nested-target.f90
Modified:
flang/lib/Semantics/check-omp-structure.cpp
flang/lib/Semantics/check-omp-structure.h
Removed:
################################################################################
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 366a6506a8ec4..a81914f7db278 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -288,6 +288,9 @@ void OmpStructureChecker::Enter(const parser::OpenMPConstruct &x) {
if (GetDirectiveNest(SIMDNest) > 0) {
CheckSIMDNest(x);
}
+ if (GetDirectiveNest(TargetNest) > 0) {
+ CheckTargetNest(x);
+ }
}
}
@@ -473,6 +476,53 @@ void OmpStructureChecker::CheckSIMDNest(const parser::OpenMPConstruct &c) {
}
}
+void OmpStructureChecker::CheckTargetNest(const parser::OpenMPConstruct &c) {
+ // 2.12.5 Target Construct Restriction
+ bool eligibleTarget{true};
+ llvm::omp::Directive ineligibleTargetDir;
+ std::visit(
+ common::visitors{
+ [&](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_target_data) {
+ eligibleTarget = false;
+ ineligibleTargetDir = beginDir.v;
+ }
+ },
+ [&](const parser::OpenMPStandaloneConstruct &c) {
+ std::visit(
+ common::visitors{
+ [&](const parser::OpenMPSimpleStandaloneConstruct &c) {
+ const auto &dir{
+ std::get<parser::OmpSimpleStandaloneDirective>(c.t)};
+ if (dir.v == llvm::omp::Directive::OMPD_target_update ||
+ dir.v ==
+ llvm::omp::Directive::OMPD_target_enter_data ||
+ dir.v ==
+ llvm::omp::Directive::OMPD_target_exit_data) {
+ eligibleTarget = false;
+ ineligibleTargetDir = dir.v;
+ }
+ },
+ [&](const auto &c) {},
+ },
+ c.u);
+ },
+ [&](const auto &c) {},
+ },
+ c.u);
+ if (!eligibleTarget) {
+ context_.Say(parser::FindSourceLocation(c),
+ "If %s directive is nested inside TARGET region, the behaviour "
+ "is unspecified"_en_US,
+ parser::ToUpperCaseLetters(
+ getDirectiveName(ineligibleTargetDir).str()));
+ }
+}
+
std::int64_t OmpStructureChecker::GetOrdCollapseLevel(
const parser::OpenMPLoopConstruct &x) {
const auto &beginLoopDir{std::get<parser::OmpBeginLoopDirective>(x.t)};
@@ -616,6 +666,9 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) {
CheckMatching<parser::OmpBlockDirective>(beginDir, endDir);
PushContextAndClauseSets(beginDir.source, beginDir.v);
+ if (GetContext().directive == llvm::omp::Directive::OMPD_target) {
+ EnterDirectiveNest(TargetNest);
+ }
if (CurrentDirectiveIsNested()) {
CheckIfDoOrderedClause(beginDir);
@@ -710,6 +763,9 @@ void OmpStructureChecker::Leave(const parser::OpenMPBlockConstruct &) {
if (GetDirectiveNest(TargetBlockOnlyTeams)) {
ExitDirectiveNest(TargetBlockOnlyTeams);
}
+ if (GetContext().directive == llvm::omp::Directive::OMPD_target) {
+ ExitDirectiveNest(TargetNest);
+ }
dirContext_.pop_back();
}
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 03cd1f8d3f298..bd0d8100ddd3d 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -226,6 +226,7 @@ class OmpStructureChecker
void CheckCycleConstraints(const parser::OpenMPLoopConstruct &x);
void CheckDistLinear(const parser::OpenMPLoopConstruct &x);
void CheckSIMDNest(const parser::OpenMPConstruct &x);
+ void CheckTargetNest(const parser::OpenMPConstruct &x);
void CheckCancellationNest(
const parser::CharBlock &source, const parser::OmpCancelType::Type &type);
std::int64_t GetOrdCollapseLevel(const parser::OpenMPLoopConstruct &x);
@@ -253,7 +254,12 @@ class OmpStructureChecker
void ExitDirectiveNest(const int index) { directiveNest_[index]--; }
int GetDirectiveNest(const int index) { return directiveNest_[index]; }
- enum directiveNestType { SIMDNest, TargetBlockOnlyTeams, LastType };
+ enum directiveNestType {
+ SIMDNest,
+ TargetBlockOnlyTeams,
+ TargetNest,
+ LastType
+ };
int directiveNest_[LastType + 1] = {0};
};
} // namespace Fortran::semantics
diff --git a/flang/test/Semantics/omp-nested-target.f90 b/flang/test/Semantics/omp-nested-target.f90
new file mode 100644
index 0000000000000..da4d1619f1063
--- /dev/null
+++ b/flang/test/Semantics/omp-nested-target.f90
@@ -0,0 +1,54 @@
+! RUN: %S/test_errors.sh %s %t %flang_fc1 -fopenmp
+! REQUIRES: shell
+
+! OpenMP Version 5.0
+! Check OpenMP construct validity for the following directives:
+! 2.12.5 Target Construct
+
+program main
+ integer :: i, j, N = 10
+ real :: a, arrayA(512), arrayB(512), ai(10)
+ real, allocatable :: B(:)
+
+ !$omp target
+ !WARNING: If TARGET UPDATE directive is nested inside TARGET region, the behaviour is unspecified
+ !$omp target update from(arrayA) to(arrayB)
+ do i = 1, 512
+ arrayA(i) = arrayB(i)
+ end do
+ !$omp end target
+
+ !$omp parallel
+ !$omp target
+ !$omp parallel
+ !WARNING: If TARGET UPDATE directive is nested inside TARGET region, the behaviour is unspecified
+ !$omp target update from(arrayA) to(arrayB)
+ do i = 1, 512
+ arrayA(i) = arrayB(i)
+ end do
+ !$omp end parallel
+ !$omp end target
+ !$omp end parallel
+
+ !$omp target
+ !WARNING: If TARGET DATA directive is nested inside TARGET region, the behaviour is unspecified
+ !$omp target data map(to: a)
+ do i = 1, N
+ a = 3.14
+ end do
+ !$omp end target data
+ !$omp end target
+
+ allocate(B(N))
+ !$omp target
+ !WARNING: If TARGET ENTER DATA directive is nested inside TARGET region, the behaviour is unspecified
+ !$omp target enter data map(alloc:B)
+ !$omp end target
+
+ !$omp target
+ !WARNING: If TARGET EXIT DATA directive is nested inside TARGET region, the behaviour is unspecified
+ !$omp target exit data map(delete:B)
+ !$omp end target
+ deallocate(B)
+
+end program main
More information about the flang-commits
mailing list