aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2023-08-04 12:11:45 +0200
committerRichard Biener <rguenther@suse.de>2023-08-04 13:15:05 +0200
commit1a599caab86464006ea8c9501aff6c6638e891eb (patch)
treeff972a0135fd19369a611d67639fe1ad521a8b3a
parent0782b01c9ea43d43648071faa9c65a101f5068a2 (diff)
downloadgcc-1a599caab86464006ea8c9501aff6c6638e891eb.zip
gcc-1a599caab86464006ea8c9501aff6c6638e891eb.tar.gz
gcc-1a599caab86464006ea8c9501aff6c6638e891eb.tar.bz2
tree-optimization/110838 - vectorization of widened right shifts
The following fixes a problem with my last attempt of avoiding out-of-bound shift values for vectorized right shifts of widened operands. Instead of truncating the shift amount with a bitwise and we actually need to saturate it to the target precision. The following does that and adds test coverage for the constant and invariant but variable case that would previously have failed. PR tree-optimization/110838 * tree-vect-patterns.cc (vect_recog_over_widening_pattern): Fix right-shift value sanitizing. Properly emit external def mangling in the preheader rather than in the pattern def sequence where it will fail vectorizing. * gcc.dg/vect/pr110838.c: New testcase.
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr110838.c31
-rw-r--r--gcc/tree-vect-patterns.cc22
2 files changed, 48 insertions, 5 deletions
diff --git a/gcc/testsuite/gcc.dg/vect/pr110838.c b/gcc/testsuite/gcc.dg/vect/pr110838.c
new file mode 100644
index 0000000..cf8765b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr110838.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+
+#include "tree-vect.h"
+
+short a[32], b[32];
+
+void __attribute__((noipa)) foo ()
+{
+ for (int i = 0; i < 32; ++i)
+ a[i] = b[i] >> 16;
+}
+
+void __attribute__((noipa)) bar (int n)
+{
+ int np = n & 31;
+ for (int i = 0; i < 32; ++i)
+ a[i] = b[i] >> np;
+}
+
+int main ()
+{
+ check_vect ();
+ b[0] = -8;
+ foo ();
+ if (a[0] != -1)
+ abort ();
+ bar (16);
+ if (a[0] != -1)
+ abort ();
+ return 0;
+}
diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc
index e4ab8c2..2cedf23 100644
--- a/gcc/tree-vect-patterns.cc
+++ b/gcc/tree-vect-patterns.cc
@@ -3109,8 +3109,8 @@ vect_recog_over_widening_pattern (vec_info *vinfo,
wide_int min_value, max_value;
if (TREE_CODE (ops[1]) == INTEGER_CST)
ops[1] = wide_int_to_tree (op_type,
- wi::bit_and (wi::to_wide (ops[1]),
- new_precision - 1));
+ wi::umin (wi::to_wide (ops[1]),
+ new_precision - 1));
else if (!vect_get_range_info (ops[1], &min_value, &max_value)
|| wi::ge_p (max_value, new_precision, TYPE_SIGN (op_type)))
{
@@ -3118,11 +3118,23 @@ vect_recog_over_widening_pattern (vec_info *vinfo,
same argument widened shifts and it un-CSEs same arguments. */
tree new_var = vect_recog_temp_ssa_var (op_type, NULL);
gimple *pattern_stmt
- = gimple_build_assign (new_var, BIT_AND_EXPR, ops[1],
+ = gimple_build_assign (new_var, MIN_EXPR, ops[1],
build_int_cst (op_type, new_precision - 1));
- ops[1] = new_var;
gimple_set_location (pattern_stmt, gimple_location (last_stmt));
- append_pattern_def_seq (vinfo, last_stmt_info, pattern_stmt);
+ if (unprom[1].dt == vect_external_def)
+ {
+ if (edge e = vect_get_external_def_edge (vinfo, ops[1]))
+ {
+ basic_block new_bb
+ = gsi_insert_on_edge_immediate (e, pattern_stmt);
+ gcc_assert (!new_bb);
+ }
+ else
+ return NULL;
+ }
+ else
+ append_pattern_def_seq (vinfo, last_stmt_info, pattern_stmt);
+ ops[1] = new_var;
}
}