This is the mail archive of the gcc-patches@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]

Fix PR rtl-optimization/28096


This is the miscompilation of libjava/classpath/native/fdlibm/strtod.c at -O2 
on i686 present on mainline, a regression from the 4.1.x series.

The problem stems from the new cond_move_process_if_block optimization in 
ifcvt.c, which turns

(note 20 19 22 4 [bb 4] NOTE_INSN_BASIC_BLOCK)

(insn 22 20 23 4 (set (reg:CCGOC 17 flags)
        (compare:CCGOC (reg/v:SI 60 [ e.51 ])
            (const_int 0 [0x0]))) 0 {*cmpsi_ccno_1} (nil)
    (nil))

(jump_insn 23 22 25 4 (set (pc)
        (if_then_else (lt (reg:CCGOC 17 flags)
                (const_int 0 [0x0]))
            (label_ref 30)
            (pc))) 365 {*jcc_1} (nil)
    (expr_list:REG_BR_PROB (const_int 2100 [0x834])
        (nil)))

(note 25 23 26 5 [bb 5] NOTE_INSN_BASIC_BLOCK)

(insn 26 25 27 5 (set (reg/v:SI 62 [ bb2 ])
        (const_int 0 [0x0])) 34 {*movsi_1} (nil)
    (nil))

(insn 27 26 28 5 (set (reg/v:SI 61 [ bb5 ])
        (const_int 0 [0x0])) 34 {*movsi_1} (nil)
    (nil))

(jump_insn 28 27 29 5 (set (pc)
        (label_ref 34)) 380 {jump} (nil)
    (nil))

(barrier 29 28 30)

(code_label 30 29 31 6 10 "" [1 uses])

(note 31 30 32 6 [bb 6] NOTE_INSN_BASIC_BLOCK)

(insn 32 31 33 6 (set (reg/v:SI 61 [ bb5 ])
        (reg/v:SI 59 [ bb5.52 ])) 34 {*movsi_1} (nil)
    (nil))

(insn 33 32 34 6 (set (reg/v:SI 62 [ bb2 ])
        (reg/v:SI 61 [ bb5 ])) 34 {*movsi_1} (nil)
    (nil))

(code_label 34 33 35 7 12 "" [1 uses])

into

(insn 22 20 57 4 (set (reg:CCGOC 17 flags)
        (compare:CCGOC (reg/v:SI 60 [ e.51 ])
            (const_int 0 [0x0]))) 0 {*cmpsi_ccno_1} (nil)
    (nil))

(insn 57 22 58 4 (parallel [
            (set (reg:SI 67)
                (ashiftrt:SI (reg/v:SI 60 [ e.51 ])
                    (const_int 31 [0x1f])))
            (clobber (reg:CC 17 flags))
        ]) 303 {*ashrsi3_1} (nil)
    (nil))

(insn 58 57 61 4 (parallel [
            (set (reg/v:SI 62 [ bb2 ])
                (and:SI (reg/v:SI 61 [ bb5 ])
                    (reg:SI 67)))
            (clobber (reg:CC 17 flags))
        ]) 208 {*andsi_1} (nil)
    (nil))

(insn 61 58 62 4 (parallel [
            (set (reg:SI 68)
                (ashiftrt:SI (reg/v:SI 60 [ e.51 ])
                    (const_int 31 [0x1f])))
            (clobber (reg:CC 17 flags))
        ]) 303 {*ashrsi3_1} (nil)
    (nil))

(insn 62 61 37 4 (parallel [
            (set (reg/v:SI 61 [ bb5 ])
                (and:SI (reg/v:SI 59 [ bb5.52 ])
                    (reg:SI 68)))
            (clobber (reg:CC 17 flags))
        ]) 208 {*andsi_1} (nil)
    (nil))

where (reg/v:SI 61 [ bb5 ]) is now used before being set.


The problematic pattern is:

if
  ...
then
  (set (reg1) (...))
  (set (reg2) (...))
else
  (set (reg2) (...))
  (set (reg1) (reg2))
end if


Fixed by disabling the new optimization if the source of an assignment has 
already been used as a destination earlier in the block.  That shouldn't 
pessimize much in practice because you need the conjunction of a bunch of 
factors to run into this pattern (not too strong Tree optimizations, partial 
cancellation of successive RTL optimizations, etc).

Bootstrapped/regtested on i686-suse-linux, applied to mainline.



2006-09-30  Eric Botcazou  <ebotcazou@libertysurf.fr>

	PR rtl-optimization/28096
	* ifcvt.c (check_cond_move_block): Return FALSE if the source of an
 	assignment has already been used as a destination earlier in the block.


2006-09-30  Eric Botcazou  <ebotcazou@libertysurf.fr>

	* gcc.c-torture/execute/20060930-1.c: New test.


-- 
Eric Botcazou
Index: ifcvt.c
===================================================================
--- ifcvt.c	(revision 117300)
+++ ifcvt.c	(working copy)
@@ -2424,7 +2424,7 @@ check_cond_move_block (basic_block bb, r
       src = SET_SRC (set);
       if (!REG_P (dest)
 	  || (SMALL_REGISTER_CLASSES && HARD_REGISTER_P (dest)))
-	return false;
+	return FALSE;
 
       if (!CONSTANT_P (src) && !register_operand (src, VOIDmode))
 	return FALSE;
@@ -2435,6 +2435,14 @@ check_cond_move_block (basic_block bb, r
       if (may_trap_p (src) || may_trap_p (dest))
 	return FALSE;
 
+      /* Don't try to handle this if the source register was
+	 modified earlier in the block.  */
+      if ((REG_P (src)
+	   && vals[REGNO (src)] != NULL)
+	  || (GET_CODE (src) == SUBREG && REG_P (SUBREG_REG (src))
+	      && vals[REGNO (SUBREG_REG (src))] != NULL))
+	return FALSE;
+
       /* Don't try to handle this if the destination register was
 	 modified earlier in the block.  */
       if (vals[REGNO (dest)] != NULL)
/* PR rtl-optimization/28096 */
/* Origin: Jan Stein <jan@gatespacetelematics.com> */

extern void abort (void);

int bar (int, int) __attribute__((noinline));
int bar (int a, int b)
{
  if (b != 1)
    abort ();
}

void foo(int, int) __attribute__((noinline));
void foo (int e, int n)
{
  int i, bb2, bb5;

  if (e > 0)
    e = -e;

  for (i = 0; i < n; i++)
    {
      if (e >= 0)
	{
	  bb2 = 0;
	  bb5 = 0;
	}
      else
	{
	  bb5 = -e;
	  bb2 = bb5;
	}

      bar (bb5, bb2);
    }
}

int main(void)
{
  foo (1, 1);
  return 0;
}

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