Hi!

This patch adds min/max reduction support for C/C++, which was quite easy
given that the middle-end already needs to support it for Fortran.

Tested on x86_64-linux, committed to gomp-3_1-branch.

2011-03-03  Jakub Jelinek  <ja...@redhat.com>

        * c-parser.c (c_parser_omp_clause_reduction): Handle min and max.
        * c-typeck.c (c_finish_omp_clauses): Handle MIN_EXPR and MAX_EXPR.

        * parser.c (cp_parser_omp_clause_reduction): Handle min and max.
        * semantics.c (finish_omp_clauses): Handle MIN_EXPR and MAX_EXPR.

        * testsuite/libgomp.c/reduction-6.c: New test.
        * testsuite/libgomp.c++/reduction-4.C: New test.

--- gcc/c-parser.c.jj   2011-03-03 16:57:07.000000000 +0100
+++ gcc/c-parser.c      2011-03-03 19:49:05.000000000 +0100
@@ -8692,7 +8692,12 @@ c_parser_omp_clause_private (c_parser *p
    reduction ( reduction-operator : variable-list )
 
    reduction-operator:
-     One of: + * - & ^ | && || */
+     One of: + * - & ^ | && ||
+     
+   OpenMP 3.1:
+   
+   reduction-operator:
+     One of: + * - & ^ | && || max min  */
 
 static tree
 c_parser_omp_clause_reduction (c_parser *parser, tree list)
@@ -8728,10 +8733,26 @@ c_parser_omp_clause_reduction (c_parser 
        case CPP_OR_OR:
          code = TRUTH_ORIF_EXPR;
          break;
+        case CPP_NAME:
+         {
+           const char *p
+             = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+           if (strcmp (p, "min") == 0)
+             {
+               code = MIN_EXPR;
+               break;
+             }
+           if (strcmp (p, "max") == 0)
+             {
+               code = MAX_EXPR;
+               break;
+             }
+         }
+         /* FALLTHRU */
        default:
          c_parser_error (parser,
                          "expected %<+%>, %<*%>, %<-%>, %<&%>, "
-                         "%<^%>, %<|%>, %<&&%>, or %<||%>");
+                         "%<^%>, %<|%>, %<&&%>, %<||%>, %<min%> or %<max%>");
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
          return list;
        }
--- gcc/c-typeck.c.jj   2011-02-24 14:20:36.000000000 +0100
+++ gcc/c-typeck.c      2011-03-03 19:27:19.000000000 +0100
@@ -10441,6 +10441,8 @@ c_finish_omp_clauses (tree clauses)
                case PLUS_EXPR:
                case MULT_EXPR:
                case MINUS_EXPR:
+               case MIN_EXPR:
+               case MAX_EXPR:
                  break;
                case BIT_AND_EXPR:
                  r_name = "&";
--- gcc/cp/parser.c.jj  2011-02-24 14:18:07.000000000 +0100
+++ gcc/cp/parser.c     2011-03-03 19:48:52.000000000 +0100
@@ -23683,7 +23683,12 @@ cp_parser_omp_clause_ordered (cp_parser 
    reduction ( reduction-operator : variable-list )
 
    reduction-operator:
-     One of: + * - & ^ | && || */
+     One of: + * - & ^ | && ||
+
+   OpenMP 3.1:
+
+   reduction-operator:
+     One of: + * - & ^ | && || min max  */
 
 static tree
 cp_parser_omp_clause_reduction (cp_parser *parser, tree list)
@@ -23720,9 +23725,26 @@ cp_parser_omp_clause_reduction (cp_parse
     case CPP_OR_OR:
       code = TRUTH_ORIF_EXPR;
       break;
+    case CPP_NAME:
+      {
+       tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+       const char *p = IDENTIFIER_POINTER (id);
+
+       if (strcmp (p, "min") == 0)
+         {
+           code = MIN_EXPR;
+           break;
+         }
+       if (strcmp (p, "max") == 0)
+         {
+           code = MAX_EXPR;
+           break;
+         }
+      }
+      /* FALLTHROUGH */
     default:
       cp_parser_error (parser, "expected %<+%>, %<*%>, %<-%>, %<&%>, %<^%>, "
-                              "%<|%>, %<&&%>, or %<||%>");
+                              "%<|%>, %<&&%>, %<||%>, %<min%> or %<max%>");
     resync_fail:
       cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
                                             /*or_comma=*/false,
--- gcc/cp/semantics.c.jj       2011-02-28 19:27:17.000000000 +0100
+++ gcc/cp/semantics.c  2011-03-03 19:50:38.000000000 +0100
@@ -3893,6 +3893,8 @@ finish_omp_clauses (tree clauses)
                case PLUS_EXPR:
                case MULT_EXPR:
                case MINUS_EXPR:
+               case MIN_EXPR:
+               case MAX_EXPR:
                  break;
                default:
                  error ("%qE has invalid type for %<reduction(%s)%>",
--- libgomp/testsuite/libgomp.c/reduction-6.c.jj        2011-03-03 
19:44:19.000000000 +0100
+++ libgomp/testsuite/libgomp.c/reduction-6.c   2011-03-03 19:43:38.000000000 
+0100
@@ -0,0 +1,29 @@
+/* { dg-do run } */
+
+extern void abort (void);
+int j;
+float f;
+
+int
+main ()
+{
+  j = -10000;
+  f = 1024.0;
+  int i;
+  #pragma omp parallel for reduction (min:f) reduction (max:j)
+    for (i = 0; i < 4; i++)
+      switch (i)
+       {
+       case 0:
+         if (j < -16) j = -16; break;
+       case 1:
+         if (f > -2.0) f = -2.0; break;
+       case 2:
+         if (j < 8) j = 8; if (f > 9.0) f = 9.0; break;
+       case 3:
+         break;
+       }
+  if (j != 8 || f != -2.0)
+    abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c++/reduction-4.C.jj      2011-03-03 
19:54:22.000000000 +0100
+++ libgomp/testsuite/libgomp.c++/reduction-4.C 2011-03-03 19:53:49.000000000 
+0100
@@ -0,0 +1,54 @@
+// { dg-do run }
+
+extern "C" void abort (void);
+
+template <typename I, typename F>
+void
+foo ()
+{
+  I j = -10000;
+  F f = 1024.0;
+  int i;
+  #pragma omp parallel for reduction (min:f) reduction (max:j)
+    for (i = 0; i < 4; i++)
+      switch (i)
+       {
+       case 0:
+         if (j < -16) j = -16; break;
+       case 1:
+         if (f > -2.0) f = -2.0; break;
+       case 2:
+         if (j < 8) j = 8; if (f > 9.0) f = 9.0; break;
+       case 3:
+         break;
+       }
+  if (j != 8 || f != -2.0)
+    abort ();
+}
+
+int
+main ()
+{
+  int j = -10000;
+  float f = 1024.0;
+  int i;
+  #pragma omp parallel for reduction (min:f) reduction (max:j)
+    for (i = 0; i < 4; i++)
+      switch (i)
+       {
+       case 0:
+         if (j < -16) j = -16; break;
+       case 1:
+         if (f > -2.0) f = -2.0; break;
+       case 2:
+         if (j < 8) j = 8; if (f > 9.0) f = 9.0; break;
+       case 3:
+         break;
+       }
+  if (j != 8 || f != -2.0)
+    abort ();
+  foo <int, float> ();
+  foo <long, double> ();
+  foo <long long, long double> ();
+  return 0;
+}

        Jakub

Reply via email to