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

--- Comment #1 from yuki.tanaka at defaultcase dot de ---
This is not specific to vaddq_s8: arm_neon.h open-codes vmulq_s8 as signed __a
* __b as well, and this one is not a regression.

#include <arm_neon.h>
#include <stdint.h>

__attribute__((noipa)) int8x16_t a(int8x16_t b)
{
  return vmulq_s8(b, vdupq_n_s8(3)) / 3;
}

int main(void)
{
  int8_t d[16] = {100, 127, 43, 1, 0, -1, -100, -128, 85, 86, 90, -90, 2, 50,
51, 20};
  int8x16_t r = a(vld1q_s8(d));

  for (int i = 0; i < 16; i++)
    {
      int8_t p = (int8_t)(uint8_t)(d[i] * 3);

      if (r[i] != p / 3)
        __builtin_abort();
    }

  return 0;
}

vmulq_s8 wraps to 8 bits. For lane 0, 100 * 3 = 300 wraps to 44, and 44 / 3 =
14. The program must return normally.

With -O2 -mcpu=cortex-a15 -mfpu=neon-vfpv4, GCC 14.3.0, 15.2.0, 16.1.0 and
trunk compile a to a bare bx lr: the multiplication and the division are gone,
and the argument is returned unchanged. -fwrapv avoids the problem.

Compiler Explorer:
https://godbolt.org/z/av19c7fhd

Reply via email to