Skip to content

Commit 3973955

Browse files
committed
[OpenACC] Implement 'reduction' clause parsing.
The 'reduction' clause takes a mandatory operator followed by a colon, followed by a 'var-list'. This patch implements the parsing for the 'reduction' clause.
1 parent 32dd5b2 commit 3973955

File tree

4 files changed

+125
-0
lines changed

4 files changed

+125
-0
lines changed

clang/include/clang/Basic/DiagnosticParseKinds.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1368,6 +1368,12 @@ def err_acc_invalid_default_clause_kind
13681368
: Error<"invalid value for 'default' clause; expected 'present' or 'none'">;
13691369
def err_acc_invalid_tag_kind
13701370
: Error<"invalid tag %0 on '%1' %select{directive|clause}2">;
1371+
def err_acc_expected_reduction_operator
1372+
: Error<"missing reduction operator, expected '+', '*', 'max', 'min', '&', "
1373+
"'|', '^', '&&', or '||', follwed by a ':'">;
1374+
def err_acc_invalid_reduction_operator
1375+
: Error<"invalid reduction operator, expected '+', '*', 'max', 'min', "
1376+
"'&', '|', '^', '&&', or '||'">;
13711377

13721378
// OpenMP support.
13731379
def warn_pragma_omp_ignored : Warning<

clang/include/clang/Basic/OpenACCKinds.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,9 @@ enum class OpenACCClauseKind {
214214
/// 'copyin' clause, allowed on Compute and Combined constructs, plus 'data',
215215
/// 'enter data', and 'declare'.
216216
Create,
217+
/// 'reduction' clause, allowed on Parallel, Serial, Loop, and the combined
218+
/// constructs.
219+
Reduction,
217220

218221
/// Represents an invalid clause, for the purposes of parsing.
219222
Invalid,
@@ -306,6 +309,9 @@ inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out,
306309
case OpenACCClauseKind::Create:
307310
return Out << "create";
308311

312+
case OpenACCClauseKind::Reduction:
313+
return Out << "reduction";
314+
309315
case OpenACCClauseKind::Invalid:
310316
return Out << "<invalid>";
311317
}
@@ -319,6 +325,29 @@ enum class OpenACCDefaultClauseKind {
319325
/// Not a valid option.
320326
Invalid,
321327
};
328+
329+
enum class OpenACCReductionOperator {
330+
/// '+'.
331+
Addition,
332+
/// '*'.
333+
Multiplication,
334+
/// 'max'.
335+
Max,
336+
/// 'min'.
337+
Min,
338+
/// '&'.
339+
BitwiseAnd,
340+
/// '|'.
341+
BitwiseOr,
342+
/// '^'.
343+
BitwiseXOr,
344+
/// '&&'.
345+
And,
346+
/// '||'.
347+
Or,
348+
/// Invalid Reduction Clause Kind.
349+
Invalid,
350+
};
322351
} // namespace clang
323352

324353
#endif // LLVM_CLANG_BASIC_OPENACCKINDS_H

clang/lib/Parse/ParseOpenACC.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ OpenACCClauseKind getOpenACCClauseKind(Token Tok) {
112112
.Case("nohost", OpenACCClauseKind::NoHost)
113113
.Case("present", OpenACCClauseKind::Present)
114114
.Case("private", OpenACCClauseKind::Private)
115+
.Case("reduction", OpenACCClauseKind::Reduction)
115116
.Case("self", OpenACCClauseKind::Self)
116117
.Case("seq", OpenACCClauseKind::Seq)
117118
.Case("use_device", OpenACCClauseKind::UseDevice)
@@ -260,6 +261,47 @@ bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, Token Tok) {
260261
llvm_unreachable("Unknown 'Kind' Passed");
261262
}
262263

264+
OpenACCReductionOperator ParseReductionOperator(Parser &P) {
265+
// If there is no colon, treat as if the reduction operator was missing, else
266+
// we probably will not recover from it in the case where an expression starts
267+
// with one of the operator tokens.
268+
if (P.NextToken().isNot(tok::colon)) {
269+
P.Diag(P.getCurToken(), diag::err_acc_expected_reduction_operator);
270+
return OpenACCReductionOperator::Invalid;
271+
}
272+
Token ReductionKindTok = P.getCurToken();
273+
// Consume both the kind and the colon.
274+
P.ConsumeToken();
275+
P.ConsumeToken();
276+
277+
switch (ReductionKindTok.getKind()) {
278+
case tok::plus:
279+
return OpenACCReductionOperator::Addition;
280+
case tok::star:
281+
return OpenACCReductionOperator::Multiplication;
282+
case tok::amp:
283+
return OpenACCReductionOperator::BitwiseAnd;
284+
case tok::pipe:
285+
return OpenACCReductionOperator::BitwiseOr;
286+
case tok::caret:
287+
return OpenACCReductionOperator::BitwiseXOr;
288+
case tok::ampamp:
289+
return OpenACCReductionOperator::And;
290+
case tok::pipepipe:
291+
return OpenACCReductionOperator::Or;
292+
case tok::identifier:
293+
if (ReductionKindTok.getIdentifierInfo()->isStr("max"))
294+
return OpenACCReductionOperator::Max;
295+
if (ReductionKindTok.getIdentifierInfo()->isStr("min"))
296+
return OpenACCReductionOperator::Min;
297+
LLVM_FALLTHROUGH;
298+
default:
299+
P.Diag(ReductionKindTok, diag::err_acc_invalid_reduction_operator);
300+
return OpenACCReductionOperator::Invalid;
301+
}
302+
llvm_unreachable("Reduction op token kind not caught by 'default'?");
303+
}
304+
263305
/// Used for cases where we expect an identifier-like token, but don't want to
264306
/// give awkward error messages in cases where it is accidentially a keyword.
265307
bool expectIdentifierOrKeyword(Parser &P) {
@@ -419,6 +461,7 @@ ClauseParensKind getClauseParensKind(OpenACCDirectiveKind DirKind,
419461
case OpenACCClauseKind::Device:
420462
case OpenACCClauseKind::Link:
421463
case OpenACCClauseKind::Host:
464+
case OpenACCClauseKind::Reduction:
422465
return ClauseParensKind::Required;
423466

424467
case OpenACCClauseKind::Auto:
@@ -581,6 +624,13 @@ bool Parser::ParseOpenACCClauseParams(OpenACCDirectiveKind DirKind,
581624
if (ParseOpenACCClauseVarList(Kind))
582625
return true;
583626
break;
627+
case OpenACCClauseKind::Reduction:
628+
// If we're missing a clause-kind (or it is invalid), see if we can parse
629+
// the var-list anyway.
630+
ParseReductionOperator(*this);
631+
if (ParseOpenACCClauseVarList(Kind))
632+
return true;
633+
break;
584634
case OpenACCClauseKind::Self:
585635
// The 'self' clause is a var-list instead of a 'condition' in the case of
586636
// the 'update' clause, so we have to handle it here. U se an assert to

clang/test/ParserOpenACC/parse-clauses.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,46 @@ void VarListClauses() {
619619
// expected-error@+2{{use of undeclared identifier 'invalid'}}
620620
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
621621
#pragma acc serial copyin(invalid s.array[s.value : 5], s.value), seq
622+
}
623+
624+
void ReductionClauseParsing() {
625+
char *Begin, *End;
626+
// expected-error@+2{{expected '('}}
627+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
628+
#pragma acc serial reduction
629+
// expected-error@+3{{missing reduction operator, expected '+', '*', 'max', 'min', '&', '|', '^', '&&', or '||', follwed by a ':'}}
630+
// expected-error@+2{{expected expression}}
631+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
632+
#pragma acc serial reduction()
633+
// expected-error@+2{{missing reduction operator, expected '+', '*', 'max', 'min', '&', '|', '^', '&&', or '||', follwed by a ':'}}
634+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
635+
#pragma acc serial reduction(Begin)
636+
// expected-error@+2{{missing reduction operator, expected '+', '*', 'max', 'min', '&', '|', '^', '&&', or '||', follwed by a ':'}}
637+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
638+
#pragma acc serial reduction(Begin, End)
639+
// expected-error@+2{{missing reduction operator, expected '+', '*', 'max', 'min', '&', '|', '^', '&&', or '||', follwed by a ':'}}
640+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
641+
#pragma acc serial reduction(Begin, End)
642+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
643+
#pragma acc serial reduction(+:Begin)
644+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
645+
#pragma acc serial reduction(+:Begin, End)
646+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
647+
#pragma acc serial reduction(*: Begin, End)
648+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
649+
#pragma acc serial reduction(max : Begin, End)
650+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
651+
#pragma acc serial reduction(min: Begin, End)
652+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
653+
#pragma acc serial reduction(&: Begin, End)
654+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
655+
#pragma acc serial reduction(|: Begin, End)
656+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
657+
#pragma acc serial reduction(^: Begin, End)
658+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
659+
#pragma acc serial seq, reduction(&&: Begin, End)
660+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
661+
#pragma acc serial reduction(||: Begin, End), seq
622662
}
623663

624664
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}

0 commit comments

Comments
 (0)