From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 6546 invoked by alias); 12 Sep 2004 00:39:43 -0000 Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org Received: (qmail 6527 invoked by alias); 12 Sep 2004 00:39:41 -0000 Date: Sun, 12 Sep 2004 00:39:00 -0000 From: "gcc-bugzilla at gcc dot gnu dot org" To: gcc-bugs@gcc.gnu.org Message-ID: <20040912003938.17425.snyder@fnal.gov> Reply-To: gcc-bugzilla@gcc.gnu.org Subject: [Bug middle-end/17425] New: 4.0: wrong code with optimization (tree_ssa invariant motion pass?) X-Bugzilla-Reason: CC X-SW-Source: 2004-09/txt/msg01154.txt.bz2 List-Id: The program below gets miscompiled if optimization is on. I expect this program to return `1', which it does with no optimization: (The examples here are with g++, but i get the same results if i make the trivial changes needed to get it to compile as C rather than C++.) $ g++ -o x x.cc $ ./x; echo $? 1 $ However, with optimzation on, it returns `0': $ g++ -O1 -o x x.cc $ ./x; echo $? 0 $ Here's the generated assembly code for bar() with -O1. (I've suppressed the labels used just for exception handling for easier reading): _Z3barv: pushl %ebp movl %esp, %ebp pushl %ebx subl $4, %esp movl phi, %ebx ; bx=phi jmp .L15 .L4: movl $1, %ebx .L15: leal 1(%ebx), %eax ; ax=phi+1 movl %eax, phi ; store ax (old phi+1) back into phi cmpl $10, %eax jg .L4 cmpl $4, %eax jg .L6 movl %eax, (%esp) ; fall though tests to here; call foo() call _Z3fooi testl %eax, %eax .p2align 4,,2 je .L15 ; return from foo; this branch is not taken movl %ebx, phi ; !!! store bx (old phi) back into phi. ; this overwrites the correct value ; of phi with the old value! jmp .L2 .L6: movl $0, phi .L2: addl $4, %esp popl %ebx popl %ebp ret Everything looks fine until just before the function exits, at which point the old value of phi (before the increment is done) is stored back into phi. It appears that this problem is introduced during the loop invariant motion SSA pass. Here's the .t47.lim dump for bar: ;; Function void bar() (_Z3barv) void bar() () { int lsm_tmp.6; int T.4; int T.3; int T.2; int phi.1; : lsm_tmp.6_11 = phi; goto (); # lsm_tmp.6_12 = PHI ; :; # lsm_tmp.6_16 = PHI ; :; phi.1_3 = lsm_tmp.6_16; T.2_4 = phi.1_3 + 1; phi = T.2_4; if (T.2_4 > 10) goto ; else goto ; :; lsm_tmp.6_15 = 1; goto (); :; if (T.2_4 <= 4) goto ; else goto ; :; T.3_10 = foo (T.2_4); if (T.3_10 != 0) goto ; else goto ; # lsm_tmp.6_18 = PHI ; :; phi = lsm_tmp.6_18; goto (); :; lsm_tmp.6_6 = phi.1_3; goto (); # lsm_tmp.6_17 = PHI ; :; phi = lsm_tmp.6_17; phi = 0; :; return; } This shows the old value of phi (lsm_tmp_6) being stored back into phi at L12. Here's the previous dump, .t46.loopinit: ;; Function void bar() (_Z3barv) ;; 2 loops found, 2 levels ;; ;; Loop 0: ;; header -1, latch -2, pre-header -1 ;; depth 0, level 2, outer -1 ;; nodes: -1 0 1 2 3 4 5 9 6 7 8 -2 ;; ;; Loop 1: ;; header 2, latch 1, pre-header -1 ;; depth 1, level 1, outer 0 ;; nodes: 2 1 6 3 5 4 ;; 0 succs { 2 } ;; 1 succs { 2 } ;; 2 succs { 4 3 } ;; 3 succs { 1 } ;; 4 succs { 7 5 } ;; 5 succs { 6 9 } ;; 9 succs { 8 } ;; 6 succs { 1 } ;; 7 succs { 8 } ;; 8 succs { -2 } void bar() () { int T.4; int T.3; int T.2; int phi.1; : goto (); :; :; phi.1_3 = phi; T.2_4 = phi.1_3 + 1; phi = T.2_4; if (T.2_4 > 10) goto ; else goto ; :; phi = 1; goto (); :; if (T.2_4 <= 4) goto ; else goto ; :; T.3_10 = foo (T.2_4); if (T.3_10 != 0) goto ; else goto ; :; goto (); :; phi = phi.1_3; goto (); :; phi = 0; :; return; } Here, things look ok, at least on the control path used in this example. Environment: System: Linux karma 2.6.7 #18 Wed Jul 14 03:27:01 EDT 2004 i686 i686 i386 GNU/Linux Architecture: i686 host: i686-pc-linux-gnu build: i686-pc-linux-gnu target: i686-pc-linux-gnu configured with: /home/sss/gcc/gcc/configure --prefix=/usr/local/gcc --enable-threads=posix --enable-long-long --enable-languages=c,c++,f95 How-To-Repeat: Compile with -O1: ----------------------------------------- int foo (int) { return 1; } int phi; void bar() { while(1) { phi++; if(phi > 10) { phi = 1; } else if (phi < 5) { if (foo(phi)) return; else phi = phi - 1; } else { phi = 0; break; } } } int main() { bar(); return phi; } ----------------------------------------- ------- Additional Comments From snyder at fnal dot gov 2004-09-12 00:39 ------- Fix: -- Summary: 4.0: wrong code with optimization (tree_ssa invariant motion pass?) Product: gcc Version: 3.5.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: snyder at fnal dot gov CC: gcc-bugs at gcc dot gnu dot org GCC build triplet: i686-pc-linux-gnu GCC host triplet: i686-pc-linux-gnu GCC target triplet: i686-pc-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17425