diff mbox

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

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

Commit Message

Iyer, Balaji V Dec. 24, 2013, 4:50 a.m. UTC
Ping!

-Balaji V. Iyer.

> -----Original Message-----
> From: Iyer, Balaji V
> Sent: Thursday, December 19, 2013 1:12 PM
> To: Jakub Jelinek
> Cc: 'Aldy Hernandez (aldyh@redhat.com)'; 'gcc-patches@gcc.gnu.org'
> Subject: RE: [GOMP4][PATCH] SIMD-enabled functions (formerly Elemental
> functions) for C++
> 
> Hi Jakub,
> 	Attached, please find a fixed patch. I have answered your questions
> below. Is this OK for trunk?
> 
> Here are the ChangeLog entries:
> Gcc/cp/ChangeLog
> 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"
>         and "vectorlength" clauses when Cilk Plus is enabled.
>         (cp_parser_omp_clause_linear): Added a new parameter of type bool
>         and emit a sorry message when step size is a parameter.
>         * parser.h (cp_parser::cilk_simd_fn_info): New field.
> 
> Testsuite/ChangeLog
> 2013-12-19  Balaji V. Iyer  <balaji.v.iyer@intel.com>
> 
>         * g++.dg/cilk-plus/cilk-plus.exp: Called the C/C++ common tests for
>         SIMD enabled function.
>         * g++.dg/cilk-plus/ef_test.C: New test.
>         * c-c++-common/cilk-plus/vlength_errors.c: Added new dg-error tags
>         to differenciate C error messages from C++ ones.
> 
> Thanks,
> 
> Balaji V. Iyer.
> 
> > -----Original Message-----
> > From: Jakub Jelinek [mailto:jakub@redhat.com]
> > Sent: Thursday, December 19, 2013 2:23 AM
> > 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 Wed, Dec 18, 2013 at 11:36:04PM +0000, Iyer, Balaji V wrote:
> > > --- a/gcc/cp/decl2.c
> > > +++ b/gcc/cp/decl2.c
> > > @@ -1124,6 +1124,10 @@ is_late_template_attribute (tree attr, tree
> decl)
> > >        && is_attribute_p ("omp declare simd", name))
> > >      return true;
> > >
> > > +  /* Ditto as above for Cilk Plus SIMD-enabled function attributes.
> > > + */  if (flag_enable_cilkplus && is_attribute_p ("cilk simd
> > > + function",
> > name))
> > > +    return true;
> >
> > Why?  It doesn't have any argument, why it should be processed late?
> >
> 
> Fixed.
> 
> > > @@ -17097,6 +17102,14 @@ 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_lexer_next_token_is_keyword (parser->lexer,
> > > +							 RID_ATTRIBUTE))
> > > +		    attrs = chainon (cp_parser_gnu_attributes_opt (parser),
> > > +				     attrs);
> > >  		  late_return = (cp_parser_late_return_type_opt
> > >  				 (parser, declarator,
> > >  				  memfn ? cv_quals : -1));
> >
> > Doesn't this change the grammar (for all attributes, not just Cilk+
> > specific
> > ones) just based on whether -fcilkplus has been specified or not?
> >
> 
> OK. Fixed this by making it parse tentatively (sort of similar to how you parse
> attributes after labels (line #9584))
> 
> > > @@ -17820,10 +17833,14 @@ 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);
> >
> > Formatting looks wrong, put = on the next line and align && right
> > below parser.
> 
> Fixed.
> 
> > > +
> > > +cp_omp_declare_simd_data info;
> >
> > Global var?  Why?  Isn't heap or GC allocation better?
> 
> Fixed. Replaced it with XNEW and XDELETE combinations instead of setting
> the address of a global value.
> 
> > > +  /* The vectorlength clause in #pragma simdbehaves exactly like
> > > + OpenMP's
> >
> > Missing space after simd
> >
> 
> Fixed.
> 
> > > @@ -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))))
> >
> > Again, why this?
> >
> 
> SIMD enabled function is marked with omp declare simd and cilk simd
> function attributes. So I should handle them both...
> 
> > 	Jakub
diff mbox

Patch

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 2a2cbf0..d1e904b 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
@@ -17097,6 +17102,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_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));
@@ -17805,7 +17828,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.  */
@@ -17820,10 +17843,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;
@@ -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);
   if (declare_simd_p)
     declarator->std_attributes
       = cp_parser_late_parsing_omp_declare_simd (parser,
@@ -21375,6 +21405,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:
@@ -21433,6 +21513,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:
@@ -21471,8 +21562,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.  */
@@ -21480,7 +21572,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);
 
@@ -21492,10 +21584,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
@@ -21506,6 +21604,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)
 	    {
@@ -26785,12 +26888,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))
@@ -26836,6 +26943,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;
 	}
     }
 
@@ -27588,7 +27699,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;
@@ -27603,6 +27715,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,
@@ -27924,6 +28041,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))
     {
@@ -28020,11 +28138,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);
@@ -28093,7 +28213,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:
@@ -28129,6 +28251,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;
@@ -28145,7 +28271,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;
@@ -30147,6 +30276,68 @@  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");
+      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;
+
+  /* Vector attributes are converted to #pragma omp declare simd values and
+     so we need them enabled.  */
+  flag_openmp = 1;
+
+  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"), cl);
+      TREE_CHAIN (c) = attrs;
+      if (processing_template_decl)
+	ATTR_IS_DEPENDENT (c) = 1;
+      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.  */
 
@@ -31327,35 +31518,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))
@@ -31518,7 +31737,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 e26e350..da58136 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 6199478..50a64ba 100644
--- 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));
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/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;
+}