Hi!

OpenMP 4.1 allows modifiers on the linear clause, like:
#ifdef __cplusplus
#pragma omp declare simd linear(ref(a):1) linear(val(b)) linear(uval(c))
int foo (int &a, int &b, int &c);
#else
#pragma omp declare simd linear(a:1) linear(val(b)) linear(uval(c))
int bar (int a, int b, int c);
#endif

This patch parses them and checks requirements.  Further changes
(for elemental function handling and vectorization) will depend on the
vector ABI details.

2015-06-11  Jakub Jelinek  <ja...@redhat.com>

        * tree-core.h (enum omp_clause_linear_kind): New.
        (struct tree_omp_clause): Add subcode.linear_kind.
        * tree.h (OMP_CLAUSE_LINEAR_KIND): Define.
        * tree-pretty-print.h (dump_omp_clause): Dump linear
        clause modifiers.
c/
        * c-parser.c (c_parser_omp_clause_linear): Handle linear clause
        modifiers.
cp/
        * parser.c (cp_parser_omp_clause_linear): Handle linear clause
        modifiers.
        * semantics.c (finish_omp_clauses): Diagnose linear(ref(var))
        where var isn't a reference.  Don't use pointer_sum
        for ref(var), just multiply by size of pointer.

--- gcc/tree-core.h.jj  2015-06-08 11:08:41.000000000 +0200
+++ gcc/tree-core.h     2015-06-11 14:34:43.926623065 +0200
@@ -1264,6 +1264,14 @@ enum omp_clause_proc_bind_kind
   OMP_CLAUSE_PROC_BIND_LAST
 };
 
+enum omp_clause_linear_kind
+{
+  OMP_CLAUSE_LINEAR_DEFAULT,
+  OMP_CLAUSE_LINEAR_REF,
+  OMP_CLAUSE_LINEAR_VAL,
+  OMP_CLAUSE_LINEAR_UVAL
+};
+
 struct GTY(()) tree_exp {
   struct tree_typed typed;
   location_t locus;
@@ -1328,6 +1336,7 @@ struct GTY(()) tree_omp_clause {
     unsigned char                 map_kind;
     enum omp_clause_proc_bind_kind proc_bind_kind;
     enum tree_code                 reduction_code;
+    enum omp_clause_linear_kind    linear_kind;
   } GTY ((skip)) subcode;
 
   /* The gimplification of OMP_CLAUSE_REDUCTION_{INIT,MERGE} for omp-low's
--- gcc/tree.h.jj       2015-06-08 10:48:20.000000000 +0200
+++ gcc/tree.h  2015-06-11 14:36:37.236879987 +0200
@@ -1494,6 +1494,9 @@ extern void protected_set_expr_location
 #define OMP_CLAUSE_LINEAR_GIMPLE_SEQ(NODE) \
   (OMP_CLAUSE_CHECK (NODE))->omp_clause.gimple_reduction_init
 
+#define OMP_CLAUSE_LINEAR_KIND(NODE) \
+  (OMP_CLAUSE_SUBCODE_CHECK (NODE, 
OMP_CLAUSE_LINEAR)->omp_clause.subcode.linear_kind)
+
 #define OMP_CLAUSE_ALIGNED_ALIGNMENT(NODE) \
   OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ALIGNED), 1)
 
--- gcc/tree-pretty-print.c.jj  2015-06-11 11:32:39.000000000 +0200
+++ gcc/tree-pretty-print.c     2015-06-11 14:43:37.367415531 +0200
@@ -495,8 +495,26 @@ dump_omp_clause (pretty_printer *pp, tre
 
     case OMP_CLAUSE_LINEAR:
       pp_string (pp, "linear(");
+      switch (OMP_CLAUSE_LINEAR_KIND (clause))
+       {
+       case OMP_CLAUSE_LINEAR_DEFAULT:
+         break;
+       case OMP_CLAUSE_LINEAR_REF:
+         pp_string (pp, "ref(");
+         break;
+       case OMP_CLAUSE_LINEAR_VAL:
+         pp_string (pp, "val(");
+         break;
+       case OMP_CLAUSE_LINEAR_UVAL:
+         pp_string (pp, "uval(");
+         break;
+       default:
+         gcc_unreachable ();
+       }
       dump_generic_node (pp, OMP_CLAUSE_DECL (clause),
                         spc, flags, false);
+      if (OMP_CLAUSE_LINEAR_KIND (clause) != OMP_CLAUSE_LINEAR_DEFAULT)
+       pp_right_paren (pp);
       pp_colon (pp);
       dump_generic_node (pp, OMP_CLAUSE_LINEAR_STEP (clause),
                         spc, flags, false);
--- gcc/c/c-parser.c.jj 2015-06-11 13:02:30.000000000 +0200
+++ gcc/c/c-parser.c    2015-06-11 17:00:21.046632435 +0200
@@ -11461,20 +11461,46 @@ c_parser_omp_clause_aligned (c_parser *p
 
 /* OpenMP 4.0:
    linear ( variable-list )
-   linear ( variable-list : expression ) */
+   linear ( variable-list : expression )
+
+   OpenMP 4.1:
+   linear ( modifier ( variable-list ) )
+   linear ( modifier ( variable-list ) : expression ) */
 
 static tree
 c_parser_omp_clause_linear (c_parser *parser, tree list, bool is_cilk_simd_fn)
 {
   location_t clause_loc = c_parser_peek_token (parser)->location;
   tree nl, c, step;
+  enum omp_clause_linear_kind kind = OMP_CLAUSE_LINEAR_DEFAULT;
 
   if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     return list;
 
+  if (!is_cilk_simd_fn
+      && c_parser_next_token_is (parser, CPP_NAME))
+    {
+      c_token *tok = c_parser_peek_token (parser);
+      const char *p = IDENTIFIER_POINTER (tok->value);
+      if (strcmp ("val", p) == 0)
+       kind = OMP_CLAUSE_LINEAR_VAL;
+      else if (strcmp ("uval", p) == 0)
+       kind = OMP_CLAUSE_LINEAR_UVAL;
+      if (c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN)
+       kind = OMP_CLAUSE_LINEAR_DEFAULT;
+      if (kind != OMP_CLAUSE_LINEAR_DEFAULT)
+       {
+         c_parser_consume_token (parser);
+         c_parser_consume_token (parser);
+       }
+    }
+
   nl = c_parser_omp_variable_list (parser, clause_loc,
                                   OMP_CLAUSE_LINEAR, list);
 
+  if (kind != OMP_CLAUSE_LINEAR_DEFAULT)
+    c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+
   if (c_parser_next_token_is (parser, CPP_COLON))
     {
       c_parser_consume_token (parser);
@@ -11500,6 +11526,7 @@ c_parser_omp_clause_linear (c_parser *pa
   for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
     {
       OMP_CLAUSE_LINEAR_STEP (c) = step;
+      OMP_CLAUSE_LINEAR_KIND (c) = kind;
     }
 
   c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
--- gcc/cp/parser.c.jj  2015-06-11 13:03:19.000000000 +0200
+++ gcc/cp/parser.c     2015-06-11 16:59:24.879484663 +0200
@@ -28965,7 +28965,11 @@ cp_parser_omp_clause_aligned (cp_parser
 
 /* OpenMP 4.0:
    linear ( variable-list )
-   linear ( variable-list : expression )  */
+   linear ( variable-list : expression )
+
+   OpenMP 4.1:
+   linear ( modifier ( variable-list ) )
+   linear ( modifier ( variable-list ) : expression ) */
 
 static tree
 cp_parser_omp_clause_linear (cp_parser *parser, tree list, 
@@ -28973,12 +28977,43 @@ cp_parser_omp_clause_linear (cp_parser *
 {
   tree nlist, c, step = integer_one_node;
   bool colon;
+  enum omp_clause_linear_kind kind = OMP_CLAUSE_LINEAR_DEFAULT;
 
   if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
     return list;
 
-  nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_LINEAR, list,
-                                         &colon);
+  if (!is_cilk_simd_fn
+      && cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+    {
+      tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+      const char *p = IDENTIFIER_POINTER (id);
+
+      if (strcmp ("ref", p) == 0)
+       kind = OMP_CLAUSE_LINEAR_REF;
+      else if (strcmp ("val", p) == 0)
+       kind = OMP_CLAUSE_LINEAR_VAL;
+      else if (strcmp ("uval", p) == 0)
+       kind = OMP_CLAUSE_LINEAR_UVAL;
+      if (cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN))
+       cp_lexer_consume_token (parser->lexer);
+      else
+       kind = OMP_CLAUSE_LINEAR_DEFAULT;
+    }
+
+  if (kind == OMP_CLAUSE_LINEAR_DEFAULT)
+    nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_LINEAR, list,
+                                           &colon);
+  else
+    {
+      nlist = cp_parser_omp_var_list (parser, OMP_CLAUSE_LINEAR, list);
+      colon = cp_lexer_next_token_is (parser->lexer, CPP_COLON);
+      if (colon)
+       cp_parser_require (parser, CPP_COLON, RT_COLON);
+      else if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+       cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+                                              /*or_comma=*/false,
+                                              /*consume_paren=*/true);
+    }
 
   if (colon)
     {
@@ -28999,7 +29034,10 @@ cp_parser_omp_clause_linear (cp_parser *
     }
 
   for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
-    OMP_CLAUSE_LINEAR_STEP (c) = step;
+    {
+      OMP_CLAUSE_LINEAR_STEP (c) = step;
+      OMP_CLAUSE_LINEAR_KIND (c) = kind;
+    }
 
   return nlist;
 }
--- gcc/cp/semantics.c.jj       2015-06-10 16:09:56.000000000 +0200
+++ gcc/cp/semantics.c  2015-06-11 17:12:29.324582468 +0200
@@ -5579,6 +5579,15 @@ finish_omp_clauses (tree clauses, bool a
          if (!type_dependent_expression_p (t))
            {
              tree type = TREE_TYPE (t);
+             if (OMP_CLAUSE_LINEAR_KIND (c) == OMP_CLAUSE_LINEAR_REF
+                 && TREE_CODE (type) != REFERENCE_TYPE)
+               {
+                 error ("linear clause with %<ref%> modifier applied to "
+                        "non-reference variable with %qT type",
+                        TREE_TYPE (t));
+                 remove = true;
+                 break;
+               }
              if (TREE_CODE (type) == REFERENCE_TYPE)
                type = TREE_TYPE (type);
              if (!INTEGRAL_TYPE_P (type)
@@ -5616,7 +5625,16 @@ finish_omp_clauses (tree clauses, bool a
                  tree type = TREE_TYPE (OMP_CLAUSE_DECL (c));
                  if (TREE_CODE (type) == REFERENCE_TYPE)
                    type = TREE_TYPE (type);
-                 if (TREE_CODE (type) == POINTER_TYPE)
+                 if (OMP_CLAUSE_LINEAR_KIND (c) == OMP_CLAUSE_LINEAR_REF)
+                   {
+                     type = TREE_TYPE (OMP_CLAUSE_DECL (c));
+                     t = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
+                                           sizetype, t);
+                     t = fold_build2_loc (OMP_CLAUSE_LOCATION (c),
+                                          MULT_EXPR, sizetype, t,
+                                          TYPE_SIZE_UNIT (type));
+                   }
+                 else if (TREE_CODE (type) == POINTER_TYPE)
                    {
                      tree d = convert_from_reference (OMP_CLAUSE_DECL (c));
                      t = pointer_int_sum (OMP_CLAUSE_LOCATION (c), PLUS_EXPR,


        Jakub

Reply via email to