[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