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

login
register
mail settings
Submitter Iyer, Balaji V
Date Dec. 5, 2013, 4:36 p.m.
Message ID <BF230D13CA30DD48930C31D4099330003A4AF7E6@FMSMSX101.amr.corp.intel.com>
Download mbox | patch
Permalink /patch/297197/
State New
Headers show

Comments

Iyer, Balaji V - Dec. 5, 2013, 4:36 p.m.
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.

Patch

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