Skip to content

Commit 00e1cc4

Browse files
[flang][OpenMP]Add support for fail clause (llvm#118683)
Support the atomic compare option of a fail(memory-order) clauses. Additional tests introduced to check that parsing and semantics checks for the new clause is handled. Lowering for atomic compare is still unsupported and wil end in a TOOD (aka "Not yet implemented"). A test for this case with the fail clause is also present.
1 parent 673c324 commit 00e1cc4

File tree

12 files changed

+193
-73
lines changed

12 files changed

+193
-73
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,7 @@ class ParseTreeDumper {
546546
NODE(parser, OmpEndCriticalDirective)
547547
NODE(parser, OmpEndLoopDirective)
548548
NODE(parser, OmpEndSectionsDirective)
549+
NODE(parser, OmpFailClause)
549550
NODE(parser, OmpFromClause)
550551
NODE(OmpFromClause, Modifier)
551552
NODE(parser, OmpExpectation)

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

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ struct OpenACCRoutineConstruct;
269269
struct OpenMPConstruct;
270270
struct OpenMPDeclarativeConstruct;
271271
struct OmpEndLoopDirective;
272+
struct OmpMemoryOrderClause;
272273
struct CUFKernelDoConstruct;
273274

274275
// Cooked character stream locations
@@ -3914,6 +3915,14 @@ struct OmpDeviceTypeClause {
39143915
WRAPPER_CLASS_BOILERPLATE(OmpDeviceTypeClause, DeviceTypeDescription);
39153916
};
39163917

3918+
// OMP 5.2 15.8.3 extended-atomic, fail-clause ->
3919+
// FAIL(memory-order)
3920+
struct OmpFailClause {
3921+
WRAPPER_CLASS_BOILERPLATE(
3922+
OmpFailClause, common::Indirection<OmpMemoryOrderClause>);
3923+
CharBlock source;
3924+
};
3925+
39173926
// Ref: [4.5:107-109], [5.0:176-180], [5.1:205-210], [5.2:167-168]
39183927
//
39193928
// from-clause ->
@@ -4317,11 +4326,12 @@ struct OmpMemoryOrderClause {
43174326
};
43184327

43194328
// 2.17.7 Atomic construct
4320-
// atomic-clause -> memory-order-clause | HINT(hint-expression)
4329+
// atomic-clause -> memory-order-clause | HINT(hint-expression) |
4330+
// FAIL(memory-order)
43214331
struct OmpAtomicClause {
43224332
UNION_CLASS_BOILERPLATE(OmpAtomicClause);
43234333
CharBlock source;
4324-
std::variant<OmpMemoryOrderClause, OmpClause> u;
4334+
std::variant<OmpMemoryOrderClause, OmpFailClause, OmpClause> u;
43254335
};
43264336

43274337
// atomic-clause-list -> [atomic-clause, [atomic-clause], ...]

flang/lib/Parser/openmp-parsers.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,9 @@ TYPE_PARSER(sourced(construct<OpenMPCancellationPointConstruct>(
739739
TYPE_PARSER(sourced(construct<OpenMPCancelConstruct>(verbatim("CANCEL"_tok),
740740
Parser<OmpCancelType>{}, maybe("IF" >> parenthesized(scalarLogicalExpr)))))
741741

742+
TYPE_PARSER(sourced(construct<OmpFailClause>(
743+
parenthesized(indirect(Parser<OmpMemoryOrderClause>{})))))
744+
742745
// 2.17.7 Atomic construct/2.17.8 Flush construct [OpenMP 5.0]
743746
// memory-order-clause ->
744747
// seq_cst
@@ -767,6 +770,7 @@ TYPE_PARSER(construct<OmpAtomicDefaultMemOrderClause>(
767770
// atomic-clause -> memory-order-clause | HINT(hint-expression)
768771
TYPE_PARSER(sourced(construct<OmpAtomicClause>(
769772
construct<OmpAtomicClause>(Parser<OmpMemoryOrderClause>{}) ||
773+
construct<OmpAtomicClause>("FAIL" >> Parser<OmpFailClause>{}) ||
770774
construct<OmpAtomicClause>("HINT" >>
771775
sourced(construct<OmpClause>(
772776
construct<OmpClause::Hint>(parenthesized(constantExpr))))))))

flang/lib/Parser/unparse.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2702,10 +2702,16 @@ class UnparseVisitor {
27022702
Put("\n");
27032703
EndOpenMP();
27042704
}
2705+
void Unparse(const OmpFailClause &x) {
2706+
Word("FAIL(");
2707+
Walk(x.v);
2708+
Put(")");
2709+
}
27052710
void Unparse(const OmpMemoryOrderClause &x) { Walk(x.v); }
27062711
void Unparse(const OmpAtomicClause &x) {
27072712
common::visit(common::visitors{
27082713
[&](const OmpMemoryOrderClause &y) { Walk(y); },
2714+
[&](const OmpFailClause &y) { Walk(y); },
27092715
[&](const OmpClause &z) { Walk(z); },
27102716
},
27112717
x.u);

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

Lines changed: 62 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2530,18 +2530,27 @@ void OmpStructureChecker::CheckAtomicCaptureConstruct(
25302530
void OmpStructureChecker::CheckAtomicMemoryOrderClause(
25312531
const parser::OmpAtomicClauseList *leftHandClauseList,
25322532
const parser::OmpAtomicClauseList *rightHandClauseList) {
2533-
int numMemoryOrderClause = 0;
2533+
int numMemoryOrderClause{0};
2534+
int numFailClause{0};
25342535
auto checkForValidMemoryOrderClause =
25352536
[&](const parser::OmpAtomicClauseList *clauseList) {
25362537
for (const auto &clause : clauseList->v) {
2537-
if (std::get_if<Fortran::parser::OmpMemoryOrderClause>(&clause.u)) {
2538-
numMemoryOrderClause++;
2539-
if (numMemoryOrderClause > 1) {
2538+
if (std::get_if<parser::OmpFailClause>(&clause.u)) {
2539+
numFailClause++;
2540+
if (numFailClause > 1) {
25402541
context_.Say(clause.source,
2541-
"More than one memory order clause not allowed on "
2542-
"OpenMP Atomic construct"_err_en_US);
2542+
"More than one FAIL clause not allowed on OpenMP ATOMIC construct"_err_en_US);
25432543
return;
25442544
}
2545+
} else {
2546+
if (std::get_if<Fortran::parser::OmpMemoryOrderClause>(&clause.u)) {
2547+
numMemoryOrderClause++;
2548+
if (numMemoryOrderClause > 1) {
2549+
context_.Say(clause.source,
2550+
"More than one memory order clause not allowed on OpenMP ATOMIC construct"_err_en_US);
2551+
return;
2552+
}
2553+
}
25452554
}
25462555
}
25472556
};
@@ -2816,8 +2825,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause &x) {
28162825

28172826
// Following clauses do not have a separate node in parse-tree.h.
28182827
CHECK_SIMPLE_CLAUSE(Absent, OMPC_absent)
2819-
CHECK_SIMPLE_CLAUSE(AcqRel, OMPC_acq_rel)
2820-
CHECK_SIMPLE_CLAUSE(Acquire, OMPC_acquire)
28212828
CHECK_SIMPLE_CLAUSE(Affinity, OMPC_affinity)
28222829
CHECK_SIMPLE_CLAUSE(Capture, OMPC_capture)
28232830
CHECK_SIMPLE_CLAUSE(Contains, OMPC_contains)
@@ -2853,9 +2860,6 @@ CHECK_SIMPLE_CLAUSE(Nogroup, OMPC_nogroup)
28532860
CHECK_SIMPLE_CLAUSE(Notinbranch, OMPC_notinbranch)
28542861
CHECK_SIMPLE_CLAUSE(Partial, OMPC_partial)
28552862
CHECK_SIMPLE_CLAUSE(ProcBind, OMPC_proc_bind)
2856-
CHECK_SIMPLE_CLAUSE(Release, OMPC_release)
2857-
CHECK_SIMPLE_CLAUSE(Relaxed, OMPC_relaxed)
2858-
CHECK_SIMPLE_CLAUSE(SeqCst, OMPC_seq_cst)
28592863
CHECK_SIMPLE_CLAUSE(Simd, OMPC_simd)
28602864
CHECK_SIMPLE_CLAUSE(Sizes, OMPC_sizes)
28612865
CHECK_SIMPLE_CLAUSE(Permutation, OMPC_permutation)
@@ -2883,7 +2887,6 @@ CHECK_SIMPLE_CLAUSE(Compare, OMPC_compare)
28832887
CHECK_SIMPLE_CLAUSE(CancellationConstructType, OMPC_cancellation_construct_type)
28842888
CHECK_SIMPLE_CLAUSE(OmpxAttribute, OMPC_ompx_attribute)
28852889
CHECK_SIMPLE_CLAUSE(OmpxBare, OMPC_ompx_bare)
2886-
CHECK_SIMPLE_CLAUSE(Fail, OMPC_fail)
28872890
CHECK_SIMPLE_CLAUSE(Weak, OMPC_weak)
28882891

28892892
CHECK_REQ_SCALAR_INT_CLAUSE(NumTeams, OMPC_num_teams)
@@ -2896,6 +2899,53 @@ CHECK_REQ_CONSTANT_SCALAR_INT_CLAUSE(Collapse, OMPC_collapse)
28962899
CHECK_REQ_CONSTANT_SCALAR_INT_CLAUSE(Safelen, OMPC_safelen)
28972900
CHECK_REQ_CONSTANT_SCALAR_INT_CLAUSE(Simdlen, OMPC_simdlen)
28982901

2902+
void OmpStructureChecker::Enter(const parser::OmpClause::AcqRel &) {
2903+
if (!isFailClause)
2904+
CheckAllowedClause(llvm::omp::Clause::OMPC_acq_rel);
2905+
}
2906+
2907+
void OmpStructureChecker::Enter(const parser::OmpClause::Acquire &) {
2908+
if (!isFailClause)
2909+
CheckAllowedClause(llvm::omp::Clause::OMPC_acquire);
2910+
}
2911+
2912+
void OmpStructureChecker::Enter(const parser::OmpClause::Release &) {
2913+
if (!isFailClause)
2914+
CheckAllowedClause(llvm::omp::Clause::OMPC_release);
2915+
}
2916+
2917+
void OmpStructureChecker::Enter(const parser::OmpClause::Relaxed &) {
2918+
if (!isFailClause)
2919+
CheckAllowedClause(llvm::omp::Clause::OMPC_relaxed);
2920+
}
2921+
2922+
void OmpStructureChecker::Enter(const parser::OmpClause::SeqCst &) {
2923+
if (!isFailClause)
2924+
CheckAllowedClause(llvm::omp::Clause::OMPC_seq_cst);
2925+
}
2926+
2927+
void OmpStructureChecker::Enter(const parser::OmpClause::Fail &) {
2928+
assert(!isFailClause && "Unexpected FAIL clause inside a FAIL clause?");
2929+
isFailClause = true;
2930+
CheckAllowedClause(llvm::omp::Clause::OMPC_fail);
2931+
}
2932+
2933+
void OmpStructureChecker::Leave(const parser::OmpClause::Fail &) {
2934+
assert(isFailClause && "Expected to be inside a FAIL clause here");
2935+
isFailClause = false;
2936+
}
2937+
2938+
void OmpStructureChecker::Enter(const parser::OmpFailClause &) {
2939+
assert(!isFailClause && "Unexpected FAIL clause inside a FAIL clause?");
2940+
isFailClause = true;
2941+
CheckAllowedClause(llvm::omp::Clause::OMPC_fail);
2942+
}
2943+
2944+
void OmpStructureChecker::Leave(const parser::OmpFailClause &) {
2945+
assert(isFailClause && "Expected to be inside a FAIL clause here");
2946+
isFailClause = false;
2947+
}
2948+
28992949
// Restrictions specific to each clause are implemented apart from the
29002950
// generalized restrictions.
29012951

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,10 @@ class OmpStructureChecker
142142
#define GEN_FLANG_CLAUSE_CHECK_ENTER
143143
#include "llvm/Frontend/OpenMP/OMP.inc"
144144

145+
void Leave(const parser::OmpClause::Fail &);
146+
void Enter(const parser::OmpFailClause &);
147+
void Leave(const parser::OmpFailClause &);
148+
145149
private:
146150
bool CheckAllowedClause(llvmOmpClause clause);
147151
bool IsVariableListItem(const Symbol &sym);
@@ -276,6 +280,7 @@ class OmpStructureChecker
276280
using LoopConstruct = std::variant<const parser::DoConstruct *,
277281
const parser::OpenMPLoopConstruct *>;
278282
std::vector<LoopConstruct> loopStack_;
283+
bool isFailClause{false};
279284
};
280285

281286
/// Find a duplicate entry in the range, and return an iterator to it.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s
2+
3+
! CHECK: not yet implemented: OpenMP atomic compare
4+
program p
5+
integer :: x
6+
logical :: r
7+
!$omp atomic compare fail(relaxed)
8+
if (x .eq. 0) then
9+
x = 2
10+
end if
11+
end program p

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,20 @@ program main
165165
i = j
166166
end if
167167

168+
169+
!$omp atomic compare fail(relaxed)
170+
if (i .eq. k) then
171+
i = j
172+
end if
173+
!$omp atomic fail(relaxed) compare
174+
if (i .eq. k) then
175+
i = j
176+
end if
177+
!$omp atomic fail(relaxed) compare acquire
178+
if (i .eq. k) then
179+
i = j
180+
end if
181+
168182
!ATOMIC
169183
!$omp atomic
170184
i = j
@@ -262,6 +276,9 @@ end program main
262276
!CHECK: !$OMP ATOMIC COMPARE ACQUIRE
263277
!CHECK: !$OMP ATOMIC RELAXED COMPARE
264278
!CHECK: !$OMP ATOMIC COMPARE RELAXED
279+
!CHECK: !$OMP ATOMIC COMPARE FAIL(RELAXED)
280+
!CHECK: !$OMP ATOMIC FAIL(RELAXED) COMPARE
281+
!CHECK: !$OMP ATOMIC FAIL(RELAXED) COMPARE ACQUIRE
265282

266283
!ATOMIC
267284
!CHECK: !$OMP ATOMIC
@@ -270,3 +287,5 @@ end program main
270287
!CHECK: !$OMP ATOMIC ACQ_REL
271288
!CHECK: !$OMP ATOMIC ACQUIRE
272289
!CHECK: !$OMP ATOMIC RELAXED
290+
291+

flang/test/Semantics/OpenMP/atomic-compare.f90

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,45 +35,58 @@
3535
if (b .eq. a) b = c
3636
!$omp end atomic
3737

38+
!$omp atomic hint(1) acq_rel compare fail(release)
39+
if (c .eq. a) a = b
40+
!$omp end atomic
41+
42+
!$omp atomic compare fail(release)
43+
if (c .eq. a) a = b
44+
!$omp end atomic
45+
3846
! Check for error conditions:
39-
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
47+
!ERROR: More than one memory order clause not allowed on OpenMP ATOMIC construct
4048
!ERROR: At most one SEQ_CST clause can appear on the COMPARE directive
4149
!$omp atomic seq_cst seq_cst compare
4250
if (b .eq. c) b = a
43-
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
51+
!ERROR: More than one memory order clause not allowed on OpenMP ATOMIC construct
4452
!ERROR: At most one SEQ_CST clause can appear on the COMPARE directive
4553
!$omp atomic compare seq_cst seq_cst
4654
if (b .eq. c) b = a
47-
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
55+
!ERROR: More than one memory order clause not allowed on OpenMP ATOMIC construct
4856
!ERROR: At most one SEQ_CST clause can appear on the COMPARE directive
4957
!$omp atomic seq_cst compare seq_cst
5058
if (b .eq. c) b = a
5159

52-
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
60+
!ERROR: More than one memory order clause not allowed on OpenMP ATOMIC construct
5361
!ERROR: At most one ACQUIRE clause can appear on the COMPARE directive
5462
!$omp atomic acquire acquire compare
5563
if (b .eq. c) b = a
56-
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
64+
!ERROR: More than one memory order clause not allowed on OpenMP ATOMIC construct
5765
!ERROR: At most one ACQUIRE clause can appear on the COMPARE directive
5866
!$omp atomic compare acquire acquire
5967
if (b .eq. c) b = a
60-
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
68+
!ERROR: More than one memory order clause not allowed on OpenMP ATOMIC construct
6169
!ERROR: At most one ACQUIRE clause can appear on the COMPARE directive
6270
!$omp atomic acquire compare acquire
6371
if (b .eq. c) b = a
6472

65-
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
73+
!ERROR: More than one memory order clause not allowed on OpenMP ATOMIC construct
6674
!ERROR: At most one RELAXED clause can appear on the COMPARE directive
6775
!$omp atomic relaxed relaxed compare
6876
if (b .eq. c) b = a
69-
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
77+
!ERROR: More than one memory order clause not allowed on OpenMP ATOMIC construct
7078
!ERROR: At most one RELAXED clause can appear on the COMPARE directive
7179
!$omp atomic compare relaxed relaxed
7280
if (b .eq. c) b = a
73-
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
81+
!ERROR: More than one memory order clause not allowed on OpenMP ATOMIC construct
7482
!ERROR: At most one RELAXED clause can appear on the COMPARE directive
7583
!$omp atomic relaxed compare relaxed
7684
if (b .eq. c) b = a
7785

86+
!ERROR: More than one FAIL clause not allowed on OpenMP ATOMIC construct
87+
!$omp atomic fail(release) compare fail(release)
88+
if (c .eq. a) a = b
89+
!$omp end atomic
90+
7891
!$omp end parallel
7992
end

0 commit comments

Comments
 (0)