Skip to content

Commit 7dc18a6

Browse files
committed
[flang][OpenMP] Added semantic checks for hint clause
This patch improves semantic checks for hint clause. It checks "hint-expression is a constant expression that evaluates to a scalar value with kind `omp_sync_hint_kind` and a value that is a valid synchronization hint." Reviewed By: peixin Differential Revision: https://reviews.llvm.org/D127615
1 parent a56b76d commit 7dc18a6

File tree

4 files changed

+275
-0
lines changed

4 files changed

+275
-0
lines changed

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

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,48 @@ void OmpStructureChecker::CheckPredefinedAllocatorRestriction(
314314
}
315315
}
316316

317+
template <class D>
318+
void OmpStructureChecker::CheckHintClause(
319+
D *leftOmpClauseList, D *rightOmpClauseList) {
320+
auto checkForValidHintClause = [&](const D *clauseList) {
321+
for (const auto &clause : clauseList->v) {
322+
const Fortran::parser::OmpClause *ompClause = nullptr;
323+
if constexpr (std::is_same_v<D,
324+
const Fortran::parser::OmpAtomicClauseList>) {
325+
ompClause = std::get_if<Fortran::parser::OmpClause>(&clause.u);
326+
if (!ompClause)
327+
continue;
328+
} else if constexpr (std::is_same_v<D,
329+
const Fortran::parser::OmpClauseList>) {
330+
ompClause = &clause;
331+
}
332+
if (const Fortran::parser::OmpClause::Hint *
333+
hintClause{
334+
std::get_if<Fortran::parser::OmpClause::Hint>(&ompClause->u)}) {
335+
std::optional<std::int64_t> hintValue = GetIntValue(hintClause->v);
336+
if (hintValue && hintValue.value() >= 0) {
337+
if((hintValue.value() & 0xC) == 0xC /*`omp_sync_hint_nonspeculative` and `omp_lock_hint_speculative`*/
338+
|| (hintValue.value() & 0x3) == 0x3 /*`omp_sync_hint_uncontended` and omp_sync_hint_contended*/ )
339+
context_.Say(clause.source,
340+
"Hint clause value "
341+
"is not a valid OpenMP synchronization value"_err_en_US);
342+
} else {
343+
context_.Say(clause.source,
344+
"Hint clause must have non-negative constant "
345+
"integer expression"_err_en_US);
346+
}
347+
}
348+
}
349+
};
350+
351+
if (leftOmpClauseList) {
352+
checkForValidHintClause(leftOmpClauseList);
353+
}
354+
if (rightOmpClauseList) {
355+
checkForValidHintClause(rightOmpClauseList);
356+
}
357+
}
358+
317359
void OmpStructureChecker::Enter(const parser::OpenMPConstruct &x) {
318360
// Simd Construct with Ordered Construct Nesting check
319361
// We cannot use CurrentDirectiveIsNested() here because
@@ -1277,6 +1319,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPCriticalConstruct &x) {
12771319
parser::MessageFormattedText{
12781320
"Hint clause other than omp_sync_hint_none cannot be specified for an unnamed CRITICAL directive"_err_en_US});
12791321
}
1322+
CheckHintClause<const parser::OmpClauseList>(&ompClause, nullptr);
12801323
}
12811324

12821325
void OmpStructureChecker::Leave(const parser::OpenMPCriticalConstruct &) {
@@ -1580,6 +1623,9 @@ void OmpStructureChecker::Enter(const parser::OpenMPAtomicConstruct &x) {
15801623
CheckAtomicMemoryOrderClause(
15811624
&std::get<parser::OmpAtomicClauseList>(atomicConstruct.t),
15821625
nullptr);
1626+
CheckHintClause<const parser::OmpAtomicClauseList>(
1627+
&std::get<parser::OmpAtomicClauseList>(atomicConstruct.t),
1628+
nullptr);
15831629
},
15841630
[&](const parser::OmpAtomicUpdate &atomicUpdate) {
15851631
const auto &dir{std::get<parser::Verbatim>(atomicUpdate.t)};
@@ -1591,13 +1637,18 @@ void OmpStructureChecker::Enter(const parser::OpenMPAtomicConstruct &x) {
15911637
.statement);
15921638
CheckAtomicMemoryOrderClause(
15931639
&std::get<0>(atomicUpdate.t), &std::get<2>(atomicUpdate.t));
1640+
CheckHintClause<const parser::OmpAtomicClauseList>(
1641+
&std::get<0>(atomicUpdate.t), &std::get<2>(atomicUpdate.t));
15941642
},
15951643
[&](const auto &atomicConstruct) {
15961644
const auto &dir{std::get<parser::Verbatim>(atomicConstruct.t)};
15971645
PushContextAndClauseSets(
15981646
dir.source, llvm::omp::Directive::OMPD_atomic);
15991647
CheckAtomicMemoryOrderClause(&std::get<0>(atomicConstruct.t),
16001648
&std::get<2>(atomicConstruct.t));
1649+
CheckHintClause<const parser::OmpAtomicClauseList>(
1650+
&std::get<0>(atomicConstruct.t),
1651+
&std::get<2>(atomicConstruct.t));
16011652
},
16021653
},
16031654
x.u);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ class OmpStructureChecker
268268
void EnterDirectiveNest(const int index) { directiveNest_[index]++; }
269269
void ExitDirectiveNest(const int index) { directiveNest_[index]--; }
270270
int GetDirectiveNest(const int index) { return directiveNest_[index]; }
271+
template <typename D> void CheckHintClause(D *, D *);
271272

272273
enum directiveNestType {
273274
SIMDNest,
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp
2+
! Semantic checks on hint clauses, as they appear on atomic constructs
3+
4+
program sample
5+
use omp_lib
6+
integer :: x, y
7+
logical :: z
8+
real :: k
9+
integer :: p(1)
10+
integer, parameter :: a = 1
11+
!$omp atomic hint(1) write
12+
y = 2
13+
14+
!$omp atomic read hint(2)
15+
y = x
16+
17+
!ERROR: Hint clause value is not a valid OpenMP synchronization value
18+
!$omp atomic hint(3)
19+
y = y + 10
20+
21+
!$omp atomic update hint(5)
22+
y = x
23+
24+
!ERROR: Hint clause value is not a valid OpenMP synchronization value
25+
!$omp atomic hint(7) capture
26+
y = x
27+
x = y
28+
!$omp end atomic
29+
30+
!ERROR: Hint clause must have non-negative constant integer expression
31+
!ERROR: Must be a constant value
32+
!$omp atomic update hint(x)
33+
y = y * 1
34+
35+
!$omp atomic read hint(4)
36+
y = x
37+
38+
!$omp atomic hint(8)
39+
x = x * y
40+
41+
!$omp atomic write hint(omp_sync_hint_uncontended)
42+
x = 10 * y
43+
44+
!$omp atomic hint(omp_lock_hint_speculative)
45+
x = y + x
46+
47+
!ERROR: Hint clause must have non-negative constant integer expression
48+
!ERROR: Must be a constant value
49+
!$omp atomic hint(omp_sync_hint_uncontended + omp_sync_hint) read
50+
y = x
51+
52+
!$omp atomic hint(omp_sync_hint_nonspeculative)
53+
y = y * 9
54+
55+
!$omp atomic hint(omp_sync_hint_none) read
56+
y = x
57+
58+
!$omp atomic read hint(omp_sync_hint_uncontended + omp_lock_hint_speculative)
59+
y = x
60+
61+
!$omp atomic hint(omp_lock_hint_nonspeculative + omp_lock_hint_uncontended)
62+
x = x * y
63+
64+
!$omp atomic write hint(omp_lock_hint_contended + omp_sync_hint_speculative)
65+
x = 10 * y
66+
67+
!$omp atomic hint(omp_lock_hint_contended + omp_sync_hint_nonspeculative)
68+
x = y + x
69+
70+
!ERROR: Hint clause value is not a valid OpenMP synchronization value
71+
!$omp atomic hint(omp_sync_hint_uncontended + omp_sync_hint_contended) read
72+
y = x
73+
74+
!ERROR: Hint clause value is not a valid OpenMP synchronization value
75+
!$omp atomic hint(omp_sync_hint_nonspeculative + omp_lock_hint_speculative)
76+
y = y * 9
77+
78+
!ERROR: Hint clause must have non-negative constant integer expression
79+
!$omp atomic hint(1.0) read
80+
y = x
81+
82+
!ERROR: Hint clause must have non-negative constant integer expression
83+
!ERROR: Operands of + must be numeric; have LOGICAL(4) and INTEGER(4)
84+
!$omp atomic hint(z + omp_sync_hint_nonspeculative) read
85+
y = x
86+
87+
!ERROR: Hint clause must have non-negative constant integer expression
88+
!ERROR: Must be a constant value
89+
!$omp atomic hint(k + omp_sync_hint_speculative) read
90+
y = x
91+
92+
!ERROR: Hint clause must have non-negative constant integer expression
93+
!ERROR: Must be a constant value
94+
!$omp atomic hint(p(1) + omp_sync_hint_uncontended) write
95+
x = 10 * y
96+
97+
!$omp atomic write hint(a)
98+
x = y + x
99+
100+
!$omp atomic hint(abs(-1)) write
101+
x = 7
102+
103+
!$omp atomic hint(omp_sync_hint_uncontended + omp_sync_hint_uncontended + omp_sync_hint_speculative) write
104+
x = 7
105+
end program
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp
2+
! Semantic checks on hint clauses, as they appear on critical construct
3+
4+
program sample
5+
use omp_lib
6+
integer :: y
7+
logical :: z
8+
real :: k
9+
integer :: p(1)
10+
11+
!$omp critical (name) hint(1)
12+
y = 2
13+
!$omp end critical (name)
14+
15+
!$omp critical (name) hint(2)
16+
y = 2
17+
!$omp end critical (name)
18+
19+
!ERROR: Hint clause value is not a valid OpenMP synchronization value
20+
!$omp critical (name) hint(3)
21+
y = 2
22+
!$omp end critical (name)
23+
24+
!$omp critical (name) hint(5)
25+
y = 2
26+
!$omp end critical (name)
27+
28+
!ERROR: Hint clause value is not a valid OpenMP synchronization value
29+
!$omp critical (name) hint(7)
30+
y = 2
31+
!$omp end critical (name)
32+
33+
!ERROR: Hint clause must have non-negative constant integer expression
34+
!ERROR: Must be a constant value
35+
!$omp critical (name) hint(x)
36+
y = 2
37+
!$omp end critical (name)
38+
39+
!$omp critical (name) hint(4)
40+
y = 2
41+
!$omp end critical (name)
42+
43+
!$omp critical (name) hint(8)
44+
y = 2
45+
!$omp end critical (name)
46+
47+
!$omp critical (name) hint(omp_sync_hint_uncontended)
48+
y = 2
49+
!$omp end critical (name)
50+
51+
!$omp critical (name) hint(omp_lock_hint_speculative)
52+
y = 2
53+
!$omp end critical (name)
54+
55+
!ERROR: Hint clause must have non-negative constant integer expression
56+
!ERROR: Must be a constant value
57+
!$omp critical (name) hint(omp_sync_hint_uncontended + omp_sync_hint)
58+
y = 2
59+
!$omp end critical (name)
60+
61+
!$omp critical (name) hint(omp_sync_hint_nonspeculative)
62+
y = 2
63+
!$omp end critical (name)
64+
65+
!$omp critical (name) hint(omp_sync_hint_none)
66+
y = 2
67+
!$omp end critical (name)
68+
69+
!$omp critical (name) hint(omp_sync_hint_uncontended + omp_lock_hint_speculative)
70+
y = 2
71+
!$omp end critical (name)
72+
73+
!$omp critical (name) hint(omp_lock_hint_nonspeculative + omp_lock_hint_uncontended)
74+
y = 2
75+
!$omp end critical (name)
76+
77+
!$omp critical (name) hint(omp_lock_hint_contended + omp_sync_hint_speculative)
78+
y = 2
79+
!$omp end critical (name)
80+
81+
!$omp critical (name) hint(omp_lock_hint_contended + omp_sync_hint_nonspeculative)
82+
y = 2
83+
!$omp end critical (name)
84+
85+
!ERROR: Hint clause value is not a valid OpenMP synchronization value
86+
!$omp critical (name) hint(omp_sync_hint_uncontended + omp_sync_hint_contended)
87+
y = 2
88+
!$omp end critical (name)
89+
90+
!ERROR: Hint clause value is not a valid OpenMP synchronization value
91+
!$omp critical (name) hint(omp_sync_hint_nonspeculative + omp_lock_hint_speculative)
92+
y = 2
93+
!$omp end critical (name)
94+
95+
!ERROR: Hint clause must have non-negative constant integer expression
96+
!$omp critical (name) hint(1.0)
97+
y = 2
98+
!$omp end critical (name)
99+
100+
!ERROR: Hint clause must have non-negative constant integer expression
101+
!ERROR: Operands of + must be numeric; have LOGICAL(4) and INTEGER(4)
102+
!$omp critical (name) hint(z + omp_sync_hint_nonspeculative)
103+
y = 2
104+
!$omp end critical (name)
105+
106+
!ERROR: Hint clause must have non-negative constant integer expression
107+
!ERROR: Must be a constant value
108+
!$omp critical (name) hint(k + omp_sync_hint_speculative)
109+
y = 2
110+
!$omp end critical (name)
111+
112+
!ERROR: Hint clause must have non-negative constant integer expression
113+
!ERROR: Must be a constant value
114+
!$omp critical (name) hint(p(1) + omp_sync_hint_uncontended)
115+
y = 2
116+
!$omp end critical (name)
117+
end program
118+

0 commit comments

Comments
 (0)