tm.texi (TARGET_VECTORIZE_BUILTIN_CONVERSION): New target hook.

* doc/tm.texi (TARGET_VECTORIZE_BUILTIN_CONVERSION): New target hook.
        * targhooks.c (default_builtin_vectorized_conversion): New.
        * targhooks.h (default_builtin_vectorized_function): New declaration.
        * target.h (struct vectorize): Add builtin_conversion field.
        * tree-vectorizer.h (type_conversion_vec_info_type): New enum
        stmt_vec_info_type value.
        (vectorizable_conversion): New declaration.
        * tree-vect-analyze.c (vect_analyze_operations): Add
        vectorizable_conversion call.
        * target-def.h (TARGET_VECTORIZE_BUILTIN_CONVERSION): New.
        * tree-vect-transform.c (vectorizable_conversion): New function.
        (vect_transform_stmt): Add case for type_conversion_vec_info_type.
        * tree-vect-generic.c (expand_vector_operations_1): Consider correct
        mode.
        * config/rs6000/rs6000.c (rs6000_builtin_conversion): New.
        (TARGET_VECTORIZE_BUILTIN_CONVERSION): Defined.
        (rs6000_expand_builtin): Add handling a case of ALTIVEC_BUILTIN_VCFUX or
        ALTIVEC_BUILTIN_VCFSX.


Co-Authored-By: Dorit Nuzman <dorit@il.ibm.com>
Co-Authored-By: Ira Rosen <irar@il.ibm.com>

From-SVN: r121818
This commit is contained in:
Tehila Meyzels 2007-02-11 11:46:07 +00:00 committed by Dorit Nuzman
parent 1c85c51a47
commit f57d17f1fc
15 changed files with 288 additions and 9 deletions

View File

@ -1,3 +1,26 @@
2007-02-11 Tehila Meyzels <tehila@il.ibm.com>
Ira Rosen <irar@il.ibm.com>
Dorit Nuzman <dorit@il.ibm.com>
* doc/tm.texi (TARGET_VECTORIZE_BUILTIN_CONVERSION): New target hook.
* targhooks.c (default_builtin_vectorized_conversion): New.
* targhooks.h (default_builtin_vectorized_function): New declaration.
* target.h (struct vectorize): Add builtin_conversion field.
* tree-vectorizer.h (type_conversion_vec_info_type): New enum
stmt_vec_info_type value.
(vectorizable_conversion): New declaration.
* tree-vect-analyze.c (vect_analyze_operations): Add
vectorizable_conversion call.
* target-def.h (TARGET_VECTORIZE_BUILTIN_CONVERSION): New.
* tree-vect-transform.c (vectorizable_conversion): New function.
(vect_transform_stmt): Add case for type_conversion_vec_info_type.
* tree-vect-generic.c (expand_vector_operations_1): Consider correct
mode.
* config/rs6000/rs6000.c (rs6000_builtin_conversion): New.
(TARGET_VECTORIZE_BUILTIN_CONVERSION): Defined.
(rs6000_expand_builtin): Add handling a case of ALTIVEC_BUILTIN_VCFUX or
ALTIVEC_BUILTIN_VCFSX.
2007-02-10 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
PR target/30634

View File

@ -716,6 +716,7 @@ static int rs6000_use_sched_lookahead_guard (rtx);
static tree rs6000_builtin_mask_for_load (void);
static tree rs6000_builtin_mul_widen_even (tree);
static tree rs6000_builtin_mul_widen_odd (tree);
static tree rs6000_builtin_conversion (enum tree_code, tree);
static void def_builtin (int, const char *, tree, int);
static void rs6000_init_builtins (void);
@ -981,6 +982,8 @@ static const char alt_reg_names[][8] =
#define TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_EVEN rs6000_builtin_mul_widen_even
#undef TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_ODD
#define TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_ODD rs6000_builtin_mul_widen_odd
#undef TARGET_VECTORIZE_BUILTIN_CONVERSION
#define TARGET_VECTORIZE_BUILTIN_CONVERSION rs6000_builtin_conversion
#undef TARGET_INIT_BUILTINS
#define TARGET_INIT_BUILTINS rs6000_init_builtins
@ -1677,6 +1680,30 @@ rs6000_builtin_mask_for_load (void)
return 0;
}
/* Implement targetm.vectorize.builtin_conversion. */
static tree
rs6000_builtin_conversion (enum tree_code code, tree type)
{
if (!TARGET_ALTIVEC)
return NULL_TREE;
switch (code)
{
case FLOAT_EXPR:
switch (TYPE_MODE (type))
{
case V4SImode:
return TYPE_UNSIGNED (type) ?
rs6000_builtin_decls[ALTIVEC_BUILTIN_VCFUX] :
rs6000_builtin_decls[ALTIVEC_BUILTIN_VCFSX];
default:
return NULL_TREE;
}
default:
return NULL_TREE;
}
}
/* Implement targetm.vectorize.builtin_mul_widen_even. */
static tree
rs6000_builtin_mul_widen_even (tree type)
@ -8151,6 +8178,21 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
return target;
}
if (fcode == ALTIVEC_BUILTIN_VCFUX
|| fcode == ALTIVEC_BUILTIN_VCFSX)
{
if (!TREE_CHAIN (arglist))
{
tree t, arg0;
t = NULL_TREE;
t = tree_cons (NULL_TREE, integer_zero_node, t);
arg0 = TREE_VALUE (arglist);
t = tree_cons (NULL_TREE, arg0, t);
arglist = t;
TREE_OPERAND (exp, 1) = t;
}
}
if (TARGET_ALTIVEC)
{

View File

@ -5384,6 +5384,21 @@ 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_CONVERSION (enum tree_code @var{code}, tree @var{type})
This hook should return the DECL of a function that implements conversion of the
input vector of type @var{type}.
If @var{type} is an integral type, the result of the conversion is a vector of
floating-point type of the same size.
If @var{type} is a floating-point type, the result of the conversion is a vector
of integral type of the same size.
@var{code} specifies how the conversion is to be applied
(truncation, rounding, etc.).
If this hook is defined, the autovectorizer will use the
@code{TARGET_VECTORIZE_BUILTIN_CONVERSION} target hook when vectorizing
conversion. Otherwise, it will return @code{NULL_TREE}.
@end deftypefn
@deftypefn {Target Hook} tree TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION (enum built_in_function @var{code}, tree @var{vec_type_out}, tree @var{vec_type_in})
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

View File

@ -345,6 +345,7 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#define TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD 0
#define TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION default_builtin_vectorized_function
#define TARGET_VECTORIZE_BUILTIN_CONVERSION default_builtin_vectorized_conversion
#define TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_EVEN 0
#define TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_ODD 0
@ -352,6 +353,7 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
{ \
TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD, \
TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION, \
TARGET_VECTORIZE_BUILTIN_CONVERSION, \
TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_EVEN, \
TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_ODD \
}

View File

@ -397,6 +397,10 @@ struct gcc_target
function, or NULL_TREE if not available. */
tree (* builtin_vectorized_function) (unsigned, tree, tree);
/* Returns a code for builtin that realizes vectorized version of
conversion, or NULL_TREE if not available. */
tree (* builtin_conversion) (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

@ -329,6 +329,15 @@ default_builtin_vectorized_function (enum built_in_function fn ATTRIBUTE_UNUSED,
return NULL_TREE;
}
/* Vectorized conversion. */
tree
default_builtin_vectorized_conversion (enum tree_code code 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

@ -59,6 +59,8 @@ extern bool default_narrow_bitfield (void);
extern tree default_builtin_vectorized_function (enum built_in_function, tree, tree);
extern tree default_builtin_vectorized_conversion (enum tree_code, 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

@ -1,3 +1,13 @@
2007-02-11 Tehila Meyzels <tehila@il.ibm.com>
Dorit Nuzman <dorit@il.ibm.com>
* gcc.dg/vect/vect-intfloat-conversion.c-1: New test.
* gcc.dg/vect/vect-intfloat-conversion.c-2: New test.
* gcc.dg/vect/vect-93.c: Another loop gets vectorized on powerpc.
* gcc.dg/vect/vect-113.c: Likewise.
* gcc.dg/vect/vect-iv-11.c: A loop gets vectorized.
2007-02-10 Richard Henderson <rth@redhat.com>
* lib/target-supports.exp (check_effective_target_tls): Redefine

View File

@ -11,7 +11,7 @@ main1 (void)
int i;
float a[N];
/* Induction. */
/* Induction and type conversion. */
for ( i = 0; i < N; i++)
{
a[i] = i;
@ -32,5 +32,5 @@ int main (void)
return main1 ();
}
/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target powerpc*-*-* } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */

View File

@ -65,12 +65,21 @@ int main (void)
return 0;
}
/* in main1 */
/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" } } */
/* 2 loops vectorized in main1, 2 loops vectorized in main:
the first loop in main requires vectorization of conversions,
the second loop in main requires vectorization of misaliged load: */
/* main && main1 together: */
/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 2 "vect" { target powerpc*-*-* } } } */
/* { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 2 "vect" { target vect_no_align } } } */
/* { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 3 "vect" { xfail vect_no_align } } } */
/* in main */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail vect_no_align } } } */
/* in main1: */
/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { target {! powerpc*-*-* } } } } */
/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { target vect_no_align } } } */
/* in main: */
/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { target vect_no_align } } } */
/* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 1 "vect" { xfail vect_no_align } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */

View File

@ -28,5 +28,5 @@ int main (void)
return 0;
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
/* { dg-final { cleanup-tree-dump "vect" } } */

View File

@ -315,6 +315,7 @@ vect_analyze_operations (loop_vec_info loop_vinfo)
ok = (vectorizable_type_promotion (stmt, NULL, NULL)
|| vectorizable_type_demotion (stmt, NULL, NULL)
|| vectorizable_conversion (stmt, NULL, NULL)
|| vectorizable_operation (stmt, NULL, NULL)
|| vectorizable_assignment (stmt, NULL, NULL)
|| vectorizable_load (stmt, NULL, NULL)

View File

@ -405,7 +405,10 @@ expand_vector_operations_1 (block_stmt_iterator *bsi)
&& TREE_CODE_CLASS (code) != tcc_binary)
return;
if (code == NOP_EXPR || code == VIEW_CONVERT_EXPR)
if (code == NOP_EXPR
|| code == FLOAT_EXPR
|| code == FIX_TRUNC_EXPR
|| code == VIEW_CONVERT_EXPR)
return;
gcc_assert (code != CONVERT_EXPR);

View File

@ -1951,6 +1951,157 @@ vectorizable_call (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
}
/* Function vectorizable_conversion.
Check if STMT performs a conversion operation, 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_conversion (tree stmt, block_stmt_iterator * bsi,
tree * vec_stmt)
{
tree vec_dest;
tree scalar_dest;
tree operation;
tree op0;
tree vec_oprnd0 = NULL_TREE;
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
enum tree_code code;
tree new_temp;
tree def, def_stmt;
enum vect_def_type dt0;
tree new_stmt;
int nunits_in;
int nunits_out;
int ncopies, j;
tree vectype_out, vectype_in;
tree rhs_type, lhs_type;
tree builtin_decl, params;
stmt_vec_info prev_stmt_info;
/* Is STMT a vectorizable conversion? */
if (!STMT_VINFO_RELEVANT_P (stmt_info))
return false;
gcc_assert (STMT_VINFO_DEF_TYPE (stmt_info) == vect_loop_def);
if (STMT_VINFO_LIVE_P (stmt_info))
{
/* FORNOW: not yet supported. */
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "value used after loop.");
return false;
}
if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
return false;
if (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) != SSA_NAME)
return false;
operation = GIMPLE_STMT_OPERAND (stmt, 1);
code = TREE_CODE (operation);
if (code != FIX_TRUNC_EXPR && code != FLOAT_EXPR)
return false;
/* Check types of lhs and rhs */
op0 = TREE_OPERAND (operation, 0);
rhs_type = TREE_TYPE (op0);
vectype_in = get_vectype_for_scalar_type (rhs_type);
nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
scalar_dest = GIMPLE_STMT_OPERAND (stmt, 0);
lhs_type = TREE_TYPE (scalar_dest);
vectype_out = get_vectype_for_scalar_type (lhs_type);
gcc_assert (STMT_VINFO_VECTYPE (stmt_info) == vectype_out);
nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
/* FORNOW: need to extend to support short<->float conversions as well. */
if (nunits_out != nunits_in)
return false;
/* Bail out if the types are both integral or non-integral */
if ((INTEGRAL_TYPE_P (rhs_type) && INTEGRAL_TYPE_P (lhs_type))
|| (!INTEGRAL_TYPE_P (rhs_type) && !INTEGRAL_TYPE_P (lhs_type)))
return false;
/* Sanity check: make sure that at least one copy of the vectorized stmt
needs to be generated. */
ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_in;
gcc_assert (ncopies >= 1);
if (!vect_is_simple_use (op0, loop_vinfo, &def_stmt, &def, &dt0))
{
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "use not simple.");
return false;
}
/* Supportable by target? */
if (!targetm.vectorize.builtin_conversion (code, vectype_in))
{
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "op not supported by target.");
return false;
}
if (!vec_stmt) /* transformation not required. */
{
STMT_VINFO_TYPE (stmt_info) = type_conversion_vec_info_type;
return true;
}
/** Transform. **/
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "transform conversion.");
/* Handle def. */
vec_dest = vect_create_destination_var (scalar_dest, vectype_out);
prev_stmt_info = NULL;
for (j = 0; j < ncopies; j++)
{
tree sym;
ssa_op_iter iter;
if (j == 0)
vec_oprnd0 = vect_get_vec_def_for_operand (op0, stmt, NULL);
else
vec_oprnd0 = vect_get_vec_def_for_stmt_copy (dt0, vec_oprnd0);
params = build_tree_list (NULL_TREE, vec_oprnd0);
builtin_decl =
targetm.vectorize.builtin_conversion (code, vectype_in);
new_stmt = build_function_call_expr (builtin_decl, params);
/* Arguments are ready. create the new vector stmt. */
new_stmt = build2 (GIMPLE_MODIFY_STMT, void_type_node, vec_dest,
new_stmt);
new_temp = make_ssa_name (vec_dest, new_stmt);
GIMPLE_STMT_OPERAND (new_stmt, 0) = new_temp;
vect_finish_stmt_generation (stmt, new_stmt, bsi);
FOR_EACH_SSA_TREE_OPERAND (sym, new_stmt, iter, SSA_OP_ALL_VIRTUALS)
{
if (TREE_CODE (sym) == SSA_NAME)
sym = SSA_NAME_VAR (sym);
mark_sym_for_renaming (sym);
}
if (j == 0)
STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
else
STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
prev_stmt_info = vinfo_for_stmt (new_stmt);
}
return true;
}
/* Function vectorizable_assignment.
Check if STMT performs an assignment (copy) that can be vectorized.
@ -4098,6 +4249,11 @@ vect_transform_stmt (tree stmt, block_stmt_iterator *bsi, bool *strided_store)
gcc_assert (done);
break;
case type_conversion_vec_info_type:
done = vectorizable_conversion (stmt, bsi, &vec_stmt);
gcc_assert (done);
break;
case op_vec_info_type:
done = vectorizable_operation (stmt, bsi, &vec_stmt);
gcc_assert (done);

View File

@ -168,7 +168,8 @@ enum stmt_vec_info_type {
condition_vec_info_type,
reduc_vec_info_type,
type_promotion_vec_info_type,
type_demotion_vec_info_type
type_demotion_vec_info_type,
type_conversion_vec_info_type
};
/* Indicates whether/how a variable is used in the loop. */
@ -411,6 +412,8 @@ extern bool vectorizable_store (tree, block_stmt_iterator *, tree *);
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_conversion (tree, block_stmt_iterator *,
tree *);
extern bool vectorizable_assignment (tree, block_stmt_iterator *, tree *);
extern tree vectorizable_function (tree, tree, tree);
extern bool vectorizable_call (tree, block_stmt_iterator *, tree *);