machmode.h (mode_for_vector): Declare.
2010-10-07 Richard Guenther <rguenther@suse.de> * machmode.h (mode_for_vector): Declare. * stor-layout.c (mode_for_vector): New function, split out from ... (layout_type): ... here. * tree-vectorizer.h (current_vector_size): Declare. * tree-vect-stmts.c (perm_mask_for_reverse): Check if the mask vector type is available. (get_vectype_for_scalar_type): Rename to ... (get_vectype_for_scalar_type_and_size): ... this. Get a vector size argument. (get_vectype_for_scalar_type): New wrapper around get_vectype_for_scalar_type_and_size using current_vector_size. (get_same_sized_vectype): Use get_vectype_for_scalar_type_and_size. * tree-vect-loop.c (vect_analyze_loop_2): Split out core part of vect_analyze_loop here. (vect_analyze_loop): Loop over vector sizes calling vect_analyze_loop_3. * tree-vect-slp.c (vect_slp_analyze_bb): Set current_vector_size to autodetect. * config/i386/i386.c (ix86_vectorize_builtin_conversion): Fix V8SF to V8SI conversion builtin. From-SVN: r165116
This commit is contained in:
parent
767f865fb8
commit
bb67d9c7ce
8 changed files with 182 additions and 94 deletions
|
@ -1,3 +1,25 @@
|
|||
2010-10-07 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
* machmode.h (mode_for_vector): Declare.
|
||||
* stor-layout.c (mode_for_vector): New function, split out from ...
|
||||
(layout_type): ... here.
|
||||
* tree-vectorizer.h (current_vector_size): Declare.
|
||||
* tree-vect-stmts.c (perm_mask_for_reverse): Check if the
|
||||
mask vector type is available.
|
||||
(get_vectype_for_scalar_type): Rename to ...
|
||||
(get_vectype_for_scalar_type_and_size): ... this. Get a vector
|
||||
size argument.
|
||||
(get_vectype_for_scalar_type): New wrapper around
|
||||
get_vectype_for_scalar_type_and_size using current_vector_size.
|
||||
(get_same_sized_vectype): Use get_vectype_for_scalar_type_and_size.
|
||||
* tree-vect-loop.c (vect_analyze_loop_2): Split out core part
|
||||
of vect_analyze_loop here.
|
||||
(vect_analyze_loop): Loop over vector sizes calling vect_analyze_loop_3.
|
||||
* tree-vect-slp.c (vect_slp_analyze_bb): Set current_vector_size
|
||||
to autodetect.
|
||||
* config/i386/i386.c (ix86_vectorize_builtin_conversion): Fix
|
||||
V8SF to V8SI conversion builtin.
|
||||
|
||||
2010-10-07 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
* target.def (autovectorize_vector_sizes): New target hook.
|
||||
|
|
|
@ -26272,7 +26272,7 @@ ix86_vectorize_builtin_conversion (unsigned int code,
|
|||
case V8SFmode:
|
||||
return (TYPE_UNSIGNED (src_type)
|
||||
? NULL_TREE
|
||||
: ix86_builtins[IX86_BUILTIN_CVTDQ2PS]);
|
||||
: ix86_builtins[IX86_BUILTIN_CVTDQ2PS256]);
|
||||
default:
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
|
|
@ -241,6 +241,11 @@ extern enum machine_mode smallest_mode_for_size (unsigned int,
|
|||
|
||||
extern enum machine_mode int_mode_for_mode (enum machine_mode);
|
||||
|
||||
/* Return a mode that is suitable for representing a vector,
|
||||
or BLKmode on failure. */
|
||||
|
||||
extern enum machine_mode mode_for_vector (enum machine_mode, unsigned);
|
||||
|
||||
/* Find the best mode to use to access a bit field. */
|
||||
|
||||
extern enum machine_mode get_best_mode (int, int, unsigned int,
|
||||
|
|
|
@ -470,6 +470,50 @@ int_mode_for_mode (enum machine_mode mode)
|
|||
return mode;
|
||||
}
|
||||
|
||||
/* Find a mode that is suitable for representing a vector with
|
||||
NUNITS elements of mode INNERMODE. Returns BLKmode if there
|
||||
is no suitable mode. */
|
||||
|
||||
enum machine_mode
|
||||
mode_for_vector (enum machine_mode innermode, unsigned nunits)
|
||||
{
|
||||
enum machine_mode mode;
|
||||
|
||||
/* First, look for a supported vector type. */
|
||||
if (SCALAR_FLOAT_MODE_P (innermode))
|
||||
mode = MIN_MODE_VECTOR_FLOAT;
|
||||
else if (SCALAR_FRACT_MODE_P (innermode))
|
||||
mode = MIN_MODE_VECTOR_FRACT;
|
||||
else if (SCALAR_UFRACT_MODE_P (innermode))
|
||||
mode = MIN_MODE_VECTOR_UFRACT;
|
||||
else if (SCALAR_ACCUM_MODE_P (innermode))
|
||||
mode = MIN_MODE_VECTOR_ACCUM;
|
||||
else if (SCALAR_UACCUM_MODE_P (innermode))
|
||||
mode = MIN_MODE_VECTOR_UACCUM;
|
||||
else
|
||||
mode = MIN_MODE_VECTOR_INT;
|
||||
|
||||
/* Do not check vector_mode_supported_p here. We'll do that
|
||||
later in vector_type_mode. */
|
||||
for (; mode != VOIDmode ; mode = GET_MODE_WIDER_MODE (mode))
|
||||
if (GET_MODE_NUNITS (mode) == nunits
|
||||
&& GET_MODE_INNER (mode) == innermode)
|
||||
break;
|
||||
|
||||
/* For integers, try mapping it to a same-sized scalar mode. */
|
||||
if (mode == VOIDmode
|
||||
&& GET_MODE_CLASS (innermode) == MODE_INT)
|
||||
mode = mode_for_size (nunits * GET_MODE_BITSIZE (innermode),
|
||||
MODE_INT, 0);
|
||||
|
||||
if (mode == VOIDmode
|
||||
|| (GET_MODE_CLASS (mode) == MODE_INT
|
||||
&& !have_regs_of_mode[mode]))
|
||||
return BLKmode;
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
/* Return the alignment of MODE. This will be bounded by 1 and
|
||||
BIGGEST_ALIGNMENT. */
|
||||
|
||||
|
@ -1848,44 +1892,8 @@ layout_type (tree type)
|
|||
|
||||
/* Find an appropriate mode for the vector type. */
|
||||
if (TYPE_MODE (type) == VOIDmode)
|
||||
{
|
||||
enum machine_mode innermode = TYPE_MODE (innertype);
|
||||
enum machine_mode mode;
|
||||
|
||||
/* First, look for a supported vector type. */
|
||||
if (SCALAR_FLOAT_MODE_P (innermode))
|
||||
mode = MIN_MODE_VECTOR_FLOAT;
|
||||
else if (SCALAR_FRACT_MODE_P (innermode))
|
||||
mode = MIN_MODE_VECTOR_FRACT;
|
||||
else if (SCALAR_UFRACT_MODE_P (innermode))
|
||||
mode = MIN_MODE_VECTOR_UFRACT;
|
||||
else if (SCALAR_ACCUM_MODE_P (innermode))
|
||||
mode = MIN_MODE_VECTOR_ACCUM;
|
||||
else if (SCALAR_UACCUM_MODE_P (innermode))
|
||||
mode = MIN_MODE_VECTOR_UACCUM;
|
||||
else
|
||||
mode = MIN_MODE_VECTOR_INT;
|
||||
|
||||
/* Do not check vector_mode_supported_p here. We'll do that
|
||||
later in vector_type_mode. */
|
||||
for (; mode != VOIDmode ; mode = GET_MODE_WIDER_MODE (mode))
|
||||
if (GET_MODE_NUNITS (mode) == nunits
|
||||
&& GET_MODE_INNER (mode) == innermode)
|
||||
break;
|
||||
|
||||
/* For integers, try mapping it to a same-sized scalar mode. */
|
||||
if (mode == VOIDmode
|
||||
&& GET_MODE_CLASS (innermode) == MODE_INT)
|
||||
mode = mode_for_size (nunits * GET_MODE_BITSIZE (innermode),
|
||||
MODE_INT, 0);
|
||||
|
||||
if (mode == VOIDmode ||
|
||||
(GET_MODE_CLASS (mode) == MODE_INT
|
||||
&& !have_regs_of_mode[mode]))
|
||||
SET_TYPE_MODE (type, BLKmode);
|
||||
else
|
||||
SET_TYPE_MODE (type, mode);
|
||||
}
|
||||
SET_TYPE_MODE (type,
|
||||
mode_for_vector (TYPE_MODE (innertype), nunits));
|
||||
|
||||
TYPE_SATURATING (type) = TYPE_SATURATING (TREE_TYPE (type));
|
||||
TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TREE_TYPE (type));
|
||||
|
|
|
@ -1371,41 +1371,18 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo)
|
|||
}
|
||||
|
||||
|
||||
/* Function vect_analyze_loop.
|
||||
/* Function vect_analyze_loop_2.
|
||||
|
||||
Apply a set of analyses on LOOP, and create a loop_vec_info struct
|
||||
for it. The different analyses will record information in the
|
||||
loop_vec_info struct. */
|
||||
loop_vec_info
|
||||
vect_analyze_loop (struct loop *loop)
|
||||
static bool
|
||||
vect_analyze_loop_2 (loop_vec_info loop_vinfo)
|
||||
{
|
||||
bool ok, dummy;
|
||||
loop_vec_info loop_vinfo;
|
||||
int max_vf = MAX_VECTORIZATION_FACTOR;
|
||||
int min_vf = 2;
|
||||
|
||||
if (vect_print_dump_info (REPORT_DETAILS))
|
||||
fprintf (vect_dump, "===== analyze_loop_nest =====");
|
||||
|
||||
if (loop_outer (loop)
|
||||
&& loop_vec_info_for_loop (loop_outer (loop))
|
||||
&& LOOP_VINFO_VECTORIZABLE_P (loop_vec_info_for_loop (loop_outer (loop))))
|
||||
{
|
||||
if (vect_print_dump_info (REPORT_DETAILS))
|
||||
fprintf (vect_dump, "outer-loop already vectorized.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check the CFG characteristics of the loop (nesting, entry/exit, etc. */
|
||||
|
||||
loop_vinfo = vect_analyze_loop_form (loop);
|
||||
if (!loop_vinfo)
|
||||
{
|
||||
if (vect_print_dump_info (REPORT_DETAILS))
|
||||
fprintf (vect_dump, "bad loop form.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Find all data references in the loop (which correspond to vdefs/vuses)
|
||||
and analyze their evolution in the loop. Also adjust the minimal
|
||||
vectorization factor according to the loads and stores.
|
||||
|
@ -1418,8 +1395,7 @@ vect_analyze_loop (struct loop *loop)
|
|||
{
|
||||
if (vect_print_dump_info (REPORT_DETAILS))
|
||||
fprintf (vect_dump, "bad data references.");
|
||||
destroy_loop_vec_info (loop_vinfo, true);
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Classify all cross-iteration scalar data-flow cycles.
|
||||
|
@ -1436,8 +1412,7 @@ vect_analyze_loop (struct loop *loop)
|
|||
{
|
||||
if (vect_print_dump_info (REPORT_DETAILS))
|
||||
fprintf (vect_dump, "unexpected pattern.");
|
||||
destroy_loop_vec_info (loop_vinfo, true);
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Analyze data dependences between the data-refs in the loop
|
||||
|
@ -1451,8 +1426,7 @@ vect_analyze_loop (struct loop *loop)
|
|||
{
|
||||
if (vect_print_dump_info (REPORT_DETAILS))
|
||||
fprintf (vect_dump, "bad data dependence.");
|
||||
destroy_loop_vec_info (loop_vinfo, true);
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
ok = vect_determine_vectorization_factor (loop_vinfo);
|
||||
|
@ -1460,15 +1434,13 @@ vect_analyze_loop (struct loop *loop)
|
|||
{
|
||||
if (vect_print_dump_info (REPORT_DETAILS))
|
||||
fprintf (vect_dump, "can't determine vectorization factor.");
|
||||
destroy_loop_vec_info (loop_vinfo, true);
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
if (max_vf < LOOP_VINFO_VECT_FACTOR (loop_vinfo))
|
||||
{
|
||||
if (vect_print_dump_info (REPORT_DETAILS))
|
||||
fprintf (vect_dump, "bad data dependence.");
|
||||
destroy_loop_vec_info (loop_vinfo, true);
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Analyze the alignment of the data-refs in the loop.
|
||||
|
@ -1479,8 +1451,7 @@ vect_analyze_loop (struct loop *loop)
|
|||
{
|
||||
if (vect_print_dump_info (REPORT_DETAILS))
|
||||
fprintf (vect_dump, "bad data alignment.");
|
||||
destroy_loop_vec_info (loop_vinfo, true);
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Analyze the access patterns of the data-refs in the loop (consecutive,
|
||||
|
@ -1491,8 +1462,7 @@ vect_analyze_loop (struct loop *loop)
|
|||
{
|
||||
if (vect_print_dump_info (REPORT_DETAILS))
|
||||
fprintf (vect_dump, "bad data access.");
|
||||
destroy_loop_vec_info (loop_vinfo, true);
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Prune the list of ddrs to be tested at run-time by versioning for alias.
|
||||
|
@ -1504,8 +1474,7 @@ vect_analyze_loop (struct loop *loop)
|
|||
if (vect_print_dump_info (REPORT_DETAILS))
|
||||
fprintf (vect_dump, "too long list of versioning for alias "
|
||||
"run-time tests.");
|
||||
destroy_loop_vec_info (loop_vinfo, true);
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* This pass will decide on using loop versioning and/or loop peeling in
|
||||
|
@ -1516,8 +1485,7 @@ vect_analyze_loop (struct loop *loop)
|
|||
{
|
||||
if (vect_print_dump_info (REPORT_DETAILS))
|
||||
fprintf (vect_dump, "bad data alignment.");
|
||||
destroy_loop_vec_info (loop_vinfo, true);
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check the SLP opportunities in the loop, analyze and build SLP trees. */
|
||||
|
@ -1539,13 +1507,70 @@ vect_analyze_loop (struct loop *loop)
|
|||
{
|
||||
if (vect_print_dump_info (REPORT_DETAILS))
|
||||
fprintf (vect_dump, "bad operation or unsupported loop bound.");
|
||||
destroy_loop_vec_info (loop_vinfo, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Function vect_analyze_loop.
|
||||
|
||||
Apply a set of analyses on LOOP, and create a loop_vec_info struct
|
||||
for it. The different analyses will record information in the
|
||||
loop_vec_info struct. */
|
||||
loop_vec_info
|
||||
vect_analyze_loop (struct loop *loop)
|
||||
{
|
||||
loop_vec_info loop_vinfo;
|
||||
unsigned int vector_sizes;
|
||||
|
||||
/* Autodetect first vector size we try. */
|
||||
current_vector_size = 0;
|
||||
vector_sizes = targetm.vectorize.autovectorize_vector_sizes ();
|
||||
|
||||
if (vect_print_dump_info (REPORT_DETAILS))
|
||||
fprintf (vect_dump, "===== analyze_loop_nest =====");
|
||||
|
||||
if (loop_outer (loop)
|
||||
&& loop_vec_info_for_loop (loop_outer (loop))
|
||||
&& LOOP_VINFO_VECTORIZABLE_P (loop_vec_info_for_loop (loop_outer (loop))))
|
||||
{
|
||||
if (vect_print_dump_info (REPORT_DETAILS))
|
||||
fprintf (vect_dump, "outer-loop already vectorized.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LOOP_VINFO_VECTORIZABLE_P (loop_vinfo) = 1;
|
||||
while (1)
|
||||
{
|
||||
/* Check the CFG characteristics of the loop (nesting, entry/exit). */
|
||||
loop_vinfo = vect_analyze_loop_form (loop);
|
||||
if (!loop_vinfo)
|
||||
{
|
||||
if (vect_print_dump_info (REPORT_DETAILS))
|
||||
fprintf (vect_dump, "bad loop form.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return loop_vinfo;
|
||||
if (vect_analyze_loop_2 (loop_vinfo))
|
||||
{
|
||||
LOOP_VINFO_VECTORIZABLE_P (loop_vinfo) = 1;
|
||||
|
||||
return loop_vinfo;
|
||||
}
|
||||
|
||||
destroy_loop_vec_info (loop_vinfo, true);
|
||||
|
||||
vector_sizes &= ~current_vector_size;
|
||||
if (vector_sizes == 0
|
||||
|| current_vector_size == 0)
|
||||
return NULL;
|
||||
|
||||
/* Try the next biggest vector size. */
|
||||
current_vector_size = 1 << floor_log2 (vector_sizes);
|
||||
if (vect_print_dump_info (REPORT_DETAILS))
|
||||
fprintf (vect_dump, "***** Re-trying analysis with "
|
||||
"vector size %d\n", current_vector_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1643,6 +1643,7 @@ vect_slp_analyze_bb (basic_block bb)
|
|||
int max_vf = MAX_VECTORIZATION_FACTOR;
|
||||
bool data_dependence_in_bb = false;
|
||||
|
||||
current_vector_size = 0;
|
||||
|
||||
if (vect_print_dump_info (REPORT_DETAILS))
|
||||
fprintf (vect_dump, "===vect_slp_analyze_bb===\n");
|
||||
|
|
|
@ -3455,7 +3455,8 @@ perm_mask_for_reverse (tree vectype, tree *mask)
|
|||
|
||||
mask_type = get_vectype_for_scalar_type (mask_element_type);
|
||||
nunits = TYPE_VECTOR_SUBPARTS (vectype);
|
||||
if (TYPE_VECTOR_SUBPARTS (vectype) != TYPE_VECTOR_SUBPARTS (mask_type))
|
||||
if (!mask_type
|
||||
|| TYPE_VECTOR_SUBPARTS (vectype) != TYPE_VECTOR_SUBPARTS (mask_type))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < nunits; i++)
|
||||
|
@ -4784,13 +4785,13 @@ free_stmt_vec_info (gimple stmt)
|
|||
}
|
||||
|
||||
|
||||
/* Function get_vectype_for_scalar_type.
|
||||
/* Function get_vectype_for_scalar_type_and_size.
|
||||
|
||||
Returns the vector type corresponding to SCALAR_TYPE as supported
|
||||
Returns the vector type corresponding to SCALAR_TYPE and SIZE as supported
|
||||
by the target. */
|
||||
|
||||
tree
|
||||
get_vectype_for_scalar_type (tree scalar_type)
|
||||
static tree
|
||||
get_vectype_for_scalar_type_and_size (tree scalar_type, unsigned size)
|
||||
{
|
||||
enum machine_mode inner_mode = TYPE_MODE (scalar_type);
|
||||
enum machine_mode simd_mode;
|
||||
|
@ -4818,7 +4819,12 @@ get_vectype_for_scalar_type (tree scalar_type)
|
|||
&& GET_MODE_CLASS (inner_mode) != MODE_FLOAT)
|
||||
return NULL_TREE;
|
||||
|
||||
simd_mode = targetm.vectorize.preferred_simd_mode (inner_mode);
|
||||
/* If no size was supplied use the mode the target prefers. Otherwise
|
||||
lookup a vector mode of the specified size. */
|
||||
if (size == 0)
|
||||
simd_mode = targetm.vectorize.preferred_simd_mode (inner_mode);
|
||||
else
|
||||
simd_mode = mode_for_vector (inner_mode, size / nbytes);
|
||||
nunits = GET_MODE_SIZE (simd_mode) / nbytes;
|
||||
if (nunits <= 1)
|
||||
return NULL_TREE;
|
||||
|
@ -4850,15 +4856,35 @@ get_vectype_for_scalar_type (tree scalar_type)
|
|||
return vectype;
|
||||
}
|
||||
|
||||
unsigned int current_vector_size;
|
||||
|
||||
/* Function get_vectype_for_scalar_type.
|
||||
|
||||
Returns the vector type corresponding to SCALAR_TYPE as supported
|
||||
by the target. */
|
||||
|
||||
tree
|
||||
get_vectype_for_scalar_type (tree scalar_type)
|
||||
{
|
||||
tree vectype;
|
||||
vectype = get_vectype_for_scalar_type_and_size (scalar_type,
|
||||
current_vector_size);
|
||||
if (vectype
|
||||
&& current_vector_size == 0)
|
||||
current_vector_size = GET_MODE_SIZE (TYPE_MODE (vectype));
|
||||
return vectype;
|
||||
}
|
||||
|
||||
/* Function get_same_sized_vectype
|
||||
|
||||
Returns a vector type corresponding to SCALAR_TYPE of size
|
||||
VECTOR_TYPE if supported by the target. */
|
||||
|
||||
tree
|
||||
get_same_sized_vectype (tree scalar_type, tree vector_type ATTRIBUTE_UNUSED)
|
||||
get_same_sized_vectype (tree scalar_type, tree vector_type)
|
||||
{
|
||||
return get_vectype_for_scalar_type (scalar_type);
|
||||
return get_vectype_for_scalar_type_and_size
|
||||
(scalar_type, GET_MODE_SIZE (TYPE_MODE (vector_type)));
|
||||
}
|
||||
|
||||
/* Function vect_is_simple_use.
|
||||
|
|
|
@ -779,6 +779,7 @@ extern LOC find_loop_location (struct loop *);
|
|||
extern bool vect_can_advance_ivs_p (loop_vec_info);
|
||||
|
||||
/* In tree-vect-stmts.c. */
|
||||
extern unsigned int current_vector_size;
|
||||
extern tree get_vectype_for_scalar_type (tree);
|
||||
extern tree get_same_sized_vectype (tree, tree);
|
||||
extern bool vect_is_simple_use (tree, loop_vec_info, bb_vec_info, gimple *,
|
||||
|
|
Loading…
Add table
Reference in a new issue