re PR target/63404 (gcc 5 miscompiles linux block layer)

PR target/63404

  * shrink-wrap.c (move_insn_for_shrink_wrap): Don't use single_set.
  Restrict the set of expressions we're willing to move.

From-SVN: r216096
This commit is contained in:
Richard Henderson 2014-10-10 08:56:07 -07:00 committed by Richard Henderson
parent fb0ab69706
commit 069d7fc5a4
2 changed files with 72 additions and 23 deletions

View File

@ -1,3 +1,9 @@
2014-10-10 Richard Henderson <rth@redhat.com>
PR target/63404
* shrink-wrap.c (move_insn_for_shrink_wrap): Don't use single_set.
Restrict the set of expressions we're willing to move.
2014-10-10 Jeff Law <law@redhat.com>
* ira.c (struct equivalence): Promote INIT_INSNs field to

View File

@ -176,17 +176,40 @@ move_insn_for_shrink_wrap (basic_block bb, rtx_insn *insn,
basic_block next_block;
edge live_edge;
/* Look for a simple register copy. */
set = single_set (insn);
if (!set)
/* Look for a simple register assignment. We don't use single_set here
because we can't deal with any CLOBBERs, USEs, or REG_UNUSED secondary
destinations. */
if (!INSN_P (insn))
return false;
set = PATTERN (insn);
if (GET_CODE (set) != SET)
return false;
src = SET_SRC (set);
dest = SET_DEST (set);
if (!REG_P (src))
/* For the destination, we want only a register. Also disallow STACK
or FRAME related adjustments. They are likely part of the prologue,
so keep them in the entry block. */
if (!REG_P (dest)
|| dest == stack_pointer_rtx
|| dest == frame_pointer_rtx
|| dest == hard_frame_pointer_rtx)
return false;
/* For the source, we want one of:
(1) A (non-overlapping) register
(2) A constant,
(3) An expression involving no more than one register.
That last point comes from the code following, which was originally
written to handle only register move operations, and still only handles
a single source register when checking for overlaps. Happily, the
same checks can be applied to expressions like (plus reg const). */
if (CONSTANT_P (src))
;
else if (!REG_P (src))
{
unsigned int reg_num = 0;
unsigned int nonconstobj_num = 0;
rtx src_inner = NULL_RTX;
if (can_throw_internal (insn))
@ -196,30 +219,50 @@ move_insn_for_shrink_wrap (basic_block bb, rtx_insn *insn,
FOR_EACH_SUBRTX_VAR (iter, array, src, ALL)
{
rtx x = *iter;
if (REG_P (x))
switch (GET_RTX_CLASS (GET_CODE (x)))
{
reg_num++;
src_inner = x;
case RTX_CONST_OBJ:
case RTX_COMPARE:
case RTX_COMM_COMPARE:
case RTX_BIN_ARITH:
case RTX_COMM_ARITH:
case RTX_UNARY:
case RTX_TERNARY:
/* Constant or expression. Continue. */
break;
case RTX_OBJ:
case RTX_EXTRA:
switch (GET_CODE (x))
{
case UNSPEC:
case SUBREG:
case STRICT_LOW_PART:
case PC:
/* Ok. Continue. */
break;
case REG:
/* Fail if we see a second inner register. */
if (src_inner != NULL)
return false;
src_inner = x;
break;
default:
return false;
}
break;
default:
return false;
}
else if (!CONSTANT_P (x) && OBJECT_P (x))
nonconstobj_num++;
}
if (nonconstobj_num > 0
|| reg_num > 1)
src = NULL_RTX;
else if (reg_num == 1)
if (src_inner != NULL)
src = src_inner;
}
if (!REG_P (dest) || src == NULL_RTX
/* STACK or FRAME related adjustment might be part of prologue.
So keep them in the entry block. */
|| dest == stack_pointer_rtx
|| dest == frame_pointer_rtx
|| dest == hard_frame_pointer_rtx)
return false;
/* Make sure that the source register isn't defined later in BB. */
if (REG_P (src))
{