From: Daniel Berlin Date: Fri, 19 May 2006 21:18:23 +0000 (+0000) Subject: re PR rtl-optimization/26855 (ICE in add_deps_for_def with -fmodulo-sched -maltivec) X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=23249ac43c6d4d9dde16347bc44dc757e41f1d8d;p=platform%2Fupstream%2Fgcc.git re PR rtl-optimization/26855 (ICE in add_deps_for_def with -fmodulo-sched -maltivec) 2006-05-19 Daniel Berlin Kenneth Zadeck 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 --- diff --git a/gcc/df-core.c b/gcc/df-core.c index 0619c20..1d4aff2 100644 --- a/gcc/df-core.c +++ b/gcc/df-core.c @@ -45,7 +45,7 @@ Here is an example of using the dataflow routines. df = df_init (init_flags); - df_add_problem (df, problem); + df_add_problem (df, problem, flags); df_set_blocks (df, blocks); @@ -63,21 +63,20 @@ DF_INIT simply creates a poor man's object (df) that needs to be passed to all the dataflow routines. df_finish destroys this object and frees up any allocated memory. -There are two flags that can be passed to df_init: - -DF_NO_SCAN means that no scanning of the rtl code is performed. This -is used if the problem instance is to do it's own scanning. +There are three flags that can be passed to df_init, each of these +flags controls the scanning of the rtl: DF_HARD_REGS means that the scanning is to build information about both pseudo registers and hardware registers. Without this information, the problems will be solved only on pseudo registers. - +DF_EQUIV_NOTES marks the uses present in EQUIV/EQUAL notes. +DF_SUBREGS return subregs rather than the inner reg. DF_ADD_PROBLEM adds a problem, defined by an instance to struct df_problem, to the set of problems solved in this instance of df. All calls to add a problem for a given instance of df must occur before -the first call to DF_RESCAN_BLOCKS or DF_ANALYZE. +the first call to DF_RESCAN_BLOCKS, DF_SET_BLOCKS or DF_ANALYZE. For all of the problems defined in df-problems.c, there are convenience functions named DF_*_ADD_PROBLEM. @@ -297,7 +296,7 @@ are write-only operations. static struct df *ddf = NULL; struct df *shared_df = NULL; -static void * df_get_bb_info (struct dataflow *, unsigned int); +static void *df_get_bb_info (struct dataflow *, unsigned int); static void df_set_bb_info (struct dataflow *, unsigned int, void *); /*---------------------------------------------------------------------------- Functions to create, destroy and manipulate an instance of df. @@ -311,14 +310,13 @@ struct df * df_init (int flags) { struct df *df = XCNEW (struct df); - df->flags = flags; /* This is executed once per compilation to initialize platform specific data structures. */ df_hard_reg_init (); /* All df instance must define the scanning problem. */ - df_scan_add_problem (df); + df_scan_add_problem (df, flags); ddf = df; return df; } @@ -326,13 +324,13 @@ df_init (int flags) /* Add PROBLEM to the DF instance. */ struct dataflow * -df_add_problem (struct df *df, struct df_problem *problem) +df_add_problem (struct df *df, struct df_problem *problem, int flags) { struct dataflow *dflow; /* First try to add the dependent problem. */ - if (problem->dependent_problem) - df_add_problem (df, problem->dependent_problem); + if (problem->dependent_problem_fun) + (problem->dependent_problem_fun) (df, 0); /* Check to see if this problem has already been defined. If it has, just return that instance, if not, add it to the end of the @@ -343,6 +341,7 @@ df_add_problem (struct df *df, struct df_problem *problem) /* Make a new one and add it to the end. */ dflow = XCNEW (struct dataflow); + dflow->flags = flags; dflow->df = df; dflow->problem = problem; df->problems_in_order[df->num_problems_defined++] = dflow; @@ -352,6 +351,36 @@ df_add_problem (struct df *df, struct df_problem *problem) } +/* Set the MASK flags in the DFLOW problem. The old flags are + returned. If a flag is not allowed to be changed this will fail if + checking is enabled. */ +int +df_set_flags (struct dataflow *dflow, int mask) +{ + int old_flags = dflow->flags; + + gcc_assert (!(mask & (~dflow->problem->changeable_flags))); + + dflow->flags |= mask; + + return old_flags; +} + +/* Clear the MASK flags in the DFLOW problem. The old flags are + returned. If a flag is not allowed to be changed this will fail if + checking is enabled. */ +int +df_clear_flags (struct dataflow *dflow, int mask) +{ + int old_flags = dflow->flags; + + gcc_assert (!(mask & (~dflow->problem->changeable_flags))); + + dflow->flags &= !mask; + + return old_flags; +} + /* Set the blocks that are to be considered for analysis. If this is not called or is called with null, the entire function in analyzed. */ @@ -435,6 +464,26 @@ df_set_blocks (struct df *df, bitmap blocks) } +/* Free all of the per basic block dataflow from all of the problems. + This is typically called before a basic block is deleted and the + problem will be reanalyzed. */ + +void +df_delete_basic_block (struct df *df, int bb_index) +{ + basic_block bb = BASIC_BLOCK (bb_index); + int i; + + for (i = 0; i < df->num_problems_defined; i++) + { + struct dataflow *dflow = df->problems_in_order[i]; + if (dflow->problem->free_bb_fun) + dflow->problem->free_bb_fun + (dflow, bb, df_get_bb_info (dflow, bb_index)); + } +} + + /* Free all the dataflow info and the DF structure. This should be called from the df_finish macro which also NULLs the parm. */ @@ -594,6 +643,8 @@ df_iterative_dataflow (struct dataflow *dataflow, sbitmap_zero (pending); sbitmap_zero (considered); + gcc_assert (dataflow->problem->dir); + EXECUTE_IF_SET_IN_BITMAP (blocks_to_consider, 0, idx, bi) { SET_BIT (considered, idx); @@ -696,7 +747,7 @@ df_prune_to_subcfg (int list[], unsigned len, bitmap blocks) small fixup fringe sub sub */ -static void +void df_analyze_problem (struct dataflow *dflow, bitmap blocks_to_consider, bitmap blocks_to_init, @@ -705,7 +756,7 @@ df_analyze_problem (struct dataflow *dflow, { /* (Re)Allocate the datastructures necessary to solve the problem. */ if (dflow->problem->alloc_fun) - dflow->problem->alloc_fun (dflow, blocks_to_scan); + dflow->problem->alloc_fun (dflow, blocks_to_scan, blocks_to_init); /* Set up the problem and compute the local information. This function is passed both the blocks_to_consider and the @@ -1066,7 +1117,7 @@ df_dump (struct df *df, FILE *file) { int i; - if (! df || ! file) + if (!df || !file) return; fprintf (file, "\n\n%s\n", current_function_name ()); @@ -1082,8 +1133,7 @@ df_dump (struct df *df, FILE *file) void -df_refs_chain_dump (struct df *df, struct df_ref *ref, - bool follow_chain, FILE *file) +df_refs_chain_dump (struct df_ref *ref, bool follow_chain, FILE *file) { fprintf (file, "{ "); while (ref) @@ -1093,7 +1143,7 @@ df_refs_chain_dump (struct df *df, struct df_ref *ref, DF_REF_ID (ref), DF_REF_REGNO (ref)); if (follow_chain) - df_chain_dump (df, DF_REF_CHAIN (ref), file); + df_chain_dump (DF_REF_CHAIN (ref), file); ref = ref->next_ref; } fprintf (file, "}"); @@ -1118,13 +1168,32 @@ df_regs_chain_dump (struct df *df ATTRIBUTE_UNUSED, struct df_ref *ref, FILE *f } -void -df_insn_debug (struct df *df, rtx insn, bool follow_chain, FILE *file) +static void +df_mws_dump (struct df_mw_hardreg *mws, FILE *file) { - unsigned int uid; - int bbi; + while (mws) + { + struct df_link *regs = mws->regs; + fprintf (file, "%c%d(", + (mws->type == DF_REF_REG_DEF) ? 'd' : 'u', + DF_REF_REGNO (regs->ref)); + while (regs) + { + fprintf (file, "%d ", DF_REF_REGNO (regs->ref)); + regs = regs->next; + } - uid = INSN_UID (insn); + fprintf (file, ") "); + mws = mws->next; + } +} + + +static void +df_insn_uid_debug (struct df *df, unsigned int uid, + bool follow_chain, FILE *file) +{ + int bbi; if (DF_INSN_UID_DEFS (df, uid)) bbi = DF_REF_BBNO (DF_INSN_UID_DEFS (df, uid)); @@ -1133,15 +1202,36 @@ df_insn_debug (struct df *df, rtx insn, bool follow_chain, FILE *file) else bbi = -1; - fprintf (file, "insn %d bb %d luid %d defs ", - uid, bbi, DF_INSN_LUID (df, insn)); + fprintf (file, "insn %d bb %d luid %d", + uid, bbi, DF_INSN_UID_LUID (df, uid)); - df_refs_chain_dump (df, DF_INSN_UID_DEFS (df, uid), follow_chain, file); - fprintf (file, " defs "); - df_refs_chain_dump (df, DF_INSN_UID_USES (df, uid), follow_chain, file); + if (DF_INSN_UID_DEFS (df, uid)) + { + fprintf (file, " defs "); + df_refs_chain_dump (DF_INSN_UID_DEFS (df, uid), follow_chain, file); + } + + if (DF_INSN_UID_USES (df, uid)) + { + fprintf (file, " uses "); + df_refs_chain_dump (DF_INSN_UID_USES (df, uid), follow_chain, file); + } + + if (DF_INSN_UID_MWS (df, uid)) + { + fprintf (file, " mws "); + df_mws_dump (DF_INSN_UID_MWS (df, uid), file); + } fprintf (file, "\n"); } + +void +df_insn_debug (struct df *df, rtx insn, bool follow_chain, FILE *file) +{ + df_insn_uid_debug (df, INSN_UID (insn), follow_chain, file); +} + void df_insn_debug_regno (struct df *df, rtx insn, FILE *file) { @@ -1177,17 +1267,17 @@ df_regno_debug (struct df *df, unsigned int regno, FILE *file) void -df_ref_debug (struct df *df, struct df_ref *ref, FILE *file) +df_ref_debug (struct df_ref *ref, FILE *file) { fprintf (file, "%c%d ", DF_REF_REG_DEF_P (ref) ? 'd' : 'u', DF_REF_ID (ref)); - fprintf (file, "reg %d bb %d luid %d insn %d chain ", + fprintf (file, "reg %d bb %d insn %d flag %x chain ", DF_REF_REGNO (ref), DF_REF_BBNO (ref), - DF_REF_INSN (ref) ? DF_INSN_LUID (df, DF_REF_INSN (ref)) : -1, - DF_REF_INSN (ref) ? INSN_UID (DF_REF_INSN (ref)) : -1); - df_chain_dump (df, DF_REF_CHAIN (ref), file); + DF_REF_INSN (ref) ? INSN_UID (DF_REF_INSN (ref)) : -1, + DF_REF_FLAGS (ref)); + df_chain_dump (DF_REF_CHAIN (ref), file); fprintf (file, "\n"); } @@ -1218,27 +1308,27 @@ debug_df_regno (unsigned int regno) void debug_df_ref (struct df_ref *ref) { - df_ref_debug (ddf, ref, stderr); + df_ref_debug (ref, stderr); } void debug_df_defno (unsigned int defno) { - df_ref_debug (ddf, DF_DEFS_GET (ddf, defno), stderr); + df_ref_debug (DF_DEFS_GET (ddf, defno), stderr); } void debug_df_useno (unsigned int defno) { - df_ref_debug (ddf, DF_USES_GET (ddf, defno), stderr); + df_ref_debug (DF_USES_GET (ddf, defno), stderr); } void debug_df_chain (struct df_link *link) { - df_chain_dump (ddf, link, stderr); + df_chain_dump (link, stderr); fputc ('\n', stderr); } 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)]; -} - - diff --git a/gcc/df-scan.c b/gcc/df-scan.c index b35c3a4..46dfb07 100644 --- a/gcc/df-scan.c +++ b/gcc/df-scan.c @@ -65,9 +65,6 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #define EPILOGUE_USES(REGNO) 0 #endif -/* Indicates where we are in the compilation. */ -int df_state; - /* The bitmap_obstack is used to hold some static variables that should not be reset after each function is compiled. */ @@ -122,6 +119,8 @@ struct df_scan_problem_data alloc_pool ref_pool; alloc_pool insn_pool; alloc_pool reg_pool; + alloc_pool mw_reg_pool; + alloc_pool mw_link_pool; }; typedef struct df_scan_bb_info *df_scan_bb_info_t; @@ -130,8 +129,8 @@ static void df_scan_free_internal (struct dataflow *dflow) { struct df *df = dflow->df; - struct df_scan_problem_data *problem_data = - (struct df_scan_problem_data *) dflow->problem_data; + struct df_scan_problem_data *problem_data + = (struct df_scan_problem_data *) dflow->problem_data; free (df->def_info.regs); free (df->def_info.refs); @@ -157,6 +156,8 @@ df_scan_free_internal (struct dataflow *dflow) free_alloc_pool (problem_data->ref_pool); free_alloc_pool (problem_data->insn_pool); free_alloc_pool (problem_data->reg_pool); + free_alloc_pool (problem_data->mw_reg_pool); + free_alloc_pool (problem_data->mw_link_pool); } @@ -200,7 +201,8 @@ df_scan_free_bb_info (struct dataflow *dflow, basic_block bb, void *vbb_info) be rescanned. */ static void -df_scan_alloc (struct dataflow *dflow, bitmap blocks_to_rescan) +df_scan_alloc (struct dataflow *dflow, bitmap blocks_to_rescan, + bitmap all_blocks ATTRIBUTE_UNUSED) { struct df *df = dflow->df; struct df_scan_problem_data *problem_data; @@ -231,6 +233,12 @@ df_scan_alloc (struct dataflow *dflow, bitmap blocks_to_rescan) problem_data->reg_pool = create_alloc_pool ("df_scan_reg pool", sizeof (struct df_reg_info), block_size); + problem_data->mw_reg_pool + = create_alloc_pool ("df_scan_mw_reg pool", + sizeof (struct df_mw_hardreg), block_size); + problem_data->mw_link_pool + = create_alloc_pool ("df_scan_mw_link pool", + sizeof (struct df_link), block_size); insn_num += insn_num / 4; df_grow_reg_info (dflow, &df->def_info); @@ -319,7 +327,8 @@ static struct df_problem problem_SCAN = NULL, /* Finalize function. */ df_scan_free, /* Free all of the problem information. */ df_scan_dump, /* Debugging. */ - NULL /* Dependent problem. */ + NULL, /* Dependent problem. */ + 0 /* Changeable flags. */ }; @@ -328,9 +337,9 @@ static struct df_problem problem_SCAN = solution. */ struct dataflow * -df_scan_add_problem (struct df *df) +df_scan_add_problem (struct df *df, int flags) { - return df_add_problem (df, &problem_SCAN); + return df_add_problem (df, &problem_SCAN, flags); } /*---------------------------------------------------------------------------- @@ -350,8 +359,8 @@ df_grow_reg_info (struct dataflow *dflow, struct df_ref_info *ref_info) { unsigned int max_reg = max_reg_num (); unsigned int new_size = max_reg; - struct df_scan_problem_data *problem_data = - (struct df_scan_problem_data *) dflow->problem_data; + struct df_scan_problem_data *problem_data + = (struct df_scan_problem_data *) dflow->problem_data; unsigned int i; if (ref_info->regs_size < new_size) @@ -432,6 +441,9 @@ df_rescan_blocks (struct df *df, bitmap blocks) if (blocks) { int i; + unsigned int bb_index; + bitmap_iterator bi; + bool cleared_bits = false; /* Need to assure that there are space in all of the tables. */ unsigned int insn_num = get_max_uid () + 1; @@ -447,6 +459,20 @@ df_rescan_blocks (struct df *df, bitmap blocks) df_grow_bb_info (dflow); bitmap_copy (local_blocks_to_scan, blocks); + + EXECUTE_IF_SET_IN_BITMAP (blocks, 0, bb_index, bi) + { + basic_block bb = BASIC_BLOCK (bb_index); + if (!bb) + { + bitmap_clear_bit (local_blocks_to_scan, bb_index); + cleared_bits = true; + } + } + + if (cleared_bits) + bitmap_copy (blocks, local_blocks_to_scan); + df->def_info.add_refs_inline = true; df->use_info.add_refs_inline = true; @@ -490,7 +516,7 @@ df_rescan_blocks (struct df *df, bitmap blocks) { bitmap_set_bit (local_blocks_to_scan, bb->index); } - df_scan_alloc (dflow, local_blocks_to_scan); + df_scan_alloc (dflow, local_blocks_to_scan, NULL); df->def_info.add_refs_inline = false; df->use_info.add_refs_inline = false; @@ -508,6 +534,7 @@ df_rescan_blocks (struct df *df, bitmap blocks) BITMAP_FREE (local_blocks_to_scan); } + /* Create a new ref of type DF_REF_TYPE for register REG at address LOC within INSN of BB. */ @@ -634,8 +661,8 @@ df_reg_chain_unlink (struct dataflow *dflow, struct df_ref *ref) struct df *df = dflow->df; struct df_ref *next = DF_REF_NEXT_REG (ref); struct df_ref *prev = DF_REF_PREV_REG (ref); - struct df_scan_problem_data *problem_data = - (struct df_scan_problem_data *) dflow->problem_data; + struct df_scan_problem_data *problem_data + = (struct df_scan_problem_data *) dflow->problem_data; struct df_reg_info *reg_info; struct df_ref *next_ref = ref->next_ref; unsigned int id = DF_REF_ID (ref); @@ -697,8 +724,8 @@ df_ref_remove (struct df *df, struct df_ref *ref) = df_ref_unlink (bb_info->artificial_defs, ref); } else - DF_INSN_UID_DEFS (df, DF_REF_INSN_UID (ref)) = - df_ref_unlink (DF_INSN_UID_DEFS (df, DF_REF_INSN_UID (ref)), ref); + DF_INSN_UID_DEFS (df, DF_REF_INSN_UID (ref)) + = df_ref_unlink (DF_INSN_UID_DEFS (df, DF_REF_INSN_UID (ref)), ref); if (df->def_info.add_refs_inline) DF_DEFS_SET (df, DF_REF_ID (ref), NULL); @@ -713,8 +740,8 @@ df_ref_remove (struct df *df, struct df_ref *ref) = df_ref_unlink (bb_info->artificial_uses, ref); } else - DF_INSN_UID_USES (df, DF_REF_INSN_UID (ref)) = - df_ref_unlink (DF_INSN_UID_USES (df, DF_REF_INSN_UID (ref)), ref); + DF_INSN_UID_USES (df, DF_REF_INSN_UID (ref)) + = df_ref_unlink (DF_INSN_UID_USES (df, DF_REF_INSN_UID (ref)), ref); if (df->use_info.add_refs_inline) DF_USES_SET (df, DF_REF_ID (ref), NULL); @@ -730,8 +757,8 @@ static struct df_insn_info * df_insn_create_insn_record (struct dataflow *dflow, rtx insn) { struct df *df = dflow->df; - struct df_scan_problem_data *problem_data = - (struct df_scan_problem_data *) dflow->problem_data; + struct df_scan_problem_data *problem_data + = (struct df_scan_problem_data *) dflow->problem_data; struct df_insn_info *insn_rec = DF_INSN_GET (df, insn); if (!insn_rec) @@ -754,14 +781,31 @@ df_insn_refs_delete (struct dataflow *dflow, rtx insn) unsigned int uid = INSN_UID (insn); struct df_insn_info *insn_info = NULL; struct df_ref *ref; - struct df_scan_problem_data *problem_data = - (struct df_scan_problem_data *) dflow->problem_data; + struct df_scan_problem_data *problem_data + = (struct df_scan_problem_data *) dflow->problem_data; if (uid < df->insns_size) insn_info = DF_INSN_UID_GET (df, uid); if (insn_info) { + struct df_mw_hardreg *hardregs = insn_info->mw_hardregs; + + while (hardregs) + { + struct df_mw_hardreg *next_hr = hardregs->next; + struct df_link *link = hardregs->regs; + while (link) + { + struct df_link *next_l = link->next; + pool_free (problem_data->mw_link_pool, link); + link = next_l; + } + + pool_free (problem_data->mw_reg_pool, hardregs); + hardregs = next_hr; + } + ref = insn_info->defs; while (ref) ref = df_reg_chain_unlink (dflow, ref); @@ -876,20 +920,6 @@ df_reorganize_refs (struct df_ref_info *ref_info) } -/* Local miscellaneous routines. */ - -/* Local routines for recording refs. */ - -/* Set where we are in the compilation. */ - -void -df_set_state (int state) -{ - df_state = state; -} - - - /*---------------------------------------------------------------------------- Hard core instruction scanning code. No external interfaces here, just a lot of routines that look inside insns. @@ -906,8 +936,8 @@ df_ref_create_structure (struct dataflow *dflow, rtx reg, rtx *loc, struct df_ref *this_ref; struct df *df = dflow->df; int regno = REGNO (GET_CODE (reg) == SUBREG ? SUBREG_REG (reg) : reg); - struct df_scan_problem_data *problem_data = - (struct df_scan_problem_data *) dflow->problem_data; + struct df_scan_problem_data *problem_data + = (struct df_scan_problem_data *) dflow->problem_data; this_ref = pool_alloc (problem_data->ref_pool); DF_REF_REG (this_ref) = reg; @@ -922,76 +952,88 @@ df_ref_create_structure (struct dataflow *dflow, rtx reg, rtx *loc, /* Link the ref into the reg_def and reg_use chains and keep a count of the instances. */ - if (ref_type == DF_REF_REG_DEF) + switch (ref_type) { - struct df_reg_info *reg_info = DF_REG_DEF_GET (df, regno); - reg_info->n_refs++; - - /* Add the ref to the reg_def chain. */ - df_reg_chain_create (reg_info, this_ref); - DF_REF_ID (this_ref) = df->def_info.bitmap_size; - if (df->def_info.add_refs_inline) - { - if (DF_DEFS_SIZE (df) >= df->def_info.refs_size) - { - int new_size = df->def_info.bitmap_size - + df->def_info.bitmap_size / 4; - df_grow_ref_info (&df->def_info, new_size); - } - /* Add the ref to the big array of defs. */ - DF_DEFS_SET (df, df->def_info.bitmap_size, this_ref); - df->def_info.refs_organized = false; - } - - df->def_info.bitmap_size++; + case DF_REF_REG_DEF: + { + struct df_reg_info *reg_info = DF_REG_DEF_GET (df, regno); + reg_info->n_refs++; + + /* Add the ref to the reg_def chain. */ + df_reg_chain_create (reg_info, this_ref); + DF_REF_ID (this_ref) = df->def_info.bitmap_size; + if (df->def_info.add_refs_inline) + { + if (DF_DEFS_SIZE (df) >= df->def_info.refs_size) + { + int new_size = df->def_info.bitmap_size + + df->def_info.bitmap_size / 4; + df_grow_ref_info (&df->def_info, new_size); + } + /* Add the ref to the big array of defs. */ + DF_DEFS_SET (df, df->def_info.bitmap_size, this_ref); + df->def_info.refs_organized = false; + } + + df->def_info.bitmap_size++; + + if (DF_REF_FLAGS (this_ref) & DF_REF_ARTIFICIAL) + { + struct df_scan_bb_info *bb_info + = df_scan_get_bb_info (dflow, bb->index); + this_ref->next_ref = bb_info->artificial_defs; + bb_info->artificial_defs = this_ref; + } + else + { + this_ref->next_ref = DF_INSN_GET (df, insn)->defs; + DF_INSN_GET (df, insn)->defs = this_ref; + } + } + break; - if (DF_REF_FLAGS (this_ref) & DF_REF_ARTIFICIAL) - { - struct df_scan_bb_info *bb_info - = df_scan_get_bb_info (dflow, bb->index); - this_ref->next_ref = bb_info->artificial_defs; - bb_info->artificial_defs = this_ref; - } - else - { - this_ref->next_ref = DF_INSN_GET (df, insn)->defs; - DF_INSN_GET (df, insn)->defs = this_ref; - } - } - else - { - struct df_reg_info *reg_info = DF_REG_USE_GET (df, regno); - reg_info->n_refs++; + case DF_REF_REG_MEM_LOAD: + case DF_REF_REG_MEM_STORE: + case DF_REF_REG_USE: + { + struct df_reg_info *reg_info = DF_REG_USE_GET (df, regno); + reg_info->n_refs++; + + /* Add the ref to the reg_use chain. */ + df_reg_chain_create (reg_info, this_ref); + DF_REF_ID (this_ref) = df->use_info.bitmap_size; + if (df->use_info.add_refs_inline) + { + if (DF_USES_SIZE (df) >= df->use_info.refs_size) + { + int new_size = df->use_info.bitmap_size + + df->use_info.bitmap_size / 4; + df_grow_ref_info (&df->use_info, new_size); + } + /* Add the ref to the big array of defs. */ + DF_USES_SET (df, df->use_info.bitmap_size, this_ref); + df->use_info.refs_organized = false; + } + + df->use_info.bitmap_size++; + if (DF_REF_FLAGS (this_ref) & DF_REF_ARTIFICIAL) + { + struct df_scan_bb_info *bb_info + = df_scan_get_bb_info (dflow, bb->index); + this_ref->next_ref = bb_info->artificial_uses; + bb_info->artificial_uses = this_ref; + } + else + { + this_ref->next_ref = DF_INSN_GET (df, insn)->uses; + DF_INSN_GET (df, insn)->uses = this_ref; + } + } + break; - /* Add the ref to the reg_use chain. */ - df_reg_chain_create (reg_info, this_ref); - DF_REF_ID (this_ref) = df->use_info.bitmap_size; - if (df->use_info.add_refs_inline) - { - if (DF_USES_SIZE (df) >= df->use_info.refs_size) - { - int new_size = df->use_info.bitmap_size - + df->use_info.bitmap_size / 4; - df_grow_ref_info (&df->use_info, new_size); - } - /* Add the ref to the big array of defs. */ - DF_USES_SET (df, df->use_info.bitmap_size, this_ref); - df->use_info.refs_organized = false; - } + default: + gcc_unreachable (); - df->use_info.bitmap_size++; - if (DF_REF_FLAGS (this_ref) & DF_REF_ARTIFICIAL) - { - struct df_scan_bb_info *bb_info - = df_scan_get_bb_info (dflow, bb->index); - this_ref->next_ref = bb_info->artificial_uses; - bb_info->artificial_uses = this_ref; - } - else - { - this_ref->next_ref = DF_INSN_GET (df, insn)->uses; - DF_INSN_GET (df, insn)->uses = this_ref; - } } return this_ref; } @@ -1007,8 +1049,9 @@ df_ref_record (struct dataflow *dflow, rtx reg, rtx *loc, enum df_ref_flags ref_flags, bool record_live) { - unsigned int regno; struct df *df = dflow->df; + rtx oldreg = reg; + unsigned int regno; gcc_assert (REG_P (reg) || GET_CODE (reg) == SUBREG); @@ -1017,7 +1060,7 @@ df_ref_record (struct dataflow *dflow, rtx reg, rtx *loc, reg. As written in the docu those should have the form (subreg:SI (reg:M A) N), with size(SImode) > size(Mmode). XXX Is that true? We could also use the global word_mode variable. */ - if ((df->flags & DF_SUBREGS) == 0 + if ((dflow->flags & DF_SUBREGS) == 0 && GET_CODE (reg) == SUBREG && (GET_MODE_SIZE (GET_MODE (reg)) < GET_MODE_SIZE (word_mode) || GET_MODE_SIZE (GET_MODE (reg)) @@ -1031,10 +1074,13 @@ df_ref_record (struct dataflow *dflow, rtx reg, rtx *loc, regno = REGNO (GET_CODE (reg) == SUBREG ? SUBREG_REG (reg) : reg); if (regno < FIRST_PSEUDO_REGISTER) { - int i; - int endregno; + unsigned int i; + unsigned int endregno; + struct df_mw_hardreg *hardreg = NULL; + struct df_scan_problem_data *problem_data + = (struct df_scan_problem_data *) dflow->problem_data; - if (! (df->flags & DF_HARD_REGS)) + if (!(dflow->flags & DF_HARD_REGS)) return; /* GET_MODE (reg) is correct here. We do not want to go into a SUBREG @@ -1048,8 +1094,30 @@ df_ref_record (struct dataflow *dflow, rtx reg, rtx *loc, SUBREG_BYTE (reg), GET_MODE (reg)); endregno += regno; + /* If this is a multiword hardreg, we create some extra datastructures that + will enable us to easily build REG_DEAD and REG_UNUSED notes. */ + if ((endregno != regno + 1) && insn) + { + struct df_insn_info *insn_info = DF_INSN_GET (df, insn); + /* Sets to a subreg of a multiword register are partial. + Sets to a non-subreg of a multiword register are not. */ + if (GET_CODE (oldreg) == SUBREG) + ref_flags |= DF_REF_PARTIAL; + ref_flags |= DF_REF_MW_HARDREG; + hardreg = pool_alloc (problem_data->mw_reg_pool); + hardreg->next = insn_info->mw_hardregs; + insn_info->mw_hardregs = hardreg; + hardreg->type = ref_type; + hardreg->flags = ref_flags; + hardreg->mw_reg = reg; + hardreg->regs = NULL; + + } + for (i = regno; i < endregno; i++) { + struct df_ref *ref; + /* Calls are handled at call site because regs_ever_live doesn't include clobbered regs, only used ones. */ if (ref_type == DF_REF_REG_DEF && record_live) @@ -1061,14 +1129,22 @@ df_ref_record (struct dataflow *dflow, rtx reg, rtx *loc, { /* Set regs_ever_live on uses of non-eliminable frame pointers and arg pointers. */ - if (! (TEST_HARD_REG_BIT (elim_reg_set, regno) + if (!(TEST_HARD_REG_BIT (elim_reg_set, regno) && (regno == FRAME_POINTER_REGNUM || regno == ARG_POINTER_REGNUM))) regs_ever_live[i] = 1; } - df_ref_create_structure (dflow, regno_reg_rtx[i], loc, - bb, insn, ref_type, ref_flags); + ref = df_ref_create_structure (dflow, regno_reg_rtx[i], loc, + bb, insn, ref_type, ref_flags); + if (hardreg) + { + struct df_link *link = pool_alloc (problem_data->mw_link_pool); + + link->next = hardreg->regs; + link->ref = ref; + hardreg->regs = link; + } } } else @@ -1107,6 +1183,7 @@ df_def_record_1 (struct dataflow *dflow, rtx x, { rtx *loc; rtx dst; + bool dst_in_strict_lowpart = false; /* We may recursively call ourselves on EXPR_LIST when dealing with PARALLEL construct. */ @@ -1127,7 +1204,8 @@ df_def_record_1 (struct dataflow *dflow, rtx x, if (GET_CODE (temp) == EXPR_LIST || GET_CODE (temp) == CLOBBER || GET_CODE (temp) == SET) df_def_record_1 (dflow, temp, bb, insn, - GET_CODE (temp) == CLOBBER ? flags | DF_REF_CLOBBER : flags, + GET_CODE (temp) == CLOBBER + ? flags | DF_REF_MUST_CLOBBER : flags, record_live); } return; @@ -1149,10 +1227,20 @@ df_def_record_1 (struct dataflow *dflow, rtx x, } #endif loc = &XEXP (dst, 0); + if (GET_CODE (dst) == STRICT_LOW_PART) + dst_in_strict_lowpart = true; dst = *loc; flags |= DF_REF_READ_WRITE; + } + /* Sets to a subreg of a single word register are partial sets if + they are wrapped in a strict lowpart, and not partial otherwise. + */ + if (GET_CODE (dst) == SUBREG && REG_P (SUBREG_REG (dst)) + && dst_in_strict_lowpart) + flags |= DF_REF_PARTIAL; + if (REG_P (dst) || (GET_CODE (dst) == SUBREG && REG_P (SUBREG_REG (dst)))) df_ref_record (dflow, dst, loc, bb, insn, @@ -1171,7 +1259,7 @@ df_defs_record (struct dataflow *dflow, rtx x, basic_block bb, rtx insn) { /* Mark the single def within the pattern. */ df_def_record_1 (dflow, x, bb, insn, - code == CLOBBER ? DF_REF_CLOBBER : 0, true); + code == CLOBBER ? DF_REF_MUST_CLOBBER : 0, true); } else if (code == COND_EXEC) { @@ -1232,7 +1320,7 @@ df_uses_record (struct dataflow *dflow, rtx *loc, enum df_ref_type ref_type, case SUBREG: /* While we're here, optimize this case. */ - + flags |= DF_REF_PARTIAL; /* In case the SUBREG is not of a REG, do not optimize. */ if (!REG_P (SUBREG_REG (x))) { @@ -1424,8 +1512,8 @@ df_insn_contains_asm (rtx insn) static void df_insn_refs_record (struct dataflow *dflow, basic_block bb, rtx insn) { - int i; struct df *df = dflow->df; + int i; if (INSN_P (insn)) { @@ -1437,7 +1525,7 @@ df_insn_refs_record (struct dataflow *dflow, basic_block bb, rtx insn) /* Record register defs. */ df_defs_record (dflow, PATTERN (insn), bb, insn); - if (df->flags & DF_EQUIV_NOTES) + if (dflow->flags & DF_EQUIV_NOTES) for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) { @@ -1490,7 +1578,7 @@ df_insn_refs_record (struct dataflow *dflow, basic_block bb, rtx insn) DF_REF_REG_USE, bb, insn, 0); - if (df->flags & DF_HARD_REGS) + if (dflow->flags & DF_HARD_REGS) { bitmap_iterator bi; unsigned int ui; @@ -1502,8 +1590,8 @@ df_insn_refs_record (struct dataflow *dflow, basic_block bb, rtx insn) DF_REF_REG_USE, bb, insn, 0); EXECUTE_IF_SET_IN_BITMAP (df_invalidated_by_call, 0, ui, bi) - df_ref_record (dflow, regno_reg_rtx[ui], ®no_reg_rtx[ui], bb, insn, - DF_REF_REG_DEF, DF_REF_CLOBBER, false); + df_ref_record (dflow, regno_reg_rtx[ui], ®no_reg_rtx[ui], bb, + insn, DF_REF_REG_DEF, DF_REF_MAY_CLOBBER, false); } } @@ -1537,6 +1625,10 @@ df_bb_refs_record (struct dataflow *dflow, basic_block bb) rtx insn; int luid = 0; struct df_scan_bb_info *bb_info = df_scan_get_bb_info (dflow, bb->index); + bitmap artificial_uses_at_bottom = NULL; + + if (dflow->flags & DF_HARD_REGS) + artificial_uses_at_bottom = BITMAP_ALLOC (NULL); /* Need to make sure that there is a record in the basic block info. */ if (!bb_info) @@ -1561,7 +1653,7 @@ df_bb_refs_record (struct dataflow *dflow, basic_block bb) } #ifdef EH_RETURN_DATA_REGNO - if ((df->flags & DF_HARD_REGS) + if ((dflow->flags & DF_HARD_REGS) && df_has_eh_preds (bb)) { unsigned int i; @@ -1580,7 +1672,7 @@ df_bb_refs_record (struct dataflow *dflow, basic_block bb) #endif - if ((df->flags & DF_HARD_REGS) + if ((dflow->flags & DF_HARD_REGS) && df_has_eh_preds (bb)) { #ifdef EH_USES @@ -1611,56 +1703,60 @@ df_bb_refs_record (struct dataflow *dflow, basic_block bb) { if (frame_pointer_needed) { - df_uses_record (dflow, ®no_reg_rtx[FRAME_POINTER_REGNUM], - DF_REF_REG_USE, bb, NULL, DF_REF_ARTIFICIAL); + bitmap_set_bit (artificial_uses_at_bottom, FRAME_POINTER_REGNUM); #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM - df_uses_record (dflow, ®no_reg_rtx[HARD_FRAME_POINTER_REGNUM], - DF_REF_REG_USE, bb, NULL, DF_REF_ARTIFICIAL); + bitmap_set_bit (artificial_uses_at_bottom, HARD_FRAME_POINTER_REGNUM); #endif } #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM if (fixed_regs[ARG_POINTER_REGNUM]) - df_uses_record (dflow, ®no_reg_rtx[ARG_POINTER_REGNUM], - DF_REF_REG_USE, bb, NULL, - DF_REF_ARTIFICIAL); + bitmap_set_bit (artificial_uses_at_bottom, ARG_POINTER_REGNUM); #endif } } - if ((df->flags & DF_HARD_REGS) + if ((dflow->flags & DF_HARD_REGS) && bb->index >= NUM_FIXED_BLOCKS) { /* 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. */ - df_uses_record (dflow, ®no_reg_rtx[FRAME_POINTER_REGNUM], - DF_REF_REG_USE, bb, NULL, DF_REF_ARTIFICIAL); + bitmap_set_bit (artificial_uses_at_bottom, FRAME_POINTER_REGNUM); #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM /* Pseudos with argument area equivalences may require reloading via the argument pointer. */ if (fixed_regs[ARG_POINTER_REGNUM]) - df_uses_record (dflow, ®no_reg_rtx[ARG_POINTER_REGNUM], - DF_REF_REG_USE, bb, NULL, - DF_REF_ARTIFICIAL); + bitmap_set_bit (artificial_uses_at_bottom, ARG_POINTER_REGNUM); #endif /* Any constant, or pseudo with constant equivalences, may require reloading from memory using the pic register. */ if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM && fixed_regs[PIC_OFFSET_TABLE_REGNUM]) - df_uses_record (dflow, ®no_reg_rtx[PIC_OFFSET_TABLE_REGNUM], - DF_REF_REG_USE, bb, NULL, - DF_REF_ARTIFICIAL); + bitmap_set_bit (artificial_uses_at_bottom, PIC_OFFSET_TABLE_REGNUM); } /* The all-important stack pointer must always be live. */ - df_uses_record (dflow, ®no_reg_rtx[STACK_POINTER_REGNUM], - DF_REF_REG_USE, bb, NULL, DF_REF_ARTIFICIAL); + bitmap_set_bit (artificial_uses_at_bottom, STACK_POINTER_REGNUM); + } + + if (dflow->flags & DF_HARD_REGS) + { + bitmap_iterator bi; + unsigned int regno; + + EXECUTE_IF_SET_IN_BITMAP (artificial_uses_at_bottom, 0, regno, bi) + { + df_uses_record (dflow, ®no_reg_rtx[regno], + DF_REF_REG_USE, bb, NULL, DF_REF_ARTIFICIAL); + } + + BITMAP_FREE (artificial_uses_at_bottom); } } @@ -1716,16 +1812,16 @@ df_mark_reg (rtx reg, void *vset) entry to the function. */ static void -df_record_entry_block_defs (struct dataflow * dflow) +df_record_entry_block_defs (struct dataflow *dflow) { unsigned int i; bitmap_iterator bi; rtx r; - struct df * df = dflow->df; + struct df *df = dflow->df; bitmap_clear (df->entry_block_defs); - if (! (df->flags & DF_HARD_REGS)) + if (!(dflow->flags & DF_HARD_REGS)) return; for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) @@ -1750,6 +1846,9 @@ df_record_entry_block_defs (struct dataflow * dflow) } else { + /* The always important stack pointer. */ + bitmap_set_bit (df->entry_block_defs, STACK_POINTER_REGNUM); + #ifdef INCOMING_RETURN_ADDR_RTX if (REG_P (INCOMING_RETURN_ADDR_RTX)) bitmap_set_bit (df->entry_block_defs, REGNO (INCOMING_RETURN_ADDR_RTX)); @@ -1771,13 +1870,21 @@ df_record_entry_block_defs (struct dataflow * dflow) bitmap_set_bit (df->entry_block_defs, REGNO (r)); } - /* These registers are live everywhere. */ - if (!reload_completed) + if ((!reload_completed) || frame_pointer_needed) { /* Any reference to any pseudo before reload is a potential reference of the frame pointer. */ bitmap_set_bit (df->entry_block_defs, FRAME_POINTER_REGNUM); +#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM + /* If they are different, also mark the hard frame pointer as live. */ + if (!LOCAL_REGNO (HARD_FRAME_POINTER_REGNUM)) + bitmap_set_bit (df->entry_block_defs, HARD_FRAME_POINTER_REGNUM); +#endif + } + /* These registers are live everywhere. */ + if (!reload_completed) + { #ifdef EH_USES /* The ia-64, the only machine that uses this, does not define these until after reload. */ @@ -1826,15 +1933,15 @@ df_record_exit_block_uses (struct dataflow *dflow) bitmap_clear (df->exit_block_uses); - if (! (df->flags & DF_HARD_REGS)) + if (!(dflow->flags & DF_HARD_REGS)) return; /* If exiting needs the right stack value, consider the stack pointer live at the end of the function. */ if ((HAVE_epilogue && epilogue_completed) - || ! EXIT_IGNORE_STACK - || (! FRAME_POINTER_REQUIRED - && ! current_function_calls_alloca + || !EXIT_IGNORE_STACK + || (!FRAME_POINTER_REQUIRED + && !current_function_calls_alloca && flag_omit_frame_pointer) || current_function_sp_is_unchanging) { @@ -1845,12 +1952,12 @@ df_record_exit_block_uses (struct dataflow *dflow) If we end up eliminating it, it will be removed from the live list of each basic block by reload. */ - if (! reload_completed || frame_pointer_needed) + if ((!reload_completed) || frame_pointer_needed) { bitmap_set_bit (df->exit_block_uses, FRAME_POINTER_REGNUM); #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM /* If they are different, also mark the hard frame pointer as live. */ - if (! LOCAL_REGNO (HARD_FRAME_POINTER_REGNUM)) + if (!LOCAL_REGNO (HARD_FRAME_POINTER_REGNUM)) bitmap_set_bit (df->exit_block_uses, HARD_FRAME_POINTER_REGNUM); #endif } @@ -1875,8 +1982,8 @@ df_record_exit_block_uses (struct dataflow *dflow) { /* Mark all call-saved registers that we actually used. */ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - if (regs_ever_live[i] && ! LOCAL_REGNO (i) - && ! TEST_HARD_REG_BIT (regs_invalidated_by_call, i)) + if (regs_ever_live[i] && !LOCAL_REGNO (i) + && !TEST_HARD_REG_BIT (regs_invalidated_by_call, i)) bitmap_set_bit (df->exit_block_uses, i); } @@ -1893,7 +2000,7 @@ df_record_exit_block_uses (struct dataflow *dflow) #endif #ifdef EH_RETURN_STACKADJ_RTX - if ((! HAVE_epilogue || ! epilogue_completed) + if ((!HAVE_epilogue || ! epilogue_completed) && current_function_calls_eh_return) { rtx tmp = EH_RETURN_STACKADJ_RTX; @@ -1903,7 +2010,7 @@ df_record_exit_block_uses (struct dataflow *dflow) #endif #ifdef EH_RETURN_HANDLER_RTX - if ((! HAVE_epilogue || ! epilogue_completed) + if ((!HAVE_epilogue || ! epilogue_completed) && current_function_calls_eh_return) { rtx tmp = EH_RETURN_HANDLER_RTX; @@ -1915,7 +2022,7 @@ df_record_exit_block_uses (struct dataflow *dflow) /* Mark function return value. */ diddle_return_value (df_mark_reg, (void*) df->exit_block_uses); - if (df->flags & DF_HARD_REGS) + if (dflow->flags & DF_HARD_REGS) EXECUTE_IF_SET_IN_BITMAP (df->exit_block_uses, 0, i, bi) df_uses_record (dflow, ®no_reg_rtx[i], DF_REF_REG_USE, EXIT_BLOCK_PTR, NULL, diff --git a/gcc/df.h b/gcc/df.h index 3a735ae..b1e9384 100644 --- a/gcc/df.h +++ b/gcc/df.h @@ -34,6 +34,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA struct dataflow; struct df; struct df_problem; +struct df_link; /* Data flow problems. All problems must have a unique here. */ /* Scanning is not really a dataflow problem, but it is useful to have @@ -49,10 +50,6 @@ struct df_problem; #define DF_RI 7 /* Register Info. */ #define DF_LAST_PROBLEM_PLUS1 (DF_RI + 1) -/* Flags that control the building of chains. */ -#define DF_DU_CHAIN 1 /* Build DU chains. */ -#define DF_UD_CHAIN 2 /* Build UD chains. */ - /* Dataflow direction. */ enum df_flow_dir @@ -62,10 +59,72 @@ enum df_flow_dir DF_BACKWARD }; + +/* The first of these is a set of a register. The remaining three are + all uses of a register (the mem_load and mem_store relate to how + the register as an addressing operand). */ +enum df_ref_type {DF_REF_REG_DEF, DF_REF_REG_USE, DF_REF_REG_MEM_LOAD, + DF_REF_REG_MEM_STORE}; + +#define DF_REF_TYPE_NAMES {"def", "use", "mem load", "mem store"} + +enum df_ref_flags + { + /* Read-modify-write refs generate both a use and a def and + these are marked with this flag to show that they are not + independent. */ + DF_REF_READ_WRITE = 1, + + /* This flag is set, if we stripped the subreg from the reference. + In this case we must make conservative guesses, at what the + outer mode was. */ + DF_REF_STRIPPED = 2, + + /* If this flag is set, this is not a real definition/use, but an + artificial one created to model always live registers, eh uses, etc. */ + DF_REF_ARTIFICIAL = 4, + + + /* If this flag is set for an artificial use or def, that ref + logically happens at the top of the block. If it is not set + for an artificial use or def, that ref logically happens at the + bottom of the block. This is never set for regular refs. */ + DF_REF_AT_TOP = 8, + + /* This flag is set if the use is inside a REG_EQUAL note. */ + DF_REF_IN_NOTE = 16, + + /* This flag is set if this ref, generally a def, may clobber the + referenced register. This is generally only set for hard + registers that cross a call site. With better information + about calls, some of these could be changed in the future to + DF_REF_MUST_CLOBBER. */ + DF_REF_MAY_CLOBBER = 32, + + /* This flag is set if this ref, generally a def, is a real + clobber. This is not currently set for registers live across a + call because that clobbering may or may not happen. + + Most of the uses of this are with sets that have a + GET_CODE(..)==CLOBBER. Note that this is set even if the + clobber is to a subreg. So in order to tell if the clobber + wipes out the entire register, it is necessary to also check + the DF_REF_PARTIAL flag. */ + DF_REF_MUST_CLOBBER = 64, + + /* This bit is true if this ref is part of a multiword hardreg. */ + DF_REF_MW_HARDREG = 128, + + /* This flag is set if this ref is a partial use or def of the + associated register. */ + DF_REF_PARTIAL = 256 + }; + + /* Function prototypes added to df_problem instance. */ /* Allocate the problem specific data. */ -typedef void (*df_alloc_function) (struct dataflow *, bitmap); +typedef void (*df_alloc_function) (struct dataflow *, bitmap, bitmap); /* This function is called if the problem has global data that needs to be cleared when ever the set of blocks changes. The bitmap @@ -107,6 +166,10 @@ typedef void (*df_free_function) (struct dataflow *); /* Function to dump results to FILE. */ typedef void (*df_dump_problem_function) (struct dataflow *, FILE *); +/* Function to add problem a dataflow problem that must be solved + before this problem can be solved. */ +typedef struct dataflow * (*df_dependent_problem_function) (struct df *, int); + /* The static description of a dataflow problem to solve. See above typedefs for doc for the function fields. */ @@ -127,10 +190,10 @@ struct df_problem { df_finalizer_function finalize_fun; df_free_function free_fun; df_dump_problem_function dump_fun; + df_dependent_problem_function dependent_problem_fun; - /* A dataflow problem that must be solved before this problem can be - solved. */ - struct df_problem *dependent_problem; + /* Flags can be changed after analysis starts. */ + int changeable_flags; }; @@ -151,6 +214,20 @@ struct dataflow /* The pool to allocate the block_info from. */ alloc_pool block_pool; + /* Problem specific control infomation. */ + + /* Scanning flags. */ +#define DF_HARD_REGS 1 /* Mark hard registers. */ +#define DF_EQUIV_NOTES 2 /* Mark uses present in EQUIV/EQUAL notes. */ +#define DF_SUBREGS 4 /* Return subregs rather than the inner reg. */ + /* Flags that control the building of chains. */ +#define DF_DU_CHAIN 1 /* Build DU chains. */ +#define DF_UD_CHAIN 2 /* Build UD chains. */ + /* Flag to control the building of register info. */ +#define DF_RI_LIFE 1 /* Build register info. */ + + int flags; + /* Other problem specific data that is not on a per basic block basis. The structure is generally defined privately for the problem. The exception being the scanning problem where it is @@ -158,17 +235,35 @@ struct dataflow void *problem_data; }; + +/* The set of multiword hardregs used as operands to this + instruction. These are factored into individual uses and defs but + the aggregate is still needed to service the REG_DEAD and + REG_UNUSED notes. */ +struct df_mw_hardreg +{ + rtx mw_reg; /* The multiword hardreg. */ + enum df_ref_type type; /* Used to see if the ref is read or write. */ + enum df_ref_flags flags; /* Various flags. */ + struct df_link *regs; /* The individual regs that make up + this hardreg. */ + struct df_mw_hardreg *next; /* The next mw_hardreg in this insn. */ +}; + + /* One of these structures is allocated for every insn. */ struct df_insn_info { struct df_ref *defs; /* Head of insn-def chain. */ struct df_ref *uses; /* Head of insn-use chain. */ + struct df_mw_hardreg *mw_hardregs; /* ???? The following luid field should be considered private so that we can change it on the fly to accommodate new insns? */ int luid; /* Logical UID. */ bool contains_asm; /* Contains an asm instruction. */ }; + /* Two of these structures are allocated for every pseudo reg, one for the uses and one for the defs. */ struct df_reg_info @@ -178,48 +273,6 @@ struct df_reg_info unsigned int n_refs; /* Number of refs or defs for this pseudo. */ }; - -enum df_ref_type {DF_REF_REG_DEF, DF_REF_REG_USE, DF_REF_REG_MEM_LOAD, - DF_REF_REG_MEM_STORE}; - -#define DF_REF_TYPE_NAMES {"def", "use", "mem load", "mem store"} - -enum df_ref_flags - { - /* Read-modify-write refs generate both a use and a def and - these are marked with this flag to show that they are not - independent. */ - DF_REF_READ_WRITE = 1, - - /* This flag is set, if we stripped the subreg from the reference. - In this case we must make conservative guesses, at what the - outer mode was. */ - DF_REF_STRIPPED = 2, - - /* If this flag is set, this is not a real definition/use, but an - artificial one created to model always live registers, eh uses, etc. */ - DF_REF_ARTIFICIAL = 4, - - - /* If this flag is set for an artificial use or def, that ref - logically happens at the top of the block. If it is not set - for an artificial use or def, that ref logically happens at the - bottom of the block. This is never set for regular refs. */ - DF_REF_AT_TOP = 8, - - /* This flag is set if the use is inside a REG_EQUAL note. */ - DF_REF_IN_NOTE = 16, - - /* This flag is set if this ref is really a clobber, and not a def. */ - DF_REF_CLOBBER = 32, - - /* True if ref is dead (i.e. the next ref is a def or clobber or - the end of the function.) This is only valid the RI problem - has been set in this df instance. */ - DF_REF_DIES_AFTER_THIS_USE = 64 - }; - - /* Define a register reference structure. One of these is allocated for every register reference (use or def). Note some register references (e.g., post_inc, subreg) generate both a def and a use. */ @@ -250,9 +303,9 @@ struct df_ref void *data; /* The data assigned to it by user. */ }; -/* There are two kinds of links: */ - -/* This is used for def-use or use-def chains. */ +/* These links are used for two purposes: + 1) def-use or use-def chains. + 2) Multiword hard registers that underly a single hardware register. */ struct df_link { struct df_ref *ref; @@ -288,12 +341,6 @@ struct df_ref_info struct df { -#define DF_HARD_REGS 1 /* Mark hard registers. */ -#define DF_EQUIV_NOTES 2 /* Mark uses present in EQUIV/EQUAL notes. */ -#define DF_SUBREGS 4 /* Return subregs rather than the inner reg. */ - - int flags; /* Indicates what's recorded. */ - /* The set of problems to be solved is stored in two arrays. In PROBLEMS_IN_ORDER, the problems are stored in the order that they are solved. This is an internally dense array that may have @@ -379,7 +426,7 @@ struct df /* Macros to determine the reference type. */ #define DF_REF_REG_DEF_P(REF) (DF_REF_TYPE (REF) == DF_REF_REG_DEF) -#define DF_REF_REG_USE_P(REF) ((REF) && ! DF_REF_REG_DEF_P (REF)) +#define DF_REF_REG_USE_P(REF) ((REF) && !DF_REF_REG_DEF_P (REF)) #define DF_REF_REG_MEM_STORE_P(REF) (DF_REF_TYPE (REF) == DF_REF_REG_MEM_STORE) #define DF_REF_REG_MEM_LOAD_P(REF) (DF_REF_TYPE (REF) == DF_REF_REG_MEM_LOAD) #define DF_REF_REG_MEM_P(REF) (DF_REF_REG_MEM_STORE_P (REF) \ @@ -398,8 +445,10 @@ struct df #define DF_REG_SIZE(DF) ((DF)->def_info.regs_inited) #define DF_REG_DEF_GET(DF, REG) ((DF)->def_info.regs[(REG)]) #define DF_REG_DEF_SET(DF, REG, VAL) ((DF)->def_info.regs[(REG)]=(VAL)) +#define DF_REG_DEF_COUNT(DF, REG) ((DF)->def_info.regs[(REG)]->n_refs) #define DF_REG_USE_GET(DF, REG) ((DF)->use_info.regs[(REG)]) #define DF_REG_USE_SET(DF, REG, VAL) ((DF)->use_info.regs[(REG)]=(VAL)) +#define DF_REG_USE_COUNT(DF, REG) ((DF)->use_info.regs[(REG)]->n_refs) /* Macros to access the elements within the reg_info structure table. */ @@ -422,27 +471,13 @@ struct df #define DF_INSN_UID_LUID(DF, INSN) (DF_INSN_UID_GET(DF,INSN)->luid) #define DF_INSN_UID_DEFS(DF, INSN) (DF_INSN_UID_GET(DF,INSN)->defs) #define DF_INSN_UID_USES(DF, INSN) (DF_INSN_UID_GET(DF,INSN)->uses) +#define DF_INSN_UID_MWS(DF, INSN) (DF_INSN_UID_GET(DF,INSN)->mw_hardregs) /* This is a bitmap copy of regs_invalidated_by_call so that we can easily add it into bitmaps, etc. */ extern bitmap df_invalidated_by_call; -/* Initialize ur_in and ur_out as if all hard registers were partially -available. */ - -/* The way that registers are processed, especially hard registers, - changes as the compilation proceeds. These states are passed to - df_set_state to control this processing. */ - -#define DF_SCAN_INITIAL 1 /* Processing from beginning of rtl to - global-alloc. */ -#define DF_SCAN_GLOBAL 2 /* Processing before global - allocation. */ -#define DF_SCAN_POST_ALLOC 4 /* Processing after register - allocation. */ -extern int df_state; /* Indicates where we are in the compilation. */ - /* One of these structures is allocated for every basic block. */ struct df_scan_bb_info @@ -513,9 +548,13 @@ struct df_urec_bb_info /* Functions defined in df-core.c. */ extern struct df *df_init (int); -extern struct dataflow *df_add_problem (struct df *, struct df_problem *); +extern struct dataflow *df_add_problem (struct df *, struct df_problem *, int); +extern int df_set_flags (struct dataflow *, int); +extern int df_clear_flags (struct dataflow *, int); extern void df_set_blocks (struct df*, bitmap); +extern void df_delete_basic_block (struct df *, int); extern void df_finish1 (struct df *); +extern void df_analyze_problem (struct dataflow *, bitmap, bitmap, bitmap, int *, int, bool); extern void df_analyze (struct df *); extern void df_compact_blocks (struct df *); extern void df_bb_replace (struct df *, int, basic_block); @@ -529,13 +568,12 @@ extern struct df_ref *df_find_use (struct df *, rtx, rtx); extern bool df_reg_used (struct df *, rtx, rtx); extern void df_iterative_dataflow (struct dataflow *, bitmap, bitmap, int *, int, bool); extern void df_dump (struct df *, FILE *); -extern void df_chain_dump (struct df *, struct df_link *, FILE *); -extern void df_refs_chain_dump (struct df *, struct df_ref *, bool, FILE *); +extern void df_refs_chain_dump (struct df_ref *, bool, FILE *); extern void df_regs_chain_dump (struct df *, struct df_ref *, FILE *); extern void df_insn_debug (struct df *, rtx, bool, FILE *); extern void df_insn_debug_regno (struct df *, rtx, FILE *); extern void df_regno_debug (struct df *, unsigned int, FILE *); -extern void df_ref_debug (struct df *, struct df_ref *, FILE *); +extern void df_ref_debug (struct df_ref *, FILE *); extern void debug_df_insn (rtx); extern void debug_df_regno (unsigned int); extern void debug_df_reg (rtx); @@ -549,34 +587,32 @@ extern struct df *shared_df; /* Functions defined in df-problems.c. */ -extern struct dataflow *df_get_dependent_problem (struct dataflow *); extern struct df_link *df_chain_create (struct dataflow *, struct df_ref *, struct df_ref *); extern void df_chain_unlink (struct dataflow *, struct df_ref *, struct df_link *); extern void df_chain_copy (struct dataflow *, struct df_ref *, struct df_link *); extern bitmap df_get_live_in (struct df *, basic_block); extern bitmap df_get_live_out (struct df *, basic_block); extern void df_grow_bb_info (struct dataflow *); -extern void df_chain_dump (struct df *, struct df_link *, FILE *); +extern void df_chain_dump (struct df_link *, FILE *); extern void df_print_bb_index (basic_block bb, FILE *file); -extern struct dataflow *df_ru_add_problem (struct df *); +extern struct dataflow *df_ru_add_problem (struct df *, int); extern struct df_ru_bb_info *df_ru_get_bb_info (struct dataflow *, unsigned int); -extern struct dataflow *df_rd_add_problem (struct df *); +extern struct dataflow *df_rd_add_problem (struct df *, int); extern struct df_rd_bb_info *df_rd_get_bb_info (struct dataflow *, unsigned int); -extern struct dataflow *df_lr_add_problem (struct df *); +extern struct dataflow *df_lr_add_problem (struct df *, int); extern struct df_lr_bb_info *df_lr_get_bb_info (struct dataflow *, unsigned int); -extern struct dataflow *df_ur_add_problem (struct df *); +extern struct dataflow *df_ur_add_problem (struct df *, int); extern struct df_ur_bb_info *df_ur_get_bb_info (struct dataflow *, unsigned int); -extern struct dataflow *df_urec_add_problem (struct df *); +extern struct dataflow *df_urec_add_problem (struct df *, int); extern struct df_urec_bb_info *df_urec_get_bb_info (struct dataflow *, unsigned int); -extern struct dataflow *df_chain_add_problem (struct df *, int flags); -extern struct dataflow *df_ri_add_problem (struct df *); -extern int df_reg_lifetime (struct df *, rtx reg); +extern struct dataflow *df_chain_add_problem (struct df *, int); +extern struct dataflow *df_ri_add_problem (struct df *, int); /* Functions defined in df-scan.c. */ extern struct df_scan_bb_info *df_scan_get_bb_info (struct dataflow *, unsigned int); -extern struct dataflow *df_scan_add_problem (struct df *); +extern struct dataflow *df_scan_add_problem (struct df *, int); extern void df_rescan_blocks (struct df *, bitmap); extern struct df_ref *df_ref_create (struct df *, rtx, rtx *, rtx,basic_block,enum df_ref_type, enum df_ref_flags); extern struct df_ref *df_get_artificial_defs (struct df *, unsigned int); @@ -588,7 +624,6 @@ extern void df_insn_refs_delete (struct dataflow *, rtx); extern void df_bb_refs_delete (struct dataflow *, int); extern void df_refs_delete (struct dataflow *, bitmap); extern void df_reorganize_refs (struct df_ref_info *); -extern void df_set_state (int); extern void df_hard_reg_init (void); extern bool df_read_modify_subreg_p (rtx); diff --git a/gcc/final.c b/gcc/final.c index 0cb985f..044ef3a 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -4026,6 +4026,9 @@ rest_of_clean_state (void) epilogue_completed = 0; flow2_completed = 0; no_new_pseudos = 0; +#ifdef STACK_REGS + regstack_completed = 0; +#endif /* Clear out the insn_length contents now that they are no longer valid. */ diff --git a/gcc/modulo-sched.c b/gcc/modulo-sched.c index 5a27033..8b620c4 100644 --- a/gcc/modulo-sched.c +++ b/gcc/modulo-sched.c @@ -934,9 +934,9 @@ sms_schedule (void) sched_init (); /* Init Data Flow analysis, to be used in interloop dep calculation. */ - df = df_init (DF_HARD_REGS | DF_EQUIV_NOTES | DF_SUBREGS); - df_rd_add_problem (df); - df_ru_add_problem (df); + df = df_init (DF_HARD_REGS | DF_EQUIV_NOTES | DF_SUBREGS); + df_rd_add_problem (df, 0); + df_ru_add_problem (df, 0); df_chain_add_problem (df, DF_DU_CHAIN | DF_UD_CHAIN); df_analyze (df); diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c index 4ed7204..bb2e1a1 100644 --- a/gcc/reg-stack.c +++ b/gcc/reg-stack.c @@ -187,6 +187,8 @@ static VEC(char,heap) *stack_regs_mentioned_data; #define REG_STACK_SIZE (LAST_STACK_REG - FIRST_STACK_REG + 1) +int regstack_completed = 0; + /* This is the basic stack record. TOP is an index into REG[] such that REG[TOP] is the top of stack. If TOP is -1 the stack is empty. @@ -3151,6 +3153,7 @@ rest_of_handle_stack_regs (void) #ifdef STACK_REGS if (reg_to_stack () && optimize) { + regstack_completed = 1; if (cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK | (flag_crossjumping ? CLEANUP_CROSSJUMP : 0)) && (flag_reorder_blocks || flag_reorder_blocks_and_partition)) @@ -3159,6 +3162,8 @@ rest_of_handle_stack_regs (void) cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK); } } + else + regstack_completed = 1; #endif return 0; } diff --git a/gcc/rtl.h b/gcc/rtl.h index 2335bba..7539ead 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -1978,6 +1978,12 @@ extern int epilogue_completed; extern int reload_in_progress; +#ifdef STACK_REGS +/* Nonzero after end of regstack pass. + Set to 1 or 0 by reg-stack.c. */ +extern int regstack_completed; +#endif + /* If this is nonzero, we do not bother generating VOLATILE around volatile memory references, and we are willing to output indirect addresses. If cse is to follow, we reject diff --git a/gcc/see.c b/gcc/see.c index f56c27b..77fb660 100644 --- a/gcc/see.c +++ b/gcc/see.c @@ -1323,9 +1323,8 @@ static void see_initialize_data_structures (void) { /* Build the df object. */ - df = df_init (DF_HARD_REGS | DF_EQUIV_NOTES | DF_SUBREGS); - df_rd_add_problem (df); - /* df_ru_add_problem (df); */ + df = df_init (DF_HARD_REGS | DF_EQUIV_NOTES | DF_SUBREGS); + df_rd_add_problem (df, 0); df_chain_add_problem (df, DF_DU_CHAIN | DF_UD_CHAIN); df_analyze (df);