Skip to content

Commit 6fa6600

Browse files
[flang][OpenMP]Add parsing and semantics support for ATOMIC COMPARE
This adds a minimalistic implementation of parsing and semantics for the ATOMIC COMPARE feature from OpenMP 5.1. There is no lowering, just a TODO for that part. Some of the Semantics is also just a comment explaining that more is needed.
1 parent 2c63e6d commit 6fa6600

File tree

11 files changed

+195
-2
lines changed

11 files changed

+195
-2
lines changed

flang/include/flang/Parser/dump-parse-tree.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,7 @@ class ParseTreeDumper {
484484
NODE(parser, OmpAtomicCapture)
485485
NODE(OmpAtomicCapture, Stmt1)
486486
NODE(OmpAtomicCapture, Stmt2)
487+
NODE(parser, OmpAtomicCompare)
487488
NODE(parser, OmpAtomicRead)
488489
NODE(parser, OmpAtomicUpdate)
489490
NODE(parser, OmpAtomicWrite)

flang/include/flang/Parser/parse-tree.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4126,6 +4126,15 @@ struct OmpAtomicCapture {
41264126
t;
41274127
};
41284128

4129+
// ATOMCI COMPARE (OpenMP 5.1, Spec: 15.8.4)
4130+
struct OmpAtomicCompare {
4131+
TUPLE_CLASS_BOILERPLATE(OmpAtomicCompare);
4132+
CharBlock source;
4133+
std::tuple<OmpAtomicClauseList, Verbatim, OmpAtomicClauseList,
4134+
Statement<AssignmentStmt>, std::optional<OmpEndAtomic>>
4135+
t;
4136+
};
4137+
41294138
// ATOMIC
41304139
struct OmpAtomic {
41314140
TUPLE_CLASS_BOILERPLATE(OmpAtomic);
@@ -4138,11 +4147,11 @@ struct OmpAtomic {
41384147
// 2.17.7 atomic ->
41394148
// ATOMIC [atomic-clause-list] atomic-construct [atomic-clause-list] |
41404149
// ATOMIC [atomic-clause-list]
4141-
// atomic-construct -> READ | WRITE | UPDATE | CAPTURE
4150+
// atomic-construct -> READ | WRITE | UPDATE | CAPTURE | COMPARE
41424151
struct OpenMPAtomicConstruct {
41434152
UNION_CLASS_BOILERPLATE(OpenMPAtomicConstruct);
41444153
std::variant<OmpAtomicRead, OmpAtomicWrite, OmpAtomicCapture, OmpAtomicUpdate,
4145-
OmpAtomic>
4154+
OmpAtomicCompare, OmpAtomic>
41464155
u;
41474156
};
41484157

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2896,6 +2896,10 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
28962896
parser::OmpAtomicClauseList>(
28972897
converter, atomicCapture, loc);
28982898
},
2899+
[&](const parser::OmpAtomicCompare &atomicCompare) {
2900+
mlir::Location loc = converter.genLocation(atomicCompare.source);
2901+
TODO(loc, "OpenMP atomic compare");
2902+
},
28992903
},
29002904
atomicConstruct.u);
29012905
}

flang/lib/Parser/openmp-parsers.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,12 @@ TYPE_PARSER("ATOMIC" >>
912912
Parser<OmpAtomicClauseList>{} / endOmpLine, statement(assignmentStmt),
913913
statement(assignmentStmt), Parser<OmpEndAtomic>{} / endOmpLine)))
914914

915+
TYPE_PARSER("ATOMIC" >>
916+
sourced(construct<OmpAtomicCompare>(
917+
Parser<OmpAtomicClauseList>{} / maybe(","_tok), verbatim("COMPARE"_tok),
918+
Parser<OmpAtomicClauseList>{} / endOmpLine, statement(assignmentStmt),
919+
maybe(Parser<OmpEndAtomic>{} / endOmpLine))))
920+
915921
// OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] UPDATE [MEMORY-ORDER-CLAUSE-LIST]
916922
TYPE_PARSER("ATOMIC" >>
917923
sourced(construct<OmpAtomicUpdate>(
@@ -934,6 +940,7 @@ TYPE_PARSER("ATOMIC" >>
934940
// Atomic Construct
935941
TYPE_PARSER(construct<OpenMPAtomicConstruct>(Parser<OmpAtomicRead>{}) ||
936942
construct<OpenMPAtomicConstruct>(Parser<OmpAtomicCapture>{}) ||
943+
construct<OpenMPAtomicConstruct>(Parser<OmpAtomicCompare>{}) ||
937944
construct<OpenMPAtomicConstruct>(Parser<OmpAtomicWrite>{}) ||
938945
construct<OpenMPAtomicConstruct>(Parser<OmpAtomicUpdate>{}) ||
939946
construct<OpenMPAtomicConstruct>(Parser<OmpAtomic>{}))

flang/lib/Parser/unparse.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2520,6 +2520,16 @@ class UnparseVisitor {
25202520
Word("!$OMP END ATOMIC\n");
25212521
EndOpenMP();
25222522
}
2523+
void Unparse(const OmpAtomicCompare &x) {
2524+
BeginOpenMP();
2525+
Word("!$OMP ATOMIC");
2526+
Walk(std::get<0>(x.t));
2527+
Word(" COMPARE");
2528+
Walk(std::get<2>(x.t));
2529+
Put("\n");
2530+
EndOpenMP();
2531+
Walk(std::get<Statement<AssignmentStmt>>(x.t));
2532+
}
25232533
void Unparse(const OmpAtomicRead &x) {
25242534
BeginOpenMP();
25252535
Word("!$OMP ATOMIC");

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2408,6 +2408,24 @@ void OmpStructureChecker::CheckAtomicUpdateStmt(
24082408
ErrIfAllocatableVariable(var);
24092409
}
24102410

2411+
void OmpStructureChecker::CheckAtomicCompareConstruct(
2412+
const parser::OmpAtomicCompare &atomicCompareConstruct) {
2413+
2414+
CheckAtomicWriteStmt(std::get<parser::Statement<parser::AssignmentStmt>>(
2415+
atomicCompareConstruct.t)
2416+
.statement);
2417+
2418+
unsigned version{context_.langOptions().OpenMPVersion};
2419+
if (version < 51) {
2420+
context_.Say(atomicCompareConstruct.source,
2421+
"%s construct not allowed in %s, %s"_err_en_US,
2422+
atomicCompareConstruct.source, ThisVersion(version), TryVersion(51));
2423+
}
2424+
2425+
// TODO: More work needed here. Some of the Update restrictions need to
2426+
// be added, but Update isn't the same either.
2427+
}
2428+
24112429
// TODO: Allow cond-update-stmt once compare clause is supported.
24122430
void OmpStructureChecker::CheckAtomicCaptureConstruct(
24132431
const parser::OmpAtomicCapture &atomicCaptureConstruct) {
@@ -2553,6 +2571,16 @@ void OmpStructureChecker::Enter(const parser::OpenMPAtomicConstruct &x) {
25532571
&std::get<0>(atomicCapture.t), &std::get<2>(atomicCapture.t));
25542572
CheckAtomicCaptureConstruct(atomicCapture);
25552573
},
2574+
[&](const parser::OmpAtomicCompare &atomicCompare) {
2575+
const auto &dir{std::get<parser::Verbatim>(atomicCompare.t)};
2576+
PushContextAndClauseSets(
2577+
dir.source, llvm::omp::Directive::OMPD_atomic);
2578+
CheckAtomicMemoryOrderClause(
2579+
&std::get<0>(atomicCompare.t), &std::get<2>(atomicCompare.t));
2580+
CheckHintClause<const parser::OmpAtomicClauseList>(
2581+
&std::get<0>(atomicCompare.t), &std::get<2>(atomicCompare.t));
2582+
CheckAtomicCompareConstruct(atomicCompare);
2583+
},
25562584
},
25572585
x.u);
25582586
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ class OmpStructureChecker
213213
void CheckAtomicCaptureStmt(const parser::AssignmentStmt &);
214214
void CheckAtomicWriteStmt(const parser::AssignmentStmt &);
215215
void CheckAtomicCaptureConstruct(const parser::OmpAtomicCapture &);
216+
void CheckAtomicCompareConstruct(const parser::OmpAtomicCompare &);
216217
void CheckAtomicConstructStructure(const parser::OpenMPAtomicConstruct &);
217218
void CheckDistLinear(const parser::OpenMPLoopConstruct &x);
218219
void CheckSIMDNest(const parser::OpenMPConstruct &x);
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
! RUN: not %flang_fc1 -fopenmp-version=51 -fopenmp %s 2>&1 | FileCheck %s
2+
! OpenMP version for documentation purposes only - it isn't used until Sema.
3+
! This is testing for Parser errors that bail out before Sema.
4+
program main
5+
implicit none
6+
integer :: i, j = 10
7+
logical :: r
8+
9+
!CHECK: error: expected OpenMP construct
10+
!$omp atomic compare write
11+
r = i .eq. j + 1
12+
13+
!CHECK: error: expected end of line
14+
!$omp atomic compare num_threads(4)
15+
r = i .eq. j
16+
end program main

flang/test/Parser/OpenMP/atomic-unparse.f90

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
program main
44
implicit none
55
integer :: i, j = 10
6+
logical :: k
67
!READ
78
!$omp atomic read
89
i = j
@@ -121,6 +122,30 @@ program main
121122
i = j
122123
!$omp end atomic
123124

125+
!COMPARE
126+
!$omp atomic compare
127+
r = i .eq. j
128+
!$omp atomic seq_cst compare
129+
r = i .eq. j
130+
!$omp atomic compare seq_cst
131+
r = i .eq. j
132+
!$omp atomic release compare
133+
r = i .eq. j
134+
!$omp atomic compare release
135+
r = i .eq. j
136+
!$omp atomic acq_rel compare
137+
r = i .eq. j
138+
!$omp atomic compare acq_rel
139+
r = i .eq. j
140+
!$omp atomic acquire compare
141+
r = i .eq. j
142+
!$omp atomic compare acquire
143+
r = i .eq. j
144+
!$omp atomic relaxed compare
145+
r = i .eq. j
146+
!$omp atomic compare relaxed
147+
r = i .eq. j
148+
124149
!ATOMIC
125150
!$omp atomic
126151
i = j
@@ -205,6 +230,20 @@ end program main
205230
!CHECK: !$OMP ATOMIC CAPTURE RELAXED
206231
!CHECK: !$OMP END ATOMIC
207232

233+
!COMPARE
234+
235+
!CHECK: !$OMP ATOMIC COMPARE
236+
!CHECK: !$OMP ATOMIC SEQ_CST COMPARE
237+
!CHECK: !$OMP ATOMIC COMPARE SEQ_CST
238+
!CHECK: !$OMP ATOMIC RELEASE COMPARE
239+
!CHECK: !$OMP ATOMIC COMPARE RELEASE
240+
!CHECK: !$OMP ATOMIC ACQ_REL COMPARE
241+
!CHECK: !$OMP ATOMIC COMPARE ACQ_REL
242+
!CHECK: !$OMP ATOMIC ACQUIRE COMPARE
243+
!CHECK: !$OMP ATOMIC COMPARE ACQUIRE
244+
!CHECK: !$OMP ATOMIC RELAXED COMPARE
245+
!CHECK: !$OMP ATOMIC COMPARE RELAXED
246+
208247
!ATOMIC
209248
!CHECK: !$OMP ATOMIC
210249
!CHECK: !$OMP ATOMIC SEQ_CST
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=51
2+
use omp_lib
3+
implicit none
4+
! Check atomic compare. This combines elements from multiple other "atomic*.f90", as
5+
! to avoid having several files with just a few lines in them. atomic compare needs
6+
! higher openmp version than the others, so need a separate file.
7+
8+
9+
real a, b
10+
logical r
11+
a = 1.0
12+
b = 2.0
13+
!$omp parallel num_threads(4)
14+
! First a few things that should compile without error.
15+
!$omp atomic seq_cst, compare
16+
r = b .ne. a
17+
18+
!$omp atomic seq_cst compare
19+
r = a .ge. b
20+
!$omp end atomic
21+
22+
!$omp atomic compare acquire hint(OMP_LOCK_HINT_CONTENDED)
23+
r = a .lt. b
24+
25+
!$omp atomic release hint(OMP_LOCK_HINT_UNCONTENDED) compare
26+
r = a .gt. b
27+
28+
!$omp atomic compare seq_cst
29+
r = b .ne. a
30+
31+
!$omp atomic hint(1) acq_rel compare
32+
r = b .eq. a
33+
!$omp end atomic
34+
35+
! Check for error conidtions:
36+
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
37+
!ERROR: At most one SEQ_CST clause can appear on the COMPARE directive
38+
!$omp atomic seq_cst seq_cst compare
39+
r = a .le. b
40+
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
41+
!ERROR: At most one SEQ_CST clause can appear on the COMPARE directive
42+
!$omp atomic compare seq_cst seq_cst
43+
r = b .gt. a
44+
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
45+
!ERROR: At most one SEQ_CST clause can appear on the COMPARE directive
46+
!$omp atomic seq_cst compare seq_cst
47+
r = b .ge. b
48+
49+
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
50+
!ERROR: At most one ACQUIRE clause can appear on the COMPARE directive
51+
!$omp atomic acquire acquire compare
52+
r = a .le. b
53+
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
54+
!ERROR: At most one ACQUIRE clause can appear on the COMPARE directive
55+
!$omp atomic compare acquire acquire
56+
r = b .gt. a
57+
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
58+
!ERROR: At most one ACQUIRE clause can appear on the COMPARE directive
59+
!$omp atomic acquire compare acquire
60+
r = b .ge. b
61+
62+
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
63+
!ERROR: At most one RELAXED clause can appear on the COMPARE directive
64+
!$omp atomic relaxed relaxed compare
65+
r = a .le. b
66+
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
67+
!ERROR: At most one RELAXED clause can appear on the COMPARE directive
68+
!$omp atomic compare relaxed relaxed
69+
r = b .gt. a
70+
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
71+
!ERROR: At most one RELAXED clause can appear on the COMPARE directive
72+
!$omp atomic relaxed compare relaxed
73+
r = b .ge. b
74+
75+
!$omp end parallel
76+
end

0 commit comments

Comments
 (0)