extern void fn1 (long int) __attribute__ ((noreturn)); void fn2 (long int); extern long int u, v; struct S { char c; long int d; long int e; }; static inline struct S * fn3 (long int x) { if (*(char *) x != 6) fn1 (0); return (struct S *) x; } static inline int fn4 (long int x) { if (x == u) return 3; fn2 (x); return 0; } int test (long int x) { long int r; int m = 0; for (r = x; r != v; r = (fn3 (r)->d)) if (*(char *) r != 6) fn1 (x); else m |= 1 << (fn4 (fn3 (r)->e) - 1); return m; } ICEs at -O and above on x86_64.
What happens is that first dom1 splits the 1 << (f4 (...) - 1) shift into 1 << (3 - 1) and 1 << (0 - 1) branches depending on if fn3 (r)->e == u or not. The latter triggers undefined behavior, but if the 1 << (3 - 1) branch is always taken, then it will never be triggered at runtime. D.1642 = 1 << -1; is then expanded into RTL (not folded, since folders refuse to fold shifts by negative value), at life1 we still have: (insn 69 67 70 10 (set (reg:SI 66) (const_int 1 [0x1])) 40 {*movsi_1} (nil) (nil)) (insn 70 69 71 10 (parallel [ (set (reg:SI 61 [ D.1642 ]) (ashift:SI (reg:SI 66) (const_int -1 [0xffffffffffffffff]))) (clobber (reg:CC 17 flags)) ]) 413 {*ashlsi3_1} (insn_list:REG_DEP_TRUE 69 (nil)) (expr_list:REG_DEAD (reg:SI 66) (expr_list:REG_UNUSED (reg:CC 17 flags) (nil)))) but then combine changes that into: (insn 71 70 72 10 (parallel [ (set (zero_extract:DI (const_int 0 [0x0]) (const_int 1 [0x1]) (const_int -1 [0xffffffffffffffff])) (const_int 1 [0x1])) ]) 318 {*iorsi_1} (insn_list:REG_DEP_TRUE 70 (nil)) (expr_list:REG_DEAD (reg:SI 61 [ D.1642 ]) (expr_list:REG_UNUSED (reg:CC 17 flags) (nil)))) which is not valid RTL (zero_extract requires first arg to be REG or MEM). I think this is not the first time we have issues with shifts by negative value, perhaps tree->rtl expansion could mask the shift count or something, otherwise we'll keep finding such bugs all the time.
Confirmed, this is undefined behavior anyways so I don't think we should block 4.1 for this code.
Anyways patch posted: http://gcc.gnu.org/ml/gcc-patches/2006-02/msg01222.html
Well, undefined behavior only if you reach it. The original code looked like: if (((type) == (Qnothing))) return IMAGE_NOTHING; if (((type) == (Qtext))) return IMAGE_TEXT; if (((type) == (Qmono_pixmap))) return IMAGE_MONO_PIXMAP; if (((type) == (Qcolor_pixmap))) return IMAGE_COLOR_PIXMAP; if (((type) == (Qpointer))) return IMAGE_POINTER; if (((type) == (Qsubwindow))) return IMAGE_SUBWINDOW; if (((type) == (Qwidget))) return IMAGE_WIDGET; maybe_signal_simple_error("Invalid image-instance type", type, Qimage, errb); return IMAGE_UNKNOWN; where IMAGE_UNKNOWN is 0, guess the authors just assume this will never happen.
Subject: Bug 26300 Author: jakub Date: Wed Feb 15 20:41:03 2006 New Revision: 111116 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=111116 Log: PR middle-end/26300 * combine.c (make_extraction): Bail out if ORIG_POS is negative. * gcc.c-torture/compile/20060215-1.c: New test. Added: trunk/gcc/testsuite/gcc.c-torture/compile/20060215-1.c Modified: trunk/gcc/ChangeLog trunk/gcc/combine.c trunk/gcc/testsuite/ChangeLog
Subject: Bug 26300 Author: jakub Date: Fri Feb 17 08:58:46 2006 New Revision: 111176 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=111176 Log: PR middle-end/26300 * combine.c (make_extraction): Bail out if ORIG_POS is negative. * gcc.c-torture/compile/20060215-1.c: New test. Added: branches/gcc-4_1-branch/gcc/testsuite/gcc.c-torture/compile/20060215-1.c Modified: branches/gcc-4_1-branch/gcc/ChangeLog branches/gcc-4_1-branch/gcc/combine.c branches/gcc-4_1-branch/gcc/testsuite/ChangeLog
Fixed.