-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[Flang][OpenMP][Sema] Adding parsing and semantic support for scan directive. #102792
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
Conversation
@llvm/pr-subscribers-flang-parser @llvm/pr-subscribers-flang-fir-hlfir Author: Anchu Rajendran S (anchuraj) Changes
Patch is 28.78 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/102792.diff 13 Files Affected:
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index bbde77c14f36a1..52cc15d4ac6946 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -2189,6 +2189,9 @@ static void genOMPDispatch(lower::AbstractConverter &converter,
case llvm::omp::Directive::OMPD_parallel:
genStandaloneParallel(converter, symTable, semaCtx, eval, loc, queue, item);
break;
+ case llvm::omp::Directive::OMPD_scan:
+ TODO(loc, "Unhandled directive " + llvm::omp::getOpenMPDirectiveName(dir));
+ break;
case llvm::omp::Directive::OMPD_section:
llvm_unreachable("genOMPDispatch: OMPD_section");
// Lowered in the enclosing genSectionsOp.
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 52789d6e5f0f6b..7c10099fe0da8b 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -267,6 +267,8 @@ TYPE_PARSER(
construct<OmpClause>(construct<OmpClause::DynamicAllocators>()) ||
"ENTER" >> construct<OmpClause>(construct<OmpClause::Enter>(
parenthesized(Parser<OmpObjectList>{}))) ||
+ "EXCLUSIVE" >> construct<OmpClause>(construct<OmpClause::Exclusive>(
+ parenthesized(Parser<OmpObjectList>{}))) ||
"FILTER" >> construct<OmpClause>(construct<OmpClause::Filter>(
parenthesized(scalarIntExpr))) ||
"FINAL" >> construct<OmpClause>(construct<OmpClause::Final>(
@@ -286,6 +288,8 @@ TYPE_PARSER(
"IF" >> construct<OmpClause>(construct<OmpClause::If>(
parenthesized(Parser<OmpIfClause>{}))) ||
"INBRANCH" >> construct<OmpClause>(construct<OmpClause::Inbranch>()) ||
+ "INCLUSIVE" >> construct<OmpClause>(construct<OmpClause::Inclusive>(
+ parenthesized(Parser<OmpObjectList>{}))) ||
"IS_DEVICE_PTR" >> construct<OmpClause>(construct<OmpClause::IsDevicePtr>(
parenthesized(Parser<OmpObjectList>{}))) ||
"LASTPRIVATE" >> construct<OmpClause>(construct<OmpClause::Lastprivate>(
@@ -481,6 +485,7 @@ TYPE_PARSER(sourced(construct<OpenMPFlushConstruct>(verbatim("FLUSH"_tok),
TYPE_PARSER(sourced(construct<OmpSimpleStandaloneDirective>(first(
"BARRIER" >> pure(llvm::omp::Directive::OMPD_barrier),
"ORDERED" >> pure(llvm::omp::Directive::OMPD_ordered),
+ "SCAN" >> pure(llvm::omp::Directive::OMPD_scan),
"TARGET ENTER DATA" >> pure(llvm::omp::Directive::OMPD_target_enter_data),
"TARGET EXIT DATA" >> pure(llvm::omp::Directive::OMPD_target_exit_data),
"TARGET UPDATE" >> pure(llvm::omp::Directive::OMPD_target_update),
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 2511a5dda9d095..f252512a41f655 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2295,6 +2295,9 @@ class UnparseVisitor {
case llvm::omp::Directive::OMPD_barrier:
Word("BARRIER ");
break;
+ case llvm::omp::Directive::OMPD_scan:
+ Word("SCAN ");
+ break;
case llvm::omp::Directive::OMPD_taskwait:
Word("TASKWAIT ");
break;
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 50840898438c78..f38b929fb78b3d 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -550,17 +550,21 @@ void OmpStructureChecker::CheckSIMDNest(const parser::OpenMPConstruct &c) {
}
}
},
- [&](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;
+ [&](const parser::OpenMPStandaloneConstruct &c) {
+ if(const auto &simpleConstruct = std::get_if<parser::OpenMPSimpleStandaloneConstruct>(&c.u)) {
+ const auto &dir{
+ std::get<parser::OmpSimpleStandaloneDirective>(simpleConstruct->t)};
+ if (dir.v == llvm::omp::Directive::OMPD_ordered) {
+ const auto &clauses{
+ std::get<parser::OmpClauseList>(simpleConstruct->t)};
+ for (const auto &clause : clauses.v) {
+ if (std::get_if<parser::OmpClause::Simd>(&clause.u)) {
+ eligibleSIMD = true;
+ break;
+ }
}
+ } else if(dir.v == llvm::omp::Directive::OMPD_scan) {
+ eligibleSIMD = true;
}
}
},
@@ -571,6 +575,7 @@ void OmpStructureChecker::CheckSIMDNest(const parser::OpenMPConstruct &c) {
const auto &beginDir{
std::get<parser::OmpLoopDirective>(beginLoopDir.t)};
if ((beginDir.v == llvm::omp::Directive::OMPD_simd) ||
+ (beginDir.v == llvm::omp::Directive::OMPD_parallel_do_simd) ||
(beginDir.v == llvm::omp::Directive::OMPD_do_simd)) {
eligibleSIMD = true;
}
@@ -586,8 +591,9 @@ void OmpStructureChecker::CheckSIMDNest(const parser::OpenMPConstruct &c) {
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);
+ "the `SIMD` construct, the `SCAN` construct and the `ORDERED` "
+ "construct "
+ "with the `SIMD` clause."_err_en_US);
}
}
@@ -2531,6 +2537,8 @@ void OmpStructureChecker::CheckReductionModifier(
switch (dirCtx.directive) {
case llvm::omp::Directive::OMPD_do: // worksharing-loop
case llvm::omp::Directive::OMPD_do_simd: // worksharing-loop simd
+ case llvm::omp::Directive::OMPD_parallel_do_simd: // worksharing-parallel-loop
+ // simd
case llvm::omp::Directive::OMPD_simd: // "simd"
break;
default:
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index d635a7b8b7874f..018352f072a112 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -1578,9 +1578,11 @@ bool OmpAttributeVisitor::Pre(
const parser::OpenMPSimpleStandaloneConstruct &x) {
const auto &standaloneDir{
std::get<parser::OmpSimpleStandaloneDirective>(x.t)};
+ const auto &parentContext{GetContextIf()};
switch (standaloneDir.v) {
case llvm::omp::Directive::OMPD_barrier:
case llvm::omp::Directive::OMPD_ordered:
+ case llvm::omp::Directive::OMPD_scan:
case llvm::omp::Directive::OMPD_target_enter_data:
case llvm::omp::Directive::OMPD_target_exit_data:
case llvm::omp::Directive::OMPD_target_update:
@@ -1591,6 +1593,20 @@ bool OmpAttributeVisitor::Pre(
default:
break;
}
+ if (standaloneDir.v == llvm::omp::Directive::OMPD_scan) {
+ if ((std::get<parser::OmpClauseList>(x.t).v.size() != 1)) {
+ context_.Say(standaloneDir.source,
+ "Exactly one of `exclusive` or `inclusive` clause is expected"_err_en_US);
+ }
+ if (!parentContext ||
+ (llvm::omp::getDirectiveAssociation(parentContext->directive) !=
+ llvm::omp::Association::Loop)) {
+ context_.Say(standaloneDir.source,
+ "Orphaned `omp scan` directives are prohibited; perhaps you forgot to "
+ "enclose the directive in to a worksharing loop, a worksharing loop "
+ "simd or a simd directive."_err_en_US);
+ }
+ }
ClearDataSharingAttributeObjects();
return true;
}
diff --git a/flang/test/Parser/OpenMP/scan.f90 b/flang/test/Parser/OpenMP/scan.f90
new file mode 100644
index 00000000000000..a6e23ac9404882
--- /dev/null
+++ b/flang/test/Parser/OpenMP/scan.f90
@@ -0,0 +1,40 @@
+! RUN: %flang_fc1 -fdebug-unparse -fopenmp %s | FileCheck --ignore-case %s
+! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s
+
+! Check for parsing scan directive
+subroutine test_scan_inclusive()
+ implicit none
+ integer, parameter :: n = 100
+ integer a(n), b(n)
+ integer x, k
+
+ ! initialization
+ x = 0
+ do k = 1, n
+ a(k) = k
+ end do
+
+ ! a(k) is included in the computation of producing results in b(k)
+ !$omp parallel do simd reduction(inscan,+: x)
+ do k = 1, n
+ x = x + a(k)
+ !PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPSimpleStandaloneConstruct
+ !PARSE-TREE-NEXT: OmpSimpleStandaloneDirective -> llvm::omp::Directive = scan
+ !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Inclusive -> OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x'
+ !CHECK: !$omp scan inclusive(x)
+ !$omp scan inclusive(x)
+ b(k) = x
+ end do
+
+ ! a(k) is not included in the computation of producing results in b(k)
+ !$omp parallel do simd reduction(inscan,+: x)
+ do k = 1, n
+ b(k) = x
+ !PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPSimpleStandaloneConstruct
+ !PARSE-TREE-NEXT: OmpSimpleStandaloneDirective -> llvm::omp::Directive = scan
+ !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Exclusive -> OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x'
+ !CHECK: !$omp scan exclusive(x)
+ !$omp scan exclusive(x)
+ x = x + a(k)
+ end do
+end subroutine
diff --git a/flang/test/Semantics/OpenMP/do05.f90 b/flang/test/Semantics/OpenMP/do05.f90
index c0f240db57b65b..24844f9fe4f62a 100644
--- a/flang/test/Semantics/OpenMP/do05.f90
+++ b/flang/test/Semantics/OpenMP/do05.f90
@@ -39,7 +39,7 @@ program omp_do
if( i == 5 ) then
cycle
end if
- !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 only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` 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
@@ -70,7 +70,7 @@ program omp_do
if( i == 3 ) then
cycle
end if
- !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 only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` 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
@@ -93,7 +93,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: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` 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
@@ -116,7 +116,7 @@ program omp_do
!$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: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` 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/OpenMP/nested-barrier.f90 b/flang/test/Semantics/OpenMP/nested-barrier.f90
index aae283229e330d..ed13c98539c93c 100644
--- a/flang/test/Semantics/OpenMP/nested-barrier.f90
+++ b/flang/test/Semantics/OpenMP/nested-barrier.f90
@@ -17,7 +17,7 @@ program omp_nest_barrier
!$omp do simd
do i = 1, 10
k = k + 1
- !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 only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause.
!ERROR: `BARRIER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`,`CRITICAL`, `ORDERED`, `ATOMIC` or `MASTER` region.
!$omp barrier
j = j -1
@@ -34,7 +34,7 @@ program omp_nest_barrier
!$omp parallel do simd
do i = 1, 10
k = k + 1
- !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 only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause.
!ERROR: `BARRIER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`,`CRITICAL`, `ORDERED`, `ATOMIC` or `MASTER` region.
!$omp barrier
j = j -1
diff --git a/flang/test/Semantics/OpenMP/nested-master.f90 b/flang/test/Semantics/OpenMP/nested-master.f90
index 069de67cafae28..0a5118bb947550 100644
--- a/flang/test/Semantics/OpenMP/nested-master.f90
+++ b/flang/test/Semantics/OpenMP/nested-master.f90
@@ -64,7 +64,7 @@ program omp_nest_master
do i = 1, 10
k = k + 1
!WARNING: OpenMP directive 'master' has been deprecated, please use 'masked' instead.
- !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 only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause.
!ERROR: `MASTER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`, or `ATOMIC` region.
!$omp master
j = j -1
diff --git a/flang/test/Semantics/OpenMP/nested-simd.f90 b/flang/test/Semantics/OpenMP/nested-simd.f90
index 4149b6d97e9dc7..c9fb90cdeceb25 100644
--- a/flang/test/Semantics/OpenMP/nested-simd.f90
+++ b/flang/test/Semantics/OpenMP/nested-simd.f90
@@ -40,7 +40,7 @@ SUBROUTINE NESTED_BAD(N)
!$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.
+ !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, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause.
!ERROR: TEAMS region can only be strictly nested within the implicit parallel region or TARGET region
!$omp teams
DO K = 1,N
@@ -58,25 +58,25 @@ SUBROUTINE NESTED_BAD(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.
+ !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, the `SCAN` 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.
+ !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, the `SCAN` 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: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` 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.
+ !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, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause.
!$OMP PARALLEL DO
DO J = 1,N
A(J) = J
@@ -91,26 +91,26 @@ SUBROUTINE NESTED_BAD(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.
+ !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, the `SCAN` 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.
+ !ERROR:...
[truncated]
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
9a045a6
to
5bf0f84
Compare
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.
Thank you Anchu, I just have one remaining concern. I hope someone else can share their thoughts on it and get this work merged soon.
@@ -198,6 +198,10 @@ class DirectiveStructureChecker : public virtual BaseChecker { | |||
ClauseMapTy clauseInfo; | |||
std::list<C> actualClauses; | |||
std::list<C> crtGroup; | |||
std::set<std::string> usedInScanDirective; |
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.
After our private discussion, I'm not against representing symbols as strings as part of this PR and address not matching symbols as part of a separate PR, if there's actually a semantics bug causing this mismatch.
What I'm still not sure about is having these new OpenMP-specific properties added to the generic DirectiveContext
. Perhaps someone from the OpenACC side can chime in on this (@clementval, @jeanPerier).
std::get_if<parser::OmpClause::Reduction>(&clause.u)}) { | ||
const auto &maybeModifier{ | ||
std::get<std::optional<ReductionModifier>>(reductionClause->v.t)}; | ||
if (maybeModifier && *maybeModifier == ReductionModifier::Inscan) { |
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.
Nit: Reduce the nesting level to make code easier to follow.
if (maybeModifier && *maybeModifier == ReductionModifier::Inscan) { | |
if (!maybeModifier || *maybeModifier != ReductionModifier::Inscan) | |
continue; |
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.
Generally frontend code in flang is more nested.
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 prefer to go with the existing approach as personally I feel it more readable. Please let me know if there are suggestions otherwise.
const parser::OmpObjectList &x) { | ||
for (const auto &ompObj : x.v) { | ||
auto checkScanSymbolInReduction = [&](const parser::Name *name) { | ||
if (name->symbol) { |
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.
Nit: I think an early return here instead of adding a nesting level helps readability.
if (name->symbol) { | |
if (!name->symbol) | |
return; |
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.
Generally frontend code in flang is nested.
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.
A few comments.
"Orphaned `omp scan` directives are prohibited; perhaps you forgot " | ||
"to enclose the directive in to a worksharing loop, a worksharing " | ||
"loop simd or a simd directive."_err_en_US); |
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.
"Orphaned `omp scan` directives are prohibited; perhaps you forgot " | |
"to enclose the directive in to a worksharing loop, a worksharing " | |
"loop simd or a simd directive."_err_en_US); | |
"Orphaned SCAN directives are prohibited, perhaps you forgot " | |
"to enclose the directive in a WORKSHARING LOOP, a WORKSHARING " | |
"LOOP SIMD or a SIMD directive."_err_en_US); |
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.
Changed
const parser::OpenMPSimpleStandaloneConstruct &x) { | ||
if (std::get<parser::OmpClauseList>(x.t).v.size() != 1) { | ||
context_.Say(x.source, | ||
"Exactly one of `exclusive` or `inclusive` clause is expected"_err_en_US); |
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.
"Exactly one of `exclusive` or `inclusive` clause is expected"_err_en_US); | |
"Exactly one of EXCLUSIVE or INCLUSIVE clause is expected"_err_en_US); |
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.
Changed
"List item %s must appear in 'inclusive' or " | ||
"'exclusive' clause of an " | ||
"enclosed scan directive"_err_en_US, |
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.
"List item %s must appear in 'inclusive' or " | |
"'exclusive' clause of an " | |
"enclosed scan directive"_err_en_US, | |
"List item %s must appear in INCLUSIVE or " | |
"EXCLUSIVE clause of an " | |
"enclosed SCAN directive"_err_en_US, |
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.
Changed
std::get_if<parser::OmpClause::Reduction>(&clause.u)}) { | ||
const auto &maybeModifier{ | ||
std::get<std::optional<ReductionModifier>>(reductionClause->v.t)}; | ||
if (maybeModifier && *maybeModifier == ReductionModifier::Inscan) { |
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.
Generally frontend code in flang is more nested.
const parser::OmpObjectList &x) { | ||
for (const auto &ompObj : x.v) { | ||
auto checkScanSymbolInReduction = [&](const parser::Name *name) { | ||
if (name->symbol) { |
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.
Generally frontend code in flang is nested.
"List item %s must appear in 'reduction' clause " | ||
"with the 'inscan' modifier of the parent " | ||
"directive"_err_en_US, |
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.
"List item %s must appear in 'reduction' clause " | |
"with the 'inscan' modifier of the parent " | |
"directive"_err_en_US, | |
"List item %s must appear in a REDUCTION clause " | |
"with the INSCAN modifier of the parent " | |
"directive"_err_en_US, |
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.
Changed
@@ -198,6 +198,10 @@ class DirectiveStructureChecker : public virtual BaseChecker { | |||
ClauseMapTy clauseInfo; | |||
std::list<C> actualClauses; | |||
std::list<C> crtGroup; | |||
std::set<std::string> usedInScanDirective; |
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 agree with @skatrak's initial comments. We should try to keep the OpenMP specific data-structures in the OpenMP specific checkers. And if we can use the symbol that would be great. If the reduction creates a new private symbol, that should be the symbol bound to the inclusive or exclusive clause of the SCAN directive.
81f37c2
to
9e4724c
Compare
|
||
bool Pre(const parser::OmpClause::Inclusive &x) { | ||
const auto &objectList{x.v}; | ||
ResolveNames(objectList); |
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.
Can you add a debug-dump-symbols test?
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 have added a new flag and dumped the symbols in a new test.
void OmpStructureChecker::CheckBarrierNesting( | ||
const parser::OpenMPSimpleStandaloneConstruct &x) { | ||
// A barrier region may not be `closely nested` inside a worksharing, loop, | ||
// task, taskloop, critical, ordered, atomic, or master region. | ||
// TODO: Expand the check to include `LOOP` construct as well when it is | ||
// supported. | ||
if (GetContext().directive == llvm::omp::Directive::OMPD_barrier) { |
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.
Was this check for barrier not required?
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.
@@ -2865,4 +2879,19 @@ void OmpAttributeVisitor::IssueNonConformanceWarning( | |||
context_.Say(source, "%s"_warn_en_US, warnStr); | |||
} | |||
} | |||
void OmpAttributeVisitor::ResolveNames(const parser::OmpObjectList &objList) { |
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 am a bit surprised that we needed to define this function. Was the resolution of names not handled anywhere else?
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.
Thank you for pointing this out. I believe I was not understanding the existing code well. I made use of ResolveOmpObjList
function now.
…eck-omp-structure
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.
LGTM. Nice work.
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.
LGTM, thanks!
…support (#114737) Scan directive allows to specify scan reductions within an worksharing loop, worksharing loop simd or simd directive which should have an `InScan` modifier associated with it. This change adds the mlir support for the same. Related PR: [Parsing and Semantic Support for scan](llvm/llvm-project#102792)
Scan
directive specifies the scan computations. This PR adds the initial parsing and semantic support in flang.scan
is parsed as a stand alone directive as done in clang.