Skip to content

Commit 9a045a6

Browse files
committed
Adding parsing support for scan directive.
1 parent 00a4042 commit 9a045a6

File tree

13 files changed

+176
-76
lines changed

13 files changed

+176
-76
lines changed

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2199,6 +2199,9 @@ static void genOMPDispatch(lower::AbstractConverter &converter,
21992199
case llvm::omp::Directive::OMPD_parallel:
22002200
genStandaloneParallel(converter, symTable, semaCtx, eval, loc, queue, item);
22012201
break;
2202+
case llvm::omp::Directive::OMPD_scan:
2203+
TODO(loc, "Unhandled directive " + llvm::omp::getOpenMPDirectiveName(dir));
2204+
break;
22022205
case llvm::omp::Directive::OMPD_section:
22032206
llvm_unreachable("genOMPDispatch: OMPD_section");
22042207
// Lowered in the enclosing genSectionsOp.

flang/lib/Parser/openmp-parsers.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,8 @@ TYPE_PARSER(
267267
construct<OmpClause>(construct<OmpClause::DynamicAllocators>()) ||
268268
"ENTER" >> construct<OmpClause>(construct<OmpClause::Enter>(
269269
parenthesized(Parser<OmpObjectList>{}))) ||
270+
"EXCLUSIVE" >> construct<OmpClause>(construct<OmpClause::Exclusive>(
271+
parenthesized(Parser<OmpObjectList>{}))) ||
270272
"FILTER" >> construct<OmpClause>(construct<OmpClause::Filter>(
271273
parenthesized(scalarIntExpr))) ||
272274
"FINAL" >> construct<OmpClause>(construct<OmpClause::Final>(
@@ -286,6 +288,8 @@ TYPE_PARSER(
286288
"IF" >> construct<OmpClause>(construct<OmpClause::If>(
287289
parenthesized(Parser<OmpIfClause>{}))) ||
288290
"INBRANCH" >> construct<OmpClause>(construct<OmpClause::Inbranch>()) ||
291+
"INCLUSIVE" >> construct<OmpClause>(construct<OmpClause::Inclusive>(
292+
parenthesized(Parser<OmpObjectList>{}))) ||
289293
"IS_DEVICE_PTR" >> construct<OmpClause>(construct<OmpClause::IsDevicePtr>(
290294
parenthesized(Parser<OmpObjectList>{}))) ||
291295
"LASTPRIVATE" >> construct<OmpClause>(construct<OmpClause::Lastprivate>(
@@ -481,6 +485,7 @@ TYPE_PARSER(sourced(construct<OpenMPFlushConstruct>(verbatim("FLUSH"_tok),
481485
TYPE_PARSER(sourced(construct<OmpSimpleStandaloneDirective>(first(
482486
"BARRIER" >> pure(llvm::omp::Directive::OMPD_barrier),
483487
"ORDERED" >> pure(llvm::omp::Directive::OMPD_ordered),
488+
"SCAN" >> pure(llvm::omp::Directive::OMPD_scan),
484489
"TARGET ENTER DATA" >> pure(llvm::omp::Directive::OMPD_target_enter_data),
485490
"TARGET EXIT DATA" >> pure(llvm::omp::Directive::OMPD_target_exit_data),
486491
"TARGET UPDATE" >> pure(llvm::omp::Directive::OMPD_target_update),

flang/lib/Parser/unparse.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2295,6 +2295,9 @@ class UnparseVisitor {
22952295
case llvm::omp::Directive::OMPD_barrier:
22962296
Word("BARRIER ");
22972297
break;
2298+
case llvm::omp::Directive::OMPD_scan:
2299+
Word("SCAN ");
2300+
break;
22982301
case llvm::omp::Directive::OMPD_taskwait:
22992302
Word("TASKWAIT ");
23002303
break;

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

Lines changed: 63 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -532,62 +532,71 @@ void OmpStructureChecker::CheckSIMDNest(const parser::OpenMPConstruct &c) {
532532
// current context yet.
533533
// TODO: Check for declare simd regions.
534534
bool eligibleSIMD{false};
535-
common::visit(Fortran::common::visitors{
536-
// Allow `!$OMP ORDERED SIMD`
537-
[&](const parser::OpenMPBlockConstruct &c) {
538-
const auto &beginBlockDir{
539-
std::get<parser::OmpBeginBlockDirective>(c.t)};
540-
const auto &beginDir{
541-
std::get<parser::OmpBlockDirective>(beginBlockDir.t)};
542-
if (beginDir.v == llvm::omp::Directive::OMPD_ordered) {
543-
const auto &clauses{
544-
std::get<parser::OmpClauseList>(beginBlockDir.t)};
545-
for (const auto &clause : clauses.v) {
546-
if (std::get_if<parser::OmpClause::Simd>(&clause.u)) {
547-
eligibleSIMD = true;
548-
break;
549-
}
550-
}
551-
}
552-
},
553-
[&](const parser::OpenMPSimpleStandaloneConstruct &c) {
554-
const auto &dir{
555-
std::get<parser::OmpSimpleStandaloneDirective>(c.t)};
556-
if (dir.v == llvm::omp::Directive::OMPD_ordered) {
557-
const auto &clauses{
558-
std::get<parser::OmpClauseList>(c.t)};
559-
for (const auto &clause : clauses.v) {
560-
if (std::get_if<parser::OmpClause::Simd>(&clause.u)) {
561-
eligibleSIMD = true;
562-
break;
563-
}
564-
}
565-
}
566-
},
567-
// Allowing SIMD construct
568-
[&](const parser::OpenMPLoopConstruct &c) {
569-
const auto &beginLoopDir{
570-
std::get<parser::OmpBeginLoopDirective>(c.t)};
571-
const auto &beginDir{
572-
std::get<parser::OmpLoopDirective>(beginLoopDir.t)};
573-
if ((beginDir.v == llvm::omp::Directive::OMPD_simd) ||
574-
(beginDir.v == llvm::omp::Directive::OMPD_do_simd)) {
575-
eligibleSIMD = true;
576-
}
577-
},
578-
[&](const parser::OpenMPAtomicConstruct &c) {
579-
// Allow `!$OMP ATOMIC`
580-
eligibleSIMD = true;
581-
},
582-
[&](const auto &c) {},
583-
},
535+
common::visit(
536+
Fortran::common::visitors{
537+
// Allow `!$OMP ORDERED SIMD`
538+
[&](const parser::OpenMPBlockConstruct &c) {
539+
const auto &beginBlockDir{
540+
std::get<parser::OmpBeginBlockDirective>(c.t)};
541+
const auto &beginDir{
542+
std::get<parser::OmpBlockDirective>(beginBlockDir.t)};
543+
if (beginDir.v == llvm::omp::Directive::OMPD_ordered) {
544+
const auto &clauses{
545+
std::get<parser::OmpClauseList>(beginBlockDir.t)};
546+
for (const auto &clause : clauses.v) {
547+
if (std::get_if<parser::OmpClause::Simd>(&clause.u)) {
548+
eligibleSIMD = true;
549+
break;
550+
}
551+
}
552+
}
553+
},
554+
[&](const parser::OpenMPStandaloneConstruct &c) {
555+
if (const auto &simpleConstruct =
556+
std::get_if<parser::OpenMPSimpleStandaloneConstruct>(
557+
&c.u)) {
558+
const auto &dir{std::get<parser::OmpSimpleStandaloneDirective>(
559+
simpleConstruct->t)};
560+
if (dir.v == llvm::omp::Directive::OMPD_ordered) {
561+
const auto &clauses{
562+
std::get<parser::OmpClauseList>(simpleConstruct->t)};
563+
for (const auto &clause : clauses.v) {
564+
if (std::get_if<parser::OmpClause::Simd>(&clause.u)) {
565+
eligibleSIMD = true;
566+
break;
567+
}
568+
}
569+
} else if (dir.v == llvm::omp::Directive::OMPD_scan) {
570+
eligibleSIMD = true;
571+
}
572+
}
573+
},
574+
// Allowing SIMD construct
575+
[&](const parser::OpenMPLoopConstruct &c) {
576+
const auto &beginLoopDir{
577+
std::get<parser::OmpBeginLoopDirective>(c.t)};
578+
const auto &beginDir{
579+
std::get<parser::OmpLoopDirective>(beginLoopDir.t)};
580+
if ((beginDir.v == llvm::omp::Directive::OMPD_simd) ||
581+
(beginDir.v == llvm::omp::Directive::OMPD_parallel_do_simd) ||
582+
(beginDir.v == llvm::omp::Directive::OMPD_do_simd)) {
583+
eligibleSIMD = true;
584+
}
585+
},
586+
[&](const parser::OpenMPAtomicConstruct &c) {
587+
// Allow `!$OMP ATOMIC`
588+
eligibleSIMD = true;
589+
},
590+
[&](const auto &c) {},
591+
},
584592
c.u);
585593
if (!eligibleSIMD) {
586594
context_.Say(parser::FindSourceLocation(c),
587595
"The only OpenMP constructs that can be encountered during execution "
588596
"of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, "
589-
"the `SIMD` construct and the `ORDERED` construct with the `SIMD` "
590-
"clause."_err_en_US);
597+
"the `SIMD` construct, the `SCAN` construct and the `ORDERED` "
598+
"construct "
599+
"with the `SIMD` clause."_err_en_US);
591600
}
592601
}
593602

@@ -2531,6 +2540,9 @@ void OmpStructureChecker::CheckReductionModifier(
25312540
switch (dirCtx.directive) {
25322541
case llvm::omp::Directive::OMPD_do: // worksharing-loop
25332542
case llvm::omp::Directive::OMPD_do_simd: // worksharing-loop simd
2543+
case llvm::omp::Directive::
2544+
OMPD_parallel_do_simd: // worksharing-parallel-loop
2545+
// simd
25342546
case llvm::omp::Directive::OMPD_simd: // "simd"
25352547
break;
25362548
default:

flang/lib/Semantics/resolve-directives.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1578,9 +1578,11 @@ bool OmpAttributeVisitor::Pre(
15781578
const parser::OpenMPSimpleStandaloneConstruct &x) {
15791579
const auto &standaloneDir{
15801580
std::get<parser::OmpSimpleStandaloneDirective>(x.t)};
1581+
const auto &parentContext{GetContextIf()};
15811582
switch (standaloneDir.v) {
15821583
case llvm::omp::Directive::OMPD_barrier:
15831584
case llvm::omp::Directive::OMPD_ordered:
1585+
case llvm::omp::Directive::OMPD_scan:
15841586
case llvm::omp::Directive::OMPD_target_enter_data:
15851587
case llvm::omp::Directive::OMPD_target_exit_data:
15861588
case llvm::omp::Directive::OMPD_target_update:
@@ -1591,6 +1593,20 @@ bool OmpAttributeVisitor::Pre(
15911593
default:
15921594
break;
15931595
}
1596+
if (standaloneDir.v == llvm::omp::Directive::OMPD_scan) {
1597+
if ((std::get<parser::OmpClauseList>(x.t).v.size() != 1)) {
1598+
context_.Say(standaloneDir.source,
1599+
"Exactly one of `exclusive` or `inclusive` clause is expected"_err_en_US);
1600+
}
1601+
if (!parentContext ||
1602+
(llvm::omp::getDirectiveAssociation(parentContext->directive) !=
1603+
llvm::omp::Association::Loop)) {
1604+
context_.Say(standaloneDir.source,
1605+
"Orphaned `omp scan` directives are prohibited; perhaps you forgot "
1606+
"to enclose the directive in to a worksharing loop, a worksharing "
1607+
"loop simd or a simd directive."_err_en_US);
1608+
}
1609+
}
15941610
ClearDataSharingAttributeObjects();
15951611
return true;
15961612
}

flang/test/Parser/OpenMP/scan.f90

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
! RUN: %flang_fc1 -fdebug-unparse -fopenmp %s | FileCheck --ignore-case %s
2+
! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s
3+
4+
! Check for parsing scan directive
5+
subroutine test_scan_inclusive()
6+
implicit none
7+
integer, parameter :: n = 100
8+
integer a(n), b(n)
9+
integer x, k
10+
11+
! initialization
12+
x = 0
13+
do k = 1, n
14+
a(k) = k
15+
end do
16+
17+
! a(k) is included in the computation of producing results in b(k)
18+
!$omp parallel do simd reduction(inscan,+: x)
19+
do k = 1, n
20+
x = x + a(k)
21+
!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPSimpleStandaloneConstruct
22+
!PARSE-TREE-NEXT: OmpSimpleStandaloneDirective -> llvm::omp::Directive = scan
23+
!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Inclusive -> OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x'
24+
!CHECK: !$omp scan inclusive(x)
25+
!$omp scan inclusive(x)
26+
b(k) = x
27+
end do
28+
29+
! a(k) is not included in the computation of producing results in b(k)
30+
!$omp parallel do simd reduction(inscan,+: x)
31+
do k = 1, n
32+
b(k) = x
33+
!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPSimpleStandaloneConstruct
34+
!PARSE-TREE-NEXT: OmpSimpleStandaloneDirective -> llvm::omp::Directive = scan
35+
!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Exclusive -> OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x'
36+
!CHECK: !$omp scan exclusive(x)
37+
!$omp scan exclusive(x)
38+
x = x + a(k)
39+
end do
40+
end subroutine

flang/test/Semantics/OpenMP/do05.f90

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ program omp_do
3939
if( i == 5 ) then
4040
cycle
4141
end if
42-
!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.
42+
!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.
4343
!ERROR: A worksharing region may not be closely nested inside a worksharing, explicit task, taskloop, critical, ordered, atomic, or master region
4444
!$omp single
4545
do j=1,10
@@ -70,7 +70,7 @@ program omp_do
7070
if( i == 3 ) then
7171
cycle
7272
end if
73-
!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.
73+
!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.
7474
!ERROR: A worksharing region may not be closely nested inside a worksharing, explicit task, taskloop, critical, ordered, atomic, or master region
7575
!$omp single
7676
do j=1,10
@@ -93,7 +93,7 @@ program omp_do
9393

9494
!$omp target parallel do simd
9595
do i=1,10
96-
!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.
96+
!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.
9797
!ERROR: A worksharing region may not be closely nested inside a worksharing, explicit task, taskloop, critical, ordered, atomic, or master region
9898
!$omp single
9999
do j=1,10
@@ -116,7 +116,7 @@ program omp_do
116116

117117
!$omp target teams distribute parallel do simd
118118
do i=1,10
119-
!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.
119+
!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.
120120
!ERROR: A worksharing region may not be closely nested inside a worksharing, explicit task, taskloop, critical, ordered, atomic, or master region
121121
!$omp single
122122
do j=1,10

flang/test/Semantics/OpenMP/nested-barrier.f90

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ program omp_nest_barrier
1717
!$omp do simd
1818
do i = 1, 10
1919
k = k + 1
20-
!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.
20+
!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.
2121
!ERROR: `BARRIER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`,`CRITICAL`, `ORDERED`, `ATOMIC` or `MASTER` region.
2222
!$omp barrier
2323
j = j -1
@@ -34,7 +34,7 @@ program omp_nest_barrier
3434
!$omp parallel do simd
3535
do i = 1, 10
3636
k = k + 1
37-
!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.
37+
!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.
3838
!ERROR: `BARRIER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`,`CRITICAL`, `ORDERED`, `ATOMIC` or `MASTER` region.
3939
!$omp barrier
4040
j = j -1

flang/test/Semantics/OpenMP/nested-master.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ program omp_nest_master
6464
do i = 1, 10
6565
k = k + 1
6666
!WARNING: OpenMP directive 'master' has been deprecated, please use 'masked' instead.
67-
!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.
67+
!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.
6868
!ERROR: `MASTER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`, or `ATOMIC` region.
6969
!$omp master
7070
j = j -1

0 commit comments

Comments
 (0)