diff options
author | Paolo Bonzini <bonzini@gnu.org> | 2010-11-22 16:20:16 +0000 |
---|---|---|
committer | Paolo Bonzini <bonzini@gcc.gnu.org> | 2010-11-22 16:20:16 +0000 |
commit | dc007c1fd21ca601523d63765c7b5f34865784f0 (patch) | |
tree | 19195f547cbd268188abcb3d1113a7d0cb5c5be6 | |
parent | 47f647e44f933272c7d0c2a707ff537369b30ca0 (diff) | |
download | gcc-dc007c1fd21ca601523d63765c7b5f34865784f0.zip gcc-dc007c1fd21ca601523d63765c7b5f34865784f0.tar.gz gcc-dc007c1fd21ca601523d63765c7b5f34865784f0.tar.bz2 |
re PR bootstrap/44970 (Revision 162270 failed to bootstrap)
2010-11-22 Paolo Bonzini<bonzini@gnu.org>
PR bootstrap/44970
* Makefile.in (fwprop.o) Add sparseset.h.
* fwprop.c: Include sparseset.h
(struct find_occurrence_data, find_occurrence_callback,
find_occurrence): Remove.
(active_defs, active_defs_check, register_active_defs,
update_df_init, update_uses): New.
(update_df): Rewrite.
(try_fwprop_subst, forward_propagate_asm): Add calls to
update_df_init and update_df.
(fwprop_init): Allocate active_defs and active_defs_check.
(fwprop_done): Free them.
(fwprop, fwprop_addr): Adjust comments.
* df.h (df_uses_create): Declare.
* df-scan.c (df_install_ref_incremental): Break out of df_ref_create.
(df_ref_create): Return result of df_ref_create_structure directly.
(df_ref_create_structure): Call df_install_ref_incremental when
no collection_rec is passed.
(df_ref_record): Do not create multiword hard reg info when no
collection_rec is passed.
(df_uses_create): New.
From-SVN: r167038
-rw-r--r-- | gcc/ChangeLog | 24 | ||||
-rw-r--r-- | gcc/Makefile.in | 2 | ||||
-rw-r--r-- | gcc/df-scan.c | 48 | ||||
-rw-r--r-- | gcc/df.h | 1 | ||||
-rw-r--r-- | gcc/fwprop.c | 175 |
5 files changed, 154 insertions, 96 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7a42a01..a4513b7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,27 @@ +2010-11-22 Paolo Bonzini<bonzini@gnu.org> + + PR bootstrap/44970 + * Makefile.in (fwprop.o) Add sparseset.h. + * fwprop.c: Include sparseset.h + (struct find_occurrence_data, find_occurrence_callback, + find_occurrence): Remove. + (active_defs, active_defs_check, register_active_defs, + update_df_init, update_uses): New. + (update_df): Rewrite. + (try_fwprop_subst, forward_propagate_asm): Add calls to + update_df_init and update_df. + (fwprop_init): Allocate active_defs and active_defs_check. + (fwprop_done): Free them. + (fwprop, fwprop_addr): Adjust comments. + * df.h (df_uses_create): Declare. + * df-scan.c (df_install_ref_incremental): Break out of df_ref_create. + (df_ref_create): Return result of df_ref_create_structure directly. + (df_ref_create_structure): Call df_install_ref_incremental when + no collection_rec is passed. + (df_ref_record): Do not create multiword hard reg info when no + collection_rec is passed. + (df_uses_create): New. + 2010-11-21 Uros Bizjak <ubizjak@gmail.com> PR middle-end/43057 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 08da89d..57e049c 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -3115,7 +3115,7 @@ dse.o : dse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ fwprop.o : fwprop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(TOPLEV_H) $(DIAGNOSTIC_CORE_H) insn-config.h $(RECOG_H) $(FLAGS_H) $(OBSTACK_H) $(BASIC_BLOCK_H) \ output.h $(DF_H) alloc-pool.h $(TIMEVAR_H) $(TREE_PASS_H) $(TARGET_H) \ - $(TM_P_H) $(CFGLOOP_H) $(EMIT_RTL_H) domwalk.h + $(TM_P_H) $(CFGLOOP_H) $(EMIT_RTL_H) domwalk.h sparseset.h web.o : web.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ hard-reg-set.h $(FLAGS_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h $(TOPLEV_H) $(DIAGNOSTIC_CORE_H) \ insn-config.h $(RECOG_H) $(DF_H) $(OBSTACK_H) $(TIMEVAR_H) $(TREE_PASS_H) diff --git a/gcc/df-scan.c b/gcc/df-scan.c index 5cda897..1400d25 100644 --- a/gcc/df-scan.c +++ b/gcc/df-scan.c @@ -122,6 +122,7 @@ static void df_uses_record (struct df_collection_rec *, basic_block, struct df_insn_info *, int ref_flags); +static void df_install_ref_incremental (df_ref); static df_ref df_ref_create_structure (enum df_ref_class, struct df_collection_rec *, rtx, rtx *, basic_block, struct df_insn_info *, @@ -680,6 +681,19 @@ df_scan_blocks (void) } } +/* Create new refs under address LOC within INSN. This function is + only used externally. REF_FLAGS must be either 0 or DF_REF_IN_NOTE, + depending on whether LOC is inside PATTERN (INSN) or a note. */ + +void +df_uses_create (rtx *loc, rtx insn, int ref_flags) +{ + gcc_assert (!(ref_flags & ~DF_REF_IN_NOTE)); + df_uses_record (NULL, loc, DF_REF_REG_USE, + BLOCK_FOR_INSN (insn), + DF_INSN_INFO_GET (insn), + ref_flags); +} /* Create a new ref of type DF_REF_TYPE for register REG at address LOC within INSN of BB. This function is only used externally. */ @@ -690,13 +704,6 @@ df_ref_create (rtx reg, rtx *loc, rtx insn, enum df_ref_type ref_type, int ref_flags) { - df_ref ref; - struct df_reg_info **reg_info; - struct df_ref_info *ref_info; - df_ref *ref_rec; - df_ref **ref_rec_ptr; - unsigned int count = 0; - bool add_to_table; enum df_ref_class cl; df_grow_reg_info (); @@ -708,8 +715,24 @@ df_ref_create (rtx reg, rtx *loc, rtx insn, cl = DF_REF_REGULAR; else cl = DF_REF_BASE; - ref = df_ref_create_structure (cl, NULL, reg, loc, bb, DF_INSN_INFO_GET (insn), - ref_type, ref_flags); + + return df_ref_create_structure (cl, NULL, reg, loc, bb, + DF_INSN_INFO_GET (insn), + ref_type, ref_flags); +} + +static void +df_install_ref_incremental (df_ref ref) +{ + struct df_reg_info **reg_info; + struct df_ref_info *ref_info; + df_ref *ref_rec; + df_ref **ref_rec_ptr; + unsigned int count = 0; + bool add_to_table; + + rtx insn = DF_REF_INSN (ref); + basic_block bb = BLOCK_FOR_INSN (insn); if (DF_REF_REG_DEF_P (ref)) { @@ -798,8 +821,6 @@ df_ref_create (rtx reg, rtx *loc, rtx insn, to mark the block dirty ourselves. */ if (!DEBUG_INSN_P (DF_REF_INSN (ref))) df_set_bb_dirty (bb); - - return ref; } @@ -2796,6 +2817,8 @@ df_ref_create_structure (enum df_ref_class cl, else VEC_safe_push (df_ref, stack, collection_rec->use_vec, this_ref); } + else + df_install_ref_incremental (this_ref); return this_ref; } @@ -2839,7 +2862,8 @@ df_ref_record (enum df_ref_class cl, /* 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_info) + if (collection_rec + && (endregno != regno + 1) && insn_info) { /* Sets to a subreg of a multiword register are partial. Sets to a non-subreg of a multiword register are not. */ @@ -980,6 +980,7 @@ extern void df_grow_insn_info (void); extern void df_scan_blocks (void); extern df_ref df_ref_create (rtx, rtx *, rtx,basic_block, enum df_ref_type, int ref_flags); +extern void df_uses_create (rtx *, rtx, int); extern void df_ref_remove (df_ref); extern struct df_insn_info * df_insn_create_insn_record (rtx); extern void df_insn_delete (basic_block, unsigned int); diff --git a/gcc/fwprop.c b/gcc/fwprop.c index b54ff50..7f29ffb 100644 --- a/gcc/fwprop.c +++ b/gcc/fwprop.c @@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-core.h" #include "toplev.h" +#include "sparseset.h" #include "timevar.h" #include "rtl.h" #include "tm_p.h" @@ -849,84 +850,95 @@ all_uses_available_at (rtx def_insn, rtx target_insn) } -struct find_occurrence_data -{ - rtx find; - rtx *retval; -}; +static df_ref *active_defs; +#ifdef ENABLE_CHECKING +static sparseset active_defs_check; +#endif -/* Callback for for_each_rtx, used in find_occurrence. - See if PX is the rtx we have to find. Return 1 to stop for_each_rtx - if successful, or 0 to continue traversing otherwise. */ +/* Fill the ACTIVE_DEFS array with the use->def link for the registers + mentioned in USE_REC. Register the valid entries in ACTIVE_DEFS_CHECK + too, for checking purposes. */ -static int -find_occurrence_callback (rtx *px, void *data) +static void +register_active_defs (df_ref *use_rec) { - struct find_occurrence_data *fod = (struct find_occurrence_data *) data; - rtx x = *px; - rtx find = fod->find; - - if (x == find) + while (*use_rec) { - fod->retval = px; - return 1; - } + df_ref use = *use_rec++; + df_ref def = get_def_for_use (use); + int regno = DF_REF_REGNO (use); - return 0; +#ifdef ENABLE_CHECKING + sparseset_set_bit (active_defs_check, regno); +#endif + active_defs[regno] = def; + } } -/* Return a pointer to one of the occurrences of register FIND in *PX. */ -static rtx * -find_occurrence (rtx *px, rtx find) +/* Build the use->def links that we use to update the dataflow info + for new uses. Note that building the links is very cheap and if + it were done earlier, they could be used to rule out invalid + propagations (in addition to what is done in all_uses_available_at). + I'm not doing this yet, though. */ + +static void +update_df_init (rtx def_insn, rtx insn) { - struct find_occurrence_data data; +#ifdef ENABLE_CHECKING + sparseset_clear (active_defs_check); +#endif + register_active_defs (DF_INSN_USES (def_insn)); + register_active_defs (DF_INSN_USES (insn)); + register_active_defs (DF_INSN_EQ_USES (insn)); +} - gcc_assert (REG_P (find) - || (GET_CODE (find) == SUBREG - && REG_P (SUBREG_REG (find)))); - data.find = find; - data.retval = NULL; - for_each_rtx (px, find_occurrence_callback, &data); - return data.retval; -} +/* Update the USE_DEF_REF array for the given use, using the active definitions + in the ACTIVE_DEFS array to match pseudos to their def. */ - -/* Inside INSN, the expression rooted at *LOC has been changed, moving some - uses from USE_VEC. Find those that are present, and create new items - in the data flow object of the pass. Mark any new uses as having the - given TYPE. */ -static void -update_df (rtx insn, rtx *loc, df_ref *use_rec, enum df_ref_type type, - int new_flags) +static inline void +update_uses (df_ref *use_rec) { - bool changed = false; - - /* Add a use for the registers that were propagated. */ while (*use_rec) { - df_ref use = *use_rec; - df_ref orig_use = use, new_use; - rtx *new_loc = find_occurrence (loc, DF_REF_REG (orig_use)); - use_rec++; + df_ref use = *use_rec++; + int regno = DF_REF_REGNO (use); - if (!new_loc) - continue; + /* Set up the use-def chain. */ + if (DF_REF_ID (use) >= (int) VEC_length (df_ref, use_def_ref)) + VEC_safe_grow_cleared (df_ref, heap, use_def_ref, + DF_REF_ID (use) + 1); - /* Add a new insn use. Use the original type, because it says if the - use was within a MEM. */ - new_use = df_ref_create (DF_REF_REG (orig_use), new_loc, - insn, BLOCK_FOR_INSN (insn), - type, DF_REF_FLAGS (orig_use) | new_flags); +#ifdef ENABLE_CHECKING + gcc_assert (sparseset_bit_p (active_defs_check, regno)); +#endif + VEC_replace (df_ref, use_def_ref, DF_REF_ID (use), active_defs[regno]); + } +} - /* Set up the use-def chain. */ - gcc_assert (DF_REF_ID (new_use) == (int) VEC_length (df_ref, use_def_ref)); - VEC_safe_push (df_ref, heap, use_def_ref, get_def_for_use (orig_use)); - changed = true; + +/* Update the USE_DEF_REF array for the uses in INSN. Only update note + uses if NOTES_ONLY is true. */ + +static void +update_df (rtx insn, rtx note) +{ + struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn); + + if (note) + { + df_uses_create (&XEXP (note, 0), insn, DF_REF_IN_NOTE); + df_notes_rescan (insn); + } + else + { + df_uses_create (&PATTERN (insn), insn, 0); + df_insn_rescan (insn); + update_uses (DF_INSN_INFO_USES (insn_info)); } - if (changed) - df_insn_rescan (insn); + + update_uses (DF_INSN_INFO_EQ_USES (insn_info)); } @@ -940,13 +952,14 @@ static bool try_fwprop_subst (df_ref use, rtx *loc, rtx new_rtx, rtx def_insn, bool set_reg_equal) { rtx insn = DF_REF_INSN (use); - enum df_ref_type type = DF_REF_TYPE (use); - int flags = DF_REF_FLAGS (use); rtx set = single_set (insn); + rtx note = NULL_RTX; bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn)); int old_cost = 0; bool ok; + update_df_init (def_insn, insn); + /* forward_propagate_subreg may be operating on an instruction with multiple sets. If so, assume the cost of the new instruction is not greater than the old one. */ @@ -991,14 +1004,6 @@ try_fwprop_subst (df_ref use, rtx *loc, rtx new_rtx, rtx def_insn, bool set_reg_ { confirm_change_group (); num_changes++; - - df_ref_remove (use); - if (!CONSTANT_P (new_rtx)) - { - struct df_insn_info *insn_info = DF_INSN_INFO_GET (def_insn); - update_df (insn, loc, DF_INSN_INFO_USES (insn_info), type, flags); - update_df (insn, loc, DF_INSN_INFO_EQ_USES (insn_info), type, flags); - } } else { @@ -1011,21 +1016,13 @@ try_fwprop_subst (df_ref use, rtx *loc, rtx new_rtx, rtx def_insn, bool set_reg_ if (dump_file) fprintf (dump_file, " Setting REG_EQUAL note\n"); - set_unique_reg_note (insn, REG_EQUAL, copy_rtx (new_rtx)); - - /* ??? Is this still necessary if we add the note through - set_unique_reg_note? */ - if (!CONSTANT_P (new_rtx)) - { - struct df_insn_info *insn_info = DF_INSN_INFO_GET (def_insn); - update_df (insn, loc, DF_INSN_INFO_USES (insn_info), - type, DF_REF_IN_NOTE); - update_df (insn, loc, DF_INSN_INFO_EQ_USES (insn_info), - type, DF_REF_IN_NOTE); - } + note = set_unique_reg_note (insn, REG_EQUAL, copy_rtx (new_rtx)); } } + if ((ok || note) && !CONSTANT_P (new_rtx)) + update_df (insn, note); + return ok; } @@ -1153,6 +1150,7 @@ forward_propagate_asm (df_ref use, rtx def_insn, rtx def_set, rtx reg) if (use_vec[0] && use_vec[1]) return false; + update_df_init (def_insn, use_insn); speed_p = optimize_bb_for_speed_p (BLOCK_FOR_INSN (use_insn)); asm_operands = NULL_RTX; switch (GET_CODE (use_pat)) @@ -1203,6 +1201,7 @@ forward_propagate_asm (df_ref use, rtx def_insn, rtx def_set, rtx reg) if (num_changes_pending () == 0 || !apply_change_group ()) return false; + update_df (use_insn, NULL); num_changes++; return true; } @@ -1382,6 +1381,11 @@ fwprop_init (void) build_single_def_use_links (); df_set_flags (DF_DEFER_INSN_RESCAN); + + active_defs = XNEWVEC (df_ref, max_reg_num ()); +#ifdef ENABLE_CHECKING + active_defs_check = sparseset_alloc (max_reg_num ()); +#endif } static void @@ -1390,6 +1394,11 @@ fwprop_done (void) loop_optimizer_finalize (); VEC_free (df_ref, heap, use_def_ref); + free (active_defs); +#ifdef ENABLE_CHECKING + sparseset_free (active_defs_check); +#endif + free_dominance_info (CDI_DOMINATORS); cleanup_cfg (0); delete_trivially_dead_insns (get_insns (), max_reg_num ()); @@ -1416,7 +1425,7 @@ fwprop (void) fwprop_init (); - /* Go through all the uses. update_df will create new ones at the + /* Go through all the uses. df_uses_create will create new ones at the end, and we'll go through them as well. Do not forward propagate addresses into loops until after unrolling. @@ -1463,7 +1472,7 @@ fwprop_addr (void) unsigned i; fwprop_init (); - /* Go through all the uses. update_df will create new ones at the + /* Go through all the uses. df_uses_create will create new ones at the end, and we'll go through them as well. */ for (i = 0; i < DF_USES_TABLE_SIZE (); i++) { |