This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH]: update to df for mainline.


Dear Bernd,

Attached is an updated patch.  Unless noted below, all of your changes
were made as requested.

Bernd Schmidt wrote:
>> -  struct df_ri_problem_data *problem_data =
>> -    (struct df_ri_problem_data *) dflow->problem_data;
>
> I think the "=" should be on the second line.
>
I made this change uniformly in all of the df* files.  This swells the
size of the patch somewhat.

>> +  struct df * df = dflow->df;
>
> "df *df"
>
Ditto.

>> +      if (flags & DF_RI_LIFE)
>> +        if (df_ignore_stack_reg (REGNO (XEXP (link, 0))))
>> +          REG_N_DEATHS (REGNO (XEXP (link, 0)))++;
>
> Add break here for clarity.
>
I did not add the break here.  The case is meant to drop thru, note the
/*fallthru*/ comment on the next line.  If you are complaining about
having fallthru's, I can duplicate the next case into this one. 

>
>
> Lots of code shared between df_set_{dead,unused}_notes_for_mw.
>
These functions were originally one.  This is why they look structurally
similar.  I had split them when I could no longer follow what was going
on because of the special cases for each.

>
>
>> +  /* Kill this register if it is not a subreg store.  */
>> +  if (!(DF_REF_FLAGS (def) & DF_REF_PARTIAL))
>> +    bitmap_clear_bit (live, dregno);
>
> Looks like this depends on another part.  I have to admit that I'm not
> convinced yet by the subreg handling in DF as a whole.  A normal
> (non-multiword non-strict-low) subreg store _does_ kill the whole reg.
>
The setting of DF_REF_PARTIAL has been redone in df-scan.c so that it
fixes the problems mentioned in all of the mail.


> Bernd

In addition I split DF_REF_CLOBBER into DF_REF_MAY_CLOBBER and
DF_REF_MUST_CLOBBER cases (as you had requested in an earlier email). 
The may clobber is set for registers that cross calls. This may change
in the future as the aliasing gets better, we may be be able convert
some of them to must clobbers.  The must clobbers are set where we have
an explicit clobber in the code. 

The reaching defs and uninitialized register dataflow problems were
rewritten to take this fully into account since a gen is never created
for either may or must clobbers, but a kill is only generated for must
clobbers (assuming that it is not also DF_REF_PARTIAL.)

The code assumes that it is possible to have partial clobber even though
it is not clear if this will ever happen.

This patch has been bootstrapped and regression tested on

x86_64-unknown-linux-gnu
powerpc64-unknown-linux-gnu
i686-pc-linux-gnu


Is this ok?

Kenny (and Danny)

2006-05-17  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.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.
    * 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.

Index: df-scan.c
===================================================================
--- df-scan.c	(revision 113823)
+++ df-scan.c	(working copy)
@@ -65,9 +65,6 @@ Software Foundation, 51 Franklin Street,
 #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 *
   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 *d
    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, b
   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
 {
   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 
   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 
       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 
 	  {
 	    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 
   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 *df
   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_
 	    = 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_
 	    = 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 *df
   unsigned int uid = INSN_UID (insn);
   struct df_insn_info *insn_info = NULL;
   struct df_ref *ref;
-  struct df_scan_problem_data *problem_data =
-    (struct df_scan_problem_data *) dflow->problem_data;
+  struct df_scan_problem_data *problem_data
+    = (struct df_scan_problem_data *) dflow->problem_data;
 
   if (uid < df->insns_size)
     insn_info = DF_INSN_UID_GET (df, uid);
 
   if (insn_info)
     {
+      struct df_mw_hardreg *hardregs = insn_info->mw_hardregs;
+      
+      while (hardregs)
+	{
+	  struct df_mw_hardreg *next_hr = hardregs->next;
+	  struct df_link *link = hardregs->regs;
+	  while (link)
+	    {
+	      struct df_link *next_l = link->next;
+	      pool_free (problem_data->mw_link_pool, link);
+	      link = next_l;
+	    }
+	  
+	  pool_free (problem_data->mw_reg_pool, hardregs);
+	  hardregs = next_hr;
+	}
+
       ref = insn_info->defs;
       while (ref) 
 	ref = df_reg_chain_unlink (dflow, ref);
@@ -876,20 +920,6 @@ df_reorganize_refs (struct df_ref_info *
 }
 
 
-/* Local miscellaneous routines.  */
-
-/* Local routines for recording refs.  */
-
-/* Set where we are in the compilation.  */
-
-void 
-df_set_state (int state)
-{
-  df_state = state;
-}
-
-
-
 /*----------------------------------------------------------------------------
    Hard core instruction scanning code.  No external interfaces here,
    just a lot of routines that look inside insns.
@@ -906,8 +936,8 @@ df_ref_create_structure (struct dataflow
   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
 
   /* 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, r
 	       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, r
      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, r
   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, r
 				      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)
@@ -1067,8 +1135,16 @@ df_ref_record (struct dataflow *dflow, r
 		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 *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,
 	  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,
 	}
 #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, 
     {
       /* 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, 
 
     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 *df
       /* 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 *df
 			  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 *df
 				  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 *dflo
   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 *dflo
     }
 
 #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 *dflo
 #endif
 
 
-  if ((df->flags & DF_HARD_REGS)
+  if ((dflow->flags & DF_HARD_REGS)
       && df_has_eh_preds (bb))
     {
 #ifdef EH_USES
@@ -1611,23 +1703,19 @@ df_bb_refs_record (struct dataflow *dflo
 	{
 	  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
@@ -1638,29 +1726,37 @@ df_bb_refs_record (struct dataflow *dflo
 	  
 	  /* 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 dataf
     }
   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 dataf
 	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,7 +1933,7 @@ df_record_exit_block_uses (struct datafl
 
   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
@@ -1845,7 +1952,7 @@ df_record_exit_block_uses (struct datafl
      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
@@ -1915,7 +2022,7 @@ df_record_exit_block_uses (struct datafl
   /* 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: df-core.c
===================================================================
--- df-core.c	(revision 113823)
+++ df-core.c	(working copy)
@@ -45,7 +45,7 @@ Here is an example of using the dataflow
 
       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 obje
 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
 
   /* 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
 }
 
 
+/* 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 blo
 }
 
 
+/* 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 *
   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
    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 *dfl
 {
   /* (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
@@ -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, struc
 	       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 ATTRIB
 }
 
 
-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, 
   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 
 
 
 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");
 }
 
@@ -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: df.h
===================================================================
--- df.h	(revision 113823)
+++ df.h	(working copy)
@@ -34,6 +34,7 @@ Software Foundation, 51 Franklin Street,
 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
 /* 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
@@ -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 (struc
 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 
 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: df-problems.c
===================================================================
--- df-problems.c	(revision 113823)
+++ df-problems.c	(working copy)
@@ -43,30 +43,23 @@ Software Foundation, 51 Franklin Street,
 #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 *);
 
 
 /*----------------------------------------------------------------------------
    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,7 +339,9 @@ df_ru_free_bb_info (struct dataflow *dfl
    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;
@@ -359,8 +354,8 @@ df_ru_alloc (struct dataflow *dflow, bit
   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, bit
      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 (stru
   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 (stru
 		    }
 		  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);
@@ -523,14 +521,14 @@ df_ru_bb_local_compute (struct dataflow 
 	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 *df
   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 *dfl
 
   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
 {
   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");
 
@@ -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);
 }
 
 
@@ -869,7 +871,9 @@ df_rd_free_bb_info (struct dataflow *dfl
    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;
@@ -882,8 +886,8 @@ df_rd_alloc (struct dataflow *dflow, bit
   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, bit
 
   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 (stru
 	    {
 	      /* 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 (stru
 		    }
 		  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 (stru
 	      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));
 	    }
 	}
@@ -1024,7 +1032,7 @@ df_rd_bb_local_compute (struct dataflow 
 	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 *df
   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 *dfl
 
   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
 {
   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");
@@ -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,7 +1372,8 @@ df_lr_free_bb_info (struct dataflow *dfl
    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;
@@ -1371,10 +1384,6 @@ df_lr_alloc (struct dataflow *dflow, bit
 
   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 
 
   /* 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);
@@ -1432,7 +1442,7 @@ df_lr_bb_local_compute (struct dataflow 
 
       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 
 					      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 
 		  && 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 
 #endif
 }
 
+
 /* Compute local live register info for each basic block within BLOCKS.  */
 
 static void
@@ -1586,6 +1606,7 @@ df_lr_confluence_0 (struct dataflow *dfl
 
 
 /* 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 *dfl
 
 
 /* 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
 {
   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,7 +1784,8 @@ df_ur_free_bb_info (struct dataflow *dfl
    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;
@@ -1767,10 +1796,6 @@ df_ur_alloc (struct dataflow *dflow, bit
 
   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 
       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 *d
       bitmap_and_into (bb_info->out, tmp);
 #endif
     }
-  
+
   BITMAP_FREE (tmp);
 }
 
@@ -1998,6 +2030,9 @@ df_ur_dump (struct dataflow *dflow, FILE
 {
   basic_block bb;
   
+  if (!dflow->block_info) 
+    return;
+
   fprintf (file, "Undefined regs:\n");
  
   FOR_ALL_BB (bb)
@@ -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,12 +2152,14 @@ df_urec_free_bb_info (struct dataflow *d
    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)
     dflow->block_pool = create_alloc_pool ("df_urec_block pool", 
@@ -2136,10 +2174,6 @@ df_urec_alloc (struct dataflow *dflow, b
 
   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 dataflo
       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 *
 #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 
   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, FI
 {
   basic_block bb;
   
+  if (!dflow->block_info) 
+    return;
+
   fprintf (file, "Undefined regs:\n");
  
   FOR_ALL_BB (bb)
@@ -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 *df
 
   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 *df
 	    }
 	}
 
-      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 *dflo
     }
   
   /* 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 *dflo
 	}
     }
 
-  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, 
 
 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 d
 		    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 *dfl
   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 *dfl
 #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 *dfl
     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.  */
@@ -2921,25 +2945,27 @@ df_chain_create_bb (struct dataflow *dfl
       /* 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, 
 {
   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, 
 		       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, 
 		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
 
-  problem_data->lifetime = xrealloc (problem_data->lifetime, 
-				     max_reg_num () *sizeof (int));
-  memset (problem_data->lifetime, 0, max_reg_num () *sizeof (int));
+	  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;
+	}
+    }
 }
 
-/* Compute register info: lifetime, bb, and number of defs and uses
-   for basic block BB.  */
+
+/* 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_ri_bb_compute (struct dataflow *dflow, unsigned int bb_index, bitmap live)
+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;
+    }
+
+  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);
+}
+
+
+/* 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, 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;
-
+      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, b
 {
   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, b
 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)
-{
-  return df_add_problem (df, &problem_RI);
-}
-
-
-/* Return total lifetime (in insns) of REG.  */
-int
-df_reg_lifetime (struct df *df, rtx reg)
+df_ri_add_problem (struct df *df, int flags)
 {
-  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)];
+  return df_add_problem (df, &problem_RI, flags);
 }
-
-
Index: modulo-sched.c
===================================================================
--- modulo-sched.c	(revision 113823)
+++ modulo-sched.c	(working copy)
@@ -935,8 +935,8 @@ sms_schedule (void)
 
   /* 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_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: see.c
===================================================================
--- see.c	(revision 113823)
+++ see.c	(working copy)
@@ -1324,8 +1324,7 @@ 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_rd_add_problem (df, 0);
   df_chain_add_problem (df, DF_DU_CHAIN | DF_UD_CHAIN);
   df_analyze (df);
 
Index: final.c
===================================================================
--- final.c	(revision 113823)
+++ final.c	(working copy)
@@ -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: rtl.h
===================================================================
--- rtl.h	(revision 113823)
+++ rtl.h	(working copy)
@@ -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: reg-stack.c
===================================================================
--- reg-stack.c	(revision 113823)
+++ reg-stack.c	(working copy)
@@ -187,6 +187,8 @@ static VEC(char,heap) *stack_regs_mentio
 
 #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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]