diff options
author | Daniel Berlin <dberlin@dberlin.org> | 2006-05-19 21:18:23 +0000 |
---|---|---|
committer | Kenneth Zadeck <zadeck@gcc.gnu.org> | 2006-05-19 21:18:23 +0000 |
commit | 23249ac43c6d4d9dde16347bc44dc757e41f1d8d (patch) | |
tree | 46c1322fa64c2c9e1ac1a3a67befc79d25478490 /gcc/df-problems.c | |
parent | d593cb3da7ebc6246c3da0ef3b46292b20d9f233 (diff) | |
download | gcc-23249ac43c6d4d9dde16347bc44dc757e41f1d8d.zip gcc-23249ac43c6d4d9dde16347bc44dc757e41f1d8d.tar.gz gcc-23249ac43c6d4d9dde16347bc44dc757e41f1d8d.tar.bz2 |
re PR rtl-optimization/26855 (ICE in add_deps_for_def with -fmodulo-sched -maltivec)
2006-05-19 Daniel Berlin <dberlin@dberlin.org>
Kenneth Zadeck <zadeck@naturalbridge.com>
PR rtl-optimization/26855
* df-scan.c (mw_reg_pool, mw_link_pool): New allocation pools for
multiword refs.
(df_scan_alloc): Added code to properly handle multiword hard
registers and add all_blocks parameter.
(df_scan_free_internal, df_insn_refs_delete, df_ref_record): Added
code to properly handle multiword hard registers.
(df_rescan_blocks): Added code to remove deleted blocks from
bitmap.
(df_ref_create_structure, df_ref_record): Added code to properly
handle subregs.
(df_ref_record_1): Changed DF_REF_CLOBBER into DF_REF_MUST_CLOBBER
and set DF_REF_PARTIAL.
(df_defs_record): Changed DF_REF_CLOBBER into DF_REF_MUST_CLOBBER.
(df_uses_record): Added DF_REF_PARTIAL for subreg.
(df_scan_add_problem): Added flags parameter.
(df_ref_create_structure): Changed switching structure.
(df_bb_refs_record): Fixed case where duplicate artificial refs
were created. Changed location of flags.
(df_record_entry_block_defs): Added code to make stack pointer
live in entry block. Refined cases where frame pointer is needed.
Changed location of flags.
(df_record_exit_block_uses, df_insn_refs_record): Changed location of flags.
(df_set_state): Removed function.
(df_grow_reg_info, df_reg_chain_unlink, df_ref_remove,
df_insn_create_insn_record, df_insn_refs_delete,
df_ref_create_structure): Formatting changes.
* df-core.c (df_mvs_dump, df_set_flags, df_clear_flags,
df_delete_basic_block): New function.
(df_init): Changed location of flags.
(df_add_problem): Added flags parameter and the way flags are
processed.
(df_insn_uid_debug, df_ref_debug, debug_df_defno, debug_df_ref,
debug_df_chain): Improved debugging output.
(df_insn_debug, df_insn_uid_debug): Added multiword reg support.
(df_refs_chain_dump): Removed df parameter.
(df_iterative_dataflow): Added consistency check.
(df_prune_to_subcfg): Made public.
(df_analyze_problem): Added blocks_to_init parameter and made
public.
(df_ref_record, df_bb_refs_record, df_mark_reg,
df_record_exit_block_uses): Whitespace changes.
(df_dump): Whitespace changes.
* df.h: Some reordering to remove forward references.
(df_ref_flags.DF_REF_MW_HARDREG, DF_REF_PARTIAL,
DF_REF_MUST_CLOBBER, DF_REF_MAY_CLOBBER): New fields.
(df_ref_flags.DF_REF_CLOBBER): Deleted field.
(dataflow.flags): New field.
(df.flag): Deleted field.
(df_alloc_function): Added additional bitmap parameter.
(df_dependent_problem_function): New type.
(df_problem.changeable_flags): New field.
(df_ref_flags.DF_REF_DIES_AFTER_THIS_USE, DF_SCAN_INITIAL,
DF_SCAN_GLOBAL, DF_SCAN_POST_ALLOC, df_state): Removed.
(df_mw_hardreg): New struct.
(DF_INSN_UID_MWS): New macro.
(df_refs_chain_dump, df_ref_debug, df_chain_dump): Removed df
parameter.
(df_add_problem, df_ru_add_problem, df_rd_add_problem,
df_lr_add_problem, df_ur_add_problem, df_urec_add_problem,
df_ri_add_problem, df_scan_add_problem): Added flags parameter.
(df_set_state): Removed function.
(df_set_flags, df_clear_flags, df_delete_basic_block) New functions.
* df-problems.c (df_chain_dump): Removed df parameter.
(df_ru_alloc, df_rd_alloc, df_lr_alloc, df_ur_alloc,
df_urec_alloc, df_chain_alloc, df_ri_alloc): Added all blocks
parameter.
(df_ru_alloc, df_rd_alloc): Now resets all blocks.
(df_rd_bb_local_compute_process_def, df_ur_bb_local_compute,
df_chain_create_bb, df_create_unused_note, df_ri_bb_compute):
Split DF_REF_CLOBBER into DF_REF_MAY_CLOBBER and
DF_REF_MUST_CLOBBER cases.
(df_ru_bb_local_compute_process_def,
df_rd_bb_local_compute_process_def, df_lr_bb_local_compute,
df_lr_bb_local_compute, df_ur_bb_local_compute,
df_chain_create_bb): Made subreg aware.
(df_ru_bb_local_compute, df_rd_bb_local_compute,
df_lr_bb_local_compute, df_lr_bb_local_compute,
df_chain_create_bb): Cleanup to use proper macros.
(df_ur_local_finalize, df_urec_local_finalize): Removed unnecessary
code to fixup bitvectors.
(df_ri_alloc): Cleared lifetime.
(df_ignore_stack_reg, df_kill_notes, df_set_notes_for_mw,
df_create_unused_note): New function.
(df_ri_bb_compute, df_ri_compute): Added code to create/update
REG_DEAD and REG_UNUSED notes as well as register information.
(df_ru_dump, df_rd_dump, df_lr_dump, df_ur_dump, df_urec_dump,
df_chains_dump): Fixed crash if problem was never run.
(df_ru_add_problem, df_rd_add_problem, df_lr_add_problem,
df_ur_add_problem, df_urec_add_problem, df_chain_add_problem,
df_ri_add_problem): Processes flags in uniform manner.
(df_ru_alloc, df_ru_local_compute, df_ru_confluence_n, df_ru_free,
df_ru_dump, df_rd_local_compute, df_rd_confluence_n, df_rd_free,
df_rd_dump, df_urec_free_bb_info): Formatting changes.
(df_ru_free_bb_info, df_ru_bb_local_compute, df_ru_dump,
df_rd_free_bb_info, df_rd_bb_local_compute_process_def,
df_rd_bb_local_compute, df_rd_dump, df_lr_free_bb_info,
df_lr_bb_local_compute, df_lr_local_compute, df_ur_free_bb_info,
df_ur_dump, df_urec_free_bb_info, df_urec_dump,
df_chain_create_bb, df_ri_bb_compute): Whitespace changes.
* modulo-sched.c (sms_schedule): Added flag parameter to calls.
* see.c (see_initialize_data): Ditto.
* final.c (rest_of_clean_state) Added regstack_completed.
* rtl.h (regstack_completed): Ditto.
* reg-stack.c (regstack_completed): Ditto.
From-SVN: r113915
Diffstat (limited to 'gcc/df-problems.c')
-rw-r--r-- | gcc/df-problems.c | 998 |
1 files changed, 749 insertions, 249 deletions
diff --git a/gcc/df-problems.c b/gcc/df-problems.c index 4f5f2e1..8c5ed6d 100644 --- a/gcc/df-problems.c +++ b/gcc/df-problems.c @@ -43,30 +43,23 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "timevar.h" #include "df.h" #include "vecprim.h" +#include "except.h" + +#if 0 +#define REG_DEAD_DEBUGGING +#endif #define DF_SPARSE_THRESHOLD 32 static bitmap seen_in_block = NULL; static bitmap seen_in_insn = NULL; +static void df_ri_dump (struct dataflow *, FILE *); /*---------------------------------------------------------------------------- Public functions access functions for the dataflow problems. ----------------------------------------------------------------------------*/ -/* Get the instance of the problem that DFLOW is dependent on. */ - -struct dataflow * -df_get_dependent_problem (struct dataflow *dflow) -{ - struct df *df = dflow->df; - struct df_problem *dependent_problem = dflow->problem->dependent_problem; - - gcc_assert (dependent_problem); - return df->problems_by_index[dependent_problem->id]; -} - - /* Create a du or ud chain from SRC to DST and link it into SRC. */ struct df_link * @@ -207,7 +200,7 @@ df_grow_bb_info (struct dataflow *dflow) /* Dump a def-use or use-def chain for REF to FILE. */ void -df_chain_dump (struct df *df ATTRIBUTE_UNUSED, struct df_link *link, FILE *file) +df_chain_dump (struct df_link *link, FILE *file) { fprintf (file, "{ "); for (; link; link = link->next) @@ -346,21 +339,23 @@ df_ru_free_bb_info (struct dataflow *dflow, not touched unless the block is new. */ static void -df_ru_alloc (struct dataflow *dflow, bitmap blocks_to_rescan) +df_ru_alloc (struct dataflow *dflow, + bitmap blocks_to_rescan ATTRIBUTE_UNUSED, + bitmap all_blocks) { unsigned int bb_index; bitmap_iterator bi; unsigned int reg_size = max_reg_num (); - if (! dflow->block_pool) + if (!dflow->block_pool) dflow->block_pool = create_alloc_pool ("df_ru_block pool", sizeof (struct df_ru_bb_info), 50); if (dflow->problem_data) { unsigned int i; - struct df_ru_problem_data *problem_data = - (struct df_ru_problem_data *) dflow->problem_data; + struct df_ru_problem_data *problem_data + = (struct df_ru_problem_data *) dflow->problem_data; for (i = 0; i < problem_data->use_sites_size; i++) { @@ -401,7 +396,7 @@ df_ru_alloc (struct dataflow *dflow, bitmap blocks_to_rescan) we have to process all of the blocks before doing the analysis. */ - EXECUTE_IF_SET_IN_BITMAP (blocks_to_rescan, 0, bb_index, bi) + EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi) { struct df_ru_bb_info *bb_info = df_ru_get_bb_info (dflow, bb_index); if (bb_info) @@ -435,7 +430,10 @@ df_ru_bb_local_compute_process_def (struct dataflow *dflow, struct df *df = dflow->df; while (def) { - if (top_flag == (DF_REF_FLAGS (def) & DF_REF_AT_TOP)) + if ((top_flag == (DF_REF_FLAGS (def) & DF_REF_AT_TOP)) + /* If the def is to only part of the reg, it is as if it did + not happen, since some of the bits may get thru. */ + && (!(DF_REF_FLAGS (def) & DF_REF_PARTIAL))) { unsigned int regno = DF_REF_REGNO (def); unsigned int begin = DF_REG_USE_GET (df, regno)->begin; @@ -453,10 +451,10 @@ df_ru_bb_local_compute_process_def (struct dataflow *dflow, } else { - struct df_ru_problem_data * problem_data = - (struct df_ru_problem_data *)dflow->problem_data; - bitmap uses = - df_ref_bitmap (problem_data->use_sites, regno, + struct df_ru_problem_data * problem_data + = (struct df_ru_problem_data *)dflow->problem_data; + bitmap uses + = df_ref_bitmap (problem_data->use_sites, regno, begin, n_uses); bitmap_ior_into (bb_info->kill, uses); bitmap_and_compl_into (bb_info->gen, uses); @@ -519,18 +517,18 @@ df_ru_bb_local_compute (struct dataflow *dflow, unsigned int bb_index) FOR_BB_INSNS (bb, insn) { unsigned int uid = INSN_UID (insn); - if (! INSN_P (insn)) + if (!INSN_P (insn)) continue; df_ru_bb_local_compute_process_def (dflow, bb_info, - DF_INSN_UID_GET (df, uid)->defs, 0); + DF_INSN_UID_DEFS (df, uid), 0); /* The use processing must happen after the defs processing even though the uses logically happen first since the defs clear the gen set. Otherwise, a use for regno occuring in the same instruction as a def for regno would be cleared. */ df_ru_bb_local_compute_process_use (bb_info, - DF_INSN_UID_GET (df, uid)->uses, 0); + DF_INSN_UID_USES (df, uid), 0); bitmap_ior_into (seen_in_block, seen_in_insn); bitmap_clear (seen_in_insn); @@ -556,8 +554,8 @@ df_ru_local_compute (struct dataflow *dflow, unsigned int bb_index; bitmap_iterator bi; unsigned int regno; - struct df_ru_problem_data *problem_data = - (struct df_ru_problem_data *) dflow->problem_data; + struct df_ru_problem_data *problem_data + = (struct df_ru_problem_data *) dflow->problem_data; bitmap sparse_invalidated = problem_data->sparse_invalidated_by_call; bitmap dense_invalidated = problem_data->dense_invalidated_by_call; @@ -616,8 +614,8 @@ df_ru_confluence_n (struct dataflow *dflow, edge e) if (e->flags & EDGE_EH) { - struct df_ru_problem_data *problem_data = - (struct df_ru_problem_data *) dflow->problem_data; + struct df_ru_problem_data *problem_data + = (struct df_ru_problem_data *) dflow->problem_data; bitmap sparse_invalidated = problem_data->sparse_invalidated_by_call; bitmap dense_invalidated = problem_data->dense_invalidated_by_call; struct df *df = dflow->df; @@ -691,8 +689,8 @@ static void df_ru_free (struct dataflow *dflow) { unsigned int i; - struct df_ru_problem_data *problem_data = - (struct df_ru_problem_data *) dflow->problem_data; + struct df_ru_problem_data *problem_data + = (struct df_ru_problem_data *) dflow->problem_data; if (problem_data) { @@ -737,10 +735,13 @@ df_ru_dump (struct dataflow *dflow, FILE *file) { basic_block bb; struct df *df = dflow->df; - struct df_ru_problem_data *problem_data = - (struct df_ru_problem_data *) dflow->problem_data; + struct df_ru_problem_data *problem_data + = (struct df_ru_problem_data *) dflow->problem_data; unsigned int m = max_reg_num (); unsigned int regno; + + if (!dflow->block_info) + return; fprintf (file, "Reaching uses:\n"); @@ -761,7 +762,7 @@ df_ru_dump (struct dataflow *dflow, FILE *file) struct df_ru_bb_info *bb_info = df_ru_get_bb_info (dflow, bb->index); df_print_bb_index (bb, file); - if (! bb_info->in) + if (!bb_info->in) continue; fprintf (file, " in \t"); @@ -793,7 +794,8 @@ static struct df_problem problem_RU = NULL, /* Finalize function. */ df_ru_free, /* Free all of the problem information. */ df_ru_dump, /* Debugging. */ - NULL /* Dependent problem. */ + NULL, /* Dependent problem. */ + 0 /* Changeable flags. */ }; @@ -803,9 +805,9 @@ static struct df_problem problem_RU = solution. */ struct dataflow * -df_ru_add_problem (struct df *df) +df_ru_add_problem (struct df *df, int flags) { - return df_add_problem (df, &problem_RU); + return df_add_problem (df, &problem_RU, flags); } @@ -869,21 +871,23 @@ df_rd_free_bb_info (struct dataflow *dflow, not touched unless the block is new. */ static void -df_rd_alloc (struct dataflow *dflow, bitmap blocks_to_rescan) +df_rd_alloc (struct dataflow *dflow, + bitmap blocks_to_rescan ATTRIBUTE_UNUSED, + bitmap all_blocks) { unsigned int bb_index; bitmap_iterator bi; unsigned int reg_size = max_reg_num (); - if (! dflow->block_pool) + if (!dflow->block_pool) dflow->block_pool = create_alloc_pool ("df_rd_block pool", sizeof (struct df_rd_bb_info), 50); if (dflow->problem_data) { unsigned int i; - struct df_rd_problem_data *problem_data = - (struct df_rd_problem_data *) dflow->problem_data; + struct df_rd_problem_data *problem_data + = (struct df_rd_problem_data *) dflow->problem_data; for (i = 0; i < problem_data->def_sites_size; i++) { @@ -920,11 +924,11 @@ df_rd_alloc (struct dataflow *dflow, bitmap blocks_to_rescan) df_grow_bb_info (dflow); - /* Because of the clustering of all def sites for the same pseudo, + /* Because of the clustering of all use sites for the same pseudo, we have to process all of the blocks before doing the analysis. */ - EXECUTE_IF_SET_IN_BITMAP (blocks_to_rescan, 0, bb_index, bi) + EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi) { struct df_rd_bb_info *bb_info = df_rd_get_bb_info (dflow, bb_index); if (bb_info) @@ -970,7 +974,11 @@ df_rd_bb_local_compute_process_def (struct dataflow *dflow, { /* The first def for regno in insn gets to knock out the defs from other instructions. */ - if (!bitmap_bit_p (seen_in_insn, regno)) + if ((!bitmap_bit_p (seen_in_insn, regno)) + /* If the def is to only part of the reg, it does + not kill the other defs that reach here. */ + && (!((DF_REF_FLAGS (def) & DF_REF_PARTIAL) + || (DF_REF_FLAGS (def) & DF_REF_MAY_CLOBBER)))) { if (n_defs > DF_SPARSE_THRESHOLD) { @@ -979,11 +987,10 @@ df_rd_bb_local_compute_process_def (struct dataflow *dflow, } else { - struct df_rd_problem_data * problem_data = - (struct df_rd_problem_data *)dflow->problem_data; - bitmap defs = - df_ref_bitmap (problem_data->def_sites, regno, - begin, n_defs); + struct df_rd_problem_data * problem_data + = (struct df_rd_problem_data *)dflow->problem_data; + bitmap defs = df_ref_bitmap (problem_data->def_sites, + regno, begin, n_defs); bitmap_ior_into (bb_info->kill, defs); bitmap_and_compl_into (bb_info->gen, defs); } @@ -992,7 +999,8 @@ df_rd_bb_local_compute_process_def (struct dataflow *dflow, bitmap_set_bit (seen_in_insn, regno); /* All defs for regno in the instruction may be put into the gen set. */ - if (! (DF_REF_FLAGS (def) & DF_REF_CLOBBER)) + if (!(DF_REF_FLAGS (def) + & (DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER))) bitmap_set_bit (bb_info->gen, DF_REF_ID (def)); } } @@ -1020,11 +1028,11 @@ df_rd_bb_local_compute (struct dataflow *dflow, unsigned int bb_index) { unsigned int uid = INSN_UID (insn); - if (! INSN_P (insn)) + if (!INSN_P (insn)) continue; df_rd_bb_local_compute_process_def (dflow, bb_info, - DF_INSN_UID_GET (df, uid)->defs, 0); + DF_INSN_UID_DEFS (df, uid), 0); /* This complex dance with the two bitmaps is required because instructions can assign twice to the same pseudo. This @@ -1056,8 +1064,8 @@ df_rd_local_compute (struct dataflow *dflow, unsigned int bb_index; bitmap_iterator bi; unsigned int regno; - struct df_rd_problem_data *problem_data = - (struct df_rd_problem_data *) dflow->problem_data; + struct df_rd_problem_data *problem_data + = (struct df_rd_problem_data *) dflow->problem_data; bitmap sparse_invalidated = problem_data->sparse_invalidated_by_call; bitmap dense_invalidated = problem_data->dense_invalidated_by_call; @@ -1117,8 +1125,8 @@ df_rd_confluence_n (struct dataflow *dflow, edge e) if (e->flags & EDGE_EH) { - struct df_rd_problem_data *problem_data = - (struct df_rd_problem_data *) dflow->problem_data; + struct df_rd_problem_data *problem_data + = (struct df_rd_problem_data *) dflow->problem_data; bitmap sparse_invalidated = problem_data->sparse_invalidated_by_call; bitmap dense_invalidated = problem_data->dense_invalidated_by_call; struct df *df = dflow->df; @@ -1192,8 +1200,8 @@ static void df_rd_free (struct dataflow *dflow) { unsigned int i; - struct df_rd_problem_data *problem_data = - (struct df_rd_problem_data *) dflow->problem_data; + struct df_rd_problem_data *problem_data + = (struct df_rd_problem_data *) dflow->problem_data; if (problem_data) { @@ -1238,11 +1246,14 @@ df_rd_dump (struct dataflow *dflow, FILE *file) { struct df *df = dflow->df; basic_block bb; - struct df_rd_problem_data *problem_data = - (struct df_rd_problem_data *) dflow->problem_data; + struct df_rd_problem_data *problem_data + = (struct df_rd_problem_data *) dflow->problem_data; unsigned int m = max_reg_num (); unsigned int regno; + if (!dflow->block_info) + return; + fprintf (file, "Reaching defs:\n\n"); fprintf (file, " sparse invalidated \t"); @@ -1262,7 +1273,7 @@ df_rd_dump (struct dataflow *dflow, FILE *file) struct df_rd_bb_info *bb_info = df_rd_get_bb_info (dflow, bb->index); df_print_bb_index (bb, file); - if (! bb_info->in) + if (!bb_info->in) continue; fprintf (file, " in\t(%d)\n", (int) bitmap_count_bits (bb_info->in)); @@ -1294,7 +1305,8 @@ static struct df_problem problem_RD = NULL, /* Finalize function. */ df_rd_free, /* Free all of the problem information. */ df_rd_dump, /* Debugging. */ - NULL /* Dependent problem. */ + NULL, /* Dependent problem. */ + 0 /* Changeable flags. */ }; @@ -1304,9 +1316,9 @@ static struct df_problem problem_RD = solution. */ struct dataflow * -df_rd_add_problem (struct df *df) +df_rd_add_problem (struct df *df, int flags) { - return df_add_problem (df, &problem_RD); + return df_add_problem (df, &problem_RD, flags); } @@ -1360,21 +1372,18 @@ df_lr_free_bb_info (struct dataflow *dflow, not touched unless the block is new. */ static void -df_lr_alloc (struct dataflow *dflow, bitmap blocks_to_rescan) +df_lr_alloc (struct dataflow *dflow, bitmap blocks_to_rescan, + bitmap all_blocks ATTRIBUTE_UNUSED) { unsigned int bb_index; bitmap_iterator bi; - if (! dflow->block_pool) + if (!dflow->block_pool) dflow->block_pool = create_alloc_pool ("df_lr_block pool", sizeof (struct df_lr_bb_info), 50); df_grow_bb_info (dflow); - /* Because of the clustering of all def sites for the same pseudo, - we have to process all of the blocks before doing the - analysis. */ - EXECUTE_IF_SET_IN_BITMAP (blocks_to_rescan, 0, bb_index, bi) { struct df_lr_bb_info *bb_info = df_lr_get_bb_info (dflow, bb_index); @@ -1410,7 +1419,8 @@ df_lr_bb_local_compute (struct dataflow *dflow, /* Process the registers set in an exception handler. */ for (def = df_get_artificial_defs (df, bb_index); def; def = def->next_ref) - if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0) + if (((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0) + && (!(DF_REF_FLAGS (def) & DF_REF_PARTIAL))) { unsigned int dregno = DF_REF_REGNO (def); bitmap_set_bit (bb_info->def, dregno); @@ -1427,12 +1437,12 @@ df_lr_bb_local_compute (struct dataflow *dflow, { unsigned int uid = INSN_UID (insn); - if (! INSN_P (insn)) + if (!INSN_P (insn)) continue; if (CALL_P (insn)) { - for (def = DF_INSN_UID_GET (df, uid)->defs; def; def = def->next_ref) + for (def = DF_INSN_UID_DEFS (df, uid); def; def = def->next_ref) { unsigned int dregno = DF_REF_REGNO (def); @@ -1443,15 +1453,19 @@ df_lr_bb_local_compute (struct dataflow *dflow, current_function_return_rtx, (rtx *)0))) { - /* Add def to set of defs in this BB. */ - bitmap_set_bit (bb_info->def, dregno); - bitmap_clear_bit (bb_info->use, dregno); + /* If the def is to only part of the reg, it does + not kill the other defs that reach here. */ + if (!(DF_REF_FLAGS (def) & DF_REF_PARTIAL)) + { + bitmap_set_bit (bb_info->def, dregno); + bitmap_clear_bit (bb_info->use, dregno); + } } } } else { - for (def = DF_INSN_UID_GET (df, uid)->defs; def; def = def->next_ref) + for (def = DF_INSN_UID_DEFS (df, uid); def; def = def->next_ref) { unsigned int dregno = DF_REF_REGNO (def); @@ -1459,25 +1473,30 @@ df_lr_bb_local_compute (struct dataflow *dflow, && dregno < FIRST_PSEUDO_REGISTER) { unsigned int i; - unsigned int end = - dregno + hard_regno_nregs[dregno][GET_MODE (DF_REF_REG (def))] - 1; + unsigned int end = dregno + + hard_regno_nregs[dregno][GET_MODE (DF_REF_REG (def))] - 1; for (i = dregno; i <= end; ++i) regs_asm_clobbered[i] = 1; } - /* Add def to set of defs in this BB. */ - bitmap_set_bit (bb_info->def, dregno); - bitmap_clear_bit (bb_info->use, dregno); + /* If the def is to only part of the reg, it does + not kill the other defs that reach here. */ + if (!(DF_REF_FLAGS (def) & DF_REF_PARTIAL)) + { + bitmap_set_bit (bb_info->def, dregno); + bitmap_clear_bit (bb_info->use, dregno); + } } } - for (use = DF_INSN_UID_GET (df, uid)->uses; use; use = use->next_ref) + for (use = DF_INSN_UID_USES (df, uid); use; use = use->next_ref) /* Add use to set of uses in this BB. */ bitmap_set_bit (bb_info->use, DF_REF_REGNO (use)); } /* Process the registers set in an exception handler. */ for (def = df_get_artificial_defs (df, bb_index); def; def = def->next_ref) - if (DF_REF_FLAGS (def) & DF_REF_AT_TOP) + if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) + && (!(DF_REF_FLAGS (def) & DF_REF_PARTIAL))) { unsigned int dregno = DF_REF_REGNO (def); bitmap_set_bit (bb_info->def, dregno); @@ -1493,6 +1512,7 @@ df_lr_bb_local_compute (struct dataflow *dflow, #endif } + /* Compute local live register info for each basic block within BLOCKS. */ static void @@ -1517,7 +1537,7 @@ df_lr_local_compute (struct dataflow *dflow, /* Before reload, there are a few registers that must be forced live everywhere -- which might not already be the case for blocks within infinite loops. */ - if (! reload_completed) + if (!reload_completed) { /* Any reference to any pseudo before reload is a potential reference of the frame pointer. */ @@ -1586,6 +1606,7 @@ df_lr_confluence_0 (struct dataflow *dflow, basic_block bb) /* Confluence function that ignores fake edges. */ + static void df_lr_confluence_n (struct dataflow *dflow, edge e) { @@ -1605,6 +1626,7 @@ df_lr_confluence_n (struct dataflow *dflow, edge e) /* Transfer function. */ + static bool df_lr_transfer_function (struct dataflow *dflow, int bb_index) { @@ -1642,6 +1664,8 @@ df_lr_free (struct dataflow *dflow) dflow->block_info_size = 0; free (dflow->block_info); } + + free (dflow->problem_data); free (dflow); } @@ -1653,6 +1677,9 @@ df_lr_dump (struct dataflow *dflow, FILE *file) { basic_block bb; + if (!dflow->block_info) + return; + fprintf (file, "Live Registers:\n"); FOR_ALL_BB (bb) { @@ -1691,7 +1718,8 @@ static struct df_problem problem_LR = NULL, /* Finalize function. */ df_lr_free, /* Free all of the problem information. */ df_lr_dump, /* Debugging. */ - NULL /* Dependent problem. */ + NULL, /* Dependent problem. */ + 0 }; @@ -1700,9 +1728,9 @@ static struct df_problem problem_LR = solution. */ struct dataflow * -df_lr_add_problem (struct df *df) +df_lr_add_problem (struct df *df, int flags) { - return df_add_problem (df, &problem_LR); + return df_add_problem (df, &problem_LR, flags); } @@ -1756,21 +1784,18 @@ df_ur_free_bb_info (struct dataflow *dflow, not touched unless the block is new. */ static void -df_ur_alloc (struct dataflow *dflow, bitmap blocks_to_rescan) +df_ur_alloc (struct dataflow *dflow, bitmap blocks_to_rescan, + bitmap all_blocks ATTRIBUTE_UNUSED) { unsigned int bb_index; bitmap_iterator bi; - if (! dflow->block_pool) + if (!dflow->block_pool) dflow->block_pool = create_alloc_pool ("df_ur_block pool", sizeof (struct df_ur_bb_info), 100); df_grow_bb_info (dflow); - /* Because of the clustering of all def sites for the same pseudo, - we have to process all of the blocks before doing the - analysis. */ - EXECUTE_IF_SET_IN_BITMAP (blocks_to_rescan, 0, bb_index, bi) { struct df_ur_bb_info *bb_info = df_ur_get_bb_info (dflow, bb_index); @@ -1823,16 +1848,23 @@ df_ur_bb_local_compute (struct dataflow *dflow, unsigned int bb_index) if (!INSN_P (insn)) continue; - for (def = DF_INSN_UID_GET (df, uid)->defs; def; def = def->next_ref) + for (def = DF_INSN_UID_DEFS (df, uid); def; def = def->next_ref) { unsigned int regno = DF_REF_REGNO (def); - /* Only the last def counts. */ + /* Only the last def counts. */ if (!bitmap_bit_p (seen_in_block, regno)) { bitmap_set_bit (seen_in_insn, regno); - if (DF_REF_FLAGS (def) & DF_REF_CLOBBER) - bitmap_set_bit (bb_info->kill, regno); + if (DF_REF_FLAGS (def) + & (DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER)) + { + /* Only must clobbers for the entire reg destroy the + value. */ + if ((DF_REF_FLAGS (def) & DF_REF_MUST_CLOBBER) + && (!DF_REF_FLAGS (def) & DF_REF_PARTIAL)) + bitmap_set_bit (bb_info->kill, regno); + } else bitmap_set_bit (bb_info->gen, regno); } @@ -1927,7 +1959,7 @@ df_ur_local_finalize (struct dataflow *dflow, bitmap all_blocks) bitmap_and_into (bb_info->out, tmp); #endif } - + BITMAP_FREE (tmp); } @@ -1998,6 +2030,9 @@ df_ur_dump (struct dataflow *dflow, FILE *file) { basic_block bb; + if (!dflow->block_info) + return; + fprintf (file, "Undefined regs:\n"); FOR_ALL_BB (bb) @@ -2005,7 +2040,7 @@ df_ur_dump (struct dataflow *dflow, FILE *file) struct df_ur_bb_info *bb_info = df_ur_get_bb_info (dflow, bb->index); df_print_bb_index (bb, file); - if (! bb_info->in) + if (!bb_info->in) continue; fprintf (file, " in \t"); @@ -2037,7 +2072,8 @@ static struct df_problem problem_UR = df_ur_local_finalize, /* Finalize function. */ df_ur_free, /* Free all of the problem information. */ df_ur_dump, /* Debugging. */ - &problem_LR /* Dependent problem. */ + df_lr_add_problem, /* Dependent problem. */ + 0 /* Changeable flags. */ }; @@ -2046,9 +2082,9 @@ static struct df_problem problem_UR = solution. */ struct dataflow * -df_ur_add_problem (struct df *df) +df_ur_add_problem (struct df *df, int flags) { - return df_add_problem (df, &problem_UR); + return df_add_problem (df, &problem_UR, flags); } @@ -2116,14 +2152,16 @@ df_urec_free_bb_info (struct dataflow *dflow, not touched unless the block is new. */ static void -df_urec_alloc (struct dataflow *dflow, bitmap blocks_to_rescan) +df_urec_alloc (struct dataflow *dflow, bitmap blocks_to_rescan, + bitmap all_blocks ATTRIBUTE_UNUSED) + { unsigned int bb_index; bitmap_iterator bi; - struct df_urec_problem_data *problem_data = - (struct df_urec_problem_data *) dflow->problem_data; + struct df_urec_problem_data *problem_data + = (struct df_urec_problem_data *) dflow->problem_data; - if (! dflow->block_pool) + if (!dflow->block_pool) dflow->block_pool = create_alloc_pool ("df_urec_block pool", sizeof (struct df_urec_bb_info), 50); @@ -2136,10 +2174,6 @@ df_urec_alloc (struct dataflow *dflow, bitmap blocks_to_rescan) df_grow_bb_info (dflow); - /* Because of the clustering of all def sites for the same pseudo, - we have to process all of the blocks before doing the - analysis. */ - EXECUTE_IF_SET_IN_BITMAP (blocks_to_rescan, 0, bb_index, bi) { struct df_urec_bb_info *bb_info = df_urec_get_bb_info (dflow, bb_index); @@ -2376,11 +2410,10 @@ df_urec_bb_local_compute (struct dataflow *dflow, unsigned int bb_index) if (INSN_P (insn)) { note_stores (PATTERN (insn), df_urec_mark_reg_change, bb_info); - if (df_state & (DF_SCAN_GLOBAL | DF_SCAN_POST_ALLOC) - && df_urec_check_earlyclobber (insn)) + if (df_urec_check_earlyclobber (insn)) { - struct df_urec_problem_data *problem_data = - (struct df_urec_problem_data *) dflow->problem_data; + struct df_urec_problem_data *problem_data + = (struct df_urec_problem_data *) dflow->problem_data; problem_data->earlyclobbers_found = true; note_uses (&PATTERN (insn), df_urec_mark_reg_use_for_earlyclobber_1, bb_info); @@ -2410,8 +2443,8 @@ df_urec_local_compute (struct dataflow *dflow, #ifdef STACK_REGS int i; HARD_REG_SET zero, stack_hard_regs, used; - struct df_urec_problem_data *problem_data = - (struct df_urec_problem_data *) dflow->problem_data; + struct df_urec_problem_data *problem_data + = (struct df_urec_problem_data *) dflow->problem_data; /* Any register that MAY be allocated to a register stack (like the 387) is treated poorly. Each such register is marked as being @@ -2479,8 +2512,8 @@ df_urec_local_finalize (struct dataflow *dflow, bitmap all_blocks) bitmap tmp = BITMAP_ALLOC (NULL); bitmap_iterator bi; unsigned int bb_index; - struct df_urec_problem_data *problem_data = - (struct df_urec_problem_data *) dflow->problem_data; + struct df_urec_problem_data *problem_data + = (struct df_urec_problem_data *) dflow->problem_data; EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi) { @@ -2597,6 +2630,9 @@ df_urec_dump (struct dataflow *dflow, FILE *file) { basic_block bb; + if (!dflow->block_info) + return; + fprintf (file, "Undefined regs:\n"); FOR_ALL_BB (bb) @@ -2604,7 +2640,7 @@ df_urec_dump (struct dataflow *dflow, FILE *file) struct df_urec_bb_info *bb_info = df_urec_get_bb_info (dflow, bb->index); df_print_bb_index (bb, file); - if (! bb_info->in) + if (!bb_info->in) continue; fprintf (file, " in \t"); @@ -2638,7 +2674,8 @@ static struct df_problem problem_UREC = df_urec_local_finalize, /* Finalize function. */ df_urec_free, /* Free all of the problem information. */ df_urec_dump, /* Debugging. */ - &problem_LR /* Dependent problem. */ + df_lr_add_problem, /* Dependent problem. */ + 0 /* Changeable flags. */ }; @@ -2647,9 +2684,9 @@ static struct df_problem problem_UREC = solution. */ struct dataflow * -df_urec_add_problem (struct df *df) +df_urec_add_problem (struct df *df, int flags) { - return df_add_problem (df, &problem_UREC); + return df_add_problem (df, &problem_UREC, flags); } @@ -2665,22 +2702,16 @@ df_urec_add_problem (struct df *df) the reaching defs information (the dependent problem). ----------------------------------------------------------------------------*/ -struct df_chain_problem_data -{ - int flags; -}; - - /* Create def-use or use-def chains. */ static void df_chain_alloc (struct dataflow *dflow, - bitmap blocks_to_rescan ATTRIBUTE_UNUSED) + bitmap blocks_to_rescan ATTRIBUTE_UNUSED, + bitmap all_blocks ATTRIBUTE_UNUSED) + { struct df *df = dflow->df; unsigned int i; - struct df_chain_problem_data *problem_data = - (struct df_chain_problem_data *) dflow->problem_data; /* Wholesale destruction of the old chains. */ if (dflow->block_pool) @@ -2689,7 +2720,7 @@ df_chain_alloc (struct dataflow *dflow, dflow->block_pool = create_alloc_pool ("df_chain_chain_block pool", sizeof (struct df_link), 100); - if (problem_data->flags & DF_DU_CHAIN) + if (dflow->flags & DF_DU_CHAIN) { if (!df->def_info.refs_organized) df_reorganize_refs (&df->def_info); @@ -2702,7 +2733,7 @@ df_chain_alloc (struct dataflow *dflow, } } - if (problem_data->flags & DF_UD_CHAIN) + if (dflow->flags & DF_UD_CHAIN) { if (!df->use_info.refs_organized) df_reorganize_refs (&df->use_info); @@ -2721,8 +2752,6 @@ static void df_chain_insn_reset (struct dataflow *dflow, rtx insn) { struct df *df = dflow->df; - struct df_chain_problem_data *problem_data = - (struct df_chain_problem_data *) dflow->problem_data; unsigned int uid = INSN_UID (insn); struct df_insn_info *insn_info = NULL; struct df_ref *ref; @@ -2732,7 +2761,7 @@ df_chain_insn_reset (struct dataflow *dflow, rtx insn) if (insn_info) { - if (problem_data->flags & DF_DU_CHAIN) + if (dflow->flags & DF_DU_CHAIN) { ref = insn_info->defs; while (ref) @@ -2742,7 +2771,7 @@ df_chain_insn_reset (struct dataflow *dflow, rtx insn) } } - if (problem_data->flags & DF_UD_CHAIN) + if (dflow->flags & DF_UD_CHAIN) { ref = insn_info->uses; while (ref) @@ -2761,8 +2790,6 @@ static void df_chain_bb_reset (struct dataflow *dflow, unsigned int bb_index) { struct df *df = dflow->df; - struct df_chain_problem_data *problem_data = - (struct df_chain_problem_data *) dflow->problem_data; rtx insn; basic_block bb = BASIC_BLOCK (bb_index); @@ -2780,7 +2807,7 @@ df_chain_bb_reset (struct dataflow *dflow, unsigned int bb_index) } /* Get rid of any chains in artificial uses or defs. */ - if (problem_data->flags & DF_DU_CHAIN) + if (dflow->flags & DF_DU_CHAIN) { struct df_ref *def; def = df_get_artificial_defs (df, bb_index); @@ -2791,7 +2818,7 @@ df_chain_bb_reset (struct dataflow *dflow, unsigned int bb_index) } } - if (problem_data->flags & DF_UD_CHAIN) + if (dflow->flags & DF_UD_CHAIN) { struct df_ref *use; use = df_get_artificial_uses (df, bb_index); @@ -2827,7 +2854,6 @@ df_chain_reset (struct dataflow *dflow, bitmap blocks_to_clear) static void df_chain_create_bb_process_use (struct dataflow *dflow, - struct df_chain_problem_data *problem_data, bitmap local_rd, struct df_ref *use, enum df_ref_flags top_flag) @@ -2855,9 +2881,9 @@ df_chain_create_bb_process_use (struct dataflow *dflow, break; def = DF_DEFS_GET (df, def_index); - if (problem_data->flags & DF_DU_CHAIN) + if (dflow->flags & DF_DU_CHAIN) df_chain_create (dflow, def, use); - if (problem_data->flags & DF_UD_CHAIN) + if (dflow->flags & DF_UD_CHAIN) df_chain_create (dflow, use, def); } } @@ -2881,8 +2907,6 @@ df_chain_create_bb (struct dataflow *dflow, rtx insn; bitmap cpy = BITMAP_ALLOC (NULL); struct df *df = dflow->df; - struct df_chain_problem_data *problem_data = - (struct df_chain_problem_data *) dflow->problem_data; struct df_ref *def; bitmap_copy (cpy, bb_info->in); @@ -2893,7 +2917,7 @@ df_chain_create_bb (struct dataflow *dflow, #ifdef EH_USES /* Create the chains for the artificial uses from the EH_USES at the beginning of the block. */ - df_chain_create_bb_process_use (dflow, problem_data, cpy, + df_chain_create_bb_process_use (dflow, cpy, df_get_artificial_uses (df, bb->index), DF_REF_AT_TOP); #endif @@ -2902,11 +2926,11 @@ df_chain_create_bb (struct dataflow *dflow, if (DF_REF_FLAGS (def) & DF_REF_AT_TOP) { unsigned int dregno = DF_REF_REGNO (def); - bitmap_clear_range (cpy, - DF_REG_DEF_GET (df, dregno)->begin, - DF_REG_DEF_GET (df, dregno)->n_refs); - if (! (DF_REF_FLAGS (def) & DF_REF_CLOBBER)) - bitmap_set_bit (cpy, DF_REF_ID (def)); + if (!(DF_REF_FLAGS (def) & DF_REF_PARTIAL)) + bitmap_clear_range (cpy, + DF_REG_DEF_GET (df, dregno)->begin, + DF_REG_DEF_GET (df, dregno)->n_refs); + bitmap_set_bit (cpy, DF_REF_ID (def)); } /* Process the regular instructions next. */ @@ -2915,31 +2939,33 @@ df_chain_create_bb (struct dataflow *dflow, struct df_ref *def; unsigned int uid = INSN_UID (insn); - if (! INSN_P (insn)) + if (!INSN_P (insn)) continue; /* Now scan the uses and link them up with the defs that remain in the cpy vector. */ - df_chain_create_bb_process_use (dflow, problem_data, cpy, - DF_INSN_UID_GET (df, uid)->uses, 0); + df_chain_create_bb_process_use (dflow, cpy, + DF_INSN_UID_USES (df, uid), 0); /* Since we are going forwards, process the defs second. This pass only changes the bits in cpy. */ - for (def = DF_INSN_UID_GET (df, uid)->defs; def; def = def->next_ref) + for (def = DF_INSN_UID_DEFS (df, uid); def; def = def->next_ref) { unsigned int dregno = DF_REF_REGNO (def); - bitmap_clear_range (cpy, - DF_REG_DEF_GET (df, dregno)->begin, - DF_REG_DEF_GET (df, dregno)->n_refs); - if (! (DF_REF_FLAGS (def) & DF_REF_CLOBBER)) + if (!(DF_REF_FLAGS (def) & DF_REF_PARTIAL)) + bitmap_clear_range (cpy, + DF_REG_DEF_GET (df, dregno)->begin, + DF_REG_DEF_GET (df, dregno)->n_refs); + if (!(DF_REF_FLAGS (def) + & (DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER))) bitmap_set_bit (cpy, DF_REF_ID (def)); } } /* Create the chains for the artificial uses of the hard registers at the end of the block. */ - df_chain_create_bb_process_use (dflow, problem_data, cpy, + df_chain_create_bb_process_use (dflow, cpy, df_get_artificial_uses (df, bb->index), 0); } @@ -2967,7 +2993,6 @@ static void df_chain_free (struct dataflow *dflow) { free_alloc_pool (dflow->block_pool); - free (dflow->problem_data); free (dflow); } @@ -2979,10 +3004,8 @@ df_chains_dump (struct dataflow *dflow, FILE *file) { struct df *df = dflow->df; unsigned int j; - struct df_chain_problem_data *problem_data = - (struct df_chain_problem_data *) dflow->problem_data; - if (problem_data->flags & DF_DU_CHAIN) + if (dflow->flags & DF_DU_CHAIN) { fprintf (file, "Def-use chains:\n"); for (j = 0; j < df->def_info.bitmap_size; j++) @@ -2999,13 +3022,13 @@ df_chains_dump (struct dataflow *dflow, FILE *file) DF_REF_REGNO (def)); if (def->flags & DF_REF_READ_WRITE) fprintf (file, "read/write "); - df_chain_dump (df, DF_REF_CHAIN (def), file); + df_chain_dump (DF_REF_CHAIN (def), file); fprintf (file, "\n"); } } } - if (problem_data->flags & DF_UD_CHAIN) + if (dflow->flags & DF_UD_CHAIN) { fprintf (file, "Use-def chains:\n"); for (j = 0; j < df->use_info.bitmap_size; j++) @@ -3028,7 +3051,7 @@ df_chains_dump (struct dataflow *dflow, FILE *file) fprintf (file, "stripped "); if (use->flags & DF_REF_IN_NOTE) fprintf (file, "note "); - df_chain_dump (df, DF_REF_CHAIN (use), file); + df_chain_dump (DF_REF_CHAIN (use), file); fprintf (file, "\n"); } } @@ -3052,7 +3075,8 @@ static struct df_problem problem_CHAIN = df_chain_finalize, /* Finalize function. */ df_chain_free, /* Free all of the problem information. */ df_chains_dump, /* Debugging. */ - &problem_RD /* Dependent problem. */ + df_rd_add_problem, /* Dependent problem. */ + 0 /* Changeable flags. */ }; @@ -3063,104 +3087,560 @@ static struct df_problem problem_CHAIN = struct dataflow * df_chain_add_problem (struct df *df, int flags) { - struct df_chain_problem_data *problem_data = - XNEW (struct df_chain_problem_data); - struct dataflow *dflow = df_add_problem (df, &problem_CHAIN); - - dflow->problem_data = problem_data; - problem_data->flags = flags; - - return dflow; + return df_add_problem (df, &problem_CHAIN, flags); } /*---------------------------------------------------------------------------- REGISTER INFORMATION - Currently this consists of only lifetime information. But the plan is - to enhance it so that it produces all of the register information needed - by the register allocators. -----------------------------------------------------------------------------*/ - + Currently this consists of only lifetime information and reg_dead + and reg_unused. + ----------------------------------------------------------------------------*/ -struct df_ri_problem_data +#ifdef REG_DEAD_DEBUGGING +static void +print_note (char *prefix, rtx insn, rtx note) { - int *lifetime; -}; - + fprintf (stderr, "%s %d ", prefix, INSN_UID (insn)); + print_rtl (stderr, note); + fprintf (stderr, "\n"); +} +#endif /* Allocate the lifetime information. */ static void -df_ri_alloc (struct dataflow *dflow, bitmap blocks_to_rescan ATTRIBUTE_UNUSED) +df_ri_alloc (struct dataflow *dflow, + bitmap blocks_to_rescan ATTRIBUTE_UNUSED, + bitmap all_blocks ATTRIBUTE_UNUSED) { - struct df_ri_problem_data *problem_data = - (struct df_ri_problem_data *) dflow->problem_data; + int i; + struct df *df = dflow->df; - if (!dflow->problem_data) + if (dflow->flags & DF_RI_LIFE) { - struct df_ri_problem_data *problem_data = XNEW (struct df_ri_problem_data); - dflow->problem_data = problem_data; + max_regno = max_reg_num (); + allocate_reg_info (max_regno, FALSE, FALSE); + + /* Reset all the data we'll collect. */ + for (i = 0; i < max_regno; i++) + { + REG_N_SETS (i) = DF_REG_DEF_COUNT (df, i); + REG_N_REFS (i) = DF_REG_USE_COUNT (df, i) + REG_N_SETS (i); + REG_N_DEATHS (i) = 0; + REG_N_CALLS_CROSSED (i) = 0; + REG_N_THROWING_CALLS_CROSSED (i) = 0; + REG_LIVE_LENGTH (i) = 0; + REG_FREQ (i) = 0; + REG_BASIC_BLOCK (i) = REG_BLOCK_UNKNOWN; + } + } +} + + +/* After reg-stack, the x86 floating point stack regs are difficult to + analyze because of all of the pushes, pops and rotations. Thus, we + just leave the notes alone. */ + +static inline bool +df_ignore_stack_reg (int regno ATTRIBUTE_UNUSED) +{ +#ifdef STACK_REGS + return (regstack_completed + && IN_RANGE (regno, FIRST_STACK_REG, LAST_STACK_REG)); +#else + return false; +#endif +} + + +/* Remove all of the REG_DEAD or REG_UNUSED notes from INSN. */ + +static void +df_kill_notes (rtx insn, int flags) +{ + rtx *pprev = ®_NOTES (insn); + rtx link = *pprev; + + while (link) + { + switch (REG_NOTE_KIND (link)) + { + case REG_DEAD: + if (flags & DF_RI_LIFE) + if (df_ignore_stack_reg (REGNO (XEXP (link, 0)))) + REG_N_DEATHS (REGNO (XEXP (link, 0)))++; + + /* Fallthru */ + case REG_UNUSED: + if (!df_ignore_stack_reg (REGNO (XEXP (link, 0)))) + { + rtx next = XEXP (link, 1); +#ifdef REG_DEAD_DEBUGGING + print_note ("deleting: ", insn, link); +#endif + free_EXPR_LIST_node (link); + *pprev = link = next; + } + break; + + default: + pprev = &XEXP (link, 1); + link = *pprev; + break; + } + } +} + + +/* Set the REG_UNUSED notes for the multiword hardreg defs in INSN + based on the bits in LIVE. Do not generate notes for registers in + artificial uses. DO_NOT_GEN is updated so that REG_DEAD notes are + not generated if the reg is both read and written by the + instruction. +*/ + +static void +df_set_unused_notes_for_mw (rtx insn, struct df_mw_hardreg *mws, + bitmap live, bitmap do_not_gen, + bitmap artificial_uses, int flags) +{ + bool all_dead = true; + struct df_link *regs = mws->regs; + unsigned int regno = DF_REF_REGNO (regs->ref); + +#ifdef REG_DEAD_DEBUGGING + fprintf (stderr, "mw unused looking at %d\n", DF_REF_REGNO (regs->ref)); + df_ref_debug (regs->ref, stderr); +#endif + while (regs) + { + unsigned int regno = DF_REF_REGNO (regs->ref); + if ((bitmap_bit_p (live, regno)) + || bitmap_bit_p (artificial_uses, regno)) + { + all_dead = false; + break; + } + regs = regs->next; + } + + if (all_dead) + { + struct df_link *regs = mws->regs; + rtx note = alloc_EXPR_LIST (REG_UNUSED, *DF_REF_LOC (regs->ref), + REG_NOTES (insn)); + REG_NOTES (insn) = note; +#ifdef REG_DEAD_DEBUGGING + print_note ("adding 1: ", insn, note); +#endif + bitmap_set_bit (do_not_gen, regno); + /* Only do this if the value is totally dead. */ + if (flags & DF_RI_LIFE) + { + REG_N_DEATHS (regno) ++; + REG_LIVE_LENGTH (regno)++; + } + } + else + { + struct df_link *regs = mws->regs; + while (regs) + { + struct df_ref *ref = regs->ref; + + regno = DF_REF_REGNO (ref); + if ((!bitmap_bit_p (live, regno)) + && (!bitmap_bit_p (artificial_uses, regno))) + { + rtx note = alloc_EXPR_LIST (REG_UNUSED, regno_reg_rtx[regno], + REG_NOTES (insn)); + REG_NOTES (insn) = note; +#ifdef REG_DEAD_DEBUGGING + print_note ("adding 2: ", insn, note); +#endif + } + bitmap_set_bit (do_not_gen, regno); + regs = regs->next; + } + } +} + + +/* Set the REG_DEAD notes for the multiword hardreg use in INSN based + on the bits in LIVE. DO_NOT_GEN is used to keep REG_DEAD notes + from being set if the instruction both reads and writes the + register. */ + +static void +df_set_dead_notes_for_mw (rtx insn, struct df_mw_hardreg *mws, + bitmap live, bitmap do_not_gen, + bitmap artificial_uses, int flags) +{ + bool all_dead = true; + struct df_link *regs = mws->regs; + unsigned int regno = DF_REF_REGNO (regs->ref); + +#ifdef REG_DEAD_DEBUGGING + fprintf (stderr, "mw looking at %d\n", DF_REF_REGNO (regs->ref)); + df_ref_debug (regs->ref, stderr); +#endif + while (regs) + { + unsigned int regno = DF_REF_REGNO (regs->ref); + if ((bitmap_bit_p (live, regno)) + || bitmap_bit_p (artificial_uses, regno)) + { + all_dead = false; + break; + } + regs = regs->next; + } + + if (all_dead) + { + if (!bitmap_bit_p (do_not_gen, regno)) + { + /* Add a dead note for the entire multi word register. */ + struct df_link *regs = mws->regs; + rtx note = alloc_EXPR_LIST (REG_DEAD, *DF_REF_LOC (regs->ref), + REG_NOTES (insn)); + REG_NOTES (insn) = note; +#ifdef REG_DEAD_DEBUGGING + print_note ("adding 1: ", insn, note); +#endif + + if (flags & DF_RI_LIFE) + { + struct df_link *regs = mws->regs; + while (regs) + { + struct df_ref *ref = regs->ref; + regno = DF_REF_REGNO (ref); + REG_N_DEATHS (regno)++; + regs = regs->next; + } + } + } + } + else + { + struct df_link *regs = mws->regs; + while (regs) + { + struct df_ref *ref = regs->ref; + + regno = DF_REF_REGNO (ref); + if ((!bitmap_bit_p (live, regno)) + && (!bitmap_bit_p (artificial_uses, regno)) + && (!bitmap_bit_p (do_not_gen, regno))) + { + rtx note = alloc_EXPR_LIST (REG_DEAD, regno_reg_rtx[regno], + REG_NOTES (insn)); + REG_NOTES (insn) = note; + if (flags & DF_RI_LIFE) + REG_N_DEATHS (regno)++; +#ifdef REG_DEAD_DEBUGGING + print_note ("adding 2: ", insn, note); +#endif + } + + regs = regs->next; + } + } +} + + +/* Create a REG_UNUSED note if necessary for DEF in INSN updating LIVE + and DO_NOT_GEN. Do not generate notes for registers in artificial + uses. */ + +static void +df_create_unused_note (basic_block bb, rtx insn, struct df_ref *def, + bitmap live, bitmap do_not_gen, bitmap artificial_uses, + bitmap local_live, bitmap local_processed, + int flags, int luid) +{ + unsigned int dregno = DF_REF_REGNO (def); + +#ifdef REG_DEAD_DEBUGGING + fprintf (stderr, " regular looking at def "); + df_ref_debug (def, stderr); +#endif + + if (bitmap_bit_p (live, dregno)) + { + if (flags & DF_RI_LIFE) + { + /* If we have seen this regno, then it has already been + processed correctly with the per insn increment. If we + have not seen it we need to add the length from here to + the end of the block to the live length. */ + if (bitmap_bit_p (local_processed, dregno)) + { + if (!(DF_REF_FLAGS (def) & DF_REF_PARTIAL)) + bitmap_clear_bit (local_live, dregno); + } + else + { + bitmap_set_bit (local_processed, dregno); + REG_LIVE_LENGTH (dregno) += luid; + } + } + } + else if ((!(DF_REF_FLAGS (def) & DF_REF_MW_HARDREG)) + && (!bitmap_bit_p (artificial_uses, dregno)) + && (!df_ignore_stack_reg (dregno))) + { + rtx reg = GET_CODE (*DF_REF_LOC (def)) == SUBREG ? + SUBREG_REG (*DF_REF_LOC (def)) : *DF_REF_LOC (def); + rtx note = alloc_EXPR_LIST (REG_UNUSED, reg, REG_NOTES (insn)); + REG_NOTES (insn) = note; +#ifdef REG_DEAD_DEBUGGING + print_note ("adding 3: ", insn, note); +#endif + if (flags & DF_RI_LIFE) + { + REG_N_DEATHS (dregno) ++; + REG_LIVE_LENGTH (dregno)++; + } + } + + if ((flags & DF_RI_LIFE) && (dregno >= FIRST_PSEUDO_REGISTER)) + { + REG_FREQ (dregno) += REG_FREQ_FROM_BB (bb); + if (REG_BASIC_BLOCK (dregno) == REG_BLOCK_UNKNOWN) + REG_BASIC_BLOCK (dregno) = bb->index; + else if (REG_BASIC_BLOCK (dregno) != bb->index) + REG_BASIC_BLOCK (dregno) = REG_BLOCK_GLOBAL; } - problem_data->lifetime = xrealloc (problem_data->lifetime, - max_reg_num () *sizeof (int)); - memset (problem_data->lifetime, 0, max_reg_num () *sizeof (int)); + if (!(DF_REF_FLAGS (def) & (DF_REF_MUST_CLOBBER + DF_REF_MAY_CLOBBER))) + bitmap_set_bit (do_not_gen, dregno); + + /* Kill this register if it is not a subreg store. */ + if (!(DF_REF_FLAGS (def) & DF_REF_PARTIAL)) + bitmap_clear_bit (live, dregno); } -/* Compute register info: lifetime, bb, and number of defs and uses - for basic block BB. */ + +/* Recompute the REG_DEAD and REG_UNUSED notes and compute register + info: lifetime, bb, and number of defs and uses for basic block + BB. The three bitvectors are scratch regs used here. */ static void -df_ri_bb_compute (struct dataflow *dflow, unsigned int bb_index, bitmap live) +df_ri_bb_compute (struct dataflow *dflow, unsigned int bb_index, + bitmap live, bitmap do_not_gen, bitmap artificial_uses, + bitmap local_live, bitmap local_processed, bitmap setjumps_crossed) { struct df *df = dflow->df; - struct df_ur_bb_info *bb_info = df_ur_get_bb_info (dflow, bb_index); - struct df_ri_problem_data *problem_data = - (struct df_ri_problem_data *) dflow->problem_data; basic_block bb = BASIC_BLOCK (bb_index); rtx insn; + struct df_ref *def; + struct df_ref *use; + int luid = 0; + + bitmap_copy (live, df_get_live_out (df, bb)); + bitmap_clear (artificial_uses); + + if (dflow->flags & DF_RI_LIFE) + { + /* Process the regs live at the end of the block. Mark them as + not local to any one basic block. */ + bitmap_iterator bi; + unsigned int regno; + EXECUTE_IF_SET_IN_BITMAP (live, 0, regno, bi) + REG_BASIC_BLOCK (regno) = REG_BLOCK_GLOBAL; + } + + /* Process the artificial defs and uses at the bottom of the block + to begin processing. */ + for (def = df_get_artificial_defs (df, bb_index); def; def = def->next_ref) + if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0) + bitmap_clear_bit (live, DF_REF_REGNO (def)); - bitmap_copy (live, bb_info->out); + for (use = df_get_artificial_uses (df, bb_index); use; use = use->next_ref) + if ((DF_REF_FLAGS (use) & DF_REF_AT_TOP) == 0) + { + unsigned int regno = DF_REF_REGNO (use); + bitmap_set_bit (live, regno); + /* Notes are not generated for any of the artificial registers + at the bottom of the block. */ + bitmap_set_bit (artificial_uses, regno); + } + FOR_BB_INSNS_REVERSE (bb, insn) { unsigned int uid = INSN_UID (insn); unsigned int regno; bitmap_iterator bi; - struct df_ref *def; - struct df_ref *use; - - if (! INSN_P (insn)) + struct df_mw_hardreg *mws; + + if (!INSN_P (insn)) continue; - for (def = DF_INSN_UID_GET (df, uid)->defs; def; def = def->next_ref) + if (dflow->flags & DF_RI_LIFE) { - unsigned int dregno = DF_REF_REGNO (def); + /* Increment the live_length for all of the registers that + are are referenced in this block and live at this + particular point. */ + bitmap_iterator bi; + unsigned int regno; + EXECUTE_IF_SET_IN_BITMAP (local_live, 0, regno, bi) + { + REG_LIVE_LENGTH (regno)++; + } + luid++; + } + + bitmap_clear (do_not_gen); + df_kill_notes (insn, dflow->flags); + + /* Process the defs. */ + if (CALL_P (insn)) + { + if (dflow->flags & DF_RI_LIFE) + { + bool can_throw = can_throw_internal (insn); + bool set_jump = (find_reg_note (insn, REG_SETJMP, NULL) != NULL); + EXECUTE_IF_SET_IN_BITMAP (live, 0, regno, bi) + { + REG_N_CALLS_CROSSED (regno)++; + if (can_throw) + REG_N_THROWING_CALLS_CROSSED (regno)++; + + /* We have a problem with any pseudoreg that lives + across the setjmp. ANSI says that if a user + variable does not change in value between the + setjmp and the longjmp, then the longjmp + preserves it. This includes longjmp from a place + where the pseudo appears dead. (In principle, + the value still exists if it is in scope.) If + the pseudo goes in a hard reg, some other value + may occupy that hard reg where this pseudo is + dead, thus clobbering the pseudo. Conclusion: + such a pseudo must not go in a hard reg. */ + if (set_jump && regno >= FIRST_PSEUDO_REGISTER) + bitmap_set_bit (setjumps_crossed, regno); + } + } + + /* We only care about real sets for calls. Clobbers only + may clobber and cannot be depended on. */ + for (mws = DF_INSN_UID_MWS (df, uid); mws; mws = mws->next) + { + if ((mws->type == DF_REF_REG_DEF) + && !df_ignore_stack_reg (REGNO (mws->mw_reg))) + df_set_unused_notes_for_mw (insn, mws, live, do_not_gen, + artificial_uses, dflow->flags); + } + + /* All of the defs except the return value are some sort of + clobber. This code is for the return. */ + for (def = DF_INSN_UID_DEFS (df, uid); def; def = def->next_ref) + if (!(DF_REF_FLAGS (def) & (DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER))) + df_create_unused_note (bb, insn, def, live, do_not_gen, + artificial_uses, local_live, + local_processed, dflow->flags, luid); - /* Kill this register. */ - bitmap_clear_bit (live, dregno); + } + else + { + /* Regular insn. */ + for (mws = DF_INSN_UID_MWS (df, uid); mws; mws = mws->next) + { + if (mws->type == DF_REF_REG_DEF) + df_set_unused_notes_for_mw (insn, mws, live, do_not_gen, + artificial_uses, dflow->flags); + } + + for (def = DF_INSN_UID_DEFS (df, uid); def; def = def->next_ref) + df_create_unused_note (bb, insn, def, live, do_not_gen, + artificial_uses, local_live, + local_processed, dflow->flags, luid); + } + + /* Process the uses. */ + for (mws = DF_INSN_UID_MWS (df, uid); mws; mws = mws->next) + { + if ((mws->type != DF_REF_REG_DEF) + && !df_ignore_stack_reg (REGNO (mws->mw_reg))) + df_set_dead_notes_for_mw (insn, mws, live, do_not_gen, + artificial_uses, dflow->flags); } - for (use = DF_INSN_UID_GET (df, uid)->uses; use; use = use->next_ref) + for (use = DF_INSN_UID_USES (df, uid); use; use = use->next_ref) { unsigned int uregno = DF_REF_REGNO (use); + if ((dflow->flags & DF_RI_LIFE) && (uregno >= FIRST_PSEUDO_REGISTER)) + { + REG_FREQ (uregno) += REG_FREQ_FROM_BB (bb); + if (REG_BASIC_BLOCK (uregno) == REG_BLOCK_UNKNOWN) + REG_BASIC_BLOCK (uregno) = bb->index; + else if (REG_BASIC_BLOCK (uregno) != bb->index) + REG_BASIC_BLOCK (uregno) = REG_BLOCK_GLOBAL; + } + +#ifdef REG_DEAD_DEBUGGING + fprintf (stderr, " regular looking at use "); + df_ref_debug (use, stderr); +#endif if (!bitmap_bit_p (live, uregno)) { - use->flags |= DF_REF_DIES_AFTER_THIS_USE; + if ( (!(DF_REF_FLAGS (use) & DF_REF_MW_HARDREG)) + && (!bitmap_bit_p (do_not_gen, uregno)) + && (!bitmap_bit_p (artificial_uses, uregno)) + && (!(DF_REF_FLAGS (use) & DF_REF_READ_WRITE)) + && (!df_ignore_stack_reg (uregno))) + { + rtx reg = GET_CODE (*DF_REF_LOC (use)) == SUBREG ? + SUBREG_REG (*DF_REF_LOC (use)) : *DF_REF_LOC (use); + rtx note = alloc_EXPR_LIST (REG_DEAD, reg, REG_NOTES (insn)); + REG_NOTES (insn) = note; + if (dflow->flags & DF_RI_LIFE) + REG_N_DEATHS (uregno)++; + +#ifdef REG_DEAD_DEBUGGING + print_note ("adding 4: ", insn, note); +#endif + } /* This register is now live. */ bitmap_set_bit (live, uregno); + + if (dflow->flags & DF_RI_LIFE) + { + /* If we have seen this regno, then it has already + been processed correctly with the per insn + increment. If we have not seen it we set the bit + so that begins to get processed locally. Note + that we don't even get here if the variable was + live at the end of the block since just a ref + inside the block does not effect the + calculations. */ + REG_LIVE_LENGTH (uregno) ++; + bitmap_set_bit (local_live, uregno); + bitmap_set_bit (local_processed, uregno); + } } - else - use->flags &= ~DF_REF_DIES_AFTER_THIS_USE; } - - /* Increment lifetimes of all live registers. */ + } + + if (dflow->flags & DF_RI_LIFE) + { + /* Add the length of the block to all of the registers that were + not referenced, but still live in this block. */ + bitmap_iterator bi; + unsigned int regno; + bitmap_and_compl_into (live, local_processed); EXECUTE_IF_SET_IN_BITMAP (live, 0, regno, bi) { - problem_data->lifetime[regno]++; + REG_LIVE_LENGTH (regno) += luid; } + bitmap_clear (local_processed); + bitmap_clear (local_live); } } @@ -3172,16 +3652,50 @@ df_ri_compute (struct dataflow *dflow, bitmap all_blocks ATTRIBUTE_UNUSED, { unsigned int bb_index; bitmap_iterator bi; - bitmap live; + bitmap live = BITMAP_ALLOC (NULL); + bitmap do_not_gen = BITMAP_ALLOC (NULL); + bitmap artificial_uses = BITMAP_ALLOC (NULL); + bitmap local_live = NULL; + bitmap local_processed = NULL; + bitmap setjumps_crossed = NULL; + + if (dflow->flags & DF_RI_LIFE) + { + local_live = BITMAP_ALLOC (NULL); + local_processed = BITMAP_ALLOC (NULL); + setjumps_crossed = BITMAP_ALLOC (NULL); + } - live = BITMAP_ALLOC (NULL); + +#ifdef REG_DEAD_DEBUGGING + df_lr_dump (dflow->df->problems_by_index [DF_LR], stderr); + print_rtl_with_bb (stderr, get_insns()); +#endif EXECUTE_IF_SET_IN_BITMAP (blocks_to_scan, 0, bb_index, bi) { - df_ri_bb_compute (dflow, bb_index, live); + df_ri_bb_compute (dflow, bb_index, live, do_not_gen, artificial_uses, + local_live, local_processed, setjumps_crossed); } BITMAP_FREE (live); + BITMAP_FREE (do_not_gen); + BITMAP_FREE (artificial_uses); + if (dflow->flags & DF_RI_LIFE) + { + bitmap_iterator bi; + unsigned int regno; + /* See the setjump comment in df_ri_bb_compute. */ + EXECUTE_IF_SET_IN_BITMAP (setjumps_crossed, 0, regno, bi) + { + REG_BASIC_BLOCK (regno) = REG_BLOCK_UNKNOWN; + REG_LIVE_LENGTH (regno) = -1; + } + + BITMAP_FREE (local_live); + BITMAP_FREE (local_processed); + BITMAP_FREE (setjumps_crossed); + } } @@ -3190,10 +3704,6 @@ df_ri_compute (struct dataflow *dflow, bitmap all_blocks ATTRIBUTE_UNUSED, static void df_ri_free (struct dataflow *dflow) { - struct df_ri_problem_data *problem_data = - (struct df_ri_problem_data *) dflow->problem_data; - - free (problem_data->lifetime); free (dflow->problem_data); free (dflow); } @@ -3204,14 +3714,12 @@ df_ri_free (struct dataflow *dflow) static void df_ri_dump (struct dataflow *dflow, FILE *file) { - struct df_ri_problem_data *problem_data = - (struct df_ri_problem_data *) dflow->problem_data; - int j; + print_rtl_with_bb (file, get_insns ()); - fprintf (file, "Register info:\n"); - for (j = 0; j < max_reg_num (); j++) + if (dflow->flags & DF_RI_LIFE) { - fprintf (file, "reg %d life %d\n", j, problem_data->lifetime[j]); + fprintf (file, "Register info:\n"); + dump_flow_info (file, -1); } } @@ -3233,7 +3741,12 @@ static struct df_problem problem_RI = NULL, /* Finalize function. */ df_ri_free, /* Free all of the problem information. */ df_ri_dump, /* Debugging. */ - &problem_UR /* Dependent problem. */ + + /* Technically this is only dependent on the live registers problem + but it will produce infomation if built one of uninitialized + register problems (UR, UREC) is also run. */ + df_lr_add_problem, /* Dependent problem. */ + 0 /* Changeable flags. */ }; @@ -3242,20 +3755,7 @@ static struct df_problem problem_RI = solution. */ struct dataflow * -df_ri_add_problem (struct df *df) +df_ri_add_problem (struct df *df, int flags) { - return df_add_problem (df, &problem_RI); + return df_add_problem (df, &problem_RI, flags); } - - -/* Return total lifetime (in insns) of REG. */ -int -df_reg_lifetime (struct df *df, rtx reg) -{ - struct dataflow *dflow = df->problems_by_index[DF_RI]; - struct df_ri_problem_data *problem_data = - (struct df_ri_problem_data *) dflow->problem_data; - return problem_data->lifetime[REGNO (reg)]; -} - - |