Skip to content

Commit

Permalink
[OpenACC] Implement 'reduction' clause parsing.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
erichkeane committed Jan 16, 2024
1 parent 32dd5b2 commit 3973955
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 0 deletions.
6 changes: 6 additions & 0 deletions clang/include/clang/Basic/DiagnosticParseKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -1368,6 +1368,12 @@ def err_acc_invalid_default_clause_kind
: Error<"invalid value for 'default' clause; expected 'present' or 'none'">;
def err_acc_invalid_tag_kind
: Error<"invalid tag %0 on '%1' %select{directive|clause}2">;
def err_acc_expected_reduction_operator
: Error<"missing reduction operator, expected '+', '*', 'max', 'min', '&', "
"'|', '^', '&&', or '||', follwed by a ':'">;
def err_acc_invalid_reduction_operator
: Error<"invalid reduction operator, expected '+', '*', 'max', 'min', "
"'&', '|', '^', '&&', or '||'">;

// OpenMP support.
def warn_pragma_omp_ignored : Warning<
Expand Down
29 changes: 29 additions & 0 deletions clang/include/clang/Basic/OpenACCKinds.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,9 @@ enum class OpenACCClauseKind {
/// 'copyin' clause, allowed on Compute and Combined constructs, plus 'data',
/// 'enter data', and 'declare'.
Create,
/// 'reduction' clause, allowed on Parallel, Serial, Loop, and the combined
/// constructs.
Reduction,

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

case OpenACCClauseKind::Reduction:
return Out << "reduction";

case OpenACCClauseKind::Invalid:
return Out << "<invalid>";
}
Expand All @@ -319,6 +325,29 @@ enum class OpenACCDefaultClauseKind {
/// Not a valid option.
Invalid,
};

enum class OpenACCReductionOperator {
/// '+'.
Addition,
/// '*'.
Multiplication,
/// 'max'.
Max,
/// 'min'.
Min,
/// '&'.
BitwiseAnd,
/// '|'.
BitwiseOr,
/// '^'.
BitwiseXOr,
/// '&&'.
And,
/// '||'.
Or,
/// Invalid Reduction Clause Kind.
Invalid,
};
} // namespace clang

#endif // LLVM_CLANG_BASIC_OPENACCKINDS_H
50 changes: 50 additions & 0 deletions clang/lib/Parse/ParseOpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ OpenACCClauseKind getOpenACCClauseKind(Token Tok) {
.Case("nohost", OpenACCClauseKind::NoHost)
.Case("present", OpenACCClauseKind::Present)
.Case("private", OpenACCClauseKind::Private)
.Case("reduction", OpenACCClauseKind::Reduction)
.Case("self", OpenACCClauseKind::Self)
.Case("seq", OpenACCClauseKind::Seq)
.Case("use_device", OpenACCClauseKind::UseDevice)
Expand Down Expand Up @@ -260,6 +261,47 @@ bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, Token Tok) {
llvm_unreachable("Unknown 'Kind' Passed");
}

OpenACCReductionOperator ParseReductionOperator(Parser &P) {
// If there is no colon, treat as if the reduction operator was missing, else
// we probably will not recover from it in the case where an expression starts
// with one of the operator tokens.
if (P.NextToken().isNot(tok::colon)) {
P.Diag(P.getCurToken(), diag::err_acc_expected_reduction_operator);
return OpenACCReductionOperator::Invalid;
}
Token ReductionKindTok = P.getCurToken();
// Consume both the kind and the colon.
P.ConsumeToken();
P.ConsumeToken();

switch (ReductionKindTok.getKind()) {
case tok::plus:
return OpenACCReductionOperator::Addition;
case tok::star:
return OpenACCReductionOperator::Multiplication;
case tok::amp:
return OpenACCReductionOperator::BitwiseAnd;
case tok::pipe:
return OpenACCReductionOperator::BitwiseOr;
case tok::caret:
return OpenACCReductionOperator::BitwiseXOr;
case tok::ampamp:
return OpenACCReductionOperator::And;
case tok::pipepipe:
return OpenACCReductionOperator::Or;
case tok::identifier:
if (ReductionKindTok.getIdentifierInfo()->isStr("max"))
return OpenACCReductionOperator::Max;
if (ReductionKindTok.getIdentifierInfo()->isStr("min"))
return OpenACCReductionOperator::Min;
LLVM_FALLTHROUGH;
default:
P.Diag(ReductionKindTok, diag::err_acc_invalid_reduction_operator);
return OpenACCReductionOperator::Invalid;
}
llvm_unreachable("Reduction op token kind not caught by 'default'?");
}

/// Used for cases where we expect an identifier-like token, but don't want to
/// give awkward error messages in cases where it is accidentially a keyword.
bool expectIdentifierOrKeyword(Parser &P) {
Expand Down Expand Up @@ -419,6 +461,7 @@ ClauseParensKind getClauseParensKind(OpenACCDirectiveKind DirKind,
case OpenACCClauseKind::Device:
case OpenACCClauseKind::Link:
case OpenACCClauseKind::Host:
case OpenACCClauseKind::Reduction:
return ClauseParensKind::Required;

case OpenACCClauseKind::Auto:
Expand Down Expand Up @@ -581,6 +624,13 @@ bool Parser::ParseOpenACCClauseParams(OpenACCDirectiveKind DirKind,
if (ParseOpenACCClauseVarList(Kind))
return true;
break;
case OpenACCClauseKind::Reduction:
// If we're missing a clause-kind (or it is invalid), see if we can parse
// the var-list anyway.
ParseReductionOperator(*this);
if (ParseOpenACCClauseVarList(Kind))
return true;
break;
case OpenACCClauseKind::Self:
// The 'self' clause is a var-list instead of a 'condition' in the case of
// the 'update' clause, so we have to handle it here. U se an assert to
Expand Down
40 changes: 40 additions & 0 deletions clang/test/ParserOpenACC/parse-clauses.c
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,46 @@ void VarListClauses() {
// expected-error@+2{{use of undeclared identifier 'invalid'}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial copyin(invalid s.array[s.value : 5], s.value), seq
}

void ReductionClauseParsing() {
char *Begin, *End;
// expected-error@+2{{expected '('}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial reduction
// expected-error@+3{{missing reduction operator, expected '+', '*', 'max', 'min', '&', '|', '^', '&&', or '||', follwed by a ':'}}
// expected-error@+2{{expected expression}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial reduction()
// expected-error@+2{{missing reduction operator, expected '+', '*', 'max', 'min', '&', '|', '^', '&&', or '||', follwed by a ':'}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial reduction(Begin)
// expected-error@+2{{missing reduction operator, expected '+', '*', 'max', 'min', '&', '|', '^', '&&', or '||', follwed by a ':'}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial reduction(Begin, End)
// expected-error@+2{{missing reduction operator, expected '+', '*', 'max', 'min', '&', '|', '^', '&&', or '||', follwed by a ':'}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial reduction(Begin, End)
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial reduction(+:Begin)
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial reduction(+:Begin, End)
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial reduction(*: Begin, End)
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial reduction(max : Begin, End)
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial reduction(min: Begin, End)
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial reduction(&: Begin, End)
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial reduction(|: Begin, End)
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial reduction(^: Begin, End)
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial seq, reduction(&&: Begin, End)
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial reduction(||: Begin, End), seq
}

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

0 comments on commit 3973955

Please sign in to comment.