target.h (struct gcc_target): Add builtin_vectorized_function target hook.

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.

Co-Authored-By: Zdenek Dvorak <dvorakz@suse.cz>

From-SVN: r119249
This commit is contained in:
Richard Guenther 2006-11-27 12:41:51 +00:00 committed by Richard Biener
parent 9fca6f972d
commit 2505a3f233
9 changed files with 201 additions and 3 deletions

View File

@ -1,3 +1,22 @@
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

View 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

View 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

View 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

View 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,

View 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. */

View 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));

View 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.");

View 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 *);