Hello Everyone, 
        Attached, please find a patch that will implement SIMD enabled 
functions for C targeting the gomp-4_0-branch. Here are the ChangeLog entries. 
Is this OK to install?

gcc/c/ChangeLog
2013-11-18  Balaji V. Iyer  <balaji.v.i...@intel.com>

        * c-parser.c (c_parser_declaration_or_fndef): Added a check for
        attribute keyword before the function name.  If so, call the function
        to parse attributes.  Added a NULL parameter for c_parser_attributes.
        (c_parser_declspecs): Added a NULL parameter for c_parser_attributes.
        (c_parser_enum_specifier): Likewise.
        (c_parser_struct_or_union_specifier): Likewise.
        (c_parser_struct_declaration): Likewise.
        (c_parser_direct_declarator): Likewise.
        (c_parser_direct_declarator_inner): Likewise.
        (c_parser_parms_list_declarator): Likewise.
        (c_parser_parameter_declaration): Likewise.
        (c_parser_label): Likewise.
        (c_parser_objc_maybe_method_attributes): Likewise.
        (c_parser_objc_method_decl): Likewise.
        (c_parser_transaction_attributes): Likewise.
        (c_parser_elem_fn_vectorlength): New function.
        (c_parser_elem_fn_expr_list): Likewise.
        (c_finish_elem_fn_tokens): Likewise.
        (c_parser_elem_fn_attributes): Added a elem_fn_tokens parameter.  Added
        a check for vector attribute and if so call c_parser_elem_fn_expr_list.
        Also, called c_finish_elem_fn_tokens when Cilk Plus is enabled.

testsuite/ChangeLog
2013-11-18  Balaji V. Iyer  <balaji.v.i...@intel.com>

        * c-c++-common/cilk-plus/EF/ef_test.c: New test.
        * c-c++-common/cilk-plus/EF/vlength_errors.c: Likewise.
        * gcc.dg/cilk-plus/cilk-plus.exp: Added calls for the above tests.


Thanks,

Balaji V. Iyer.
Index: gcc/c/c-parser.c
===================================================================
--- gcc/c/c-parser.c    (revision 204981)
+++ gcc/c/c-parser.c    (working copy)
@@ -1148,7 +1148,7 @@
                                                          tree);
 static struct c_parm *c_parser_parameter_declaration (c_parser *, tree);
 static tree c_parser_simple_asm_expr (c_parser *);
-static tree c_parser_attributes (c_parser *);
+static tree c_parser_attributes (c_parser *, vec <c_token> *);
 static struct c_type_name *c_parser_type_name (c_parser *);
 static struct c_expr c_parser_initializer (c_parser *);
 static struct c_expr c_parser_braced_init (c_parser *, tree, bool);
@@ -1502,9 +1502,17 @@
       c_parser_peek_token (parser)->value = error_mark_node;
       fndef_ok = !nested;
     }
+  /* In Cilk Plus SIMD-enabled functions (formerly known as Elemental
+     Functions), attributes are used right above the functoin declaration or
+     the function itself.  */
+  tree attrs = NULL_TREE;
+  if (flag_enable_cilkplus
+      && c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+    attrs = c_parser_attributes (parser, &omp_declare_simd_clauses);
 
   c_parser_declspecs (parser, specs, true, true, start_attr_ok,
                      true, true, cla_nonabstract_decl);
+  specs->attrs = chainon (attrs, specs->attrs);
   if (parser->error)
     {
       c_parser_skip_to_end_of_block_or_statement (parser);
@@ -1676,7 +1684,7 @@
          if (c_parser_next_token_is_keyword (parser, RID_ASM))
            asm_name = c_parser_simple_asm_expr (parser);
          if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
-           postfix_attrs = c_parser_attributes (parser);
+           postfix_attrs = c_parser_attributes (parser, NULL);
          if (c_parser_next_token_is (parser, CPP_EQ))
            {
              tree d;
@@ -1815,7 +1823,7 @@
                }
              c_parser_consume_token (parser);
              if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
-               all_prefix_attrs = chainon (c_parser_attributes (parser),
+               all_prefix_attrs = chainon (c_parser_attributes (parser, NULL),
                                            prefix_attrs);
              else
                all_prefix_attrs = prefix_attrs;
@@ -2403,7 +2411,7 @@
        case RID_ATTRIBUTE:
          if (!attrs_ok)
            goto out;
-         attrs = c_parser_attributes (parser);
+         attrs = c_parser_attributes (parser, NULL);
          declspecs_add_attrs (loc, specs, attrs);
          break;
        case RID_ALIGNAS:
@@ -2452,7 +2460,7 @@
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM));
   enum_loc = c_parser_peek_token (parser)->location;
   c_parser_consume_token (parser);
-  attrs = c_parser_attributes (parser);
+  attrs = c_parser_attributes (parser, NULL);
   enum_loc = c_parser_peek_token (parser)->location;
   /* Set the location in case we create a decl now.  */
   c_parser_set_source_position_from_token (c_parser_peek_token (parser));
@@ -2532,7 +2540,7 @@
              break;
            }
        }
-      postfix_attrs = c_parser_attributes (parser);
+      postfix_attrs = c_parser_attributes (parser, NULL);
       ret.spec = finish_enum (type, nreverse (values),
                              chainon (attrs, postfix_attrs));
       ret.kind = ctsk_tagdef;
@@ -2623,7 +2631,7 @@
     }
   struct_loc = c_parser_peek_token (parser)->location;
   c_parser_consume_token (parser);
-  attrs = c_parser_attributes (parser);
+  attrs = c_parser_attributes (parser, NULL);
 
   /* Set the location in case we create a decl now.  */
   c_parser_set_source_position_from_token (c_parser_peek_token (parser));
@@ -2735,7 +2743,7 @@
                 recovered already.  Go on with the next field. */
            }
        }
-      postfix_attrs = c_parser_attributes (parser);
+      postfix_attrs = c_parser_attributes (parser, NULL);
       ret.spec = finish_struct (struct_loc, type, nreverse (contents),
                                chainon (attrs, postfix_attrs), struct_info);
       ret.kind = ctsk_tagdef;
@@ -2904,7 +2912,7 @@
              width = c_parser_expr_no_commas (parser, NULL).value;
            }
          if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
-           postfix_attrs = c_parser_attributes (parser);
+           postfix_attrs = c_parser_attributes (parser, NULL);
          d = grokfield (c_parser_peek_token (parser)->location,
                         declarator, specs, width, &all_prefix_attrs);
          decl_attributes (&d, chainon (postfix_attrs,
@@ -2912,7 +2920,7 @@
          DECL_CHAIN (d) = decls;
          decls = d;
          if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
-           all_prefix_attrs = chainon (c_parser_attributes (parser),
+           all_prefix_attrs = chainon (c_parser_attributes (parser, NULL),
                                        prefix_attrs);
          else
            all_prefix_attrs = prefix_attrs;
@@ -3226,7 +3234,7 @@
       tree attrs;
       struct c_declarator *inner;
       c_parser_consume_token (parser);
-      attrs = c_parser_attributes (parser);
+      attrs = c_parser_attributes (parser, NULL);
       if (kind != C_DTR_NORMAL
          && (c_parser_next_token_starts_declspecs (parser)
              || c_parser_next_token_is (parser, CPP_CLOSE_PAREN)))
@@ -3382,7 +3390,7 @@
       tree attrs;
       struct c_arg_info *args;
       c_parser_consume_token (parser);
-      attrs = c_parser_attributes (parser);
+      attrs = c_parser_attributes (parser, NULL);
       args = c_parser_parms_declarator (parser, id_present, attrs);
       if (args == NULL)
        return NULL;
@@ -3529,7 +3537,7 @@
          tree new_attrs;
          c_parser_consume_token (parser);
          mark_forward_parm_decls ();
-         new_attrs = c_parser_attributes (parser);
+         new_attrs = c_parser_attributes (parser, NULL);
          return c_parser_parms_list_declarator (parser, new_attrs, expr);
        }
       if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
@@ -3623,7 +3631,7 @@
       return NULL;
     }
   if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
-    postfix_attrs = c_parser_attributes (parser);
+    postfix_attrs = c_parser_attributes (parser, NULL);
   return build_c_parm (specs, chainon (postfix_attrs, prefix_attrs),
                       declarator);
 }
@@ -3760,6 +3768,148 @@
   return attr_name;
 }
 
+/* Parses the vectorlength vector attribute for the SIMD Enabled functions
+   in Cilk Plus.
+   Syntax:
+   vectorlength (<integer constant expression>)  */
+
+static bool
+c_parser_elem_fn_vectorlength (c_parser *parser, vec <c_token> *token_list)
+{
+  c_token *token = c_parser_peek_token (parser);
+  gcc_assert (simple_cst_equal (token->value,
+                                get_identifier ("vectorlength")) == 1);
+  token->value = get_identifier ("simdlen");
+  token_list->safe_push (*token);
+
+  c_parser_consume_token (parser);
+
+  token = c_parser_peek_token (parser);
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    return false;
+
+  token_list->safe_push (*token);
+
+  token = c_parser_peek_token (parser);
+  tree value = token->value;
+  if (!value)
+    {
+      error_at (token->location, "expected vectorlength value");
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+      return false;
+    }
+  c_parser_consume_token (parser);
+  if (TREE_CODE (value) != INTEGER_CST)
+    {
+      error_at (token->location, "vectorlength must be a constant integer");
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+      return false;
+    }
+  if (!integer_pow2p (value))
+    {
+      error_at (token->location, "vectorlength must be a power of 2");
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+      return false;
+    }
+  token_list->safe_push (*token);
+
+  token = c_parser_peek_token (parser);
+  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+    return false;
+  token_list->safe_push (*token);
+  return true;
+}
+
+/* Parses the vector attribute of SIMD enabled functions in Cilk Plus.
+   Syntax:
+   vector
+   vector (<vector attributes>).  */
+
+static void
+c_parser_elem_fn_expr_list (c_parser *parser, c_token vec_token,
+                            vec <c_token> *elem_fn_tokens)
+{
+  gcc_assert (simple_cst_equal (vec_token.value,
+                                get_identifier ("vector")) == 1);
+  int paren_scope = 0;
+  /* Replace the vector keyword with SIMD.  */
+  vec_token.value = get_identifier ("simd");
+  elem_fn_tokens->safe_push (vec_token);
+
+  /* Consume the "vector" token.  */
+  c_parser_consume_token (parser);
+
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+    {
+      c_parser_consume_token (parser);
+      paren_scope++;
+    }
+  while (paren_scope > 0)
+    {
+      c_token *token = c_parser_peek_token (parser);
+      if (token->type == CPP_OPEN_PAREN)
+        paren_scope++;
+      else if (token->type == CPP_CLOSE_PAREN)
+        paren_scope--;
+      if (token->type == CPP_NAME
+          && TREE_CODE (token->value) == IDENTIFIER_NODE)
+        {
+          tree value = token->value;
+          if (simple_cst_equal (value, get_identifier ("mask")) == 1)
+            token->value = get_identifier ("inbranch");
+          else if (simple_cst_equal (value, get_identifier ("nomask")) == 1)
+            token->value = get_identifier ("notinbranch");
+          else if (simple_cst_equal (value,
+                                     get_identifier ("vectorlength")) == 1)
+            {
+              if (!c_parser_elem_fn_vectorlength (parser, elem_fn_tokens))
+                {
+                  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+                  /* No reason to keep any of these tokens if the
+                     vectorlength is messed up.  */
+                  elem_fn_tokens->release ();
+                  return;
+                }
+              else
+                continue;
+            }
+          /* linear and uniform are the same between SIMD
+             enabled functions and #pragma omp declare simd.  */
+        }
+      /* Do not push the last ')'  */
+      if (!(token->type == CPP_CLOSE_PAREN && paren_scope == 0))
+        elem_fn_tokens->safe_push (*token);
+      c_parser_consume_token (parser);
+    }
+  c_token eol_token;
+  memset (&eol_token, 0, sizeof (eol_token));
+  eol_token.type = CPP_PRAGMA_EOL;
+  elem_fn_tokens->safe_push (eol_token);
+  return;
+}
+
+/* Add 2 CPP_EOF at the end of ELEM_FN_TOKENS vector.  */
+
+static void
+c_finish_elem_fn_tokens (vec <c_token> *elem_fn_tokens)
+{
+  /* If the token is a CPP_EOF, then there is no reason to stuff it again
+     with 2 EOF.  If it is NULL, then we didn't find any vector keywords.  */
+  if (!elem_fn_tokens || *elem_fn_tokens == vNULL 
+      || (*elem_fn_tokens)[0].type == CPP_EOF)
+    return;
+    /* Since we are converting an attribute to a pragma, we need to end the
+     attribute with PRAGMA_EOL.  OpenMP guys would like to have 2 CPP_EOF
+     at the end, and so we insert that also.  */
+  c_token eof_token;
+  memset (&eof_token, 0, sizeof (eof_token));
+  eof_token.type = CPP_PRAGMA_EOL;
+  elem_fn_tokens->safe_push (eof_token);
+  eof_token.type = CPP_EOF;
+  elem_fn_tokens->safe_push (eof_token);
+  elem_fn_tokens->safe_push (eof_token);
+}
+
 /* Parse (possibly empty) attributes.  This is a GNU extension.
 
    attributes:
@@ -3788,7 +3938,7 @@
    allow identifiers declared as types to start the arguments?  */
 
 static tree
-c_parser_attributes (c_parser *parser)
+c_parser_attributes (c_parser *parser, vec <c_token> *elem_fn_tokens)
 {
   tree attrs = NULL_TREE;
   while (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
@@ -3824,6 +3974,13 @@
          attr_name = c_parser_attribute_any_word (parser);
          if (attr_name == NULL)
            break;
+         if (flag_enable_cilkplus
+             && simple_cst_equal (attr_name, get_identifier ("vector")) == 1)
+           {
+             c_token *v_token = c_parser_peek_token (parser);
+             c_parser_elem_fn_expr_list (parser, *v_token, elem_fn_tokens);
+             continue;
+           }
          c_parser_consume_token (parser);
          if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
            {
@@ -3904,6 +4061,9 @@
        }
       parser->lex_untranslated_string = false;
     }
+
+  if (flag_enable_cilkplus)
+    c_finish_elem_fn_tokens (elem_fn_tokens);
   return attrs;
 }
 
@@ -4588,7 +4748,7 @@
       c_parser_consume_token (parser);
       gcc_assert (c_parser_next_token_is (parser, CPP_COLON));
       c_parser_consume_token (parser);
-      attrs = c_parser_attributes (parser);
+      attrs = c_parser_attributes (parser, NULL);
       tlab = define_label (loc2, name);
       if (tlab)
        {
@@ -8386,7 +8546,7 @@
     }
 
   if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
-    *attributes = c_parser_attributes (parser);
+    *attributes = c_parser_attributes (parser, NULL);
 
   /* If there were no attributes here, just report any earlier error.  */
   if (*attributes == NULL_TREE || bad)
@@ -8475,7 +8635,7 @@
            }
          /* New ObjC allows attributes on method parameters.  */
          if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
-           param_attr = c_parser_attributes (parser);
+           param_attr = c_parser_attributes (parser, NULL);
          if (c_parser_next_token_is_not (parser, CPP_NAME))
            {
              c_parser_error (parser, "expected identifier");
@@ -13630,7 +13790,7 @@
   tree attr_name, attr = NULL;
 
   if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
-    return c_parser_attributes (parser);
+    return c_parser_attributes (parser, NULL);
 
   if (!c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
     return NULL_TREE;
Index: gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp
===================================================================
--- gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp        (revision 204981)
+++ gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp        (working copy)
@@ -59,6 +59,12 @@
     dg-runtest [lsort [glob -nocomplain 
$srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O3 -flto -g -fcilkplus" " "
 }
 
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/EF/*.c]] " 
-g" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/EF/*.c]] " 
-O1" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/EF/*.c]] " 
-O2 -std=c99" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/EF/*.c]] " 
-O2 -ftree-vectorize" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/EF/*.c]] " 
-O3 -g" " "
+
 dg-finish
 
 unset TEST_EXTRA_LIBS
Index: gcc/testsuite/c-c++-common/cilk-plus/EF/vlength_errors.c
===================================================================
--- gcc/testsuite/c-c++-common/cilk-plus/EF/vlength_errors.c    (revision 0)
+++ gcc/testsuite/c-c++-common/cilk-plus/EF/vlength_errors.c    (revision 0)
@@ -0,0 +1,49 @@
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus -Wunknown-pragmas" } */
+
+#define Q 4
+
+int z = Q;
+
+__attribute__ ((vector (uniform(x), vectorlength (), linear (y:1) ))) /* { 
dg-error "expected vectorlength value" } */
+int func2 (int x, int y)
+{
+  int zq = 5;
+  return x + (y*zq);
+}
+
+__attribute__ ((vector (uniform(x), linear (y:1), vectorlength (4.5) ))) /* { 
dg-error "vectorlength must be a constant integer" } */
+int func3 (int x, int y)
+{
+  int zq = 5;
+  return x + (y*zq);
+}
+
+__attribute__ ((vector (uniform(x), linear (y:1), vectorlength (z) ))) /* { 
dg-error "vectorlength must be a constant integer" } */
+int func4 (int x, int y)
+{
+  int zq = 5;
+  return x + (y*zq);
+}
+
+__attribute__ ((vector (uniform(x), linear (y:1), vectorlength (Q) ))) /* This 
is OK!  */
+int func5 (int x, int y)
+{
+  int zq = 5;
+  return x + (y*zq);
+}
+
+__attribute__ ((vector (uniform(x), vectorlength (z), linear (y:1)))) /* { 
dg-error "vectorlength must be a constant integer" } */
+int func6 (int x, int y)
+{
+  int zq = 5;
+  return x + (y*zq);
+}
+
+int main (void)
+{
+  int ii = 0, q = 5;
+  for (ii = 0; ii < 10; ii++)
+    q += func2 (z, ii);
+  return q;
+}
Index: gcc/testsuite/c-c++-common/cilk-plus/EF/ef_test.c
===================================================================
--- gcc/testsuite/c-c++-common/cilk-plus/EF/ef_test.c   (revision 0)
+++ gcc/testsuite/c-c++-common/cilk-plus/EF/ef_test.c   (revision 0)
@@ -0,0 +1,78 @@
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus -Wunknown-pragmas" } */
+
+/* Tests the clauses in several combinations put in different locations.  */
+/* This is mostly a parser test.  */
+#define Q 4
+
+int z = Q;
+
+ __attribute__ ((vector (uniform(x), linear (y:1), vectorlength (4) )))
+int func (int x, int y)
+{
+  int zq = 5;
+  return x + (y*zq);
+}
+ __attribute__ ((vector (uniform(x), vectorlength (2), linear (y:1) )))
+int func2 (int x, int y)
+{
+  int zq = 5;
+  return x + (y*zq);
+}
+
+__attribute__ ((vector (uniform(y), linear (x), vectorlength (4) )))
+int func3 (int x, int y)
+{
+  int zq = 5;
+  return x + (y*zq);
+}
+
+__attribute__ ((vector (uniform(x), linear (y:1), mask)))
+int func4 (int x, int y)
+{
+  int zq = 5;
+  return x + (y*zq);
+}
+
+__attribute__ ((vector (uniform(x), linear (y:1), nomask)))
+int func5 (int x, int y)
+{
+  int zq = 5;
+  return x + (y*zq);
+}
+
+__attribute__ ((vector (uniform(x), mask, linear (y:1)))) 
+int func6 (int x, int y)
+{
+  int zq = 5;
+  return x + (y*zq);
+}
+
+__attribute__ ((vector (uniform (x), mask, linear (y:1)), vector))
+int func7 (int x, int y)
+{
+  int zq = 5;
+  return x + (y*zq);
+}
+
+__attribute__ ((vector (uniform (x), mask, linear (y:1)), vector (uniform (y), 
mask)))
+int func8 (int x, int y)
+{
+  int zq = 5;
+  return x + (y*zq);
+}
+
+__attribute__ ((vector, vector (uniform (y), mask)))
+int func9 (int x, int y)
+{
+  int zq = 5;
+  return x + (y*zq);
+}
+
+int main (int argc, char *argv[])
+{
+  int ii = 0, q = 5;
+  for (ii = 0; ii < 10; ii++)
+    q += func (argc, ii);
+  return q;
+}

Reply via email to