Skip to content

Commit 39665d9

Browse files
Add Semantic check for Flang OpenMP 4.5 - 2.7.1 Do Loop restrictions on single directive and firstprivate clause.
Semantic checks added to check the worksharing 'single' region closely nested inside a worksharing 'do' region. And also to check whether the 'do' iteration variable is a variable in 'Firstprivate' clause. Files: check-directive-structure.h check-omp-structure.h check-omp-structure.cpp Testcases: omp-do01-positivecase.f90 omp-do01.f90 omp-do05-positivecase.f90 omp-do05.f90 Reviewed by: Kiran Chandramohan @kiranchandramohan , Valentin Clement @clementval Differential Revision: https://reviews.llvm.org/D93205
1 parent 7dc3575 commit 39665d9

File tree

7 files changed

+133
-23
lines changed

7 files changed

+133
-23
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,11 @@ class DirectiveStructureChecker : public virtual BaseChecker {
139139
const PC *clause{nullptr};
140140
std::multimap<C, const PC *> clauseInfo;
141141
std::list<C> actualClauses;
142+
Symbol *loopIV{nullptr};
142143
};
143144

145+
void SetLoopIv(Symbol *symbol) { GetContext().loopIV = symbol; }
146+
144147
// back() is the top of the stack
145148
DirectiveContext &GetContext() {
146149
CHECK(!dirContext_.empty());
@@ -160,6 +163,7 @@ class DirectiveStructureChecker : public virtual BaseChecker {
160163
GetContext().allowedExclusiveClauses = {};
161164
GetContext().requiredClauses = {};
162165
GetContext().clauseInfo = {};
166+
GetContext().loopIV = {nullptr};
163167
}
164168

165169
void SetContextDirectiveSource(const parser::CharBlock &directive) {

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

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,22 @@ void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) {
9393
llvm::omp::Directive::OMPD_master});
9494
PushContextAndClauseSets(beginDir.source, llvm::omp::Directive::OMPD_do);
9595
}
96+
SetLoopInfo(x);
97+
}
98+
const parser::Name OmpStructureChecker::GetLoopIndex(
99+
const parser::DoConstruct *x) {
100+
using Bounds = parser::LoopControl::Bounds;
101+
return std::get<Bounds>(x->GetLoopControl()->u).name.thing;
102+
}
103+
void OmpStructureChecker::SetLoopInfo(const parser::OpenMPLoopConstruct &x) {
104+
if (const auto &loopConstruct{
105+
std::get<std::optional<parser::DoConstruct>>(x.t)}) {
106+
const parser::DoConstruct *loop{&*loopConstruct};
107+
if (loop && loop->IsDoNormal()) {
108+
const parser::Name &itrVal{GetLoopIndex(loop)};
109+
SetLoopIv(itrVal.symbol);
110+
}
111+
}
96112
}
97113

98114
void OmpStructureChecker::Leave(const parser::OpenMPLoopConstruct &) {
@@ -124,6 +140,13 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) {
124140

125141
CheckMatching<parser::OmpBlockDirective>(beginDir, endDir);
126142

143+
// TODO: This check needs to be extended while implementing nesting of regions
144+
// checks.
145+
if (beginDir.v == llvm::omp::Directive::OMPD_single) {
146+
HasInvalidWorksharingNesting(
147+
beginDir.source, {llvm::omp::Directive::OMPD_do});
148+
}
149+
127150
PushContextAndClauseSets(beginDir.source, beginDir.v);
128151
CheckNoBranching(block, beginDir.v, beginDir.source);
129152
}
@@ -401,7 +424,6 @@ CHECK_SIMPLE_CLAUSE(Copyprivate, OMPC_copyprivate)
401424
CHECK_SIMPLE_CLAUSE(Default, OMPC_default)
402425
CHECK_SIMPLE_CLAUSE(Device, OMPC_device)
403426
CHECK_SIMPLE_CLAUSE(Final, OMPC_final)
404-
CHECK_SIMPLE_CLAUSE(Firstprivate, OMPC_firstprivate)
405427
CHECK_SIMPLE_CLAUSE(From, OMPC_from)
406428
CHECK_SIMPLE_CLAUSE(Inbranch, OMPC_inbranch)
407429
CHECK_SIMPLE_CLAUSE(IsDevicePtr, OMPC_is_device_ptr)
@@ -487,6 +509,23 @@ void OmpStructureChecker::CheckIsVarPartOfAnotherVar(
487509
ompObject.u);
488510
}
489511
}
512+
void OmpStructureChecker::Enter(const parser::OmpClause::Firstprivate &x) {
513+
CheckAllowed(llvm::omp::Clause::OMPC_firstprivate);
514+
CheckIsLoopIvPartOfClause(llvmOmpClause::OMPC_firstprivate, x.v);
515+
}
516+
void OmpStructureChecker::CheckIsLoopIvPartOfClause(
517+
llvmOmpClause clause, const parser::OmpObjectList &ompObjectList) {
518+
for (const auto &ompObject : ompObjectList.v) {
519+
if (const parser::Name * name{parser::Unwrap<parser::Name>(ompObject)}) {
520+
if (name->symbol == GetContext().loopIV) {
521+
context_.Say(name->source,
522+
"DO iteration variable %s is not allowed in %s clause."_err_en_US,
523+
name->ToString(),
524+
parser::ToUpperCaseLetters(getClauseName(clause).str()));
525+
}
526+
}
527+
}
528+
}
490529
// Following clauses have a seperate node in parse-tree.h.
491530
// Atomic-clause
492531
CHECK_SIMPLE_PARSER_CLAUSE(OmpAtomicRead, OMPC_read)

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ class OmpStructureChecker
8888
#include "llvm/Frontend/OpenMP/OMP.inc"
8989
) {
9090
}
91+
using llvmOmpClause = const llvm::omp::Clause;
9192

9293
void Enter(const parser::OpenMPConstruct &);
9394
void Enter(const parser::OpenMPLoopConstruct &);
@@ -207,6 +208,11 @@ class OmpStructureChecker
207208
const parser::OmpObjectList &, const llvm::omp::Clause);
208209
void GetSymbolsInObjectList(
209210
const parser::OmpObjectList &, std::vector<const Symbol *> &);
211+
212+
const parser::Name GetLoopIndex(const parser::DoConstruct *x);
213+
void SetLoopInfo(const parser::OpenMPLoopConstruct &x);
214+
void CheckIsLoopIvPartOfClause(
215+
llvmOmpClause clause, const parser::OmpObjectList &ompObjectList);
210216
};
211217
} // namespace Fortran::semantics
212218
#endif // FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
! RUN: %S/test_symbols.sh %s %t %f18 -fopenmp
2+
! OpenMP Version 4.5
3+
! 2.7.1 Loop Construct
4+
! The loop iteration variable may not appear in a firstprivate directive.
5+
! A positive case
6+
7+
!DEF: /omp_do MainProgram
8+
program omp_do
9+
!DEF: /omp_do/i ObjectEntity INTEGER(4)
10+
integer i
11+
12+
!$omp do firstprivate(k)
13+
!DEF: /omp_do/Block1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
14+
do i=1,10
15+
print *, "Hello"
16+
end do
17+
!$omp end do
18+
19+
end program omp_do

flang/test/Semantics/omp-do01.f90

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
! RUN: %S/test_errors.sh %s %t %f18 -fopenmp
2-
! XFAIL: *
3-
42
! OpenMP Version 4.5
53
! 2.7.1 Loop Construct
6-
! collapse(n) where n > num of loops
4+
! The loop iteration variable may not appear in a firstprivate directive.
75

86
program omp_do
97
integer i, j, k
108

11-
!ERROR: Not enough do loops for collapsed !$OMP DO
12-
!$omp do collapse(2)
9+
!ERROR: DO iteration variable i is not allowed in FIRSTPRIVATE clause.
10+
!$omp do firstprivate(k,i)
1311
do i = 1, 10
14-
print *, "hello"
12+
do j = 1, 10
13+
print *, "Hello"
14+
end do
1515
end do
1616
!$omp end do
1717

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
! RUN: %S/test_symbols.sh %s %t %f18 -fopenmp
2+
! OpenMP Version 4.5
3+
! 2.7.1 Loop Construct restrictions on single directive.
4+
! A positive case
5+
6+
!DEF: /omp_do MainProgram
7+
program omp_do
8+
!DEF: /omp_do/i ObjectEntity INTEGER(4)
9+
!DEF: /omp_do/n ObjectEntity INTEGER(4)
10+
integer i,n
11+
!$omp parallel
12+
!DEF: /omp_do/Block1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
13+
do i=1,10
14+
!$omp single
15+
print *, "hello"
16+
!$omp end single
17+
end do
18+
!$omp end parallel
19+
20+
!$omp parallel default(shared)
21+
!$omp do
22+
!DEF: /omp_do/Block2/Block1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
23+
!REF: /omp_do/n
24+
do i=1,n
25+
!$omp parallel
26+
!$omp single
27+
!DEF: /work EXTERNAL (Subroutine) ProcEntity
28+
!REF: /omp_do/Block2/Block1/i
29+
call work(i, 1)
30+
!$omp end single
31+
!$omp end parallel
32+
end do
33+
!$omp end do
34+
!$omp end parallel
35+
36+
end program omp_do

flang/test/Semantics/omp-do05.f90

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,32 @@
11
! RUN: %S/test_errors.sh %s %t %f18 -fopenmp
2-
! XFAIL: *
3-
42
! OpenMP Version 4.5
5-
! 2.7.1 Loop Construct
6-
! chunk_size must be a loop invariant integer expression
7-
! with a positive value.
3+
! 2.7.1 Loop Construct restrictions on single directive.
4+
85

96
program omp_do
10-
integer i, j, k
11-
integer :: a(10), b(10)
12-
a = 10
13-
j = 0
147

15-
!ERROR: INTEGER expression of SCHEDULE clause chunk_size must be positive
16-
!$omp do schedule(static, -1)
17-
do i = 1, 10
18-
j = j + 1
19-
b(i) = a(i) * 2.0
8+
integer n
9+
integer i,j
10+
!$omp do
11+
do i=1,10
12+
!ERROR: A worksharing region may not be closely nested inside a worksharing, explicit task, taskloop, critical, ordered, atomic, or master region
13+
!$omp single
14+
do j=1,10
15+
print *,"hello"
16+
end do
17+
!$omp end single
2018
end do
2119
!$omp end do
2220

23-
print *, j
24-
print *, b
21+
!$omp parallel default(shared)
22+
!$omp do
23+
do i = 1, n
24+
!ERROR: A worksharing region may not be closely nested inside a worksharing, explicit task, taskloop, critical, ordered, atomic, or master region
25+
!$omp single
26+
call work(i, 1)
27+
!$omp end single
28+
end do
29+
!$omp end do
30+
!$omp end parallel
2531

2632
end program omp_do

0 commit comments

Comments
 (0)