aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vect-stmts.c
diff options
context:
space:
mode:
authorBingfeng Mei <bmei@broadcom.com>2013-12-20 13:46:01 +0000
committerBingfeng Mei <meibf@gcc.gnu.org>2013-12-20 13:46:01 +0000
commit09dfa4951aa9b8700c9d3047e712050d7c1e4e94 (patch)
tree80c9cee1e5490b99e947f1d357a1fa73a7eb85a8 /gcc/tree-vect-stmts.c
parentfc4f394b22144fd86324bec3c0566ad6a548bc9b (diff)
downloadgcc-09dfa4951aa9b8700c9d3047e712050d7c1e4e94.zip
gcc-09dfa4951aa9b8700c9d3047e712050d7c1e4e94.tar.gz
gcc-09dfa4951aa9b8700c9d3047e712050d7c1e4e94.tar.bz2
re PR tree-optimization/59544 (Vectorizing store with negative step)
2013-12-20 Bingfeng Mei <bmei@broadcom.com> PR tree-optimization/59544 * tree-vect-stmts.c (perm_mask_for_reverse): Move before vectorizable_store. (vectorizable_store): Handle negative step. * gcc.target/i386/pr59544.c: New test. From-SVN: r206148
Diffstat (limited to 'gcc/tree-vect-stmts.c')
-rw-r--r--gcc/tree-vect-stmts.c95
1 files changed, 71 insertions, 24 deletions
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 99f6b1f..3056c2e 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -4859,6 +4859,25 @@ ensure_base_align (stmt_vec_info stmt_info, struct data_reference *dr)
}
+/* Given a vector type VECTYPE returns the VECTOR_CST mask that implements
+ reversal of the vector elements. If that is impossible to do,
+ returns NULL. */
+
+static tree
+perm_mask_for_reverse (tree vectype)
+{
+ int i, nunits;
+ unsigned char *sel;
+
+ nunits = TYPE_VECTOR_SUBPARTS (vectype);
+ sel = XALLOCAVEC (unsigned char, nunits);
+
+ for (i = 0; i < nunits; ++i)
+ sel[i] = nunits - 1 - i;
+
+ return vect_gen_perm_mask (vectype, sel);
+}
+
/* Function vectorizable_store.
Check if STMT defines a non scalar data-ref (array/pointer/structure) that
@@ -4902,6 +4921,8 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
vec<tree> oprnds = vNULL;
vec<tree> result_chain = vNULL;
bool inv_p;
+ bool negative = false;
+ tree offset = NULL_TREE;
vec<tree> vec_oprnds = vNULL;
bool slp = (slp_node != NULL);
unsigned int vec_num;
@@ -4976,16 +4997,39 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
if (!STMT_VINFO_DATA_REF (stmt_info))
return false;
- if (tree_int_cst_compare (loop && nested_in_vect_loop_p (loop, stmt)
- ? STMT_VINFO_DR_STEP (stmt_info) : DR_STEP (dr),
- size_zero_node) < 0)
+ negative =
+ tree_int_cst_compare (loop && nested_in_vect_loop_p (loop, stmt)
+ ? STMT_VINFO_DR_STEP (stmt_info) : DR_STEP (dr),
+ size_zero_node) < 0;
+ if (negative && ncopies > 1)
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "negative step for store.\n");
+ "multiple types with negative step.");
return false;
}
+ if (negative)
+ {
+ gcc_assert (!grouped_store);
+ alignment_support_scheme = vect_supportable_dr_alignment (dr, false);
+ if (alignment_support_scheme != dr_aligned
+ && alignment_support_scheme != dr_unaligned_supported)
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "negative step but alignment required.");
+ return false;
+ }
+ if (!perm_mask_for_reverse (vectype))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "negative step and reversing not supported.");
+ return false;
+ }
+ }
+
if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
{
grouped_store = true;
@@ -5090,6 +5134,9 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
|| alignment_support_scheme == dr_aligned
|| alignment_support_scheme == dr_unaligned_supported);
+ if (negative)
+ offset = size_int (-TYPE_VECTOR_SUBPARTS (vectype) + 1);
+
if (store_lanes_p)
aggr_type = build_array_type_nelts (elem_type, vec_num * nunits);
else
@@ -5200,7 +5247,7 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
dataref_ptr
= vect_create_data_ref_ptr (first_stmt, aggr_type,
simd_lane_access_p ? loop : NULL,
- NULL_TREE, &dummy, gsi, &ptr_incr,
+ offset, &dummy, gsi, &ptr_incr,
simd_lane_access_p, &inv_p);
gcc_assert (bb_vinfo || !inv_p);
}
@@ -5306,6 +5353,25 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
set_ptr_info_alignment (get_ptr_info (dataref_ptr), align,
misalign);
+ if (negative)
+ {
+ tree perm_mask = perm_mask_for_reverse (vectype);
+ tree perm_dest
+ = vect_create_destination_var (gimple_assign_rhs1 (stmt),
+ vectype);
+ tree new_temp = make_ssa_name (perm_dest, NULL);
+
+ /* Generate the permute statement. */
+ gimple perm_stmt
+ = gimple_build_assign_with_ops (VEC_PERM_EXPR, new_temp,
+ vec_oprnd, vec_oprnd,
+ perm_mask);
+ vect_finish_stmt_generation (stmt, perm_stmt, gsi);
+
+ perm_stmt = SSA_NAME_DEF_STMT (new_temp);
+ vec_oprnd = new_temp;
+ }
+
/* Arguments are ready. Create the new vector stmt. */
new_stmt = gimple_build_assign (data_ref, vec_oprnd);
vect_finish_stmt_generation (stmt, new_stmt, gsi);
@@ -5363,25 +5429,6 @@ vect_gen_perm_mask (tree vectype, unsigned char *sel)
return mask_vec;
}
-/* Given a vector type VECTYPE returns the VECTOR_CST mask that implements
- reversal of the vector elements. If that is impossible to do,
- returns NULL. */
-
-static tree
-perm_mask_for_reverse (tree vectype)
-{
- int i, nunits;
- unsigned char *sel;
-
- nunits = TYPE_VECTOR_SUBPARTS (vectype);
- sel = XALLOCAVEC (unsigned char, nunits);
-
- for (i = 0; i < nunits; ++i)
- sel[i] = nunits - 1 - i;
-
- return vect_gen_perm_mask (vectype, sel);
-}
-
/* Given a vector variable X and Y, that was generated for the scalar
STMT, generate instructions to permute the vector elements of X and Y
using permutation mask MASK_VEC, insert them at *GSI and return the