aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog22
-rw-r--r--gcc/config/i386/i386.c2
-rw-r--r--gcc/machmode.h5
-rw-r--r--gcc/stor-layout.c84
-rw-r--r--gcc/tree-vect-loop.c119
-rw-r--r--gcc/tree-vect-slp.c1
-rw-r--r--gcc/tree-vect-stmts.c42
-rw-r--r--gcc/tree-vectorizer.h1
8 files changed, 182 insertions, 94 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 94eada1..ffc280e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,27 @@
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.
* targhooks.c (default_autovectorize_vector_sizes): New function.
* targhooks.h (default_autovectorize_vector_sizes): Declare.
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 39308cf..33510a7 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -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;
}
diff --git a/gcc/machmode.h b/gcc/machmode.h
index 936a36e..3ab7a81 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -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,
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 7ffef4d..5796ea1 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -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));
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index 95b36f7..d7a864a 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -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);
+ }
}
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 4739538..2dbe328 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -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");
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 8fba200..6d0c112 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -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.
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index b438dbc..389e80a 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -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 *,