This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug middle-end/17425] New: 4.0: wrong code with optimization (tree_ssa invariant motion pass?)
- From: "gcc-bugzilla at gcc dot gnu dot org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 12 Sep 2004 00:39:41 -0000
- Subject: [Bug middle-end/17425] New: 4.0: wrong code with optimization (tree_ssa invariant motion pass?)
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
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;
<bb 0>:
lsm_tmp.6_11 = phi;
goto <bb 2> (<L11>);
# lsm_tmp.6_12 = PHI <lsm_tmp.6_6(6), lsm_tmp.6_15(3)>;
<L0>:;
# lsm_tmp.6_16 = PHI <lsm_tmp.6_11(0), lsm_tmp.6_12(1)>;
<L11>:;
phi.1_3 = lsm_tmp.6_16;
T.2_4 = phi.1_3 + 1;
phi = T.2_4;
if (T.2_4 > 10) goto <L1>; else goto <L2>;
<L1>:;
lsm_tmp.6_15 = 1;
goto <bb 1> (<L0>);
<L2>:;
if (T.2_4 <= 4) goto <L3>; else goto <L5>;
<L3>:;
T.3_10 = foo (T.2_4);
if (T.3_10 != 0) goto <L12>; else goto <L4>;
# lsm_tmp.6_18 = PHI <lsm_tmp.6_16(5)>;
<L12>:;
phi = lsm_tmp.6_18;
goto <bb 8> (<L9>);
<L4>:;
lsm_tmp.6_6 = phi.1_3;
goto <bb 1> (<L0>);
# lsm_tmp.6_17 = PHI <lsm_tmp.6_16(4)>;
<L5>:;
phi = lsm_tmp.6_17;
phi = 0;
<L9>:;
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;
<bb 0>:
goto <bb 2> (<L11>);
<L0>:;
<L11>:;
phi.1_3 = phi;
T.2_4 = phi.1_3 + 1;
phi = T.2_4;
if (T.2_4 > 10) goto <L1>; else goto <L2>;
<L1>:;
phi = 1;
goto <bb 1> (<L0>);
<L2>:;
if (T.2_4 <= 4) goto <L3>; else goto <L5>;
<L3>:;
T.3_10 = foo (T.2_4);
if (T.3_10 != 0) goto <L12>; else goto <L4>;
<L12>:;
goto <bb 8> (<L9>);
<L4>:;
phi = phi.1_3;
goto <bb 1> (<L0>);
<L5>:;
phi = 0;
<L9>:;
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
<machine, os, target, libraries (multiple lines)>
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:
<how to correct or work around the problem, if known (multiple lines)>
--
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