This is a stripped-down bit of code representing a bad code generation problem we've been having with XEmacs 21.5 + gcc 4.X + optimization. I can reproduce with Fedora Core 5's packaging of gcc 4.1.1 on the x86_64 platform, and with Ubuntu's packaging of gcc 4.0.3 on the i386 platform. Compile the following code without optimization, and it reports that the negation of 1 is -1, which is in bounds. Compile with any -O flag (confirmed for -O, -O2, -O3, and -Os) and the code reports that the negation of 1 is -1, which is out of bounds. If I break the && expression up into 2 consecutive if statements to see which bound is supposedly violated, the optimized code reports that -1 is within each bound individually. Things that have no effect: int/long are interchangeable; the size of the "tag" bitfield doesn't seem to matter, so long as the "tag" size and the "val" size add up to "INT_BITS". I also tried compiling with all of the flags turned on by -O, but without -O itself. Good code is generated in that case. #include <stdio.h> #define INT_BITS (sizeof(int) * 8) #define MAX_VALUE (int)((1UL << (INT_BITS - 2)) - 1UL) #define MIN_VALUE (-MAX_VALUE - 1) struct tagged_int { int tag: 2; int val: INT_BITS - 2; }; static void negate (struct tagged_int accum) { printf ("min = %d, max = %d\n", MIN_VALUE, MAX_VALUE); printf ("The negation of 1 is %d, which is ", -(int)accum.val); if (-(int)accum.val <= MAX_VALUE && -(int)accum.val >= MIN_VALUE) { puts ("in bounds."); } else { puts ("out of bounds."); } } int main () { struct tagged_int obj; obj.tag = 0; obj.val = 1L; negate(obj); return 0; }
Works for me on the mainline.
Created attachment 11688 [details] Testcase showing an optimizaton bug
I can confirm that both the mainline and the current 4.1 branch compile the testcase correctly. Nevertheless, both the current 4.1 branch and the mainline (revision 114741) are still miscompiling XEmacs when any optimization at all is used, so the testcase must be too simple. I just attached a more complex testcase that includes much of the actual code from XEmacs. I trimmed this down quite a bit from the original code, but it's still over 600 lines. This code illustrates the bug on both the i386 and x86_64 platforms. You have to link with the GMP library (-lgmp) when compiling.
Reduced testcase: struct a { unsigned int bits : 1; signed long val : ((sizeof(long) * 8) - 1); }; int Fnegate (struct a b) { if ((-((long)b.val)) <= ((long) ((1UL << (((sizeof(long) * 8) - 1) - 1)) -1UL)) && (-((long)b.val)) >= (-(((long) ((1UL << (((sizeof(long) * 8) - 1) - 1)) -1UL))) - 1)) return 0 ; abort (); } int main () { struct a b = {1, 1}; Fnegate (b); return 0; }
operand_equal_p (bD.1525.valD.1524, (long intD.2) bD.1525.valD.1524, 0) is true. make_range preserved the cast to (long int) for a reason, though. If we fix operand_equal_p, we no longer fold the test, but keep if (-(long int) b.val <= 1073741823 && -(long int) b.val >= -1073741824) { return 0; } abort (); so, I have a patch.
Subject: Bug 28045 Author: rguenth Date: Mon Jun 19 14:48:47 2006 New Revision: 114772 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=114772 Log: 2006-06-19 Richard Guenther <rguenther@suse.de> PR middle-end/28045 * fold-const.c (operand_equal_p): Check if the argument types have the same precision before stripping NOPs. * gcc.dg/torture/pr28045.c: New testcase. Added: trunk/gcc/testsuite/gcc.dg/torture/pr28045.c Modified: trunk/gcc/ChangeLog trunk/gcc/fold-const.c trunk/gcc/testsuite/ChangeLog
Fixed on the mainline.
On behalf of the XEmacs team, I thank you for your amazingly speedy attention to this bug report.
Subject: Bug 28045 Author: rguenth Date: Fri Jun 23 09:52:40 2006 New Revision: 114929 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=114929 Log: 2006-06-23 Richard Guenther <rguenther@suse.de> PR middle-end/28045 * fold-const.c (operand_equal_p): Check if the argument types have the same precision before stripping NOPs. * gcc.dg/torture/pr28045.c: New testcase. Added: branches/gcc-4_1-branch/gcc/testsuite/gcc.dg/torture/pr28045.c - copied unchanged from r114772, trunk/gcc/testsuite/gcc.dg/torture/pr28045.c Modified: branches/gcc-4_1-branch/gcc/ChangeLog branches/gcc-4_1-branch/gcc/fold-const.c branches/gcc-4_1-branch/gcc/testsuite/ChangeLog
Subject: Bug 28045 Author: rguenth Date: Fri Jun 23 09:57:37 2006 New Revision: 114930 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=114930 Log: 2006-06-23 Richard Guenther <rguenther@suse.de> PR middle-end/28045 * fold-const.c (operand_equal_p): Check if the argument types have the same precision before stripping NOPs. * gcc.dg/torture/pr28045.c: New testcase. Added: branches/gcc-4_0-branch/gcc/testsuite/gcc.dg/torture/pr28045.c - copied unchanged from r114772, trunk/gcc/testsuite/gcc.dg/torture/pr28045.c Modified: branches/gcc-4_0-branch/gcc/ChangeLog branches/gcc-4_0-branch/gcc/fold-const.c branches/gcc-4_0-branch/gcc/testsuite/ChangeLog
Fixed.
Subject: Bug number PR28045 A patch for this bug has been added to the patch tracker. The mailing list url for the patch is http://gcc.gnu.org/ml/gcc-patches/2006-06/msg01000.html
*** Bug 260998 has been marked as a duplicate of this bug. *** Seen from the domain http://volichat.com Page where seen: http://volichat.com/adult-chat-rooms Marked for reference. Resolved as fixed @bugzilla.