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> 2011-07-22 Jakub Jelinek <jakub@redhat.com>
* dwarf2out.c (struct macinfo_struct): Change code to unsigned char. * dwarf2out.c (struct macinfo_struct): Change code to unsigned char.

View File

@ -200,19 +200,17 @@ init_label_info (rtx f)
} }
} }
/* Mark the label each jump jumps to. /* A subroutine of mark_all_labels. Trivially propagate a simple label
Combine consecutive labels, and count uses of labels. */ load into a jump_insn that uses it. */
static void static void
mark_all_labels (rtx f) maybe_propagate_label_ref (rtx jump_insn, rtx prev_nonjump_insn)
{ {
rtx insn; rtx label_note, pc, pc_src;
rtx prev_nonjump_insn = NULL;
for (insn = f; insn; insn = NEXT_INSN (insn)) pc = pc_set (jump_insn);
if (NONDEBUG_INSN_P (insn)) pc_src = pc != NULL ? SET_SRC (pc) : NULL;
{ label_note = find_reg_note (prev_nonjump_insn, REG_LABEL_OPERAND, NULL);
mark_jump_label (PATTERN (insn), insn, 0);
/* If the previous non-jump insn sets something to a label, /* If the previous non-jump insn sets something to a label,
something that this jump insn uses, make that label the primary something that this jump insn uses, make that label the primary
@ -222,23 +220,11 @@ mark_all_labels (rtx f)
and must be a plain (set (pc) ...), maybe in a parallel, and 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 may refer to the item being set only directly or as one of the
arms in an IF_THEN_ELSE. */ 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) if (label_note != NULL && pc_src != NULL)
{ {
rtx label_set = single_set (prev_nonjump_insn); rtx label_set = single_set (prev_nonjump_insn);
rtx label_dest rtx label_dest = label_set != NULL ? SET_DEST (label_set) : NULL;
= label_set != NULL ? SET_DEST (label_set) : NULL;
if (label_set != NULL if (label_set != NULL
/* The source must be the direct LABEL_REF, not a /* The source must be the direct LABEL_REF, not a
@ -247,45 +233,53 @@ mark_all_labels (rtx f)
&& (rtx_equal_p (label_dest, pc_src) && (rtx_equal_p (label_dest, pc_src)
|| (GET_CODE (pc_src) == IF_THEN_ELSE || (GET_CODE (pc_src) == IF_THEN_ELSE
&& (rtx_equal_p (label_dest, XEXP (pc_src, 1)) && (rtx_equal_p (label_dest, XEXP (pc_src, 1))
|| rtx_equal_p (label_dest, || rtx_equal_p (label_dest, XEXP (pc_src, 2))))))
XEXP (pc_src, 2))))))
{ {
/* The CODE_LABEL referred to in the note must be the /* The CODE_LABEL referred to in the note must be the
CODE_LABEL in the LABEL_REF of the "set". We can CODE_LABEL in the LABEL_REF of the "set". We can
conveniently use it for the marker function, which conveniently use it for the marker function, which
requires a LABEL_REF wrapping. */ requires a LABEL_REF wrapping. */
gcc_assert (XEXP (label_note, 0) gcc_assert (XEXP (label_note, 0) == XEXP (SET_SRC (label_set), 0));
== XEXP (SET_SRC (label_set), 0));
mark_jump_label_1 (label_set, insn, false, true); mark_jump_label_1 (label_set, jump_insn, false, true);
gcc_assert (JUMP_LABEL (insn)
== XEXP (SET_SRC (label_set), 0)); gcc_assert (JUMP_LABEL (jump_insn) == XEXP (label_note, 0));
} }
} }
} }
else if (! INSN_DELETED_P (insn))
prev_nonjump_insn = insn; /* Mark the label each jump jumps to.
} Combine consecutive labels, and count uses of labels. */
else if (LABEL_P (insn))
prev_nonjump_insn = NULL; static void
mark_all_labels (rtx f)
{
rtx insn;
/* 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) if (current_ir_type () == IR_RTL_CFGLAYOUT)
{ {
basic_block bb; basic_block bb;
rtx insn;
FOR_EACH_BB (bb) 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)) for (insn = bb->il.rtl->header; insn; insn = NEXT_INSN (insn))
if (INSN_P (insn)) if (INSN_P (insn))
{ {
gcc_assert (JUMP_TABLE_DATA_P (insn)); gcc_assert (JUMP_TABLE_DATA_P (insn));
mark_jump_label (PATTERN (insn), insn, 0); mark_jump_label (PATTERN (insn), insn, 0);
} }
for (insn = bb->il.rtl->footer; insn; insn = NEXT_INSN (insn)) for (insn = bb->il.rtl->footer; insn; insn = NEXT_INSN (insn))
if (INSN_P (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 /* Given a comparison (CODE ARG0 ARG1), inside an insn, INSN, return a code