https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128403
Bug ID: 128403
Summary: [16/17 Regression] Vectorizer rounded-average
recognition discards unsigned truncation
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-011.c):
int printf(const char *, ...);
unsigned short a[8];
signed char b[8];
unsigned short out[8];
int main(void)
{
b[1] = -1;
for (int i = 0; i < 8; i++)
out[i] = (unsigned)((unsigned long long)a[i] + b[i] + 1) >> 1;
printf("%x\n", out[1]);
return 0;
}
Reproduction commands:
gcc -std=gnu2x -Wall -Wextra -O0 bug-011.c -o o0
./o0
gcc -std=gnu2x -Wall -Wextra -O3 bug-011.c -o o3
./o3
Expected: 0
Actual with -O0: 0
Actual with -O3: 8000
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:
For element 1, a[1] is zero and b[1] is -1. In the expression, b[1] converts to
unsigned long long, so adding 1 wraps to zero in unsigned 64-bit arithmetic.
The explicit cast to unsigned yields zero and shifting right yields zero. The
optimized executable instead prints 8000.
Compiler Explorer GCC 15.3 prints 0 at -O3; GCC 16.2 and current trunk print
8000. Adding -fno-tree-vectorize to current trunk restores 0.
Suspected area: vect_recog_average_pattern recognizing an average while
ignoring the explicit unsigned conversion and its truncation semantics. No
patch or independently repeated first-bad bisection is claimed.
The ASan+UBSan+float-cast-overflow build runs without sanitizer diagnostics and
prints 0; instrumentation hides the failure.