Bug 22429 - [4.1 Regression] -1073741824 <= n && n <= 1073741823 is true where n is 1073741824
Summary: [4.1 Regression] -1073741824 <= n && n <= 1073741823 is true where n is 10737...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.1.0
: P1 critical
Target Milestone: 4.1.0
Assignee: Richard Henderson
URL: http://gcc.gnu.org/ml/gcc-patches/200...
Keywords: patch, wrong-code
Depends on:
Blocks:
 
Reported: 2005-07-12 06:42 UTC by akr
Modified: 2005-11-02 21:47 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work: 4.0.2
Known to fail: 4.1.0
Last reconfirmed: 2005-11-02 02:42:01


Attachments
patch which I need to test (333 bytes, patch)
2005-07-12 16:25 UTC, Andrew Pinski
Details | Diff
new patch which should not cause Ada test failures (592 bytes, patch)
2005-07-12 19:32 UTC, Andrew Pinski
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description akr 2005-07-12 06:42:48 UTC
I found that following program exits with 1 instead of 0.

% cat z.c
int f(int n)
{
  if (-1073741824 <= n && n <= 1073741823)
    return 1;
  return 0;
}

int main()
{
  return f(1073741824);
}
% /home/src/chkbuild-tmp/build/gcc-trunk/20050712T134449/bin/gcc -v -O  z.c    
Using built-in specs.
Target: i686-pc-linux-gnu
Configured with: ../../gcc/configure
--prefix=/home/akr/ruby/chkbuild/tmp/build/gcc-trunk/20050712T134449
--enable-languages=c
Thread model: posix
gcc version 4.1.0 20050712 (experimental)
 /home/src/chkbuild-tmp/build/gcc-trunk/20050712T134449/bin/../libexec/gcc/i686-pc-linux-gnu/4.1.0/cc1
-quiet -v -iprefix
/home/src/chkbuild-tmp/build/gcc-trunk/20050712T134449/bin/../lib/gcc/i686-pc-linux-gnu/4.1.0/
z.c -quiet -dumpbase z.c -mtune=pentiumpro -auxbase z -O -version -o /tmp/cc3anyqv.s
ignoring nonexistent directory
"/home/src/chkbuild-tmp/build/gcc-trunk/20050712T134449/bin/../lib/gcc/i686-pc-linux-gnu/4.1.0/../../../../i686-pc-linux-gnu/include"
ignoring duplicate directory
"/home/akr/ruby/chkbuild/tmp/build/gcc-trunk/20050712T134449/lib/gcc/i686-pc-linux-gnu/4.1.0/include"
ignoring nonexistent directory
"/home/akr/ruby/chkbuild/tmp/build/gcc-trunk/20050712T134449/lib/gcc/i686-pc-linux-gnu/4.1.0/../../../../i686-pc-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /home/src/chkbuild-tmp/build/gcc-trunk/20050712T134449/bin/../lib/gcc/i686-pc-linux-gnu/4.1.0/include
 /usr/local/include
 /home/akr/ruby/chkbuild/tmp/build/gcc-trunk/20050712T134449/include
 /usr/include
End of search list.
GNU C version 4.1.0 20050712 (experimental) (i686-pc-linux-gnu)
        compiled by GNU C version 4.1.0 20050712 (experimental).
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
Compiler executable checksum: cab36206423b633931a3bd43d355747c
 as -V -Qy -o /tmp/ccUCeuxU.o /tmp/cc3anyqv.s
GNU assembler version 2.15 (i386-linux) using BFD version 2.15
 /home/src/chkbuild-tmp/build/gcc-trunk/20050712T134449/bin/../libexec/gcc/i686-pc-linux-gnu/4.1.0/collect2
--eh-frame-hdr -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o
/usr/lib/crti.o
/home/src/chkbuild-tmp/build/gcc-trunk/20050712T134449/bin/../lib/gcc/i686-pc-linux-gnu/4.1.0/crtbegin.o
-L/home/src/chkbuild-tmp/build/gcc-trunk/20050712T134449/bin/../lib/gcc/i686-pc-linux-gnu/4.1.0
-L/home/src/chkbuild-tmp/build/gcc-trunk/20050712T134449/bin/../lib/gcc
-L/home/akr/ruby/chkbuild/tmp/build/gcc-trunk/20050712T134449/lib/gcc/i686-pc-linux-gnu/4.1.0
-L/home/src/chkbuild-tmp/build/gcc-trunk/20050712T134449/bin/../lib/gcc/i686-pc-linux-gnu/4.1.0/../../..
-L/home/akr/ruby/chkbuild/tmp/build/gcc-trunk/20050712T134449/lib/gcc/i686-pc-linux-gnu/4.1.0/../../..
/tmp/ccUCeuxU.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed
-lgcc_s --no-as-needed
/home/src/chkbuild-tmp/build/gcc-trunk/20050712T134449/bin/../lib/gcc/i686-pc-linux-gnu/4.1.0/crtend.o
/usr/lib/crtn.o
% ./a.out                                                                   
zsh: exit 1     ./a.out

It exists with 0 if optimization is disabled.

% /home/src/chkbuild-tmp/build/gcc-trunk/20050712T134449/bin/gcc z.c        
% ./a.out
Comment 1 Andrew Pinski 2005-07-12 06:54:16 UTC
4.0 produced:
  D.1463 = n - -1073741824;
  if (D.1463 >= 0)

Which is wrong as overflow is undefined.

4.1 produces:
(n >= -1073741824)
as overflow is undefined.

This was exposed by:
2005-07-02  Andrew Pinski  <pinskia@physics.uc.edu>

        PR middle-end/14490
        * fold-const.c (fold_binary): Handle the return value of
        fold_to_nonsharp_ineq_using_bound if we get back the same operand back.
        Implement "X +- C1 CMP C2" folding to "X CMP C2 -+ C1".

Which means I have to look into it since I exposed it.  We should be subtracting using unsigned mode.
Comment 2 Andrew Pinski 2005-07-12 07:04:28 UTC
(In reply to comment #1)
> 4.0 produced:
>   D.1463 = n - -1073741824;
>   if (D.1463 >= 0)
> 
> Which is wrong as overflow is undefined.

This shows that fold is doing something wrong:
void abort(void);

int f(int n)
{
  if (n< 0)
   return 1;
  n+=1073741824;
  return n >= 0;
}
int main()
{
 if (f(1073741824))
   abort ();
}
Comment 3 Andrew Pinski 2005-07-12 16:18:45 UTC
I have a fix, the problem is that build_range_check depends on wrapping on signed types being defined 
which is not correct.
Comment 4 Andrew Pinski 2005-07-12 16:25:20 UTC
Created attachment 9249 [details]
patch which I need to test

ChangeLog:
* fold-const.c (build_range_check): If signed wrapping is undefined use
unsigned types even if value has not overflowed.
Comment 5 Andrew Pinski 2005-07-12 19:32:01 UTC
Created attachment 9251 [details]
new patch which should not cause Ada test failures

This is a new patch which should not cause Ada (ACATS) test failures.
Comment 6 Andrew Pinski 2005-07-12 22:56:41 UTC
Patch posted here: <http://gcc.gnu.org/ml/gcc-patches/2005-07/msg00879.html>.
Comment 7 Paolo Bonzini 2005-10-13 15:59:02 UTC
Why can't build_range_check first cast to an unsigned type?
Comment 8 Paolo Bonzini 2005-10-13 16:05:29 UTC
Sorry, let me rephrase.  Could build_range_check not cast to the unsigned type if flag_wrapv?
Comment 9 Paolo Bonzini 2005-10-13 16:09:21 UTC
As in:

  if (value != 0
      && (!flag_wrapv || TREE_OVERFLOW (value))
      && (flag_wrapv || !TYPE_UNSIGNED (etype)))

which in turn means

  if (value != 0
      && (flag_wrapv ? TREE_OVERFLOW (value) : !TYPE_UNSIGNED (etype)))
Comment 10 Andrew Pinski 2005-10-13 16:12:40 UTC
Subject: Re:  [4.1 Regression] -1073741824 <= n && n <= 1073741823 is true where n is 1073741824

> 
> 
> 
> ------- Comment #9 from bonzini at gcc dot gnu dot org  2005-10-13 16:09 -------
> As in:
> 
>   if (value != 0
>       && (!flag_wrapv || TREE_OVERFLOW (value))
>       && (flag_wrapv || !TYPE_UNSIGNED (etype)))
> 
> which in turn means
> 
>   if (value != 0
>       && (flag_wrapv ? TREE_OVERFLOW (value) : !TYPE_UNSIGNED (etype)))

That is what my patch does.

The extra stuff was needed to make sure that Ada would be able to bootstrap.

-- Pinski

Comment 11 Andrew Pinski 2005-10-22 21:55:12 UTC
I am no longer working on this and my machine went bust today, sorry.  If someone wants to take my patch and fix up for future comments, please do.
Comment 12 Mark Mitchell 2005-10-31 04:03:22 UTC
This is a showstopper; wrong code on a primary platform using plausible inputs.
Comment 13 Richard Henderson 2005-11-02 21:44:26 UTC
Subject: Bug 22429

Author: rth
Date: Wed Nov  2 21:44:17 2005
New Revision: 106400

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=106400
Log:
        PR 22429
        * fold-const.c (build_range_check): Use unsigned when signed
        overflow is undefined also.  If etype is subtype, make sure that
        the subtraction is in the supertype.

Added:
    trunk/gcc/testsuite/gcc.c-torture/execute/pr22429.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/fold-const.c

Comment 14 Richard Henderson 2005-11-02 21:47:24 UTC
Fixed.