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 0619c200bdc3829b5371d63f8d87affb433b672b..1d4aff2315feddfc76d6dc7c3cbb44c8465b6451 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 4f5f2e126588a00f7be0c27781490d226d0ec89c..8c5ed6d7bd3863dd8c2aef16d76a6a763dd11c40 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 b35c3a474e45967b0765db5ffb5a2255df1b06c0..46dfb072cce43fb561134e1950cfac56f14166af 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);
@@ -875,20 +919,6 @@ df_reorganize_refs (struct df_ref_info *ref_info)
   ref_info->add_refs_inline = true;
 }
 
-\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,
@@ -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 3a735aedd05f86e0990e556f9f61713f5ce83f08..b1e93844ed3f82dc9bbcbe624cb39ceef44478d4 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 0cb985fd4d67f576dfc577786cc246e66e974fbc..044ef3a2afb0857e75c24f17a4ffe1064b263e25 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 5a270339492ad70c2145ee4236d3e9a3d773659b..8b620c4b119d91e56ed36fb42c765e5904daac72 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 4ed72047ab7be79bc7bd23fcdb8b62e2c196ab6e..bb2e1a1f9c67faa5eedcd0121c22d3ff951bb43e 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 2335bba5ff52e20639cc03361161da68b9ea311e..7539eadf96d16c8fa101b94b45697ade1f79804e 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 f56c27b8b92dd0e0a928213de715c360c509015d..77fb6600772cac6d3418326fb29e0595e68c7dd2 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);