summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog19
-rw-r--r--gcc/doc/tm.texi7
-rw-r--r--gcc/target-def.h10
-rw-r--r--gcc/target.h4
-rw-r--r--gcc/targhooks.c9
-rw-r--r--gcc/targhooks.h2
-rw-r--r--gcc/tree-vect-analyze.c1
-rw-r--r--gcc/tree-vect-transform.c150
-rw-r--r--gcc/tree-vectorizer.h2
9 files changed, 201 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 65451c705ed..4d4a97d1428 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 768c7c7540d..70e30ae3ac3 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -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
diff --git a/gcc/target-def.h b/gcc/target-def.h
index 1e158c164f3..580c3276900 100644
--- a/gcc/target-def.h
+++ b/gcc/target-def.h
@@ -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
diff --git a/gcc/target.h b/gcc/target.h
index 82eaccdd551..1147142f2cf 100644
--- a/gcc/target.h
+++ b/gcc/target.h
@@ -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
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index a12d6b557ba..e7bdf0b3cbc 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -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,
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index f6d50ddf6e2..5f63dd77f6f 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -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. */
diff --git a/gcc/tree-vect-analyze.c b/gcc/tree-vect-analyze.c
index 4ea7b15dde5..a0d6e087082 100644
--- a/gcc/tree-vect-analyze.c
+++ b/gcc/tree-vect-analyze.c
@@ -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));
diff --git a/gcc/tree-vect-transform.c b/gcc/tree-vect-transform.c
index b2771bbf77c..84ae19facfd 100644
--- a/gcc/tree-vect-transform.c
+++ b/gcc/tree-vect-transform.c
@@ -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.");
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index d60a494d004..6af68a319f8 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -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 *);
OpenPOWER on IntegriCloud