diff mbox

[PING] : [GOMP4] [PATCH] SIMD-Enabled Functions (formerly Elemental functions) for C

Message ID BF230D13CA30DD48930C31D4099330003A4B2811@FMSMSX101.amr.corp.intel.com
State New
Headers show

Commit Message

Iyer, Balaji V Dec. 17, 2013, 5:23 p.m. UTC
Hi Jakub,
	Please see attached patch and my answers to your questions below.

	Aldy, I have made a couple changes to #pragma simd routines, can you please give me your blessing on those?

Thanks,

Balaji V. Iyer.

> -----Original Message-----
> From: gcc-patches-owner@gcc.gnu.org [mailto:gcc-patches-
> owner@gcc.gnu.org] On Behalf Of Jakub Jelinek
> Sent: Monday, December 16, 2013 5:01 PM
> To: Iyer, Balaji V; Joseph S. Myers
> Cc: Aldy Hernandez; 'gcc-patches@gcc.gnu.org'
> Subject: Re: [PING]: [GOMP4] [PATCH] SIMD-Enabled Functions (formerly
> Elemental functions) for C
> 
> On Mon, Dec 16, 2013 at 09:41:43PM +0000, Iyer, Balaji V wrote:
> > --- gcc/c/c-parser.c	(revision 205759)
> > +++ gcc/c/c-parser.c	(working copy)
> > @@ -208,6 +208,12 @@
> >    /* True if we are in a context where the Objective-C "Property attribute"
> >       keywords are valid.  */
> >    BOOL_BITFIELD objc_property_attr_context : 1;
> > +
> > +  /* Cilk Plus specific parser/lexer information.  */
> > +
> > +  /* Buffer to hold all the tokens from parsing the vector attribute for the
> > +     SIMD-enabled functions (formerly known as elemental functions).
> > + */  vec <c_token, va_gc> *cilk_simd_fn_tokens;
> >  } c_parser;
> 
> Joseph, is this ok for you?
> 
> > +/* Returns true of NAME is an IDENTIFIER_NODE with identiifer "vector,"
> > +   "__vector" or "__vector__."  */
> > +
> > +static bool
> 
> static inline bool
> 

Fixed.

> > +is_cilkplus_vector_p (tree name)
> > +{
> > +  if (flag_enable_cilkplus
> > +      && (simple_cst_equal (name, get_identifier ("vector")) == 1
> > +	  || simple_cst_equal (name, get_identifier ("__vector")) == 1
> > +	  || simple_cst_equal (name, get_identifier ("__vector__")) == 1))
> > +    return true;
> > +  return false;
> > +}
> 
> Why not just
>   return flag_enable_cilkplus && is_attribute_p ("vector", name); ?

Fixed.

> 
> > +#define CILK_SIMD_FN_CLAUSE_MASK				\
> > +	( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN)
> 	\
> > +	| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR)
> 	\
> > +	| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM)
> 	\
> > +	| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INBRANCH)
> 	\
> > +	| (OMP_CLAUSE_MASK_1 <<
> PRAGMA_OMP_CLAUSE_NOTINBRANCH))
> 
> I thought you'd instead add there PRAGMA_CILK_CLAUSE_VECTORLENGTH,
> PRAGMA_CILK_CLAUSE_MASK and PRAGMA_CILK_CLAUSE_NOMASK (or
> similar).
> 

Yes, I renamed them to PRAGMA_CILK_CLAUSE_*

> > +      if (token->type == CPP_NAME
> > +	  && TREE_CODE (token->value) == IDENTIFIER_NODE)
> > +	if (simple_cst_equal (token->value,
> > +			      get_identifier ("vectorlength")) == 1)
> 
> Why the simple_cst_equal + get_identifier?  I mean, strcmp on
> IDENTIFIER_POINTER should be cheaper, and done elsewhere in c-parser.c.
> 

Fixed.

> > +	  {
> > +	    if (!c_parser_cilk_clause_vectorlength (parser, NULL, true))
> 
> Why do you parse it here?  Just parse it when parsing other clauses, and only
> during parsing of vectorlength clause create OMP_CLAUSE_SAFELEN out of it
> (after all the verifications).
> 
> > +      if (is_cilk_simd_fn && TREE_CODE (step) == PARM_DECL)
> > +	{
> > +	  error_at (clause_loc, "using parameters for %<linear%> step is "
> > +		    "not supported in this release");
> > +	  step = integer_one_node;
> 
> That would be sorry, not error_at.
> 

Fixed.

> >        here = c_parser_peek_token (parser)->location;
> > -      c_kind = c_parser_omp_clause_name (parser);
> > +
> > +      if (mask == CILK_SIMD_FN_CLAUSE_MASK)
> 
> Ugh, no.
> 
> > +	c_kind = c_parser_cilk_simd_fn_clause_name (parser);
> > +      else
> > +	c_kind = c_parser_omp_clause_name (parser);
> 
> Always parse it the same, just use PRAGMA_CILK_CLAUSE_* for the Cilk+
> specific clauses.

Well, if  I don't have a different "*_clause_name" function, then I have to modify the c_parser_omp_clause_name to add the support for things like "vectorlength", "mask and "unmask." Am I right?

Now, if I do that, then if we compile the following 2 lines:

#pragma omp declare simd vectorlength (4)
void foo () 

with -fcilkplus, they will be parsed correctly, when it should give an error.

> >
> >        switch (c_kind)
> >  	{
> > @@ -10933,7 +11092,8 @@
> >  	  c_name = "aligned";
> >  	  break;
> >  	case PRAGMA_OMP_CLAUSE_LINEAR:
> > -	  clauses = c_parser_omp_clause_linear (parser, clauses);
> > +	  clauses = c_parser_omp_clause_linear
> > +	    (parser, clauses, mask == CILK_SIMD_FN_CLAUSE_MASK);
> 
> Again, this is too ugly.  Perhaps check if (mask &
> PRAGMA_CILK_CLAUSE_VECTORLENGTH) != 0 or similar.
> 

The reason why I do mask == CILK_SIMD_FN_CLAUSE_MASk is to set the bool parameter to true if we are compiling the Cilk Plus SIMD-enabled function. This bool is checked to give the sorry error that using parameter for step-size is not implemented.

> 	Jakub

Comments

Jakub Jelinek Dec. 17, 2013, 6:25 p.m. UTC | #1
Hi!

On Tue, Dec 17, 2013 at 05:23:43PM +0000, Iyer, Balaji V wrote:
> +/* Returns name of the next clause in Cilk Plus SIMD-enabled function's
> +   attribute.
> +   If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and
> +   the token is not consumed.  Otherwise appropriate pragma_omp_clause is
> +   returned and the token is consumed.  */
> +
> +static pragma_omp_clause
> +c_parser_cilk_simd_fn_clause_name (c_parser *parser)
> +{
> +  pragma_omp_clause result = PRAGMA_OMP_CLAUSE_NONE;
> +
> +  if (c_parser_next_token_is_not (parser, CPP_NAME))
> +    return result;
> +  
> +  const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
> +  if (!strcmp (p, "vectorlength"))
> +    result = PRAGMA_CILK_CLAUSE_VECTORLENGTH;
> +  else if (!strcmp (p, "uniform"))
> +    result = PRAGMA_CILK_CLAUSE_UNIFORM;
> +  else if (!strcmp (p, "linear"))
> +    result = PRAGMA_CILK_CLAUSE_LINEAR;
> +  else if (!strcmp (p, "mask"))
> +    result = PRAGMA_CILK_CLAUSE_MASK;
> +  else if (!strcmp (p, "nomask"))
> +    result = PRAGMA_CILK_CLAUSE_UNMASK;
> +
> +  if (result != PRAGMA_OMP_CLAUSE_NONE)
> +    c_parser_consume_token (parser);
> +  return result;
> +}

No, this isn't what I meant.  I meant that you add the 3 new clause names
to c_parser_omp_clause_name (and use PRAGMA_CILK_* for those).

> +      if (token->type == CPP_NAME
> +	  && TREE_CODE (token->value) == IDENTIFIER_NODE)       
> +	if (!strcmp (IDENTIFIER_POINTER (token->value), "vectorlength"))
> +	  {
> +	    if (!c_parser_cilk_clause_vectorlength (parser, NULL, true))
> +	      {
> +		c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
> +		return;
> +	      }
> +	    else
> +	      continue;
> +	  }

Why do you need this at all?  I'd expect you just remove this whole if and
the c_parser_cilk_clause_vectorlength function, and instead just parse
vectorlength normally when you see PRAGMA_CILK_CLAUSE_VECTORLENGTH.

> +	  sorry ("using parameters for %<linear%> step is not supported "
> +		 "in this release");

... is not supported yet".

> -      c_kind = c_parser_omp_clause_name (parser);
> + 
> +      if (mask == CILK_SIMD_FN_CLAUSE_MASK)
> +	c_kind = c_parser_cilk_simd_fn_clause_name (parser);
> +      else
> +	c_kind = c_parser_omp_clause_name (parser);

Please revert this.

> @@ -10933,7 +11088,8 @@
>  	  c_name = "aligned";
>  	  break;
>  	case PRAGMA_OMP_CLAUSE_LINEAR:
> -	  clauses = c_parser_omp_clause_linear (parser, clauses);
> +	  clauses = c_parser_omp_clause_linear
> +	    (parser, clauses, mask == CILK_SIMD_FN_CLAUSE_MASK);

Please test for some particular bit in the mask, not == on the masks.

	Jakub
diff mbox

Patch

Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	(revision 205759)
+++ gcc/c-family/c-common.c	(working copy)
@@ -771,6 +771,8 @@ 
 			      handle_returns_nonnull_attribute, false },
   { "omp declare simd",       0, -1, true,  false, false,
 			      handle_omp_declare_simd_attribute, false },
+  { "cilk simd function",     0, -1, true,  false, false,
+			      handle_omp_declare_simd_attribute, false },
   { "omp declare target",     0, 0, true, false, false,
 			      handle_omp_declare_target_attribute, false },
   { "bnd_variable_size",      0, 0, true,  false, false,
Index: gcc/c-family/c-pragma.h
===================================================================
--- gcc/c-family/c-pragma.h	(revision 205759)
+++ gcc/c-family/c-pragma.h	(working copy)
@@ -104,20 +104,21 @@ 
   PRAGMA_OMP_CLAUSE_THREAD_LIMIT,
   PRAGMA_OMP_CLAUSE_TO,
   PRAGMA_OMP_CLAUSE_UNIFORM,
-  PRAGMA_OMP_CLAUSE_UNTIED
+  PRAGMA_OMP_CLAUSE_UNTIED,
+  
+  /* Clauses for Cilk Plus SIMD-enabled function.  */
+  PRAGMA_CILK_CLAUSE_NONE = PRAGMA_OMP_CLAUSE_NONE,
+  PRAGMA_CILK_CLAUSE_LINEAR = PRAGMA_OMP_CLAUSE_LINEAR,
+  PRAGMA_CILK_CLAUSE_MASK = PRAGMA_OMP_CLAUSE_INBRANCH,
+  PRAGMA_CILK_CLAUSE_PRIVATE = PRAGMA_OMP_CLAUSE_PRIVATE,
+  PRAGMA_CILK_CLAUSE_FIRSTPRIVATE = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE,
+  PRAGMA_CILK_CLAUSE_LASTPRIVATE = PRAGMA_OMP_CLAUSE_LASTPRIVATE,
+  PRAGMA_CILK_CLAUSE_REDUCTION = PRAGMA_OMP_CLAUSE_REDUCTION,
+  PRAGMA_CILK_CLAUSE_UNIFORM = PRAGMA_OMP_CLAUSE_UNIFORM,
+  PRAGMA_CILK_CLAUSE_UNMASK = PRAGMA_OMP_CLAUSE_NOTINBRANCH,
+  PRAGMA_CILK_CLAUSE_VECTORLENGTH = PRAGMA_OMP_CLAUSE_SIMDLEN
 } pragma_omp_clause;
 
-/* All Cilk Plus #pragma omp clauses.  */
-typedef enum pragma_cilk_clause {
-  PRAGMA_CILK_CLAUSE_NONE = 0,
-  PRAGMA_CILK_CLAUSE_VECTORLENGTH,
-  PRAGMA_CILK_CLAUSE_LINEAR,
-  PRAGMA_CILK_CLAUSE_PRIVATE,
-  PRAGMA_CILK_CLAUSE_FIRSTPRIVATE,
-  PRAGMA_CILK_CLAUSE_LASTPRIVATE,
-  PRAGMA_CILK_CLAUSE_REDUCTION
-} pragma_cilk_clause;
-
 extern struct cpp_reader* parse_in;
 
 /* It's safe to always leave visibility pragma enabled as if
Index: gcc/c/c-parser.c
===================================================================
--- gcc/c/c-parser.c	(revision 205759)
+++ gcc/c/c-parser.c	(working copy)
@@ -208,6 +208,12 @@ 
   /* True if we are in a context where the Objective-C "Property attribute"
      keywords are valid.  */
   BOOL_BITFIELD objc_property_attr_context : 1;
+
+  /* Cilk Plus specific parser/lexer information.  */
+
+  /* Buffer to hold all the tokens from parsing the vector attribute for the
+     SIMD-enabled functions (formerly known as elemental functions).  */
+  vec <c_token, va_gc> *cilk_simd_fn_tokens;
 } c_parser;
 
 
@@ -1246,6 +1252,7 @@ 
 static void c_parser_cilk_simd (c_parser *);
 static bool c_parser_cilk_verify_simd (c_parser *, enum pragma_context);
 static tree c_parser_array_notation (location_t, c_parser *, tree, tree);
+static bool c_parser_cilk_clause_vectorlength (c_parser *, tree *, bool);
 
 /* Parse a translation unit (C90 6.7, C99 6.9).
 
@@ -1647,7 +1654,8 @@ 
 					C_DTR_NORMAL, &dummy);
       if (declarator == NULL)
 	{
-	  if (omp_declare_simd_clauses.exists ())
+	  if (omp_declare_simd_clauses.exists ()
+	      || !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
 	    c_finish_omp_declare_simd (parser, NULL_TREE, NULL_TREE,
 				       omp_declare_simd_clauses);
 	  c_parser_skip_to_end_of_block_or_statement (parser);
@@ -1734,7 +1742,8 @@ 
 				  chainon (postfix_attrs, all_prefix_attrs));
 		  if (!d)
 		    d = error_mark_node;
-		  if (omp_declare_simd_clauses.exists ())
+		  if (omp_declare_simd_clauses.exists ()
+		      || !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
 		    c_finish_omp_declare_simd (parser, d, NULL_TREE,
 					       omp_declare_simd_clauses);
 		}
@@ -1746,7 +1755,8 @@ 
 				  chainon (postfix_attrs, all_prefix_attrs));
 		  if (!d)
 		    d = error_mark_node;
-		  if (omp_declare_simd_clauses.exists ())
+		  if (omp_declare_simd_clauses.exists ()
+		      || !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
 		    c_finish_omp_declare_simd (parser, d, NULL_TREE,
 					       omp_declare_simd_clauses);
 		  start_init (d, asm_name, global_bindings_p ());
@@ -1774,7 +1784,8 @@ 
 	      tree d = start_decl (declarator, specs, false,
 				   chainon (postfix_attrs,
 					    all_prefix_attrs));
-	      if (omp_declare_simd_clauses.exists ())
+	      if (omp_declare_simd_clauses.exists ()
+		  || !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
 		{
 		  tree parms = NULL_TREE;
 		  if (d && TREE_CODE (d) == FUNCTION_DECL)
@@ -1902,7 +1913,8 @@ 
 	c_parser_declaration_or_fndef (parser, false, false, false,
 				       true, false, NULL, vNULL);
       store_parm_decls ();
-      if (omp_declare_simd_clauses.exists ())
+      if (omp_declare_simd_clauses.exists ()
+	  || !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
 	c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
 				   omp_declare_simd_clauses);
       DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
@@ -3765,6 +3777,130 @@ 
   return attr_name;
 }
 
+/* Returns name of the next clause in Cilk Plus SIMD-enabled function's
+   attribute.
+   If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and
+   the token is not consumed.  Otherwise appropriate pragma_omp_clause is
+   returned and the token is consumed.  */
+
+static pragma_omp_clause
+c_parser_cilk_simd_fn_clause_name (c_parser *parser)
+{
+  pragma_omp_clause result = PRAGMA_OMP_CLAUSE_NONE;
+
+  if (c_parser_next_token_is_not (parser, CPP_NAME))
+    return result;
+  
+  const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+  if (!strcmp (p, "vectorlength"))
+    result = PRAGMA_CILK_CLAUSE_VECTORLENGTH;
+  else if (!strcmp (p, "uniform"))
+    result = PRAGMA_CILK_CLAUSE_UNIFORM;
+  else if (!strcmp (p, "linear"))
+    result = PRAGMA_CILK_CLAUSE_LINEAR;
+  else if (!strcmp (p, "mask"))
+    result = PRAGMA_CILK_CLAUSE_MASK;
+  else if (!strcmp (p, "nomask"))
+    result = PRAGMA_CILK_CLAUSE_UNMASK;
+
+  if (result != PRAGMA_OMP_CLAUSE_NONE)
+    c_parser_consume_token (parser);
+  return result;
+}
+
+/* Returns true of NAME is an IDENTIFIER_NODE with identiifer "vector,"
+   "__vector" or "__vector__."  */
+
+static inline bool
+is_cilkplus_vector_p (tree name)
+{ 
+  if (flag_enable_cilkplus && is_attribute_p ("vector", name)) 
+    return true;
+  return false;
+}
+
+#define CILK_SIMD_FN_CLAUSE_MASK				\
+	((OMP_CLAUSE_MASK_1 << PRAGMA_CILK_CLAUSE_VECTORLENGTH)	\
+	 | (OMP_CLAUSE_MASK_1 << PRAGMA_CILK_CLAUSE_LINEAR)	\
+	 | (OMP_CLAUSE_MASK_1 << PRAGMA_CILK_CLAUSE_UNIFORM)	\
+	 | (OMP_CLAUSE_MASK_1 << PRAGMA_CILK_CLAUSE_MASK)	\
+	 | (OMP_CLAUSE_MASK_1 << PRAGMA_CILK_CLAUSE_UNMASK))
+
+/* Parses the vector attribute of SIMD enabled functions in Cilk Plus.
+   VEC_TOKEN is the "vector" token that is replaced with "simd" and
+   pushed into the token list. 
+   Syntax:
+   vector
+   vector (<vector attributes>).  */
+
+static void
+c_parser_cilk_simd_fn_vector_attrs (c_parser *parser, c_token vec_token)
+{
+  gcc_assert (is_cilkplus_vector_p (vec_token.value));
+  
+  int paren_scope = 0;
+  vec_safe_push (parser->cilk_simd_fn_tokens, 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)       
+	if (!strcmp (IDENTIFIER_POINTER (token->value), "vectorlength"))
+	  {
+	    if (!c_parser_cilk_clause_vectorlength (parser, NULL, true))
+	      {
+		c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+		return;
+	      }
+	    else
+	      continue;
+	  }
+      /* Do not push the last ')' since we are not pushing the '('.  */
+      if (!(token->type == CPP_CLOSE_PAREN && paren_scope == 0))
+	vec_safe_push (parser->cilk_simd_fn_tokens, *token);
+      c_parser_consume_token (parser);
+    }
+  
+  /* Since we are converting an attribute to a pragma, we need to end the
+     attribute with PRAGMA_EOL.  */
+  c_token eol_token;
+  memset (&eol_token, 0, sizeof (eol_token));
+  eol_token.type = CPP_PRAGMA_EOL;
+  vec_safe_push (parser->cilk_simd_fn_tokens, eol_token);
+}
+
+/* Add 2 CPP_EOF at the end of PARSER->ELEM_FN_TOKENS vector.  */
+
+static void
+c_finish_cilk_simd_fn_tokens (c_parser *parser)
+{
+  c_token last_token = parser->cilk_simd_fn_tokens->last ();
+
+  /* c_parser_attributes is called in several places, so if these EOF
+     tokens are already inserted, then don't do them again.  */
+  if (last_token.type == CPP_EOF)
+    return;
+  
+  /* Two CPP_EOF token are added as a safety net since the normal C
+     front-end has two token look-ahead.  */
+  c_token eof_token;
+  eof_token.type = CPP_EOF;
+  vec_safe_push (parser->cilk_simd_fn_tokens, eof_token);
+  vec_safe_push (parser->cilk_simd_fn_tokens, eof_token);
+}
+
 /* Parse (possibly empty) attributes.  This is a GNU extension.
 
    attributes:
@@ -3829,6 +3965,12 @@ 
 	  attr_name = c_parser_attribute_any_word (parser);
 	  if (attr_name == NULL)
 	    break;
+	  if (is_cilkplus_vector_p (attr_name))		  
+	    {
+	      c_token *v_token = c_parser_peek_token (parser);
+	      c_parser_cilk_simd_fn_vector_attrs (parser, *v_token);
+	      continue;
+	    }
 	  c_parser_consume_token (parser);
 	  if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
 	    {
@@ -3909,6 +4051,9 @@ 
 	}
       parser->lex_untranslated_string = false;
     }
+
+  if (flag_enable_cilkplus && !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
+    c_finish_cilk_simd_fn_tokens (parser);
   return attrs;
 }
 
@@ -10401,7 +10546,7 @@ 
    linear ( variable-list : expression ) */
 
 static tree
-c_parser_omp_clause_linear (c_parser *parser, tree list)
+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;
@@ -10418,6 +10563,12 @@ 
       step = c_parser_expression (parser).value;
       mark_exp_read (step);
       step = c_fully_fold (step, false, NULL);
+      if (is_cilk_simd_fn && TREE_CODE (step) == PARM_DECL)
+	{
+	  sorry ("using parameters for %<linear%> step is not supported "
+		 "in this release");
+	  step = integer_one_node;
+	}
       if (!INTEGRAL_TYPE_P (TREE_TYPE (step)))
 	{
 	  error_at (clause_loc, "%<linear%> clause step expression must "
@@ -10789,7 +10940,11 @@ 
 	c_parser_consume_token (parser);
 
       here = c_parser_peek_token (parser)->location;
-      c_kind = c_parser_omp_clause_name (parser);
+ 
+      if (mask == CILK_SIMD_FN_CLAUSE_MASK)
+	c_kind = c_parser_cilk_simd_fn_clause_name (parser);
+      else
+	c_kind = c_parser_omp_clause_name (parser);
 
       switch (c_kind)
 	{
@@ -10933,7 +11088,8 @@ 
 	  c_name = "aligned";
 	  break;
 	case PRAGMA_OMP_CLAUSE_LINEAR:
-	  clauses = c_parser_omp_clause_linear (parser, clauses);
+	  clauses = c_parser_omp_clause_linear
+	    (parser, clauses, mask == CILK_SIMD_FN_CLAUSE_MASK);
 	  c_name = "linear";
 	  break;
 	case PRAGMA_OMP_CLAUSE_DEPEND:
@@ -12754,10 +12910,20 @@ 
 c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms,
 			   vec<c_token> clauses)
 {
+
+  if (flag_enable_cilkplus
+      && clauses.exists () && !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
+    {
+      error ("%<#pragma omp declare simd%> cannot be used in the same "
+	     "function marked as a Cilk Plus SIMD-enabled function");
+      vec_free (parser->cilk_simd_fn_tokens);
+      return;
+    }
+  
   /* Normally first token is CPP_NAME "simd".  CPP_EOF there indicates
      error has been reported and CPP_PRAGMA that c_finish_omp_declare_simd
      has already processed the tokens.  */
-  if (clauses[0].type == CPP_EOF)
+  if (clauses.exists () && clauses[0].type == CPP_EOF)
     return;
   if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL)
     {
@@ -12766,7 +12932,7 @@ 
       clauses[0].type = CPP_EOF;
       return;
     }
-  if (clauses[0].type != CPP_NAME)
+  if (clauses.exists () && clauses[0].type != CPP_NAME)
     {
       error_at (DECL_SOURCE_LOCATION (fndecl),
 		"%<#pragma omp declare simd%> not immediately followed by "
@@ -12780,23 +12946,49 @@ 
 
   unsigned int tokens_avail = parser->tokens_avail;
   gcc_assert (parser->tokens == &parser->tokens_buf[0]);
-  parser->tokens = clauses.address ();
-  parser->tokens_avail = clauses.length ();
-
+  bool is_cilkplus_cilk_simd_fn = false;
+  
+  if (flag_enable_cilkplus && !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
+    {
+      parser->tokens = parser->cilk_simd_fn_tokens->address ();
+      parser->tokens_avail = vec_safe_length (parser->cilk_simd_fn_tokens);
+      is_cilkplus_cilk_simd_fn = true;
+    }
+  else
+    {
+      parser->tokens = clauses.address ();
+      parser->tokens_avail = clauses.length ();
+    }
+  
   /* c_parser_omp_declare_simd pushed 2 extra CPP_EOF tokens at the end.  */
   while (parser->tokens_avail > 3)
     {
       c_token *token = c_parser_peek_token (parser);
-      gcc_assert (token->type == CPP_NAME
-		  && strcmp (IDENTIFIER_POINTER (token->value), "simd") == 0);
+      if (!is_cilkplus_cilk_simd_fn) 
+	gcc_assert (token->type == CPP_NAME 
+		    && strcmp (IDENTIFIER_POINTER (token->value), "simd") == 0);
+      else
+	gcc_assert (token->type == CPP_NAME
+		    && is_cilkplus_vector_p (token->value));
       c_parser_consume_token (parser);
       parser->in_pragma = true;
 
-      tree c = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK,
-					 "#pragma omp declare simd");
+      tree c = NULL_TREE;
+      if (is_cilkplus_cilk_simd_fn) 
+	c = c_parser_omp_all_clauses (parser, CILK_SIMD_FN_CLAUSE_MASK,
+				      "SIMD-enabled functions attribute");
+      else 
+	c = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK,
+				      "#pragma omp declare simd");
       c = c_omp_declare_simd_clauses_to_numbers (parms, c);
       if (c != NULL_TREE)
 	c = tree_cons (NULL_TREE, c, NULL_TREE);
+      if (is_cilkplus_cilk_simd_fn) 
+	{ 
+	  tree k = build_tree_list (get_identifier ("cilk simd function"), c);
+	  TREE_CHAIN (k) = DECL_ATTRIBUTES (fndecl);
+	  DECL_ATTRIBUTES (fndecl) = k;
+	} 
       c = build_tree_list (get_identifier ("omp declare simd"), c);
       TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
       DECL_ATTRIBUTES (fndecl) = c;
@@ -12804,7 +12996,11 @@ 
 
   parser->tokens = &parser->tokens_buf[0];
   parser->tokens_avail = tokens_avail;
-  clauses[0].type = CPP_PRAGMA;
+  if (clauses.exists ())
+    clauses[0].type = CPP_PRAGMA;
+
+  if (!vec_safe_is_empty (parser->cilk_simd_fn_tokens))
+    vec_free (parser->cilk_simd_fn_tokens);
 }
 
 
@@ -13400,39 +13596,108 @@ 
 }
 
 /* Cilk Plus:
-   vectorlength ( constant-expression ) */
+   This function is shared by SIMD-enabled functions and #pragma simd.  
+   If IS_SIMD_FN is true then it is parsing a SIMD-enabled function and 
+   CLAUSES is unused.  The main purpose of this function is to parse a
+   vectorlength attribute or clause and check for parse errors.
+   When IS_SIMD_FN is true then the function is merely caching the tokens
+   in PARSER->CILK_SIMD_FN_TOKENS.  If errors are found then the token
+   cache is cleared since there is no reason to continue.
+   Syntax:
+   vectorlength ( constant-expression )  */
 
-static tree
-c_parser_cilk_clause_vectorlength (c_parser *parser, tree clauses)
+static bool
+c_parser_cilk_clause_vectorlength (c_parser *parser, tree *clauses, 
+				   bool is_simd_fn)
 {
-  /* The vectorlength clause behaves exactly like OpenMP's safelen
-     clause.  Represent it in OpenMP terms.  */
-  check_no_duplicate_clause (clauses, OMP_CLAUSE_SAFELEN, "vectorlength");
+  c_token *token = c_parser_peek_token (parser);
+  if (is_simd_fn)
+    {
+      gcc_assert (!strcmp (IDENTIFIER_POINTER (token->value), "vectorlength"));
+      vec_safe_push (parser->cilk_simd_fn_tokens, *token);
+      c_parser_consume_token (parser);
+    }
+  else
+    /* The vectorlength clause behaves exactly like OpenMP's safelen
+       clause.  Represent it in OpenMP terms.  */
+    check_no_duplicate_clause (*clauses, OMP_CLAUSE_SAFELEN, "vectorlength");
 
+  token = c_parser_peek_token (parser);
   if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-    return clauses;
+    {
+      /* No reason to keep any of these tokens if the
+	 vectorlength is messed up.  */
+      vec_free (parser->cilk_simd_fn_tokens);
+      return false;
+    }
 
+  if (is_simd_fn)
+    vec_safe_push (parser->cilk_simd_fn_tokens, *token);
+
+  *token = *c_parser_peek_token (parser);
   location_t loc = c_parser_peek_token (parser)->location;
   tree expr = c_parser_expr_no_commas (parser, NULL).value;
   expr = c_fully_fold (expr, false, NULL);
+  bool error_found = false;
 
-  if (!TREE_TYPE (expr)
-      || !TREE_CONSTANT (expr)
-      || !INTEGRAL_TYPE_P (TREE_TYPE (expr)))
-    error_at (loc, "vectorlength must be an integer constant");
+  /* If expr is error_mark_node, then the returning function would have
+     flagged the error.  No need to flag it twice.  */
+  if (expr == error_mark_node)
+    error_found = true;
+  else if (!TREE_TYPE (expr)
+	   || !TREE_CONSTANT (expr)
+	   || !INTEGRAL_TYPE_P (TREE_TYPE (expr)))
+    {
+      error_at (loc, "vectorlength must be an integer constant");
+      error_found = true;
+    }
   else if (exact_log2 (TREE_INT_CST_LOW (expr)) == -1)
-    error_at (loc, "vectorlength must be a power of 2");
+    {
+      error_at (loc, "vectorlength must be a power of 2");
+      error_found = true;
+    }
   else
     {
-      tree u = build_omp_clause (loc, OMP_CLAUSE_SAFELEN);
-      OMP_CLAUSE_SAFELEN_EXPR (u) = expr;
-      OMP_CLAUSE_CHAIN (u) = clauses;
-      clauses = u;
+      if (is_simd_fn)
+	{
+	  c_token new_token;
+	  /* If we are here then it has be a number or an integral constant.
+	     The function that checks this token only checks to see if it is
+	     a keyword or name, so we set it to the most common case.  */
+	  new_token.type = CPP_NUMBER;
+	  new_token.keyword = RID_MAX;
+	  new_token.value = expr;
+	  vec_safe_push (parser->cilk_simd_fn_tokens, new_token);
+	}
+      else
+	{
+	  tree u = build_omp_clause (loc, OMP_CLAUSE_SAFELEN);
+	  OMP_CLAUSE_SAFELEN_EXPR (u) = expr;
+	  OMP_CLAUSE_CHAIN (u) = *clauses;
+	  *clauses = u;
+	}
     }
+  if (error_found && is_simd_fn)
+    {
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+      /* No reason to keep any of these tokens if the
+	 vectorlength is messed up.  */
+      vec_free (parser->cilk_simd_fn_tokens);
+      return false;
+    }
 
-  c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+  token = c_parser_peek_token (parser);
+  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+    {
+      /* No reason to keep any of these tokens if the
+	 vectorlength is messed up.  */
+      vec_free (parser->cilk_simd_fn_tokens);
+      return false;
+    }
 
-  return clauses;
+  if (is_simd_fn)
+    vec_safe_push (parser->cilk_simd_fn_tokens, *token);
+  return true;
 }
 
 /* Cilk Plus:
@@ -13524,10 +13789,10 @@ 
    not consumed.  Otherwise, the appropriate pragma_simd_clause is
    returned and the token is consumed.  */
 
-static pragma_cilk_clause
+static pragma_omp_clause
 c_parser_cilk_clause_name (c_parser *parser)
 {
-  pragma_cilk_clause result;
+  pragma_omp_clause result;
   c_token *token = c_parser_peek_token (parser);
 
   if (!token->value || token->type != CPP_NAME)
@@ -13564,14 +13829,14 @@ 
 
   while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
     {
-      pragma_cilk_clause c_kind;
+      pragma_omp_clause c_kind;
 
       c_kind = c_parser_cilk_clause_name (parser);
 
       switch (c_kind)
 	{
 	case PRAGMA_CILK_CLAUSE_VECTORLENGTH:
-	  clauses = c_parser_cilk_clause_vectorlength (parser, clauses);
+	  c_parser_cilk_clause_vectorlength (parser, &clauses, false);
 	  break;
 	case PRAGMA_CILK_CLAUSE_LINEAR:
 	  clauses = c_parser_cilk_clause_linear (parser, clauses);
Index: gcc/omp-low.c
===================================================================
--- gcc/omp-low.c	(revision 205759)
+++ gcc/omp-low.c	(working copy)
@@ -11300,7 +11300,7 @@ 
      declare simd".  */
   bool cilk_clone
     = (flag_enable_cilkplus
-       && lookup_attribute ("cilk plus elemental",
+       && lookup_attribute ("cilk simd function",
 			    DECL_ATTRIBUTES (node->decl)));
 
   /* Allocate one more than needed just in case this is an in-branch
Index: gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp
===================================================================
--- gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp	(revision 205759)
+++ gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp	(working copy)
@@ -59,6 +59,10 @@ 
     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/SE/*.c]] " -g" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/SE/*.c]] " -O3 -std=c99" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/SE/*.c]] " -O3 -g" " "
+
 dg-finish
 
 unset TEST_EXTRA_LIBS
Index: gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error.c
===================================================================
--- gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error.c	(revision 0)
+++ gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error.c	(revision 0)
@@ -0,0 +1,32 @@ 
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus -fopenmp" } */
+
+#pragma omp declare simd linear(y:1) simdlen(4) 
+__attribute__((vector (linear (y:1), vectorlength(4))))
+int func (int x, int y) { /* { dg-error "cannot be used in the same function marked as a Cilk Plus SIMD-enabled" } */ 
+  return (x+y);
+}
+__attribute__((vector (linear (y:1), private (x)))) /* { dg-error "expected clause" } */
+int func2 (int x, int y) {
+  return (x+y);
+}
+
+__attribute__((vector (linear (y:1), simdlen (4)))) /* { dg-error "expected clause" } */
+int func2_1 (int x, int y) {
+  return (x+y);
+}
+
+__attribute__((vector (linear (y:1), inbranch))) /* { dg-error "expected clause" } */
+int func2_3 (int x, int y) {
+  return (x+y);
+}
+
+__attribute__((vector (notinbranch, vectorlength (4)))) /* { dg-error "expected clause" } */
+int func2_2 (int x, int y) {
+  return (x+y);
+}
+
+int main (void)
+{
+  return (func (5,6));
+}
Index: gcc/testsuite/c-c++-common/cilk-plus/SE/vlength_errors.c
===================================================================
--- gcc/testsuite/c-c++-common/cilk-plus/SE/vlength_errors.c	(revision 0)
+++ gcc/testsuite/c-c++-common/cilk-plus/SE/vlength_errors.c	(revision 0)
@@ -0,0 +1,56 @@ 
+/* { 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 expression" } */
+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 an 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 an 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 an integer" } */
+int func6 (int x, int y)
+{
+  int zq = 5;
+  return x + (y*zq);
+}
+
+__attribute__ ((vector (uniform(x), linear (y:1), vectorlength (sizeof (int)) ))) /* This is OK too!  */
+int func7 (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/SE/ef_error2.c
===================================================================
--- gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error2.c	(revision 0)
+++ gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error2.c	(revision 0)
@@ -0,0 +1,14 @@ 
+/* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus -Wall" } */
+
+__attribute__((vector (vectorlength(32)))) 
+//#pragma omp simd simdlen (32)
+int func2 (int x, int y)  /* { dg-warning "unsupported simdlen" } */
+{
+  return (x+y);
+}
+
+int main (void)
+{
+  return (func2 (5,6));
+}
Index: gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error3.c
===================================================================
--- gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error3.c	(revision 0)
+++ gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error3.c	(revision 0)
@@ -0,0 +1,13 @@ 
+/* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus -Wall" } */
+
+__attribute__((vector (linear (x:y))))
+int func2 (int x, int y) 
+{ /* { dg-message "using parameters for" } */
+  return (x+y);
+}
+
+int main (void)
+{
+  return (func2 (5,6));
+}
Index: gcc/testsuite/c-c++-common/cilk-plus/SE/ef_test.c
===================================================================
--- gcc/testsuite/c-c++-common/cilk-plus/SE/ef_test.c	(revision 0)
+++ gcc/testsuite/c-c++-common/cilk-plus/SE/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;
+}
Index: gcc/testsuite/c-c++-common/cilk-plus/SE/ef_test2.c
===================================================================
--- gcc/testsuite/c-c++-common/cilk-plus/SE/ef_test2.c	(revision 0)
+++ gcc/testsuite/c-c++-common/cilk-plus/SE/ef_test2.c	(revision 0)
@@ -0,0 +1,16 @@ 
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus" } */
+void func (int x, int y) __attribute__((vector(linear(x:1), uniform (y)),
+					vector));
+
+int q;
+int main (void)
+{
+  int ii = 0;
+  q = 5; 
+  for (ii = 0; ii < 100; ii++) 
+    func (ii, q);
+
+  return 0;
+}
+
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 205759)
+++ gcc/cp/parser.c	(working copy)
@@ -31411,10 +31411,10 @@ 
    token is not consumed.  Otherwise, the appropriate enum from the
    pragma_simd_clause is returned and the token is consumed.  */
 
-static pragma_cilk_clause
+static pragma_omp_clause
 cp_parser_cilk_simd_clause_name (cp_parser *parser)
 {
-  pragma_cilk_clause clause_type;
+  pragma_omp_clause clause_type;
   cp_token *token = cp_lexer_peek_token (parser->lexer);
 
   if (token->keyword == RID_PRIVATE)
@@ -31448,7 +31448,7 @@ 
   while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)
 	 && clauses != error_mark_node)
     {
-      pragma_cilk_clause c_kind;
+      pragma_omp_clause c_kind;
       c_kind = cp_parser_cilk_simd_clause_name (parser);
       if (c_kind == PRAGMA_CILK_CLAUSE_VECTORLENGTH)
 	clauses = cp_parser_cilk_simd_vectorlength (parser, clauses);