Skip to content

Commit 7f93fd3

Browse files
PeixinQiaojeanPerier
authored andcommitted
[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
1 parent f1bfbe7 commit 7f93fd3

File tree

3 files changed

+117
-1
lines changed

3 files changed

+117
-1
lines changed

flang/lib/Semantics/check-omp-structure.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,9 @@ void OmpStructureChecker::Enter(const parser::OpenMPConstruct &x) {
288288
if (GetDirectiveNest(SIMDNest) > 0) {
289289
CheckSIMDNest(x);
290290
}
291+
if (GetDirectiveNest(TargetNest) > 0) {
292+
CheckTargetNest(x);
293+
}
291294
}
292295
}
293296

@@ -473,6 +476,53 @@ void OmpStructureChecker::CheckSIMDNest(const parser::OpenMPConstruct &c) {
473476
}
474477
}
475478

479+
void OmpStructureChecker::CheckTargetNest(const parser::OpenMPConstruct &c) {
480+
// 2.12.5 Target Construct Restriction
481+
bool eligibleTarget{true};
482+
llvm::omp::Directive ineligibleTargetDir;
483+
std::visit(
484+
common::visitors{
485+
[&](const parser::OpenMPBlockConstruct &c) {
486+
const auto &beginBlockDir{
487+
std::get<parser::OmpBeginBlockDirective>(c.t)};
488+
const auto &beginDir{
489+
std::get<parser::OmpBlockDirective>(beginBlockDir.t)};
490+
if (beginDir.v == llvm::omp::Directive::OMPD_target_data) {
491+
eligibleTarget = false;
492+
ineligibleTargetDir = beginDir.v;
493+
}
494+
},
495+
[&](const parser::OpenMPStandaloneConstruct &c) {
496+
std::visit(
497+
common::visitors{
498+
[&](const parser::OpenMPSimpleStandaloneConstruct &c) {
499+
const auto &dir{
500+
std::get<parser::OmpSimpleStandaloneDirective>(c.t)};
501+
if (dir.v == llvm::omp::Directive::OMPD_target_update ||
502+
dir.v ==
503+
llvm::omp::Directive::OMPD_target_enter_data ||
504+
dir.v ==
505+
llvm::omp::Directive::OMPD_target_exit_data) {
506+
eligibleTarget = false;
507+
ineligibleTargetDir = dir.v;
508+
}
509+
},
510+
[&](const auto &c) {},
511+
},
512+
c.u);
513+
},
514+
[&](const auto &c) {},
515+
},
516+
c.u);
517+
if (!eligibleTarget) {
518+
context_.Say(parser::FindSourceLocation(c),
519+
"If %s directive is nested inside TARGET region, the behaviour "
520+
"is unspecified"_en_US,
521+
parser::ToUpperCaseLetters(
522+
getDirectiveName(ineligibleTargetDir).str()));
523+
}
524+
}
525+
476526
std::int64_t OmpStructureChecker::GetOrdCollapseLevel(
477527
const parser::OpenMPLoopConstruct &x) {
478528
const auto &beginLoopDir{std::get<parser::OmpBeginLoopDirective>(x.t)};
@@ -616,6 +666,9 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) {
616666
CheckMatching<parser::OmpBlockDirective>(beginDir, endDir);
617667

618668
PushContextAndClauseSets(beginDir.source, beginDir.v);
669+
if (GetContext().directive == llvm::omp::Directive::OMPD_target) {
670+
EnterDirectiveNest(TargetNest);
671+
}
619672

620673
if (CurrentDirectiveIsNested()) {
621674
CheckIfDoOrderedClause(beginDir);
@@ -710,6 +763,9 @@ void OmpStructureChecker::Leave(const parser::OpenMPBlockConstruct &) {
710763
if (GetDirectiveNest(TargetBlockOnlyTeams)) {
711764
ExitDirectiveNest(TargetBlockOnlyTeams);
712765
}
766+
if (GetContext().directive == llvm::omp::Directive::OMPD_target) {
767+
ExitDirectiveNest(TargetNest);
768+
}
713769
dirContext_.pop_back();
714770
}
715771

flang/lib/Semantics/check-omp-structure.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ class OmpStructureChecker
226226
void CheckCycleConstraints(const parser::OpenMPLoopConstruct &x);
227227
void CheckDistLinear(const parser::OpenMPLoopConstruct &x);
228228
void CheckSIMDNest(const parser::OpenMPConstruct &x);
229+
void CheckTargetNest(const parser::OpenMPConstruct &x);
229230
void CheckCancellationNest(
230231
const parser::CharBlock &source, const parser::OmpCancelType::Type &type);
231232
std::int64_t GetOrdCollapseLevel(const parser::OpenMPLoopConstruct &x);
@@ -253,7 +254,12 @@ class OmpStructureChecker
253254
void ExitDirectiveNest(const int index) { directiveNest_[index]--; }
254255
int GetDirectiveNest(const int index) { return directiveNest_[index]; }
255256

256-
enum directiveNestType { SIMDNest, TargetBlockOnlyTeams, LastType };
257+
enum directiveNestType {
258+
SIMDNest,
259+
TargetBlockOnlyTeams,
260+
TargetNest,
261+
LastType
262+
};
257263
int directiveNest_[LastType + 1] = {0};
258264
};
259265
} // namespace Fortran::semantics
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
! RUN: %S/test_errors.sh %s %t %flang_fc1 -fopenmp
2+
! REQUIRES: shell
3+
4+
! OpenMP Version 5.0
5+
! Check OpenMP construct validity for the following directives:
6+
! 2.12.5 Target Construct
7+
8+
program main
9+
integer :: i, j, N = 10
10+
real :: a, arrayA(512), arrayB(512), ai(10)
11+
real, allocatable :: B(:)
12+
13+
!$omp target
14+
!WARNING: If TARGET UPDATE directive is nested inside TARGET region, the behaviour is unspecified
15+
!$omp target update from(arrayA) to(arrayB)
16+
do i = 1, 512
17+
arrayA(i) = arrayB(i)
18+
end do
19+
!$omp end target
20+
21+
!$omp parallel
22+
!$omp target
23+
!$omp parallel
24+
!WARNING: If TARGET UPDATE directive is nested inside TARGET region, the behaviour is unspecified
25+
!$omp target update from(arrayA) to(arrayB)
26+
do i = 1, 512
27+
arrayA(i) = arrayB(i)
28+
end do
29+
!$omp end parallel
30+
!$omp end target
31+
!$omp end parallel
32+
33+
!$omp target
34+
!WARNING: If TARGET DATA directive is nested inside TARGET region, the behaviour is unspecified
35+
!$omp target data map(to: a)
36+
do i = 1, N
37+
a = 3.14
38+
end do
39+
!$omp end target data
40+
!$omp end target
41+
42+
allocate(B(N))
43+
!$omp target
44+
!WARNING: If TARGET ENTER DATA directive is nested inside TARGET region, the behaviour is unspecified
45+
!$omp target enter data map(alloc:B)
46+
!$omp end target
47+
48+
!$omp target
49+
!WARNING: If TARGET EXIT DATA directive is nested inside TARGET region, the behaviour is unspecified
50+
!$omp target exit data map(delete:B)
51+
!$omp end target
52+
deallocate(B)
53+
54+
end program main

0 commit comments

Comments
 (0)