+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
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.
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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;
+}
{
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);
/* 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;
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
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;