Fix mark_all_labels vs cfglayout mode.

* jump.c (maybe_propagate_label_ref): Split out of...
        (mark_all_labels): ... here.  Do not attempt label_ref
        propagation while in cfglayout mode.

From-SVN: r176663
This commit is contained in:
Richard Henderson 2011-07-22 16:19:25 -07:00 committed by Richard Henderson
parent a0a22423b0
commit 5f93b30abd
2 changed files with 89 additions and 67 deletions

View File

@ -1,3 +1,9 @@
2011-07-22 Richard Henderson <rth@redhat.com>
* jump.c (maybe_propagate_label_ref): Split out of...
(mark_all_labels): ... here. Do not attempt label_ref
propagation while in cfglayout mode.
2011-07-22 Jakub Jelinek <jakub@redhat.com>
* dwarf2out.c (struct macinfo_struct): Change code to unsigned char.

View File

@ -200,6 +200,54 @@ init_label_info (rtx f)
}
}
/* A subroutine of mark_all_labels. Trivially propagate a simple label
load into a jump_insn that uses it. */
static void
maybe_propagate_label_ref (rtx jump_insn, rtx prev_nonjump_insn)
{
rtx label_note, pc, pc_src;
pc = pc_set (jump_insn);
pc_src = pc != NULL ? SET_SRC (pc) : NULL;
label_note = find_reg_note (prev_nonjump_insn, REG_LABEL_OPERAND, NULL);
/* If the previous non-jump insn sets something to a label,
something that this jump insn uses, make that label the primary
target of this insn if we don't yet have any. That previous
insn must be a single_set and not refer to more than one label.
The jump insn must not refer to other labels as jump targets
and must be a plain (set (pc) ...), maybe in a parallel, and
may refer to the item being set only directly or as one of the
arms in an IF_THEN_ELSE. */
if (label_note != NULL && pc_src != NULL)
{
rtx label_set = single_set (prev_nonjump_insn);
rtx label_dest = label_set != NULL ? SET_DEST (label_set) : NULL;
if (label_set != NULL
/* The source must be the direct LABEL_REF, not a
PLUS, UNSPEC, IF_THEN_ELSE etc. */
&& GET_CODE (SET_SRC (label_set)) == LABEL_REF
&& (rtx_equal_p (label_dest, pc_src)
|| (GET_CODE (pc_src) == IF_THEN_ELSE
&& (rtx_equal_p (label_dest, XEXP (pc_src, 1))
|| rtx_equal_p (label_dest, XEXP (pc_src, 2))))))
{
/* The CODE_LABEL referred to in the note must be the
CODE_LABEL in the LABEL_REF of the "set". We can
conveniently use it for the marker function, which
requires a LABEL_REF wrapping. */
gcc_assert (XEXP (label_note, 0) == XEXP (SET_SRC (label_set), 0));
mark_jump_label_1 (label_set, jump_insn, false, true);
gcc_assert (JUMP_LABEL (jump_insn) == XEXP (label_note, 0));
}
}
}
/* Mark the label each jump jumps to.
Combine consecutive labels, and count uses of labels. */
@ -207,85 +255,31 @@ static void
mark_all_labels (rtx f)
{
rtx insn;
rtx prev_nonjump_insn = NULL;
for (insn = f; insn; insn = NEXT_INSN (insn))
if (NONDEBUG_INSN_P (insn))
{
mark_jump_label (PATTERN (insn), insn, 0);
/* If the previous non-jump insn sets something to a label,
something that this jump insn uses, make that label the primary
target of this insn if we don't yet have any. That previous
insn must be a single_set and not refer to more than one label.
The jump insn must not refer to other labels as jump targets
and must be a plain (set (pc) ...), maybe in a parallel, and
may refer to the item being set only directly or as one of the
arms in an IF_THEN_ELSE. */
if (! INSN_DELETED_P (insn)
&& JUMP_P (insn)
&& JUMP_LABEL (insn) == NULL)
{
rtx label_note = NULL;
rtx pc = pc_set (insn);
rtx pc_src = pc != NULL ? SET_SRC (pc) : NULL;
if (prev_nonjump_insn != NULL)
label_note
= find_reg_note (prev_nonjump_insn, REG_LABEL_OPERAND, NULL);
if (label_note != NULL && pc_src != NULL)
{
rtx label_set = single_set (prev_nonjump_insn);
rtx label_dest
= label_set != NULL ? SET_DEST (label_set) : NULL;
if (label_set != NULL
/* The source must be the direct LABEL_REF, not a
PLUS, UNSPEC, IF_THEN_ELSE etc. */
&& GET_CODE (SET_SRC (label_set)) == LABEL_REF
&& (rtx_equal_p (label_dest, pc_src)
|| (GET_CODE (pc_src) == IF_THEN_ELSE
&& (rtx_equal_p (label_dest, XEXP (pc_src, 1))
|| rtx_equal_p (label_dest,
XEXP (pc_src, 2))))))
{
/* The CODE_LABEL referred to in the note must be the
CODE_LABEL in the LABEL_REF of the "set". We can
conveniently use it for the marker function, which
requires a LABEL_REF wrapping. */
gcc_assert (XEXP (label_note, 0)
== XEXP (SET_SRC (label_set), 0));
mark_jump_label_1 (label_set, insn, false, true);
gcc_assert (JUMP_LABEL (insn)
== XEXP (SET_SRC (label_set), 0));
}
}
}
else if (! INSN_DELETED_P (insn))
prev_nonjump_insn = insn;
}
else if (LABEL_P (insn))
prev_nonjump_insn = NULL;
/* If we are in cfglayout mode, there may be non-insns between the
basic blocks. If those non-insns represent tablejump data, they
contain label references that we must record. */
if (current_ir_type () == IR_RTL_CFGLAYOUT)
{
basic_block bb;
rtx insn;
FOR_EACH_BB (bb)
{
/* In cfglayout mode, we don't bother with trivial next-insn
propagation of LABEL_REFs into JUMP_LABEL. This will be
handled by other optimizers using better algorithms. */
FOR_BB_INSNS (bb, insn)
{
gcc_assert (! INSN_DELETED_P (insn));
if (NONDEBUG_INSN_P (insn))
mark_jump_label (PATTERN (insn), insn, 0);
}
/* In cfglayout mode, there may be non-insns between the
basic blocks. If those non-insns represent tablejump data,
they contain label references that we must record. */
for (insn = bb->il.rtl->header; insn; insn = NEXT_INSN (insn))
if (INSN_P (insn))
{
gcc_assert (JUMP_TABLE_DATA_P (insn));
mark_jump_label (PATTERN (insn), insn, 0);
}
for (insn = bb->il.rtl->footer; insn; insn = NEXT_INSN (insn))
if (INSN_P (insn))
{
@ -294,6 +288,28 @@ mark_all_labels (rtx f)
}
}
}
else
{
rtx prev_nonjump_insn = NULL;
for (insn = f; insn; insn = NEXT_INSN (insn))
{
if (INSN_DELETED_P (insn))
;
else if (LABEL_P (insn))
prev_nonjump_insn = NULL;
else if (NONDEBUG_INSN_P (insn))
{
mark_jump_label (PATTERN (insn), insn, 0);
if (JUMP_P (insn))
{
if (JUMP_LABEL (insn) == NULL && prev_nonjump_insn != NULL)
maybe_propagate_label_ref (insn, prev_nonjump_insn);
}
else
prev_nonjump_insn = insn;
}
}
}
}
/* Given a comparison (CODE ARG0 ARG1), inside an insn, INSN, return a code