https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108692

--- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
So, on simplified -O2 -ftree-vectorize testcase with trunk:
int
foo (signed char *x, signed char *y, int n)
{
  int i, r = 0;
  signed char a, b;
  for (i = 0; i < n; i++)
    {
      a = x[i];
      b = y[i];
      int c = (unsigned char) a - (unsigned char) b;
      r = r + (c < 0 ? -c : c);
    }
  return r;
}
everything looks ok to me until vect_recog_sad_pattern is called.
The interesting part of the loop in question is:
<bb 3> [local count: 955630225]:
# i_22 = PHI <i_20(6), 0(5)>
# r_23 = PHI <r_19(6), 0(5)>
...
a.0_5 = (unsigned char) a_15;
_6 = (int) a.0_5;
b.1_7 = (unsigned char) b_17;
_8 = (int) b.1_7;
c_18 = _6 - _8;
_9 = ABS_EXPR <c_18>;
r_19 = _9 + r_23;
with 15/17 having signed char type, 5/7 unsigned char and everything else int.
Now, when vect_recog_sad_pattern is called, it sees as diff_stmt_vinfo->stmt
patt_34 = (a.0_5) w- (b.1_7);
which is reasonable, abs_stmt_vinfo was
patt_30 = ABS_EXPR <patt_33>;
where 30 is signed short, patt_33 too set to (signed short) patt_34 and 34
unsigned short.  Still, the widening subtraction is done with zero extensions
from unsigned char operands to unsigned short.
But vect_recog_sad_pattern calls
1325      if (!vect_widened_op_tree (vinfo, diff_stmt_vinfo, MINUS_EXPR,
WIDEN_MINUS_EXPR,
1326                                 false, 2, unprom, &half_type))
1327        return NULL;
and instead of returning a.0_5 and b.1_7 as the unpromoted operands and
unsigned char as half_type, it returns a_15 and b_17 as the unpromoted operands
and signed char as half_type.
I'd think if in vect_widened_op_tree after the early checks rhs_code != code we
shouldn't look through further promotions and just accept what we have.
as

Reply via email to