aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Bonzini <bonzini@gnu.org>2010-11-22 16:20:16 +0000
committerPaolo Bonzini <bonzini@gcc.gnu.org>2010-11-22 16:20:16 +0000
commitdc007c1fd21ca601523d63765c7b5f34865784f0 (patch)
tree19195f547cbd268188abcb3d1113a7d0cb5c5be6
parent47f647e44f933272c7d0c2a707ff537369b30ca0 (diff)
downloadgcc-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/ChangeLog24
-rw-r--r--gcc/Makefile.in2
-rw-r--r--gcc/df-scan.c48
-rw-r--r--gcc/df.h1
-rw-r--r--gcc/fwprop.c175
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. */
diff --git a/gcc/df.h b/gcc/df.h
index f268289..a9bc366 100644
--- a/gcc/df.h
+++ b/gcc/df.h
@@ -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++)
{