The following testcase: extern void abort(void); long long smod16(long long x) { return x % 16; } int main(void) { if (smod16 (0xFFFFFFFF) != 0xF) abort (); return 0; } distilled from ada/uintp.adb:UI_From_Dint is miscompiled on i486 because of 2004-06-27 Roger Sayle <roger@eyesopen.com> * expmed.c (expand_smod_pow2): New function to expand signed remainder by a constant power of 2, such as "x % 16". (expand_divmod): Call new expand_smod_pow2 when appropriate. Minor corrections to comments, e.g. splitting long lines. The second part of expand_smod_pow2 cannot handle modes whose size is greater than that of HOST_WIDE_INT.
Confirmed (-march=i486 will show the bug on i686-*).
Thanks for confirming (I think -mtune=i486 is sufficient). Patch in testing.
Subject: Bug 18045 CVSROOT: /cvs/gcc Module name: gcc Changes by: ebotcazou@gcc.gnu.org 2004-10-18 22:45:01 Modified files: gcc : ChangeLog expmed.c gcc/testsuite : ChangeLog Added files: gcc/testsuite/gcc.dg: smod-1.c Log message: PR middle-end/18045 * expmed.c (expand_smod_pow2): Handle modes whose size is greater than that of HOST_WIDE_INT. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.5940&r2=2.5941 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/expmed.c.diff?cvsroot=gcc&r1=1.198&r2=1.199 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.4472&r2=1.4473 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/smod-1.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
See http://gcc.gnu.org/ml/gcc-patches/2004-10/msg01571.html