diff mbox

[Cilkplus] Handling elemental function for C Compiler.

Message ID BF230D13CA30DD48930C31D4099330000991471E@FMSMSX102.amr.corp.intel.com
State New
Headers show

Commit Message

Iyer, Balaji V May 8, 2012, 2:56 p.m. UTC
Hello Everyone,
    This patch is for the Cilkplus branch affecting mostly the C compiler. This patch will insert elemental functions for C programs.

Thanks,

Balaji V. Iyer.
diff mbox

Patch

diff --git a/gcc/ChangeLog.cilk b/gcc/ChangeLog.cilk
index d6b28e2..4f01d31 100644
--- a/gcc/ChangeLog.cilk
+++ b/gcc/ChangeLog.cilk
@@ -1,3 +1,17 @@ 
+2012-05-07  Balaji V. Iyer  <balaji.v.iyer@intel.com>
+
+	* c-parser.c (c_parser_declaration_or_fndef): Saved function arguments
+	for an elemental function.
+	* elem-function.c (find_elem_fn_parm_type_1): Added step-size parameter.
+	(find_elem_fn_parm_type): Likewise.
+	* tree-vect-stmts.c (vect_get_vec_def_for_operand): Added step-size
+	support for linear clause.  Also called elem_fn_linear_init_vector for
+	linear clause.
+	(vectorizable_call): When linear clause is set, set the vector type to
+	constant_def.
+	(elem_fn_linear_init_vector): New function.
+	* tree.c (build_elem_fn_linear_vector_from_val): Likewise.
+
 2012-04-24  Balaji V. Iyer  <balaji.v.iyer@intel.com>
 
 	* elem-function.c (find_elem_fn_param_type_1): New function.
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
index 6af434f..04c8eef 100644
--- a/gcc/c-parser.c
+++ b/gcc/c-parser.c
@@ -1640,7 +1640,7 @@  c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
   specs->attrs = NULL_TREE;
   while (true)
     {
-      struct c_declarator *declarator;
+      struct c_declarator *declarator = NULL;
       bool dummy = false;
       timevar_id_t tv;
       tree fnbody;
@@ -1705,6 +1705,11 @@  c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 	      tree d = start_decl (declarator, specs, false,
 				   chainon (postfix_attrs,
 					    all_prefix_attrs));
+	      if (d && TREE_CODE (d) == FUNCTION_DECL
+		  && declarator->kind == cdk_function
+		  && lookup_attribute ("vector", all_prefix_attrs)
+		  && declarator && declarator->u.arg_info)
+		DECL_ARGUMENTS (d) = declarator->u.arg_info->parms;
 	      if (d)
 		finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
 			     NULL_TREE, asm_name);
diff --git a/gcc/elem-function.c b/gcc/elem-function.c
index e6e3650..f3e4985 100644
--- a/gcc/elem-function.c
+++ b/gcc/elem-function.c
@@ -85,7 +85,7 @@  static tree create_processor_attribute (elem_fn_info *, tree *);
 
 /* this is an helper function for find_elem_fn_param_type */
 static enum elem_fn_parm_type
-find_elem_fn_parm_type_1 (tree fndecl, int parm_no)
+find_elem_fn_parm_type_1 (tree fndecl, int parm_no, tree *step_size)
 {
   int ii = 0;
   elem_fn_info *elem_fn_values;
@@ -96,7 +96,12 @@  find_elem_fn_parm_type_1 (tree fndecl, int parm_no)
 
   for (ii = 0; ii < elem_fn_values->no_lvars; ii++)
     if (elem_fn_values->linear_location[ii] == parm_no)
-      return TYPE_LINEAR;
+      {
+	if (step_size != NULL)
+	  *step_size = build_int_cst (integer_type_node,
+				      elem_fn_values->linear_steps[ii]);
+	return TYPE_LINEAR;
+      }
     
   for (ii = 0; ii < elem_fn_values->no_uvars; ii++)
     if (elem_fn_values->uniform_location[ii] == parm_no)
@@ -109,7 +114,7 @@  find_elem_fn_parm_type_1 (tree fndecl, int parm_no)
 /* this function will return the type of a parameter in elemental function.
    The choices are UNIFORM or LINEAR. */
 enum elem_fn_parm_type
-find_elem_fn_parm_type (gimple stmt, tree op)
+find_elem_fn_parm_type (gimple stmt, tree op, tree *step_size)
 {
   tree fndecl, parm = NULL_TREE;
   int ii, nargs;
@@ -128,7 +133,7 @@  find_elem_fn_parm_type (gimple stmt, tree op)
       parm = gimple_call_arg (stmt, ii);
       if (op == parm)
 	{
-	  return_type = find_elem_fn_parm_type_1 (fndecl, 1);
+	  return_type = find_elem_fn_parm_type_1 (fndecl, ii, step_size);
 	  return return_type;
 	}
     }
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 738a5a7..46dd4a8 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -42,6 +42,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "langhooks.h"
 #include "cilk.h"
 
+extern enum elem_fn_parm_type find_elem_fn_parm_type (gimple, tree, tree *);
 /* Return a variable of type ELEM_TYPE[NELEMS].  */
 
 static tree
@@ -1259,8 +1260,8 @@  vect_get_vec_def_for_operand (tree op, gimple stmt, tree *scalar_def)
   enum vect_def_type dt;
   bool is_simple_use;
   tree vector_type;
-
-  extern enum elem_fn_parm_type find_elem_fn_parm_type (gimple, tree);
+  enum elem_fn_parm_type parm_type;
+  tree step_size = NULL_TREE;
 
   if (vect_print_dump_info (REPORT_DETAILS))
     {
@@ -1289,14 +1290,12 @@  vect_get_vec_def_for_operand (tree op, gimple stmt, tree *scalar_def)
       && gimple_code (stmt) == GIMPLE_CALL
       && is_elem_fn (gimple_call_fndecl (stmt)))
     {
-      enum elem_fn_parm_type parm_type = find_elem_fn_parm_type (stmt, op);
-      if (parm_type == TYPE_UNIFORM)
+      parm_type = find_elem_fn_parm_type (stmt, op, &step_size);
+      if (parm_type == TYPE_UNIFORM || parm_type == TYPE_LINEAR)
 	dt = vect_constant_def;
-      else if (parm_type == TYPE_LINEAR)
-	{
-	  ;
-	}
     }
+  else
+    parm_type = TYPE_NONE;
       
   switch (dt)
     {
@@ -1313,8 +1312,13 @@  vect_get_vec_def_for_operand (tree op, gimple stmt, tree *scalar_def)
         /* Create 'vect_cst_ = {cst,cst,...,cst}'  */
         if (vect_print_dump_info (REPORT_DETAILS))
           fprintf (vect_dump, "Create vector_cst. nunits = %d", nunits);
-
-        return vect_init_vector (stmt, op, vector_type, NULL);
+	if (!flag_enable_cilk 
+	    || (parm_type == TYPE_NONE || parm_type == TYPE_UNIFORM))
+	  return vect_init_vector (stmt, op, vector_type, NULL);
+	else if (flag_enable_cilk && parm_type == TYPE_LINEAR)
+	  return elem_fn_linear_init_vector (stmt, op, vector_type,
+					     step_size, NULL);
+					     
       }
 
     /* Case 2: operand is defined outside the loop - loop invariant.  */
@@ -1640,6 +1644,7 @@  vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
   enum { NARROW, NONE, WIDEN } modifier;
   size_t i, nargs;
   tree lhs;
+  tree step_size = NULL_TREE;
 
   if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
     return false;
@@ -1841,6 +1846,16 @@  vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
 	      else
 		{
 		  vec_oprnd0 = gimple_call_arg (new_stmt, i);
+		  if (flag_enable_cilk
+		      && gimple_code (new_stmt) == GIMPLE_CALL
+		      && is_elem_fn (gimple_call_fndecl (new_stmt)))
+		    {
+		      enum elem_fn_parm_type parm_type =
+			find_elem_fn_parm_type (stmt, op, &step_size);
+		      if (parm_type == TYPE_UNIFORM
+			  || parm_type == TYPE_LINEAR)
+			dt[i] = vect_constant_def;
+		    }
 		  vec_oprnd0
                     = vect_get_vec_def_for_stmt_copy (dt[i], vec_oprnd0);
 		}
@@ -6549,3 +6564,55 @@  supportable_narrowing_operation (enum tree_code code,
   VEC_free (tree, heap, *interm_types);
   return false;
 }
+
+/* Function vect_init_vector.
+
+   Insert a new stmt (INIT_STMT) that initializes a new variable of type
+   TYPE with the value VAL.  If TYPE is a vector type and VAL does not have
+   vector type a vector with all elements equal to VAL is created first.
+   Place the initialization at BSI if it is not NULL.  Otherwise, place the
+   initialization at the loop preheader.
+   Return the DEF of INIT_STMT.
+   It will be used in the vectorization of STMT.  */
+
+tree
+elem_fn_linear_init_vector (gimple stmt, tree val, tree type, tree step_size,
+			    gimple_stmt_iterator *gsi)
+{
+  tree new_var;
+  gimple init_stmt;
+  tree vec_oprnd;
+  tree new_temp;
+
+  if (TREE_CODE (type) == VECTOR_TYPE
+      && TREE_CODE (TREE_TYPE (val)) != VECTOR_TYPE)
+    {
+      if (!types_compatible_p (TREE_TYPE (type), TREE_TYPE (val)))
+	{
+	  if (CONSTANT_CLASS_P (val))
+	    val = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (type), val);
+	  else
+	    {
+	      new_var = create_tmp_reg (TREE_TYPE (type), NULL);
+	      add_referenced_var (new_var);
+	      init_stmt = gimple_build_assign_with_ops (NOP_EXPR,
+							new_var, val,
+							NULL_TREE);
+	      new_temp = make_ssa_name (new_var, init_stmt);
+	      gimple_assign_set_lhs (init_stmt, new_temp);
+	      vect_init_vector_1 (stmt, init_stmt, gsi);
+	      val = new_temp;
+	    }
+	}
+      val = build_elem_fn_linear_vector_from_val (type, val, step_size);
+    }
+
+  new_var = vect_get_new_vect_var (type, vect_simple_var, "cst_");
+  add_referenced_var (new_var);
+  init_stmt = gimple_build_assign  (new_var, val);
+  new_temp = make_ssa_name (new_var, init_stmt);
+  gimple_assign_set_lhs (init_stmt, new_temp);
+  vect_init_vector_1 (stmt, init_stmt, gsi);
+  vec_oprnd = gimple_assign_lhs (init_stmt);
+  return vec_oprnd;
+}
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 095af93..5c2219e 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -861,6 +861,8 @@  extern bool vect_supportable_shift (enum tree_code, tree);
 extern void vect_get_vec_defs (tree, tree, gimple, VEC (tree, heap) **,
 			       VEC (tree, heap) **, slp_tree, int);
 extern tree vect_gen_perm_mask (tree, unsigned char *);
+extern tree elem_fn_linear_init_vector (gimple, tree, tree, tree, 
+					gimple_stmt_iterator *);
 
 /* In tree-vect-data-refs.c.  */
 extern bool vect_can_force_dr_alignment_p (const_tree, unsigned int);
diff --git a/gcc/tree.c b/gcc/tree.c
index 3311635..7c7e6c6 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -11624,6 +11624,51 @@  build_call_list (tree return_type, tree fn, tree arglist)
 }
 
 
+/* Build a vector of type VECTYPE where all the elements are SCs.  */
+tree
+build_elem_fn_linear_vector_from_val (tree vectype, tree sc, tree step_size) 
+{
+  int i, nunits = TYPE_VECTOR_SUBPARTS (vectype);
+
+  if (sc == error_mark_node)
+    return sc;
+
+  /* Verify that the vector type is suitable for SC.  Note that there
+     is some inconsistency in the type-system with respect to restrict
+     qualifications of pointers.  Vector types always have a main-variant
+     element type and the qualification is applied to the vector-type.
+     So TREE_TYPE (vector-type) does not return a properly qualified
+     vector element-type.  */
+  gcc_checking_assert (types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE (sc)),
+					   TREE_TYPE (vectype)));
+
+  if (CONSTANT_CLASS_P (sc))
+    {
+      tree *v = XALLOCAVEC (tree, nunits);
+      for (i = 0; i < nunits; ++i)
+	// v[i] = sc;
+	v[i] = build2 (PLUS_EXPR, TREE_TYPE (sc), sc,
+		       fold_build2 (MULT_EXPR, TREE_TYPE (step_size), step_size,
+			            build_int_cst (integer_type_node, i)));
+      return build_vector (vectype, v);
+    }
+  else
+    {
+      VEC(constructor_elt, gc) *v = VEC_alloc (constructor_elt, gc, nunits);
+      for (i = 0; i < nunits; ++i)
+	{
+	  // CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, sc);
+	  tree tmp = NULL_TREE;
+	  tmp = build2 (PLUS_EXPR, TREE_TYPE (sc), sc,
+			fold_build2 (MULT_EXPR, TREE_TYPE (step_size), 
+				     step_size, 
+				     build_int_cst (integer_type_node, i)));
+	  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, tmp);
+	}
+      return build_constructor (vectype, v);
+    }
+}
+
 
 
 
diff --git a/gcc/tree.h b/gcc/tree.h
index cef639d..2c56e93 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -4530,7 +4530,7 @@  extern tree build_call_valist (tree, tree, int, va_list);
    build_call_array_loc (UNKNOWN_LOCATION, T1, T2, N, T3)
 extern tree build_call_array_loc (location_t, tree, tree, int, const tree *);
 extern tree build_call_vec (tree, tree, VEC(tree,gc) *);
-
+extern tree build_elem_fn_linear_vector_from_val (tree, tree, tree);
 /* Construct various nodes representing data types.  */
 
 extern tree make_signed_type (int);