re PR rtl-optimization/45695 (-O1 wrong-code by cmove)

PR rtl-optimization/45695
	* combine.c (try_combine): When splitting a two set pattern,
	make sure the pattern which will be put into i2 doesn't use REGs
	or MEMs set by insns in between i2 and i3.

	* gcc.c-torture/execute/pr45695.c: New test.

From-SVN: r164431
This commit is contained in:
Jakub Jelinek 2010-09-20 15:24:23 +02:00 committed by Jakub Jelinek
parent 4ee472e528
commit 2960be837a
4 changed files with 68 additions and 52 deletions

View File

@ -1,3 +1,10 @@
2010-09-20 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/45695
* combine.c (try_combine): When splitting a two set pattern,
make sure the pattern which will be put into i2 doesn't use REGs
or MEMs set by insns in between i2 and i3.
2010-09-19 Jan Hubicka <jh@suse.cz>
PR lto/44246

View File

@ -3690,36 +3690,41 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx i0, int *new_direct_jump_p)
&& GET_CODE (XVECEXP (newpat, 0, 1)) == SET
&& GET_CODE (SET_DEST (XVECEXP (newpat, 0, 1))) != ZERO_EXTRACT
&& GET_CODE (SET_DEST (XVECEXP (newpat, 0, 1))) != STRICT_LOW_PART
&& ! use_crosses_set_p (SET_SRC (XVECEXP (newpat, 0, 1)),
DF_INSN_LUID (i2))
&& ! reg_referenced_p (SET_DEST (XVECEXP (newpat, 0, 1)),
XVECEXP (newpat, 0, 0))
&& ! reg_referenced_p (SET_DEST (XVECEXP (newpat, 0, 0)),
XVECEXP (newpat, 0, 1))
&& ! (contains_muldiv (SET_SRC (XVECEXP (newpat, 0, 0)))
&& contains_muldiv (SET_SRC (XVECEXP (newpat, 0, 1))))
#ifdef HAVE_cc0
/* We cannot split the parallel into two sets if both sets
reference cc0. */
&& ! (reg_referenced_p (cc0_rtx, XVECEXP (newpat, 0, 0))
&& reg_referenced_p (cc0_rtx, XVECEXP (newpat, 0, 1)))
#endif
)
&& contains_muldiv (SET_SRC (XVECEXP (newpat, 0, 1)))))
{
/* Normally, it doesn't matter which of the two is done first,
but it does if one references cc0. In that case, it has to
but the one that references cc0 can't be the second, and
one which uses any regs/memory set in between i2 and i3 can't
be first. */
if (!use_crosses_set_p (SET_SRC (XVECEXP (newpat, 0, 1)),
DF_INSN_LUID (i2))
#ifdef HAVE_cc0
if (reg_referenced_p (cc0_rtx, XVECEXP (newpat, 0, 0)))
&& !reg_referenced_p (cc0_rtx, XVECEXP (newpat, 0, 0))
#endif
)
{
newi2pat = XVECEXP (newpat, 0, 1);
newpat = XVECEXP (newpat, 0, 0);
}
else if (!use_crosses_set_p (SET_SRC (XVECEXP (newpat, 0, 0)),
DF_INSN_LUID (i2))
#ifdef HAVE_cc0
&& !reg_referenced_p (cc0_rtx, XVECEXP (newpat, 0, 1))
#endif
)
{
newi2pat = XVECEXP (newpat, 0, 0);
newpat = XVECEXP (newpat, 0, 1);
}
else
#endif
{
newi2pat = XVECEXP (newpat, 0, 1);
newpat = XVECEXP (newpat, 0, 0);
undo_all ();
return 0;
}
i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
@ -3735,44 +3740,11 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx i0, int *new_direct_jump_p)
{
rtx reg = XEXP (XVECEXP (newi2pat, 0, i), 0);
if (reg_overlap_mentioned_p (reg, newpat))
break;
{
undo_all ();
return 0;
}
}
if (i >= 0)
{
/* CLOBBERs on newi2pat prevent it going first.
Try the other order of the insns if possible. */
temp = newpat;
newpat = XVECEXP (newi2pat, 0, 0);
newi2pat = temp;
#ifdef HAVE_cc0
if (reg_referenced_p (cc0_rtx, newpat))
{
undo_all ();
return 0;
}
#endif
i2_code_number = recog_for_combine (&newi2pat, i2,
&new_i2_notes);
if (i2_code_number < 0)
{
undo_all ();
return 0;
}
if (GET_CODE (newi2pat) == PARALLEL)
for (i = XVECLEN (newi2pat, 0) - 1; i >= 0; i--)
if (GET_CODE (XVECEXP (newi2pat, 0, i)) == CLOBBER)
{
rtx reg = XEXP (XVECEXP (newi2pat, 0, i), 0);
if (reg_overlap_mentioned_p (reg, newpat))
{
undo_all ();
return 0;
}
}
}
}
insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);

View File

@ -1,3 +1,8 @@
2010-09-20 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/45695
* gcc.c-torture/execute/pr45695.c: New test.
2010-09-19 Jan Hubicka <jh@suse.cz>
PR lto/44246

View File

@ -0,0 +1,32 @@
/* PR rtl-optimization/45695 */
extern void abort (void);
__attribute__((noinline)) void
g (int x)
{
asm volatile ("" : "+r" (x));
}
__attribute__((noinline)) int
f (int a, int b, int d)
{
int r = -1;
b += d;
if (d == a)
r = b - d;
g (b);
return r;
}
int
main (void)
{
int l;
asm ("" : "=r" (l) : "0" (0));
if (f (l + 0, l + 1, l + 4) != -1)
abort ();
if (f (l + 4, l + 1, l + 4) != 1)
abort ();
return 0;
}