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:
Richard Guenther 2010-10-07 14:36:38 +00:00 committed by Richard Biener
parent 767f865fb8
commit bb67d9c7ce
8 changed files with 182 additions and 94 deletions

View File

@ -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> 2010-10-07 Richard Guenther <rguenther@suse.de>
* target.def (autovectorize_vector_sizes): New target hook. * target.def (autovectorize_vector_sizes): New target hook.

View File

@ -26272,7 +26272,7 @@ ix86_vectorize_builtin_conversion (unsigned int code,
case V8SFmode: case V8SFmode:
return (TYPE_UNSIGNED (src_type) return (TYPE_UNSIGNED (src_type)
? NULL_TREE ? NULL_TREE
: ix86_builtins[IX86_BUILTIN_CVTDQ2PS]); : ix86_builtins[IX86_BUILTIN_CVTDQ2PS256]);
default: default:
return NULL_TREE; return NULL_TREE;
} }

View File

@ -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); 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. */ /* Find the best mode to use to access a bit field. */
extern enum machine_mode get_best_mode (int, int, unsigned int, extern enum machine_mode get_best_mode (int, int, unsigned int,

View File

@ -470,6 +470,50 @@ int_mode_for_mode (enum machine_mode mode)
return 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 /* Return the alignment of MODE. This will be bounded by 1 and
BIGGEST_ALIGNMENT. */ BIGGEST_ALIGNMENT. */
@ -1848,44 +1892,8 @@ layout_type (tree type)
/* Find an appropriate mode for the vector type. */ /* Find an appropriate mode for the vector type. */
if (TYPE_MODE (type) == VOIDmode) if (TYPE_MODE (type) == VOIDmode)
{ SET_TYPE_MODE (type,
enum machine_mode innermode = TYPE_MODE (innertype); mode_for_vector (TYPE_MODE (innertype), 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]))
SET_TYPE_MODE (type, BLKmode);
else
SET_TYPE_MODE (type, mode);
}
TYPE_SATURATING (type) = TYPE_SATURATING (TREE_TYPE (type)); TYPE_SATURATING (type) = TYPE_SATURATING (TREE_TYPE (type));
TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TREE_TYPE (type)); TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TREE_TYPE (type));

View File

@ -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 Apply a set of analyses on LOOP, and create a loop_vec_info struct
for it. The different analyses will record information in the for it. The different analyses will record information in the
loop_vec_info struct. */ loop_vec_info struct. */
loop_vec_info static bool
vect_analyze_loop (struct loop *loop) vect_analyze_loop_2 (loop_vec_info loop_vinfo)
{ {
bool ok, dummy; bool ok, dummy;
loop_vec_info loop_vinfo;
int max_vf = MAX_VECTORIZATION_FACTOR; int max_vf = MAX_VECTORIZATION_FACTOR;
int min_vf = 2; 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) /* Find all data references in the loop (which correspond to vdefs/vuses)
and analyze their evolution in the loop. Also adjust the minimal and analyze their evolution in the loop. Also adjust the minimal
vectorization factor according to the loads and stores. 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)) if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "bad data references."); fprintf (vect_dump, "bad data references.");
destroy_loop_vec_info (loop_vinfo, true); return false;
return NULL;
} }
/* Classify all cross-iteration scalar data-flow cycles. /* 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)) if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "unexpected pattern."); fprintf (vect_dump, "unexpected pattern.");
destroy_loop_vec_info (loop_vinfo, true); return false;
return NULL;
} }
/* Analyze data dependences between the data-refs in the loop /* 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)) if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "bad data dependence."); fprintf (vect_dump, "bad data dependence.");
destroy_loop_vec_info (loop_vinfo, true); return false;
return NULL;
} }
ok = vect_determine_vectorization_factor (loop_vinfo); ok = vect_determine_vectorization_factor (loop_vinfo);
@ -1460,15 +1434,13 @@ vect_analyze_loop (struct loop *loop)
{ {
if (vect_print_dump_info (REPORT_DETAILS)) if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "can't determine vectorization factor."); fprintf (vect_dump, "can't determine vectorization factor.");
destroy_loop_vec_info (loop_vinfo, true); return false;
return NULL;
} }
if (max_vf < LOOP_VINFO_VECT_FACTOR (loop_vinfo)) if (max_vf < LOOP_VINFO_VECT_FACTOR (loop_vinfo))
{ {
if (vect_print_dump_info (REPORT_DETAILS)) if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "bad data dependence."); fprintf (vect_dump, "bad data dependence.");
destroy_loop_vec_info (loop_vinfo, true); return false;
return NULL;
} }
/* Analyze the alignment of the data-refs in the loop. /* 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)) if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "bad data alignment."); fprintf (vect_dump, "bad data alignment.");
destroy_loop_vec_info (loop_vinfo, true); return false;
return NULL;
} }
/* Analyze the access patterns of the data-refs in the loop (consecutive, /* 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)) if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "bad data access."); fprintf (vect_dump, "bad data access.");
destroy_loop_vec_info (loop_vinfo, true); return false;
return NULL;
} }
/* Prune the list of ddrs to be tested at run-time by versioning for alias. /* 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)) if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "too long list of versioning for alias " fprintf (vect_dump, "too long list of versioning for alias "
"run-time tests."); "run-time tests.");
destroy_loop_vec_info (loop_vinfo, true); return false;
return NULL;
} }
/* This pass will decide on using loop versioning and/or loop peeling in /* 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)) if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "bad data alignment."); fprintf (vect_dump, "bad data alignment.");
destroy_loop_vec_info (loop_vinfo, true); return false;
return NULL;
} }
/* Check the SLP opportunities in the loop, analyze and build SLP trees. */ /* 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)) if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "bad operation or unsupported loop bound."); 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; 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);
}
} }

View File

@ -1643,6 +1643,7 @@ vect_slp_analyze_bb (basic_block bb)
int max_vf = MAX_VECTORIZATION_FACTOR; int max_vf = MAX_VECTORIZATION_FACTOR;
bool data_dependence_in_bb = false; bool data_dependence_in_bb = false;
current_vector_size = 0;
if (vect_print_dump_info (REPORT_DETAILS)) if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "===vect_slp_analyze_bb===\n"); fprintf (vect_dump, "===vect_slp_analyze_bb===\n");

View File

@ -3455,7 +3455,8 @@ perm_mask_for_reverse (tree vectype, tree *mask)
mask_type = get_vectype_for_scalar_type (mask_element_type); mask_type = get_vectype_for_scalar_type (mask_element_type);
nunits = TYPE_VECTOR_SUBPARTS (vectype); 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; return NULL;
for (i = 0; i < nunits; i++) 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. */ by the target. */
tree static tree
get_vectype_for_scalar_type (tree scalar_type) get_vectype_for_scalar_type_and_size (tree scalar_type, unsigned size)
{ {
enum machine_mode inner_mode = TYPE_MODE (scalar_type); enum machine_mode inner_mode = TYPE_MODE (scalar_type);
enum machine_mode simd_mode; enum machine_mode simd_mode;
@ -4818,7 +4819,12 @@ get_vectype_for_scalar_type (tree scalar_type)
&& GET_MODE_CLASS (inner_mode) != MODE_FLOAT) && GET_MODE_CLASS (inner_mode) != MODE_FLOAT)
return NULL_TREE; 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; nunits = GET_MODE_SIZE (simd_mode) / nbytes;
if (nunits <= 1) if (nunits <= 1)
return NULL_TREE; return NULL_TREE;
@ -4850,15 +4856,35 @@ get_vectype_for_scalar_type (tree scalar_type)
return vectype; 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 /* Function get_same_sized_vectype
Returns a vector type corresponding to SCALAR_TYPE of size Returns a vector type corresponding to SCALAR_TYPE of size
VECTOR_TYPE if supported by the target. */ VECTOR_TYPE if supported by the target. */
tree 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. /* Function vect_is_simple_use.

View File

@ -779,6 +779,7 @@ extern LOC find_loop_location (struct loop *);
extern bool vect_can_advance_ivs_p (loop_vec_info); extern bool vect_can_advance_ivs_p (loop_vec_info);
/* In tree-vect-stmts.c. */ /* In tree-vect-stmts.c. */
extern unsigned int current_vector_size;
extern tree get_vectype_for_scalar_type (tree); extern tree get_vectype_for_scalar_type (tree);
extern tree get_same_sized_vectype (tree, tree); extern tree get_same_sized_vectype (tree, tree);
extern bool vect_is_simple_use (tree, loop_vec_info, bb_vec_info, gimple *, extern bool vect_is_simple_use (tree, loop_vec_info, bb_vec_info, gimple *,