First Last Prev Next    No search results available      Search page      Enter new bug
Bug#: 28045
Product:  
Component:  
Status: RESOLVED
Resolution: FIXED
Assigned To: Richard Guenther <rguenth@gcc.gnu.org>
Host:
Reported against  
Priority:  
Severity:  
Target Milestone:  
 
 
Target:
Reporter: Jerry James <Jerry.James@usu.edu>
Add CC:
CC:
Remove selected CCs
Build:
URL:
Summary:
Keywords:
Known to work:
Known to fail:

Attachment Description Type Created Size Actions
negate.c Testcase showing an optimizaton bug text/plain 2006-06-17 21:04 5.64 KB Edit
Create a New Attachment (proposed patch, testcase, etc.) View All

Bug 28045 depends on: Show dependency tree
Show dependency graph
Bug 28045 blocks:

Additional Comments:






View Bug Activity   |   Format For Printing   |   Clone This Bug


Description:   Last confirmed: 2006-06-18 10:58 Opened: 2006-06-15 19:12
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;
}

------- Comment #1 From Richard Guenther 2006-06-15 20:04 -------
Works for me on the mainline.

------- Comment #2 From Jerry James 2006-06-17 21:04 -------
Created an attachment (id=11688) [edit]
Testcase showing an optimizaton bug

------- Comment #3 From Jerry James 2006-06-17 21:05 -------
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.

------- Comment #4 From Andrew Pinski 2006-06-17 22:06 -------
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;
}

------- Comment #5 From Richard Guenther 2006-06-18 10:58 -------
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.

------- Comment #6 From Richard Guenther 2006-06-19 14:48 -------
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

------- Comment #7 From Richard Guenther 2006-06-19 14:49 -------
Fixed on the mainline.

------- Comment #8 From Jerry James 2006-06-19 16:27 -------
On behalf of the XEmacs team, I thank you for your amazingly speedy attention
to this bug report.

------- Comment #9 From Richard Guenther 2006-06-23 09:52 -------
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

------- Comment #10 From Richard Guenther 2006-06-23 09:57 -------
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

------- Comment #11 From Richard Guenther 2006-06-23 09:57 -------
Fixed.

------- Comment #12 From patchapp@dberlin.org 2006-06-29 21:37 -------
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

First Last Prev Next    No search results available      Search page      Enter new bug