df.h (df_insn_delete): Adjust prototype.

* df.h (df_insn_delete): Adjust prototype.
	* emit-rtl.c (remove_insn): Pass a basic block to df_insn_delete
	and let it decide whether mark the basic block dirty.
	(set_insn_deleted): Only pass INSN_P insns to df_insn_delete.
	* df-scan.c (df_insn_info_delete): New helper function, split
	off from df_insn_delete.
	(df_scan_free_bb_info): Use it.
	(df_insn_rescan, df_insn_rescan_all, df_process_deferred_rescans):
	Likewise.
	(df_insn_delete): Likewise.  Take insn rtx as argument.  Verify
	that the insn is actually an insn and it has a non-NULL basic block.
	Do not mark basic block dirty if only deleting a DEBUG_INSN.

From-SVN: r196977
This commit is contained in:
Steven Bosscher 2013-03-22 16:37:00 +00:00
parent f13a8728c1
commit 80eb8028eb
3 changed files with 84 additions and 49 deletions

View File

@ -142,6 +142,8 @@ static void df_install_ref (df_ref, struct df_reg_info *,
static int df_ref_compare (const void *, const void *);
static int df_mw_compare (const void *, const void *);
static void df_insn_info_delete (unsigned int);
/* Indexed by hardware reg number, is true if that register is ever
used in the current function.
@ -277,8 +279,7 @@ df_scan_free_bb_info (basic_block bb, void *vbb_info)
FOR_BB_INSNS (bb, insn)
{
if (INSN_P (insn))
/* Record defs within INSN. */
df_insn_delete (bb, INSN_UID (insn));
df_insn_info_delete (INSN_UID (insn));
}
if (bb_index < df_scan->block_info_size)
@ -1087,44 +1088,15 @@ df_mw_hardreg_chain_delete (struct df_mw_hardreg **hardregs)
}
/* Delete all of the refs information from INSN. BB must be passed in
except when called from df_process_deferred_rescans to mark the block
as dirty. */
/* Delete all of the refs information from the insn with UID.
Internal helper for df_insn_delete, df_insn_rescan, and other
df-scan routines that don't have to work in deferred mode
and do not have to mark basic blocks for re-processing. */
void
df_insn_delete (basic_block bb, unsigned int uid)
static void
df_insn_info_delete (unsigned int uid)
{
struct df_insn_info *insn_info = NULL;
if (!df)
return;
df_grow_bb_info (df_scan);
df_grow_reg_info ();
/* The block must be marked as dirty now, rather than later as in
df_insn_rescan and df_notes_rescan because it may not be there at
rescanning time and the mark would blow up. */
if (bb)
df_set_bb_dirty (bb);
insn_info = DF_INSN_UID_SAFE_GET (uid);
/* The client has deferred rescanning. */
if (df->changeable_flags & DF_DEFER_INSN_RESCAN)
{
if (insn_info)
{
bitmap_clear_bit (&df->insns_to_rescan, uid);
bitmap_clear_bit (&df->insns_to_notes_rescan, uid);
bitmap_set_bit (&df->insns_to_delete, uid);
}
if (dump_file)
fprintf (dump_file, "deferring deletion of insn with uid = %d.\n", uid);
return;
}
if (dump_file)
fprintf (dump_file, "deleting insn with uid = %d.\n", uid);
struct df_insn_info *insn_info = DF_INSN_UID_SAFE_GET (uid);
bitmap_clear_bit (&df->insns_to_delete, uid);
bitmap_clear_bit (&df->insns_to_rescan, uid);
@ -1160,6 +1132,67 @@ df_insn_delete (basic_block bb, unsigned int uid)
}
}
/* Delete all of the refs information from INSN, either right now
or marked for later in deferred mode. */
void
df_insn_delete (rtx insn)
{
unsigned int uid;
basic_block bb;
gcc_checking_assert (INSN_P (insn));
if (!df)
return;
uid = INSN_UID (insn);
bb = BLOCK_FOR_INSN (insn);
/* ??? bb can be NULL after pass_free_cfg. At that point, DF should
not exist anymore (as mentioned in df-core.c: "The only requirement
[for DF] is that there be a correct control flow graph." Clearly
that isn't the case after pass_free_cfg. But DF is freed much later
because some back-ends want to use DF info even though the CFG is
already gone. It's not clear to me whether that is safe, actually.
In any case, we expect BB to be non-NULL at least up to register
allocation, so disallow a non-NULL BB up to there. Not perfect
but better than nothing... */
gcc_checking_assert (bb != NULL || reload_completed);
df_grow_bb_info (df_scan);
df_grow_reg_info ();
/* The block must be marked as dirty now, rather than later as in
df_insn_rescan and df_notes_rescan because it may not be there at
rescanning time and the mark would blow up.
DEBUG_INSNs do not make a block's data flow solution dirty (at
worst the LUIDs are no longer contiguous). */
if (bb != NULL && NONDEBUG_INSN_P (insn))
df_set_bb_dirty (bb);
/* The client has deferred rescanning. */
if (df->changeable_flags & DF_DEFER_INSN_RESCAN)
{
struct df_insn_info *insn_info = DF_INSN_UID_SAFE_GET (uid);
if (insn_info)
{
bitmap_clear_bit (&df->insns_to_rescan, uid);
bitmap_clear_bit (&df->insns_to_notes_rescan, uid);
bitmap_set_bit (&df->insns_to_delete, uid);
}
if (dump_file)
fprintf (dump_file, "deferring deletion of insn with uid = %d.\n", uid);
return;
}
if (dump_file)
fprintf (dump_file, "deleting insn with uid = %d.\n", uid);
df_insn_info_delete (uid);
}
/* Free all of the refs and the mw_hardregs in COLLECTION_REC. */
@ -1262,7 +1295,7 @@ df_insn_rescan (rtx insn)
/* There's change - we need to delete the existing info.
Since the insn isn't moved, we can salvage its LUID. */
luid = DF_INSN_LUID (insn);
df_insn_delete (NULL, uid);
df_insn_info_delete (uid);
df_insn_create_insn_record (insn);
DF_INSN_LUID (insn) = luid;
}
@ -1345,7 +1378,7 @@ df_insn_rescan_debug_internal (rtx insn)
/* Rescan all of the insns in the function. Note that the artificial
uses and defs are not touched. This function will destroy def-se
uses and defs are not touched. This function will destroy def-use
or use-def chains. */
void
@ -1377,7 +1410,7 @@ df_insn_rescan_all (void)
{
struct df_insn_info *insn_info = DF_INSN_UID_SAFE_GET (uid);
if (insn_info)
df_insn_delete (NULL, uid);
df_insn_info_delete (uid);
}
bitmap_clear (&tmp);
@ -1434,7 +1467,7 @@ df_process_deferred_rescans (void)
{
struct df_insn_info *insn_info = DF_INSN_UID_SAFE_GET (uid);
if (insn_info)
df_insn_delete (NULL, uid);
df_insn_info_delete (uid);
}
bitmap_copy (&tmp, &df->insns_to_rescan);

View File

@ -996,7 +996,7 @@ extern df_ref df_ref_create (rtx, rtx *, rtx,basic_block,
extern void df_uses_create (rtx *, rtx, int);
extern void df_ref_remove (df_ref);
extern struct df_insn_info * df_insn_create_insn_record (rtx);
extern void df_insn_delete (basic_block, unsigned int);
extern void df_insn_delete (rtx);
extern void df_bb_refs_record (int, bool);
extern bool df_insn_rescan (rtx);
extern bool df_insn_rescan_debug_internal (rtx);

View File

@ -3964,7 +3964,8 @@ add_insn_before (rtx insn, rtx before, basic_block bb)
void
set_insn_deleted (rtx insn)
{
df_insn_delete (BLOCK_FOR_INSN (insn), INSN_UID (insn));
if (INSN_P (insn) && !JUMP_TABLE_DATA_P (insn))
df_insn_delete (insn);
PUT_CODE (insn, NOTE);
NOTE_KIND (insn) = NOTE_INSN_DELETED;
}
@ -3979,9 +3980,6 @@ remove_insn (rtx insn)
rtx prev = PREV_INSN (insn);
basic_block bb;
/* Later in the code, the block will be marked dirty. */
df_insn_delete (NULL, INSN_UID (insn));
if (prev)
{
NEXT_INSN (prev) = next;
@ -4032,11 +4030,15 @@ remove_insn (rtx insn)
gcc_assert (stack);
}
/* Invalidate data flow information associated with INSN. */
if (INSN_P (insn) && !JUMP_TABLE_DATA_P (insn))
df_insn_delete (insn);
/* Fix up basic block boundaries, if necessary. */
if (!BARRIER_P (insn)
&& (bb = BLOCK_FOR_INSN (insn)))
{
if (NONDEBUG_INSN_P (insn))
df_set_bb_dirty (bb);
if (BB_HEAD (bb) == insn)
{
/* Never ever delete the basic block note without deleting whole