-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[Flang][OpenMP] Allow copyprivate and nowait on the directive clauses #127769
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Flang][OpenMP] Allow copyprivate and nowait on the directive clauses #127769
Conversation
Issue: - Single construct used to throw semantic error for copyprivate and nowiat clause when used in the single directive. - Also, the Nowait and copyprivate restrictions has be removed from OpenMP 6.0 Fix: - The above mentioned semantic error was valid until OpenMP 5.1. - From OpenMP 5.2, copyprivate and nowait is allowed in both clause and end-clause 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 ```
@llvm/pr-subscribers-flang-semantics @llvm/pr-subscribers-flang-openmp Author: Thirumalai Shaktivel (Thirumalai-Shaktivel) ChangesIssue:
Fix:
From Reference guide (OpenMP 5.2, 2.10.2):
Towards: #110008 Full diff: https://github.com/llvm/llvm-project/pull/127769.diff 4 Files Affected:
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 1d6fe6c8d4249..93f71c1951658 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -1203,6 +1203,40 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) {
deviceConstructFound_ = true;
}
+ unsigned version{context_.langOptions().OpenMPVersion};
+ if (version >= 52 &&
+ GetContext().directive == llvm::omp::Directive::OMPD_single) {
+ bool foundCopyPrivate{false};
+ bool foundNowait{false};
+ parser::CharBlock NowaitSource{""};
+ auto catchCopyPrivateNowaitClauses = [&](const auto &dir) {
+ for (auto &clause : std::get<parser::OmpClauseList>(dir.t).v) {
+ if (clause.Id() == llvm::omp::Clause::OMPC_copyprivate) {
+ if (foundCopyPrivate) {
+ context_.Say(clause.source,
+ "At most one COPYPRIVATE clause can appear on the SINGLE directive"_err_en_US);
+ } else {
+ foundCopyPrivate = true;
+ }
+ } else if (clause.Id() == llvm::omp::Clause::OMPC_nowait) {
+ if (foundNowait) {
+ context_.Say(clause.source,
+ "At most one NOWAIT clause can appear on the SINGLE directive"_err_en_US);
+ } else {
+ foundNowait = true;
+ NowaitSource = clause.source;
+ }
+ }
+ }
+ };
+ catchCopyPrivateNowaitClauses(beginBlockDir);
+ catchCopyPrivateNowaitClauses(endBlockDir);
+ if (version == 52 && foundCopyPrivate && foundNowait) {
+ context_.Say(NowaitSource,
+ "NOWAIT clause must not be used with COPYPRIVATE clause on the SINGLE directive"_err_en_US);
+ }
+ }
+
switch (beginDir.v) {
case llvm::omp::Directive::OMPD_target:
if (CheckTargetBlockOnlyTeams(block)) {
@@ -2853,7 +2887,8 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
CheckMultListItems();
// 2.7.3 Single Construct Restriction
- if (GetContext().directive == llvm::omp::Directive::OMPD_end_single) {
+ if (context_.langOptions().OpenMPVersion < 52 &&
+ GetContext().directive == llvm::omp::Directive::OMPD_end_single) {
CheckNotAllowedIfClause(
llvm::omp::Clause::OMPC_copyprivate, {llvm::omp::Clause::OMPC_nowait});
}
@@ -3481,14 +3516,16 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Private &x) {
void OmpStructureChecker::Enter(const parser::OmpClause::Nowait &x) {
CheckAllowedClause(llvm::omp::Clause::OMPC_nowait);
- if (llvm::omp::noWaitClauseNotAllowedSet.test(GetContext().directive)) {
+ if (context_.langOptions().OpenMPVersion < 52 &&
+ llvm::omp::noWaitClauseNotAllowedSet.test(GetContext().directive)) {
+ std::string dirName{
+ parser::ToUpperCaseLetters(GetContext().directiveSource.ToString())};
context_.Say(GetContext().clauseSource,
"%s clause is not allowed on the OMP %s directive,"
- " use it on OMP END %s directive "_err_en_US,
+ " use it on OMP END %s directive or %s"_err_en_US,
parser::ToUpperCaseLetters(
getClauseName(llvm::omp::Clause::OMPC_nowait).str()),
- parser::ToUpperCaseLetters(GetContext().directiveSource.ToString()),
- parser::ToUpperCaseLetters(GetContext().directiveSource.ToString()));
+ dirName, dirName, TryVersion(52));
}
}
@@ -4220,14 +4257,16 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Copyprivate &x) {
CheckIntentInPointer(symbols, llvm::omp::Clause::OMPC_copyprivate);
CheckCopyingPolymorphicAllocatable(
symbols, llvm::omp::Clause::OMPC_copyprivate);
- if (GetContext().directive == llvm::omp::Directive::OMPD_single) {
+ if (context_.langOptions().OpenMPVersion < 52 &&
+ GetContext().directive == llvm::omp::Directive::OMPD_single) {
+ std::string dirName{
+ parser::ToUpperCaseLetters(GetContext().directiveSource.ToString())};
context_.Say(GetContext().clauseSource,
"%s clause is not allowed on the OMP %s directive,"
- " use it on OMP END %s directive "_err_en_US,
+ " use it on OMP END %s directive or %s"_err_en_US,
parser::ToUpperCaseLetters(
getClauseName(llvm::omp::Clause::OMPC_copyprivate).str()),
- parser::ToUpperCaseLetters(GetContext().directiveSource.ToString()),
- parser::ToUpperCaseLetters(GetContext().directiveSource.ToString()));
+ dirName, dirName, TryVersion(52));
}
}
diff --git a/flang/test/Semantics/OpenMP/clause-validity01.f90 b/flang/test/Semantics/OpenMP/clause-validity01.f90
index e8114154a809b..0349a5a760753 100644
--- a/flang/test/Semantics/OpenMP/clause-validity01.f90
+++ b/flang/test/Semantics/OpenMP/clause-validity01.f90
@@ -330,7 +330,7 @@
!$omp parallel
b = 1
!ERROR: LASTPRIVATE clause is not allowed on the SINGLE directive
- !ERROR: NOWAIT clause is not allowed on the OMP SINGLE directive, use it on OMP END SINGLE directive
+ !ERROR: NOWAIT clause is not allowed on the OMP SINGLE directive, use it on OMP END SINGLE directive or try -fopenmp-version=52
!$omp single private(a) lastprivate(c) nowait
a = 3.14
!ERROR: Clause NOWAIT is not allowed if clause COPYPRIVATE appears on the END SINGLE directive
@@ -351,7 +351,7 @@
a = 1.0
!ERROR: COPYPRIVATE clause is not allowed on the END WORKSHARE directive
!$omp end workshare nowait copyprivate(a)
- !ERROR: NOWAIT clause is not allowed on the OMP WORKSHARE directive, use it on OMP END WORKSHARE directive
+ !ERROR: NOWAIT clause is not allowed on the OMP WORKSHARE directive, use it on OMP END WORKSHARE directive or try -fopenmp-version=52
!$omp workshare nowait
!$omp end workshare
!$omp end parallel
@@ -420,7 +420,7 @@
!$omp parallel
!ERROR: No ORDERED clause with a parameter can be specified on the DO SIMD directive
!ERROR: NOGROUP clause is not allowed on the DO SIMD directive
- !ERROR: NOWAIT clause is not allowed on the OMP DO SIMD directive, use it on OMP END DO SIMD directive
+ !ERROR: NOWAIT clause is not allowed on the OMP DO SIMD directive, use it on OMP END DO SIMD directive or try -fopenmp-version=52
!$omp do simd ordered(2) NOGROUP nowait
do i = 1, N
do j = 1, N
diff --git a/flang/test/Semantics/OpenMP/single03.f90 b/flang/test/Semantics/OpenMP/single03.f90
new file mode 100644
index 0000000000000..bc7647b66e39f
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/single03.f90
@@ -0,0 +1,54 @@
+! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp -fopenmp-version=52
+!
+! OpenMP Version 5.2
+!
+! 2.10.2 single Construct
+! Copyprivate and Nowait clauses are allowed in both clause and end clause
+
+subroutine omp_single
+ integer, save :: i
+ integer :: j
+ i = 10; j = 11
+
+ !ERROR: COPYPRIVATE variable 'i' is not PRIVATE or THREADPRIVATE in outer context
+ !ERROR: NOWAIT clause must not be used with COPYPRIVATE clause on the SINGLE directive
+ !$omp single copyprivate(i) nowait
+ print *, "omp single", i
+ !$omp end single
+
+ !$omp parallel private(i)
+ !$omp single copyprivate(i)
+ print *, "omp single", i
+ !$omp end single
+ !$omp end parallel
+
+ !$omp parallel
+ !ERROR: NOWAIT clause must not be used with COPYPRIVATE clause on the SINGLE directive
+ !$omp single nowait
+ print *, "omp single", i
+ !ERROR: COPYPRIVATE variable 'i' is not PRIVATE or THREADPRIVATE in outer context
+ !$omp end single copyprivate(i)
+
+ !ERROR: COPYPRIVATE variable 'i' is not PRIVATE or THREADPRIVATE in outer context
+ !$omp single copyprivate(i)
+ print *, "omp single", i
+ !ERROR: NOWAIT clause must not be used with COPYPRIVATE clause on the SINGLE directive
+ !$omp end single nowait
+
+ !ERROR: COPYPRIVATE variable 'j' may not appear on a PRIVATE or FIRSTPRIVATE clause on a SINGLE construct
+ !$omp single private(j) copyprivate(j)
+ print *, "omp single", j
+ !ERROR: At most one COPYPRIVATE clause can appear on the SINGLE directive
+ !ERROR: COPYPRIVATE variable 'j' may not appear on a PRIVATE or FIRSTPRIVATE clause on a SINGLE construct
+ !$omp end single copyprivate(j)
+
+ !$omp single nowait
+ print *, "omp single", j
+ !ERROR: At most one NOWAIT clause can appear on the SINGLE directive
+ !$omp end single nowait
+ !$omp end parallel
+
+ !$omp single nowait
+ print *, "omp single", i
+ !$omp end single
+end subroutine omp_single
diff --git a/flang/test/Semantics/OpenMP/threadprivate04.f90 b/flang/test/Semantics/OpenMP/threadprivate04.f90
index 3d8c7fb8de8fa..db23cdb06ed96 100644
--- a/flang/test/Semantics/OpenMP/threadprivate04.f90
+++ b/flang/test/Semantics/OpenMP/threadprivate04.f90
@@ -14,7 +14,7 @@ program main
!$omp parallel num_threads(x1)
!$omp end parallel
- !ERROR: COPYPRIVATE clause is not allowed on the OMP SINGLE directive, use it on OMP END SINGLE directive
+ !ERROR: COPYPRIVATE clause is not allowed on the OMP SINGLE directive, use it on OMP END SINGLE directive or try -fopenmp-version=52
!$omp single copyprivate(x2, /blk1/)
!$omp end single
|
Would it make sense to allow this usage irrespective of the standard? |
My two cents. If flang supports both forms, it'd better to disallow mixing two forms in a single construct. There is if copyprivate is specified on the single directive, there shouldn't be anything on the end single. I guess that is less confusing. |
Yes, that makes sense, I will make the required changes soon. @kkwli, I have added a check to catch the duplicate usage of the clauses, see: https://github.com/llvm/llvm-project/pull/127769/files#diff-69cb55326952c1dffb012c3c2691d8ddc1e65bf9500fd41821f1196d04216bf9R39-R48. I hope, it looks good. |
6d30850
to
6cbaf66
Compare
Ready for review! |
auto catchCopyPrivateNowaitClauses = [&](const auto &dir) { | ||
for (auto &clause : std::get<parser::OmpClauseList>(dir.t).v) { | ||
if (clause.Id() == llvm::omp::Clause::OMPC_copyprivate) { | ||
if (foundCopyPrivate) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This condition is incorrect and needs to be tied to the list-items in the copyprivate
clause. Several copyprivate
clauses can be at the directive, as long as they have different list-items.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I missed this, thanks for noticing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
I would argue that this should be warning instead of a hard error. The code would not be incorrect according to the OpenMP API and therefore should be accepted, and the warning should tell the user to be consistent. |
I fine with lowering to a warning. |
Changes: - Throw error for repeated list items in the copyprivate clause - Throw warnings for repeated use of copyprivate and nowait in the end directive
✅ With the latest revision this PR passed the C/C++ code formatter. |
2638d3b
to
292203e
Compare
@mjklemm, I made the required changes and added some more test cases, do you see anything missing there. program single
!$omp single nowait
print *, x
!$omp end single copyprivate(x, y) nowait
end program Error: $ flang x.f90 -fopenmp
flang-21: warning: OpenMP support in flang is still experimental [-Wexperimental-option]
error: Semantic errors in x.f90
./x.f90:2:18: error: NOWAIT clause must not be used with COPYPRIVATE clause on the SINGLE directive
!$omp single nowait
^^^^^^
./x.f90:4:40: warning: NOWAIT clause is already used on the SINGLE directive
!$omp end single copyprivate(x, y) nowait
^^^^^^ Is the error and the warning correct and expected? |
I think this is a bug. I do not see any restriction in the OpenMP specification that would disallow NOWAIT when COPYPRIVATE is present. However, the compiler should produce an error that you have NOWAIT at both the begin and end directive. Only for the COPYPRIVATE clause the diagnostic should be a warning. I consider NOWAIT at both directives an actual error, because NOWAIT is a unique clause as per [5.2:308:10]. |
Thanks for the review!
Maybe I think I need to fix the error message there. I actually altered the previous error message, it used to throw the following: error: Semantic errors in <source>
<source>:7:7: error: Clause NOWAIT is not allowed if clause COPYPRIVATE appears on the END SINGLE directive
!$omp end single copyprivate(x) nowait
^^^^^^^^^^ Let me know, what needs to be done here.
This seems right, I will make the required changes soon. |
Done, now I get: $ flang-new x.f90 -fopenmp
flang-21: warning: OpenMP support in flang is still experimental [-Wexperimental-option]
error: Semantic errors in x.f90
./x.f90:2:18: error: NOWAIT clause must not be used with COPYPRIVATE clause on the SINGLE directive
!$omp single nowait
^^^^^^
./x.f90:4:40: error: At most one NOWAIT clause can appear on the SINGLE directive
!$omp end single copyprivate(x, y) nowait
^^^^^^ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this LGTM.
Thanks for the review! |
…llvm#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: llvm#110008
Issue:
Fix:
From Reference guide (OpenMP 5.2, 2.10.2):
Towards: #110008