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
Fix: unknown
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.
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
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!
State-Changed-From-To: analyzed->closed State-Changed-Why: Fixed.
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
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