public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [GOMP4][PATCH] SIMD-enabled functions (formerly Elemental functions) for C++
@ 2013-11-21  4:41 Iyer, Balaji V
  2013-12-01  4:53 ` Iyer, Balaji V
  0 siblings, 1 reply; 11+ messages in thread
From: Iyer, Balaji V @ 2013-11-21  4:41 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Aldy Hernandez (aldyh@redhat.com), Jeff Law, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1376 bytes --]

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

gcc/cp/ChangeLog
2013-11-20  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).
        (cp_parser_elem_fn_vectorlength): New function.
        (cp_parser_elem_fn_expr_list): Likewise.
        (cp_parser_late_parsing_elem_fn_info): Likewise.
        * parser.h (cp_parser::elem_fn_info): New field.

gcc/testsuite/ChangeLog
2013-11-20  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.


Thanking You,

Yours Sincerely,

Balaji V. Iyer.

[-- Attachment #2: diff.txt --]
[-- Type: text/plain, Size: 13119 bytes --]

Index: gcc/testsuite/g++.dg/cilk-plus/ef_test.C
===================================================================
--- gcc/testsuite/g++.dg/cilk-plus/ef_test.C	(revision 0)
+++ gcc/testsuite/g++.dg/cilk-plus/ef_test.C	(revision 0)
@@ -0,0 +1,38 @@
+/* { 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;
+}
+
Index: gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
===================================================================
--- gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp	(revision 205160)
+++ gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp	(working copy)
@@ -60,6 +60,12 @@
 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O2 -ftree-vectorize -fcilkplus" " "
 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O3 -fcilkplus" " "
 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -O3 -ftree-vectorize -fcilkplus -g" " "
+
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/EF/*.c]] " -g" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/EF/*.c]] " -O1" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/EF/*.c]] " -O2 -std=c++11" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/EF/*.c]] " -O2 -ftree-vectorize" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/EF/*.c]] " -O3 -g" " "
 dg-finish
 
 unset TEST_EXTRA_LIBS
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 205160)
+++ gcc/cp/parser.c	(working copy)
@@ -2111,6 +2111,9 @@
 static tree cp_parser_late_parsing_omp_declare_simd
   (cp_parser *, tree);
 
+static tree cp_parser_late_parsing_elem_fn_info
+  (cp_parser *, tree);
+
 static tree synthesize_implicit_template_parm
   (cp_parser *);
 static tree finish_fully_implicit_template
@@ -17031,6 +17034,14 @@
 
 		  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));
@@ -17739,7 +17750,7 @@
    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.  */
@@ -17754,10 +17765,14 @@
 			 && declarator
 			 && declarator->kind == cdk_id);
 
+  bool elem_fn_vector_p = (parser->elem_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 || elem_fn_vector_p))
     return NULL_TREE;
 
   tree save_ccp = current_class_ptr;
@@ -17776,6 +17791,10 @@
       type = cp_parser_trailing_type_id (parser);
     }
 
+  if (elem_fn_vector_p)
+    declarator->std_attributes
+      = cp_parser_late_parsing_elem_fn_info (parser,
+					     declarator->std_attributes);
   if (declare_simd_p)
     declarator->std_attributes
       = cp_parser_late_parsing_omp_declare_simd (parser,
@@ -21306,6 +21325,121 @@
   return cp_parser_std_attribute_spec_seq (parser);
 }
 
+/* Parses the vectorlength clause in Cilk Plus SIMD-enabled function
+   (formerly called elemental functions).  Syntax:
+   vectorlength ( <constant integer> )   */
+
+static void
+cp_parser_elem_fn_vectorlength (cp_parser *parser,
+				cp_omp_declare_simd_data *info)
+{
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+    {
+      info->error_seen = true;
+      return;
+    }
+  
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+  location_t loc = token->location;
+  if (!token->u.value)
+    {
+      error_at (loc, "expected vectorlength value");
+      info->error_seen = true;
+      cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
+      return;
+    }
+  if (TREE_CODE (token->u.value) != INTEGER_CST)
+    {
+      error_at (loc, "vectorlength must be a constant integer");
+      info->error_seen = true;
+      cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
+      return;
+    }
+  if (!integer_pow2p (token->u.value))
+    {
+      error_at (loc, "vectorlength must be a power of 2");
+      info->error_seen = true;
+      cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
+      return;
+    }
+  /* Consume the vectorlength value.  */
+  cp_lexer_consume_token (parser->lexer);
+
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+    info->error_seen = true;
+}
+  
+cp_omp_declare_simd_data info;
+
+/* Parses the Cilk Plus SIMD-enabled function's attribute.  Syntax:
+   vector [(<clauses>)]  */
+
+static void
+cp_parser_elem_fn_expr_list (cp_parser *parser, cp_token *v_token)
+{  
+  bool first_p = parser->elem_fn_info == NULL;
+  cp_token *token = v_token;
+  if (first_p)
+    {
+      info.error_seen = false;
+      info.fndecl_seen = false;
+      info.tokens = vNULL;
+      parser->elem_fn_info = &info;
+    }
+  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--;
+      else if (token->type == CPP_NAME
+	  && TREE_CODE (token->u.value) == IDENTIFIER_NODE)
+	{
+	  tree val = token->u.value;
+	  if (simple_cst_equal (val, get_identifier ("mask")) == 1)
+	    token->u.value = get_identifier ("inbranch");
+	  else if (simple_cst_equal (val, get_identifier ("nomask")) == 1)
+	    token->u.value = get_identifier ("notinbranch");
+	  else if (simple_cst_equal (val, 
+				     get_identifier ("vectorlength")) == 1)
+	    {
+	      token->u.value = get_identifier ("simdlen");
+	      parser->lexer->next_token->u.value = token->u.value;
+	      cp_lexer_consume_token (parser->lexer);
+	      cp_parser_elem_fn_vectorlength (parser, &info);
+	      /* The above function should parse till the end of 
+		 vectorlength's last parenthesis.  */
+	      continue;
+	    }
+	  /* linear and uniform are the same between SIMD-enabled functions
+	     and #pragma omp declare simd.  */
+	  
+	  /* We sometimes modify the next token, so reset the next token.  */
+	  parser->lexer->next_token->u.value = token->u.value;
+	}
+
+      /* 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->elem_fn_info->tokens.safe_push (cp);
+}
+
 /* Parse an (optional) series of attributes.
 
    attributes:
@@ -21402,8 +21536,9 @@
 	{
 	  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.  */
@@ -21411,7 +21546,7 @@
 	    /* 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);
 
@@ -21423,10 +21558,17 @@
 	      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 (simple_cst_equal (identifier,
+				    get_identifier ("vector")) == 1)
+		{
+		  cp_parser_elem_fn_expr_list (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
@@ -21437,6 +21579,12 @@
 	      /* Save the arguments away.  */
 	      TREE_VALUE (attribute) = arguments;
 	    }
+	  else if (simple_cst_equal (identifier,
+				     get_identifier ("vector")) == 1)
+	    {
+	      cp_parser_elem_fn_expr_list (parser, id_token);
+	      continue;
+	    }
 
 	  if (arguments != error_mark_node)
 	    {
@@ -28076,7 +28224,10 @@
 	}
     }
  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;
@@ -30074,6 +30225,59 @@
     }
 }
 
+/* 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_elem_fn_info (cp_parser *parser, tree attrs)
+{
+  struct cp_token_cache *ce;
+  cp_omp_declare_simd_data *info = parser->elem_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 SIMD-enabled function");
+      parser->elem_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, OMP_DECLARE_SIMD_CLAUSE_MASK,
+				      "#pragma omp declare simd", NULL);
+      cp_parser_pop_lexer (parser);
+      if (cl)
+	cl = tree_cons (NULL_TREE, cl, NULL_TREE);
+      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;
+  parser->elem_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.  */
 
Index: gcc/cp/parser.h
===================================================================
--- gcc/cp/parser.h	(revision 205160)
+++ gcc/cp/parser.h	(working copy)
@@ -361,6 +361,13 @@
      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)) elem_fn_info;
+
   /* Nonzero if parsing a parameter list where 'auto' should trigger an implicit
      template parameter.  */
   bool auto_is_implicit_function_template_parm_p;

^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [GOMP4][PATCH] SIMD-enabled functions (formerly Elemental functions) for C++
  2013-11-21  4:41 [GOMP4][PATCH] SIMD-enabled functions (formerly Elemental functions) for C++ Iyer, Balaji V
@ 2013-12-01  4:53 ` Iyer, Balaji V
  2013-12-05 16:36   ` FW: " Iyer, Balaji V
  0 siblings, 1 reply; 11+ messages in thread
From: Iyer, Balaji V @ 2013-12-01  4:53 UTC (permalink / raw)
  To: 'Jakub Jelinek'
  Cc: Aldy Hernandez (aldyh@redhat.com), 'Jeff Law',
	'gcc-patches@gcc.gnu.org'

[-- Attachment #1: Type: text/plain, Size: 3432 bytes --]

Hello Everyone,
	The changes mentioned in http://gcc.gnu.org/ml/gcc-patches/2013-11/msg03506.html is also applicable to my C++ patch. With this email, I am attaching a fixed patch.

Here are the ChangeLog entries:

gcc/cp/ChangeLog
2013-11-30  Balaji V. Iyer  <balaji.v.iyer@intel.com>

        * decl2.c (is_late_template_attribute): Added a check for SIMD-enabled
        functions attribute.  If found, return true.
        * 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).
        (cp_parser_elem_fn_vectorlength): New function.
        (cp_parser_elem_fn_expr_list): Likewise.
        (cp_parser_late_parsing_elem_fn_info): Likewise.
        * parser.h (cp_parser::elem_fn_info): New field.
        * decl.c (grokfndecl): Added a check if Cilk Plus is enabled and
        if so, adjust the Cilk Plus SIMD-enabled function attributes.


gcc/testsuite/ChangeLog
2013-11-30  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.

Is this OK for branch?

Thanks,

Balaji V. Iyer.

> -----Original Message-----
> From: Iyer, Balaji V
> Sent: Wednesday, November 20, 2013 6:19 PM
> To: Jakub Jelinek
> Cc: Aldy Hernandez (aldyh@redhat.com); Jeff Law; gcc-patches@gcc.gnu.org
> Subject: [GOMP4][PATCH] SIMD-enabled functions (formerly Elemental
> functions) for C++
> 
> Hello Everyone,
> 	Attached, please find a patch that will implement SIMD-enabled
> functions for C++ targeting the gomp-4_0-branch. Here are the Changelog
> entries. Is this OK to install?
> 
> gcc/cp/ChangeLog
> 2013-11-20  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).
>         (cp_parser_elem_fn_vectorlength): New function.
>         (cp_parser_elem_fn_expr_list): Likewise.
>         (cp_parser_late_parsing_elem_fn_info): Likewise.
>         * parser.h (cp_parser::elem_fn_info): New field.
> 
> gcc/testsuite/ChangeLog
> 2013-11-20  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.
> 
> 
> Thanking You,
> 
> Yours Sincerely,
> 
> Balaji V. Iyer.

[-- Attachment #2: diff2.txt --]
[-- Type: text/plain, Size: 15526 bytes --]

Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(revision 205562)
+++ gcc/cp/decl.c	(working copy)
@@ -7669,6 +7669,34 @@
 	}
     }
 
+  if (flag_enable_cilkplus)
+    {
+      /* Adjust "cilk plus elemental attribute" attributes.  */
+      tree ods = lookup_attribute ("cilk plus elemental", *attrlist);
+      if (ods)
+	{
+	  tree attr;
+	  for (attr = ods; attr; 
+	       attr = lookup_attribute ("cilk plus elemental",
+					TREE_CHAIN (attr)))
+	    {
+	      if (TREE_CODE (type) == METHOD_TYPE)
+		walk_tree (&TREE_VALUE (attr), declare_simd_adjust_this,
+			   DECL_ARGUMENTS (decl), NULL);
+	      if (TREE_VALUE (attr) != NULL_TREE)
+		{
+		  tree cl = TREE_VALUE (TREE_VALUE (attr));
+		  cl = c_omp_declare_simd_clauses_to_numbers
+						(DECL_ARGUMENTS (decl), cl);
+		  if (cl)
+		    TREE_VALUE (TREE_VALUE (attr)) = cl;
+		  else
+		    TREE_VALUE (attr) = NULL_TREE;
+		}
+	    }
+	}
+    }
+  
   /* Caller will do the rest of this.  */
   if (check < 0)
     return decl;
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 205562)
+++ gcc/cp/pt.c	(working copy)
@@ -8603,9 +8603,12 @@
 	    {
 	      *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 plus elemental",
+					  get_attribute_name (t))))
 		  && TREE_VALUE (t))
 		{
 		  tree clauses = TREE_VALUE (TREE_VALUE (t));
Index: gcc/cp/decl2.c
===================================================================
--- gcc/cp/decl2.c	(revision 205562)
+++ gcc/cp/decl2.c	(working copy)
@@ -1124,6 +1124,10 @@
       && 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 plus elemental", name))
+    return true;
+
   /* If any of the arguments are dependent expressions, we can't evaluate
      the attribute until instantiation time.  */
   for (arg = args; arg; arg = TREE_CHAIN (arg))
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 205562)
+++ gcc/cp/parser.c	(working copy)
@@ -2115,6 +2115,9 @@
 static tree cp_parser_late_parsing_omp_declare_simd
   (cp_parser *, tree);
 
+static tree cp_parser_late_parsing_elem_fn_info
+  (cp_parser *, tree);
+
 static tree synthesize_implicit_template_parm
   (cp_parser *);
 static tree finish_fully_implicit_template
@@ -17035,6 +17038,14 @@
 
 		  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));
@@ -17743,7 +17754,7 @@
    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.  */
@@ -17758,10 +17769,14 @@
 			 && declarator
 			 && declarator->kind == cdk_id);
 
+  bool elem_fn_vector_p = (parser->elem_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 || elem_fn_vector_p))
     return NULL_TREE;
 
   tree save_ccp = current_class_ptr;
@@ -17780,6 +17795,10 @@
       type = cp_parser_trailing_type_id (parser);
     }
 
+  if (elem_fn_vector_p)
+    declarator->std_attributes
+      = cp_parser_late_parsing_elem_fn_info (parser,
+					     declarator->std_attributes);
   if (declare_simd_p)
     declarator->std_attributes
       = cp_parser_late_parsing_omp_declare_simd (parser,
@@ -21310,6 +21329,121 @@
   return cp_parser_std_attribute_spec_seq (parser);
 }
 
+/* Parses the vectorlength clause in Cilk Plus SIMD-enabled function
+   (formerly called elemental functions).  Syntax:
+   vectorlength ( <constant integer> )   */
+
+static void
+cp_parser_elem_fn_vectorlength (cp_parser *parser,
+				cp_omp_declare_simd_data *info)
+{
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+    {
+      info->error_seen = true;
+      return;
+    }
+  
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+  location_t loc = token->location;
+  if (!token->u.value)
+    {
+      error_at (loc, "expected vectorlength value");
+      info->error_seen = true;
+      cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
+      return;
+    }
+  if (TREE_CODE (token->u.value) != INTEGER_CST)
+    {
+      error_at (loc, "vectorlength must be a constant integer");
+      info->error_seen = true;
+      cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
+      return;
+    }
+  if (!integer_pow2p (token->u.value))
+    {
+      error_at (loc, "vectorlength must be a power of 2");
+      info->error_seen = true;
+      cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
+      return;
+    }
+  /* Consume the vectorlength value.  */
+  cp_lexer_consume_token (parser->lexer);
+
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+    info->error_seen = true;
+}
+  
+cp_omp_declare_simd_data info;
+
+/* Parses the Cilk Plus SIMD-enabled function's attribute.  Syntax:
+   vector [(<clauses>)]  */
+
+static void
+cp_parser_elem_fn_expr_list (cp_parser *parser, cp_token *v_token)
+{  
+  bool first_p = parser->elem_fn_info == NULL;
+  cp_token *token = v_token;
+  if (first_p)
+    {
+      info.error_seen = false;
+      info.fndecl_seen = false;
+      info.tokens = vNULL;
+      parser->elem_fn_info = &info;
+    }
+  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--;
+      else if (token->type == CPP_NAME
+	  && TREE_CODE (token->u.value) == IDENTIFIER_NODE)
+	{
+	  tree val = token->u.value;
+	  if (simple_cst_equal (val, get_identifier ("mask")) == 1)
+	    token->u.value = get_identifier ("inbranch");
+	  else if (simple_cst_equal (val, get_identifier ("nomask")) == 1)
+	    token->u.value = get_identifier ("notinbranch");
+	  else if (simple_cst_equal (val, 
+				     get_identifier ("vectorlength")) == 1)
+	    {
+	      token->u.value = get_identifier ("simdlen");
+	      parser->lexer->next_token->u.value = token->u.value;
+	      cp_lexer_consume_token (parser->lexer);
+	      cp_parser_elem_fn_vectorlength (parser, &info);
+	      /* The above function should parse till the end of 
+		 vectorlength's last parenthesis.  */
+	      continue;
+	    }
+	  /* linear and uniform are the same between SIMD-enabled functions
+	     and #pragma omp declare simd.  */
+	      
+	  /* We sometimes modify the next token, so reset the next token.  */
+	  parser->lexer->next_token->u.value = token->u.value;
+	}
+
+      /* 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->elem_fn_info->tokens.safe_push (cp);
+}
+
 /* Parse an (optional) series of attributes.
 
    attributes:
@@ -21406,8 +21540,9 @@
 	{
 	  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.  */
@@ -21415,7 +21550,7 @@
 	    /* 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);
 
@@ -21427,10 +21562,17 @@
 	      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 (simple_cst_equal (identifier,
+				    get_identifier ("vector")) == 1)
+		{
+		  cp_parser_elem_fn_expr_list (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
@@ -21441,6 +21583,12 @@
 	      /* Save the arguments away.  */
 	      TREE_VALUE (attribute) = arguments;
 	    }
+	  else if (simple_cst_equal (identifier,
+				     get_identifier ("vector")) == 1)
+	    {
+	      cp_parser_elem_fn_expr_list (parser, id_token);
+	      continue;
+	    }
 
 	  if (arguments != error_mark_node)
 	    {
@@ -28080,7 +28228,10 @@
 	}
     }
  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;
@@ -30078,6 +30229,61 @@
     }
 }
 
+/* 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_elem_fn_info (cp_parser *parser, tree attrs)
+{
+  struct cp_token_cache *ce;
+  cp_omp_declare_simd_data *info = parser->elem_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 SIMD-enabled function");
+      parser->elem_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, OMP_DECLARE_SIMD_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 ("omp declare simd"), cl);
+      c = build_tree_list (get_identifier ("cilk plus elemental"), cl);
+      TREE_CHAIN (c) = attrs;
+      if (processing_template_decl)
+	ATTR_IS_DEPENDENT (c) = 1;
+      attrs = c;
+    }
+  info->fndecl_seen = true;
+  parser->elem_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.  */
 
Index: gcc/cp/parser.h
===================================================================
--- gcc/cp/parser.h	(revision 205562)
+++ gcc/cp/parser.h	(working copy)
@@ -361,6 +361,13 @@
      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)) elem_fn_info;
+
   /* Nonzero if parsing a parameter list where 'auto' should trigger an implicit
      template parameter.  */
   bool auto_is_implicit_function_template_parm_p;
Index: gcc/testsuite/g++.dg/cilk-plus/ef_test.C
===================================================================
--- gcc/testsuite/g++.dg/cilk-plus/ef_test.C	(revision 0)
+++ gcc/testsuite/g++.dg/cilk-plus/ef_test.C	(revision 0)
@@ -0,0 +1,38 @@
+/* { 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;
+}
+
Index: gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
===================================================================
--- gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp	(revision 205562)
+++ gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp	(working copy)
@@ -60,6 +60,12 @@
 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O2 -ftree-vectorize -fcilkplus" " "
 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O3 -fcilkplus" " "
 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -O3 -ftree-vectorize -fcilkplus -g" " "
+
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/EF/*.c]] " -g" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/EF/*.c]] " -O1" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/EF/*.c]] " -O2 -std=c++11" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/EF/*.c]] " -O2 -ftree-vectorize" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/EF/*.c]] " -O3 -g" " "
 dg-finish
 
 unset TEST_EXTRA_LIBS

^ permalink raw reply	[flat|nested] 11+ messages in thread

* FW: [GOMP4][PATCH] SIMD-enabled functions (formerly Elemental functions) for C++
  2013-12-01  4:53 ` Iyer, Balaji V
@ 2013-12-05 16:36   ` Iyer, Balaji V
  2013-12-16  4:53     ` Iyer, Balaji V
  0 siblings, 1 reply; 11+ messages in thread
From: Iyer, Balaji V @ 2013-12-05 16:36 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Aldy Hernandez (aldyh@redhat.com), gcc-patches

[-- Attachment #1: Type: text/plain, Size: 3941 bytes --]

PING!

-Balaji V. Iyer.

> -----Original Message-----
> From: Iyer, Balaji V
> Sent: Saturday, November 30, 2013 11:53 PM
> To: 'Jakub Jelinek'
> Cc: Aldy Hernandez (aldyh@redhat.com); 'Jeff Law'; 'gcc-
> patches@gcc.gnu.org'
> Subject: RE: [GOMP4][PATCH] SIMD-enabled functions (formerly Elemental
> functions) for C++
> 
> Hello Everyone,
> 	The changes mentioned in http://gcc.gnu.org/ml/gcc-patches/2013-
> 11/msg03506.html is also applicable to my C++ patch. With this email, I am
> attaching a fixed patch.
> 
> Here are the ChangeLog entries:
> 
> gcc/cp/ChangeLog
> 2013-11-30  Balaji V. Iyer  <balaji.v.iyer@intel.com>
> 
>         * decl2.c (is_late_template_attribute): Added a check for SIMD-enabled
>         functions attribute.  If found, return true.
>         * 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).
>         (cp_parser_elem_fn_vectorlength): New function.
>         (cp_parser_elem_fn_expr_list): Likewise.
>         (cp_parser_late_parsing_elem_fn_info): Likewise.
>         * parser.h (cp_parser::elem_fn_info): New field.
>         * decl.c (grokfndecl): Added a check if Cilk Plus is enabled and
>         if so, adjust the Cilk Plus SIMD-enabled function attributes.
> 
> 
> gcc/testsuite/ChangeLog
> 2013-11-30  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.
> 
> Is this OK for branch?
> 
> Thanks,
> 
> Balaji V. Iyer.
> 
> > -----Original Message-----
> > From: Iyer, Balaji V
> > Sent: Wednesday, November 20, 2013 6:19 PM
> > To: Jakub Jelinek
> > Cc: Aldy Hernandez (aldyh@redhat.com); Jeff Law;
> > gcc-patches@gcc.gnu.org
> > Subject: [GOMP4][PATCH] SIMD-enabled functions (formerly Elemental
> > functions) for C++
> >
> > Hello Everyone,
> > 	Attached, please find a patch that will implement SIMD-enabled
> > functions for C++ targeting the gomp-4_0-branch. Here are the
> > Changelog entries. Is this OK to install?
> >
> > gcc/cp/ChangeLog
> > 2013-11-20  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).
> >         (cp_parser_elem_fn_vectorlength): New function.
> >         (cp_parser_elem_fn_expr_list): Likewise.
> >         (cp_parser_late_parsing_elem_fn_info): Likewise.
> >         * parser.h (cp_parser::elem_fn_info): New field.
> >
> > gcc/testsuite/ChangeLog
> > 2013-11-20  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.
> >
> >
> > Thanking You,
> >
> > Yours Sincerely,
> >
> > Balaji V. Iyer.

[-- Attachment #2: diff2.txt --]
[-- Type: text/plain, Size: 15526 bytes --]

Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(revision 205562)
+++ gcc/cp/decl.c	(working copy)
@@ -7669,6 +7669,34 @@
 	}
     }
 
+  if (flag_enable_cilkplus)
+    {
+      /* Adjust "cilk plus elemental attribute" attributes.  */
+      tree ods = lookup_attribute ("cilk plus elemental", *attrlist);
+      if (ods)
+	{
+	  tree attr;
+	  for (attr = ods; attr; 
+	       attr = lookup_attribute ("cilk plus elemental",
+					TREE_CHAIN (attr)))
+	    {
+	      if (TREE_CODE (type) == METHOD_TYPE)
+		walk_tree (&TREE_VALUE (attr), declare_simd_adjust_this,
+			   DECL_ARGUMENTS (decl), NULL);
+	      if (TREE_VALUE (attr) != NULL_TREE)
+		{
+		  tree cl = TREE_VALUE (TREE_VALUE (attr));
+		  cl = c_omp_declare_simd_clauses_to_numbers
+						(DECL_ARGUMENTS (decl), cl);
+		  if (cl)
+		    TREE_VALUE (TREE_VALUE (attr)) = cl;
+		  else
+		    TREE_VALUE (attr) = NULL_TREE;
+		}
+	    }
+	}
+    }
+  
   /* Caller will do the rest of this.  */
   if (check < 0)
     return decl;
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 205562)
+++ gcc/cp/pt.c	(working copy)
@@ -8603,9 +8603,12 @@
 	    {
 	      *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 plus elemental",
+					  get_attribute_name (t))))
 		  && TREE_VALUE (t))
 		{
 		  tree clauses = TREE_VALUE (TREE_VALUE (t));
Index: gcc/cp/decl2.c
===================================================================
--- gcc/cp/decl2.c	(revision 205562)
+++ gcc/cp/decl2.c	(working copy)
@@ -1124,6 +1124,10 @@
       && 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 plus elemental", name))
+    return true;
+
   /* If any of the arguments are dependent expressions, we can't evaluate
      the attribute until instantiation time.  */
   for (arg = args; arg; arg = TREE_CHAIN (arg))
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 205562)
+++ gcc/cp/parser.c	(working copy)
@@ -2115,6 +2115,9 @@
 static tree cp_parser_late_parsing_omp_declare_simd
   (cp_parser *, tree);
 
+static tree cp_parser_late_parsing_elem_fn_info
+  (cp_parser *, tree);
+
 static tree synthesize_implicit_template_parm
   (cp_parser *);
 static tree finish_fully_implicit_template
@@ -17035,6 +17038,14 @@
 
 		  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));
@@ -17743,7 +17754,7 @@
    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.  */
@@ -17758,10 +17769,14 @@
 			 && declarator
 			 && declarator->kind == cdk_id);
 
+  bool elem_fn_vector_p = (parser->elem_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 || elem_fn_vector_p))
     return NULL_TREE;
 
   tree save_ccp = current_class_ptr;
@@ -17780,6 +17795,10 @@
       type = cp_parser_trailing_type_id (parser);
     }
 
+  if (elem_fn_vector_p)
+    declarator->std_attributes
+      = cp_parser_late_parsing_elem_fn_info (parser,
+					     declarator->std_attributes);
   if (declare_simd_p)
     declarator->std_attributes
       = cp_parser_late_parsing_omp_declare_simd (parser,
@@ -21310,6 +21329,121 @@
   return cp_parser_std_attribute_spec_seq (parser);
 }
 
+/* Parses the vectorlength clause in Cilk Plus SIMD-enabled function
+   (formerly called elemental functions).  Syntax:
+   vectorlength ( <constant integer> )   */
+
+static void
+cp_parser_elem_fn_vectorlength (cp_parser *parser,
+				cp_omp_declare_simd_data *info)
+{
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+    {
+      info->error_seen = true;
+      return;
+    }
+  
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+  location_t loc = token->location;
+  if (!token->u.value)
+    {
+      error_at (loc, "expected vectorlength value");
+      info->error_seen = true;
+      cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
+      return;
+    }
+  if (TREE_CODE (token->u.value) != INTEGER_CST)
+    {
+      error_at (loc, "vectorlength must be a constant integer");
+      info->error_seen = true;
+      cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
+      return;
+    }
+  if (!integer_pow2p (token->u.value))
+    {
+      error_at (loc, "vectorlength must be a power of 2");
+      info->error_seen = true;
+      cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
+      return;
+    }
+  /* Consume the vectorlength value.  */
+  cp_lexer_consume_token (parser->lexer);
+
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+    info->error_seen = true;
+}
+  
+cp_omp_declare_simd_data info;
+
+/* Parses the Cilk Plus SIMD-enabled function's attribute.  Syntax:
+   vector [(<clauses>)]  */
+
+static void
+cp_parser_elem_fn_expr_list (cp_parser *parser, cp_token *v_token)
+{  
+  bool first_p = parser->elem_fn_info == NULL;
+  cp_token *token = v_token;
+  if (first_p)
+    {
+      info.error_seen = false;
+      info.fndecl_seen = false;
+      info.tokens = vNULL;
+      parser->elem_fn_info = &info;
+    }
+  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--;
+      else if (token->type == CPP_NAME
+	  && TREE_CODE (token->u.value) == IDENTIFIER_NODE)
+	{
+	  tree val = token->u.value;
+	  if (simple_cst_equal (val, get_identifier ("mask")) == 1)
+	    token->u.value = get_identifier ("inbranch");
+	  else if (simple_cst_equal (val, get_identifier ("nomask")) == 1)
+	    token->u.value = get_identifier ("notinbranch");
+	  else if (simple_cst_equal (val, 
+				     get_identifier ("vectorlength")) == 1)
+	    {
+	      token->u.value = get_identifier ("simdlen");
+	      parser->lexer->next_token->u.value = token->u.value;
+	      cp_lexer_consume_token (parser->lexer);
+	      cp_parser_elem_fn_vectorlength (parser, &info);
+	      /* The above function should parse till the end of 
+		 vectorlength's last parenthesis.  */
+	      continue;
+	    }
+	  /* linear and uniform are the same between SIMD-enabled functions
+	     and #pragma omp declare simd.  */
+	      
+	  /* We sometimes modify the next token, so reset the next token.  */
+	  parser->lexer->next_token->u.value = token->u.value;
+	}
+
+      /* 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->elem_fn_info->tokens.safe_push (cp);
+}
+
 /* Parse an (optional) series of attributes.
 
    attributes:
@@ -21406,8 +21540,9 @@
 	{
 	  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.  */
@@ -21415,7 +21550,7 @@
 	    /* 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);
 
@@ -21427,10 +21562,17 @@
 	      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 (simple_cst_equal (identifier,
+				    get_identifier ("vector")) == 1)
+		{
+		  cp_parser_elem_fn_expr_list (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
@@ -21441,6 +21583,12 @@
 	      /* Save the arguments away.  */
 	      TREE_VALUE (attribute) = arguments;
 	    }
+	  else if (simple_cst_equal (identifier,
+				     get_identifier ("vector")) == 1)
+	    {
+	      cp_parser_elem_fn_expr_list (parser, id_token);
+	      continue;
+	    }
 
 	  if (arguments != error_mark_node)
 	    {
@@ -28080,7 +28228,10 @@
 	}
     }
  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;
@@ -30078,6 +30229,61 @@
     }
 }
 
+/* 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_elem_fn_info (cp_parser *parser, tree attrs)
+{
+  struct cp_token_cache *ce;
+  cp_omp_declare_simd_data *info = parser->elem_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 SIMD-enabled function");
+      parser->elem_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, OMP_DECLARE_SIMD_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 ("omp declare simd"), cl);
+      c = build_tree_list (get_identifier ("cilk plus elemental"), cl);
+      TREE_CHAIN (c) = attrs;
+      if (processing_template_decl)
+	ATTR_IS_DEPENDENT (c) = 1;
+      attrs = c;
+    }
+  info->fndecl_seen = true;
+  parser->elem_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.  */
 
Index: gcc/cp/parser.h
===================================================================
--- gcc/cp/parser.h	(revision 205562)
+++ gcc/cp/parser.h	(working copy)
@@ -361,6 +361,13 @@
      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)) elem_fn_info;
+
   /* Nonzero if parsing a parameter list where 'auto' should trigger an implicit
      template parameter.  */
   bool auto_is_implicit_function_template_parm_p;
Index: gcc/testsuite/g++.dg/cilk-plus/ef_test.C
===================================================================
--- gcc/testsuite/g++.dg/cilk-plus/ef_test.C	(revision 0)
+++ gcc/testsuite/g++.dg/cilk-plus/ef_test.C	(revision 0)
@@ -0,0 +1,38 @@
+/* { 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;
+}
+
Index: gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
===================================================================
--- gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp	(revision 205562)
+++ gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp	(working copy)
@@ -60,6 +60,12 @@
 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O2 -ftree-vectorize -fcilkplus" " "
 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O3 -fcilkplus" " "
 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -O3 -ftree-vectorize -fcilkplus -g" " "
+
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/EF/*.c]] " -g" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/EF/*.c]] " -O1" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/EF/*.c]] " -O2 -std=c++11" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/EF/*.c]] " -O2 -ftree-vectorize" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/EF/*.c]] " -O3 -g" " "
 dg-finish
 
 unset TEST_EXTRA_LIBS

^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [GOMP4][PATCH] SIMD-enabled functions (formerly Elemental functions) for C++
  2013-12-05 16:36   ` FW: " Iyer, Balaji V
@ 2013-12-16  4:53     ` Iyer, Balaji V
  2013-12-18 23:40       ` Iyer, Balaji V
  0 siblings, 1 reply; 11+ messages in thread
From: Iyer, Balaji V @ 2013-12-16  4:53 UTC (permalink / raw)
  To: 'Jakub Jelinek'
  Cc: Aldy Hernandez (aldyh@redhat.com), 'gcc-patches@gcc.gnu.org'

[-- Attachment #1: Type: text/plain, Size: 6841 bytes --]

Hello Everyone,
	The following changes mentioned in this thread (http://gcc.gnu.org/ml/gcc-patches/2013-12/msg01280.html) are also applicable to the C++ patch and the attached patch has been fixed accordingly:

1. Sharing the vectorlength parsing function between #pragma simd and SIMD enabled functions
2. Renaming the function that is parsing the SIMD enabled function attributes
3. Renaming "Cilk plus elementals" to "Cilk SIMD function" for the attribute name
4. Marking all the SIMD enabled function attributes with both "omp declare simd" and "cilk simd function."
5. Renaming an error message from "..SIMD-enabled function" to "Cilk Plus SIMD-enabled function..."

So, is this patch OK for branch/trunk?

Here are the ChangeLog entries:

Gcc/cp/ChangeLog:
2013-12-16  Balaji V. Iyer  <balaji.v.iyer@intel.com>

        * decl2.c (is_late_template_attribute): Added a check for SIMD-enabled
        functions attribute.  If found, return true.
        * 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).
        (cp_parser_cilk_simd_vectorlength): Modified this function to parse
        vectorlength attribute in SIMD-enabled function and #pragma SIMD's
        vectorlength clause.  Added a new parameter to pass in SIMD-enabled
        function's info.
        (cp_parser_cilk_simd_fn_vector_attrs): New function.
        (cp_parser_late_parsing_elem_fn_info): Likewise.
        * parser.h (cp_parser::elem_fn_info): New field.
        * decl.c (grokfndecl): Added a check if Cilk Plus is enabled and
        if so, adjust the Cilk Plus SIMD-enabled function attributes.

Gcc/testsuite/ChangeLog
2013-12-16  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.


Thanks,

Balaji V. Iyer.

> -----Original Message-----
> From: Iyer, Balaji V
> Sent: Thursday, December 5, 2013 11:37 AM
> To: Jakub Jelinek
> Cc: Aldy Hernandez (aldyh@redhat.com); gcc-patches@gcc.gnu.org
> Subject: FW: [GOMP4][PATCH] SIMD-enabled functions (formerly Elemental
> functions) for C++
> 
> PING!
> 
> -Balaji V. Iyer.
> 
> > -----Original Message-----
> > From: Iyer, Balaji V
> > Sent: Saturday, November 30, 2013 11:53 PM
> > To: 'Jakub Jelinek'
> > Cc: Aldy Hernandez (aldyh@redhat.com); 'Jeff Law'; 'gcc-
> > patches@gcc.gnu.org'
> > Subject: RE: [GOMP4][PATCH] SIMD-enabled functions (formerly
> Elemental
> > functions) for C++
> >
> > Hello Everyone,
> > 	The changes mentioned in http://gcc.gnu.org/ml/gcc-patches/2013-
> > 11/msg03506.html is also applicable to my C++ patch. With this email,
> > I am attaching a fixed patch.
> >
> > Here are the ChangeLog entries:
> >
> > gcc/cp/ChangeLog
> > 2013-11-30  Balaji V. Iyer  <balaji.v.iyer@intel.com>
> >
> >         * decl2.c (is_late_template_attribute): Added a check for SIMD-
> enabled
> >         functions attribute.  If found, return true.
> >         * 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).
> >         (cp_parser_elem_fn_vectorlength): New function.
> >         (cp_parser_elem_fn_expr_list): Likewise.
> >         (cp_parser_late_parsing_elem_fn_info): Likewise.
> >         * parser.h (cp_parser::elem_fn_info): New field.
> >         * decl.c (grokfndecl): Added a check if Cilk Plus is enabled and
> >         if so, adjust the Cilk Plus SIMD-enabled function attributes.
> >
> >
> > gcc/testsuite/ChangeLog
> > 2013-11-30  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.
> >
> > Is this OK for branch?
> >
> > Thanks,
> >
> > Balaji V. Iyer.
> >
> > > -----Original Message-----
> > > From: Iyer, Balaji V
> > > Sent: Wednesday, November 20, 2013 6:19 PM
> > > To: Jakub Jelinek
> > > Cc: Aldy Hernandez (aldyh@redhat.com); Jeff Law;
> > > gcc-patches@gcc.gnu.org
> > > Subject: [GOMP4][PATCH] SIMD-enabled functions (formerly Elemental
> > > functions) for C++
> > >
> > > Hello Everyone,
> > > 	Attached, please find a patch that will implement SIMD-enabled
> > > functions for C++ targeting the gomp-4_0-branch. Here are the
> > > Changelog entries. Is this OK to install?
> > >
> > > gcc/cp/ChangeLog
> > > 2013-11-20  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).
> > >         (cp_parser_elem_fn_vectorlength): New function.
> > >         (cp_parser_elem_fn_expr_list): Likewise.
> > >         (cp_parser_late_parsing_elem_fn_info): Likewise.
> > >         * parser.h (cp_parser::elem_fn_info): New field.
> > >
> > > gcc/testsuite/ChangeLog
> > > 2013-11-20  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.
> > >
> > >
> > > Thanking You,
> > >
> > > Yours Sincerely,
> > >
> > > Balaji V. Iyer.

[-- Attachment #2: diff3.txt --]
[-- Type: text/plain, Size: 17776 bytes --]

Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(revision 205562)
+++ gcc/cp/decl.c	(working copy)
@@ -7669,6 +7669,34 @@
 	}
     }
 
+  if (flag_enable_cilkplus)
+    {
+      /* Adjust "cilk simd function attribute" attributes.  */
+      tree ods = lookup_attribute ("cilk simd function", *attrlist);
+      if (ods)
+	{
+	  tree attr;
+	  for (attr = ods; attr; 
+	       attr = lookup_attribute ("cilk simd function",
+					TREE_CHAIN (attr)))
+	    {
+	      if (TREE_CODE (type) == METHOD_TYPE)
+		walk_tree (&TREE_VALUE (attr), declare_simd_adjust_this,
+			   DECL_ARGUMENTS (decl), NULL);
+	      if (TREE_VALUE (attr) != NULL_TREE)
+		{
+		  tree cl = TREE_VALUE (TREE_VALUE (attr));
+		  cl = c_omp_declare_simd_clauses_to_numbers
+						(DECL_ARGUMENTS (decl), cl);
+		  if (cl)
+		    TREE_VALUE (TREE_VALUE (attr)) = cl;
+		  else
+		    TREE_VALUE (attr) = NULL_TREE;
+		}
+	    }
+	}
+    }
+  
   /* Caller will do the rest of this.  */
   if (check < 0)
     return decl;
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 205562)
+++ gcc/cp/pt.c	(working copy)
@@ -8603,9 +8603,12 @@
 	    {
 	      *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));
Index: gcc/cp/decl2.c
===================================================================
--- gcc/cp/decl2.c	(revision 205562)
+++ gcc/cp/decl2.c	(working copy)
@@ -1124,6 +1124,10 @@
       && 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;
+
   /* If any of the arguments are dependent expressions, we can't evaluate
      the attribute until instantiation time.  */
   for (arg = args; arg; arg = TREE_CHAIN (arg))
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 205562)
+++ gcc/cp/parser.c	(working copy)
@@ -241,6 +241,8 @@
   (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, cp_omp_declare_simd_data *);
 
 /* Manifest constants.  */
 #define CP_LEXER_BUFFER_SIZE ((256 * 1024) / sizeof (cp_token))
@@ -2115,6 +2117,9 @@
 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
@@ -17035,6 +17040,14 @@
 
 		  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));
@@ -17743,7 +17756,7 @@
    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.  */
@@ -17758,10 +17771,14 @@
 			 && 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;
@@ -17780,6 +17797,10 @@
       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,
@@ -21310,6 +21331,77 @@
   return cp_parser_std_attribute_spec_seq (parser);
 }
 
+cp_omp_declare_simd_data info;
+
+/* 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)
+    {
+      info.error_seen = false;
+      info.fndecl_seen = false;
+      info.tokens = vNULL;
+      parser->cilk_simd_fn_info = &info;
+    }
+  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--;
+      else if (token->type == CPP_NAME
+	  && TREE_CODE (token->u.value) == IDENTIFIER_NODE)
+	{
+	  tree val = token->u.value;
+	  if (simple_cst_equal (val, get_identifier ("mask")) == 1)
+	    token->u.value = get_identifier ("inbranch");
+	  else if (simple_cst_equal (val, get_identifier ("nomask")) == 1)
+	    token->u.value = get_identifier ("notinbranch");
+	  else if (simple_cst_equal (val, 
+				     get_identifier ("vectorlength")) == 1)
+	    {
+	      token->u.value = get_identifier ("simdlen");
+	      parser->lexer->next_token->u.value = token->u.value;
+	      cp_lexer_consume_token (parser->lexer);
+	      cp_parser_cilk_simd_vectorlength (parser, NULL_TREE, &info);
+	      /* The above function should parse till the end of 
+		 vectorlength's last parenthesis.  */
+	      continue;
+	    }
+	  /* linear and uniform are the same between SIMD-enabled functions
+	     and #pragma omp declare simd.  */
+	      
+	  /* We sometimes modify the next token, so reset the next token.  */
+	  parser->lexer->next_token->u.value = token->u.value;
+	}
+
+      /* 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:
@@ -21406,8 +21498,9 @@
 	{
 	  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.  */
@@ -21415,7 +21508,7 @@
 	    /* 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);
 
@@ -21427,10 +21520,17 @@
 	      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 (simple_cst_equal (identifier,
+				    get_identifier ("vector")) == 1)
+		{
+		  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
@@ -21441,6 +21541,12 @@
 	      /* Save the arguments away.  */
 	      TREE_VALUE (attribute) = arguments;
 	    }
+	  else if (simple_cst_equal (identifier,
+				     get_identifier ("vector")) == 1)
+	    {
+	      cp_parser_cilk_simd_fn_vector_attrs (parser, id_token);
+	      continue;
+	    }
 
 	  if (arguments != error_mark_node)
 	    {
@@ -28080,7 +28186,10 @@
 	}
     }
  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;
@@ -30078,6 +30187,67 @@
     }
 }
 
+/* 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, OMP_DECLARE_SIMD_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;
+  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.  */
 
@@ -31260,39 +31430,72 @@
   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,
+				  cp_omp_declare_simd_data *info)
 {
+  bool parsing_simd_fn = true;
+  if (info == NULL) 
+    parsing_simd_fn = false;
+
   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);
+  if (!parsing_simd_fn) 
+    check_no_duplicate_clause (clauses, OMP_CLAUSE_SAFELEN, "vectorlength", 
+			       loc);
   
   if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
-    return error_mark_node;
+    {
+      if (parsing_simd_fn)
+	info->error_seen = true; 
+      return error_mark_node;
+    }
   
   expr = cp_parser_constant_expression (parser, false, NULL);
   expr = maybe_constant_value (expr);
-
+  if (parsing_simd_fn && expr == error_mark_node)
+    {
+      info->error_seen = true;
+      cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
+      return error_mark_node;
+    }
+  if (parsing_simd_fn && !processing_template_decl
+      && (!TREE_TYPE (expr) || !TREE_CONSTANT (expr) 
+	  || !INTEGRAL_TYPE_P (TREE_TYPE (expr))))
+    {
+      error_at (loc, "vectorlength must be an integer constant");
+      info->error_seen = true;
+      cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
+      return error_mark_node;
+    }
   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)
     {
-      tree c = build_omp_clause (loc, OMP_CLAUSE_SAFELEN);
-      OMP_CLAUSE_SAFELEN_EXPR (c) = expr;
-      OMP_CLAUSE_CHAIN (c) = clauses;
-      clauses = c;
+      if (!parsing_simd_fn)
+	{ 
+	  tree c = build_omp_clause (loc, OMP_CLAUSE_SAFELEN); 
+	  OMP_CLAUSE_SAFELEN_EXPR (c) = expr; 
+	  OMP_CLAUSE_CHAIN (c) = clauses; 
+	  clauses = c;
+	}
     }
 
   if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
-    return error_mark_node;
+    { 
+      if (parsing_simd_fn) 
+	info->error_seen = true;
+      return error_mark_node;
+    }
   return clauses;
 }
 
@@ -31451,7 +31654,7 @@
       pragma_cilk_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, NULL);
       else if (c_kind == PRAGMA_CILK_CLAUSE_LINEAR)
 	clauses = cp_parser_cilk_simd_linear (parser, clauses);
       else if (c_kind == PRAGMA_CILK_CLAUSE_PRIVATE)
Index: gcc/cp/parser.h
===================================================================
--- gcc/cp/parser.h	(revision 205562)
+++ gcc/cp/parser.h	(working copy)
@@ -361,6 +361,13 @@
      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;
Index: gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
===================================================================
--- gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp	(revision 205562)
+++ gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp	(working copy)
@@ -60,6 +60,12 @@
 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O2 -ftree-vectorize -fcilkplus" " "
 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O3 -fcilkplus" " "
 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -O3 -ftree-vectorize -fcilkplus -g" " "
+
+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]] " -O1" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/SE/*.c]] " -O2 -std=c++11" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/SE/*.c]] " -O2 -ftree-vectorize" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/SE/*.c]] " -O3 -g" " "
 dg-finish
 
 unset TEST_EXTRA_LIBS
Index: gcc/testsuite/g++.dg/cilk-plus/ef_test.C
===================================================================
--- gcc/testsuite/g++.dg/cilk-plus/ef_test.C	(revision 0)
+++ gcc/testsuite/g++.dg/cilk-plus/ef_test.C	(revision 0)
@@ -0,0 +1,38 @@
+/* { 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;
+}
+

^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [GOMP4][PATCH] SIMD-enabled functions (formerly Elemental functions) for C++
  2013-12-16  4:53     ` Iyer, Balaji V
@ 2013-12-18 23:40       ` Iyer, Balaji V
  2013-12-19  7:23         ` Jakub Jelinek
  0 siblings, 1 reply; 11+ messages in thread
From: Iyer, Balaji V @ 2013-12-18 23:40 UTC (permalink / raw)
  To: 'Jakub Jelinek'
  Cc: 'Aldy Hernandez (aldyh@redhat.com)',
	'gcc-patches@gcc.gnu.org'

[-- Attachment #1: Type: text/plain, Size: 9704 bytes --]

Hello Jakub,
	Attached, please find a patch that will implement SIMD-enabled functions for C++.  To my best knowledge, I have incorporated all the changes you have mentioned in C patch that are applicable for C++.

	Is this Ok to trunk? It passes all the tests on my SUSE machine for -m32 and -m64.

Here are the ChangeLog entries:
gcc/cp/ChangeLog
2013-12-18  Balaji V. Iyer  <balaji.v.iyer@intel.com>

	* decl2.c (is_late_template_attribute): Added a check for SIMD-enabled
	functions attribute.  If found, return true.
	* 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.

gcc/testsuite/ChangeLog
2013-12-18  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 differentiate C error messages from C++ ones.

Thanks,
Balaji V. Iyer.



> -----Original Message-----
> From: Iyer, Balaji V
> Sent: Sunday, December 15, 2013 11:53 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++
> 
> Hello Everyone,
> 	The following changes mentioned in this thread
> (http://gcc.gnu.org/ml/gcc-patches/2013-12/msg01280.html) are also
> applicable to the C++ patch and the attached patch has been fixed
> accordingly:
> 
> 1. Sharing the vectorlength parsing function between #pragma simd and
> SIMD enabled functions 2. Renaming the function that is parsing the SIMD
> enabled function attributes 3. Renaming "Cilk plus elementals" to "Cilk SIMD
> function" for the attribute name 4. Marking all the SIMD enabled function
> attributes with both "omp declare simd" and "cilk simd function."
> 5. Renaming an error message from "..SIMD-enabled function" to "Cilk Plus
> SIMD-enabled function..."
> 
> So, is this patch OK for branch/trunk?
> 
> Here are the ChangeLog entries:
> 
> Gcc/cp/ChangeLog:
> 2013-12-16  Balaji V. Iyer  <balaji.v.iyer@intel.com>
> 
>         * decl2.c (is_late_template_attribute): Added a check for SIMD-enabled
>         functions attribute.  If found, return true.
>         * 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).
>         (cp_parser_cilk_simd_vectorlength): Modified this function to parse
>         vectorlength attribute in SIMD-enabled function and #pragma SIMD's
>         vectorlength clause.  Added a new parameter to pass in SIMD-enabled
>         function's info.
>         (cp_parser_cilk_simd_fn_vector_attrs): New function.
>         (cp_parser_late_parsing_elem_fn_info): Likewise.
>         * parser.h (cp_parser::elem_fn_info): New field.
>         * decl.c (grokfndecl): Added a check if Cilk Plus is enabled and
>         if so, adjust the Cilk Plus SIMD-enabled function attributes.
> 
> Gcc/testsuite/ChangeLog
> 2013-12-16  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.
> 
> 
> Thanks,
> 
> Balaji V. Iyer.
> 
> > -----Original Message-----
> > From: Iyer, Balaji V
> > Sent: Thursday, December 5, 2013 11:37 AM
> > To: Jakub Jelinek
> > Cc: Aldy Hernandez (aldyh@redhat.com); gcc-patches@gcc.gnu.org
> > Subject: FW: [GOMP4][PATCH] SIMD-enabled functions (formerly
> Elemental
> > functions) for C++
> >
> > PING!
> >
> > -Balaji V. Iyer.
> >
> > > -----Original Message-----
> > > From: Iyer, Balaji V
> > > Sent: Saturday, November 30, 2013 11:53 PM
> > > To: 'Jakub Jelinek'
> > > Cc: Aldy Hernandez (aldyh@redhat.com); 'Jeff Law'; 'gcc-
> > > patches@gcc.gnu.org'
> > > Subject: RE: [GOMP4][PATCH] SIMD-enabled functions (formerly
> > Elemental
> > > functions) for C++
> > >
> > > Hello Everyone,
> > > 	The changes mentioned in http://gcc.gnu.org/ml/gcc-patches/2013-
> > > 11/msg03506.html is also applicable to my C++ patch. With this
> > > email, I am attaching a fixed patch.
> > >
> > > Here are the ChangeLog entries:
> > >
> > > gcc/cp/ChangeLog
> > > 2013-11-30  Balaji V. Iyer  <balaji.v.iyer@intel.com>
> > >
> > >         * decl2.c (is_late_template_attribute): Added a check for
> > > SIMD-
> > enabled
> > >         functions attribute.  If found, return true.
> > >         * 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).
> > >         (cp_parser_elem_fn_vectorlength): New function.
> > >         (cp_parser_elem_fn_expr_list): Likewise.
> > >         (cp_parser_late_parsing_elem_fn_info): Likewise.
> > >         * parser.h (cp_parser::elem_fn_info): New field.
> > >         * decl.c (grokfndecl): Added a check if Cilk Plus is enabled and
> > >         if so, adjust the Cilk Plus SIMD-enabled function attributes.
> > >
> > >
> > > gcc/testsuite/ChangeLog
> > > 2013-11-30  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.
> > >
> > > Is this OK for branch?
> > >
> > > Thanks,
> > >
> > > Balaji V. Iyer.
> > >
> > > > -----Original Message-----
> > > > From: Iyer, Balaji V
> > > > Sent: Wednesday, November 20, 2013 6:19 PM
> > > > To: Jakub Jelinek
> > > > Cc: Aldy Hernandez (aldyh@redhat.com); Jeff Law;
> > > > gcc-patches@gcc.gnu.org
> > > > Subject: [GOMP4][PATCH] SIMD-enabled functions (formerly
> Elemental
> > > > functions) for C++
> > > >
> > > > Hello Everyone,
> > > > 	Attached, please find a patch that will implement SIMD-enabled
> > > > functions for C++ targeting the gomp-4_0-branch. Here are the
> > > > Changelog entries. Is this OK to install?
> > > >
> > > > gcc/cp/ChangeLog
> > > > 2013-11-20  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).
> > > >         (cp_parser_elem_fn_vectorlength): New function.
> > > >         (cp_parser_elem_fn_expr_list): Likewise.
> > > >         (cp_parser_late_parsing_elem_fn_info): Likewise.
> > > >         * parser.h (cp_parser::elem_fn_info): New field.
> > > >
> > > > gcc/testsuite/ChangeLog
> > > > 2013-11-20  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.
> > > >
> > > >
> > > > Thanking You,
> > > >
> > > > Yours Sincerely,
> > > >
> > > > Balaji V. Iyer.

[-- Attachment #2: simd_fn_cpp_diff.txt --]
[-- Type: text/plain, Size: 21050 bytes --]

diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index e5b98b1..b0c5ddd 100644
--- 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;
+
   /* If any of the arguments are dependent expressions, we can't evaluate
      the attribute until instantiation time.  */
   for (arg = args; arg; arg = TREE_CHAIN (arg))
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 2a2cbf0..b11c9ca 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,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));
@@ -17805,7 +17818,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 +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);
+  
   /* 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 +17859,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 +21396,58 @@ 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))
+
+cp_omp_declare_simd_data info;
+
+/* 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)
+    {
+      info.error_seen = false;
+      info.fndecl_seen = false;
+      info.tokens = vNULL;
+      parser->cilk_simd_fn_info = &info;
+    }
+  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 +21506,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 +21555,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 +21565,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 +21577,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 +21597,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 +26881,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 +26936,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 +27692,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 +27708,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 +28034,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 +28131,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 +28206,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 +28244,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 +28264,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 +30269,67 @@ 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;
+  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 +31510,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 simdbehaves 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 +31729,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;
+}

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [GOMP4][PATCH] SIMD-enabled functions (formerly Elemental functions) for C++
  2013-12-18 23:40       ` Iyer, Balaji V
@ 2013-12-19  7:23         ` Jakub Jelinek
  2013-12-19 18:12           ` Iyer, Balaji V
  0 siblings, 1 reply; 11+ messages in thread
From: Jakub Jelinek @ 2013-12-19  7:23 UTC (permalink / raw)
  To: Iyer, Balaji V
  Cc: 'Aldy Hernandez (aldyh@redhat.com)',
	'gcc-patches@gcc.gnu.org'

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?

> @@ -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?

> @@ -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.
> +
> +cp_omp_declare_simd_data info;

Global var?  Why?  Isn't heap or GC allocation better?
> +  /* The vectorlength clause in #pragma simdbehaves exactly like OpenMP's

Missing space after simd

> @@ -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?

	Jakub

^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [GOMP4][PATCH] SIMD-enabled functions (formerly Elemental functions) for C++
  2013-12-19  7:23         ` Jakub Jelinek
@ 2013-12-19 18:12           ` Iyer, Balaji V
  2014-01-17 17:45             ` Jakub Jelinek
  0 siblings, 1 reply; 11+ messages in thread
From: Iyer, Balaji V @ 2013-12-19 18:12 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: 'Aldy Hernandez (aldyh@redhat.com)',
	'gcc-patches@gcc.gnu.org'

[-- Attachment #1: Type: text/plain, Size: 5429 bytes --]

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

[-- Attachment #2: diff2.txt --]
[-- Type: text/plain, Size: 20870 bytes --]

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;
+}

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [GOMP4][PATCH] SIMD-enabled functions (formerly Elemental functions) for C++
  2013-12-19 18:12           ` Iyer, Balaji V
@ 2014-01-17 17:45             ` Jakub Jelinek
  2014-01-20  3:37               ` Iyer, Balaji V
       [not found]               ` <BF230D13CA30DD48930C31D4099330003A4BD257@FMSMSX101.amr.corp.intel.com>
  0 siblings, 2 replies; 11+ messages in thread
From: Jakub Jelinek @ 2014-01-17 17:45 UTC (permalink / raw)
  To: Iyer, Balaji V
  Cc: 'Aldy Hernandez (aldyh@redhat.com)',
	'gcc-patches@gcc.gnu.org'

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 " .

> +		  /* 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.

> +		    {
> +		      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.

> +  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.

> +/* 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.

> +      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.

> +      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;

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.

	Jakub

^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [GOMP4][PATCH] SIMD-enabled functions (formerly Elemental functions) for C++
  2014-01-17 17:45             ` Jakub Jelinek
@ 2014-01-20  3:37               ` Iyer, Balaji V
  2014-01-23  5:24                 ` FW: " Iyer, Balaji V
       [not found]               ` <BF230D13CA30DD48930C31D4099330003A4BD257@FMSMSX101.amr.corp.intel.com>
  1 sibling, 1 reply; 11+ messages in thread
From: Iyer, Balaji V @ 2014-01-20  3:37 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: 'Aldy Hernandez (aldyh@redhat.com)',
	'gcc-patches@gcc.gnu.org'

[-- Attachment #1: Type: text/plain, Size: 7017 bytes --]

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

[-- Attachment #2: diff.txt --]
[-- Type: text/plain, Size: 22970 bytes --]

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;
+}

[-- Attachment #3: ChangeLog.elem_fn --]
[-- Type: application/octet-stream, Size: 1952 bytes --]

gcc/c/ChangeLog
2014-01-19  Balaji V. Iyer  <balaji.v.iyer@intel.com>

	* c-parser.c (c_finish_omp_declare_simd): Made "cilk simd function"
	attribute an attribute without value.

gcc/cp/ChangeLog
2014-01-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
2014-01-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/ef_error3.c: Made certain messages C specific
	and added C++ ones.
	* c-c++-common/cilk-plus/vlength_errors.c: Added new dg-error tags
	to differenciate C error messages from C++ ones.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* FW: [GOMP4][PATCH] SIMD-enabled functions (formerly Elemental functions) for C++
  2014-01-20  3:37               ` Iyer, Balaji V
@ 2014-01-23  5:24                 ` Iyer, Balaji V
  0 siblings, 0 replies; 11+ messages in thread
From: Iyer, Balaji V @ 2014-01-23  5:24 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 7923 bytes --]

Hi Jakub,
	Did you get a chance to look at this? Is it OK to install to trunk?

Thanks,

Balaji V. Iyer.

> -----Original Message-----
> From: gcc-patches-owner@gcc.gnu.org [mailto:gcc-patches-
> owner@gcc.gnu.org] On Behalf Of Iyer, Balaji V
> Sent: Sunday, January 19, 2014 10:37 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,
> 	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

[-- Attachment #2: diff.txt --]
[-- Type: text/plain, Size: 22970 bytes --]

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;
+}

[-- Attachment #3: ChangeLog.elem_fn --]
[-- Type: application/octet-stream, Size: 1952 bytes --]

gcc/c/ChangeLog
2014-01-19  Balaji V. Iyer  <balaji.v.iyer@intel.com>

	* c-parser.c (c_finish_omp_declare_simd): Made "cilk simd function"
	attribute an attribute without value.

gcc/cp/ChangeLog
2014-01-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
2014-01-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/ef_error3.c: Made certain messages C specific
	and added C++ ones.
	* c-c++-common/cilk-plus/vlength_errors.c: Added new dg-error tags
	to differenciate C error messages from C++ ones.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: FW: [GOMP4][PATCH] SIMD-enabled functions (formerly Elemental functions) for C++
       [not found]               ` <BF230D13CA30DD48930C31D4099330003A4BD257@FMSMSX101.amr.corp.intel.com>
@ 2014-01-23  9:37                 ` Jakub Jelinek
  0 siblings, 0 replies; 11+ messages in thread
From: Jakub Jelinek @ 2014-01-23  9:37 UTC (permalink / raw)
  To: Iyer, Balaji V; +Cc: 'GCC Patches (gcc-patches@gcc.gnu.org)'

On Mon, Jan 20, 2014 at 03:42:02AM +0000, Iyer, Balaji V wrote:
> I forgot to add the 2 changelog entries for decl.c and pt.c. The patch is attached again with the corrected Changelogs.

This is ok for trunk, thanks.

	Jakub

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2014-01-23  9:37 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-11-21  4:41 [GOMP4][PATCH] SIMD-enabled functions (formerly Elemental functions) for C++ Iyer, Balaji V
2013-12-01  4:53 ` Iyer, Balaji V
2013-12-05 16:36   ` FW: " Iyer, Balaji V
2013-12-16  4:53     ` Iyer, Balaji V
2013-12-18 23:40       ` Iyer, Balaji V
2013-12-19  7:23         ` Jakub Jelinek
2013-12-19 18:12           ` Iyer, Balaji V
2014-01-17 17:45             ` Jakub Jelinek
2014-01-20  3:37               ` Iyer, Balaji V
2014-01-23  5:24                 ` FW: " Iyer, Balaji V
     [not found]               ` <BF230D13CA30DD48930C31D4099330003A4BD257@FMSMSX101.amr.corp.intel.com>
2014-01-23  9:37                 ` Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).