diff mbox

[GOMP4] SIMD-enabled functions (formerly Elemental functions) for C++

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

Commit Message

Iyer, Balaji V Jan. 20, 2014, 3:37 a.m. UTC
Hi Jakub,
	I have fixed all the issues you have mentioned below. I am also attaching a fixed patch along with ChangeLog entries.  I have also rebased the patch to the trunk revision r206786.

	Is this Ok to install?

Thanks,

Balaji V. Iyer.

> -----Original Message-----
> From: Jakub Jelinek [mailto:jakub@redhat.com]
> Sent: Friday, January 17, 2014 12:46 PM
> To: Iyer, Balaji V
> Cc: 'Aldy Hernandez (aldyh@redhat.com)'; 'gcc-patches@gcc.gnu.org'
> Subject: Re: [GOMP4][PATCH] SIMD-enabled functions (formerly Elemental
> functions) for C++
> 
> On Thu, Dec 19, 2013 at 06:12:29PM +0000, Iyer, Balaji V wrote:
> > 2013-12-19  Balaji V. Iyer  <balaji.v.iyer@intel.com>
> >
> >         * parser.c (cp_parser_direct_declarator): When Cilk Plus is enabled
> >         see if there is an attribute after function decl.  If so, then
> >         parse them now.
> >         (cp_parser_late_return_type_opt): Handle parsing of Cilk Plus SIMD
> >         enabled function late parsing.
> >         (cp_parser_gnu_attribute_list): Parse all the tokens for the vector
> >         attribute for a SIMD-enabled function.
> >         (cp_parser_omp_all_clauses): Skip parsing to the end of pragma when
> >         the function is used by SIMD-enabled function (indicated by NULL
> >         pragma token).   Added 3 new clauses: PRAGMA_CILK_CLAUSE_MASK,
> >         PRAGMA_CILK_CLAUSE_NOMASK and
> PRAGMA_CILK_CLAUSE_VECTORLENGTH
> >         (cp_parser_cilk_simd_vectorlength): Modified this function to handle
> >         vectorlength clause in SIMD-enabled function and #pragma SIMD's
> >         vectorlength clause.  Added a new bool parameter to differentiate
> >         between the two.
> >         (cp_parser_cilk_simd_fn_vector_attrs): New function.
> >         (is_cilkplus_vector_p): Likewise.
> >         (cp_parser_late_parsing_elem_fn_info): Likewise.
> >         (cp_parser_omp_clause_name): Added a check for "mask," "nomask"
> 
> The comma should have been after " .
> 

Fixed.

> > +		  /* In here, we handle cases where attribute is used after
> > +		     the function declaration.  For example:
> > +		     void func (int x) __attribute__((vector(..)));  */
> > +		  if (flag_enable_cilkplus
> > +		      && cp_next_tokens_can_be_attribute_p (parser))
> 
> As you are just calling cp_parser_gnu_attributes_opt here and not ..._std_...,
> I'd say the above should be cp_next_tokens_can_be_gnu_attribute_p
> rather than cp_next_tokens_can_be_attribute_p.  I think [[...]] attributes at
> this position are ignored, so no need to handle them, not sure about
> whether we allow e.g. combination of GNU and std attributes or vice versa.
> 

Fixed.

> > +		    {
> > +		      cp_parser_parse_tentatively (parser);
> > +		      tree attr = cp_parser_gnu_attributes_opt (parser);
> > +		      if (cp_lexer_next_token_is_not (parser->lexer,
> > +						      CPP_SEMICOLON)
> > +			  && cp_lexer_next_token_is_not (parser->lexer,
> > +							 CPP_OPEN_BRACE))
> > +			cp_parser_abort_tentative_parse (parser);
> > +		      else if (!cp_parser_parse_definitely (parser))
> > +			;
> > +		      else
> > +			attrs = chainon (attr, attrs);
> > +		    }
> >  		  late_return = (cp_parser_late_return_type_opt
> >  				 (parser, declarator,
> >  				  memfn ? cv_quals : -1));
> 
> > @@ -17842,6 +17868,10 @@ cp_parser_late_return_type_opt (cp_parser*
> parser, cp_declarator *declarator,
> >        type = cp_parser_trailing_type_id (parser);
> >      }
> >
> > +  if (cilk_simd_fn_vector_p)
> > +    declarator->std_attributes
> > +      = cp_parser_late_parsing_cilk_simd_fn_info (parser,
> > +					     declarator->std_attributes);
> 
> Please make sure declarator is aligned below parser.
> 

Fixed.

> > +  token->type = CPP_PRAGMA_EOL;
> > +  parser->lexer->next_token = token;
> > +  cp_lexer_consume_token (parser->lexer);
> > +
> > +  struct cp_token_cache *cp =
> > +    cp_token_cache_new (v_token, cp_lexer_peek_token
> > + (parser->lexer));
> 
> The = should already go on the next line.
> 

Fixed.

> > +/* Handles the delayed parsing of the Cilk Plus SIMD-enabled function.
> > +   This function is modelled similar to the late parsing of omp declare
> > +   simd.  */
> > +
> > +static tree
> > +cp_parser_late_parsing_cilk_simd_fn_info (cp_parser *parser, tree
> > +attrs) {
> > +  struct cp_token_cache *ce;
> > +  cp_omp_declare_simd_data *info = parser->cilk_simd_fn_info;
> > +  int ii = 0;
> > +
> > +  if (parser->omp_declare_simd != NULL)
> > +    {
> > +      error ("%<#pragma omp declare simd%> cannot be used in the same
> function"
> > +	     " marked as a Cilk Plus SIMD-enabled function");
> > +      parser->cilk_simd_fn_info = NULL;
> 
> This will leak parser->cilk_simd_fn_info memory.  Please XDELETE it first.
> 

Fixed

> > +      return attrs;
> > +    }
> > +  if (!info->error_seen && info->fndecl_seen)
> > +    {
> > +      error ("vector attribute not immediately followed by a single function"
> > +	     " declaration or definition");
> > +      info->error_seen = true;
> > +    }
> > +  if (info->error_seen)
> > +    return attrs;
> > +
> > +  /* Vector attributes are converted to #pragma omp declare simd values
> and
> > +     so we need them enabled.  */
> > +  flag_openmp = 1;
> 
> The C FE doesn't do this.  I thought all the omp-low.c spots are now guarded
> by flag_openmp || flag_enable_cilkplus etc. conditions.

Fixed. The above "orring" was omitted in decl.c and pt.c . I have put them in.

> 
> > +      c = build_tree_list (get_identifier ("cilk simd function"),
> > + cl);
> 
> Please use NULL_TREE instead of cl here and please fix up the C FE as well,
> the "cilk simd function" attribute should be just an attribute without value,
> serving only as a boolean, if present, decl with "omp declare simd" attribute
> is Cilk+, otherwise OpenMP.
> 
> > +      TREE_CHAIN (c) = attrs;
> > +      if (processing_template_decl)
> > +	ATTR_IS_DEPENDENT (c) = 1;
> 

Fixed.

> But, as a boolean attribute it doesn't and shouldn't be ATTR_IS_DEPENDENT,
> there is nothing to adjust in it.
> > --- a/gcc/cp/pt.c
> > +++ b/gcc/cp/pt.c
> > @@ -8602,9 +8602,12 @@ apply_late_template_attributes (tree *decl_p,
> tree attributes, int attr_flags,
> >  	    {
> >  	      *p = TREE_CHAIN (t);
> >  	      TREE_CHAIN (t) = NULL_TREE;
> > -	      if (flag_openmp
> > -		  && is_attribute_p ("omp declare simd",
> > -				     get_attribute_name (t))
> > +	      if (((flag_openmp
> > +		    && is_attribute_p ("omp declare simd",
> > +				       get_attribute_name (t)))
> > +		   || (flag_enable_cilkplus
> > +		       && is_attribute_p ("cilk simd function",
> > +					  get_attribute_name (t))))
> >  		  && TREE_VALUE (t))
> >  		{
> >  		  tree clauses = TREE_VALUE (TREE_VALUE (t));
> 
> And this change is unnecessary after the above suggested change.
> 

Fixed.

> 	Jakub
diff mbox

Patch

diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 4490210..bbf5287 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -12924,7 +12924,8 @@  c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms,
 	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 k = build_tree_list (get_identifier ("cilk simd function"), 
+				    NULL_TREE);
 	  TREE_CHAIN (k) = DECL_ATTRIBUTES (fndecl);
 	  DECL_ATTRIBUTES (fndecl) = k;
 	} 
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 5906653..9918416 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -7674,7 +7674,7 @@  grokfndecl (tree ctype,
   if (TYPE_NOTHROW_P (type) || nothrow_libfn_p (decl))
     TREE_NOTHROW (decl) = 1;
 
-  if (flag_openmp)
+  if (flag_openmp || flag_enable_cilkplus)
     {
       /* Adjust "omp declare simd" attributes.  */
       tree ods = lookup_attribute ("omp declare simd", *attrlist);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index c3016bc..971fe8f 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -241,6 +241,8 @@  static void cp_parser_cilk_simd
   (cp_parser *, cp_token *);
 static bool cp_parser_omp_declare_reduction_exprs
   (tree, cp_parser *);
+static tree cp_parser_cilk_simd_vectorlength 
+  (cp_parser *, tree, bool);
 
 /* Manifest constants.  */
 #define CP_LEXER_BUFFER_SIZE ((256 * 1024) / sizeof (cp_token))
@@ -2115,6 +2117,9 @@  static bool cp_parser_ctor_initializer_opt_and_function_body
 static tree cp_parser_late_parsing_omp_declare_simd
   (cp_parser *, tree);
 
+static tree cp_parser_late_parsing_cilk_simd_fn_info
+  (cp_parser *, tree);
+
 static tree synthesize_implicit_template_parm
   (cp_parser *);
 static tree finish_fully_implicit_template
@@ -17121,6 +17126,24 @@  cp_parser_direct_declarator (cp_parser* parser,
 
 		  attrs = cp_parser_std_attribute_spec_seq (parser);
 
+		  /* In here, we handle cases where attribute is used after
+		     the function declaration.  For example:
+		     void func (int x) __attribute__((vector(..)));  */
+		  if (flag_enable_cilkplus
+		      && cp_next_tokens_can_be_gnu_attribute_p (parser))
+		    {
+		      cp_parser_parse_tentatively (parser);
+		      tree attr = cp_parser_gnu_attributes_opt (parser);
+		      if (cp_lexer_next_token_is_not (parser->lexer,
+						      CPP_SEMICOLON)
+			  && cp_lexer_next_token_is_not (parser->lexer,
+							 CPP_OPEN_BRACE))
+			cp_parser_abort_tentative_parse (parser);
+		      else if (!cp_parser_parse_definitely (parser))
+			;
+		      else
+			attrs = chainon (attr, attrs);
+		    }
 		  late_return = (cp_parser_late_return_type_opt
 				 (parser, declarator,
 				  memfn ? cv_quals : -1));
@@ -17829,7 +17852,7 @@  parsing_nsdmi (void)
    Returns the type indicated by the type-id.
 
    In addition to this this parses any queued up omp declare simd
-   clauses.
+   clauses and Cilk Plus SIMD-enabled function's vector attributes.
 
    QUALS is either a bitmask of cv_qualifiers or -1 for a non-member
    function.  */
@@ -17844,10 +17867,13 @@  cp_parser_late_return_type_opt (cp_parser* parser, cp_declarator *declarator,
 			 && declarator
 			 && declarator->kind == cdk_id);
 
+  bool cilk_simd_fn_vector_p = (parser->cilk_simd_fn_info 
+				&& declarator && declarator->kind == cdk_id);
+  
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
   /* A late-specified return type is indicated by an initial '->'. */
-  if (token->type != CPP_DEREF && !declare_simd_p)
+  if (token->type != CPP_DEREF && !(declare_simd_p || cilk_simd_fn_vector_p))
     return NULL_TREE;
 
   tree save_ccp = current_class_ptr;
@@ -17866,6 +17892,10 @@  cp_parser_late_return_type_opt (cp_parser* parser, cp_declarator *declarator,
       type = cp_parser_trailing_type_id (parser);
     }
 
+  if (cilk_simd_fn_vector_p)
+    declarator->std_attributes
+      = cp_parser_late_parsing_cilk_simd_fn_info (parser,
+						  declarator->std_attributes);
   if (declare_simd_p)
     declarator->std_attributes
       = cp_parser_late_parsing_omp_declare_simd (parser,
@@ -21399,6 +21429,56 @@  cp_parser_attributes_opt (cp_parser *parser)
   return cp_parser_std_attribute_spec_seq (parser);
 }
 
+#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_NOMASK))
+
+/* Parses the Cilk Plus SIMD-enabled function's attribute.  Syntax:
+   vector [(<clauses>)]  */
+
+static void
+cp_parser_cilk_simd_fn_vector_attrs (cp_parser *parser, cp_token *v_token)
+{  
+  bool first_p = parser->cilk_simd_fn_info == NULL;
+  cp_token *token = v_token;
+  if (first_p)
+    {
+      parser->cilk_simd_fn_info = XNEW (cp_omp_declare_simd_data);
+      parser->cilk_simd_fn_info->error_seen = false;
+      parser->cilk_simd_fn_info->fndecl_seen = false;
+      parser->cilk_simd_fn_info->tokens = vNULL;
+    }
+  int paren_scope = 0;
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+    {
+      cp_lexer_consume_token (parser->lexer);
+      v_token = cp_lexer_peek_token (parser->lexer);
+      paren_scope++;
+    }
+  while (paren_scope > 0)
+    {
+      token = cp_lexer_peek_token (parser->lexer);
+      if (token->type == CPP_OPEN_PAREN)
+	paren_scope++;
+      else if (token->type == CPP_CLOSE_PAREN)
+	paren_scope--;
+      /* Do not push the last ')'  */
+      if (!(token->type == CPP_CLOSE_PAREN && paren_scope == 0))
+	cp_lexer_consume_token (parser->lexer);
+    }
+
+  token->type = CPP_PRAGMA_EOL;
+  parser->lexer->next_token = token;
+  cp_lexer_consume_token (parser->lexer);
+
+  struct cp_token_cache *cp
+    = cp_token_cache_new (v_token, cp_lexer_peek_token (parser->lexer));
+  parser->cilk_simd_fn_info->tokens.safe_push (cp);
+}
+
 /* Parse an (optional) series of attributes.
 
    attributes:
@@ -21457,6 +21537,17 @@  cp_parser_gnu_attributes_opt (cp_parser* parser)
   return attributes;
 }
 
+/* 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;
+}
+
 /* Parse a GNU attribute-list.
 
    attribute-list:
@@ -21495,8 +21586,9 @@  cp_parser_gnu_attribute_list (cp_parser* parser)
 	{
 	  tree arguments = NULL_TREE;
 
-	  /* Consume the token.  */
-	  token = cp_lexer_consume_token (parser->lexer);
+	  /* Consume the token, but save it since we need it for the
+	     SIMD enabled function parsing.  */
+	  cp_token *id_token = cp_lexer_consume_token (parser->lexer);
 
 	  /* Save away the identifier that indicates which attribute
 	     this is.  */
@@ -21504,7 +21596,7 @@  cp_parser_gnu_attribute_list (cp_parser* parser)
 	    /* For keywords, use the canonical spelling, not the
 	       parsed identifier.  */
 	    ? ridpointers[(int) token->keyword]
-	    : token->u.value;
+	    : id_token->u.value;
 	  
 	  attribute = build_tree_list (identifier, NULL_TREE);
 
@@ -21516,10 +21608,16 @@  cp_parser_gnu_attribute_list (cp_parser* parser)
 	      vec<tree, va_gc> *vec;
 	      int attr_flag = (attribute_takes_identifier_p (identifier)
 			       ? id_attr : normal_attr);
-	      vec = cp_parser_parenthesized_expression_list
-		    (parser, attr_flag, /*cast_p=*/false,
-		     /*allow_expansion_p=*/false,
-		     /*non_constant_p=*/NULL);
+	      if (is_cilkplus_vector_p (identifier))
+		{
+		  cp_parser_cilk_simd_fn_vector_attrs (parser, id_token);
+		  continue;
+		}
+	      else
+		vec = cp_parser_parenthesized_expression_list 
+		  (parser, attr_flag, /*cast_p=*/false, 
+		   /*allow_expansion_p=*/false, 
+		   /*non_constant_p=*/NULL);
 	      if (vec == NULL)
 		arguments = error_mark_node;
 	      else
@@ -21530,6 +21628,11 @@  cp_parser_gnu_attribute_list (cp_parser* parser)
 	      /* Save the arguments away.  */
 	      TREE_VALUE (attribute) = arguments;
 	    }
+	  else if (is_cilkplus_vector_p (identifier))
+	    {
+	      cp_parser_cilk_simd_fn_vector_attrs (parser, id_token);
+	      continue;
+	    }
 
 	  if (arguments != error_mark_node)
 	    {
@@ -26809,12 +26912,16 @@  cp_parser_omp_clause_name (cp_parser *parser)
 	    result = PRAGMA_OMP_CLAUSE_MAP;
 	  else if (!strcmp ("mergeable", p))
 	    result = PRAGMA_OMP_CLAUSE_MERGEABLE;
+	  else if (flag_enable_cilkplus && !strcmp ("mask", p))
+	    result = PRAGMA_CILK_CLAUSE_MASK;
 	  break;
 	case 'n':
 	  if (!strcmp ("notinbranch", p))
 	    result = PRAGMA_OMP_CLAUSE_NOTINBRANCH;
 	  else if (!strcmp ("nowait", p))
 	    result = PRAGMA_OMP_CLAUSE_NOWAIT;
+	  else if (flag_enable_cilkplus && !strcmp ("nomask", p))
+	    result = PRAGMA_CILK_CLAUSE_NOMASK;
 	  else if (!strcmp ("num_teams", p))
 	    result = PRAGMA_OMP_CLAUSE_NUM_TEAMS;
 	  else if (!strcmp ("num_threads", p))
@@ -26860,6 +26967,10 @@  cp_parser_omp_clause_name (cp_parser *parser)
 	  else if (!strcmp ("untied", p))
 	    result = PRAGMA_OMP_CLAUSE_UNTIED;
 	  break;
+	case 'v':
+	  if (flag_enable_cilkplus && !strcmp ("vectorlength", p))
+	    result = PRAGMA_CILK_CLAUSE_VECTORLENGTH;
+	  break;
 	}
     }
 
@@ -27612,7 +27723,8 @@  cp_parser_omp_clause_aligned (cp_parser *parser, tree list)
    linear ( variable-list : expression )  */
 
 static tree
-cp_parser_omp_clause_linear (cp_parser *parser, tree list)
+cp_parser_omp_clause_linear (cp_parser *parser, tree list, 
+			     bool is_cilk_simd_fn)
 {
   tree nlist, c, step = integer_one_node;
   bool colon;
@@ -27627,6 +27739,11 @@  cp_parser_omp_clause_linear (cp_parser *parser, tree list)
     {
       step = cp_parser_expression (parser, false, NULL);
 
+      if (is_cilk_simd_fn && TREE_CODE (step) == PARM_DECL)
+	{
+	  sorry ("using parameters for %<linear%> step is not supported yet");
+	  step = integer_one_node;
+	}
       if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
 	cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
 					       /*or_comma=*/false,
@@ -27948,6 +28065,7 @@  cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
   tree clauses = NULL;
   bool first = true;
   cp_token *token = NULL;
+  bool cilk_simd_fn = false;
 
   while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
     {
@@ -28044,11 +28162,13 @@  cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
 	  c_name = "untied";
 	  break;
 	case PRAGMA_OMP_CLAUSE_INBRANCH:
+	case PRAGMA_CILK_CLAUSE_MASK:
 	  clauses = cp_parser_omp_clause_branch (parser, OMP_CLAUSE_INBRANCH,
 						 clauses, token->location);
 	  c_name = "inbranch";
 	  break;
 	case PRAGMA_OMP_CLAUSE_NOTINBRANCH:
+	case PRAGMA_CILK_CLAUSE_NOMASK:
 	  clauses = cp_parser_omp_clause_branch (parser,
 						 OMP_CLAUSE_NOTINBRANCH,
 						 clauses, token->location);
@@ -28117,7 +28237,9 @@  cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
 	  c_name = "aligned";
 	  break;
 	case PRAGMA_OMP_CLAUSE_LINEAR:
-	  clauses = cp_parser_omp_clause_linear (parser, clauses);
+	  if (((mask >> PRAGMA_CILK_CLAUSE_VECTORLENGTH) & 1) != 0)
+	    cilk_simd_fn = true;
+	  clauses = cp_parser_omp_clause_linear (parser, clauses, cilk_simd_fn);
 	  c_name = "linear";
 	  break;
 	case PRAGMA_OMP_CLAUSE_DEPEND:
@@ -28153,6 +28275,10 @@  cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
 						  token->location);
 	  c_name = "simdlen";
 	  break;
+	case PRAGMA_CILK_CLAUSE_VECTORLENGTH:
+	  clauses = cp_parser_cilk_simd_vectorlength (parser, clauses, true);
+	  c_name = "simdlen";
+	  break;
 	default:
 	  cp_parser_error (parser, "expected %<#pragma omp%> clause");
 	  goto saw_error;
@@ -28169,7 +28295,10 @@  cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
 	}
     }
  saw_error:
-  cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+  /* In Cilk Plus SIMD enabled functions there is no pragma_token, so
+     no reason to skip to the end.  */
+  if (!(flag_enable_cilkplus && pragma_tok == NULL))
+    cp_parser_skip_to_pragma_eol (parser, pragma_tok);
   if (finish_p)
     return finish_omp_clauses (clauses);
   return clauses;
@@ -30171,6 +30300,63 @@  cp_parser_omp_declare_simd (cp_parser *parser, cp_token *pragma_tok,
     }
 }
 
+/* Handles the delayed parsing of the Cilk Plus SIMD-enabled function.  
+   This function is modelled similar to the late parsing of omp declare 
+   simd.  */
+
+static tree
+cp_parser_late_parsing_cilk_simd_fn_info (cp_parser *parser, tree attrs)
+{
+  struct cp_token_cache *ce;
+  cp_omp_declare_simd_data *info = parser->cilk_simd_fn_info;
+  int ii = 0;
+
+  if (parser->omp_declare_simd != NULL)
+    {
+      error ("%<#pragma omp declare simd%> cannot be used in the same function"
+	     " marked as a Cilk Plus SIMD-enabled function");
+      XDELETE (parser->cilk_simd_fn_info);
+      parser->cilk_simd_fn_info = NULL;
+      return attrs;
+    }
+  if (!info->error_seen && info->fndecl_seen)
+    {
+      error ("vector attribute not immediately followed by a single function"
+	     " declaration or definition");
+      info->error_seen = true;
+    }
+  if (info->error_seen)
+    return attrs;
+
+  FOR_EACH_VEC_ELT (info->tokens, ii, ce)
+    {
+      tree c, cl;
+
+      cp_parser_push_lexer_for_tokens (parser, ce);
+      parser->lexer->in_pragma = true;
+      cl = cp_parser_omp_all_clauses (parser, CILK_SIMD_FN_CLAUSE_MASK,
+				      "SIMD-enabled functions attribute", 
+				      NULL);
+      cp_parser_pop_lexer (parser);
+      if (cl)
+	cl = tree_cons (NULL_TREE, cl, NULL_TREE);
+
+      c = build_tree_list (get_identifier ("cilk simd function"), NULL_TREE);
+      TREE_CHAIN (c) = attrs;
+      attrs = c;
+
+      c = build_tree_list (get_identifier ("omp declare simd"), cl);
+      TREE_CHAIN (c) = attrs;
+      if (processing_template_decl)
+	ATTR_IS_DEPENDENT (c) = 1;
+      attrs = c;
+    }
+  info->fndecl_seen = true;
+  XDELETE (parser->cilk_simd_fn_info);
+  parser->cilk_simd_fn_info = NULL;
+  return attrs;
+}
+
 /* Finalize #pragma omp declare simd clauses after direct declarator has
    been parsed, and put that into "omp declare simd" attribute.  */
 
@@ -31351,35 +31537,63 @@  c_parse_file (void)
   the_parser = NULL;
 }
 
-/* Parses the Cilk Plus #pragma simd vectorlength clause:
+/* Parses the Cilk Plus #pragma simd and SIMD-enabled function attribute's 
+   vectorlength clause:
    Syntax:
    vectorlength ( constant-expression )  */
 
 static tree
-cp_parser_cilk_simd_vectorlength (cp_parser *parser, tree clauses)
+cp_parser_cilk_simd_vectorlength (cp_parser *parser, tree clauses,
+				  bool is_simd_fn)
 {
   location_t loc = cp_lexer_peek_token (parser->lexer)->location;
   tree expr;
-  /* The vectorlength clause behaves exactly like OpenMP's safelen
-     clause.  Thus, vectorlength is represented as OMP 4.0
-     safelen.  */
-  check_no_duplicate_clause (clauses, OMP_CLAUSE_SAFELEN, "vectorlength", loc);
-  
+  /* The vectorlength clause in #pragma simd behaves exactly like OpenMP's
+     safelen clause.  Thus, vectorlength is represented as OMP 4.0
+     safelen.  For SIMD-enabled function it is represented by OMP 4.0
+     simdlen.  */
+  if (!is_simd_fn)
+    check_no_duplicate_clause (clauses, OMP_CLAUSE_SAFELEN, "vectorlength", 
+			       loc);
+  else
+    check_no_duplicate_clause (clauses, OMP_CLAUSE_SIMDLEN, "vectorlength",
+			       loc);
+
   if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
     return error_mark_node;
   
   expr = cp_parser_constant_expression (parser, false, NULL);
   expr = maybe_constant_value (expr);
-
-  if (TREE_CONSTANT (expr)
+  
+  /* If expr == error_mark_node, then don't emit any errors nor
+     create a clause.  if any of the above functions returns
+     error mark node then they would have emitted an error message.  */
+  if (expr == error_mark_node)
+    ;
+  else if (!TREE_TYPE (expr)
+	   || !TREE_CONSTANT (expr)
+	   || !INTEGRAL_TYPE_P (TREE_TYPE (expr)))
+    error_at (loc, "vectorlength must be an integer constant");
+  else if (TREE_CONSTANT (expr)
 	   && exact_log2 (TREE_INT_CST_LOW (expr)) == -1)
     error_at (loc, "vectorlength must be a power of 2");
-  else if (expr != error_mark_node)
+  else 
     {
-      tree c = build_omp_clause (loc, OMP_CLAUSE_SAFELEN);
-      OMP_CLAUSE_SAFELEN_EXPR (c) = expr;
-      OMP_CLAUSE_CHAIN (c) = clauses;
-      clauses = c;
+      tree c;
+      if (!is_simd_fn)
+	{ 
+	  c = build_omp_clause (loc, OMP_CLAUSE_SAFELEN); 
+	  OMP_CLAUSE_SAFELEN_EXPR (c) = expr; 
+	  OMP_CLAUSE_CHAIN (c) = clauses; 
+	  clauses = c;
+	}
+      else
+	{
+	  c = build_omp_clause (loc, OMP_CLAUSE_SIMDLEN);
+	  OMP_CLAUSE_SIMDLEN_EXPR (c) = expr;
+	  OMP_CLAUSE_CHAIN (c) = clauses;
+	  clauses = c;
+	}
     }
 
   if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
@@ -31542,7 +31756,7 @@  cp_parser_cilk_simd_all_clauses (cp_parser *parser, cp_token *pragma_token)
       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);
+	clauses = cp_parser_cilk_simd_vectorlength (parser, clauses, false);
       else if (c_kind == PRAGMA_CILK_CLAUSE_LINEAR)
 	clauses = cp_parser_cilk_simd_linear (parser, clauses);
       else if (c_kind == PRAGMA_CILK_CLAUSE_PRIVATE)
diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h
index 484a8cd..d558c60 100644
--- a/gcc/cp/parser.h
+++ b/gcc/cp/parser.h
@@ -362,6 +362,13 @@  typedef struct GTY(()) cp_parser {
      data structure with everything needed for parsing the clauses.  */
   cp_omp_declare_simd_data * GTY((skip)) omp_declare_simd;
 
+  /* When parsing the vector attribute in Cilk Plus SIMD-enabled function,
+     this is a pointer to data structure with everything needed for parsing
+     the clauses.  The cp_omp_declare_simd_data struct will hold all the
+     necessary information, so creating another struct for this is not
+     necessary.  */
+  cp_omp_declare_simd_data * GTY((skip)) cilk_simd_fn_info;
+
   /* Nonzero if parsing a parameter list where 'auto' should trigger an implicit
      template parameter.  */
   bool auto_is_implicit_function_template_parm_p;
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 2e7cf60..a91df4c 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -8613,7 +8613,7 @@  apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags,
 	    {
 	      *p = TREE_CHAIN (t);
 	      TREE_CHAIN (t) = NULL_TREE;
-	      if (flag_openmp
+	      if ((flag_openmp || flag_enable_cilkplus)
 		  && is_attribute_p ("omp declare simd",
 				     get_attribute_name (t))
 		  && TREE_VALUE (t))
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error3.c b/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error3.c
index ab55fae..195e9f1 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error3.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error3.c
@@ -1,9 +1,9 @@ 
 /* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */
 /* { dg-options "-fcilkplus -Wall" } */
 
-__attribute__((vector (linear (x:y))))
+__attribute__((vector (linear (x:y)))) /* { dg-message "parameter" "" { target c++ } } */
 int func2 (int x, int y) 
-{ /* { dg-message "using parameters for" } */
+{ /* { dg-message "using parameters for" "" { target c } } */
   return (x+y);
 }
 
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/SE/vlength_errors.c b/gcc/testsuite/c-c++-common/cilk-plus/SE/vlength_errors.c
index 38d610a..1bcf2a2 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/SE/vlength_errors.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/SE/vlength_errors.c
@@ -5,7 +5,8 @@ 
 
 int z = Q;
 
-__attribute__ ((vector (uniform(x), vectorlength (), linear (y:1) ))) /* { dg-error "expected expression" } */
+__attribute__ ((vector (uniform(x), vectorlength (), linear (y:1) ))) /* { dg-error "expected expression" "" { target c } } */ 
+     /* { dg-error "expected primary-expression" "" { target c++ }  8 } */ 
 int func2 (int x, int y)
 {
   int zq = 5;
@@ -19,7 +20,8 @@  int func3 (int x, int y)
   return x + (y*zq);
 }
 
-__attribute__ ((vector (uniform(x), linear (y:1), vectorlength (z) ))) /* { dg-error "vectorlength must be an integer" } */
+__attribute__ ((vector (uniform(x), linear (y:1), vectorlength (z) ))) /* { dg-error "vectorlength must be an integer" "" { target c } } */ 
+     /* { dg-error "constant" "" { target c++ } 23 } */
 int func4 (int x, int y)
 {
   int zq = 5;
@@ -33,7 +35,8 @@  int func5 (int x, int y)
   return x + (y*zq);
 }
 
-__attribute__ ((vector (uniform(x), vectorlength (z), linear (y:1)))) /* { dg-error "vectorlength must be an integer" } */
+__attribute__ ((vector (uniform(x), vectorlength (z), linear (y:1)))) /* { dg-error "vectorlength must be an integer" ""  { target c } } */ 
+     /* { dg-error "constant" "" { target c++ }  38 } */
 int func6 (int x, int y)
 {
   int zq = 5;
diff --git a/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
index 37b8ccb..204a754 100644
--- a/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
+++ b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
@@ -33,6 +33,9 @@  set TEST_EXTRA_LIBS "-L${library_var}/libcilkrts/.libs"
 dg-init
 # Run the tests that are shared with C.
 g++-dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/PS/*.c]] ""
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/SE/*.c]] "-O3" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/SE/*.c]] " " " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/SE/*.c]] "-g -O2" " "
 # Run the C++ only tests.
 g++-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C]] ""
 dg-finish
diff --git a/gcc/testsuite/g++.dg/cilk-plus/ef_test.C b/gcc/testsuite/g++.dg/cilk-plus/ef_test.C
new file mode 100644
index 0000000..3e75cbd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/ef_test.C
@@ -0,0 +1,37 @@ 
+/* { dg-do run }  */
+/* { dg-options "-fcilkplus" } */
+
+
+__attribute__((vector (nomask), vector(mask), vector(mask,linear(x:1))))
+int func (int x)
+{
+  return x+5;
+}
+
+
+__attribute__((vector(mask,uniform (y), linear(x:1))))
+__attribute__((vector (nomask, uniform (x), linear(y:1))))
+int func2 (int x, int y)
+{
+  return x+y;
+}
+
+int func4 (int x, int y) __attribute__((vector, vector (nomask), vector (uniform(y), linear(x:1))));
+
+
+template <class T, class R>
+__attribute__((vector, vector(mask,uniform (y), linear(x:1))))
+T func3 (T x, R y)
+{
+  return x+(T)y;
+}
+
+
+
+int main (void)
+{
+  if ((func3 (5, 4) + func2 (5, 4) + func (5) + (int) func3<long, int> (5, 4)) != 
+      (5 + 4) + (5 + 4) + (5 + 5) + (int) ((long)5 +(int)4))
+    __builtin_abort ();
+  return 0;
+}