Bug 8639 - [3.2/3.3 regression] simple integer arithmetic expression broken
[3.2/3.3 regression] simple integer arithmetic expression broken
Status: RESOLVED FIXED
Product: gcc
Classification: Unclassified
Component: c
unknown
: P1 critical
: ---
Assigned To: Not yet assigned to anyone
: wrong-code
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2002-11-19 06:46 UTC by stevejepsen
Modified: 2003-07-25 17:33 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
gcc_bug.tgz (22.26 KB, application/x-gzip )
2003-05-21 15:16 UTC, stevejepsen
Details

Note You need to log in before you can comment on or make changes to this bug.
Description stevejepsen 2002-11-19 06:46:02 UTC
the expression:

   bug_result = (80 - 4 * intvar) / 20;

with intvar == 1 returns 4 (should return 3)

Release:
unknown

Environment:
gcc version 3.2 20020903 (Red Hat Linux 8.0 3.2-7)

How-To-Repeat:
run attached "tst" program
Comment 1 stevejepsen 2002-11-19 06:46:02 UTC
Fix:
unknown
Comment 2 Wolfgang Bangerth 2002-11-19 07:36:06 UTC
State-Changed-From-To: open->analyzed
State-Changed-Why: Unless I am very blind, I think this reduced testcase
    should indeed pass the assertion:
    -------------------------
    #include <assert.h>
    
    int foo (int i) {
      int r;
      r = (80 - 4 * i) / 20;
      assert (r == 3);
    }
    
    int main () {
      foo(1);
    }
    -----------------------------
    Unfortunately, it aborts, with all gccs since 3.0. It
    passes with 2.95, though. Since this seems like a regression
    to me, I raise the priority. Note that no optimization
    flags are necessary to trigger this behavior. The same
    happens with the C++ front end, by the way.
Comment 3 Christian Ehrhardt 2002-11-19 17:10:33 UTC
From: "Christian Ehrhardt" <ehrhardt@mathematik.uni-ulm.de>
To: steveJepsen@netscape.net
Cc: gcc-bugs@gcc.gnu.org, gcc-gnats@gcc.gnu.org
Subject: Re: c/8639: simple integer arithmetic expression broken
Date: Tue, 19 Nov 2002 17:10:33 +0100

 On Tue, Nov 19, 2002 at 02:42:14PM -0000, steveJepsen@netscape.net wrote:
 > >Number:         8639
 > >Category:       c
 > >Synopsis:       simple integer arithmetic expression broken
 
 This is:
 a) real
 b) present in 3.2, 3.2.1 and 3.3
 c) present at least in C and C++
 d) A regression from 2.95.2
 d) arch independant (!)
 e) A show stopper (IMHO)
 
 Someone please mark this as confirmed, priority high. It should probably
 also be reclassified as middle end.
 
 > >Confidential:   no
 > >Severity:       critical
 > >Priority:       medium
 > >Responsible:    unassigned
 > >State:          open
 > >Class:          wrong-code
 > >Submitter-Id:   net
 > >Arrival-Date:   Tue Nov 19 06:46:02 PST 2002
 > >Closed-Date:
 > >Last-Modified:
 > >Originator:     Steve Jepsen
 > >Release:        unknown-1.0
 > >Organization:
 > >Environment:
 > gcc version 3.2 20020903 (Red Hat Linux 8.0 3.2-7)
 > >Description:
 > the expression:
 > 
 >    bug_result = (80 - 4 * intvar) / 20;
 > 
 > with intvar == 1 returns 4 (should return 3)
 
 I did a few experiments with expression of the form (A-B*intvar)/C with
 A, B and C beeing constant. In these expressions the Bug only seems to
 happen if C divides A and B divides C. According to the assembler output
 this is rewritten as A/C - intvar/(C/B) which is NOT the same.
 A/C - (intvar-1+C/B)/(C/B) would be the same as far as I can see.
 
 A minimal example is this:
 
 int main ()
 {
 	int x = 1;
 	int res = (80 - 4*x)/20;
 	return res;
 }
 
 Compiled with gcc t.c this gives:
 elbereth$ gcc -Wall t.c
 elbereth$ a.out
 elbereth$ echo $? 
 4
 elbereth$ 
 
 Here's the asm output on sparc which shows that the expression
 is rewritten as (20 - x/5).
 
 main:
         !#PROLOGUE# 0
         save    %sp, -120, %sp
         !#PROLOGUE# 1
         mov     1, %o0
         st      %o0, [%fp-20]
         ld      [%fp-20], %o0
         sll     %o0, 2, %o1
         mov     81, %o0
         sub     %o0, %o1, %o0
         mov     20, %o1
         call    .div, 0
          nop
         st      %o0, [%fp-24]
         ld      [%fp-24], %o0
         mov     %o0, %i0
         nop
         ret
         restore
 
 
    regards    Christian
 

Comment 4 Christian Ehrhardt 2002-11-19 19:09:59 UTC
From: "Christian Ehrhardt" <ehrhardt@mathematik.uni-ulm.de>
To: gcc-gnats@gcc.gnu.org, gcc-prs@gcc.gnu.org, steveJepsen@netscape.net,
  gcc-bugs@gcc.gnu.org, nobody@gcc.gnu.org
Cc:  
Subject: Re: c/8639: [3.2/3.3 regression] simple integer arithmetic expression broken
Date: Tue, 19 Nov 2002 19:09:59 +0100

 Hi,
 
 this patch will be bootstrapping here in a minute. An non bootstapped
 compile indicates that this fixes the bug. I'm not sure if we can be
 more clever here without doing a big rewrite of fold-const.c. I'll
 report back tonight/tomorrow (CET) when the testsuite has completed.
 
 Someone please consider to check this in. I don't have CVS access.
 Also adding a testcase would probably be a good idea.
 
     regards  Christian
 
 
 --- gcc-3.2.1-20021111/gcc/fold-const.c.orig	Tue Nov 19 18:47:57 2002
 +++ gcc-3.2.1-20021111/gcc/fold-const.c	Tue Nov 19 18:57:04 2002
 @@ -4617,10 +4617,12 @@
        t2 = extract_muldiv (op1, c, code, wide_type);
        if (t1 != 0 && t2 != 0
  	  && (code == MULT_EXPR
 -	      /* If not multiplication, we can only do this if either operand
 -		 is divisible by c.  */
 -	      || multiple_of_p (ctype, op0, c)
 -	      || multiple_of_p (ctype, op1, c)))
 +	      /* If not multiplication, we can only do this if this is 
 +	       * PLUS_EXPR and both operands are divisible by c. Note that
 +	       * (80 - 4*x)/20 or (80 + (-4)*x)/20 must not degenerate
 +	       * into (20 - x/5). */
 +	      || (multiple_of_p (ctype, op0, c) &&
 +	          multiple_of_p (ctype, op1, c))))
  	return fold (build (tcode, ctype, convert (ctype, t1),
  			    convert (ctype, t2)));
  
 
 http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=8639
 
 -- 
 THAT'S ALL FOLKS!

Comment 5 Richard Henderson 2002-11-25 14:42:43 UTC
State-Changed-From-To: analyzed->closed
State-Changed-Why: Fixed.
Comment 6 Richard Henderson 2002-11-25 19:04:58 UTC
From: rth@gcc.gnu.org
To: gcc-gnats@gcc.gnu.org
Cc:  
Subject: c/8639
Date: 25 Nov 2002 19:04:58 -0000

 CVSROOT:	/cvs/gcc
 Module name:	gcc
 Changes by:	rth@gcc.gnu.org	2002-11-25 11:04:58
 
 Modified files:
 	gcc            : ChangeLog fold-const.c 
 Added files:
 	gcc/testsuite/gcc.c-torture/execute: 20021119-1.c 
 
 Log message:
 	PR c/8639
 	* fold-const.c (extract_muldiv): Don't propagate division unless
 	both arguments are multiples of C.
 	* gcc.c-torture/execute/20021119-1.c: New.
 
 Patches:
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=1.15985&r2=1.15986
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/fold-const.c.diff?cvsroot=gcc&r1=1.226&r2=1.227
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.c-torture/execute/20021119-1.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
 
Comment 7 Richard Henderson 2002-11-25 22:42:00 UTC
From: rth@gcc.gnu.org
To: gcc-gnats@gcc.gnu.org
Cc:  
Subject: c/8639
Date: 25 Nov 2002 22:42:00 -0000

 CVSROOT:	/cvs/gcc
 Module name:	gcc
 Branch: 	gcc-3_2-branch
 Changes by:	rth@gcc.gnu.org	2002-11-25 14:42:00
 
 Modified files:
 	gcc            : ChangeLog fold-const.c 
 
 Log message:
 	PR c/8639
 	* fold-const.c (extract_muldiv): Don't propagate division unless
 	both arguments are multiples of C.
 
 Patches:
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.13152.2.657.2.149&r2=1.13152.2.657.2.150
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/fold-const.c.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.185.2.4.2.2&r2=1.185.2.4.2.3