GCC 3.3 on Solaris SPARC produces invalid assembler code, for shift operator shifting 32 bits. GCC 3.3 is compiled to use the system's assembler, /usr/ccs/bin/as To reproduce the issue (admitted, this code has undefined behaviour): % cat shift.c #if __GNUC__ #define ATTR_ALWAYS_INLINE __attribute__ ((__always_inline__)) #else #define ATTR_ALWAYS_INLINE #endif static ATTR_ALWAYS_INLINE unsigned put_bits(int n, unsigned int value) { return value << n; } main() { unsigned val = 1; int i; for (i = 0; i < 4; i++) val = put_bits(32, val); printf("val=%x\n", val); } % gcc -O3 -mcpu=ultrasparc -o shift shift.c /usr/ccs/bin/as: "/tmp/cc0VFu29.s", line 20: error: shift count negative or too big: 32 Looking at the generated assembler source... % gcc -O3 -mcpu=ultrasparc -S shift.c ... there's a shift instruction with a constant shift count of 32, where the immediate shift count is restricted to the range 0 .. 31 on SPARC: sll %o1, 32, %o1 The same code used to compile with gcc 3.2 and erlier, and it does compile with gcc 3.3 at optimization level -O2 or when option -mcpu=ultrasparc is not used.
I can reproduce this on Sparc Linux with gcc 3.3.1 20030728 (Debian prerelease).
Created attachment 4622 [details] sparc.md patch Funny, I just found + fixed this bug over the last weekend on NetBSD when compiling XFree on sparc64. The patch fixes it and does not cause any regressions in the testsuite. I only tested generating 64 bit sparc code on a 64 bit sparc host, but the patch tries to handle the 32bit case correctly too (similar to the mips backend).
Forgot to mention: I used gcc version 3.3.1. I initially left out the 32bit changes (since that cases currently seem to not be triggered), but Ian L. Taylor told me you can not rely on that and pointed to the mips backends way of handling it.
This is a regression from 3.2.3 and there is even a patch. Martin can you send the patch to gcc-patches saying this fixes this PR?
Created attachment 4708 [details] revised patch This is a simplified version that also addresses the same issue in other shift instruction patterns.
I'll bootstrap/regtest it for SPARC and SPARC64 on the 3.3 branch and install it.
Subject: Bug 11965 CVSROOT: /cvs/gcc Module name: gcc Changes by: ebotcazou@gcc.gnu.org 2003-09-10 12:59:36 Modified files: gcc : ChangeLog gcc/config/sparc: sparc.c sparc.md gcc/testsuite : ChangeLog Added files: gcc/testsuite/gcc.dg: ultrasp10.c Log message: PR target/11965 * config/sparc/sparc.c (sparc_v8plus_shift): Protect against constants greater than 63. * config/sparc/sparc.md (ashlsi3, ashrsi3, lshrsi3): Protect against constants greater than 31. (*ashldi3_sp64, *ashrdi3_sp64, *lshrdi3_sp64): Protect against constants greater than 63. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.1022&r2=2.1023 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/sparc/sparc.c.diff?cvsroot=gcc&r1=1.258&r2=1.259 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/sparc/sparc.md.diff?cvsroot=gcc&r1=1.190&r2=1.191 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.3047&r2=1.3048 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/ultrasp10.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
Subject: Bug 11965 CVSROOT: /cvs/gcc Module name: gcc Branch: gcc-3_3-branch Changes by: ebotcazou@gcc.gnu.org 2003-09-10 13:04:00 Modified files: gcc : ChangeLog gcc/config/sparc: sparc.c sparc.md gcc/testsuite : ChangeLog Added files: gcc/testsuite/gcc.dg: ultrasp10.c Log message: PR target/11965 * config/sparc/sparc.c (sparc_v8plus_shift): Protect against constants greater than 63. * config/sparc/sparc.md (ashlsi3, ashrsi3, lshrsi3): Protect against constants greater than 31. (*ashldi3_sp64, *ashrdi3_sp64, *lshrdi3_sp64): Protect against constants greater than 63. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_3-branch&r1=1.16114.2.734&r2=1.16114.2.735 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/sparc/sparc.c.diff?cvsroot=gcc&only_with_tag=gcc-3_3-branch&r1=1.233.4.5&r2=1.233.4.6 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/sparc/sparc.md.diff?cvsroot=gcc&only_with_tag=gcc-3_3-branch&r1=1.181.4.6&r2=1.181.4.7 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_3-branch&r1=1.2261.2.276&r2=1.2261.2.277 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/ultrasp10.c.diff?cvsroot=gcc&only_with_tag=gcc-3_3-branch&r1=NONE&r2=1.1.2.1
Done.