[clang] 3973955 - [OpenACC] Implement 'reduction' clause parsing.
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 16 11:38:01 PST 2024
Author: erichkeane
Date: 2024-01-16T11:37:56-08:00
New Revision: 3973955282121cf97fb3b77c4bac0a89dcf82591
URL: https://github.com/llvm/llvm-project/commit/3973955282121cf97fb3b77c4bac0a89dcf82591
DIFF: https://github.com/llvm/llvm-project/commit/3973955282121cf97fb3b77c4bac0a89dcf82591.diff
LOG: [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.
Added:
Modified:
clang/include/clang/Basic/DiagnosticParseKinds.td
clang/include/clang/Basic/OpenACCKinds.h
clang/lib/Parse/ParseOpenACC.cpp
clang/test/ParserOpenACC/parse-clauses.c
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 31530444d6920c5..fcfe8a3fffeae8c 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -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<
diff --git a/clang/include/clang/Basic/OpenACCKinds.h b/clang/include/clang/Basic/OpenACCKinds.h
index 87da3fc108ce062..23d41c41b9a6349 100644
--- a/clang/include/clang/Basic/OpenACCKinds.h
+++ b/clang/include/clang/Basic/OpenACCKinds.h
@@ -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,
@@ -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>";
}
@@ -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
diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp
index 5196eb9056be281..b397553de01a089 100644
--- a/clang/lib/Parse/ParseOpenACC.cpp
+++ b/clang/lib/Parse/ParseOpenACC.cpp
@@ -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)
@@ -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) {
@@ -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:
@@ -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
diff --git a/clang/test/ParserOpenACC/parse-clauses.c b/clang/test/ParserOpenACC/parse-clauses.c
index c5638531b68b965..6d548210e816caa 100644
--- a/clang/test/ParserOpenACC/parse-clauses.c
+++ b/clang/test/ParserOpenACC/parse-clauses.c
@@ -619,6 +619,46 @@ void VarListClauses() {
// expected-error at +2{{use of undeclared identifier 'invalid'}}
// expected-warning at +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 at +2{{expected '('}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial reduction
+ // expected-error at +3{{missing reduction operator, expected '+', '*', 'max', 'min', '&', '|', '^', '&&', or '||', follwed by a ':'}}
+ // expected-error at +2{{expected expression}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial reduction()
+ // expected-error at +2{{missing reduction operator, expected '+', '*', 'max', 'min', '&', '|', '^', '&&', or '||', follwed by a ':'}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial reduction(Begin)
+ // expected-error at +2{{missing reduction operator, expected '+', '*', 'max', 'min', '&', '|', '^', '&&', or '||', follwed by a ':'}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial reduction(Begin, End)
+ // expected-error at +2{{missing reduction operator, expected '+', '*', 'max', 'min', '&', '|', '^', '&&', or '||', follwed by a ':'}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial reduction(Begin, End)
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial reduction(+:Begin)
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial reduction(+:Begin, End)
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial reduction(*: Begin, End)
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial reduction(max : Begin, End)
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial reduction(min: Begin, End)
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial reduction(&: Begin, End)
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial reduction(|: Begin, End)
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial reduction(^: Begin, End)
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial seq, reduction(&&: Begin, End)
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial reduction(||: Begin, End), seq
}
// expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
More information about the cfe-commits
mailing list