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

            Bug ID: 128140
           Summary: [17 Regression] wrong code at -O2: vectorized x >= C ?
                    x : C - 1 gives a wrong result in the lane where C
                    wraps around to 0
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: yuki.tanaka at defaultcase dot de
  Target Milestone: ---

unsigned char x[8], r[8];

__attribute__((noipa)) void a(void)
{
  for (int i = 0; i < 8; i++)
    r[i] = x[i] >= (unsigned char) (i + 253) ? x[i] : (unsigned char) (i +
252);
}

int main(void)
{
  a();
  if (r[3] != 0)
    __builtin_abort();
  return 0;
}

Compiler Explorer (GCC 16.1 vs. 17):
https://godbolt.org/z/hMvhh6Wsh

GCC 17:
"a":
        movq    xmm1, QWORD PTR "x"[rip]
        movabs  rax, 216736835873734140
        movq    xmm0, rax
        pmaxub  xmm0, xmm1
        movq    QWORD PTR "r"[rip], xmm0
        ret

The loop is turned into a single MAX with i + 252.  That is only correct if i +
252 == (i + 253) - 1 in every lane, but in lane 3 i + 253 wraps to 0 and i +
252 is 255, so r[3] is 255 instead of 0. GCC 16.1 keeps the compare and select.
 Also fails at -O3, on aarch64 -O2 trunk emits the same single umax.

Possibly related to r17-3277-g729eb68a002 ("tree-optimization: Fold
canonicalized vector min/max conditionals [PR98602]").

Reply via email to