diff options
author | Steven Bosscher <steven@gcc.gnu.org> | 2013-03-22 16:37:00 +0000 |
---|---|---|
committer | Steven Bosscher <steven@gcc.gnu.org> | 2013-03-22 16:37:00 +0000 |
commit | 80eb8028ebbb183885946c80402b59dcbd002f69 (patch) | |
tree | 763d9ae5800f6d6a19f7446337ea0119f8095e00 | |
parent | f13a8728c143fe1aacc103c38463f19d829c9857 (diff) | |
download | gcc-80eb8028ebbb183885946c80402b59dcbd002f69.zip gcc-80eb8028ebbb183885946c80402b59dcbd002f69.tar.gz gcc-80eb8028ebbb183885946c80402b59dcbd002f69.tar.bz2 |
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
-rw-r--r-- | gcc/df-scan.c | 117 | ||||
-rw-r--r-- | gcc/df.h | 2 | ||||
-rw-r--r-- | gcc/emit-rtl.c | 14 |
3 files changed, 84 insertions, 49 deletions
diff --git a/gcc/df-scan.c b/gcc/df-scan.c index 931fa2c..fdfa931 100644 --- a/gcc/df-scan.c +++ b/gcc/df-scan.c @@ -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); @@ -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); diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 59cd38d..31c1e63 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -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 |