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

            Bug ID: 128404
           Summary: [17 Regression] Vectorized unsigned average produces
                    arithmetic-shift result
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jeffchen006 at gmail dot com
  Target Milestone: ---

GCC 17.0.0 20261102 (experimental), revision
7eb405c3d119d4fc84b31f21d6499069fbfedad8
Target: x86_64-linux-gnu; reproduced on Compiler Explorer.
Configure options (installation paths and packaging metadata omitted):
--build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
--disable-bootstrap --enable-multiarch --with-abi=m64
--with-multilib-list=m32,m64,mx32 --enable-multilib --enable-clocale=gnu
--enable-languages=c,c++,fortran,ada,objc,obj-c++,go,d,rust,m2,cobol,algol68
--enable-ld=yes --enable-gold=yes --enable-libstdcxx-time=yes
--enable-linker-build-id --enable-lto --enable-plugins --enable-threads=posix

The testcase is complete and has no #include dependencies. Compile and run with
no command-line arguments.

Testcase (bug-010.c):

int printf(const char *, ...);

signed char a[8];
unsigned out[8];

void f(unsigned c)
{
  for (int i = 0; i < 8; i++)
    out[i] = ((unsigned long long)c + (unsigned)(c ? 0 : a[i])) / 2;
}

unsigned c0 = 0;

int main(void)
{
  a[1] = -1;
  f(c0);
  printf("%x\n", out[1]);
  return 0;
}

Reproduction commands:

  gcc -std=gnu2x -Wall -Wextra -O0 bug-010.c -o o0
  ./o0
  gcc -std=gnu2x -Wall -Wextra -O3 bug-010.c -o o3
  ./o3

Expected: 7fffffff
Actual with -O0: 7fffffff
Actual with -O3: ffffffff
Compilation produces no diagnostics with -Wall -Wextra.

The failure also persists with:

  -O3 -fno-strict-aliasing -fwrapv -fno-aggressive-loop-optimizations

Analysis and additional checks:

With c == 0 and a[1] == -1, converting a[1] to unsigned gives 0xffffffff.
Conversion to unsigned long long preserves that value, and unsigned 64-bit
division by 2 gives 0x7fffffff. The output element is unsigned, so printf("%x",
out[1]) must print 7fffffff. Current trunk at -O3 prints ffffffff.

Compiler Explorer GCC 16.2 prints 7fffffff at -O3. Current trunk also prints
7fffffff with -O3 -fno-tree-vectorize.

Suspected area: AVG_FLOOR fallback expansion using an arithmetic shift for an
unsigned average. Earlier bisection supplied with the reduction points to
9edd8aa65a3; that bisection was not repeated here.

The ASan+UBSan+float-cast-overflow build runs without sanitizer diagnostics and
prints the expected 7fffffff; instrumentation hides the failure.

Related: PR127216 is a RISC-V code-generation-quality regression in average
fallback handling; this testcase is an x86-64 wrong-result case. PR128142
concerns a signed wrapping vector add folded in match.pd and was fixed on trunk
on October 26; this testcase still fails on the November 2 snapshot. No
identical report was identified in the AVG_FLOOR searches.
  • [Bug tree-optimization/128404] N... jeffchen006 at gmail dot com via Gcc-bugs

Reply via email to