2006-11-27 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 27 Nov 2006 12:41:51 +0000 (12:41 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 27 Nov 2006 12:41:51 +0000 (12:41 +0000)
Zdenek Dvorak <dvorakz@suse.cz>

* target.h (struct gcc_target): Add builtin_vectorized_function
target hook.
* target-def.h (TARGET_VECTORIZE): Likewise.
* doc/tm.texi (TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION):
Document new target hook.
* targhooks.h (default_builtin_vectorized_function): Declare.
* targhooks.c (default_builtin_vectorized_function): Define.
* tree-vectorizer.h (stmt_vec_info_type): Add call_vec_info_type.
(vectorizable_call): Declare.
* tree-vect-analyze.c (vect_analyze_operations): Call
vectorizable_call.
* tree-vect-transform.c (vectorizable_function): New static function.
(build_vectorized_function_call): Likewise.
(vectorizable_call): New function.
(vect_transform_stmt): Handle vectorizable calls.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@119249 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/doc/tm.texi
gcc/target-def.h
gcc/target.h
gcc/targhooks.c
gcc/targhooks.h
gcc/tree-vect-analyze.c
gcc/tree-vect-transform.c
gcc/tree-vectorizer.h

index 65451c7..4d4a97d 100644 (file)
@@ -1,4 +1,23 @@
 2006-11-27  Richard Guenther  <rguenther@suse.de>
+       Zdenek Dvorak <dvorakz@suse.cz>
+
+       * target.h (struct gcc_target): Add builtin_vectorized_function
+       target hook.
+       * target-def.h (TARGET_VECTORIZE): Likewise.
+       * doc/tm.texi (TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION):
+       Document new target hook.
+       * targhooks.h (default_builtin_vectorized_function): Declare.
+       * targhooks.c (default_builtin_vectorized_function): Define.
+       * tree-vectorizer.h (stmt_vec_info_type): Add call_vec_info_type.
+       (vectorizable_call): Declare.
+       * tree-vect-analyze.c (vect_analyze_operations): Call
+       vectorizable_call.
+       * tree-vect-transform.c (vectorizable_function): New static function.
+       (build_vectorized_function_call): Likewise.
+       (vectorizable_call): New function.
+       (vect_transform_stmt): Handle vectorizable calls.
+
+2006-11-27  Richard Guenther  <rguenther@suse.de>
 
        PR middle-end/25620
        * builtins.c (expand_builtin_pow): Optimize non integer valued
index 768c7c7..70e30ae 100644 (file)
@@ -5306,6 +5306,13 @@ preserved (e.g. used only by a reduction computation). Otherwise, the
 @code{widen_mult_hi/lo} idioms will be used.
 @end deftypefn
 
+@deftypefn {Target Hook} tree TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION (enum built_in_function @var{code}, tree @var{vec_type})
+This hook should return the decl of a function that implements the vectorized
+variant of the builtin function with builtin function code @var{code} or
+@code{NULL_TREE} if such a function is not available.  The return type of
+the vectorized function shall be of vector type @var{vec_type}.
+@end deftypefn
+
 @node Anchored Addresses
 @section Anchored Addresses
 @cindex anchored addresses
index 1e158c1..580c327 100644 (file)
@@ -332,13 +332,17 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
    TARGET_SCHED_SET_SCHED_FLAGS}
 
 #define TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD 0
+#define TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION default_builtin_vectorized_function
 #define TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_EVEN 0
 #define TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_ODD 0
 
 #define TARGET_VECTORIZE                                                \
-  {TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD,                             \
-   TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_EVEN,                             \
-   TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_ODD}
+  {                                                                    \
+    TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD,                            \
+    TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION,                      \
+    TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_EVEN,                            \
+    TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_ODD                             \
+  }
 
 #define TARGET_DEFAULT_TARGET_FLAGS 0
 
index 82eaccd..1147142 100644 (file)
@@ -370,6 +370,10 @@ struct gcc_target
        function.  */
     tree (* builtin_mask_for_load) (void);
 
+    /* Returns a code for builtin that realizes vectorized version of
+       function, or NULL_TREE if not available.  */
+    tree (* builtin_vectorized_function) (unsigned, tree);
+
     /* Target builtin that implements vector widening multiplication.
        builtin_mul_widen_eve computes the element-by-element products 
        for the even elements, and builtin_mul_widen_odd computes the
index a12d6b5..e7bdf0b 100644 (file)
@@ -319,6 +319,15 @@ default_invalid_within_doloop (rtx insn)
   return NULL;
 }
 
+/* Mapping of builtin functions to vectorized variants.  */
+
+tree
+default_builtin_vectorized_function (enum built_in_function fn ATTRIBUTE_UNUSED,
+                                    tree type ATTRIBUTE_UNUSED)
+{
+  return NULL_TREE;
+}
+
 bool
 hook_bool_CUMULATIVE_ARGS_mode_tree_bool_false (
        CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
index f6d50dd..5f63dd7 100644 (file)
@@ -57,6 +57,8 @@ extern const char * default_invalid_within_doloop (rtx);
 
 extern bool default_narrow_bitfield (void);
 
+extern tree default_builtin_vectorized_function (enum built_in_function, tree);
+
 /* These are here, and not in hooks.[ch], because not all users of
    hooks.h include tm.h, and thus we don't have CUMULATIVE_ARGS.  */
 
index 4ea7b15..a0d6e08 100644 (file)
@@ -301,6 +301,7 @@ vect_analyze_operations (loop_vec_info loop_vinfo)
                    || vectorizable_operation (stmt, NULL, NULL)
                    || vectorizable_assignment (stmt, NULL, NULL)
                    || vectorizable_load (stmt, NULL, NULL)
+                   || vectorizable_call (stmt, NULL, NULL)
                    || vectorizable_store (stmt, NULL, NULL)
                    || vectorizable_condition (stmt, NULL, NULL));
 
index b2771bb..84ae19f 100644 (file)
@@ -1566,6 +1566,152 @@ vectorizable_reduction (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
   return true;
 }
 
+/* Checks if CALL can be vectorized in type VECTYPE.  Returns
+   true if the target has a vectorized version of the function,
+   or false if the function cannot be vectorized.  */
+
+static bool
+vectorizable_function (tree call, tree vectype)
+{
+  tree fndecl = get_callee_fndecl (call);
+
+  /* We only handle functions that do not read or clobber memory -- i.e.
+     const or novops ones.  */
+  if (!(call_expr_flags (call) & (ECF_CONST | ECF_NOVOPS)))
+    return false;
+
+  if (!fndecl
+      || TREE_CODE (fndecl) != FUNCTION_DECL
+      || !DECL_BUILT_IN (fndecl))
+    return false;
+
+  if (targetm.vectorize.builtin_vectorized_function (DECL_FUNCTION_CODE (fndecl), vectype))
+    return true;
+
+  return false;
+}
+
+/* Returns an expression that performs a call to vectorized version
+   of FNDECL in type VECTYPE, with the arguments given by ARGS.
+   If extra statements need to be generated, they are inserted
+   before BSI.  */
+
+static tree
+build_vectorized_function_call (tree fndecl,
+                               tree vectype, tree args)
+{
+  tree vfndecl;
+  enum built_in_function code = DECL_FUNCTION_CODE (fndecl);
+
+  /* The target specific builtin should be available.  */
+  vfndecl = targetm.vectorize.builtin_vectorized_function (code, vectype);
+  gcc_assert (vfndecl != NULL_TREE);
+
+  return build_function_call_expr (vfndecl, args);
+}
+
+/* Function vectorizable_call.
+
+   Check if STMT performs a function call that can be vectorized. 
+   If VEC_STMT is also passed, vectorize the STMT: create a vectorized 
+   stmt to replace it, put it in VEC_STMT, and insert it at BSI.
+   Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
+
+bool
+vectorizable_call (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
+{
+  tree vec_dest;
+  tree scalar_dest;
+  tree operation;
+  tree op, args, type;
+  tree vec_oprnd, vargs, *pvargs_end;
+  stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+  tree vectype = STMT_VINFO_VECTYPE (stmt_info);
+  loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
+  tree fndecl, rhs, new_temp, def, def_stmt;
+  enum vect_def_type dt;
+
+  /* Is STMT a vectorizable call?   */
+  if (TREE_CODE (stmt) != MODIFY_EXPR)
+    return false;
+
+  if (TREE_CODE (TREE_OPERAND (stmt, 0)) != SSA_NAME)
+    return false;
+
+  operation = TREE_OPERAND (stmt, 1);
+  if (TREE_CODE (operation) != CALL_EXPR)
+    return false;
+   
+  /* For now, we only vectorize functions if a target specific builtin
+     is available.  TODO -- in some cases, it might be profitable to
+     insert the calls for pieces of the vector, in order to be able
+     to vectorize other operations in the loop.  */
+  if (!vectorizable_function (operation, vectype))
+    {
+      if (vect_print_dump_info (REPORT_DETAILS))
+       fprintf (vect_dump, "function is not vectorizable.");
+
+      return false;
+    }
+  gcc_assert (!stmt_references_memory_p (stmt));
+
+  for (args = TREE_OPERAND (operation, 1); args; args = TREE_CHAIN (args))
+    {
+      op = TREE_VALUE (args);
+
+      if (!vect_is_simple_use (op, loop_vinfo, &def_stmt, &def, &dt))
+       {
+         if (vect_print_dump_info (REPORT_DETAILS))
+           fprintf (vect_dump, "use not simple.");
+         return false;
+       }
+    }
+
+  if (!vec_stmt) /* transformation not required.  */
+    {
+      STMT_VINFO_TYPE (stmt_info) = call_vec_info_type;
+      return true;
+    }
+
+  /** Transform.  **/
+
+  if (vect_print_dump_info (REPORT_DETAILS))
+    fprintf (vect_dump, "transform operation.");
+
+  /* Handle def.  */
+  scalar_dest = TREE_OPERAND (stmt, 0);
+  vec_dest = vect_create_destination_var (scalar_dest, vectype);
+
+  /* Handle uses.  */
+  vargs = NULL_TREE;
+  pvargs_end = &vargs;
+  for (args = TREE_OPERAND (operation, 1); args; args = TREE_CHAIN (args))
+    {
+      op = TREE_VALUE (args);
+      vec_oprnd = vect_get_vec_def_for_operand (op, stmt, NULL);
+         
+      *pvargs_end = tree_cons (NULL_TREE, vec_oprnd, NULL_TREE);
+      pvargs_end = &TREE_CHAIN (*pvargs_end);
+    }
+
+  fndecl = get_callee_fndecl (operation);
+  rhs = build_vectorized_function_call (fndecl, vectype, vargs);
+  *vec_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, rhs);
+  new_temp = make_ssa_name (vec_dest, *vec_stmt);
+  TREE_OPERAND (*vec_stmt, 0) = new_temp;
+
+  vect_finish_stmt_generation (stmt, *vec_stmt, bsi);
+
+  /* The call in STMT might prevent it from being removed in dce.  We however
+     cannot remove it here, due to the way the ssa name it defines is mapped
+     to the new definition.  So just replace rhs of the statement with something
+     harmless.  */
+  type = TREE_TYPE (scalar_dest);
+  TREE_OPERAND (stmt, 1) = fold_convert (type, integer_zero_node);
+
+  return true;
+}
+
 
 /* Function vectorizable_assignment.
 
@@ -3721,6 +3867,10 @@ vect_transform_stmt (tree stmt, block_stmt_iterator *bsi, bool *strided_store)
        gcc_assert (done);
        break;
 
+      case call_vec_info_type:
+       done = vectorizable_call (stmt, bsi, &vec_stmt);
+       break;
+
       default:
        if (vect_print_dump_info (REPORT_DETAILS))
          fprintf (vect_dump, "stmt not supported.");
index d60a494..6af68a3 100644 (file)
@@ -163,6 +163,7 @@ enum stmt_vec_info_type {
   load_vec_info_type,
   store_vec_info_type,
   op_vec_info_type,
+  call_vec_info_type,
   assignment_vec_info_type,
   condition_vec_info_type,
   reduc_vec_info_type,
@@ -397,6 +398,7 @@ extern bool vectorizable_operation (tree, block_stmt_iterator *, tree *);
 extern bool vectorizable_type_promotion (tree, block_stmt_iterator *, tree *);
 extern bool vectorizable_type_demotion (tree, block_stmt_iterator *, tree *);
 extern bool vectorizable_assignment (tree, block_stmt_iterator *, tree *);
+extern bool vectorizable_call (tree, block_stmt_iterator *, tree *);
 extern bool vectorizable_condition (tree, block_stmt_iterator *, tree *);
 extern bool vectorizable_live_operation (tree, block_stmt_iterator *, tree *);
 extern bool vectorizable_reduction (tree, block_stmt_iterator *, tree *);