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: [trunk] patch to remove REG_NO_CONFLICT_BLOCKS


Paolo Bonzini wrote:
> We have also changed things so that global is called
for -O0. This adds .5% to the compile time, but cuts the size of the .o files by 5%.

And probably improves performance by more than that. That's good long term since if the host compiler will be gcc >= 4.4 bootstraps will be sped up significantly (stage1 uses the host compiler with -g).


With this change, actually, you can also remove this wart from gimplify.c:

  /* If not optimizing, never really reuse a temporary.  local-alloc
     won't allocate any variable that is used in more than one basic
     block, which means it will go into memory, causing much extra
     work in reload and final and poorer code generation, outweighing
     the extra memory allocation here.  */

Having fewer pseudos may actually win you back that .5% :-)

It might be worth a try, but i doubt it. It will compromise code quality. Remember web.c is trying to undo the reuse of pseudos.
The third and fourth patches will require subsequent cleanup patches. These will come later but will not effect the performance or the correctness. In the case of patch 3, we will remove all of the code in global and ra-conflict that was there to support the preallocation of registers. We will also strip out the update-equiv-regs out of local and make that a separate pass.

Yes, and even more simplification is possible since this:


+  if (1)
+    return recorded_label_ref;
+

Steven will get to this when he cleans up local-alloc.

is always returning 0.

Now, on to the DF parts review,

+      if (DF_REF_FLAGS_IS_SET (ref, DF_REF_PRE_POST_MODIFY))
+    /* See the comment at the top.  */
+    return true;

I don't see a comment at the top that matches this...


done
This pass computes REG_DEAD and REG_UNUSED notes.

Since you are at it, can you change pass to problem on this line?


done
df_simulate_artificial_refs_at_top (basic_block bb, bitmap live)
{
struct df_ref **def_rec;
+#ifdef EH_USES
struct df_ref **use_rec;
+#endif
int bb_index = bb->index;
+#ifdef EH_USES
for (use_rec = df_get_artificial_uses (bb_index); *use_rec; use_rec++)
{
struct df_ref *use = *use_rec;
if (DF_REF_FLAGS (use) & DF_REF_AT_TOP)
bitmap_set_bit (live, DF_REF_REGNO (use));
}
+#endif

it is an optimization that is consistent with the other places where we look at artificial uses.
Is this just an optimization? (Just checking.)

+/* Fast psuedo DCE. */

pseudo-level


done
+/* Fast byte DCE. */

byte-level


done
Patch 1 is mostly okay with this nits addressed. If you want you can post the updates incrementally. But then, if you don't want post the whole blahblah again.

@@ -687,6 +738,7 @@ sbitmap_a_and_b_or_c (sbitmap dst, const
*dstp++ = *ap++ & (*bp++ | *cp++);
}
+
#ifdef IN_GCC
/* Set the bitmap DST to the intersection of SRC of successors of
block number BB, using the new flow graph structures. */

Extraneous hunk. Patch 2 (introducing sbitmap_range_empty_p) is simple enough that I'll approve it even though it's strictly speaking outside my maintainance area.


will do when i commit that patch.

thanks.

kenny
Paolo
2008-04-24  Richard Sandiford  <rsandifo@nildram.co.uk>
       Kenneth Zadeck <zadeck@naturalbridge.com>

* dbgcnt.def (ra_byte_scan): Added.
* dbgcnt.c (dbg_cnt): Added code to print message to dump_file
when the last hit happens for a counter. * timevar.def (TV_DF_BYTE_LR): New variable.
* tree-pass.h (pass_fast_rtl_byte_dce): New pass.
* passes.c (pass_fast_rtl_byte_dce): New pass.
* fwprop.c (update_df): Added mode to call df_ref_create.
Renamed DF_REF_WIDTH and DF_REF_OFFSET to DF_REF_EXTRACT_WIDTH and
DF_REF_EXTRACT_OFFSET.
* df.h (DF_BYTE_LR, DF_BYTE_LR_BB_INFO, DF_BYTE_LR_IN,
DF_BYTE_LR_OUT, df_byte_lr): New macro.
(df_mm): New enum.
(df_ref_extract): Added mode field.
(DF_REF_WIDTH, DF_REF_OFFSET) Renamed to DF_REF_EXTRACT_WIDTH and
DF_REF_EXTRACT_OFFSET.
(DF_REF_EXTRACT_MODE): New macro.
(df_byte_lr_bb_info): New structure.
(df_print_byte_regset, df_compute_accessed_bytes,
df_byte_lr_add_problem, df_byte_lr_get_regno_start,
df_byte_lr_get_regno_len, df_byte_lr_simulate_defs,
df_byte_lr_simulate_uses,
df_byte_lr_simulate_artificial_refs_at_top,
df_byte_lr_simulate_artificial_refs_at_end,
df_compute_accessed_bytes): New function.
(df_ref_create): Add parameter.
(df_byte_lr_get_bb_info): New inline function.
* df-scan.c (df_ref_record, df_uses_record,
df_ref_create_structure): Added mode parameter.
(df_ref_create, df_notes_rescan, df_ref_record, df_def_record_1,
df_defs_record, df_uses_record, df_get_conditional_uses,
df_get_call_refs, df_insn_refs_collect, df_bb_refs_collect,
df_entry_block_defs_collect, df_exit_block_uses_collect):
Added mode parameter to calls to df_ref_record, df_uses_record,
df_ref_create_structure.
(df_ref_equal_p, df_ref_compare): Added test for modes.
(df_ref_create_structure): Added code to set mode. Renamed
DF_REF_WIDTH and DF_REF_OFFSET to DF_REF_EXTRACT_WIDTH and
DF_REF_EXTRACT_OFFSET.
* df-core.c (df_print_byte_regset): New function.
* df-byte-scan.c: New file.
* df-problems.c (df_rd_transfer_function): Removed unnecessary
calls to BITMAP_FREE. (df_byte_lr_problem_data, df_problem problem_BYTE_LR): New structure.
(df_byte_lr_get_regno_start, df_byte_lr_get_regno_len,
df_byte_lr_set_bb_info, df_byte_lr_free_bb_info,
df_byte_lr_check_regs, df_byte_lr_expand_bitmap,
df_byte_lr_alloc, df_byte_lr_reset, df_byte_lr_bb_local_compute,
df_byte_lr_local_compute, df_byte_lr_init,
df_byte_lr_confluence_0, df_byte_lr_confluence_n,
df_byte_lr_transfer_function, df_byte_lr_free,
df_byte_lr_top_dump, df_byte_lr_bottom_dump,
df_byte_lr_add_problem, df_byte_lr_simulate_defs,
df_byte_lr_simulate_uses,
df_byte_lr_simulate_artificial_refs_at_top,
df_byte_lr_simulate_artificial_refs_at_end): New function.
* dce.c (byte_dce_process_block): New function.
(dce_process_block): au is now passed in rather than computed
locally. Changed loops that look at artificial defs to not look
for conditional or partial ones, because there never are any. (fast_dce): Now is able to drive byte_dce_process_block or
dce_process_block depending on the kind of dce being done.
(rest_of_handle_fast_dce): Add parameter to fast_dce.
(rest_of_handle_fast_byte_dce): New function.
(rtl_opt_pass pass_fast_rtl_byte_dce): New pass.
* Makefile.in (df-byte-scan.o, debugcnt.o): Added dependencies.


committed as revison 134523 right before richards comments arrived, i will update in a few minutes for his.



Index: fwprop.c
===================================================================
--- fwprop.c	(revision 134522)
+++ fwprop.c	(working copy)
@@ -679,6 +679,7 @@ update_df (rtx insn, rtx *loc, struct df
       struct df_ref *orig_use = use, *new_use;
       int width = -1;
       int offset = -1;
+      enum machine_mode mode = 0;
       rtx *new_loc = find_occurrence (loc, DF_REF_REG (orig_use));
       use_rec++;
 
@@ -687,15 +688,17 @@ update_df (rtx insn, rtx *loc, struct df
 
       if (DF_REF_FLAGS_IS_SET (orig_use, DF_REF_SIGN_EXTRACT | DF_REF_ZERO_EXTRACT))
 	{
-	  width = DF_REF_WIDTH (orig_use);
-	  offset = DF_REF_OFFSET (orig_use);
+	  width = DF_REF_EXTRACT_WIDTH (orig_use);
+	  offset = DF_REF_EXTRACT_OFFSET (orig_use);
+	  mode = DF_REF_EXTRACT_MODE (orig_use);
 	}
 
       /* Add a new insn use.  Use the original type, because it says if the
          use was within a MEM.  */
       new_use = df_ref_create (DF_REF_REG (orig_use), new_loc,
 			       insn, BLOCK_FOR_INSN (insn),
-			       type, DF_REF_FLAGS (orig_use) | new_flags, width, offset);
+			       type, DF_REF_FLAGS (orig_use) | new_flags, 
+			       width, offset, mode);
 
       /* Set up the use-def chain.  */
       df_chain_copy (new_use, DF_REF_CHAIN (orig_use));
Index: dbgcnt.def
===================================================================
--- dbgcnt.def	(revision 134522)
+++ dbgcnt.def	(working copy)
@@ -61,6 +61,83 @@ along with GCC; see the file COPYING3.  
    Use -fdbg-cnt=counter1:N,counter2:M,...
    which sets the limit for counter1 to N, and the limit for counter2 to M, etc.
    e.g. setting a limit to zero will make dbg_cnt () return false *always*.
+
+   The following shell file can then be used to binary search for
+   exact transformation that causes the bug.  A second shell script
+   should be written, say "tryTest", which exits with 1 if the
+   compiled program fails and exits with 0 if the program succeeds.
+   This shell script should take 1 parameter, the value to be passed
+   to set the counter of the compilation command in tryTest.  Then,
+   assuming that the following script is called binarySearch,
+   the command:
+
+	binarySearch tryTest 
+
+   will automatically find the highest value of the counter for which
+   the program fails.  If tryTest never fails, binarySearch will
+   produce unpredictable results as it will try to find an upper bound
+   that does not exist.
+
+   When dbgcnt does hits the limit, it writes a comment in the current
+   dump_file of the form:
+
+       ***dbgcnt: limit reached for %s.***
+	
+   Assuming that the dump file is logging the analysis/transformations
+   it is making, this pinpoints the exact position in the log file
+   where the problem transformation is being logged.
+
+=====================================
+#!/bin/bash
+
+while getopts "l:u:i:" opt
+do
+    case $opt in
+        l) lb="$OPTARG";;
+        u) ub="$OPTARG";;
+        i) init="$OPTARG";;
+        ?) usage; exit 3;;
+    esac
+done
+
+shift $(($OPTIND - 1))
+echo $@
+cmd=${1+"${@}"}
+
+lb=${lb:=0}
+init=${init:=100}
+
+$cmd $lb
+lb_val=$?
+if [ -z "$ub" ]; then
+    # find the upper bound
+    ub=$(($init + $lb))
+    true
+    while [ $? -eq $lb_val ]; do
+        ub=$(($ub * 10))
+        #ub=`expr $ub \* 10`
+        $cmd $ub
+    done
+fi
+
+echo command: $cmd
+
+true
+while [ `expr $ub - $lb` -gt 1 ]; do
+    try=$(($lb + ( $ub - $lb ) / 2))
+    $cmd $try
+    if [ $? -eq $lb_val ]; then
+        lb=$try
+    else
+        ub=$try
+    fi
+done
+
+echo lbound: $lb
+echo ubound: $ub
+
+=====================================
+
 */
 
 /* Debug counter definitions.  */
@@ -73,6 +150,7 @@ DEBUG_COUNTER (dce)
 DEBUG_COUNTER (dce_fast)
 DEBUG_COUNTER (dce_ud)
 DEBUG_COUNTER (delete_trivial_dead)
+DEBUG_COUNTER (df_byte_scan)
 DEBUG_COUNTER (dse)
 DEBUG_COUNTER (dse1)
 DEBUG_COUNTER (dse2)
Index: tree-pass.h
===================================================================
--- tree-pass.h	(revision 134522)
+++ tree-pass.h	(working copy)
@@ -423,6 +423,7 @@ extern struct rtl_opt_pass pass_partitio
 extern struct rtl_opt_pass pass_match_asm_constraints;
 extern struct rtl_opt_pass pass_regmove;
 extern struct rtl_opt_pass pass_split_all_insns;
+extern struct rtl_opt_pass pass_fast_rtl_byte_dce;
 extern struct rtl_opt_pass pass_lower_subreg2;
 extern struct rtl_opt_pass pass_mode_switching;
 extern struct rtl_opt_pass pass_see;
Index: df-scan.c
===================================================================
--- df-scan.c	(revision 134522)
+++ df-scan.c	(working copy)
@@ -95,7 +95,7 @@ static struct df_mw_hardreg * df_null_mw
 static void df_ref_record (struct df_collection_rec *,
 			   rtx, rtx *, 
 			   basic_block, rtx, enum df_ref_type, 
-			   enum df_ref_flags, int, int);
+			   enum df_ref_flags, int, int, enum machine_mode);
 static void df_def_record_1 (struct df_collection_rec *,
 			     rtx, basic_block, rtx,
 			     enum df_ref_flags);
@@ -104,11 +104,13 @@ static void df_defs_record (struct df_co
 			    enum df_ref_flags);
 static void df_uses_record (struct df_collection_rec *,
 			    rtx *, enum df_ref_type,
-			    basic_block, rtx, enum df_ref_flags, int, int);
+			    basic_block, rtx, enum df_ref_flags, 
+			    int, int, enum machine_mode);
 
 static struct df_ref *df_ref_create_structure (struct df_collection_rec *, rtx, rtx *, 
 					       basic_block, rtx, enum df_ref_type, 
-					       enum df_ref_flags, int, int);
+					       enum df_ref_flags, 
+					       int, int, enum machine_mode);
 
 static void df_insn_refs_collect (struct df_collection_rec*, 
 				  basic_block, rtx); 
@@ -616,16 +618,16 @@ df_scan_blocks (void)
    LOC within INSN of BB.  This function is only used externally. 
 
    If the REF_FLAGS field contain DF_REF_SIGN_EXTRACT or
-   DF_REF_ZERO_EXTRACT.  WIDTH and OFFSET are used to access the fields
-   if they were constants.  Otherwise they should be -1 if those flags
-   were set.  */
+   DF_REF_ZERO_EXTRACT.  WIDTH, OFFSET and MODE are used to access the
+   fields if they were constants.  Otherwise they should be -1 if
+   those flags were set.  */
 
 struct df_ref *
 df_ref_create (rtx reg, rtx *loc, rtx insn, 
 	       basic_block bb,
 	       enum df_ref_type ref_type, 
 	       enum df_ref_flags ref_flags,
-	       int width, int offset)
+	       int width, int offset, enum machine_mode mode)
 {
   struct df_ref *ref;
   struct df_reg_info **reg_info;
@@ -640,7 +642,8 @@ df_ref_create (rtx reg, rtx *loc, rtx in
   /* You cannot hack artificial refs.  */
   gcc_assert (insn);
   ref = df_ref_create_structure (NULL, reg, loc, bb, insn,
-                                 ref_type, ref_flags, width, offset);
+                                 ref_type, ref_flags, 
+				 width, offset, mode);
 
   if (DF_REF_TYPE (ref) == DF_REF_REG_DEF)
     {
@@ -2066,7 +2069,7 @@ df_notes_rescan (rtx insn)
 	    case REG_EQUAL:
 	      df_uses_record (&collection_rec,
 			      &XEXP (note, 0), DF_REF_REG_USE,
-			      bb, insn, DF_REF_IN_NOTE, -1, -1);
+			      bb, insn, DF_REF_IN_NOTE, -1, -1, 0);
 	    default:
 	      break;
 	    }
@@ -2142,8 +2145,9 @@ df_ref_equal_p (struct df_ref *ref1, str
      compared in the next set of tests.  */
   if ((DF_REF_FLAGS_IS_SET (ref1, DF_REF_SIGN_EXTRACT | DF_REF_ZERO_EXTRACT))
       && (DF_REF_FLAGS_IS_SET (ref2, DF_REF_SIGN_EXTRACT | DF_REF_ZERO_EXTRACT))
-      && ((DF_REF_OFFSET (ref1) != DF_REF_OFFSET (ref2))
-	  || (DF_REF_WIDTH (ref1) != DF_REF_WIDTH (ref2))))
+      && ((DF_REF_EXTRACT_OFFSET (ref1) != DF_REF_EXTRACT_OFFSET (ref2))
+	  || (DF_REF_EXTRACT_WIDTH (ref1) != DF_REF_EXTRACT_WIDTH (ref2))
+	  || (DF_REF_EXTRACT_MODE (ref1) != DF_REF_EXTRACT_MODE (ref2))))
     return false;
 
   return (ref1 == ref2) ||
@@ -2199,10 +2203,12 @@ df_ref_compare (const void *r1, const vo
      at ref1.  */
   if (DF_REF_FLAGS_IS_SET (ref1, DF_REF_SIGN_EXTRACT | DF_REF_ZERO_EXTRACT))
     {
-      if (DF_REF_OFFSET (ref1) != DF_REF_OFFSET (ref2))
-	return DF_REF_OFFSET (ref1) - DF_REF_OFFSET (ref2);
-      if (DF_REF_WIDTH (ref1) != DF_REF_WIDTH (ref2))
-	return DF_REF_WIDTH (ref1) - DF_REF_WIDTH (ref2);
+      if (DF_REF_EXTRACT_OFFSET (ref1) != DF_REF_EXTRACT_OFFSET (ref2))
+	return DF_REF_EXTRACT_OFFSET (ref1) - DF_REF_EXTRACT_OFFSET (ref2);
+      if (DF_REF_EXTRACT_WIDTH (ref1) != DF_REF_EXTRACT_WIDTH (ref2))
+	return DF_REF_EXTRACT_WIDTH (ref1) - DF_REF_EXTRACT_WIDTH (ref2);
+      if (DF_REF_EXTRACT_MODE (ref1) != DF_REF_EXTRACT_MODE (ref2))
+	return DF_REF_EXTRACT_MODE (ref1) - DF_REF_EXTRACT_MODE (ref2);
     }
   return 0;
 }
@@ -2583,7 +2589,7 @@ df_refs_add_to_chains (struct df_collect
 /* Allocate a ref and initialize its fields. 
 
    If the REF_FLAGS field contain DF_REF_SIGN_EXTRACT or
-   DF_REF_ZERO_EXTRACT.  WIDTH and OFFSET are used to access the fields
+   DF_REF_ZERO_EXTRACT.  WIDTH, OFFSET and MODE are used to access the fields
    if they were constants.  Otherwise they should be -1 if those flags
    were set.  */
 
@@ -2593,7 +2599,7 @@ df_ref_create_structure (struct df_colle
 			 basic_block bb, rtx insn, 
 			 enum df_ref_type ref_type, 
 			 enum df_ref_flags ref_flags,
-			 int width, int offset)
+			 int width, int offset, enum machine_mode mode)
 {
   struct df_ref *this_ref;
   int regno = REGNO (GET_CODE (reg) == SUBREG ? SUBREG_REG (reg) : reg);
@@ -2603,8 +2609,9 @@ df_ref_create_structure (struct df_colle
   if (ref_flags & (DF_REF_SIGN_EXTRACT | DF_REF_ZERO_EXTRACT))
     {
       this_ref = pool_alloc (problem_data->ref_extract_pool);
-      DF_REF_WIDTH (this_ref) = width;
-      DF_REF_OFFSET (this_ref) = offset;
+      DF_REF_EXTRACT_WIDTH (this_ref) = width;
+      DF_REF_EXTRACT_OFFSET (this_ref) = offset;
+      DF_REF_EXTRACT_MODE (this_ref) = mode;
     }
   else
     this_ref = pool_alloc (problem_data->ref_pool);
@@ -2659,9 +2666,9 @@ df_ref_create_structure (struct df_colle
    at address LOC within INSN of BB. 
 
    If the REF_FLAGS field contain DF_REF_SIGN_EXTRACT or
-   DF_REF_ZERO_EXTRACT.  WIDTH and OFFSET are used to access the fields
-   if they were constants.  Otherwise they should be -1 if those flags
-   were set.  */
+   DF_REF_ZERO_EXTRACT.  WIDTH, OFFSET and MODE are used to access the
+   fields if they were constants.  Otherwise they should be -1 if
+   those flags were set.  */
 
 
 static void
@@ -2670,7 +2677,7 @@ df_ref_record (struct df_collection_rec 
 	       basic_block bb, rtx insn, 
 	       enum df_ref_type ref_type, 
 	       enum df_ref_flags ref_flags,
-	       int width, int offset) 
+	       int width, int offset, enum machine_mode mode) 
 {
   unsigned int regno;
 
@@ -2719,7 +2726,8 @@ df_ref_record (struct df_collection_rec 
       for (i = regno; i < endregno; i++)
 	{
 	  ref = df_ref_create_structure (collection_rec, regno_reg_rtx[i], loc, 
-					 bb, insn, ref_type, ref_flags, width, offset);
+					 bb, insn, ref_type, ref_flags, 
+					 width, offset, mode);
 
           gcc_assert (ORIGINAL_REGNO (DF_REF_REG (ref)) == i);
 	}
@@ -2728,7 +2736,7 @@ df_ref_record (struct df_collection_rec 
     {
       struct df_ref *ref;
       ref = df_ref_create_structure (collection_rec, reg, loc, bb, insn, 
-                                     ref_type, ref_flags, width, offset);
+                                     ref_type, ref_flags, width, offset, mode);
     }
 }
 
@@ -2764,6 +2772,7 @@ df_def_record_1 (struct df_collection_re
   rtx dst;
   int offset = -1;
   int width = -1;
+  enum machine_mode mode = 0;
 
  /* We may recursively call ourselves on EXPR_LIST when dealing with PARALLEL
      construct.  */
@@ -2808,6 +2817,7 @@ df_def_record_1 (struct df_collection_re
 	{
 	  width = INTVAL (XEXP (dst, 1));
 	  offset = INTVAL (XEXP (dst, 2));
+	  mode = GET_MODE (dst);
 	}
 
       loc = &XEXP (dst, 0);
@@ -2818,13 +2828,15 @@ df_def_record_1 (struct df_collection_re
   if (REG_P (dst))
     {
       df_ref_record (collection_rec, 
-		     dst, loc, bb, insn, DF_REF_REG_DEF, flags, width, offset);
+		     dst, loc, bb, insn, DF_REF_REG_DEF, flags, 
+		     width, offset, mode);
 
       /* We want to keep sp alive everywhere - by making all
 	 writes to sp also use of sp. */
       if (REGNO (dst) == STACK_POINTER_REGNUM)
 	df_ref_record (collection_rec,
-		       dst, NULL, bb, insn, DF_REF_REG_USE, flags, width, offset);
+		       dst, NULL, bb, insn, DF_REF_REG_USE, flags, 
+		       width, offset, mode);
     }
   else if (GET_CODE (dst) == SUBREG && REG_P (SUBREG_REG (dst)))
     {
@@ -2834,7 +2846,8 @@ df_def_record_1 (struct df_collection_re
       flags |= DF_REF_SUBREG;
 
       df_ref_record (collection_rec, 
-		     dst, loc, bb, insn, DF_REF_REG_DEF, flags, width, offset);
+		     dst, loc, bb, insn, DF_REF_REG_DEF, flags, 
+		     width, offset, mode);
     }
 }
 
@@ -2873,15 +2886,15 @@ df_defs_record (struct df_collection_rec
 /* Process all the registers used in the rtx at address LOC.  
 
    If the REF_FLAGS field contain DF_REF_SIGN_EXTRACT or
-   DF_REF_ZERO_EXTRACT.  WIDTH and LOWER are used to access the fields
-   if they were constants.  Otherwise they should be -1 if those flags
-   were set.  */
+   DF_REF_ZERO_EXTRACT.  WIDTH, OFFSET and MODE are used to access the
+   fields if they were constants.  Otherwise they should be -1 if
+   those flags were set.  */
 
 static void
 df_uses_record (struct df_collection_rec *collection_rec,
                 rtx *loc, enum df_ref_type ref_type,
 		basic_block bb, rtx insn, enum df_ref_flags flags,
-		int width, int offset)
+		int width, int offset, enum machine_mode mode)
 {
   RTX_CODE code;
   rtx x;
@@ -2912,7 +2925,8 @@ df_uses_record (struct df_collection_rec
       if (MEM_P (XEXP (x, 0)))
 	df_uses_record (collection_rec,
 			&XEXP (XEXP (x, 0), 0),
-			DF_REF_REG_MEM_STORE, bb, insn, flags, width, offset);
+			DF_REF_REG_MEM_STORE, bb, insn, flags, 
+			width, offset, mode);
 
       /* If we're clobbering a REG then we have a def so ignore.  */
       return;
@@ -2920,7 +2934,8 @@ df_uses_record (struct df_collection_rec
     case MEM:
       df_uses_record (collection_rec,
 		      &XEXP (x, 0), DF_REF_REG_MEM_LOAD, 
-		      bb, insn, flags & DF_REF_IN_NOTE, width, offset);
+		      bb, insn, flags & DF_REF_IN_NOTE, 
+		      width, offset, mode);
       return;
 
     case SUBREG:
@@ -2930,14 +2945,16 @@ df_uses_record (struct df_collection_rec
       if (!REG_P (SUBREG_REG (x)))
 	{
 	  loc = &SUBREG_REG (x);
-	  df_uses_record (collection_rec, loc, ref_type, bb, insn, flags, width, offset);
+	  df_uses_record (collection_rec, loc, ref_type, bb, insn, flags, 
+			  width, offset, mode);
 	  return;
 	}
       /* ... Fall through ...  */
 
     case REG:
       df_ref_record (collection_rec, 
-		     x, loc, bb, insn, ref_type, flags, width, offset);
+		     x, loc, bb, insn, ref_type, flags, 
+		     width, offset, mode);
       return;
 
     case SIGN_EXTRACT:
@@ -2951,6 +2968,7 @@ df_uses_record (struct df_collection_rec
 	  {
 	    width = INTVAL (XEXP (x, 1));
 	    offset = INTVAL (XEXP (x, 2));
+	    mode = GET_MODE (x);
 
 	    if (code == ZERO_EXTRACT)
 	      flags |= DF_REF_ZERO_EXTRACT;
@@ -2958,7 +2976,8 @@ df_uses_record (struct df_collection_rec
 	      flags |= DF_REF_SIGN_EXTRACT;
 
 	    df_uses_record (collection_rec,
-			    &XEXP (x, 0), ref_type, bb, insn, flags, width, offset);
+			    &XEXP (x, 0), ref_type, bb, insn, flags, 
+			    width, offset, mode);
 	    return;
 	  }
       }
@@ -2969,7 +2988,8 @@ df_uses_record (struct df_collection_rec
 	rtx dst = SET_DEST (x);
 	gcc_assert (!(flags & DF_REF_IN_NOTE));
 	df_uses_record (collection_rec,
-			&SET_SRC (x), DF_REF_REG_USE, bb, insn, flags, width, offset);
+			&SET_SRC (x), DF_REF_REG_USE, bb, insn, flags, 
+			width, offset, mode);
 
 	switch (GET_CODE (dst))
 	  {
@@ -2978,7 +2998,8 @@ df_uses_record (struct df_collection_rec
 		{
 		  df_uses_record (collection_rec, &SUBREG_REG (dst), 
 				  DF_REF_REG_USE, bb, insn, 
-				  flags | DF_REF_READ_WRITE | DF_REF_SUBREG, width, offset);
+				  flags | DF_REF_READ_WRITE | DF_REF_SUBREG, 
+				  width, offset, mode);
 		  break;
 		}
 	      /* Fall through.  */
@@ -2990,7 +3011,8 @@ df_uses_record (struct df_collection_rec
 		break;
 	    case MEM:
 	      df_uses_record (collection_rec, &XEXP (dst, 0),
-			      DF_REF_REG_MEM_STORE, bb, insn, flags, width, offset);
+			      DF_REF_REG_MEM_STORE, bb, insn, flags, 
+			      width, offset, mode);
 	      break;
 	    case STRICT_LOW_PART:
 	      {
@@ -3001,7 +3023,8 @@ df_uses_record (struct df_collection_rec
 		df_uses_record (collection_rec, 
 				(GET_CODE (dst) == SUBREG) ? &SUBREG_REG (dst) : temp, 
 				DF_REF_REG_USE, bb, insn, 
-				DF_REF_READ_WRITE | DF_REF_STRICT_LOW_PART, width, offset);
+				DF_REF_READ_WRITE | DF_REF_STRICT_LOW_PART, 
+				width, offset, mode);
 	      }
 	      break;
 	    case ZERO_EXTRACT:
@@ -3011,18 +3034,22 @@ df_uses_record (struct df_collection_rec
 		  {
 		    width = INTVAL (XEXP (dst, 1));
 		    offset = INTVAL (XEXP (dst, 2));
+		    mode = GET_MODE (dst);
 		  }
 		else 
 		  {
 		    df_uses_record (collection_rec, &XEXP (dst, 1), 
-				    DF_REF_REG_USE, bb, insn, flags, width, offset);
+				    DF_REF_REG_USE, bb, insn, flags, 
+				    width, offset, mode);
 		    df_uses_record (collection_rec, &XEXP (dst, 2), 
-				    DF_REF_REG_USE, bb, insn, flags, width, offset);
+				    DF_REF_REG_USE, bb, insn, flags, 
+				    width, offset, mode);
 		  }
 
 		df_uses_record (collection_rec, &XEXP (dst, 0), 
 				DF_REF_REG_USE, bb, insn, 
-				DF_REF_READ_WRITE | DF_REF_ZERO_EXTRACT, width, offset);
+				DF_REF_READ_WRITE | DF_REF_ZERO_EXTRACT, 
+				width, offset, mode);
 	      }
 	      break;
 
@@ -3072,7 +3099,8 @@ df_uses_record (struct df_collection_rec
 
 	    for (j = 0; j < ASM_OPERANDS_INPUT_LENGTH (x); j++)
 	      df_uses_record (collection_rec, &ASM_OPERANDS_INPUT (x, j),
-			      DF_REF_REG_USE, bb, insn, flags, width, offset);
+			      DF_REF_REG_USE, bb, insn, flags, 
+			      width, offset, mode);
 	    return;
 	  }
 	break;
@@ -3087,7 +3115,8 @@ df_uses_record (struct df_collection_rec
       /* Catch the def of the register being modified.  */
       df_ref_record (collection_rec, XEXP (x, 0), &XEXP (x, 0), bb, insn, 
 		     DF_REF_REG_DEF,
-                     flags | DF_REF_READ_WRITE | DF_REF_PRE_POST_MODIFY, width, offset);
+                     flags | DF_REF_READ_WRITE | DF_REF_PRE_POST_MODIFY, 
+		     width, offset, mode);
 
       /* ... Fall through to handle uses ...  */
 
@@ -3111,7 +3140,8 @@ df_uses_record (struct df_collection_rec
 		goto retry;
 	      }
 	    df_uses_record (collection_rec, &XEXP (x, i), ref_type, 
-			    bb, insn, flags, width, offset);
+			    bb, insn, flags, 
+			    width, offset, mode);
 	  }
 	else if (fmt[i] == 'E')
 	  {
@@ -3119,7 +3149,8 @@ df_uses_record (struct df_collection_rec
 	    for (j = 0; j < XVECLEN (x, i); j++)
 	      df_uses_record (collection_rec,
 			      &XVECEXP (x, i, j), ref_type, 
-			      bb, insn, flags, width, offset);
+			      bb, insn, flags, 
+			      width, offset, mode);
 	  }
       }
   }
@@ -3141,19 +3172,21 @@ df_get_conditional_uses (struct df_colle
         {
 	  int width = -1;
 	  int offset = -1;
+	  enum machine_mode mode = 0;
           struct df_ref *use;
 
 	  if (DF_REF_FLAGS_IS_SET (ref, DF_REF_SIGN_EXTRACT | DF_REF_ZERO_EXTRACT))
 	    {
-	      width = DF_REF_WIDTH (ref);
-	      offset = DF_REF_OFFSET (ref);
+	      width = DF_REF_EXTRACT_WIDTH (ref);
+	      offset = DF_REF_EXTRACT_OFFSET (ref);
+	      mode = DF_REF_EXTRACT_MODE (ref);
 	    }
 
           use = df_ref_create_structure (collection_rec, DF_REF_REG (ref),
 					 DF_REF_LOC (ref), DF_REF_BB (ref),
 					 DF_REF_INSN (ref), DF_REF_REG_USE,
 					 DF_REF_FLAGS (ref) & ~DF_REF_CONDITIONAL,
-					 width, offset);
+					 width, offset, mode);
           DF_REF_REGNO (use) = DF_REF_REGNO (ref);
         }
     }
@@ -3191,7 +3224,7 @@ df_get_call_refs (struct df_collection_r
     {
       if (GET_CODE (XEXP (note, 0)) == USE)
         df_uses_record (collection_rec, &XEXP (XEXP (note, 0), 0),
-			DF_REF_REG_USE, bb, insn, flags, -1, -1);
+			DF_REF_REG_USE, bb, insn, flags, -1, -1, 0);
       else if (GET_CODE (XEXP (note, 0)) == CLOBBER)
 	{
 	  if (REG_P (XEXP (XEXP (note, 0), 0)))
@@ -3203,13 +3236,14 @@ df_get_call_refs (struct df_collection_r
 	    }
 	  else
 	    df_uses_record (collection_rec, &XEXP (note, 0),
-		            DF_REF_REG_USE, bb, insn, flags, -1, -1);
+		            DF_REF_REG_USE, bb, insn, flags, -1, -1, 0);
 	}
     }
 
   /* The stack ptr is used (honorarily) by a CALL insn.  */
   df_ref_record (collection_rec, regno_reg_rtx[STACK_POINTER_REGNUM],
-		 NULL, bb, insn, DF_REF_REG_USE, DF_REF_CALL_STACK_USAGE | flags, -1, -1);
+		 NULL, bb, insn, DF_REF_REG_USE, DF_REF_CALL_STACK_USAGE | flags, 
+		 -1, -1, 0);
 
   /* Calls may also reference any of the global registers,
      so they are recorded as used.  */
@@ -3217,9 +3251,9 @@ df_get_call_refs (struct df_collection_r
     if (global_regs[i])
       {
 	df_ref_record (collection_rec, regno_reg_rtx[i],
-		       NULL, bb, insn, DF_REF_REG_USE, flags, -1, -1);
+		       NULL, bb, insn, DF_REF_REG_USE, flags, -1, -1, 0);
 	df_ref_record (collection_rec, regno_reg_rtx[i],
-		       NULL, bb, insn, DF_REF_REG_DEF, flags, -1, -1);
+		       NULL, bb, insn, DF_REF_REG_DEF, flags, -1, -1, 0);
       }
 
   is_sibling_call = SIBLING_CALL_P (insn);
@@ -3232,7 +3266,8 @@ df_get_call_refs (struct df_collection_r
 	      || refers_to_regno_p (ui, ui+1, 
 				    crtl->return_rtx, NULL)))
         df_ref_record (collection_rec, regno_reg_rtx[ui], 
-		       NULL, bb, insn, DF_REF_REG_DEF, DF_REF_MAY_CLOBBER | flags, -1, -1);
+		       NULL, bb, insn, DF_REF_REG_DEF, DF_REF_MAY_CLOBBER | flags, 
+		       -1, -1, 0);
     }
 
   BITMAP_FREE (defs_generated);
@@ -3270,7 +3305,7 @@ df_insn_refs_collect (struct df_collecti
         case REG_EQUAL:
           df_uses_record (collection_rec,
                           &XEXP (note, 0), DF_REF_REG_USE,
-                          bb, insn, DF_REF_IN_NOTE, -1, -1);
+                          bb, insn, DF_REF_IN_NOTE, -1, -1, 0);
           break;
         case REG_NON_LOCAL_GOTO:
           /* The frame ptr is used by a non-local goto.  */
@@ -3278,13 +3313,13 @@ df_insn_refs_collect (struct df_collecti
                          regno_reg_rtx[FRAME_POINTER_REGNUM],
                          NULL,
                          bb, insn, 
-                         DF_REF_REG_USE, 0, -1, -1);
+                         DF_REF_REG_USE, 0, -1, -1, 0);
 #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
           df_ref_record (collection_rec,
                          regno_reg_rtx[HARD_FRAME_POINTER_REGNUM],
                          NULL,
                          bb, insn, 
-                         DF_REF_REG_USE, 0, -1, -1);
+                         DF_REF_REG_USE, 0, -1, -1, 0);
 #endif
           break;
         default:
@@ -3298,7 +3333,8 @@ df_insn_refs_collect (struct df_collecti
 
   /* Record the register uses.  */
   df_uses_record (collection_rec,
-		  &PATTERN (insn), DF_REF_REG_USE, bb, insn, 0, -1, -1);
+		  &PATTERN (insn), DF_REF_REG_USE, bb, insn, 0, 
+		  -1, -1, 0);
 
   /* DF_REF_CONDITIONAL needs corresponding USES. */
   if (is_cond_exec)
@@ -3381,7 +3417,7 @@ df_bb_refs_collect (struct df_collection
 	  if (regno == INVALID_REGNUM)
 	    break;
 	  df_ref_record (collection_rec, regno_reg_rtx[regno], NULL,
-			 bb, NULL, DF_REF_REG_DEF, DF_REF_AT_TOP, -1, -1);
+			 bb, NULL, DF_REF_REG_DEF, DF_REF_AT_TOP, -1, -1, 0);
 	}
     }
 #endif
@@ -3405,7 +3441,7 @@ df_bb_refs_collect (struct df_collection
       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
 	if (EH_USES (i))
 	  df_ref_record (collection_rec, regno_reg_rtx[i], NULL,
-			 bb, NULL, DF_REF_REG_USE, DF_REF_AT_TOP, -1, -1);
+			 bb, NULL, DF_REF_REG_USE, DF_REF_AT_TOP, -1, -1, 0);
     }
 #endif
 
@@ -3413,7 +3449,7 @@ df_bb_refs_collect (struct df_collection
      non-local goto.  */
   if (bb->flags & BB_NON_LOCAL_GOTO_TARGET)
     df_ref_record (collection_rec, hard_frame_pointer_rtx, NULL,
-		   bb, NULL, DF_REF_REG_DEF, DF_REF_AT_TOP, -1, -1);
+		   bb, NULL, DF_REF_REG_DEF, DF_REF_AT_TOP, -1, -1, 0);
  
   /* Add the artificial uses.  */
   if (bb->index >= NUM_FIXED_BLOCKS)
@@ -3427,7 +3463,7 @@ df_bb_refs_collect (struct df_collection
       EXECUTE_IF_SET_IN_BITMAP (au, 0, regno, bi)
 	{
 	  df_ref_record (collection_rec, regno_reg_rtx[regno], NULL,
-			 bb, NULL, DF_REF_REG_USE, 0, -1, -1);
+			 bb, NULL, DF_REF_REG_USE, 0, -1, -1, 0);
 	}
     }
 
@@ -3720,7 +3756,7 @@ df_entry_block_defs_collect (struct df_c
   EXECUTE_IF_SET_IN_BITMAP (entry_block_defs, 0, i, bi)
     {
       df_ref_record (collection_rec, regno_reg_rtx[i], NULL, 
-		     ENTRY_BLOCK_PTR, NULL, DF_REF_REG_DEF, 0, -1, -1);
+		     ENTRY_BLOCK_PTR, NULL, DF_REF_REG_DEF, 0, -1, -1, 0);
     }
 
   df_canonize_collection_rec (collection_rec);
@@ -3881,7 +3917,7 @@ df_exit_block_uses_collect (struct df_co
 
   EXECUTE_IF_SET_IN_BITMAP (exit_block_uses, 0, i, bi)
     df_ref_record (collection_rec, regno_reg_rtx[i], NULL,
-		   EXIT_BLOCK_PTR, NULL, DF_REF_REG_USE, 0, -1, -1);
+		   EXIT_BLOCK_PTR, NULL, DF_REF_REG_USE, 0, -1, -1, 0);
 
 #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
   /* It is deliberate that this is not put in the exit block uses but
@@ -3891,7 +3927,7 @@ df_exit_block_uses_collect (struct df_co
       && bb_has_eh_pred (EXIT_BLOCK_PTR)
       && fixed_regs[ARG_POINTER_REGNUM])
     df_ref_record (collection_rec, regno_reg_rtx[ARG_POINTER_REGNUM], NULL,
-		   EXIT_BLOCK_PTR, NULL, DF_REF_REG_USE, 0, -1, -1);
+		   EXIT_BLOCK_PTR, NULL, DF_REF_REG_USE, 0, -1, -1, 0);
 #endif
 
   df_canonize_collection_rec (collection_rec);
@@ -4363,9 +4399,8 @@ df_exit_block_bitmap_verify (bool abort_
 }
 
 
-/* Return true if df_ref information for all insns in all BLOCKS are
-   correct and complete.  If BLOCKS is null, all blocks are
-   checked.  */
+/* Return true if df_ref information for all insns in all blocks are
+   correct and complete.  */
 
 void
 df_scan_verify (void)
Index: df-core.c
===================================================================
--- df-core.c	(revision 134522)
+++ df-core.c	(working copy)
@@ -1875,6 +1875,69 @@ df_print_regset (FILE *file, bitmap r)
 }
 
 
+/* Write information about registers and basic blocks into FILE.  The
+   bitmap is in the form used by df_byte_lr.  This is part of making a
+   debugging dump.  */
+
+void
+df_print_byte_regset (FILE *file, bitmap r)
+{
+  unsigned int max_reg = max_reg_num ();
+  bitmap_iterator bi;
+
+  if (r == NULL)
+    fputs (" (nil)", file);
+  else
+    {
+      unsigned int i;
+      for (i = 0; i < max_reg; i++)
+	{
+	  unsigned int first = df_byte_lr_get_regno_start (i);
+	  unsigned int len = df_byte_lr_get_regno_len (i);
+
+	  if (len > 1)
+	    {
+	      bool found = false;
+	      unsigned int j;
+
+	      EXECUTE_IF_SET_IN_BITMAP (r, first, j, bi)
+		{
+		  found = j < first + len;
+		  break;
+		}
+	      if (found)
+		{
+		  const char * sep = "";
+		  fprintf (file, " %d", i);
+		  if (i < FIRST_PSEUDO_REGISTER)
+		    fprintf (file, " [%s]", reg_names[i]);
+		  fprintf (file, "(");
+		  EXECUTE_IF_SET_IN_BITMAP (r, first, j, bi)
+		    {
+		      if (j > first + len - 1)
+			break;
+		      fprintf (file, "%s%d", sep, j-first);
+		      sep = ", ";
+		    }
+		  fprintf (file, ")");
+		}
+	    }
+	  else
+	    {
+	      if (bitmap_bit_p (r, first))
+		{
+		  fprintf (file, " %d", i);
+		  if (i < FIRST_PSEUDO_REGISTER)
+		    fprintf (file, " [%s]", reg_names[i]);
+		}
+	    }
+
+	}
+    }
+  fprintf (file, "\n");
+}
+
+
 /* Dump dataflow info.  */
 
 void
Index: timevar.def
===================================================================
--- timevar.def	(revision 134522)
+++ timevar.def	(working copy)
@@ -64,6 +64,7 @@ DEFTIMEVAR (TV_DF_LR		     , "df live re
 DEFTIMEVAR (TV_DF_LIVE		     , "df live&initialized regs")
 DEFTIMEVAR (TV_DF_UREC		     , "df uninitialized regs 2")
 DEFTIMEVAR (TV_DF_CHAIN		     , "df use-def / def-use chains")
+DEFTIMEVAR (TV_DF_BYTE_LR	     , "df live byte regs")
 DEFTIMEVAR (TV_DF_NOTE		     , "df reg dead/unused notes")
 DEFTIMEVAR (TV_REG_STATS	     , "register information")
 
Index: dbgcnt.c
===================================================================
--- dbgcnt.c	(revision 134522)
+++ dbgcnt.c	(working copy)
@@ -23,6 +23,9 @@ See dbgcnt.def for usage information.  *
 #include "system.h"
 #include "coretypes.h"
 #include "errors.h"
+#include "tm.h"
+#include "rtl.h"
+#include "output.h"
 
 #include "dbgcnt.h"
 
@@ -58,6 +61,10 @@ bool
 dbg_cnt (enum debug_counter index)
 {
   count[index]++;
+  if (dump_file && count[index] == limit[index])
+    fprintf (dump_file, "***dbgcnt: limit reached for %s.***\n", 
+	     map[index].name);
+
   return dbg_cnt_is_enabled (index);
 }
 
@@ -132,7 +139,8 @@ dbg_cnt_process_opt (const char *arg)
 
 /* Print name, limit and count of all counters.   */
 
-void dbg_cnt_list_all_counters (void)
+void 
+dbg_cnt_list_all_counters (void)
 {
   int i;
   printf ("  %-30s %-5s %-5s\n", "counter name",  "limit", "value");
Index: df.h
===================================================================
--- df.h	(revision 134522)
+++ df.h	(working copy)
@@ -42,12 +42,13 @@ struct df_link;
    a uniform manner.  The last four problems can be added or deleted
    at any time are always defined (though LIVE is always there at -O2
    or higher); the others are always there.  */
-#define DF_SCAN  0 
-#define DF_LR    1      /* Live Registers backward. */
-#define DF_LIVE  2      /* Live Registers & Uninitialized Registers */
-#define DF_RD    3      /* Reaching Defs. */
-#define DF_CHAIN 4      /* Def-Use and/or Use-Def Chains. */
-#define DF_NOTE  5      /* REG_DEF and REG_UNUSED notes. */
+#define DF_SCAN    0 
+#define DF_LR      1      /* Live Registers backward. */
+#define DF_LIVE    2      /* Live Registers & Uninitialized Registers */
+#define DF_RD      3      /* Reaching Defs. */
+#define DF_CHAIN   4      /* Def-Use and/or Use-Def Chains. */
+#define DF_BYTE_LR 5      /* Subreg tracking lr.  */
+#define DF_NOTE    6      /* REG_DEF and REG_UNUSED notes. */
 
 #define DF_LAST_PROBLEM_PLUS1 (DF_NOTE + 1)
 
@@ -59,6 +60,13 @@ enum df_flow_dir
     DF_BACKWARD
   };
 
+/* Used in the byte scanning to determine if may or must info is to be
+   returned.  */
+enum df_mm
+  {
+    DF_MM_MAY,
+    DF_MM_MUST
+  };
 
 /* 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
@@ -398,6 +406,7 @@ struct df_ref_extract
   struct df_ref ref;
   int width;
   int offset;
+  enum machine_mode mode;
 };
 
 /* These links are used for two purposes:
@@ -573,6 +582,7 @@ struct df
 #define DF_RD_BB_INFO(BB) (df_rd_get_bb_info((BB)->index))
 #define DF_LR_BB_INFO(BB) (df_lr_get_bb_info((BB)->index))
 #define DF_LIVE_BB_INFO(BB) (df_live_get_bb_info((BB)->index))
+#define DF_BYTE_LR_BB_INFO(BB) (df_byte_lr_get_bb_info((BB)->index))
 
 /* Most transformations that wish to use live register analysis will
    use these macros.  This info is the and of the lr and live sets.  */
@@ -585,6 +595,12 @@ struct df
 #define DF_LR_IN(BB) (DF_LR_BB_INFO(BB)->in) 
 #define DF_LR_OUT(BB) (DF_LR_BB_INFO(BB)->out) 
 
+/* These macros are used by passes that are not tolerant of
+   uninitialized variables.  This intolerance should eventually
+   be fixed.  */
+#define DF_BYTE_LR_IN(BB) (DF_BYTE_LR_BB_INFO(BB)->in) 
+#define DF_BYTE_LR_OUT(BB) (DF_BYTE_LR_BB_INFO(BB)->out) 
+
 /* Macros to access the elements within the ref structure.  */
 
 
@@ -619,8 +635,9 @@ struct df
 #define DF_REF_PREV_REG(REF) ((REF)->prev_reg)
 /* The following two macros may only be applied if one of 
    DF_REF_SIGN_EXTRACT | DF_REF_ZERO_EXTRACT is true. */ 
-#define DF_REF_WIDTH(REF) (((struct df_ref_extract *)(REF))->width)
-#define DF_REF_OFFSET(REF) (((struct df_ref_extract *)(REF))->offset)
+#define DF_REF_EXTRACT_WIDTH(REF) (((struct df_ref_extract *)(REF))->width)
+#define DF_REF_EXTRACT_OFFSET(REF) (((struct df_ref_extract *)(REF))->offset)
+#define DF_REF_EXTRACT_MODE(REF) (((struct df_ref_extract *)(REF))->mode)
 /* Macros to determine the reference type.  */
 
 #define DF_REF_REG_DEF_P(REF) (DF_REF_TYPE (REF) == DF_REF_REG_DEF)
@@ -775,16 +792,33 @@ struct df_live_bb_info 
 };
 
 
+/* Live registers, a backwards dataflow problem.  These bitmaps are
+indexed by the df_byte_lr_offset array which is indexed by pseudo.  */
+
+struct df_byte_lr_bb_info 
+{
+  /* Local sets to describe the basic blocks.  */
+  bitmap def;   /* The set of registers set in this block 
+                   - except artificial defs at the top.  */
+  bitmap use;   /* The set of registers used in this block.  */
+
+  /* The results of the dataflow problem.  */
+  bitmap in;    /* Just before the block itself. */
+  bitmap out;   /* At the bottom of the block.  */
+};
+
+
 /* This is used for debugging and for the dumpers to find the latest
    instance so that the df info can be added to the dumps.  This
    should not be used by regular code.  */ 
 extern struct df *df;
-#define df_scan  (df->problems_by_index[DF_SCAN])
-#define df_rd    (df->problems_by_index[DF_RD])
-#define df_lr    (df->problems_by_index[DF_LR])
-#define df_live  (df->problems_by_index[DF_LIVE])
-#define df_chain (df->problems_by_index[DF_CHAIN])
-#define df_note  (df->problems_by_index[DF_NOTE])
+#define df_scan    (df->problems_by_index[DF_SCAN])
+#define df_rd      (df->problems_by_index[DF_RD])
+#define df_lr      (df->problems_by_index[DF_LR])
+#define df_live    (df->problems_by_index[DF_LIVE])
+#define df_chain   (df->problems_by_index[DF_CHAIN])
+#define df_byte_lr (df->problems_by_index[DF_BYTE_LR])
+#define df_note    (df->problems_by_index[DF_NOTE])
 
 /* This symbol turns on checking that each modification of the cfg has
   been identified to the appropriate df routines.  It is not part of
@@ -831,6 +865,7 @@ extern struct df_ref *df_find_use (rtx, 
 extern bool df_reg_used (rtx, rtx);
 extern void df_worklist_dataflow (struct dataflow *,bitmap, int *, int);
 extern void df_print_regset (FILE *file, bitmap r);
+extern void df_print_byte_regset (FILE *file, bitmap r);
 extern void df_dump (FILE *);
 extern void df_dump_region (FILE *);
 extern void df_dump_start (FILE *);
@@ -867,6 +902,13 @@ extern void df_live_verify_transfer_func
 extern void df_live_add_problem (void);
 extern void df_live_set_all_dirty (void);
 extern void df_chain_add_problem (enum df_chain_flags);
+extern void df_byte_lr_add_problem (void);
+extern int df_byte_lr_get_regno_start (unsigned int);
+extern int df_byte_lr_get_regno_len (unsigned int);
+extern void df_byte_lr_simulate_defs (rtx, bitmap);
+extern void df_byte_lr_simulate_uses (rtx, bitmap);
+extern void df_byte_lr_simulate_artificial_refs_at_top (basic_block, bitmap);
+extern void df_byte_lr_simulate_artificial_refs_at_end (basic_block, bitmap);
 extern void df_note_add_problem (void);
 extern void df_simulate_find_defs (rtx, bitmap);
 extern void df_simulate_defs (rtx, bitmap);
@@ -885,7 +927,7 @@ extern void df_grow_insn_info (void);
 extern void df_scan_blocks (void);
 extern struct df_ref *df_ref_create (rtx, rtx *, rtx,basic_block, 
 				     enum df_ref_type, enum df_ref_flags,
-				     int, int);
+				     int, int, enum machine_mode);
 extern void df_ref_remove (struct df_ref *);
 extern struct df_insn_info * df_insn_create_insn_record (rtx);
 extern void df_insn_delete (basic_block, unsigned int);
@@ -911,6 +953,10 @@ extern void df_compute_regs_ever_live (b
 extern bool df_read_modify_subreg_p (rtx);
 extern void df_scan_verify (void);
 
+/* Functions defined in df-byte-scan.c.  */
+extern bool df_compute_accessed_bytes (struct df_ref *, enum df_mm, 
+				       unsigned int *, unsigned int *);
+
 
 /* Get basic block info.  */
 
@@ -950,6 +996,15 @@ df_live_get_bb_info (unsigned int index)
     return NULL;
 }
 
+static inline struct df_byte_lr_bb_info *
+df_byte_lr_get_bb_info (unsigned int index)
+{
+  if (index < df_byte_lr->block_info_size)
+    return (struct df_byte_lr_bb_info *) df_byte_lr->block_info[index];
+  else
+    return NULL;
+}
+
 /* Get the artificial defs for a basic block.  */
 
 static inline struct df_ref **
Index: df-problems.c
===================================================================
--- df-problems.c	(revision 134522)
+++ df-problems.c	(working copy)
@@ -1,5 +1,6 @@
 /* Standard problems for dataflow support routines.
-   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+
    Free Software Foundation, Inc.
    Originally contributed by Michael P. Hayes 
              (m.hayes@elec.canterbury.ac.nz, mhayes@redhat.com)
@@ -566,28 +567,12 @@ df_rd_transfer_function (int bb_index)
 static void
 df_rd_free (void)
 {
-  unsigned int i;
   struct df_rd_problem_data *problem_data
     = (struct df_rd_problem_data *) df_rd->problem_data;
 
   if (problem_data)
     {
-      for (i = 0; i < df_rd->block_info_size; i++)
-	{
-	  struct df_rd_bb_info *bb_info = df_rd_get_bb_info (i);
-	  if (bb_info)
-	    {
-	      BITMAP_FREE (bb_info->kill);
-	      BITMAP_FREE (bb_info->sparse_kill);
-	      BITMAP_FREE (bb_info->gen);
-	      BITMAP_FREE (bb_info->in);
-	      BITMAP_FREE (bb_info->out);
-	    }
-	}
-      
       free_alloc_pool (df_rd->block_pool);
-      BITMAP_FREE (problem_data->sparse_invalidated_by_call);
-      BITMAP_FREE (problem_data->dense_invalidated_by_call);
       bitmap_obstack_release (&problem_data->rd_bitmaps);
       
       df_rd->block_info_size = 0;
@@ -706,7 +691,7 @@ df_rd_add_problem (void)
 
    Find the locations in the function where any use of a pseudo can
    reach in the backwards direction.  In and out bitvectors are built
-   for each basic block.  The regnum is used to index into these sets.
+   for each basic block.  The regno is used to index into these sets.
    See df.h for details.
    ----------------------------------------------------------------------------*/
 
@@ -1878,7 +1863,7 @@ struct df_link *
 df_chain_create (struct df_ref *src, struct df_ref *dst)
 {
   struct df_link *head = DF_REF_CHAIN (src);
-  struct df_link *link = pool_alloc (df_chain->block_pool);;
+  struct df_link *link = pool_alloc (df_chain->block_pool);
   
   DF_REF_CHAIN (src) = link;
   link->next = head;
@@ -2344,7 +2329,733 @@ df_chain_add_problem (enum df_chain_flag
 
 
 /*----------------------------------------------------------------------------
-   This pass computes REG_DEAD and REG_UNUSED notes.
+   BYTE LEVEL LIVE REGISTERS
+
+   Find the locations in the function where any use of a pseudo can
+   reach in the backwards direction.  In and out bitvectors are built
+   for each basic block.  There are two mapping functions,
+   df_byte_lr_get_regno_start and df_byte_lr_get_regno_len that are
+   used to map regnos into bit vector postions.  
+
+   This problem differs from the regular df_lr function in the way
+   that subregs, *_extracts and strict_low_parts are handled. In lr
+   these are consider partial kills, here, the exact set of bytes is
+   modeled.  Note that any reg that has none of these operations is
+   only modeled with a single bit since all operations access the
+   entire register.
+
+   This problem is more brittle that the regular lr.  It currently can
+   be used in dce incrementally, but cannot be used in an environment
+   where insns are created or modified.  The problem is that the
+   mapping of regnos to bitmap positions is relatively compact, in
+   that if a pseudo does not do any of the byte wise operations, only
+   one slot is allocated, rather than a slot for each byte.  If insn
+   are created, where a subreg is used for a reg that had no subregs,
+   the mapping would be wrong.  Likewise, there are no checks to see
+   that new pseudos have been added.  These issues could be addressed
+   by adding a problem specific flag to not use the compact mapping,
+   if there was a need to do so.
+
+   ----------------------------------------------------------------------------*/
+
+/* Private data used to verify the solution for this problem.  */
+struct df_byte_lr_problem_data
+{
+  /* Expanded versions of bitvectors used in lr.  */
+  bitmap invalidated_by_call;
+  bitmap hardware_regs_used;
+
+  /* Indexed by regno, this is true if there are subregs, extracts or
+     strict_low_parts for this regno.  */
+  bitmap needs_expansion;
+
+  /* The start position and len for each regno in the various bit
+     vectors.  */ 
+  unsigned int* regno_start;  
+  unsigned int* regno_len;
+  /* An obstack for the bitmaps we need for this problem.  */
+  bitmap_obstack byte_lr_bitmaps;
+};
+
+
+/* Get the starting location for REGNO in the df_byte_lr bitmaps.  */
+
+int 
+df_byte_lr_get_regno_start (unsigned int regno)
+{
+  struct df_byte_lr_problem_data *problem_data 
+    = (struct df_byte_lr_problem_data *)df_byte_lr->problem_data;;
+  return problem_data->regno_start[regno];
+}
+
+
+/* Get the len for REGNO in the df_byte_lr bitmaps.  */
+
+int 
+df_byte_lr_get_regno_len (unsigned int regno)
+{  
+  struct df_byte_lr_problem_data *problem_data 
+    = (struct df_byte_lr_problem_data *)df_byte_lr->problem_data;;
+  return problem_data->regno_len[regno];
+}
+
+
+/* Set basic block info.  */
+
+static void
+df_byte_lr_set_bb_info (unsigned int index, 
+			struct df_byte_lr_bb_info *bb_info)
+{
+  gcc_assert (df_byte_lr);
+  gcc_assert (index < df_byte_lr->block_info_size);
+  df_byte_lr->block_info[index] = bb_info;
+}
+
+ 
+/* Free basic block info.  */
+
+static void
+df_byte_lr_free_bb_info (basic_block bb ATTRIBUTE_UNUSED, 
+			 void *vbb_info)
+{
+  struct df_byte_lr_bb_info *bb_info = (struct df_byte_lr_bb_info *) vbb_info;
+  if (bb_info)
+    {
+      BITMAP_FREE (bb_info->use);
+      BITMAP_FREE (bb_info->def);
+      BITMAP_FREE (bb_info->in);
+      BITMAP_FREE (bb_info->out);
+      pool_free (df_byte_lr->block_pool, bb_info);
+    }
+}
+
+
+/* Check all of the refs in REF_REC to see if any of them are
+   extracts, subregs or strict_low_parts.  */
+
+static void
+df_byte_lr_check_regs (struct df_ref **ref_rec)
+{
+  struct df_byte_lr_problem_data *problem_data 
+    = (struct df_byte_lr_problem_data *)df_byte_lr->problem_data;
+
+  for (; *ref_rec; ref_rec++)
+    {
+      struct df_ref *ref = *ref_rec;
+      if (DF_REF_FLAGS_IS_SET (ref, DF_REF_SIGN_EXTRACT 
+			       | DF_REF_ZERO_EXTRACT 
+			       | DF_REF_STRICT_LOW_PART)
+	  || GET_CODE (DF_REF_REG (ref)) == SUBREG)
+	bitmap_set_bit (problem_data->needs_expansion, DF_REF_REGNO (ref));
+    }
+}
+
+
+/* Expand bitmap SRC which is indexed by regno to DEST which is indexed by 
+   regno_start and regno_len.  */
+
+static void
+df_byte_lr_expand_bitmap (bitmap dest, bitmap src)
+{
+  struct df_byte_lr_problem_data *problem_data 
+    = (struct df_byte_lr_problem_data *)df_byte_lr->problem_data;
+  bitmap_iterator bi;
+  unsigned int i;
+
+  bitmap_clear (dest);
+  EXECUTE_IF_SET_IN_BITMAP (src, 0, i, bi)
+    {
+      bitmap_set_range (dest, problem_data->regno_start[i], 
+			problem_data->regno_len[i]);
+    }
+}
+
+
+/* Allocate or reset bitmaps for DF_BYTE_LR blocks. The solution bits are
+   not touched unless the block is new.  */
+
+static void 
+df_byte_lr_alloc (bitmap all_blocks ATTRIBUTE_UNUSED)
+{
+  unsigned int bb_index;
+  bitmap_iterator bi;
+  basic_block bb;
+  unsigned int regno;
+  unsigned int index = 0;
+  unsigned int max_reg = max_reg_num();
+  struct df_byte_lr_problem_data *problem_data 
+    = problem_data = XNEW (struct df_byte_lr_problem_data);
+
+  df_byte_lr->problem_data = problem_data;
+
+  if (!df_byte_lr->block_pool)
+    df_byte_lr->block_pool = create_alloc_pool ("df_byte_lr_block pool", 
+					   sizeof (struct df_byte_lr_bb_info), 50);
+
+  df_grow_bb_info (df_byte_lr);
+
+  /* Create the mapping from regnos to slots. This does not change
+     unless the problem is destroyed and recreated.  In particular, if
+     we end up deleting the only insn that used a subreg, we do not
+     want to redo the mapping because this would invalidate everything
+     else.  */
+
+  bitmap_obstack_initialize (&problem_data->byte_lr_bitmaps);
+  problem_data->regno_start = XNEWVEC (unsigned int, max_reg);
+  problem_data->regno_len = XNEWVEC (unsigned int, max_reg);
+  problem_data->hardware_regs_used = BITMAP_ALLOC (&problem_data->byte_lr_bitmaps);
+  problem_data->invalidated_by_call = BITMAP_ALLOC (&problem_data->byte_lr_bitmaps);
+  problem_data->needs_expansion = BITMAP_ALLOC (&problem_data->byte_lr_bitmaps);
+  
+  /* Discover which regno's use subregs, extracts or
+     strict_low_parts.  */
+  FOR_EACH_BB (bb)
+    {
+      rtx insn;
+      FOR_BB_INSNS (bb, insn)
+	{
+	  if (INSN_P (insn))
+	    {
+	      df_byte_lr_check_regs (DF_INSN_DEFS (insn));
+	      df_byte_lr_check_regs (DF_INSN_USES (insn));
+	    }
+	}
+      bitmap_set_bit (df_byte_lr->out_of_date_transfer_functions, bb->index);
+    }
+
+  bitmap_set_bit (df_byte_lr->out_of_date_transfer_functions, ENTRY_BLOCK);
+  bitmap_set_bit (df_byte_lr->out_of_date_transfer_functions, EXIT_BLOCK);
+  
+  /* Allocate the slots for each regno.  */
+  for (regno = 0; regno < max_reg; regno++)
+    {
+      int len;
+      problem_data->regno_start[regno] = index;
+      if (bitmap_bit_p (problem_data->needs_expansion, regno))
+	len = GET_MODE_SIZE (GET_MODE (regno_reg_rtx[regno]));
+      else 
+	len = 1;
+      
+      problem_data->regno_len[regno] = len;
+      index += len;
+    }
+
+  df_byte_lr_expand_bitmap (problem_data->hardware_regs_used, 
+			    df->hardware_regs_used);
+  df_byte_lr_expand_bitmap (problem_data->invalidated_by_call, 
+			    df_invalidated_by_call);
+
+  EXECUTE_IF_SET_IN_BITMAP (df_byte_lr->out_of_date_transfer_functions, 0, bb_index, bi)
+    {
+      struct df_byte_lr_bb_info *bb_info = df_byte_lr_get_bb_info (bb_index);
+      if (bb_info)
+	{ 
+	  bitmap_clear (bb_info->def);
+	  bitmap_clear (bb_info->use);
+	}
+      else
+	{ 
+	  bb_info = (struct df_byte_lr_bb_info *) pool_alloc (df_byte_lr->block_pool);
+	  df_byte_lr_set_bb_info (bb_index, bb_info);
+	  bb_info->use = BITMAP_ALLOC (&problem_data->byte_lr_bitmaps);
+	  bb_info->def = BITMAP_ALLOC (&problem_data->byte_lr_bitmaps);
+	  bb_info->in = BITMAP_ALLOC (&problem_data->byte_lr_bitmaps);
+	  bb_info->out = BITMAP_ALLOC (&problem_data->byte_lr_bitmaps);
+	}
+    }
+  
+  df_byte_lr->optional_p = true;
+}
+
+
+/* Reset the global solution for recalculation.  */
+
+static void 
+df_byte_lr_reset (bitmap all_blocks)
+{
+  unsigned int bb_index;
+  bitmap_iterator bi;
+
+  EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi)
+    {
+      struct df_byte_lr_bb_info *bb_info = df_byte_lr_get_bb_info (bb_index);
+      gcc_assert (bb_info);
+      bitmap_clear (bb_info->in);
+      bitmap_clear (bb_info->out);
+    }
+}
+
+
+/* Compute local live register info for basic block BB.  */
+
+static void
+df_byte_lr_bb_local_compute (unsigned int bb_index)
+{
+  struct df_byte_lr_problem_data *problem_data 
+    = (struct df_byte_lr_problem_data *)df_byte_lr->problem_data;
+  basic_block bb = BASIC_BLOCK (bb_index);
+  struct df_byte_lr_bb_info *bb_info = df_byte_lr_get_bb_info (bb_index);
+  rtx insn;
+  struct df_ref **def_rec;
+  struct df_ref **use_rec;
+
+  /* Process the registers set in an exception handler.  */
+  for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++)
+    {
+      struct df_ref *def = *def_rec;
+      if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0)
+	{
+	  unsigned int dregno = DF_REF_REGNO (def);
+	  unsigned int start = problem_data->regno_start[dregno];
+	  unsigned int len = problem_data->regno_len[dregno];
+	  bitmap_set_range (bb_info->def, start, len);
+	  bitmap_clear_range (bb_info->use, start, len);
+	}
+    }
+
+  /* Process the hardware registers that are always live.  */
+  for (use_rec = df_get_artificial_uses (bb_index); *use_rec; use_rec++)
+    {
+      struct df_ref *use = *use_rec;
+      /* Add use to set of uses in this BB.  */
+      if ((DF_REF_FLAGS (use) & DF_REF_AT_TOP) == 0)
+	{
+	  unsigned int uregno = DF_REF_REGNO (use);
+	  unsigned int start = problem_data->regno_start[uregno];
+	  unsigned int len = problem_data->regno_len[uregno];
+	  bitmap_set_range (bb_info->use, start, len);
+	}
+    }
+
+  FOR_BB_INSNS_REVERSE (bb, insn)
+    {
+      unsigned int uid = INSN_UID (insn);
+
+      if (!INSN_P (insn))
+	continue;	
+
+      for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
+	{
+	  struct df_ref *def = *def_rec;
+	  /* 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_CONDITIONAL)))
+	    {
+	      unsigned int dregno = DF_REF_REGNO (def);
+	      unsigned int start = problem_data->regno_start[dregno];
+	      unsigned int len = problem_data->regno_len[dregno];
+	      unsigned int sb;
+	      unsigned int lb;
+	      if (!df_compute_accessed_bytes (def, DF_MM_MUST, &sb, &lb))
+		{
+		  start += sb;
+		  len = lb - sb;
+		}
+	      if (len)
+		{
+		  bitmap_set_range (bb_info->def, start, len);
+		  bitmap_clear_range (bb_info->use, start, len);
+		}
+	    }
+	}
+
+      for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
+	{
+	  struct df_ref *use = *use_rec;
+	  unsigned int uregno = DF_REF_REGNO (use);
+	  unsigned int start = problem_data->regno_start[uregno];
+	  unsigned int len = problem_data->regno_len[uregno];
+	  unsigned int sb;
+	  unsigned int lb;
+	  if (!df_compute_accessed_bytes (use, DF_MM_MAY, &sb, &lb))
+	    {
+	      start += sb;
+	      len = lb - sb;
+	    }
+	  /* Add use to set of uses in this BB.  */
+	  if (len)
+	    bitmap_set_range (bb_info->use, start, len);
+	}
+    }
+
+  /* Process the registers set in an exception handler or the hard
+     frame pointer if this block is the target of a non local
+     goto.  */
+  for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++)
+    {
+      struct df_ref *def = *def_rec;
+      if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
+	{
+	  unsigned int dregno = DF_REF_REGNO (def);
+	  unsigned int start = problem_data->regno_start[dregno];
+	  unsigned int len = problem_data->regno_len[dregno];
+	  bitmap_set_range (bb_info->def, start, len);
+	  bitmap_clear_range (bb_info->use, start, len);
+	}
+    }
+  
+#ifdef EH_USES
+  /* Process the uses that are live into an exception handler.  */
+  for (use_rec = df_get_artificial_uses (bb_index); *use_rec; use_rec++)
+    {
+      struct df_ref *use = *use_rec;
+      /* Add use to set of uses in this BB.  */
+      if (DF_REF_FLAGS (use) & DF_REF_AT_TOP)
+	{
+	  unsigned int uregno = DF_REF_REGNO (use);
+	  unsigned int start = problem_data->regno_start[uregno];
+	  unsigned int len = problem_data->regno_len[uregno];
+	  bitmap_set_range (bb_info->use, start, len);
+	}
+    }
+#endif
+}
+
+
+/* Compute local live register info for each basic block within BLOCKS.  */
+
+static void
+df_byte_lr_local_compute (bitmap all_blocks ATTRIBUTE_UNUSED)
+{
+  unsigned int bb_index;
+  bitmap_iterator bi;
+
+  EXECUTE_IF_SET_IN_BITMAP (df_byte_lr->out_of_date_transfer_functions, 0, bb_index, bi)
+    {
+      if (bb_index == EXIT_BLOCK)
+	{
+	  /* The exit block is special for this problem and its bits are
+	     computed from thin air.  */
+	  struct df_byte_lr_bb_info *bb_info = df_byte_lr_get_bb_info (EXIT_BLOCK);
+	  df_byte_lr_expand_bitmap (bb_info->use, df->exit_block_uses);
+	}
+      else
+	df_byte_lr_bb_local_compute (bb_index);
+    }
+
+  bitmap_clear (df_byte_lr->out_of_date_transfer_functions);
+}
+
+
+/* Initialize the solution vectors.  */
+
+static void 
+df_byte_lr_init (bitmap all_blocks)
+{
+  unsigned int bb_index;
+  bitmap_iterator bi;
+
+  EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi)
+    {
+      struct df_byte_lr_bb_info *bb_info = df_byte_lr_get_bb_info (bb_index);
+      bitmap_copy (bb_info->in, bb_info->use);
+      bitmap_clear (bb_info->out);
+    }
+}
+
+
+/* Confluence function that processes infinite loops.  This might be a
+   noreturn function that throws.  And even if it isn't, getting the
+   unwind info right helps debugging.  */
+static void
+df_byte_lr_confluence_0 (basic_block bb)
+{
+  struct df_byte_lr_problem_data *problem_data 
+    = (struct df_byte_lr_problem_data *)df_byte_lr->problem_data;
+  bitmap op1 = df_byte_lr_get_bb_info (bb->index)->out;
+  if (bb != EXIT_BLOCK_PTR)
+    bitmap_copy (op1, problem_data->hardware_regs_used);
+} 
+
+
+/* Confluence function that ignores fake edges.  */
+
+static void
+df_byte_lr_confluence_n (edge e)
+{
+  struct df_byte_lr_problem_data *problem_data 
+    = (struct df_byte_lr_problem_data *)df_byte_lr->problem_data;
+  bitmap op1 = df_byte_lr_get_bb_info (e->src->index)->out;
+  bitmap op2 = df_byte_lr_get_bb_info (e->dest->index)->in;
+ 
+  /* Call-clobbered registers die across exception and call edges.  */
+  /* ??? Abnormal call edges ignored for the moment, as this gets
+     confused by sibling call edges, which crashes reg-stack.  */
+  if (e->flags & EDGE_EH)
+    bitmap_ior_and_compl_into (op1, op2, problem_data->invalidated_by_call);
+  else
+    bitmap_ior_into (op1, op2);
+
+  bitmap_ior_into (op1, problem_data->hardware_regs_used);
+} 
+
+
+/* Transfer function.  */
+
+static bool
+df_byte_lr_transfer_function (int bb_index)
+{
+  struct df_byte_lr_bb_info *bb_info = df_byte_lr_get_bb_info (bb_index);
+  bitmap in = bb_info->in;
+  bitmap out = bb_info->out;
+  bitmap use = bb_info->use;
+  bitmap def = bb_info->def;
+
+  return bitmap_ior_and_compl (in, use, out, def);
+}
+
+
+/* Free all storage associated with the problem.  */
+
+static void
+df_byte_lr_free (void)
+{
+  struct df_byte_lr_problem_data *problem_data
+    = (struct df_byte_lr_problem_data *)df_byte_lr->problem_data;
+
+
+  if (df_byte_lr->block_info)
+    {
+      free_alloc_pool (df_byte_lr->block_pool);
+      df_byte_lr->block_info_size = 0;
+      free (df_byte_lr->block_info);
+    }
+
+  BITMAP_FREE (df_byte_lr->out_of_date_transfer_functions);
+  bitmap_obstack_release (&problem_data->byte_lr_bitmaps);
+  free (problem_data->regno_start);
+  free (problem_data->regno_len);
+  free (problem_data);
+  free (df_byte_lr);
+}
+
+
+/* Debugging info at top of bb.  */
+
+static void
+df_byte_lr_top_dump (basic_block bb, FILE *file)
+{
+  struct df_byte_lr_bb_info *bb_info = df_byte_lr_get_bb_info (bb->index);
+  if (!bb_info || !bb_info->in)
+    return;
+      
+  fprintf (file, ";; blr  in  \t");
+  df_print_byte_regset (file, bb_info->in);
+  fprintf (file, ";; blr  use \t");
+  df_print_byte_regset (file, bb_info->use);
+  fprintf (file, ";; blr  def \t");
+  df_print_byte_regset (file, bb_info->def);
+}  
+
+
+/* Debugging info at bottom of bb.  */
+
+static void
+df_byte_lr_bottom_dump (basic_block bb, FILE *file)
+{
+  struct df_byte_lr_bb_info *bb_info = df_byte_lr_get_bb_info (bb->index);
+  if (!bb_info || !bb_info->out)
+    return;
+  
+  fprintf (file, ";; blr  out \t");
+  df_print_byte_regset (file, bb_info->out);
+}  
+
+
+/* All of the information associated with every instance of the problem.  */
+
+static struct df_problem problem_BYTE_LR =
+{
+  DF_BYTE_LR,                      /* Problem id.  */
+  DF_BACKWARD,                     /* Direction.  */
+  df_byte_lr_alloc,                /* Allocate the problem specific data.  */
+  df_byte_lr_reset,                /* Reset global information.  */
+  df_byte_lr_free_bb_info,         /* Free basic block info.  */
+  df_byte_lr_local_compute,        /* Local compute function.  */
+  df_byte_lr_init,                 /* Init the solution specific data.  */
+  df_worklist_dataflow,            /* Worklist solver.  */
+  df_byte_lr_confluence_0,         /* Confluence operator 0.  */ 
+  df_byte_lr_confluence_n,         /* Confluence operator n.  */ 
+  df_byte_lr_transfer_function,    /* Transfer function.  */
+  NULL,                            /* Finalize function.  */
+  df_byte_lr_free,                 /* Free all of the problem information.  */
+  df_byte_lr_free,                 /* Remove this problem from the stack of dataflow problems.  */
+  NULL,                            /* Debugging.  */
+  df_byte_lr_top_dump,             /* Debugging start block.  */
+  df_byte_lr_bottom_dump,          /* Debugging end block.  */
+  NULL,                            /* Incremental solution verify start.  */
+  NULL,                            /* Incremental solution verify end.  */
+  NULL,                            /* Dependent problem.  */
+  TV_DF_BYTE_LR,                   /* Timing variable.  */ 
+  false                            /* Reset blocks on dropping out of blocks_to_analyze.  */
+};
+
+
+/* Create a new DATAFLOW instance and add it to an existing instance
+   of DF.  The returned structure is what is used to get at the
+   solution.  */
+
+void
+df_byte_lr_add_problem (void)
+{
+  df_add_problem (&problem_BYTE_LR);
+  /* These will be initialized when df_scan_blocks processes each
+     block.  */
+  df_byte_lr->out_of_date_transfer_functions = BITMAP_ALLOC (NULL);
+}
+
+
+/* Simulate the effects of the defs of INSN on LIVE.  */
+
+void
+df_byte_lr_simulate_defs (rtx insn, bitmap live)
+{
+  struct df_byte_lr_problem_data *problem_data 
+    = (struct df_byte_lr_problem_data *)df_byte_lr->problem_data;
+  struct df_ref **def_rec;
+  unsigned int uid = INSN_UID (insn);
+
+  for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
+    {
+      struct df_ref *def = *def_rec;
+
+      /* 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_CONDITIONAL))
+	{
+	  unsigned int dregno = DF_REF_REGNO (def);
+	  unsigned int start = problem_data->regno_start[dregno];
+	  unsigned int len = problem_data->regno_len[dregno];
+	  unsigned int sb;
+	  unsigned int lb;
+	  if (!df_compute_accessed_bytes (def, DF_MM_MUST, &sb, &lb))
+	    {
+	      start += sb;
+	      len = lb - sb;
+	    }
+
+	  if (len)
+	    bitmap_clear_range (live, start, len);
+	}
+    }
+}  
+
+
+/* Simulate the effects of the uses of INSN on LIVE.  */
+
+void 
+df_byte_lr_simulate_uses (rtx insn, bitmap live)
+{
+  struct df_byte_lr_problem_data *problem_data 
+    = (struct df_byte_lr_problem_data *)df_byte_lr->problem_data;
+  struct df_ref **use_rec;
+  unsigned int uid = INSN_UID (insn);
+
+  for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
+    {
+      struct df_ref *use = *use_rec;
+      unsigned int uregno = DF_REF_REGNO (use);
+      unsigned int start = problem_data->regno_start[uregno];
+      unsigned int len = problem_data->regno_len[uregno];
+      unsigned int sb;
+      unsigned int lb;
+      
+      if (!df_compute_accessed_bytes (use, DF_MM_MAY, &sb, &lb))
+	{
+	  start += sb;
+	  len = lb - sb;
+	}
+      
+      /* Add use to set of uses in this BB.  */
+      if (len)
+	bitmap_set_range (live, start, len);
+    }
+}
+
+
+/* Apply the artificial uses and defs at the top of BB in a forwards
+   direction.  */
+
+void 
+df_byte_lr_simulate_artificial_refs_at_top (basic_block bb, bitmap live)
+{
+  struct df_byte_lr_problem_data *problem_data 
+    = (struct df_byte_lr_problem_data *)df_byte_lr->problem_data;
+  struct df_ref **def_rec;
+#ifdef EH_USES
+  struct df_ref **use_rec;
+#endif
+  int bb_index = bb->index;
+  
+#ifdef EH_USES
+  for (use_rec = df_get_artificial_uses (bb_index); *use_rec; use_rec++)
+    {
+      struct df_ref *use = *use_rec;
+      if (DF_REF_FLAGS (use) & DF_REF_AT_TOP)
+	{
+	  unsigned int uregno = DF_REF_REGNO (use);
+	  unsigned int start = problem_data->regno_start[uregno];
+	  unsigned int len = problem_data->regno_len[uregno];
+	  bitmap_set_range (live, start, len);
+	}
+    }
+#endif
+
+  for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++)
+    {
+      struct df_ref *def = *def_rec;
+      if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
+	{      
+	  unsigned int dregno = DF_REF_REGNO (def);
+	  unsigned int start = problem_data->regno_start[dregno];
+	  unsigned int len = problem_data->regno_len[dregno];
+	  bitmap_clear_range (live, start, len);
+	}
+    }
+}
+
+
+/* Apply the artificial uses and defs at the end of BB in a backwards
+   direction.  */
+
+void 
+df_byte_lr_simulate_artificial_refs_at_end (basic_block bb, bitmap live)
+{
+  struct df_byte_lr_problem_data *problem_data 
+    = (struct df_byte_lr_problem_data *)df_byte_lr->problem_data;
+  struct df_ref **def_rec;
+  struct df_ref **use_rec;
+  int bb_index = bb->index;
+  
+  for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++)
+    {
+      struct df_ref *def = *def_rec;
+      if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0)
+	{
+	  unsigned int dregno = DF_REF_REGNO (def);
+	  unsigned int start = problem_data->regno_start[dregno];
+	  unsigned int len = problem_data->regno_len[dregno];
+	  bitmap_clear_range (live, start, len);
+	}
+    }
+
+  for (use_rec = df_get_artificial_uses (bb_index); *use_rec; use_rec++)
+    {
+      struct df_ref *use = *use_rec;
+      if ((DF_REF_FLAGS (use) & DF_REF_AT_TOP) == 0)
+	{
+	  unsigned int uregno = DF_REF_REGNO (use);
+	  unsigned int start = problem_data->regno_start[uregno];
+	  unsigned int len = problem_data->regno_len[uregno];
+	  bitmap_set_range (live, start, len);
+	}
+    }
+}
+
+
+
+/*----------------------------------------------------------------------------
+   This problem computes REG_DEAD and REG_UNUSED notes.
    ----------------------------------------------------------------------------*/
 
 static void 
@@ -3053,15 +3764,19 @@ void 
 df_simulate_artificial_refs_at_top (basic_block bb, bitmap live)
 {
   struct df_ref **def_rec;
+#ifdef EH_USES
   struct df_ref **use_rec;
+#endif
   int bb_index = bb->index;
   
+#ifdef EH_USES
   for (use_rec = df_get_artificial_uses (bb_index); *use_rec; use_rec++)
     {
       struct df_ref *use = *use_rec;
       if (DF_REF_FLAGS (use) & DF_REF_AT_TOP)
 	bitmap_set_bit (live, DF_REF_REGNO (use));
     }
+#endif
 
   for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++)
     {
Index: Makefile.in
===================================================================
--- Makefile.in	(revision 134522)
+++ Makefile.in	(working copy)
@@ -797,7 +797,7 @@ IPA_UTILS_H = ipa-utils.h $(TREE_H) $(CG
 IPA_REFERENCE_H = ipa-reference.h bitmap.h $(TREE_H)
 IPA_TYPE_ESCAPE_H = ipa-type-escape.h $(TREE_H)
 CGRAPH_H = cgraph.h $(TREE_H)
-DF_H = df.h bitmap.h $(BASIC_BLOCK_H) alloc-pool.h
+DF_H = df.h bitmap.h $(BASIC_BLOCK_H) alloc-pool.h 
 RESOURCE_H = resource.h hard-reg-set.h $(DF_H)
 DDG_H = ddg.h sbitmap.h $(DF_H)
 GCC_H = gcc.h version.h
@@ -1026,6 +1026,7 @@ OBJS-common = \
 	dce.o \
 	ddg.o \
 	debug.o \
+	df-byte-scan.o \
 	df-core.o \
 	df-problems.o \
 	df-scan.o \
@@ -2617,6 +2618,8 @@ df-scan.o : df-scan.c $(CONFIG_H) $(SYST
    insn-config.h $(RECOG_H) $(FUNCTION_H) $(REGS_H) alloc-pool.h \
    hard-reg-set.h $(BASIC_BLOCK_H) $(DF_H) bitmap.h sbitmap.h $(TM_P_H) \
    $(FLAGS_H) $(TARGET_H) $(TARGET_DEF_H) $(TREE_H) output.h tree-pass.h
+df-byte-scan.o : df-byte-scan.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+   $(DF_H) output.h $(DBGCNT_H)
 regstat.o : regstat.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
    $(TM_P_H) $(FLAGS_H) $(REGS_H) output.h except.h hard-reg-set.h \
    $(BASIC_BLOCK_H) $(TIMEVAR_H) $(DF_H)
@@ -2729,7 +2732,7 @@ global.o : global.c $(CONFIG_H) $(SYSTEM
 ra-conflict.o : ra-conflict.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
    $(FLAGS_H) reload.h $(FUNCTION_H) $(RECOG_H) $(REGS_H) hard-reg-set.h \
    insn-config.h output.h toplev.h $(TM_P_H) $(MACHMODE_H) tree-pass.h \
-   $(TIMEVAR_H) vecprim.h $(DF_H) $(RA_H) sbitmap.h 
+   $(TIMEVAR_H) vecprim.h $(DF_H) $(RA_H) sbitmap.h
 varray.o : varray.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GGC_H) \
    $(HASHTAB_H) $(BCONFIG_H) $(VARRAY_H) toplev.h
 vec.o : vec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h vec.h $(GGC_H) \
@@ -2882,7 +2885,8 @@ hooks.o: hooks.c $(CONFIG_H) $(SYSTEM_H)
 pretty-print.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h intl.h $(PRETTY_PRINT_H) \
    $(TREE_H)
 errors.o : errors.c $(CONFIG_H) $(SYSTEM_H) errors.h $(BCONFIG_H)
-dbgcnt.o: dbgcnt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DBGCNT_H)
+dbgcnt.o: dbgcnt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DBGCNT_H) $(TM_H) \
+   $(RTL_H) output.h
 lower-subreg.o : lower-subreg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
    $(MACHMODE_H) $(TM_H) $(RTL_H) $(TM_P_H) $(TIMEVAR_H) $(FLAGS_H) \
    insn-config.h $(BASIC_BLOCK_H) $(RECOG_H) $(OBSTACK_H) bitmap.h \
Index: passes.c
===================================================================
--- passes.c	(revision 134522)
+++ passes.c	(working copy)
@@ -731,6 +731,7 @@ init_optimization_passes (void)
       NEXT_PASS (pass_partition_blocks);
       NEXT_PASS (pass_regmove);
       NEXT_PASS (pass_split_all_insns);
+      NEXT_PASS (pass_fast_rtl_byte_dce);
       NEXT_PASS (pass_lower_subreg2);
       NEXT_PASS (pass_df_initialize_no_opt);
       NEXT_PASS (pass_stack_ptr_mod);
Index: dce.c
===================================================================
--- dce.c	(revision 134522)
+++ dce.c	(working copy)
@@ -1,5 +1,5 @@
 /* RTL dead code elimination.
-   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -593,17 +593,18 @@ struct rtl_opt_pass pass_ud_rtl_dce =
    Fast DCE functions
    ------------------------------------------------------------------------- */
 
-/* Process basic block BB.  Return true if the live_in set has changed.  */
+/* Process basic block BB.  Return true if the live_in set has
+   changed. REDO_OUT is true if the info at the bottom of the block
+   needs to be recalculated before starting.  AU is the proper set of
+   artificial uses. */
 
 static bool
-dce_process_block (basic_block bb, bool redo_out)
+byte_dce_process_block (basic_block bb, bool redo_out, bitmap au)
 {
   bitmap local_live = BITMAP_ALLOC (&dce_tmp_bitmap_obstack);
-  bitmap au;
   rtx insn;
   bool block_changed;
-  struct df_ref **def_rec, **use_rec;
-  unsigned int bb_index = bb->index;
+  struct df_ref **def_rec;
 
   if (redo_out)
     {
@@ -612,8 +613,8 @@ dce_process_block (basic_block bb, bool 
 	 set.  */
       edge e;
       edge_iterator ei;
-      df_confluence_function_n con_fun_n = df_lr->problem->con_fun_n;
-      bitmap_clear (DF_LR_OUT (bb));
+      df_confluence_function_n con_fun_n = df_byte_lr->problem->con_fun_n;
+      bitmap_clear (DF_BYTE_LR_OUT (bb));
       FOR_EACH_EDGE (e, ei, bb->succs)
 	(*con_fun_n) (e);
     }
@@ -621,35 +622,116 @@ dce_process_block (basic_block bb, bool 
   if (dump_file)
     {
       fprintf (dump_file, "processing block %d live out = ", bb->index);
-      df_print_regset (dump_file, DF_LR_OUT (bb));
+      df_print_byte_regset (dump_file, DF_BYTE_LR_OUT (bb));
     }
 
-  bitmap_copy (local_live, DF_LR_OUT (bb));
+  bitmap_copy (local_live, DF_BYTE_LR_OUT (bb));
+
+  df_byte_lr_simulate_artificial_refs_at_end (bb, local_live);
 
-  /* Process the artificial defs and uses at the bottom of the block.  */
-  for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++)
+  FOR_BB_INSNS_REVERSE (bb, insn)
+    if (INSN_P (insn))
+      {
+	/* The insn is needed if there is someone who uses the output.  */
+	for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
+	  {
+	    struct df_ref *def = *def_rec;
+	    unsigned int last;
+	    unsigned int dregno = DF_REF_REGNO (def);
+	    unsigned int start = df_byte_lr_get_regno_start (dregno);
+	    unsigned int len = df_byte_lr_get_regno_len (dregno);
+
+	    unsigned int sb;
+	    unsigned int lb;
+	    /* This is one of the only places where DF_MM_MAY should
+	       be used for defs.  Need to make sure that we are
+	       checking for all of the bits that may be used.  */
+
+	    if (!df_compute_accessed_bytes (def, DF_MM_MAY, &sb, &lb))
+	      {
+		start += sb;
+		len = lb - sb;
+	      }
+
+	    if (bitmap_bit_p (au, dregno))
+	      {
+		mark_insn (insn, true);
+		goto quickexit;
+	      }
+	    
+	    last = start + len;
+	    while (start < last)
+	      if (bitmap_bit_p (local_live, start++))
+		{
+		  mark_insn (insn, true);
+		  goto quickexit;
+		}
+	  }
+	
+      quickexit: 
+	
+	/* No matter if the instruction is needed or not, we remove
+	   any regno in the defs from the live set.  */
+	df_byte_lr_simulate_defs (insn, local_live);
+
+	/* On the other hand, we do not allow the dead uses to set
+	   anything in local_live.  */
+	if (marked_insn_p (insn))
+	  df_byte_lr_simulate_uses (insn, local_live);
+
+	if (dump_file)
+	  {
+	    fprintf (dump_file, "finished processing insn %d live out = ", 
+		     INSN_UID (insn));
+	    df_print_byte_regset (dump_file, local_live);
+	  }
+      }
+  
+  df_byte_lr_simulate_artificial_refs_at_top (bb, local_live);
+
+  block_changed = !bitmap_equal_p (local_live, DF_BYTE_LR_IN (bb));
+  if (block_changed)
+    bitmap_copy (DF_BYTE_LR_IN (bb), local_live);
+  BITMAP_FREE (local_live);
+  return block_changed;
+}
+
+
+/* Process basic block BB.  Return true if the live_in set has
+   changed. REDO_OUT is true if the info at the bottom of the block
+   needs to be recalculated before starting.  AU is the proper set of
+   artificial uses. */
+
+static bool
+dce_process_block (basic_block bb, bool redo_out, bitmap au)
+{
+  bitmap local_live = BITMAP_ALLOC (&dce_tmp_bitmap_obstack);
+  rtx insn;
+  bool block_changed;
+  struct df_ref **def_rec;
+
+  if (redo_out)
     {
-      struct df_ref *def = *def_rec;
-      if (((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0)
-	  && (!(DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_CONDITIONAL))))
-	bitmap_clear_bit (local_live, DF_REF_REGNO (def));
+      /* Need to redo the live_out set of this block if when one of
+	 the succs of this block has had a change in it live in
+	 set.  */
+      edge e;
+      edge_iterator ei;
+      df_confluence_function_n con_fun_n = df_lr->problem->con_fun_n;
+      bitmap_clear (DF_LR_OUT (bb));
+      FOR_EACH_EDGE (e, ei, bb->succs)
+	(*con_fun_n) (e);
     }
 
-  for (use_rec = df_get_artificial_uses (bb_index); *use_rec; use_rec++)
+  if (dump_file)
     {
-      struct df_ref *use = *use_rec;
-      if ((DF_REF_FLAGS (use) & DF_REF_AT_TOP) == 0)
-	bitmap_set_bit (local_live, DF_REF_REGNO (use));
+      fprintf (dump_file, "processing block %d live out = ", bb->index);
+      df_print_regset (dump_file, DF_LR_OUT (bb));
     }
 
-  /* These regs are considered always live so if they end up dying
-     because of some def, we need to bring the back again.
-     Calling df_simulate_fixup_sets has the disadvantage of calling
-     bb_has_eh_pred once per insn, so we cache the information here.  */
-  if (bb_has_eh_pred (bb))
-    au = df->eh_block_artificial_uses;
-  else
-    au = df->regular_block_artificial_uses;
+  bitmap_copy (local_live, DF_LR_OUT (bb));
+
+  df_simulate_artificial_refs_at_end (bb, local_live);
 
   FOR_BB_INSNS_REVERSE (bb, insn)
     if (INSN_P (insn))
@@ -678,24 +760,7 @@ dce_process_block (basic_block bb, bool 
 	  df_simulate_uses (insn, local_live);
       }
   
-  for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++)
-    {
-      struct df_ref *def = *def_rec;
-      if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP)
-	  && (!(DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_CONDITIONAL))))
-	bitmap_clear_bit (local_live, DF_REF_REGNO (def));
-    }
-
-#ifdef EH_USES
-  /* Process the uses that are live into an exception handler.  */
-  for (use_rec = df_get_artificial_uses (bb_index); *use_rec; use_rec++)
-    {
-      /* Add use to set of uses in this BB.  */
-      struct df_ref *use = *use_rec;
-      if (DF_REF_FLAGS (use) & DF_REF_AT_TOP)
-	bitmap_set_bit (local_live, DF_REF_REGNO (use));
-    }
-#endif
+  df_simulate_artificial_refs_at_top (bb, local_live);
 
   block_changed = !bitmap_equal_p (local_live, DF_LR_IN (bb));
   if (block_changed)
@@ -706,10 +771,12 @@ dce_process_block (basic_block bb, bool 
 }
 
 
-/* Perform fast DCE once initialization is done.  */
+/* Perform fast DCE once initialization is done.  If BYTE_LEVEL is
+   true, use the byte level dce, otherwise do it at the pseudo
+   level.  */
 
 static void
-fast_dce (void)
+fast_dce (bool byte_level)
 {
   int *postorder = df_get_postorder (DF_BACKWARD);
   int n_blocks = df_get_n_blocks (DF_BACKWARD);
@@ -720,6 +787,14 @@ fast_dce (void)
   bitmap redo_out = BITMAP_ALLOC (&dce_blocks_bitmap_obstack);
   bitmap all_blocks = BITMAP_ALLOC (&dce_blocks_bitmap_obstack);
   bool global_changed = true;
+
+  /* These regs are considered always live so if they end up dying
+     because of some def, we need to bring the back again.  Calling
+     df_simulate_fixup_sets has the disadvantage of calling
+     bb_has_eh_pred once per insn, so we cache the information
+     here.  */
+  bitmap au = df->regular_block_artificial_uses;
+  bitmap au_eh = df->eh_block_artificial_uses;
   int i;
 
   prescan_insns_for_dce (true);
@@ -743,8 +818,14 @@ fast_dce (void)
 	      continue;
 	    }
 
-	  local_changed 
-	    = dce_process_block (bb, bitmap_bit_p (redo_out, index));
+	  if (byte_level)
+	    local_changed 
+	      = byte_dce_process_block (bb, bitmap_bit_p (redo_out, index),
+					  bb_has_eh_pred (bb) ? au_eh : au);
+	  else
+	    local_changed 
+	      = dce_process_block (bb, bitmap_bit_p (redo_out, index),
+				   bb_has_eh_pred (bb) ? au_eh : au);
 	  bitmap_set_bit (processed, index);
 	  
 	  if (local_changed)
@@ -780,7 +861,10 @@ fast_dce (void)
 	     to redo the dataflow equations for the blocks that had a
 	     change at the top of the block.  Then we need to redo the
 	     iteration.  */ 
-	  df_analyze_problem (df_lr, all_blocks, postorder, n_blocks);
+	  if (byte_level)
+	    df_analyze_problem (df_byte_lr, all_blocks, postorder, n_blocks);
+	  else
+	    df_analyze_problem (df_lr, all_blocks, postorder, n_blocks);
 
 	  if (old_flag & DF_LR_RUN_DCE)
 	    df_set_flags (DF_LR_RUN_DCE);
@@ -797,13 +881,26 @@ fast_dce (void)
 }
 
 
-/* Fast DCE.  */
+/* Fast register level DCE.  */
 
 static unsigned int
 rest_of_handle_fast_dce (void)
 {
   init_dce (true);
-  fast_dce ();
+  fast_dce (false);
+  fini_dce (true);
+  return 0;
+}
+
+
+/* Fast byte level DCE.  */
+
+static unsigned int
+rest_of_handle_fast_byte_dce (void)
+{
+  df_byte_lr_add_problem ();
+  init_dce (true);
+  fast_dce (true);
   fini_dce (true);
   return 0;
 }
@@ -875,3 +972,24 @@ struct rtl_opt_pass pass_fast_rtl_dce =
   TODO_ggc_collect                      /* todo_flags_finish */
  }
 };
+
+struct rtl_opt_pass pass_fast_rtl_byte_dce =
+{
+ {
+  RTL_PASS,
+  "byte-dce",                           /* name */
+  gate_fast_dce,                        /* gate */
+  rest_of_handle_fast_byte_dce,         /* execute */
+  NULL,                                 /* sub */
+  NULL,                                 /* next */
+  0,                                    /* static_pass_number */
+  TV_DCE,                               /* tv_id */
+  0,                                    /* properties_required */
+  0,                                    /* properties_provided */
+  0,                                    /* properties_destroyed */
+  0,                                    /* todo_flags_start */
+  TODO_dump_func |
+  TODO_df_finish | TODO_verify_rtl_sharing |
+  TODO_ggc_collect                      /* todo_flags_finish */
+ }
+};

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