re PR bootstrap/44970 (Revision 162270 failed to bootstrap)
authorPaolo Bonzini <bonzini@gnu.org>
Mon, 22 Nov 2010 16:20:16 +0000 (16:20 +0000)
committerPaolo Bonzini <bonzini@gcc.gnu.org>
Mon, 22 Nov 2010 16:20:16 +0000 (16:20 +0000)
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

gcc/ChangeLog
gcc/Makefile.in
gcc/df-scan.c
gcc/df.h
gcc/fwprop.c

index 7a42a0191196870671c93e0fb21fd4156f45a9b6..a4513b7e4423c7c6c1f4d9cb43bb3e92901847b1 100644 (file)
@@ -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
index 08da89d0c75066949b2a827cc69509b046bb3bd8..57e049c071a1b7de7cdd3c915550cbe510899a15 100644 (file)
@@ -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)
index 5cda89730d31776d444be08afe7547ce118065f8..1400d2569b0cd246fe0fddf7f9ad9923751bc520 100644 (file)
@@ -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.  */
index f268289fefba60dceb7835d8bb879930f725a7af..a9bc3664d2f5836173ed6567d8a6dfa385c6a502 100644 (file)
--- 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);
index b54ff501fea22ca2c518490c8b48b70d7e548251..7f29ffb5afbdabc71c16e77d80e58aedd58c67e7 100644 (file)
@@ -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)
 }
 
 \f
-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. */
 
-\f
-/* 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++)
     {