OSDN Git Service

* config/dfp-bits.c (DFP_TO_INT): Remove code to saturate result
[pf3gnuchains/gcc-fork.git] / gcc / df-scan.c
index 0aa07bf..46dfb07 100644 (file)
@@ -46,6 +46,9 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "sbitmap.h"
 #include "bitmap.h"
 #include "timevar.h"
+#include "tree.h"
+#include "target.h"
+#include "target-def.h"
 #include "df.h"
 
 #ifndef HAVE_epilogue
@@ -62,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.  */
 
@@ -82,8 +82,6 @@ bitmap df_invalidated_by_call = NULL;
 /* Initialize ur_in and ur_out as if all hard registers were partially
    available.  */
 
-bitmap df_all_hard_regs = NULL;
-
 static void df_ref_record (struct dataflow *, rtx, rtx *, 
                           basic_block, rtx, enum df_ref_type,
                           enum df_ref_flags, bool record_live);
@@ -99,6 +97,7 @@ static void df_refs_record (struct dataflow *, bitmap);
 static struct df_ref *df_ref_create_structure (struct dataflow *, rtx, rtx *, 
                                               basic_block, rtx, enum df_ref_type, 
                                               enum df_ref_flags);
+static void df_record_entry_block_defs (struct dataflow *);
 static void df_record_exit_block_uses (struct dataflow *);
 static void df_grow_reg_info (struct dataflow *, struct df_ref_info *);
 static void df_grow_ref_info (struct df_ref_info *, unsigned int);
@@ -120,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;
@@ -128,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);
@@ -148,12 +149,15 @@ df_scan_free_internal (struct dataflow *dflow)
   dflow->block_info_size = 0;
 
   BITMAP_FREE (df->hardware_regs_used);
+  BITMAP_FREE (df->entry_block_defs);
   BITMAP_FREE (df->exit_block_uses);
 
   free_alloc_pool (dflow->block_pool);
   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);
 }
 
 
@@ -181,11 +185,14 @@ df_scan_set_bb_info (struct dataflow *dflow, unsigned int index,
 /* Free basic block info.  */
 
 static void
-df_scan_free_bb_info (struct dataflow *dflow, void *vbb_info)
+df_scan_free_bb_info (struct dataflow *dflow, basic_block bb, void *vbb_info)
 {
   struct df_scan_bb_info *bb_info = (struct df_scan_bb_info *) vbb_info;
   if (bb_info)
-    pool_free (dflow->block_pool, bb_info);
+    {
+      df_bb_refs_delete (dflow, bb->index);
+      pool_free (dflow->block_pool, bb_info);
+    }
 }
 
 
@@ -194,7 +201,8 @@ df_scan_free_bb_info (struct dataflow *dflow, 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;
@@ -213,7 +221,7 @@ df_scan_alloc (struct dataflow *dflow, bitmap blocks_to_rescan)
                         sizeof (struct df_scan_bb_info), 
                         block_size);
 
-  problem_data = xmalloc (sizeof (struct df_scan_problem_data));
+  problem_data = XNEW (struct df_scan_problem_data);
   dflow->problem_data = problem_data;
 
   problem_data->ref_pool 
@@ -222,10 +230,15 @@ df_scan_alloc (struct dataflow *dflow, bitmap blocks_to_rescan)
   problem_data->insn_pool 
     = create_alloc_pool ("df_scan_insn pool", 
                         sizeof (struct df_insn_info), block_size);
-
   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);
@@ -250,6 +263,7 @@ df_scan_alloc (struct dataflow *dflow, bitmap blocks_to_rescan)
     }
 
   df->hardware_regs_used = BITMAP_ALLOC (NULL);
+  df->entry_block_defs = BITMAP_ALLOC (NULL);
   df->exit_block_uses = BITMAP_ALLOC (NULL);
 }
 
@@ -261,14 +275,18 @@ df_scan_free (struct dataflow *dflow)
 {
   struct df *df = dflow->df;
   
-  df_scan_free_internal (dflow);
+  if (dflow->problem_data)
+    {
+      df_scan_free_internal (dflow);
+      free (dflow->problem_data);
+    }
+
   if (df->blocks_to_scan)
     BITMAP_FREE (df->blocks_to_scan);
   
   if (df->blocks_to_analyze)
     BITMAP_FREE (df->blocks_to_analyze);
 
-  free (dflow->problem_data);
   free (dflow);
 }
 
@@ -278,12 +296,12 @@ df_scan_dump (struct dataflow *dflow ATTRIBUTE_UNUSED, FILE *file ATTRIBUTE_UNUS
   struct df *df = dflow->df;
   int i;
 
-  fprintf (file, "  all hard regs \t");
-  dump_bitmap (file, df_all_hard_regs);
   fprintf (file, "  invalidated by call \t");
   dump_bitmap (file, df_invalidated_by_call);
   fprintf (file, "  hardware regs used \t");
   dump_bitmap (file, df->hardware_regs_used);
+  fprintf (file, "  entry block uses \t");
+  dump_bitmap (file, df->entry_block_defs);
   fprintf (file, "  exit block uses \t");
   dump_bitmap (file, df->exit_block_uses);
   fprintf (file, "  regs ever live \t");
@@ -298,6 +316,7 @@ static struct df_problem problem_SCAN =
   DF_SCAN,                    /* Problem id.  */
   DF_NONE,                    /* Direction.  */
   df_scan_alloc,              /* Allocate the problem specific data.  */
+  NULL,                       /* Reset global information.  */
   df_scan_free_bb_info,       /* Free basic block info.  */
   NULL,                       /* Local compute function.  */
   NULL,                       /* Init the solution specific data.  */
@@ -308,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.  */
 };
 
 
@@ -317,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);
 }
 
 /*----------------------------------------------------------------------------
@@ -339,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)
@@ -412,7 +432,7 @@ df_rescan_blocks (struct df *df, bitmap blocks)
 {
   bitmap local_blocks_to_scan = BITMAP_ALLOC (NULL);
 
-  struct dataflow *dflow = df->problems_by_index [DF_SCAN];
+  struct dataflow *dflow = df->problems_by_index[DF_SCAN];
   basic_block bb;
 
   df->def_info.refs_organized = false;
@@ -420,6 +440,11 @@ 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;
       insn_num += insn_num / 4;
@@ -434,9 +459,41 @@ 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;
 
+      for (i = df->num_problems_defined; i; i--)
+       {
+         bitmap blocks_to_reset = NULL;
+         if (dflow->problem->reset_fun)
+           {
+             if (!blocks_to_reset)
+               {
+                 blocks_to_reset = BITMAP_ALLOC (NULL);
+                 bitmap_copy (blocks_to_reset, local_blocks_to_scan);
+                 if (df->blocks_to_scan)
+                   bitmap_ior_into (blocks_to_reset, df->blocks_to_scan);
+               }
+             dflow->problem->reset_fun (dflow, blocks_to_reset);
+           }
+         if (blocks_to_reset)
+           BITMAP_FREE (blocks_to_reset);
+       }
+
       df_refs_delete (dflow, local_blocks_to_scan);
 
       /* This may be a mistake, but if an explicit blocks is passed in
@@ -459,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;
@@ -477,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.  */
 
@@ -518,7 +576,7 @@ df_ref_create (struct df *df, rtx reg, rtx *loc, rtx insn,
 ----------------------------------------------------------------------------*/
 
 
-/* Get the artifical uses for a basic block.  */
+/* Get the artificial uses for a basic block.  */
 
 struct df_ref *
 df_get_artificial_defs (struct df *df, unsigned int bb_index)
@@ -528,7 +586,7 @@ df_get_artificial_defs (struct df *df, unsigned int bb_index)
 }
 
 
-/* Get the artifical uses for a basic block.  */
+/* Get the artificial uses for a basic block.  */
 
 struct df_ref *
 df_get_artificial_uses (struct df *df, unsigned int bb_index)
@@ -603,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);
@@ -655,7 +713,7 @@ df_reg_chain_unlink (struct dataflow *dflow, struct df_ref *ref)
 void
 df_ref_remove (struct df *df, struct df_ref *ref)
 {
-  struct dataflow *dflow = df->problems_by_index [DF_SCAN];
+  struct dataflow *dflow = df->problems_by_index[DF_SCAN];
   if (DF_REF_REG_DEF_P (ref))
     {
       if (DF_REF_FLAGS (ref) & DF_REF_ARTIFICIAL)
@@ -666,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);
@@ -682,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);
@@ -699,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)
@@ -713,20 +771,41 @@ df_insn_create_insn_record (struct dataflow *dflow, rtx insn)
   return insn_rec;
 }
 
-/* Delete all of the refs information from BLOCKS.  */
+
+/* Delete all of the refs information from INSN.  */
 
 void 
 df_insn_refs_delete (struct dataflow *dflow, rtx insn)
 {
   struct df *df = dflow->df;
   unsigned int uid = INSN_UID (insn);
-  struct df_insn_info *insn_info = DF_INSN_UID_GET (df, uid);
+  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);
@@ -741,6 +820,42 @@ df_insn_refs_delete (struct dataflow *dflow, rtx insn)
 }
 
 
+/* Delete all of the refs information from basic_block with BB_INDEX.  */
+
+void
+df_bb_refs_delete (struct dataflow *dflow, int bb_index)
+{
+  struct df_ref *def;
+  struct df_ref *use;
+
+  struct df_scan_bb_info *bb_info 
+    = df_scan_get_bb_info (dflow, bb_index);
+  rtx insn;
+  basic_block bb = BASIC_BLOCK (bb_index);
+  FOR_BB_INSNS (bb, insn)
+    {
+      if (INSN_P (insn))
+       {
+         /* Record defs within INSN.  */
+         df_insn_refs_delete (dflow, insn);
+       }
+    }
+  
+  /* Get rid of any artificial uses or defs.  */
+  if (bb_info)
+    {
+      def = bb_info->artificial_defs;
+      while (def)
+       def = df_reg_chain_unlink (dflow, def);
+      bb_info->artificial_defs = NULL;
+      use = bb_info->artificial_uses;
+      while (use)
+       use = df_reg_chain_unlink (dflow, use);
+      bb_info->artificial_uses = NULL;
+    }
+}
+
+
 /* Delete all of the refs information from BLOCKS.  */
 
 void 
@@ -748,36 +863,10 @@ df_refs_delete (struct dataflow *dflow, bitmap blocks)
 {
   bitmap_iterator bi;
   unsigned int bb_index;
-  struct df_ref *def;
-  struct df_ref *use;
 
   EXECUTE_IF_SET_IN_BITMAP (blocks, 0, bb_index, bi)
     {
-      struct df_scan_bb_info *bb_info 
-       = df_scan_get_bb_info (dflow, bb_index);
-      rtx insn;
-      basic_block bb = BASIC_BLOCK (bb_index);
-      FOR_BB_INSNS (bb, insn)
-       {
-         if (INSN_P (insn))
-           {
-             /* Record defs within INSN.  */
-             df_insn_refs_delete (dflow, insn);
-           }
-       }
-
-      /* Get rid of any artifical uses.  */
-      if (bb_info)
-       {
-         def = bb_info->artificial_defs;
-         while (def)
-           def = df_reg_chain_unlink (dflow, def);
-         bb_info->artificial_defs = NULL;
-         use = bb_info->artificial_uses;
-         while (use)
-           use = df_reg_chain_unlink (dflow, use);
-         bb_info->artificial_uses = NULL;
-       }
+      df_bb_refs_delete (dflow, bb_index);
     }
 }
 
@@ -831,20 +920,6 @@ df_reorganize_refs (struct df_ref_info *ref_info)
 }
 
 \f
-/* Local miscellaneous routines.  */
-
-/* Local routines for recording refs.  */
-
-/* Set where we are in the compilation.  */
-
-void 
-df_set_state (int state)
-{
-  df_state = state;
-}
-
-
-\f
 /*----------------------------------------------------------------------------
    Hard core instruction scanning code.  No external interfaces here,
    just a lot of routines that look inside insns.
@@ -861,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;
@@ -877,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;
 }
@@ -962,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);
 
@@ -972,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))
@@ -986,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
@@ -1003,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)
@@ -1016,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
@@ -1062,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.  */
@@ -1071,9 +1193,8 @@ df_def_record_1 (struct dataflow *dflow, rtx x,
     loc = &SET_DEST (x);
   dst = *loc;
 
-  /* Some targets place small structures in registers for
-     return values of functions.  */
-  if (GET_CODE (dst) == PARALLEL && GET_MODE (dst) == BLKmode)
+  /* It is legal to have a set destination be a parallel. */
+  if (GET_CODE (dst) == PARALLEL)
     {
       int i;
 
@@ -1083,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;
@@ -1105,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, 
@@ -1127,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)
     {
@@ -1188,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)))
        {
@@ -1206,7 +1338,7 @@ df_uses_record (struct dataflow *dflow, rtx *loc, enum df_ref_type ref_type,
       {
        rtx dst = SET_DEST (x);
        gcc_assert (!(flags & DF_REF_IN_NOTE));
-       df_uses_record (dflow, &SET_SRC (x), DF_REF_REG_USE, bb, insn, 0);
+       df_uses_record (dflow, &SET_SRC (x), DF_REF_REG_USE, bb, insn, flags);
 
        switch (GET_CODE (dst))
          {
@@ -1215,7 +1347,7 @@ df_uses_record (struct dataflow *dflow, rtx *loc, enum df_ref_type ref_type,
                {
                  df_uses_record (dflow, &SUBREG_REG (dst), 
                                  DF_REF_REG_USE, bb,
-                                 insn, DF_REF_READ_WRITE);
+                                 insn, flags | DF_REF_READ_WRITE);
                  break;
                }
              /* Fall through.  */
@@ -1228,7 +1360,7 @@ df_uses_record (struct dataflow *dflow, rtx *loc, enum df_ref_type ref_type,
            case MEM:
              df_uses_record (dflow, &XEXP (dst, 0),
                              DF_REF_REG_MEM_STORE,
-                             bb, insn, 0);
+                             bb, insn, flags);
              break;
            case STRICT_LOW_PART:
              {
@@ -1249,9 +1381,9 @@ df_uses_record (struct dataflow *dflow, rtx *loc, enum df_ref_type ref_type,
                              DF_REF_REG_USE, bb, insn,
                              DF_REF_READ_WRITE);
              df_uses_record (dflow, &XEXP (dst, 1), 
-                             DF_REF_REG_USE, bb, insn, 0);
+                             DF_REF_REG_USE, bb, insn, flags);
              df_uses_record (dflow, &XEXP (dst, 2), 
-                             DF_REF_REG_USE, bb, insn, 0);
+                             DF_REF_REG_USE, bb, insn, flags);
              dst = XEXP (dst, 0);
              break;
            default:
@@ -1301,7 +1433,7 @@ df_uses_record (struct dataflow *dflow, rtx *loc, enum df_ref_type ref_type,
 
            for (j = 0; j < ASM_OPERANDS_INPUT_LENGTH (x); j++)
              df_uses_record (dflow, &ASM_OPERANDS_INPUT (x, j),
-                             DF_REF_REG_USE, bb, insn, 0);
+                             DF_REF_REG_USE, bb, insn, flags);
            return;
          }
        break;
@@ -1314,8 +1446,9 @@ df_uses_record (struct dataflow *dflow, rtx *loc, enum df_ref_type ref_type,
     case PRE_MODIFY:
     case POST_MODIFY:
       /* Catch the def of the register being modified.  */
+      flags |= DF_REF_READ_WRITE;
       df_ref_record (dflow, XEXP (x, 0), &XEXP (x, 0), bb, insn, 
-                    DF_REF_REG_DEF, DF_REF_READ_WRITE, true);
+                    DF_REF_REG_DEF, flags, true);
 
       /* ... Fall through to handle uses ...  */
 
@@ -1379,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))
     {
@@ -1392,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))
          {
@@ -1445,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;
@@ -1457,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);
            }
        }
 
@@ -1492,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)
@@ -1516,81 +1653,110 @@ 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;
       /* Mark the registers that will contain data for the handler.  */
-      if (current_function_calls_eh_return)
-       for (i = 0; ; ++i)
-         {
-           unsigned regno = EH_RETURN_DATA_REGNO (i);
-           if (regno == INVALID_REGNUM)
-             break;
-           df_ref_record (dflow, regno_reg_rtx[i], &regno_reg_rtx[i], bb, NULL, 
-                          DF_REF_REG_DEF, DF_REF_ARTIFICIAL | DF_REF_AT_TOP, false);
-         }
+      for (i = 0; ; ++i)
+       {
+         unsigned regno = EH_RETURN_DATA_REGNO (i);
+         if (regno == INVALID_REGNUM)
+           break;
+         df_ref_record (dflow, regno_reg_rtx[regno], &regno_reg_rtx[regno],
+                        bb, NULL,
+                        DF_REF_REG_DEF, DF_REF_ARTIFICIAL | DF_REF_AT_TOP,
+                        false);
+       }
     }
 #endif
 
-#ifdef EH_USES
-  /*  This code is putting in a artificial ref for the use at the TOP
-      of the block that receives the exception.  It is too cumbersome
-      to actually put the ref on the edge.  We could either model this
-      at the top of the receiver block or the bottom of the sender
-      block.
-
-      The bottom of the sender block is problematic because not all
-      out-edges of the a block are eh-edges.  However, it is true that
-      all edges into a block are either eh-edges or none of them are
-      eh-edges.  Thus, we can model this at the top of the eh-receiver
-      for all of the edges at once. */
-  if ((df->flags & DF_HARD_REGS)
+
+  if ((dflow->flags & DF_HARD_REGS)
       && df_has_eh_preds (bb))
     {
+#ifdef EH_USES
       unsigned int i;
+      /* This code is putting in a artificial ref for the use at the
+        TOP of the block that receives the exception.  It is too
+        cumbersome to actually put the ref on the edge.  We could
+        either model this at the top of the receiver block or the
+        bottom of the sender block.
+
+         The bottom of the sender block is problematic because not all
+         out-edges of the a block are eh-edges.  However, it is true
+         that all edges into a block are either eh-edges or none of
+         them are eh-edges.  Thus, we can model this at the top of the
+         eh-receiver for all of the edges at once. */
       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
        if (EH_USES (i))
          df_uses_record (dflow, &regno_reg_rtx[i], 
-                                  DF_REF_REG_USE, EXIT_BLOCK_PTR, NULL,
-                                  DF_REF_ARTIFICIAL | DF_REF_AT_TOP);
-    }
+                         DF_REF_REG_USE, bb, NULL,
+                         DF_REF_ARTIFICIAL | DF_REF_AT_TOP);
+#endif
+
+      /* The following code (down thru the arg_pointer setting APPEARS
+        to be necessary because there is nothing that actually
+        describes what the exception handling code may actually need
+        to keep alive.  */
+      if (reload_completed)
+       {
+         if (frame_pointer_needed)
+           {
+             bitmap_set_bit (artificial_uses_at_bottom, FRAME_POINTER_REGNUM);
+#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+             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])
+           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);
     }
 }
 
@@ -1611,6 +1777,9 @@ df_refs_record (struct dataflow *dflow, bitmap blocks)
 
   if (bitmap_bit_p (blocks, EXIT_BLOCK))
     df_record_exit_block_uses (dflow);
+
+  if (bitmap_bit_p (blocks, ENTRY_BLOCK))
+    df_record_entry_block_defs (dflow);
 }
 
 
@@ -1638,6 +1807,121 @@ df_mark_reg (rtx reg, void *vset)
     }
 }
 
+
+/* Record the (conservative) set of hard registers that are defined on
+   entry to the function.  */
+
+static void
+df_record_entry_block_defs (struct dataflow *dflow)
+{
+  unsigned int i; 
+  bitmap_iterator bi;
+  rtx r;
+  struct df *df = dflow->df;
+
+  bitmap_clear (df->entry_block_defs);
+
+  if (!(dflow->flags & DF_HARD_REGS))
+    return;
+
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    {
+      if (FUNCTION_ARG_REGNO_P (i))
+#ifdef INCOMING_REGNO
+       bitmap_set_bit (df->entry_block_defs, INCOMING_REGNO (i));
+#else
+       bitmap_set_bit (df->entry_block_defs, i);
+#endif
+    }
+      
+  /* Once the prologue has been generated, all of these registers
+     should just show up in the first regular block.  */
+  if (HAVE_prologue && epilogue_completed)
+    {
+      /* Defs for the callee saved registers are inserted so that the
+        pushes have some defining location.  */
+      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+       if ((call_used_regs[i] == 0) && (regs_ever_live[i]))
+         bitmap_set_bit (df->entry_block_defs, i);
+    }
+  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));
+#endif
+            
+      /* If STATIC_CHAIN_INCOMING_REGNUM == STATIC_CHAIN_REGNUM
+        only STATIC_CHAIN_REGNUM is defined.  If they are different,
+        we only care about the STATIC_CHAIN_INCOMING_REGNUM.  */
+#ifdef STATIC_CHAIN_INCOMING_REGNUM
+      bitmap_set_bit (df->entry_block_defs, STATIC_CHAIN_INCOMING_REGNUM);
+#else 
+#ifdef STATIC_CHAIN_REGNUM
+      bitmap_set_bit (df->entry_block_defs, STATIC_CHAIN_REGNUM);
+#endif
+#endif
+      
+      r = TARGET_STRUCT_VALUE_RTX (current_function_decl, true);
+      if (r && REG_P (r))
+       bitmap_set_bit (df->entry_block_defs, REGNO (r));
+    }
+
+  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.  */
+      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+       if (EH_USES (i))
+         {
+           bitmap_set_bit (df->entry_block_defs, i);
+         }
+#endif
+      
+#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])
+       bitmap_set_bit (df->entry_block_defs, ARG_POINTER_REGNUM);
+#endif
+         
+#ifdef PIC_OFFSET_TABLE_REGNUM
+      /* 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])
+       bitmap_set_bit (df->entry_block_defs, PIC_OFFSET_TABLE_REGNUM);
+#endif
+    }
+
+  targetm.live_on_entry (df->entry_block_defs);
+
+  EXECUTE_IF_SET_IN_BITMAP (df->entry_block_defs, 0, i, bi)
+    {
+      df_ref_record (dflow, regno_reg_rtx[i], &regno_reg_rtx[i], 
+                    ENTRY_BLOCK_PTR, NULL, 
+                    DF_REF_REG_DEF, DF_REF_ARTIFICIAL , false);
+    }
+}
+
+
 /* Record the set of hard registers that are used in the exit block.  */
 
 static void
@@ -1649,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)
     {
@@ -1668,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
     }
@@ -1698,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);
     }
   
@@ -1716,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;
@@ -1726,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;
@@ -1738,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,
@@ -1752,8 +2036,8 @@ static bool initialized = false;
 void 
 df_hard_reg_init (void)
 {
-#ifdef ELIMINABLE_REGS
   int i;
+#ifdef ELIMINABLE_REGS
   static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
 #endif
   /* After reload, some ports add certain bits to regs_ever_live so
@@ -1786,10 +2070,5 @@ df_hard_reg_init (void)
     if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
       bitmap_set_bit (df_invalidated_by_call, i);
   
-  df_all_hard_regs = BITMAP_ALLOC (&persistent_obstack);
-  
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    bitmap_set_bit (df_all_hard_regs, i);
-  
   initialized = true;
 }