vect: Fix up lowering of TRUNC_MOD_EXPR by negative constant [PR94524]
authorJakub Jelinek <jakub@redhat.com>
Wed, 8 Apr 2020 19:22:05 +0000 (21:22 +0200)
committerJakub Jelinek <jakub@redhat.com>
Wed, 8 Apr 2020 19:22:05 +0000 (21:22 +0200)
commitf52eb4f988992d393c69ee4ab76f236dced80e36
treef0e536209ea52b193d614cd54c906c4b24d9e607
parent6c9a711575d8fdf9e75f01d7a0e84d558600df40
vect: Fix up lowering of TRUNC_MOD_EXPR by negative constant [PR94524]

The first testcase below is miscompiled, because for the division part
of the lowering we canonicalize negative divisors to their absolute value
(similarly how expmed.c canonicalizes it), but when multiplying the division
result back by the VECTOR_CST, we use the original constant, which can
contain negative divisors.

Fixed by computing ABS_EXPR of the VECTOR_CST.  Unfortunately, fold-const.c
doesn't support const_unop (ABS_EXPR, VECTOR_CST) and I think it is too late
in GCC 10 cycle to add it now.

Furthermore, while modulo by most negative constant happens to return the
right value, it does that only by invoking UB in the IL, because
we then expand division by that 1U+INT_MAX and say for INT_MIN % INT_MIN
compute the division as -1, and then multiply by INT_MIN, which is signed
integer overflow.  We in theory could do the computation in unsigned vector
types instead, but is it worth bothering.  People that are doing % INT_MIN
are either testing for standard conformance, or doing something wrong.
So, I've also added punting on % INT_MIN, both in vect lowering and vect
pattern recognition (we punt already for / INT_MIN).

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.

* gcc.c-torture/execute/pr94524-1.c: New test.
* gcc.c-torture/execute/pr94524-2.c: New test.
gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr94524-1.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/pr94524-2.c [new file with mode: 0644]
gcc/tree-vect-generic.c
gcc/tree-vect-patterns.c