This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug middle-end/17425] New: 4.0: wrong code with optimization (tree_ssa invariant motion pass?)



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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]