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.


Bernd Schmidt wrote:
> Kenneth Zadeck wrote:
>> The larger bugs are:
>>
>> 1) Subregs were handled improperly.  Subreg stores were treated as
>> kills rather than mods.  This terminated some def use chains
>> prematurely.
>
> One of the maddening things about subregs is that sometimes they're
> kills (generally, lowpart subregs of a single word value, outside a
> strict_lowpart), sometimes they are modifications (single-word subregs
> of a multiword value).
>
df handles subregs and multiword regs in a manner similar to the way
that flow does:  for the purpose of liveness testing, each word of a
multiword reg is treated as its own entity and all of the subregs of a
single word are handled as single entity.

For the purposes of building reg_dead and reg_unused notes, a note is
built for a multiword ref if it all behaves the same way otherwise
separate notes are built for each word.

The df code always broke multiword regs so that there was a ref for each
word.  The subreg fix that danny and I implemented now marks each of
these refs as a subreg with a bit during scanning.  We examine this bit
when we are building the transfer functions so that defs to subregs no
longer kill, the only mod the value flowing across the def.

All of the multiword reg stuff that was added to support reg_dead and
reg_unused and does not effect the building of transfer functions.

> From a cursory glance at your changes it isn't obvious to me how/where
> this is handled.  It would be easier to review them if they were
> posted one patch per fix.
>
>
I have divided the patch into 10 patches.  I tested that each of the
patches can be applied separately.  However, it is unlikely that they
will compile since many of the lines are part of several of the patches
and many of the separate patched depend on the same set of declaration
changes.  However, examination of each of the patches will give a good
view of what is being changed.

> The larger bugs are:
>
> 1) Subregs were handled improperly.  Subreg stores were treated as
> kills rather than mods.  This terminated some def use chains
> prematurely.

This part is in subreg.diff

>
> 2) Clobbers were also not being handled properly.  Clobbers in calls
> were treated the same as clobbers just in the code.  The two cases are
> now separated and dealt with properly.
>

this is now in clobber.diff

> This patch also fixes PR26855.  (I was preparing this patch before the
> bug report came in.)  This failure was almost certainly caused by one
> of the two problems mentoned above.  The particular test case causes a
> malformed def-use chain.  Either of the above problems could have
> caused it.

the testcase for this with the magic tickle is in test.diff

>
> The smaller bugs relate to inefficiencies or storage management
> issues:
>
> 1) The correct set of blocks was not being reinitialized in the
> reaching defs and reaching uses problems.  This is only be a problem
> if the problem is rerun using the same instance of df.  Because of the
> way the bits are layed out in the bit vectors, the transfer functions
> for all of the basic blocks must be rebuilt when any changes are made.
> This restriction is only true for these two dataflow problems.

this is in reset.diff

>
> 2) On certain architectures some hard registers could be put into set
> of artificial uses for a block more than once.
>

this is in artificial.diff

> 3) The code would crash if you asked it to rescan a basic block that
> had been deleted.
>

this is in reset.diff

> The cleanups are:
>
> 1) Making more of the code use the abstractions that were defined in df.h.

this is in lex.diff
>
> 2) Unifying the way flags are passed with the dataflow problems are
set up.
> This allows the dependent problems to be passed flags when they start.
>
this is in flags.diff

> 3) Removal of unused parameters from some of the debugging functions.
>
this is in debug.diff

> The additional features add by this patch are:
>
> 1) The RI problem now rebuilds REG_DEATH and REG_UNUSED notes in a
> compatible way to what flow does.  This pass can optionally build the
> register information that flow does.  In both cases, the df version is
> more precise because it is based on the pruned flow information that
> is obtained by applying both a forwards and a backwards view of the
> code.  This patch does not make use of this feature.

this is in reginfo.diff
> Bernd

Kenny
Index: df-scan.c
===================================================================
--- df-scan.c	(revision 112464)
+++ df-scan.c	(working copy)
@@ -1537,6 +1611,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)
@@ -1611,16 +1689,12 @@ 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
@@ -1638,29 +1712,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);
     }
 }
 
@@ -1750,6 +1832,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 +1856,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.  */
Index: df-problems.c
===================================================================
--- df-problems.c	(revision 112464)
+++ df-problems.c	(working copy)
@@ -1827,11 +1851,17 @@
 	  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);
+		{
+		  /* The clobber inside a call is really just a may
+		     clobber so it cannot be guaranteed to really
+		     destroy the value.  */
+		  if (!CALL_P (insn))
+		    bitmap_set_bit (bb_info->kill, regno);
+		}
 	      else
 		bitmap_set_bit (bb_info->gen, regno);
 	    }
Index: df.h
===================================================================
--- df.h	(revision 112464)
+++ df.h	(working copy)
@@ -530,12 +554,11 @@
 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);
Index: df-core.c
===================================================================
--- df-core.c	(revision 112464)
+++ df-core.c	(working copy)
@@ -1071,8 +1122,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)
@@ -1082,7 +1132,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, "}");
@@ -1107,13 +1157,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));
@@ -1122,15 +1191,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)
 {
@@ -1166,17 +1256,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");
 }
 
@@ -1207,27 +1297,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-problems.c
===================================================================
--- df-problems.c	(revision 112464)
+++ df-problems.c	(working copy)
@@ -46,7 +51,8 @@
 #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 *);
 
 
 /*----------------------------------------------------------------------------
@@ -206,7 +199,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)
@@ -2999,6 +3020,6 @@ 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");
 	    }
@@ -3028,7 +3049,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");
 	    }
 	}
Index: df-scan.c
===================================================================
--- df-scan.c	(revision 112464)
+++ df-scan.c	(working copy)
@@ -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);
 }
 
 /*----------------------------------------------------------------------------
@@ -1017,7 +1061,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))
@@ -1036,5 +1084,5 @@
 
-      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
@@ -1437,7 +1511,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 +1564,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;
@@ -1561,7 +1639,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 +1658,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
@@ -1627,7 +1701,7 @@
 	}
     }
 
-  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
@@ -1725,7 +1807,7 @@ df_record_entry_block_defs (struct dataf
 
   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++)
@@ -1826,7 +1919,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
@@ -1915,7 +2008,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 112464)
+++ 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.
@@ -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.  */
Index: df.h
===================================================================
--- df.h	(revision 112464)
+++ df.h	(working copy)
@@ -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
@@ -107,6 +151,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 +175,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 +199,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
@@ -288,12 +326,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
@@ -513,5 +533,7 @@ 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);
@@ -549,34 +572,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);
Index: df-problems.c
===================================================================
--- df-problems.c	(revision 112464)
+++ df-problems.c	(working copy)
@@ -53,19 +59,6 @@
    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 *
@@ -792,7 +793,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.  */
 };
 
 
@@ -802,9 +804,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);
 }
 
 
@@ -1293,7 +1303,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.  */
 };
 
 
@@ -1303,9 +1314,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);
 }
 
 
@@ -1641,6 +1662,8 @@ df_lr_free (struct dataflow *dflow)
       dflow->block_info_size = 0;
       free (dflow->block_info);
     }
+
+  free (dflow->problem_data);
   free (dflow);
 }
 
@@ -1690,7 +1716,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
 };
 
 
@@ -1699,9 +1726,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);
 }
 
 
@@ -2036,7 +2069,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.  */
 };
 
 
@@ -2045,9 +2079,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);
 }
 
 
@@ -2640,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.  */
 };
 
 
@@ -2649,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);
 }
 
 
@@ -2667,10 +2702,4 @@ 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.  */
@@ -2682,7 +2713,5 @@
   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)
@@ -2691,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);
@@ -2704,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);
@@ -2723,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;
@@ -2734,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)
@@ -2744,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) 
@@ -2763,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);
 
@@ -2782,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);
@@ -2793,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);
@@ -2829,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)
@@ -2857,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);
 		}
 	    }
@@ -2883,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);
@@ -2895,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
@@ -2923,8 +2946,8 @@ 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.  */
@@ -2941,7 +2965,7 @@ df_chain_create_bb (struct dataflow *dfl
 
   /* 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);
 }
 
@@ -2969,7 +2993,6 @@ static void
 df_chain_free (struct dataflow *dflow)
 {
   free_alloc_pool (dflow->block_pool);
-  free (dflow->problem_data);
   free (dflow);
 }
 
@@ -2981,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++)
@@ -3005,7 +3026,7 @@
 	}
     }
 
-  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++)
@@ -3052,7 +3073,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,13 +3085,6 @@ 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);
 }
 
Index: modulo-sched.c
===================================================================
--- modulo-sched.c	(revision 112464)
+++ 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: df-core.c
===================================================================
--- df-core.c	(revision 112464)
+++ df-core.c	(working copy)
@@ -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,
Index: df-scan.c
===================================================================
--- df-scan.c	(revision 112464)
+++ df-scan.c	(working copy)
@@ -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.  */
 
@@ -922,76 +954,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 +1051,8 @@ df_ref_record (struct dataflow *dflow, r
 	       enum df_ref_flags ref_flags, 
 	       bool record_live)
 {
-  unsigned int regno;
   struct df *df = dflow->df;
+  unsigned int regno;
 
   gcc_assert (REG_P (reg) || GET_CODE (reg) == SUBREG);
 
@@ -1424,8 +1498,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))
     {
@@ -1845,7 +1938,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
Index: df.h
===================================================================
--- df.h	(revision 112464)
+++ 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
@@ -398,8 +430,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.  */
 
@@ -517,5 +539,7 @@
 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);
Index: df-problems.c
===================================================================
--- df-problems.c	(revision 112464)
+++ df-problems.c	(working copy)
@@ -522,14 +520,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);
@@ -1023,7 +1030,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
@@ -1370,10 +1382,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);
@@ -1431,7 +1440,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);
 	      
@@ -1451,6 +1464,6 @@
       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);
 	      
@@ -1470,6 +1487,6 @@
 	}
 
-      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));
     }
@@ -1492,6 +1510,7 @@ df_lr_bb_local_compute (struct dataflow 
 #endif
 }
 
+
 /* Compute local live register info for each basic block within BLOCKS.  */
 
 static void
@@ -1585,6 +1604,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)
 {
@@ -1604,6 +1624,7 @@ df_lr_confluence_n (struct dataflow *dfl
 
 
 /* Transfer function.  */
+
 static bool
 df_lr_transfer_function (struct dataflow *dflow, int bb_index)
 {
@@ -1766,10 +1794,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);
@@ -1822,5 +1846,5 @@ 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)
 	{
@@ -1926,7 +1956,7 @@ df_ur_local_finalize (struct dataflow *d
       bitmap_and_into (bb_info->out, tmp);
 #endif
     }
-  
+
   BITMAP_FREE (tmp);
 }
 
@@ -2135,10 +2171,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);
@@ -2928,6 +2951,6 @@
 
       /* 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);
Index: df-scan.c
===================================================================
--- df-scan.c	(revision 112464)
+++ df-scan.c	(working copy)
@@ -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;
@@ -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);
 }
 
 
@@ -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);
@@ -762,6 +789,23 @@ df_insn_refs_delete (struct dataflow *df
 
   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);
@@ -1031,6 +1076,9 @@
   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;
 
@@ -1048,8 +1096,26 @@ 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);
+
+	  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 +1133,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
Index: df-core.c
===================================================================
--- df-core.c	(revision 112464)
+++ df-core.c	(working copy)
@@ -1107,11 +1157,24 @@ 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;
+    }
+}
+
 
Index: df.h
===================================================================
--- df.h	(revision 112464)
+++ df.h	(working copy)
@@ -62,6 +59,53 @@ 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 is really a clobber, and not a def.  */
+    DF_REF_CLOBBER = 32,
+
+    /* This bit is true if this ref is part of a multiword hardreg.  */
+    DF_REF_MW_HARDREG = 64,
+
+    /* This flag is set if this ref is a partial use or def of the
+       associated register.  */
+    DF_REF_PARTIAL = 128
+  };
+
+
 /* Function prototypes added to df_problem instance.  */
 
 /* Allocate the problem specific data.  */
@@ -158,17 +220,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 aggrigate 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 +258,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 +288,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;
@@ -422,7 +456,8 @@ 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. */ 
 
Index: df-problems.c
===================================================================
--- df-problems.c	(revision 112464)
+++ df-problems.c	(working copy)
@@ -42,4 +42,9 @@ Software Foundation, 51 Franklin Street,
 #include "bitmap.h"
 #include "timevar.h"
 #include "df.h"
+#include "except.h"
+
+#if 0
+#define REG_DEAD_DEBUGGING
+#endif
 
@@ -3076,91 +3091,557 @@
 
 /*----------------------------------------------------------------------------
    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. */
+
+#ifdef STACK_REGS
+static inline bool 
+df_ignore_stack_reg (int regno)
+{
+  return regstack_completed
+    && IN_RANGE (regno, FIRST_STACK_REG, LAST_STACK_REG);
+}
+#else
+static inline bool 
+df_ignore_stack_reg (int regno ATTRIBUTE_UNUSED)
+{
+  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))
+	{
+	  struct df_link *regs = mws->regs;
+	  rtx note = alloc_EXPR_LIST (REG_DEAD, *DF_REF_LOC (regs->ref), 
+				      REG_NOTES (insn));
+	  REG_NOTES (insn) = note;
+#ifdef REG_DEAD_DEBUGGING
+	  print_note ("adding 1: ", insn, note);
+#endif
+
+	  if (flags & DF_RI_LIFE)
+	    {
+	      struct df_link *regs = mws->regs;
+	      while (regs)
+		{
+		  struct df_ref *ref = regs->ref;
+		  regno = DF_REF_REGNO (ref);
+		  REG_N_DEATHS (regno)++;
+		  regs = regs->next;
+		}
+	    }
+	}
+    }
+  else
+    {
+      struct df_link *regs = mws->regs;
+      while (regs)
+	{
+	  struct df_ref *ref = regs->ref;
+
+	  regno = DF_REF_REGNO (ref);
+	  if ((!bitmap_bit_p (live, regno))
+	      && (!bitmap_bit_p (artificial_uses, regno))
+	      && (!bitmap_bit_p (do_not_gen, regno)))
+	    {
+	      rtx note = alloc_EXPR_LIST (REG_DEAD, regno_reg_rtx[regno], 
+					  REG_NOTES (insn));
+	      REG_NOTES (insn) = note;
+	      if (flags & DF_RI_LIFE)
+		REG_N_DEATHS (regno)++;
+#ifdef REG_DEAD_DEBUGGING
+	      print_note ("adding 2: ", insn, note);
+#endif
+	    }
+
+	  regs = regs->next;
+	}
+    }
+}
+
+
+/* Create a REG_UNUSED note if necessary for DEF in INSN updating LIVE
+   and DO_NOT_GEN.  Do not generate notes for registers in artificial
+   uses.  */
+
+static void
+df_create_unused_note (basic_block bb, rtx insn, struct df_ref *def, 
+		       bitmap live, bitmap do_not_gen, bitmap artificial_uses, 
+		       bitmap local_live, bitmap local_processed, 
+		       int flags, int luid)
+{
+  unsigned int dregno = DF_REF_REGNO (def);
+  
+#ifdef REG_DEAD_DEBUGGING
+  fprintf (stderr, "  regular looking at def ");
+  df_ref_debug (def, stderr);
+#endif
+
+  if (bitmap_bit_p (live, dregno))
+    {
+      if (flags & DF_RI_LIFE)
+	{
+	  /* If we have seen this regno, then it has already been
+	     processed correctly with the per insn increment.  If we
+	     have not seen it we need to add the length from here to
+	     the end of the block to the live length.  */
+	  if (bitmap_bit_p (local_processed, dregno))
+	    {
+	      if (!(DF_REF_FLAGS (def) & DF_REF_PARTIAL))
+		bitmap_clear_bit (local_live, dregno);
+	    }
+	  else
+	    {
+	      bitmap_set_bit (local_processed, dregno);
+	      REG_LIVE_LENGTH (dregno) += luid;
+	    }
+	}
+    }
+  else if ( (!(DF_REF_FLAGS (def) & DF_REF_MW_HARDREG))
+	    && (!bitmap_bit_p (artificial_uses, dregno)) 
+	    && (!df_ignore_stack_reg (dregno)))
+    {
+      rtx reg = GET_CODE (*DF_REF_LOC (def)) == SUBREG ?
+	SUBREG_REG (*DF_REF_LOC (def)) : *DF_REF_LOC (def);
+      rtx note =
+	alloc_EXPR_LIST (REG_UNUSED, reg, REG_NOTES (insn));
+      REG_NOTES (insn) = note;
+#ifdef REG_DEAD_DEBUGGING
+      print_note ("adding 3: ", insn, note);
+#endif
+      if (flags & DF_RI_LIFE)
+	{
+	  REG_N_DEATHS (dregno) ++;
+	  REG_LIVE_LENGTH (dregno)++;
+	}
+    }
+  
+  if ((flags & DF_RI_LIFE) && (dregno >= FIRST_PSEUDO_REGISTER))
+    {
+      REG_FREQ (dregno) += REG_FREQ_FROM_BB (bb);
+      if (REG_BASIC_BLOCK (dregno) == REG_BLOCK_UNKNOWN)
+	REG_BASIC_BLOCK (dregno) = bb->index;
+      else if (REG_BASIC_BLOCK (dregno) != bb->index)
+	REG_BASIC_BLOCK (dregno) = REG_BLOCK_GLOBAL;
     }
 
-  problem_data->lifetime = xrealloc (problem_data->lifetime, 
-				     max_reg_num () *sizeof (int));
-  memset (problem_data->lifetime, 0, max_reg_num () *sizeof (int));
+  if (! (DF_REF_FLAGS (def) & DF_REF_CLOBBER))
+    bitmap_set_bit (do_not_gen, dregno);
+  
+  /* Kill this register if it is not a subreg store.  */
+  if (!(DF_REF_FLAGS (def) & DF_REF_PARTIAL))
+    bitmap_clear_bit (live, dregno);
 }
 
-/* Compute register info: lifetime, bb, and number of defs and uses
-   for basic block BB.  */
+
+/* Recompute the REG_DEAD and REG_UNUSED notes and compute register
+   info: lifetime, bb, and number of defs and uses for basic block
+   BB.  The three bitvectors are scratch regs used here.  */
 
 static void
-df_ri_bb_compute (struct dataflow *dflow, unsigned int bb_index, bitmap live)
+df_ri_bb_compute (struct dataflow *dflow, unsigned int bb_index, 
+		  bitmap live, bitmap do_not_gen, bitmap artificial_uses,
+		  bitmap local_live, bitmap local_processed, bitmap setjumps_crossed)
 {
   struct df *df = dflow->df;
-  struct df_ur_bb_info *bb_info = df_ur_get_bb_info (dflow, bb_index);
-  struct df_ri_problem_data *problem_data =
-    (struct df_ri_problem_data *) dflow->problem_data;
   basic_block bb = BASIC_BLOCK (bb_index);
   rtx insn;
+  struct df_ref *def;
+  struct df_ref *use;
+  int luid = 0;
 
-  bitmap_copy (live, bb_info->out);
+  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));
+
+  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);
+	    }
+
+	  for (def = DF_INSN_UID_DEFS (df, uid); def; def = def->next_ref)
+	    if (! (DF_REF_FLAGS (def) & DF_REF_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 +3653,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 +3705,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 +3715,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 +3742,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 +3756,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: rtl.h
===================================================================
--- rtl.h	(revision 112464)
+++ 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: final.c
===================================================================
--- final.c	(revision 112464)
+++ 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: reg-stack.c
===================================================================
--- reg-stack.c	(revision 112464)
+++ reg-stack.c	(working copy)
@@ -189,6 +189,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.
 
@@ -3153,6 +3155,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))
@@ -3161,6 +3164,8 @@ rest_of_handle_stack_regs (void)
           cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK);
         }
     }
+  else 
+    regstack_completed = 1;
 #endif
   return 0;
 }
Index: df-scan.c
===================================================================
--- df-scan.c	(revision 112464)
+++ df-scan.c	(working copy)
@@ -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;
@@ -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;
Index: df.h
===================================================================
--- df.h	(revision 112464)
+++ df.h	(working copy)
@@ -65,7 +108,7 @@
 /* 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
===================================================================
--- df-core.c	(revision 112464)
+++ df-core.c	(working copy)
@@ -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);
@@ -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
Index: df-problems.c
===================================================================
--- df-problems.c	(revision 112464)
+++ df-problems.c	(working copy)
@@ -345,7 +338,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;
@@ -400,7 +395,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)
@@ -740,6 +738,9 @@ df_ru_dump (struct dataflow *dflow, FILE
     (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");
 
@@ -868,7 +870,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;
@@ -919,11 +923,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)
@@ -1242,6 +1249,9 @@ df_rd_dump (struct dataflow *dflow, FILE
   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");
@@ -1359,7 +1370,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;
@@ -1652,6 +1675,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)
     {
@@ -1755,7 +1782,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;
@@ -1997,6 +2027,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)
@@ -2115,7 +2149,9 @@ 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;
@@ -2599,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)
@@ -2677,5 +2706,7 @@
 
 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)
+
 {
Index: df-scan.c
===================================================================
--- df-scan.c	(revision 112464)
+++ 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.  */
 
@@ -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.
Index: df.h
===================================================================
--- df.h	(revision 112464)
+++ df.h	(working copy)
@@ -431,21 +466,6 @@
 
 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
@@ -588,7 +609,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 112464)
+++ df-problems.c	(working copy)
@@ -2378,8 +2410,7 @@ 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;
Index: df-scan.c
===================================================================
--- df-scan.c	(revision 112464)
+++ df-scan.c	(working copy)
@@ -909,6 +939,8 @@ df_ref_create_structure (struct dataflow
   struct df_scan_problem_data *problem_data =
     (struct df_scan_problem_data *) dflow->problem_data;
 
+  if (GET_CODE (reg) == SUBREG)
+    ref_flags |= DF_REF_PARTIAL;
   this_ref = pool_alloc (problem_data->ref_pool);
   DF_REF_REG (this_ref) = reg;
   DF_REF_REGNO (this_ref) =  regno;
@@ -1026,5 +1070,6 @@ df_ref_record (struct dataflow *dflow, r
       loc = &SUBREG_REG (reg);
       reg = *loc;
       ref_flags |= DF_REF_STRIPPED;
+      ref_flags |= DF_REF_PARTIAL;
     }
 
Index: df-problems.c
===================================================================
--- df-problems.c	(revision 112464)
+++ df-problems.c	(working copy)
@@ -434,7 +429,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;
@@ -969,7 +973,10 @@ 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)))
 		{
 		  if (n_defs > DF_SPARSE_THRESHOLD)
 		    {
@@ -1409,7 +1417,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);
@@ -1442,9 +1451,13 @@ 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);
+		    }
 		}
 	    }
 	}
@@ -1463,7 +1476,11 @@ df_lr_bb_local_compute (struct dataflow 
 		  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);
+		}
 	    }
@@ -1476,7 +1493,8 @@
 
   /* 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);
@@ -2904,9 +2926,10 @@ 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_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_CLOBBER))
 	  bitmap_set_bit (cpy, DF_REF_ID (def));
       }
@@ -2934,8 +2957,9 @@
 	{
 	  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_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_CLOBBER))
 	    bitmap_set_bit (cpy, DF_REF_ID (def));
 	}
Index: testsuite/gcc.dg/pr26855.c
===================================================================
--- testsuite/gcc.dg/pr26855.c	(revision 0)
+++ testsuite/gcc.dg/pr26855.c	(revision 0)
@@ -0,0 +1,41 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fmodulo-sched -maltivec" { target powerpc*-*-* } } */
+extern void blatz (int);
+extern char *buf;
+extern int lcol, rcol;
+
+static int
+bar (char *a, int j, char *buf, int lcol, int rcol, char g)
+{
+  char *s1, *s2;
+  int   i;
+  
+  s1 = a;
+  s2 = buf;
+  for (i = 0; i < lcol; i++)
+    if (*s2) s2++;
+
+  for (i = lcol; i <= rcol; i++)
+    {
+      if (*s2 == '\t') {
+	blatz (3);
+	return 0;
+      }
+      if (j >= i)
+	*s1 = g;
+      else if (*s2 == '\0' || *s2 == '\n')
+	*s1 = g;
+      else if (*s2 == ' ')
+	*s1 = g;
+    }
+  return 1;
+}
+
+void
+foo(char *nptr, char *cs, char *rf, int j)
+{
+  if (! bar (cs, j, buf, lcol, rcol, '.'))
+    blatz (1);
+  else if (! bar (rf, j, buf, lcol, rcol, '.'))
+    blatz (2);
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]