re PR rtl-optimization/62151 (wrong code at -O2 and -O3 on x86_64-linux-gnu)

PR rtl-optimization/62151
	* combine.c (try_combine): New local variables local_elim_i1
	and local_elim_i0.  Set elim_i1 and elim_i0 using the local
	version variables.  Distribute notes from i0notes or i1notes
	using the local variables.

	gcc/testsuite/ChangeLog
	PR rtl-optimization/62151
	* gcc.c-torture/execute/pr62151.c: New test.

From-SVN: r219008
This commit is contained in:
Bin Cheng 2014-12-22 10:25:10 +00:00 committed by Bin Cheng
parent 86a8ba5b75
commit ae9f434509
4 changed files with 89 additions and 8 deletions

View file

@ -1,3 +1,11 @@
2014-12-22 Bin Cheng <bin.cheng@arm.com>
PR rtl-optimization/62151
* combine.c (try_combine): New local variables local_elim_i1
and local_elim_i0. Set elim_i1 and elim_i0 using the local
version variables. Distribute notes from i0notes or i1notes
using the local variables.
2014-12-22 Martin Liska <mliska@suse.cz>
* cgraphunit.c (symbol_table::process_new_functions): New inline_summaries

View file

@ -4124,19 +4124,46 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
rtx midnotes = 0;
int from_luid;
/* Compute which registers we expect to eliminate. newi2pat may be setting
either i3dest or i2dest, so we must check it. Also, i1dest may be the
same as i3dest, in which case newi2pat may be setting i1dest. */
either i3dest or i2dest, so we must check it. */
rtx elim_i2 = ((newi2pat && reg_set_p (i2dest, newi2pat))
|| i2dest_in_i2src || i2dest_in_i1src || i2dest_in_i0src
|| !i2dest_killed
? 0 : i2dest);
rtx elim_i1 = (i1 == 0 || i1dest_in_i1src || i1dest_in_i0src
/* For i1, we need to compute both local elimination and global
elimination information with respect to newi2pat because i1dest
may be the same as i3dest, in which case newi2pat may be setting
i1dest. Global information is used when distributing REG_DEAD
note for i2 and i3, in which case it does matter if newi2pat sets
i1dest or not.
Local information is used when distributing REG_DEAD note for i1,
in which case it doesn't matter if newi2pat sets i1dest or not.
See PR62151, if we have four insns combination:
i0: r0 <- i0src
i1: r1 <- i1src (using r0)
REG_DEAD (r0)
i2: r0 <- i2src (using r1)
i3: r3 <- i3src (using r0)
ix: using r0
From i1's point of view, r0 is eliminated, no matter if it is set
by newi2pat or not. In other words, REG_DEAD info for r0 in i1
should be discarded.
Note local information only affects cases in forms like "I1->I2->I3",
"I0->I1->I2->I3" or "I0&I1->I2, I2->I3". For other cases like
"I0->I1, I1&I2->I3" or "I1&I2->I3", newi2pat won't set i1dest or
i0dest anyway. */
rtx local_elim_i1 = (i1 == 0 || i1dest_in_i1src || i1dest_in_i0src
|| !i1dest_killed
? 0 : i1dest);
rtx elim_i1 = (local_elim_i1 == 0
|| (newi2pat && reg_set_p (i1dest, newi2pat))
|| !i1dest_killed
? 0 : i1dest);
rtx elim_i0 = (i0 == 0 || i0dest_in_i0src
/* Same case as i1. */
rtx local_elim_i0 = (i0 == 0 || i0dest_in_i0src || !i0dest_killed
? 0 : i0dest);
rtx elim_i0 = (local_elim_i0 == 0
|| (newi2pat && reg_set_p (i0dest, newi2pat))
|| !i0dest_killed
? 0 : i0dest);
/* Get the old REG_NOTES and LOG_LINKS from all our insns and
@ -4305,10 +4332,10 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
elim_i2, elim_i1, elim_i0);
if (i1notes)
distribute_notes (i1notes, i1, i3, newi2pat ? i2 : NULL,
elim_i2, elim_i1, elim_i0);
elim_i2, local_elim_i1, local_elim_i0);
if (i0notes)
distribute_notes (i0notes, i0, i3, newi2pat ? i2 : NULL,
elim_i2, elim_i1, elim_i0);
elim_i2, elim_i1, local_elim_i0);
if (midnotes)
distribute_notes (midnotes, NULL, i3, newi2pat ? i2 : NULL,
elim_i2, elim_i1, elim_i0);

View file

@ -1,3 +1,8 @@
2014-12-22 Bin Cheng <bin.cheng@arm.com>
PR rtl-optimization/62151
* gcc.c-torture/execute/pr62151.c: New test.
2014-12-22 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/specs/atomic2.ads: New test.

View file

@ -0,0 +1,41 @@
/* PR rtl-optimization/62151 */
int a, c, d, e, f, g, h, i;
short b;
int
fn1 ()
{
b = 0;
for (;;)
{
int j[2];
j[f] = 0;
if (h)
d = 0;
else
{
for (; f; f++)
;
for (a = 0; a < 1; a++)
for (;;)
{
i = b & ((b ^ 1) & 83647) ? b : b - 1;
g = 1 ? i : 0;
e = j[0];
if (c)
break;
return 0;
}
}
}
}
int
main ()
{
fn1 ();
if (g != -1)
__builtin_abort ();
return 0;
}