Commit 57d6c446 by Steven Bosscher

jump.c (reset_insn_reg_label_operand_notes): New function, split out from ...


	* jump.c (reset_insn_reg_label_operand_notes): New function,
	split out from ...
	(init_label_info): ... here.  Reset LABEL_NUSES in cfglayout mode.
	* cfgcleanup.c (delete_dead_jump_tables_between): New function,
	split out from ...
	(delete_dead_jumptables): ... here.  Handle cfglayout mode.
	(cleanup_cfg): Delete dead jump tables in cfglayout mode if an
	expensive CFG cleanup is called for.
	* cfgrtl.c (fixup_reorder_chain): Remove BARRIERs from fallthru paths.
	(cfg_layout_finalize): Delete dead jump tables before re-building
	the insns chain.
	* ira.c (ira): Rebuild jump labels *after* deleting unreachable
	basic blocks, not before.
	* loop-init.c (rtl_loop_done): Call for an expensive CFG cleanup.

	* modulo-sched.c (sms_schedule): Do not look for BARRIERs in the
	insns chain of a scheduling extended basic block, they cannot appear
	there in cfglayout mode.

From-SVN: r205337
parent 58b07297
2013-11-24 Steven Bosscher <steven@gcc.gnu.org>
* jump.c (reset_insn_reg_label_operand_notes): New function,
split out from ...
(init_label_info): ... here. Reset LABEL_NUSES in cfglayout mode.
* cfgcleanup.c (delete_dead_jump_tables_between): New function,
split out from ...
(delete_dead_jumptables): ... here. Handle cfglayout mode.
(cleanup_cfg): Delete dead jump tables in cfglayout mode if an
expensive CFG cleanup is called for.
* cfgrtl.c (fixup_reorder_chain): Remove BARRIERs from fallthru paths.
(cfg_layout_finalize): Delete dead jump tables before re-building
the insns chain.
* ira.c (ira): Rebuild jump labels *after* deleting unreachable
basic blocks, not before.
* loop-init.c (rtl_loop_done): Call for an expensive CFG cleanup.
* modulo-sched.c (sms_schedule): Do not look for BARRIERs in the
insns chain of a scheduling extended basic block, they cannot appear
there in cfglayout mode.
2013-11-24 Tobias Burnus <burnus@net-b.de>
* doc/invoke.texi (-fsanitize=leak): Add link to the wiki page.
......@@ -2944,40 +2944,65 @@ delete_unreachable_blocks (void)
return changed;
}
/* Look for, and delete, any dead jumptables between START and END. */
static void
delete_dead_jump_tables_between (rtx start, rtx end)
{
rtx insn, next;
for (insn = start; insn != end; insn = next)
{
next = NEXT_INSN (insn);
if (next != NULL_RTX
&& LABEL_P (insn)
&& LABEL_NUSES (insn) == LABEL_PRESERVE_P (insn)
&& JUMP_TABLE_DATA_P (next))
{
rtx label = insn, jump = next;
if (dump_file)
fprintf (dump_file, "Dead jumptable %i removed\n",
INSN_UID (insn));
next = NEXT_INSN (next);
delete_insn (jump);
delete_insn (label);
}
}
}
/* Delete any jump tables never referenced. We can't delete them at the
time of removing tablejump insn as they are referenced by the preceding
insns computing the destination, so we delay deleting and garbagecollect
them once life information is computed. */
time of removing tablejump insn as the label preceding the jump table
data may be referenced by the preceding insns computing the destination.
So we delay deleting and garbage-collect them from time to time, after
a CFG cleanup. */
void
delete_dead_jumptables (void)
{
basic_block bb;
/* A dead jump table does not belong to any basic block. Scan insns
between two adjacent basic blocks. */
/* Label reference count must up-to-date to detect dead jump tables. */
rebuild_jump_labels (get_insns ());
FOR_EACH_BB (bb)
{
rtx insn, next;
for (insn = NEXT_INSN (BB_END (bb));
insn && !NOTE_INSN_BASIC_BLOCK_P (insn);
insn = next)
if (current_ir_type () == IR_RTL_CFGLAYOUT)
{
next = NEXT_INSN (insn);
if (LABEL_P (insn)
&& LABEL_NUSES (insn) == LABEL_PRESERVE_P (insn)
&& JUMP_TABLE_DATA_P (next))
{
rtx label = insn, jump = next;
if (dump_file)
fprintf (dump_file, "Dead jumptable %i removed\n",
INSN_UID (insn));
next = NEXT_INSN (next);
delete_insn (jump);
delete_insn (label);
}
/* Jump tables only appear in the header or footer of BB. */
delete_dead_jump_tables_between (BB_HEADER (bb), NULL_RTX);
delete_dead_jump_tables_between (BB_FOOTER (bb), NULL_RTX);
}
else
{
/* Jump tables are in the insns chain between basic blocks. */
rtx start = NEXT_INSN (BB_END (bb));
rtx end = (bb->next_bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
? NULL_RTX : BB_HEAD (bb->next_bb);
delete_dead_jump_tables_between (start, end);
}
}
}
......@@ -3049,13 +3074,13 @@ cleanup_cfg (int mode)
if (mode & CLEANUP_CROSSJUMP)
remove_fake_exit_edges ();
/* Don't call delete_dead_jumptables in cfglayout mode, because
that function assumes that jump tables are in the insns stream.
But we also don't _have_ to delete dead jumptables in cfglayout
mode because we shouldn't even be looking at things that are
not in a basic block. Dead jumptables are cleaned up when
going out of cfglayout mode. */
if (!(mode & CLEANUP_CFGLAYOUT))
/* Don't always call delete_dead_jumptables in cfglayout mode, because
jump tables can only appear in the headers and footers of basic blocks
and we usually are not interested in anything hiding there.
But if an expensive cleanup is called for, garbage-collect the dead
jump tables to get label reference counts right. This sometimes
allows some labels to be removed and more basic blocks to be merged. */
if (!(mode & CLEANUP_CFGLAYOUT) || (mode & CLEANUP_EXPENSIVE))
delete_dead_jumptables ();
/* ??? We probably do this way too often. */
......
......@@ -3696,10 +3696,10 @@ fixup_reorder_chain (void)
#endif
/* Now add jumps and labels as needed to match the blocks new
outgoing edges. */
outgoing edges. Fixup missing or redundant BARRIERs. */
for (bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb; bb ; bb = (basic_block)
bb->aux)
for (bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb; bb ;
bb = (basic_block) bb->aux)
{
edge e_fall, e_taken, e;
rtx bb_end_insn;
......@@ -3853,13 +3853,26 @@ fixup_reorder_chain (void)
relink_block_chain (/*stay_in_cfglayout_mode=*/false);
/* Annoying special case - jump around dead jumptables left in the code. */
/* Annoying special case - stray barriers left in the code. This happens
if a tablejump is transformed to a simpe or confitional jump, or if a
basic block ending in a tablejump is removed but the jump table itself
is not. */
FOR_EACH_BB (bb)
{
edge e = find_fallthru_edge (bb->succs);
if (e && !can_fallthru (e->src, e->dest))
force_nonfallthru (e);
if (e && e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
{
rtx insn, next;
for (insn = NEXT_INSN (BB_END (e->src));
insn != BB_HEAD (e->dest);
insn = next)
{
next = NEXT_INSN (insn);
if (BARRIER_P (insn))
remove_insn (insn);
}
}
}
/* Ensure goto_locus from edges has some instructions with that locus
......@@ -4273,7 +4286,7 @@ break_superblocks (void)
}
/* Finalize the changes: reorder insn list according to the sequence specified
by aux pointers, enter compensation code, rebuild scope forest. */
by aux pointers, enter compensation code. */
void
cfg_layout_finalize (void)
......@@ -4281,6 +4294,7 @@ cfg_layout_finalize (void)
#ifdef ENABLE_CHECKING
verify_flow_info ();
#endif
delete_dead_jumptables ();
force_one_exit_fallthru ();
rtl_register_cfg_hooks ();
if (reload_completed
......@@ -4291,9 +4305,6 @@ cfg_layout_finalize (void)
fixup_fallthru_exit_predecessor ();
fixup_reorder_chain ();
rebuild_jump_labels (get_insns ());
delete_dead_jumptables ();
#ifdef ENABLE_CHECKING
verify_insn_chain ();
verify_flow_info ();
......
......@@ -5273,9 +5273,9 @@ ira (FILE *f)
if (optimize && rebuild_p)
{
timevar_push (TV_JUMP);
rebuild_jump_labels (get_insns ());
if (purge_all_dead_edges ())
delete_unreachable_blocks ();
rebuild_jump_labels (get_insns ());
timevar_pop (TV_JUMP);
}
......
......@@ -177,6 +177,34 @@ make_pass_cleanup_barriers (gcc::context *ctxt)
}
/* Remove all REG_LABEL_OPERAND notes from INSN.
REG_LABEL_TARGET notes (including the JUMP_LABEL field) are sticky and
not reset here; that way we won't lose association with a label when
e.g. the source for a target register disappears out of reach for targets
that may use jump-target registers. Jump transformations are supposed to
transform any REG_LABEL_TARGET notes. The target label reference in a
branch may disappear from the branch (and from the instruction before it)
for other reasons, like register allocation. */
static void
reset_insn_reg_label_operand_notes (rtx insn)
{
if (INSN_P (insn))
{
rtx note, next;
for (note = REG_NOTES (insn); note; note = next)
{
next = XEXP (note, 1);
if (REG_NOTE_KIND (note) == REG_LABEL_OPERAND
&& ! reg_mentioned_p (XEXP (note, 0), PATTERN (insn)))
remove_note (insn, note);
}
}
}
/* Initialize LABEL_NUSES and JUMP_LABEL fields, add REG_LABEL_TARGET
for remaining targets for JUMP_P. Delete any REG_LABEL_OPERAND
notes whose labels don't occur in the insn any more. */
......@@ -186,32 +214,38 @@ init_label_info (rtx f)
{
rtx insn;
for (insn = f; insn; insn = NEXT_INSN (insn))
if (current_ir_type () == IR_RTL_CFGLAYOUT)
{
if (LABEL_P (insn))
LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
/* REG_LABEL_TARGET notes (including the JUMP_LABEL field) are
sticky and not reset here; that way we won't lose association
with a label when e.g. the source for a target register
disappears out of reach for targets that may use jump-target
registers. Jump transformations are supposed to transform
any REG_LABEL_TARGET notes. The target label reference in a
branch may disappear from the branch (and from the
instruction before it) for other reasons, like register
allocation. */
if (INSN_P (insn))
basic_block bb;
FOR_EACH_BB (bb)
{
rtx note, next;
/* Labels only appear between BB_HEAD and the basic block note,
and in the basic block header and footer. */
for (insn = BB_HEAD (bb);
insn && LABEL_P (insn);
insn = NEXT_INSN (insn))
LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
for (insn = BB_HEADER (bb); insn; insn = NEXT_INSN (insn))
if (LABEL_P (insn))
LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
for (insn = BB_FOOTER (bb); insn; insn = NEXT_INSN (insn))
if (LABEL_P (insn))
LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
for (note = REG_NOTES (insn); note; note = next)
{
next = XEXP (note, 1);
if (REG_NOTE_KIND (note) == REG_LABEL_OPERAND
&& ! reg_mentioned_p (XEXP (note, 0), PATTERN (insn)))
remove_note (insn, note);
}
FOR_BB_INSNS (bb, insn)
if (INSN_P (insn))
reset_insn_reg_label_operand_notes (insn);
}
}
else
{
for (insn = f; insn; insn = NEXT_INSN (insn))
{
if (LABEL_P (insn))
LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
if (INSN_P (insn))
reset_insn_reg_label_operand_notes (insn);
}
}
}
......
......@@ -415,7 +415,7 @@ rtl_loop_done (void)
loop_optimizer_finalize ();
free_dominance_info (CDI_DOMINATORS);
cleanup_cfg (0);
cleanup_cfg (CLEANUP_EXPENSIVE);
if (dump_file)
{
dump_reg_info (dump_file);
......
......@@ -1471,7 +1471,7 @@ sms_schedule (void)
continue;
}
/* Don't handle BBs with calls or barriers
/* Don't handle BBs with calls
or !single_set with the exception of instructions that include
count_reg---these instructions are part of the control part
that do-loop recognizes.
......@@ -1481,7 +1481,6 @@ sms_schedule (void)
rtx set;
if (CALL_P (insn)
|| BARRIER_P (insn)
|| (NONDEBUG_INSN_P (insn) && !JUMP_P (insn)
&& !single_set (insn) && GET_CODE (PATTERN (insn)) != USE
&& !reg_mentioned_p (count_reg, insn))
......@@ -1496,8 +1495,6 @@ sms_schedule (void)
{
if (CALL_P (insn))
fprintf (dump_file, "SMS loop-with-call\n");
else if (BARRIER_P (insn))
fprintf (dump_file, "SMS loop-with-barrier\n");
else if ((NONDEBUG_INSN_P (insn) && !JUMP_P (insn)
&& !single_set (insn) && GET_CODE (PATTERN (insn)) != USE))
fprintf (dump_file, "SMS loop-with-not-single-set\n");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment