aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr94524-1.c19
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr94524-2.c25
-rw-r--r--gcc/tree-vect-generic.c25
-rw-r--r--gcc/tree-vect-patterns.c4
6 files changed, 83 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 025a4a6..dcdfae1 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+2020-04-08 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/94524
+ * tree-vect-generic.c (expand_vector_divmod): If any elt of op1 is
+ negative for signed TRUNC_MOD_EXPR, multiply with absolute value of
+ op1 rather than op1 itself at the end. Punt for signed modulo by
+ most negative constant.
+ * tree-vect-patterns.c (vect_recog_divmod_pattern): Punt for signed
+ modulo by most negative constant.
+
2020-04-08 Richard Biener <rguenther@suse.de>
PR rtl-optimization/93946
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 8916b89..134280d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,9 @@
2020-04-08 Jakub Jelinek <jakub@redhat.com>
+ PR tree-optimization/94524
+ * gcc.c-torture/execute/pr94524-1.c: New test.
+ * gcc.c-torture/execute/pr94524-2.c: New test.
+
PR c++/94314
* g++.dg/pr94314.C (A::operator new, B::operator new, C::operator new):
Use __SIZE_TYPE__ instead of unsigned long.
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr94524-1.c b/gcc/testsuite/gcc.c-torture/execute/pr94524-1.c
new file mode 100644
index 0000000..e7365ad
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr94524-1.c
@@ -0,0 +1,19 @@
+/* PR tree-optimization/94524 */
+
+typedef signed char __attribute__ ((__vector_size__ (16))) V;
+
+static __attribute__ ((__noinline__, __noclone__)) V
+foo (V c)
+{
+ c %= (signed char) -19;
+ return (V) c;
+}
+
+int
+main ()
+{
+ V x = foo ((V) { 31 });
+ if (x[0] != 12)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr94524-2.c b/gcc/testsuite/gcc.c-torture/execute/pr94524-2.c
new file mode 100644
index 0000000..9c74b7b
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr94524-2.c
@@ -0,0 +1,25 @@
+/* PR tree-optimization/94524 */
+
+typedef signed char __attribute__ ((__vector_size__ (16))) V;
+
+static __attribute__ ((__noinline__, __noclone__)) V
+foo (V c)
+{
+ c %= (signed char) -128;
+ return (V) c;
+}
+
+int
+main ()
+{
+ V x = foo ((V) { -128 });
+ if (x[0] != 0)
+ __builtin_abort ();
+ x = foo ((V) { -127 });
+ if (x[0] != -127)
+ __builtin_abort ();
+ x = foo ((V) { 127 });
+ if (x[0] != 127)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c
index 2f6fd5e..8b00f32 100644
--- a/gcc/tree-vect-generic.c
+++ b/gcc/tree-vect-generic.c
@@ -478,6 +478,7 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
{
bool use_pow2 = true;
bool has_vector_shift = true;
+ bool use_abs_op1 = false;
int mode = -1, this_mode;
int pre_shift = -1, post_shift;
unsigned int nunits = nunits_for_known_piecewise_op (type);
@@ -618,8 +619,11 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
/* n rem d = n rem -d */
if (code == TRUNC_MOD_EXPR && d < 0)
- d = abs_d;
- else if (abs_d == HOST_WIDE_INT_1U << (prec - 1))
+ {
+ d = abs_d;
+ use_abs_op1 = true;
+ }
+ if (abs_d == HOST_WIDE_INT_1U << (prec - 1))
{
/* This case is not handled correctly below. */
mode = -2;
@@ -899,6 +903,23 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
if (op == unknown_optab
|| optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
return NULL_TREE;
+ if (use_abs_op1)
+ {
+ tree_vector_builder elts;
+ if (!elts.new_unary_operation (type, op1, false))
+ return NULL_TREE;
+ unsigned int count = elts.encoded_nelts ();
+ for (unsigned int i = 0; i < count; ++i)
+ {
+ tree elem1 = VECTOR_CST_ELT (op1, i);
+
+ tree elt = const_unop (ABS_EXPR, TREE_TYPE (elem1), elem1);
+ if (elt == NULL_TREE)
+ return NULL_TREE;
+ elts.quick_push (elt);
+ }
+ op1 = elts.build ();
+ }
tem = gimplify_build2 (gsi, MULT_EXPR, type, cur_op, op1);
op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
if (op == unknown_optab
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index 60dc1bf..dd0c19d 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -3365,8 +3365,8 @@ vect_recog_divmod_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
d = abs_d;
oprnd1 = build_int_cst (itype, abs_d);
}
- else if (HOST_BITS_PER_WIDE_INT >= prec
- && abs_d == HOST_WIDE_INT_1U << (prec - 1))
+ if (HOST_BITS_PER_WIDE_INT >= prec
+ && abs_d == HOST_WIDE_INT_1U << (prec - 1))
/* This case is not handled correctly below. */
return NULL;