vectorizer: Fix up vectorization using WIDEN_MINUS_EXPR [PR102124]
authorJakub Jelinek <jakub@redhat.com>
Wed, 1 Sep 2021 11:30:51 +0000 (13:30 +0200)
committerJakub Jelinek <jakub@redhat.com>
Wed, 1 Sep 2021 11:40:43 +0000 (13:40 +0200)
commitbea07159d1d4c9a61c8f7097e9f88c2b206b1b2f
tree9df5780b3d76c871dc729f73b17152c3fcb2a76f
parenta61623d9b38d28048ccbd397d4ccf52c2dfb3fed
vectorizer: Fix up vectorization using WIDEN_MINUS_EXPR [PR102124]

The following testcase is miscompiled on aarch64-linux at -O3 since the
introduction of WIDEN_MINUS_EXPR.
The problem is if the inner type (half_type) is unsigned and the result
type in which the subtraction is performed (type) has precision more than
twice as larger as the inner type's precision.
For other widening operations like WIDEN_{PLUS,MULT}_EXPR, if half_type
is unsigned, the addition/multiplication result in itype is also unsigned
and needs to be zero-extended to type.
But subtraction is special, even when half_type is unsigned, the subtraction
behaves as signed (also regardless of whether the result type is signed or
unsigned), 0xfeU - 0xffU is -1 or 0xffffffffU, not 0x0000ffff.

I think it is better not to use mixed signedness of types in
WIDEN_MINUS_EXPR (have unsigned vector of operands and signed result
vector), so this patch instead adds another cast to make sure we always
sign-extend the result from itype to type if type is wider than itype.

2021-09-01  Jakub Jelinek  <jakub@redhat.com>

PR tree-optimization/102124
* tree-vect-patterns.c (vect_recog_widen_op_pattern): For ORIG_CODE
MINUS_EXPR, if itype is unsigned with smaller precision than type,
add an extra cast to signed variant of itype to ensure sign-extension.

* gcc.dg/torture/pr102124.c: New test.
gcc/testsuite/gcc.dg/torture/pr102124.c [new file with mode: 0644]
gcc/tree-vect-patterns.c