Sorry, I forgot to include Changelog entries. I am attaching the updated patch.

Thanks,

Balaji V. Iyer.

________________________________________
From: Iyer, Balaji V
Sent: Wednesday, April 25, 2012 3:08 PM
To: gcc-patches@gcc.gnu.org
Subject: [PATCH][Cilkplus] Elemental function insertion

Hello Everyone,
    This patch is for the Cilkplus branch affecting both C and C++ compilers. 
This patch will insert elemental functions when the loop is vectorized.

Thanking You,

Yours Sincerely,

Balaji V. Iyer.
diff --git a/gcc/ChangeLog.cilk b/gcc/ChangeLog.cilk
index 523b7ac..d6b28e2 100644
--- a/gcc/ChangeLog.cilk
+++ b/gcc/ChangeLog.cilk
@@ -1,3 +1,19 @@
+2012-04-24  Balaji V. Iyer  <balaji.v.i...@intel.com>
+
+       * elem-function.c (find_elem_fn_param_type_1): New function.
+       (find_elem_fn_param_type): Likewise.
+       (find_elem_fn_name): Likewise.
+       (is_elem_fn): Make it unstatic.
+       * tree-data-ref.c (find_data_references_in_stmt): Added support for
+       functions that can be made to elemental functions.
+       * tree-vect-stmts.c (vect_get_vec_def_for_operand): Added a check for
+       the parameters to see whether it is uniform, linear or neither.
+       (vectorizable_function): Handled code to substitute regular function
+       with the equivalent elemental function.
+       (vectorizable_call): Set the function type for substituted elemental
+       function.
+       * tree.h (enum elem_fn_parm_type): New enum.
+
 2012-04-20  Balaji V. Iyer  <balaji.v.i...@intel.com>
 
        * final.c (rest_of_handle_final): Moved outputing ZCA data after
diff --git a/gcc/cilk.h b/gcc/cilk.h
index 27d5dd0..27ccd16 100644
--- a/gcc/cilk.h
+++ b/gcc/cilk.h
@@ -269,5 +269,7 @@ extern void cilk_remove_annotated_functions (rtx first);
 extern bool cilk_annotated_function_p (char *);            
 extern void debug_zca_data (void);
 extern zca_data *get_zca_entry (int);
-extern void insert_in_zca_table (zca_data);                                
+extern void insert_in_zca_table (zca_data);
+extern bool is_elem_fn (tree);                          
+extern tree find_elem_fn_name (tree, tree, tree);
 #endif /* GCC_CILK_H */
diff --git a/gcc/elem-function.c b/gcc/elem-function.c
index 4cc9035..42f6248 100644
--- a/gcc/elem-function.c
+++ b/gcc/elem-function.c
@@ -83,6 +83,58 @@ static elem_fn_info *extract_elem_fn_values (tree);
 static tree create_optimize_attribute (int);
 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)
+{
+  int ii = 0;
+  elem_fn_info *elem_fn_values;
+
+  elem_fn_values = extract_elem_fn_values (fndecl);
+  if (!elem_fn_values)
+    return TYPE_NONE;
+
+  for (ii = 0; ii < elem_fn_values->no_lvars; ii++)
+    if (elem_fn_values->linear_location[ii] == parm_no)
+      return TYPE_LINEAR;
+    
+  for (ii = 0; ii < elem_fn_values->no_uvars; ii++)
+    if (elem_fn_values->uniform_location[ii] == parm_no)
+      return TYPE_UNIFORM;
+    
+  return TYPE_NONE;
+}
+  
+  
+/* 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)
+{
+  tree fndecl, parm = NULL_TREE;
+  int ii, nargs;
+  enum elem_fn_parm_type return_type = TYPE_NONE;
+  
+  if (gimple_code (stmt) != GIMPLE_CALL)
+    return TYPE_NONE;
+
+  fndecl = gimple_call_fndecl (stmt);
+  gcc_assert (fndecl);
+
+  nargs = gimple_call_num_args (stmt);
+
+  for (ii = 0; ii < nargs; ii++)
+    {
+      parm = gimple_call_arg (stmt, ii);
+      if (op == parm)
+       {
+         return_type = find_elem_fn_parm_type_1 (fndecl, 1);
+         return return_type;
+       }
+    }
+  return return_type;
+}
+  
 /* this function will concatinate the suffix to the existing function decl */
 static tree
 rename_elem_fn (tree decl, const char *suffix)
@@ -108,7 +160,7 @@ rename_elem_fn (tree decl, const char *suffix)
 
 /* this function will check to see if the node is part of an function that
  * needs to be converted to its vector equivalent. */
-static bool
+bool
 is_elem_fn (tree fndecl)
 {
   tree ii_tree;
@@ -349,6 +401,55 @@ find_suffix (elem_fn_info *elem_fn_values, bool masked)
   return suffix;
 }
 
+tree
+find_elem_fn_name (tree old_fndecl,
+                  tree vectype_out ATTRIBUTE_UNUSED,
+                  tree vectype_in ATTRIBUTE_UNUSED)
+{
+  elem_fn_info *elem_fn_values = NULL;
+  tree new_fndecl = NULL_TREE, arg_type = NULL_TREE;
+  char *suffix = NULL;
+  
+  elem_fn_values = extract_elem_fn_values (old_fndecl);
+ 
+  if (elem_fn_values)
+    {
+      if (elem_fn_values->no_vlengths > 0)
+       {
+         if (elem_fn_values->vectorlength[0] ==
+             (int)TYPE_VECTOR_SUBPARTS (vectype_out))
+           suffix = find_suffix (elem_fn_values, false);
+         else
+           return NULL_TREE;
+       }
+      else
+       return NULL_TREE;
+    }
+  else
+    return NULL_TREE;
+
+  new_fndecl = copy_node (rename_elem_fn (old_fndecl, suffix));
+  TREE_TYPE (new_fndecl) = copy_node (TREE_TYPE (old_fndecl));
+
+  TYPE_ARG_TYPES (TREE_TYPE (new_fndecl)) =
+    copy_list (TYPE_ARG_TYPES (TREE_TYPE (new_fndecl)));
+  
+  for (arg_type = TYPE_ARG_TYPES (TREE_TYPE (new_fndecl));
+       arg_type && arg_type != void_type_node;
+       arg_type = TREE_CHAIN (arg_type))
+    TREE_VALUE (arg_type) = vectype_out;
+  
+  if (TREE_TYPE (TREE_TYPE (new_fndecl)) != void_type_node)
+    {
+      TREE_TYPE (TREE_TYPE (new_fndecl)) =
+       copy_node (TREE_TYPE (TREE_TYPE (new_fndecl)));
+      TREE_TYPE (TREE_TYPE (new_fndecl)) = vectype_out;
+      DECL_MODE (new_fndecl) = TYPE_MODE (vectype_out);
+    }
+  
+  return new_fndecl;
+}
+
 /* this function wil create the elemental vector function node */
 static struct cgraph_node *
 create_elem_fn_nodes (struct cgraph_node *node)
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
index 1381b53..bea2773 100644
--- a/gcc/tree-data-ref.c
+++ b/gcc/tree-data-ref.c
@@ -86,6 +86,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "langhooks.h"
 #include "tree-affine.h"
 #include "params.h"
+#include "cilk.h"
 
 static struct datadep_stats
 {
@@ -4383,8 +4384,18 @@ find_data_references_in_stmt (struct loop *nest, gimple 
stmt,
 
   if (get_references_in_stmt (stmt, &references))
     {
-      VEC_free (data_ref_loc, heap, references);
-      return false;
+      /* If we have an elemental function, then dont worry about its refernce
+       * it is probably available somewhere */
+      if (flag_enable_cilk
+         && gimple_code (stmt) == GIMPLE_CALL
+         && gimple_call_fndecl (stmt)
+         && is_elem_fn (gimple_call_fndecl (stmt)))
+       ;
+      else
+       {
+         VEC_free (data_ref_loc, heap, references);
+         return false;
+       }
     }
 
   FOR_EACH_VEC_ELT (data_ref_loc, references, i, ref)
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 968e4ed..6eb5f56 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -40,7 +40,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "diagnostic-core.h"
 #include "tree-vectorizer.h"
 #include "langhooks.h"
-
+#include "cilk.h"
 
 /* Return a variable of type ELEM_TYPE[NELEMS].  */
 
@@ -1260,6 +1260,8 @@ vect_get_vec_def_for_operand (tree op, gimple stmt, tree 
*scalar_def)
   bool is_simple_use;
   tree vector_type;
 
+  extern enum elem_fn_parm_type find_elem_fn_parm_type (gimple, tree);
+
   if (vect_print_dump_info (REPORT_DETAILS))
     {
       fprintf (vect_dump, "vect_get_vec_def_for_operand: ");
@@ -1283,13 +1285,26 @@ vect_get_vec_def_for_operand (tree op, gimple stmt, 
tree *scalar_def)
         }
     }
 
+  if (flag_enable_cilk
+      && 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)
+       dt = vect_constant_def;
+      else if (parm_type == TYPE_LINEAR)
+       {
+         ;
+       }
+    }
+      
   switch (dt)
     {
     /* Case 1: operand is a constant.  */
     case vect_constant_def:
       {
        vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
-       gcc_assert (vector_type);
+       gcc_assert (vector_type);  
        nunits = TYPE_VECTOR_SUBPARTS (vector_type);
 
        if (scalar_def)
@@ -1566,6 +1581,20 @@ vectorizable_function (gimple call, tree vectype_out, 
tree vectype_in)
 {
   tree fndecl = gimple_call_fndecl (call);
 
+  if (flag_enable_cilk && is_elem_fn (fndecl))
+    {
+      if (DECL_ELEM_FN_ALREADY_CLONED (fndecl))
+       return fndecl;
+      else
+       {
+         tree new_fndecl = find_elem_fn_name (copy_node (fndecl),
+                                              vectype_out, vectype_in);
+         if (new_fndecl)
+           DECL_ELEM_FN_ALREADY_CLONED (new_fndecl) = 1;
+         /* gimple_call_set_fntype (call, TREE_TYPE (new_fndecl)); */
+         return new_fndecl;
+       }
+    }
   /* We only handle functions that do not read or clobber memory -- i.e.
      const or novops ones.  */
   if (!(gimple_call_flags (call) & (ECF_CONST | ECF_NOVOPS)))
@@ -1718,8 +1747,6 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator 
*gsi, gimple *vec_stmt,
       return false;
     }
 
-  gcc_assert (!gimple_vuse (stmt));
-
   if (slp_node || PURE_SLP_STMT (stmt_info))
     ncopies = 1;
   else if (modifier == NARROW)
@@ -1824,7 +1851,8 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator 
*gsi, gimple *vec_stmt,
          new_stmt = gimple_build_call_vec (fndecl, vargs);
          new_temp = make_ssa_name (vec_dest, new_stmt);
          gimple_call_set_lhs (new_stmt, new_temp);
-
+         if (flag_enable_cilk && is_elem_fn (fndecl))
+           gimple_call_set_fntype (new_stmt, TREE_TYPE (fndecl));
          vect_finish_stmt_generation (stmt, new_stmt, gsi);
          mark_symbols_for_renaming (new_stmt);
 
diff --git a/gcc/tree.h b/gcc/tree.h
index 79a27bf..06fb8d3 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -3671,6 +3671,9 @@ extern VEC(tree, gc) **decl_debug_args_insert (tree);
 #define DECL_FUNCTION_SPECIFIC_OPTIMIZATION(NODE) \
    (FUNCTION_DECL_CHECK (NODE)->function_decl.function_specific_optimization)
 
+#define DECL_ELEM_FN_ALREADY_CLONED(NODE) \
+  (FUNCTION_DECL_CHECK (NODE)->function_decl.elem_fn_already_cloned)
+                    
 /* FUNCTION_DECL inherits from DECL_NON_COMMON because of the use of the
    arguments/result/saved_tree fields by front ends.   It was either inherit
    FUNCTION_DECL from non_common, or inherit non_common from FUNCTION_DECL,
@@ -3718,6 +3721,7 @@ struct GTY(()) tree_function_decl {
   unsigned cilk_has_spawn : 1;
   signed int kills_registers : DECL_KILLS_REGISTERS_BITS;
   unsigned tm_clone_flag : 1;
+  unsigned elem_fn_already_cloned : 1;
 
   /* 1 bit left */
 };
@@ -3801,6 +3805,12 @@ enum function_linkage
   linkage_cilk
 };
 
+enum elem_fn_parm_type
+{
+  TYPE_NONE = 0,
+  TYPE_UNIFORM = 1,
+  TYPE_LINEAR = 2
+};
 
 #define TREE_OPTIMIZATION(NODE) \
   (&OPTIMIZATION_NODE_CHECK (NODE)->optimization.opts)

Reply via email to