Skip to content

Commit 59752d2

Browse files
[flang][OpenMP]Add support for fail clause
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 4639a9a commit 59752d2

File tree

10 files changed

+87
-6
lines changed

10 files changed

+87
-6
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
@@ -4098,6 +4099,14 @@ struct OmpUpdateClause {
40984099
std::variant<OmpDependenceType, OmpTaskDependenceType> u;
40994100
};
41004101

4102+
// OMP 5.2 15.8.3 extened-atomic, fail-clause ->
4103+
// FAIL(memory-order)
4104+
struct OmpFailClause {
4105+
WRAPPER_CLASS_BOILERPLATE(
4106+
OmpFailClause, common::Indirection<OmpMemoryOrderClause>);
4107+
CharBlock source;
4108+
};
4109+
41014110
// OpenMP Clauses
41024111
struct OmpClause {
41034112
UNION_CLASS_BOILERPLATE(OmpClause);
@@ -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: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2486,17 +2486,28 @@ void OmpStructureChecker::CheckAtomicMemoryOrderClause(
24862486
const parser::OmpAtomicClauseList *leftHandClauseList,
24872487
const parser::OmpAtomicClauseList *rightHandClauseList) {
24882488
int numMemoryOrderClause = 0;
2489+
int numFailClause = 0;
24892490
auto checkForValidMemoryOrderClause =
24902491
[&](const parser::OmpAtomicClauseList *clauseList) {
24912492
for (const auto &clause : clauseList->v) {
2492-
if (std::get_if<Fortran::parser::OmpMemoryOrderClause>(&clause.u)) {
2493-
numMemoryOrderClause++;
2494-
if (numMemoryOrderClause > 1) {
2493+
if (std::get_if<parser::OmpFailClause>(&clause.u)) {
2494+
numFailClause++;
2495+
if (numFailClause > 1) {
24952496
context_.Say(clause.source,
2496-
"More than one memory order clause not allowed on "
2497+
"More than one fail clause not allowed on "
24972498
"OpenMP Atomic construct"_err_en_US);
24982499
return;
24992500
}
2501+
} else {
2502+
if (std::get_if<Fortran::parser::OmpMemoryOrderClause>(&clause.u)) {
2503+
numMemoryOrderClause++;
2504+
if (numMemoryOrderClause > 1) {
2505+
context_.Say(clause.source,
2506+
"More than one memory order clause not allowed on "
2507+
"OpenMP Atomic construct"_err_en_US);
2508+
return;
2509+
}
2510+
}
25002511
}
25012512
}
25022513
};

flang/lib/Semantics/semantics.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ class SemanticsVisitor : public virtual BaseChecker, public virtual C... {
114114
context_.set_location(std::nullopt);
115115
}
116116

117+
// This is necessary to avoid "walking" into the Fail clause,
118+
// which confuses the CheckAllowed into thinking there's another
119+
// memoryorder, when it's actually the argument to the fail clause.
120+
bool Pre(const parser::OmpFailClause &) { return false; }
121+
117122
bool Walk(const parser::Program &program) {
118123
parser::Walk(program, *this);
119124
return !context_.AnyFatalError();
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: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@
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:
3947
!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
@@ -75,5 +83,10 @@
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

llvm/include/llvm/Frontend/OpenMP/OMP.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ def OMPC_Exclusive : Clause<"exclusive"> {
177177
}
178178
def OMPC_Fail : Clause<"fail"> {
179179
let clangClass = "OMPFailClause";
180+
let flangClass = "OmpFailClause";
180181
}
181182
def OMPC_Filter : Clause<"filter"> {
182183
let clangClass = "OMPFilterClause";

0 commit comments

Comments
 (0)