Skip to content

Commit e15545c

Browse files
[Flang][OpenMP] Allow copyprivate and nowait on the directive clauses (#127769)
Issue: - Single construct used to throw a semantic error for copyprivate and nowait clause when used in the single directive. - Also, the copyprivate with nowait restriction has been removed from OpenMP 6.0 Fix: - Allow copyprivate and nowait on both single and end single directive - Allow at most one nowait clause - Throw a warning when the same list item is used in the copyprivate clause on the end single directive From Reference guide (OpenMP 5.2, 2.10.2): ``` !$omp single [clause[ [,]clause] ... ] loosely-structured-block !$omp end single [end-clause[ [,]end-clause] ...] clause: copyprivate (list) nowait [...] end-clause: copyprivate (list) nowait ``` Towards: #110008
1 parent f3dc358 commit e15545c

File tree

6 files changed

+199
-30
lines changed

6 files changed

+199
-30
lines changed

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

+58-24
Original file line numberDiff line numberDiff line change
@@ -1203,6 +1203,64 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) {
12031203
deviceConstructFound_ = true;
12041204
}
12051205

1206+
if (GetContext().directive == llvm::omp::Directive::OMPD_single) {
1207+
std::set<Symbol *> singleCopyprivateSyms;
1208+
std::set<Symbol *> endSingleCopyprivateSyms;
1209+
bool foundNowait{false};
1210+
parser::CharBlock NowaitSource;
1211+
1212+
auto catchCopyPrivateNowaitClauses = [&](const auto &dir, bool endDir) {
1213+
for (auto &clause : std::get<parser::OmpClauseList>(dir.t).v) {
1214+
if (clause.Id() == llvm::omp::Clause::OMPC_copyprivate) {
1215+
for (const auto &ompObject : GetOmpObjectList(clause)->v) {
1216+
const auto *name{parser::Unwrap<parser::Name>(ompObject)};
1217+
if (Symbol * symbol{name->symbol}) {
1218+
if (singleCopyprivateSyms.count(symbol)) {
1219+
if (endDir) {
1220+
context_.Warn(common::UsageWarning::OpenMPUsage, name->source,
1221+
"The COPYPRIVATE clause with '%s' is already used on the SINGLE directive"_warn_en_US,
1222+
name->ToString());
1223+
} else {
1224+
context_.Say(name->source,
1225+
"'%s' appears in more than one COPYPRIVATE clause on the SINGLE directive"_err_en_US,
1226+
name->ToString());
1227+
}
1228+
} else if (endSingleCopyprivateSyms.count(symbol)) {
1229+
context_.Say(name->source,
1230+
"'%s' appears in more than one COPYPRIVATE clause on the END SINGLE directive"_err_en_US,
1231+
name->ToString());
1232+
} else {
1233+
if (endDir) {
1234+
endSingleCopyprivateSyms.insert(symbol);
1235+
} else {
1236+
singleCopyprivateSyms.insert(symbol);
1237+
}
1238+
}
1239+
}
1240+
}
1241+
} else if (clause.Id() == llvm::omp::Clause::OMPC_nowait) {
1242+
if (foundNowait) {
1243+
context_.Say(clause.source,
1244+
"At most one NOWAIT clause can appear on the SINGLE directive"_err_en_US);
1245+
} else {
1246+
foundNowait = !endDir;
1247+
}
1248+
if (!NowaitSource.ToString().size()) {
1249+
NowaitSource = clause.source;
1250+
}
1251+
}
1252+
}
1253+
};
1254+
catchCopyPrivateNowaitClauses(beginBlockDir, false);
1255+
catchCopyPrivateNowaitClauses(endBlockDir, true);
1256+
unsigned version{context_.langOptions().OpenMPVersion};
1257+
if (version <= 52 && NowaitSource.ToString().size() &&
1258+
(singleCopyprivateSyms.size() || endSingleCopyprivateSyms.size())) {
1259+
context_.Say(NowaitSource,
1260+
"NOWAIT clause must not be used with COPYPRIVATE clause on the SINGLE directive"_err_en_US);
1261+
}
1262+
}
1263+
12061264
switch (beginDir.v) {
12071265
case llvm::omp::Directive::OMPD_target:
12081266
if (CheckTargetBlockOnlyTeams(block)) {
@@ -2903,12 +2961,6 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
29032961
// clause
29042962
CheckMultListItems();
29052963

2906-
// 2.7.3 Single Construct Restriction
2907-
if (GetContext().directive == llvm::omp::Directive::OMPD_end_single) {
2908-
CheckNotAllowedIfClause(
2909-
llvm::omp::Clause::OMPC_copyprivate, {llvm::omp::Clause::OMPC_nowait});
2910-
}
2911-
29122964
auto testThreadprivateVarErr = [&](Symbol sym, parser::Name name,
29132965
llvmOmpClause clauseTy) {
29142966
if (sym.test(Symbol::Flag::OmpThreadprivate))
@@ -3549,15 +3601,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Private &x) {
35493601

35503602
void OmpStructureChecker::Enter(const parser::OmpClause::Nowait &x) {
35513603
CheckAllowedClause(llvm::omp::Clause::OMPC_nowait);
3552-
if (llvm::omp::noWaitClauseNotAllowedSet.test(GetContext().directive)) {
3553-
context_.Say(GetContext().clauseSource,
3554-
"%s clause is not allowed on the OMP %s directive,"
3555-
" use it on OMP END %s directive "_err_en_US,
3556-
parser::ToUpperCaseLetters(
3557-
getClauseName(llvm::omp::Clause::OMPC_nowait).str()),
3558-
parser::ToUpperCaseLetters(GetContext().directiveSource.ToString()),
3559-
parser::ToUpperCaseLetters(GetContext().directiveSource.ToString()));
3560-
}
35613604
}
35623605

35633606
bool OmpStructureChecker::IsDataRefTypeParamInquiry(
@@ -4288,15 +4331,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Copyprivate &x) {
42884331
CheckIntentInPointer(symbols, llvm::omp::Clause::OMPC_copyprivate);
42894332
CheckCopyingPolymorphicAllocatable(
42904333
symbols, llvm::omp::Clause::OMPC_copyprivate);
4291-
if (GetContext().directive == llvm::omp::Directive::OMPD_single) {
4292-
context_.Say(GetContext().clauseSource,
4293-
"%s clause is not allowed on the OMP %s directive,"
4294-
" use it on OMP END %s directive "_err_en_US,
4295-
parser::ToUpperCaseLetters(
4296-
getClauseName(llvm::omp::Clause::OMPC_copyprivate).str()),
4297-
parser::ToUpperCaseLetters(GetContext().directiveSource.ToString()),
4298-
parser::ToUpperCaseLetters(GetContext().directiveSource.ToString()));
4299-
}
43004334
}
43014335

43024336
void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) {

flang/test/Semantics/OpenMP/clause-validity01.f90

+3-4
Original file line numberDiff line numberDiff line change
@@ -330,11 +330,12 @@
330330
!$omp parallel
331331
b = 1
332332
!ERROR: LASTPRIVATE clause is not allowed on the SINGLE directive
333-
!ERROR: NOWAIT clause is not allowed on the OMP SINGLE directive, use it on OMP END SINGLE directive
333+
!ERROR: NOWAIT clause must not be used with COPYPRIVATE clause on the SINGLE directive
334334
!$omp single private(a) lastprivate(c) nowait
335335
a = 3.14
336-
!ERROR: Clause NOWAIT is not allowed if clause COPYPRIVATE appears on the END SINGLE directive
337336
!ERROR: COPYPRIVATE variable 'a' may not appear on a PRIVATE or FIRSTPRIVATE clause on a SINGLE construct
337+
!ERROR: At most one NOWAIT clause can appear on the SINGLE directive
338+
!ERROR: At most one NOWAIT clause can appear on the SINGLE directive
338339
!ERROR: At most one NOWAIT clause can appear on the END SINGLE directive
339340
!$omp end single copyprivate(a) nowait nowait
340341
c = 2
@@ -351,7 +352,6 @@
351352
a = 1.0
352353
!ERROR: COPYPRIVATE clause is not allowed on the END WORKSHARE directive
353354
!$omp end workshare nowait copyprivate(a)
354-
!ERROR: NOWAIT clause is not allowed on the OMP WORKSHARE directive, use it on OMP END WORKSHARE directive
355355
!$omp workshare nowait
356356
!$omp end workshare
357357
!$omp end parallel
@@ -420,7 +420,6 @@
420420
!$omp parallel
421421
!ERROR: No ORDERED clause with a parameter can be specified on the DO SIMD directive
422422
!ERROR: NOGROUP clause is not allowed on the DO SIMD directive
423-
!ERROR: NOWAIT clause is not allowed on the OMP DO SIMD directive, use it on OMP END DO SIMD directive
424423
!$omp do simd ordered(2) NOGROUP nowait
425424
do i = 1, N
426425
do j = 1, N
+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp -fopenmp-version=52
2+
!
3+
! OpenMP Version 5.2
4+
!
5+
! 2.10.2 single Construct
6+
! Copyprivate and Nowait clauses are allowed in both clause and end clause
7+
8+
subroutine omp_single
9+
integer, save :: i
10+
integer :: j
11+
i = 10; j = 11
12+
13+
!ERROR: COPYPRIVATE variable 'i' is not PRIVATE or THREADPRIVATE in outer context
14+
!ERROR: NOWAIT clause must not be used with COPYPRIVATE clause on the SINGLE directive
15+
!$omp single copyprivate(i) nowait
16+
print *, "omp single", i
17+
!$omp end single
18+
19+
!$omp parallel private(i)
20+
!$omp single copyprivate(i)
21+
print *, "omp single", i
22+
!$omp end single
23+
!$omp end parallel
24+
25+
!$omp parallel
26+
!ERROR: NOWAIT clause must not be used with COPYPRIVATE clause on the SINGLE directive
27+
!$omp single nowait
28+
print *, "omp single", i
29+
!ERROR: COPYPRIVATE variable 'i' is not PRIVATE or THREADPRIVATE in outer context
30+
!$omp end single copyprivate(i)
31+
32+
!ERROR: COPYPRIVATE variable 'i' is not PRIVATE or THREADPRIVATE in outer context
33+
!$omp single copyprivate(i)
34+
print *, "omp single", i
35+
!ERROR: NOWAIT clause must not be used with COPYPRIVATE clause on the SINGLE directive
36+
!$omp end single nowait
37+
38+
!ERROR: COPYPRIVATE variable 'j' may not appear on a PRIVATE or FIRSTPRIVATE clause on a SINGLE construct
39+
!$omp single private(j) copyprivate(j)
40+
print *, "omp single", j
41+
!ERROR: COPYPRIVATE variable 'j' may not appear on a PRIVATE or FIRSTPRIVATE clause on a SINGLE construct
42+
!WARNING: The COPYPRIVATE clause with 'j' is already used on the SINGLE directive
43+
!$omp end single copyprivate(j)
44+
45+
!$omp single nowait
46+
print *, "omp single", j
47+
!ERROR: At most one NOWAIT clause can appear on the SINGLE directive
48+
!$omp end single nowait
49+
!$omp end parallel
50+
51+
!$omp single nowait
52+
print *, "omp single", i
53+
!$omp end single
54+
end subroutine omp_single
+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp -fopenmp-version=52
2+
!
3+
! OpenMP Version 5.2
4+
!
5+
! 2.10.2 single Construct
6+
! Valid and invalid testcases for copyprivate and nowait clause on the single directive
7+
8+
program single
9+
! Valid testcases
10+
!$omp single
11+
print *, x
12+
!$omp end single
13+
14+
!$omp single nowait
15+
print *, x
16+
!$omp end single
17+
18+
!$omp single copyprivate(x, y, z)
19+
print *, x
20+
!$omp end single
21+
22+
!$omp single
23+
print *, x
24+
!$omp end single copyprivate(x)
25+
26+
! Invalid testcases
27+
!$omp single
28+
print *, x
29+
!ERROR: NOWAIT clause must not be used with COPYPRIVATE clause on the SINGLE directive
30+
!$omp end single copyprivate(x) nowait
31+
32+
!ERROR: 'x' appears in more than one COPYPRIVATE clause on the SINGLE directive
33+
!$omp single copyprivate(x) copyprivate(x)
34+
print *, x
35+
!$omp end single
36+
37+
!$omp single
38+
print *, x
39+
!ERROR: 'x' appears in more than one COPYPRIVATE clause on the END SINGLE directive
40+
!$omp end single copyprivate(x) copyprivate(x)
41+
42+
!ERROR: At most one NOWAIT clause can appear on the SINGLE directive
43+
!$omp single nowait nowait
44+
print *, x
45+
!$omp end single
46+
47+
!$omp single
48+
print *, x
49+
!ERROR: At most one NOWAIT clause can appear on the END SINGLE directive
50+
!$omp end single nowait nowait
51+
52+
!ERROR: NOWAIT clause must not be used with COPYPRIVATE clause on the SINGLE directive
53+
!$omp single copyprivate(x) nowait
54+
print *, x
55+
!WARNING: The COPYPRIVATE clause with 'x' is already used on the SINGLE directive
56+
!ERROR: At most one NOWAIT clause can appear on the SINGLE directive
57+
!$omp end single copyprivate(x) nowait
58+
59+
!$omp single copyprivate(x)
60+
print *, x
61+
!WARNING: The COPYPRIVATE clause with 'x' is already used on the SINGLE directive
62+
!ERROR: NOWAIT clause must not be used with COPYPRIVATE clause on the SINGLE directive
63+
!$omp end single copyprivate(x) nowait
64+
65+
!ERROR: NOWAIT clause must not be used with COPYPRIVATE clause on the SINGLE directive
66+
!$omp single copyprivate(x, y) nowait
67+
print *, x
68+
!WARNING: The COPYPRIVATE clause with 'x' is already used on the SINGLE directive
69+
!ERROR: 'z' appears in more than one COPYPRIVATE clause on the END SINGLE directive
70+
!ERROR: At most one NOWAIT clause can appear on the SINGLE directive
71+
!$omp end single copyprivate(x, z) copyprivate(z) nowait
72+
73+
!ERROR: NOWAIT clause must not be used with COPYPRIVATE clause on the SINGLE directive
74+
!$omp single copyprivate(x) nowait copyprivate(y) copyprivate(z)
75+
print *, x
76+
!WARNING: The COPYPRIVATE clause with 'x' is already used on the SINGLE directive
77+
!WARNING: The COPYPRIVATE clause with 'y' is already used on the SINGLE directive
78+
!WARNING: The COPYPRIVATE clause with 'z' is already used on the SINGLE directive
79+
!ERROR: At most one NOWAIT clause can appear on the SINGLE directive
80+
!$omp end single copyprivate(x, y, z) nowait
81+
end program

flang/test/Semantics/OpenMP/threadprivate04.f90

-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ program main
1414
!$omp parallel num_threads(x1)
1515
!$omp end parallel
1616

17-
!ERROR: COPYPRIVATE clause is not allowed on the OMP SINGLE directive, use it on OMP END SINGLE directive
1817
!$omp single copyprivate(x2, /blk1/)
1918
!$omp end single
2019

llvm/include/llvm/Frontend/OpenMP/OMP.td

+3-1
Original file line numberDiff line numberDiff line change
@@ -1023,9 +1023,11 @@ def OMP_Single : Directive<"single"> {
10231023
VersionedClause<OMPC_Allocate>,
10241024
VersionedClause<OMPC_CopyPrivate>,
10251025
VersionedClause<OMPC_FirstPrivate>,
1026-
VersionedClause<OMPC_NoWait>,
10271026
VersionedClause<OMPC_Private>,
10281027
];
1028+
let allowedOnceClauses = [
1029+
VersionedClause<OMPC_NoWait>,
1030+
];
10291031
let association = AS_Block;
10301032
let category = CA_Executable;
10311033
}

0 commit comments

Comments
 (0)