diff mbox

[VECTOR,ABI] Add __attribute__((__simd__)) to GCC.

Message ID 20151028091601.GA53647@msticlxl57.ims.intel.com
State New
Headers show

Commit Message

Kirill Yukhin Oct. 28, 2015, 9:16 a.m. UTC
Hello Jakub,

Your inputs fixed.

On 27 Oct 15:15, Jakub Jelinek wrote:
> > diff --git a/gcc/omp-low.c b/gcc/omp-low.c
> > index ad7c017..232dc5c 100644
> > --- a/gcc/omp-low.c
> > +++ b/gcc/omp-low.c
> > @@ -17412,10 +17412,7 @@ public:
> >  bool
> >  pass_omp_simd_clone::gate (function *)
> >  {
> > -  return ((flag_openmp || flag_openmp_simd
> > -	   || flag_cilkplus
> > -	   || (in_lto_p && !flag_wpa))
> > -	  && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
> > +  return targetm.simd_clone.compute_vecsize_and_simdlen != NULL;
> >  }
> >  
> >  } // anon namespace
> 
> I wonder what the compile time effect this will have.
> have (alternative is of course 
Concerning this. It should affect compile time since all work is
done if attribute is actually present.
It also already `ON' while LTO.

Bootstrapped. Regtested. Is it ok for trunk?


gcc/
        * omp-low.c (pass_omp_simd_clone::gate): If target allows - call
        without additional conditions.
        * doc/extend.texi (simd): Document new attribute.
gcc/cp/
        * parser.h (cp_parser): Add simd_attr_present.
        * parser.c (cp_parser_late_return_type_opt): Handle simd_attr_present,
        require comman in __vector__ attribute.
        (cp_parser_gnu_attribute_list): Ditto.
gcc/c/
        * c-parser.c (c_parser): Add simd_attr_present flag.
        (c_parser_declaration_or_fndef): Call c_parser_declaration_or_fndef
        if simd_attr_present is set.
        (c_finish_omp_declare_simd): Handle simd_attr_present.
gcc/testsuite/
        * c-c++-common/attr-simd.c: New test.
        * c-c++-common/attr-simd-2.c: Ditto.
        * c-c++-common/attr-simd-3.c: Ditto.

Comments

Jakub Jelinek Oct. 29, 2015, 8:54 a.m. UTC | #1
On Wed, Oct 28, 2015 at 12:16:04PM +0300, Kirill Yukhin wrote:
> Bootstrapped. Regtested. Is it ok for trunk?
> 
> 
> gcc/
>         * omp-low.c (pass_omp_simd_clone::gate): If target allows - call
>         without additional conditions.
>         * doc/extend.texi (simd): Document new attribute.
> gcc/cp/
>         * parser.h (cp_parser): Add simd_attr_present.
>         * parser.c (cp_parser_late_return_type_opt): Handle simd_attr_present,
>         require comman in __vector__ attribute.
>         (cp_parser_gnu_attribute_list): Ditto.
> gcc/c/
>         * c-parser.c (c_parser): Add simd_attr_present flag.
>         (c_parser_declaration_or_fndef): Call c_parser_declaration_or_fndef
>         if simd_attr_present is set.
>         (c_finish_omp_declare_simd): Handle simd_attr_present.

Actually, do you plan to eventually add some clauses/operands to the simd
attribute, or is the plan to just say that simd attribute is
#pragma omp declare simd
with no clauses as if -fopenmp-simd has been enabled?
If you don't plan to add any clauses, I wonder whether you really need to
add any parser changes at all, whether this couldn't be all handled in
c-family/c-common.c - handle_simd_attribute, adding simd to the attribute
table in there as a function decl attribute, and simply when processing it
add
        tree c = build_tree_list (get_identifier ("omp declare simd"), NULL_TREE);
        TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
        DECL_ATTRIBUTES (fndecl) = c;
(after checking whether the attribute isn't already present and erroring out
if there is "cilk simd function" attribute).
The reason for the (admittedly ugly) parser changes for #pragma omp declare simd is
that the clauses on the directive refer to parameters that will be declared
later, so we need to save the tokens of the pragma and then after parsing
the parameter declarations actually parse the clauses.  But, in the simd
attribute case, there are no clauses, there is nothing to parse later.

Sorry for not raising this earlier.

	Jakub
diff mbox

Patch

diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index c8c6a2d..d596b77 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -224,6 +224,9 @@  struct GTY(()) c_parser {
   /* Buffer to hold all the tokens from parsing the vector attribute for the
      SIMD-enabled functions (formerly known as elemental functions).  */
   vec <c_token, va_gc> *cilk_simd_fn_tokens;
+
+  /* Designates if "simd" attribute is specified in decl.  */
+  BOOL_BITFIELD simd_attr_present : 1;
 };
 
 
@@ -1701,7 +1704,8 @@  c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
       if (declarator == NULL)
 	{
 	  if (omp_declare_simd_clauses.exists ()
-	      || !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
+	      || !vec_safe_is_empty (parser->cilk_simd_fn_tokens)
+	      || parser->simd_attr_present)
 	    c_finish_omp_declare_simd (parser, NULL_TREE, NULL_TREE,
 				       omp_declare_simd_clauses);
 	  c_parser_skip_to_end_of_block_or_statement (parser);
@@ -1797,7 +1801,8 @@  c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 		  if (!d)
 		    d = error_mark_node;
 		  if (omp_declare_simd_clauses.exists ()
-		      || !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
+		      || !vec_safe_is_empty (parser->cilk_simd_fn_tokens)
+		      || parser->simd_attr_present)
 		    c_finish_omp_declare_simd (parser, d, NULL_TREE,
 					       omp_declare_simd_clauses);
 		}
@@ -1810,7 +1815,8 @@  c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 		  if (!d)
 		    d = error_mark_node;
 		  if (omp_declare_simd_clauses.exists ()
-		      || !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
+		      || !vec_safe_is_empty (parser->cilk_simd_fn_tokens)
+		      || parser->simd_attr_present)
 		    c_finish_omp_declare_simd (parser, d, NULL_TREE,
 					       omp_declare_simd_clauses);
 		  start_init (d, asm_name, global_bindings_p ());
@@ -1839,7 +1845,8 @@  c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 				   chainon (postfix_attrs,
 					    all_prefix_attrs));
 	      if (omp_declare_simd_clauses.exists ()
-		  || !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
+		  || !vec_safe_is_empty (parser->cilk_simd_fn_tokens)
+		  || parser->simd_attr_present)
 		{
 		  tree parms = NULL_TREE;
 		  if (d && TREE_CODE (d) == FUNCTION_DECL)
@@ -1968,7 +1975,8 @@  c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 				       true, false, NULL, vNULL);
       store_parm_decls ();
       if (omp_declare_simd_clauses.exists ()
-	  || !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
+	  || !vec_safe_is_empty (parser->cilk_simd_fn_tokens)
+	  || parser->simd_attr_present)
 	c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
 				   omp_declare_simd_clauses);
       DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
@@ -3993,6 +4001,15 @@  c_parser_attributes (c_parser *parser)
 		break;
 	      continue;
 	    }
+	  if (is_attribute_p ("simd", attr_name))
+	    {
+	      parser->simd_attr_present = 1;
+	      c_parser_consume_token (parser);
+	      /* If the next token isn't a comma, we're done.  */
+	      if (!c_parser_next_token_is (parser, CPP_COMMA))
+		break;
+	      continue;
+	    }
 	  c_parser_consume_token (parser);
 	  if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
 	    {
@@ -15388,10 +15405,11 @@  c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms,
 			   vec<c_token> clauses)
 {
   if (flag_cilkplus
-      && clauses.exists () && !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
+      && (clauses.exists () || parser->simd_attr_present)
+      && !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
     {
-      error ("%<#pragma omp declare simd%> cannot be used in the same "
-	     "function marked as a Cilk Plus SIMD-enabled function");
+      error ("%<#pragma omp declare simd%> or %<__simd__%> attribute cannot be "
+	     "used in the same function marked as a Cilk Plus SIMD-enabled function");
       vec_free (parser->cilk_simd_fn_tokens);
       return;
     }
@@ -15423,7 +15441,7 @@  c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms,
   unsigned int tokens_avail = parser->tokens_avail;
   gcc_assert (parser->tokens == &parser->tokens_buf[0]);
   bool is_cilkplus_cilk_simd_fn = false;
-  
+
   if (flag_cilkplus && !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
     {
       parser->tokens = parser->cilk_simd_fn_tokens->address ();
@@ -15435,41 +15453,61 @@  c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms,
       parser->tokens = clauses.address ();
       parser->tokens_avail = clauses.length ();
     }
-  
-  /* c_parser_omp_declare_simd pushed 2 extra CPP_EOF tokens at the end.  */
-  while (parser->tokens_avail > 3)
+
+  if (parser->simd_attr_present && is_cilkplus_cilk_simd_fn)
     {
-      c_token *token = c_parser_peek_token (parser);
-      if (!is_cilkplus_cilk_simd_fn) 
-	gcc_assert (token->type == CPP_NAME 
-		    && strcmp (IDENTIFIER_POINTER (token->value), "simd") == 0);
-      else
-	gcc_assert (token->type == CPP_NAME
-		    && is_cilkplus_vector_p (token->value));
-      c_parser_consume_token (parser);
-      parser->in_pragma = true;
+      error ("SIMD-enabled function attributes"
+	     "are allowed when attribute %<__simd__%> is specified");
+      clauses[0].type = CPP_EOF;
+      return;
+    }
 
+  /* Attach `omp declare simd’ attribute if __simd__ is specified AND no OpenMP clauses
+     present in decl.  */
+  if (parser->simd_attr_present && parser->tokens_avail == 0)
+    {
       tree c = NULL_TREE;
-      if (is_cilkplus_cilk_simd_fn) 
-	c = c_parser_omp_all_clauses (parser, CILK_SIMD_FN_CLAUSE_MASK,
-				      "SIMD-enabled functions attribute");
-      else 
-	c = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK,
-				      "#pragma omp declare simd");
-      c = c_omp_declare_simd_clauses_to_numbers (parms, c);
-      if (c != NULL_TREE)
-	c = tree_cons (NULL_TREE, c, NULL_TREE);
-      if (is_cilkplus_cilk_simd_fn) 
-	{ 
-	  tree k = build_tree_list (get_identifier ("cilk simd function"), 
-				    NULL_TREE);
-	  TREE_CHAIN (k) = DECL_ATTRIBUTES (fndecl);
-	  DECL_ATTRIBUTES (fndecl) = k;
-	} 
       c = build_tree_list (get_identifier ("omp declare simd"), c);
       TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
       DECL_ATTRIBUTES (fndecl) = c;
     }
+  else
+    {
+      /* c_parser_omp_declare_simd pushed 2 extra CPP_EOF tokens at the end.  */
+      while (parser->tokens_avail > 3)
+	{
+	  c_token *token = c_parser_peek_token (parser);
+	  if (!is_cilkplus_cilk_simd_fn)
+	    gcc_assert (token->type == CPP_NAME
+			&& strcmp (IDENTIFIER_POINTER (token->value), "simd") == 0);
+	  else
+	    gcc_assert (token->type == CPP_NAME
+			&& is_cilkplus_vector_p (token->value));
+	  c_parser_consume_token (parser);
+	  parser->in_pragma = true;
+
+	  tree c = NULL_TREE;
+	  if (is_cilkplus_cilk_simd_fn)
+	    c = c_parser_omp_all_clauses (parser, CILK_SIMD_FN_CLAUSE_MASK,
+					  "SIMD-enabled functions attribute");
+	  else
+	    c = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK,
+					  "#pragma omp declare simd");
+	  c = c_omp_declare_simd_clauses_to_numbers (parms, c);
+	  if (c != NULL_TREE)
+	    c = tree_cons (NULL_TREE, c, NULL_TREE);
+	  if (is_cilkplus_cilk_simd_fn)
+	    {
+	      tree k = build_tree_list (get_identifier ("cilk simd function"),
+					NULL_TREE);
+	      TREE_CHAIN (k) = DECL_ATTRIBUTES (fndecl);
+	      DECL_ATTRIBUTES (fndecl) = k;
+	    }
+	  c = build_tree_list (get_identifier ("omp declare simd"), c);
+	  TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
+	  DECL_ATTRIBUTES (fndecl) = c;
+	}
+    }
 
   parser->tokens = &parser->tokens_buf[0];
   parser->tokens_avail = tokens_avail;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 7555bf3..a53d193 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -19331,7 +19331,9 @@  cp_parser_late_return_type_opt (cp_parser* parser, cp_declarator *declarator,
   /* A late-specified return type is indicated by an initial '->'. */
   if (token->type != CPP_DEREF
       && token->keyword != RID_REQUIRES
-      && !(declare_simd_p || cilk_simd_fn_vector_p))
+      && !(declare_simd_p
+	   || cilk_simd_fn_vector_p
+	   || parser->simd_attr_present))
     return NULL_TREE;
 
   tree save_ccp = current_class_ptr;
@@ -19363,6 +19365,17 @@  cp_parser_late_return_type_opt (cp_parser* parser, cp_declarator *declarator,
       = cp_parser_late_parsing_omp_declare_simd (parser,
 						 declarator->std_attributes);
 
+  if (parser->simd_attr_present && !declare_simd_p)
+    {
+      if (cilk_simd_fn_vector_p)
+	error ("%<__simd__%> attribute cannot be used in the same function"
+	       " marked as a Cilk Plus SIMD-enabled function");
+
+      tree c = build_tree_list (get_identifier ("omp declare simd"), NULL_TREE);
+      TREE_CHAIN (c) = declarator->std_attributes;
+      declarator->std_attributes = c;
+    }
+
   if (quals >= 0)
     {
       current_class_ptr = save_ccp;
@@ -23320,6 +23333,21 @@  cp_parser_gnu_attribute_list (cp_parser* parser)
 	  else if (is_cilkplus_vector_p (identifier))
 	    {
 	      cp_parser_cilk_simd_fn_vector_attrs (parser, id_token);
+	      /* Now, look for more attributes.  If the next token isn't a
+		 `,', we're done.  */
+	      if (token->type != CPP_COMMA)
+		break;
+
+	      continue;
+	    } else
+	  if (is_attribute_p ("simd", identifier))
+	    {
+	      parser->simd_attr_present = 1;
+	      /* Now, look for more attributes.  If the next token isn't a
+		 `,', we're done.  */
+	      if (token->type != CPP_COMMA)
+		break;
+
 	      continue;
 	    }
 
diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h
index 760467c..f4e33e3 100644
--- a/gcc/cp/parser.h
+++ b/gcc/cp/parser.h
@@ -371,6 +371,8 @@  struct GTY(()) cp_parser {
      necessary.  */
   cp_omp_declare_simd_data * GTY((skip)) cilk_simd_fn_info;
 
+  bool simd_attr_present;
+
   /* 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/doc/extend.texi b/gcc/doc/extend.texi
index fdb1547..32994a2 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -3066,6 +3066,21 @@  This function attribute make a stack protection of the function if
 flags @option{fstack-protector} or @option{fstack-protector-strong}
 or @option{fstack-protector-explicit} are set.
 
+@item simd
+@cindex @code{simd} function attribute.
+This attribute enables creation of one or more function versions that
+can process multiple arguments using SIMD instructions from a
+single invocation.  Specifying this attribute allows compiler to
+assume that such a versions are available at link time (provided
+in the same or another translation unit).  Generated versions are
+target dependent and described in corresponding Vector ABI document.  For
+x86_64 target this document can be found
+@w{@uref{https://sourceware.org/glibc/wiki/libmvec?action=AttachFile&do=view&target=VectorABI.txt,here}}.
+It is prohibited to use the attribute along with Cilk Plus's @code{vector}
+attribute. If the attribute is specified and @code{#pragma omp declare simd}
+presented on a declaration and @code{-fopenmp} or @code{-fopenmp-simd}
+switch is specified, then the attribute is ignored.
+
 @item target (@var{options})
 @cindex @code{target} function attribute
 Multiple target back ends implement the @code{target} attribute
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index ad7c017..232dc5c 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -17412,10 +17412,7 @@  public:
 bool
 pass_omp_simd_clone::gate (function *)
 {
-  return ((flag_openmp || flag_openmp_simd
-	   || flag_cilkplus
-	   || (in_lto_p && !flag_wpa))
-	  && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
+  return targetm.simd_clone.compute_vecsize_and_simdlen != NULL;
 }
 
 } // anon namespace
diff --git a/gcc/testsuite/c-c++-common/attr-simd-2.c b/gcc/testsuite/c-c++-common/attr-simd-2.c
new file mode 100644
index 0000000..e9afc11
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-simd-2.c
@@ -0,0 +1,11 @@ 
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-optimized -fopenmp-simd" } */
+
+#pragma omp declare simd
+__attribute__((__simd__))
+static int simd_attr (void)
+{
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump "omp declare simd" "optimized" } } */
diff --git a/gcc/testsuite/c-c++-common/attr-simd-3.c b/gcc/testsuite/c-c++-common/attr-simd-3.c
new file mode 100644
index 0000000..2bbdf04
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-simd-3.c
@@ -0,0 +1,5 @@ 
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-prune-output "undeclared here \\(not in a function\\)|\[^\n\r\]* was not declared in this scope" } */
+
+void f () __attribute__((__simd__, __vector__)); /* { dg-error "in the same function marked as a Cilk Plus" } */
diff --git a/gcc/testsuite/c-c++-common/attr-simd.c b/gcc/testsuite/c-c++-common/attr-simd.c
new file mode 100644
index 0000000..6fd757a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-simd.c
@@ -0,0 +1,17 @@ 
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-optimized" } */
+
+__attribute__((__simd__))
+static int simd_attr (void)
+{
+  return 0;
+}
+
+__attribute__((simd))
+static int simd_attr2 (void)
+{
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump "simd_attr\[ \\t\]simdclone|vector" "optimized" } } */
+/* { dg-final { scan-tree-dump "simd_attr2\[ \\t\]simdclone|vector" "optimized" } } */