User account creation filtered due to spam.

Bug 56250 - Wrong constant folding on unsigned int
Summary: Wrong constant folding on unsigned int
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.7.2
: P3 normal
Target Milestone: ---
Assignee: Jakub Jelinek
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2013-02-08 01:39 UTC by Ishiura Lab Compiler Team
Modified: 2013-02-19 17:43 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2013-02-08 00:00:00


Attachments
gcc48-pr56250.patch (684 bytes, patch)
2013-02-08 11:24 UTC, Jakub Jelinek
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Ishiura Lab Compiler Team 2013-02-08 01:39:39 UTC
GCC 4.7.2 and 4.8.0 miscompile the following code where UINT_MAX ==
4294967295.

  $ cat bug.c
  int main(void)
  {
         unsigned x = 2;
         return ((unsigned) 0 - ( x / 2 ) ) / 2;
  }
  $ gcc bug.c
  $ ./a.out
  $ echo $?
  0

Unsigned (0-(x/2))/2 should evaluate to 2147483647 instead of 0.  
The following code with variable x replaced by "(unsigned) 2" is
correctly compiled.

  $ cat nobug.c
  int main(void)
  {
         return ((unsigned) 0 - ( (unsigned) 2 / 2 ) ) / 2;
  }
  $ gcc nobug.c
  $ ./a.out
  $ echo $?
  255

The miscompile seems to occur on many versions of gcc (4.2 - 4.8, and
even 4.0 and 3.1 on i686-apple-darwin, 4.4 - 4.6 on
i686-linux-gnu-gcc, etc.)
Comment 1 Andrew Pinski 2013-02-08 01:51:39 UTC
When I do this:
         unsigned x = 2;
         unsigned t = (x/2);
         unsigned t1 = -t;
         unsigned t2 = t2/2;

t2 is 0 which is correct.  I don't see why 2147483647 is correct.
Comment 2 Andrew Pinski 2013-02-08 01:54:23 UTC
Actually I get the correct results with the split out one.  The problem is division is being merged together over the negative which is not valid for wrapping cases.
Comment 3 Ishiura Lab Compiler Team 2013-02-08 01:59:18 UTC
(In reply to comment #1)
> When I do this:
>          unsigned x = 2;
>          unsigned t = (x/2);
>          unsigned t1 = -t;
>          unsigned t2 = t2/2;
> 
> t2 is 0 which is correct.  I don't see why 2147483647 is correct.

The last line should be
    unsigned t2 = t1/2;
Comment 4 Jakub Jelinek 2013-02-08 08:31:03 UTC
Bug is in extract_muldiv_1.
Comment 5 Jakub Jelinek 2013-02-08 11:24:02 UTC
Created attachment 29394 [details]
gcc48-pr56250.patch

Untested fix.

I believe only division/modulus is problematic, not multiplication, and I think
-fwrapv signed types are fine too.  For *_DIV_EXPR/*_MOD_EXPR, I think wide_type is always NULL_TREE and ctype is always equal to type.
Comment 6 Jakub Jelinek 2013-02-08 15:06:37 UTC
Author: jakub
Date: Fri Feb  8 15:06:26 2013
New Revision: 195888

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=195888
Log:
	PR tree-optimization/56250
	* fold-const.c (extract_muldiv_1) <case NEGATE_EXPR>: Don't optimize
	if type is unsigned and code isn't MULT_EXPR.

	* gcc.c-torture/execute/pr56250.c: New test.

Added:
    trunk/gcc/testsuite/gcc.c-torture/execute/pr56250.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/fold-const.c
    trunk/gcc/testsuite/ChangeLog
Comment 7 Jakub Jelinek 2013-02-08 15:23:43 UTC
Fixed on the trunk so far.
Comment 8 Jakub Jelinek 2013-02-19 17:26:15 UTC
Author: jakub
Date: Tue Feb 19 17:26:04 2013
New Revision: 196147

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=196147
Log:
	Backported from mainline
	2013-02-08  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/56250
	* fold-const.c (extract_muldiv_1) <case NEGATE_EXPR>: Don't optimize
	if type is unsigned and code isn't MULT_EXPR.

	* gcc.c-torture/execute/pr56250.c: New test.

Added:
    branches/gcc-4_7-branch/gcc/testsuite/gcc.c-torture/execute/pr56250.c
Modified:
    branches/gcc-4_7-branch/gcc/ChangeLog
    branches/gcc-4_7-branch/gcc/fold-const.c
    branches/gcc-4_7-branch/gcc/testsuite/ChangeLog
Comment 9 Jakub Jelinek 2013-02-19 17:43:36 UTC
Fixed for 4.7.3+.