re PR rtl-optimization/26855 (ICE in add_deps_for_def with -fmodulo-sched -maltivec)
authorDaniel Berlin <dberlin@dberlin.org>
Fri, 19 May 2006 21:18:23 +0000 (21:18 +0000)
committerKenneth Zadeck <zadeck@gcc.gnu.org>
Fri, 19 May 2006 21:18:23 +0000 (21:18 +0000)
2006-05-19  Daniel Berlin  <dberlin@dberlin.org>
            Kenneth Zadeck <zadeck@naturalbridge.com>

PR rtl-optimization/26855

* df-scan.c (mw_reg_pool, mw_link_pool): New allocation pools for
multiword refs.
(df_scan_alloc): Added code to properly handle multiword hard
registers and add all_blocks parameter.
(df_scan_free_internal, df_insn_refs_delete, df_ref_record): Added
code to properly handle multiword hard registers.
(df_rescan_blocks): Added code to remove deleted blocks from
bitmap.
(df_ref_create_structure, df_ref_record): Added code to properly
handle subregs.
(df_ref_record_1): Changed DF_REF_CLOBBER into DF_REF_MUST_CLOBBER
and set DF_REF_PARTIAL.
(df_defs_record): Changed DF_REF_CLOBBER into DF_REF_MUST_CLOBBER.
(df_uses_record): Added DF_REF_PARTIAL for subreg.
(df_scan_add_problem): Added flags parameter.
(df_ref_create_structure): Changed switching structure.
(df_bb_refs_record): Fixed case where duplicate artificial refs
were created.  Changed location of flags.
(df_record_entry_block_defs): Added code to make stack pointer
live in entry block.  Refined cases where frame pointer is needed.
Changed location of flags.
(df_record_exit_block_uses, df_insn_refs_record): Changed location of flags.
(df_set_state): Removed function.
(df_grow_reg_info, df_reg_chain_unlink, df_ref_remove,
df_insn_create_insn_record, df_insn_refs_delete,
df_ref_create_structure): Formatting changes.
* df-core.c (df_mvs_dump, df_set_flags, df_clear_flags,
df_delete_basic_block): New function.
(df_init): Changed location of flags.
(df_add_problem): Added flags parameter and the way flags are
processed.
(df_insn_uid_debug, df_ref_debug, debug_df_defno, debug_df_ref,
debug_df_chain): Improved debugging output.
(df_insn_debug, df_insn_uid_debug): Added multiword reg support.
(df_refs_chain_dump): Removed df parameter.
(df_iterative_dataflow): Added consistency check.
(df_prune_to_subcfg): Made public.
(df_analyze_problem): Added blocks_to_init parameter and made
public.
(df_ref_record, df_bb_refs_record, df_mark_reg,
 df_record_exit_block_uses): Whitespace changes.
(df_dump): Whitespace changes.
* df.h: Some reordering to remove forward references.
(df_ref_flags.DF_REF_MW_HARDREG, DF_REF_PARTIAL,
DF_REF_MUST_CLOBBER, DF_REF_MAY_CLOBBER): New fields.
(df_ref_flags.DF_REF_CLOBBER): Deleted field.
(dataflow.flags): New field.
(df.flag): Deleted field.
(df_alloc_function): Added additional bitmap parameter.
(df_dependent_problem_function): New type.
(df_problem.changeable_flags): New field.
(df_ref_flags.DF_REF_DIES_AFTER_THIS_USE, DF_SCAN_INITIAL,
DF_SCAN_GLOBAL, DF_SCAN_POST_ALLOC, df_state): Removed.
(df_mw_hardreg): New struct.
(DF_INSN_UID_MWS): New macro.
(df_refs_chain_dump, df_ref_debug, df_chain_dump): Removed df
parameter.
(df_add_problem, df_ru_add_problem, df_rd_add_problem,
df_lr_add_problem, df_ur_add_problem, df_urec_add_problem,
df_ri_add_problem, df_scan_add_problem): Added flags parameter.
(df_set_state): Removed function.
(df_set_flags, df_clear_flags, df_delete_basic_block) New functions.
* df-problems.c (df_chain_dump): Removed df parameter.
(df_ru_alloc, df_rd_alloc, df_lr_alloc, df_ur_alloc,
df_urec_alloc, df_chain_alloc, df_ri_alloc): Added all blocks
parameter.
(df_ru_alloc, df_rd_alloc): Now resets all blocks.
(df_rd_bb_local_compute_process_def, df_ur_bb_local_compute,
df_chain_create_bb, df_create_unused_note, df_ri_bb_compute):
Split DF_REF_CLOBBER into DF_REF_MAY_CLOBBER and
DF_REF_MUST_CLOBBER cases.
(df_ru_bb_local_compute_process_def,
df_rd_bb_local_compute_process_def, df_lr_bb_local_compute,
df_lr_bb_local_compute, df_ur_bb_local_compute,
df_chain_create_bb): Made subreg aware.
(df_ru_bb_local_compute, df_rd_bb_local_compute,
df_lr_bb_local_compute, df_lr_bb_local_compute,
df_chain_create_bb): Cleanup to use proper macros.
(df_ur_local_finalize, df_urec_local_finalize): Removed unnecessary
code to fixup bitvectors.
(df_ri_alloc): Cleared lifetime.
(df_ignore_stack_reg, df_kill_notes, df_set_notes_for_mw,
df_create_unused_note): New function.
(df_ri_bb_compute, df_ri_compute): Added code to create/update
REG_DEAD and REG_UNUSED notes as well as register information.
(df_ru_dump, df_rd_dump, df_lr_dump, df_ur_dump, df_urec_dump,
df_chains_dump): Fixed crash if problem was never run.
(df_ru_add_problem, df_rd_add_problem, df_lr_add_problem,
df_ur_add_problem, df_urec_add_problem, df_chain_add_problem,
df_ri_add_problem): Processes flags in uniform manner.
(df_ru_alloc, df_ru_local_compute, df_ru_confluence_n, df_ru_free,
df_ru_dump, df_rd_local_compute, df_rd_confluence_n, df_rd_free,
df_rd_dump, df_urec_free_bb_info): Formatting changes.
(df_ru_free_bb_info, df_ru_bb_local_compute, df_ru_dump,
df_rd_free_bb_info, df_rd_bb_local_compute_process_def,
df_rd_bb_local_compute, df_rd_dump, df_lr_free_bb_info,
df_lr_bb_local_compute, df_lr_local_compute, df_ur_free_bb_info,
df_ur_dump, df_urec_free_bb_info, df_urec_dump,
df_chain_create_bb, df_ri_bb_compute): Whitespace changes.
* modulo-sched.c (sms_schedule): Added flag parameter to calls.
* see.c (see_initialize_data): Ditto.
* final.c (rest_of_clean_state) Added regstack_completed.
* rtl.h (regstack_completed): Ditto.
* reg-stack.c (regstack_completed): Ditto.

From-SVN: r113915

gcc/df-core.c
gcc/df-problems.c
gcc/df-scan.c
gcc/df.h
gcc/final.c
gcc/modulo-sched.c
gcc/reg-stack.c
gcc/rtl.h
gcc/see.c

index 0619c20..1d4aff2 100644 (file)
@@ -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");
 }
 \f
@@ -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);
 }
index 4f5f2e1..8c5ed6d 100644 (file)
@@ -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 *);
 
 \f
 /*----------------------------------------------------------------------------
    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);
 }
 
 \f
@@ -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 = &REG_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)];
-}
-
-
index b35c3a4..46dfb07 100644 (file)
@@ -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)
 }
 
 \f
-/* Local miscellaneous routines.  */
-
-/* Local routines for recording refs.  */
-
-/* Set where we are in the compilation.  */
-
-void 
-df_set_state (int state)
-{
-  df_state = state;
-}
-
-
-\f
 /*----------------------------------------------------------------------------
    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], &regno_reg_rtx[ui], bb, insn, 
-                              DF_REF_REG_DEF, DF_REF_CLOBBER, false);
+               df_ref_record (dflow, regno_reg_rtx[ui], &regno_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, &regno_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, &regno_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, &regno_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, &regno_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, &regno_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, &regno_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, &regno_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, &regno_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, &regno_reg_rtx[i], 
                      DF_REF_REG_USE, EXIT_BLOCK_PTR, NULL,
index 3a735ae..b1e9384 100644 (file)
--- 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);
 
index 0cb985f..044ef3a 100644 (file)
@@ -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.  */
index 5a27033..8b620c4 100644 (file)
@@ -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);
 
index 4ed7204..bb2e1a1 100644 (file)
@@ -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;
 }
index 2335bba..7539ead 100644 (file)
--- 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
index f56c27b..77fb660 100644 (file)
--- 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);