public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [trunk] first of three patches to get rid of no conflict blocks.
@ 2008-03-04 20:53 Kenneth Zadeck
  2008-03-04 20:57 ` Kenneth Zadeck
  0 siblings, 1 reply; 4+ messages in thread
From: Kenneth Zadeck @ 2008-03-04 20:53 UTC (permalink / raw)
  To: gcc-patches, Ian Lance Taylor, Park, Seongbae, Bonzini, Paolo,
	Steven Bosscher, Richard Sandiford

This is the first of either two or three patches to get rid of no
conflict blocks. 
The problem with using the current implementation of df for this is that
the current implementation does not keep the parameters for ZERO_EXTRACT
or SIGN_EXTRACT if one of these wraps a subreg.  So in order to recover
this info, you would of had to rescan the insn.

Most of this patch deals with df-scan.  The idea here is there that if a
ZERO_EXTRACT or SIGN_EXTRACT wraps a subreg, then new flags are added to
the df_ref and two new fields are added to the df_ref to support the
width and the offset information in these wrappers. 

To do this without blowing a lot of space, i simply use an extension of
the df_ref called df_ref_extract to support the two fields when they are
necessary. 

I would like at least one of the rtl experts to review this patch more
carefully than a normal review.  Scanning rtl is not my forte, i fell
kind of like the person in those old airplane movies that is called to
cockpit after both pilots have been killed.   I know that pulling the
stick back makes the plane go up, but there sure are a lot of buttons
and switches there. 

The next patch will use the information in ra-conflict to properly
account for partial register use and hopefully make the noconflict
blocks unnecessary.   It will utilize the offset and width fields from
the extract wrappers.

I have tested this patch on several platforms and it causes no problems,
but since nothing is using this information, this is a pretty weak test.  

Thanks,

Kenny


2008-03-04  Kenneth Zadeck <zadeck@naturalbridge.com>

    * fwprop.c (update_df): Support width and offset parameters of
    df_ref_create.
    * ra-conflict.c (mark_reg_store, clear_reg_in_live,
    global_conflicts): Change DF_REF_EXTRACT to either
    DF_REF_ZERO_EXTRACT or DF_REF_SIGN_EXTRACT.  Change
    DF_REF_STRICT_LOWER_PART to DF_REF_STRICT_LOW_PART.
    * df-scan.c (df_ref_record, df_defs_record,
    df_ref_create_structure, df_def_record_1, 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): Support new width and offset fields.
    (ref_extract_pool): New storage pool.
    (df_free_ref): New function.
    (df_reg_chain_unlink, df_free_collection_rec,
    df_sort_and_compress_refs): Call df_free_ref.
    (df_ref_equal_p, df_ref_compare): Compare offset and width fields
    of df_ref_extract.
    (df_ref_create_structure): Allocate df_ref_extract if offset and
    width fields are used.
    (df_def_record_1): Get offset and width from ZERO_EXTRACT.
    (df_uses_record): Get offset and width from ZERO_EXTRACT
    and SIGN_EXTRACT.
    * global.c (build_insn_chain): Change DF_REF_EXTRACT to either
    DF_REF_ZERO_EXTRACT or DF_REF_SIGN_EXTRACT.  Change
    DF_REF_STRICT_LOWER_PART to DF_REF_STRICT_LOW_PART.
    * df.h (df_ref_flags): Change DF_REF_EXTRACT to either
    DF_REF_ZERO_EXTRACT or DF_REF_SIGN_EXTRACT.  Change
    DF_REF_STRICT_LOWER_PART to DF_REF_STRICT_LOW_PART.
    (df_ref_extract): New structure.
    (DF_REF_WIDTH, DF_REF_OFFSET): New macros.
    (df_ref_create): Add width and offset parameters.
    

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [trunk] first of three patches to get rid of no conflict blocks.
  2008-03-04 20:53 [trunk] first of three patches to get rid of no conflict blocks Kenneth Zadeck
@ 2008-03-04 20:57 ` Kenneth Zadeck
  2008-03-05 21:24   ` Ian Lance Taylor
  0 siblings, 1 reply; 4+ messages in thread
From: Kenneth Zadeck @ 2008-03-04 20:57 UTC (permalink / raw)
  To: Kenneth Zadeck
  Cc: gcc-patches, Ian Lance Taylor, Park, Seongbae, Bonzini, Paolo,
	Steven Bosscher, Richard Sandiford

[-- Attachment #1: Type: text/plain, Size: 3387 bytes --]

enopatch

Kenneth Zadeck wrote:
> This is the first of either two or three patches to get rid of no
> conflict blocks. 
> The problem with using the current implementation of df for this is that
> the current implementation does not keep the parameters for ZERO_EXTRACT
> or SIGN_EXTRACT if one of these wraps a subreg.  So in order to recover
> this info, you would of had to rescan the insn.
>
> Most of this patch deals with df-scan.  The idea here is there that if a
> ZERO_EXTRACT or SIGN_EXTRACT wraps a subreg, then new flags are added to
> the df_ref and two new fields are added to the df_ref to support the
> width and the offset information in these wrappers. 
>
> To do this without blowing a lot of space, i simply use an extension of
> the df_ref called df_ref_extract to support the two fields when they are
> necessary. 
>
> I would like at least one of the rtl experts to review this patch more
> carefully than a normal review.  Scanning rtl is not my forte, i fell
> kind of like the person in those old airplane movies that is called to
> cockpit after both pilots have been killed.   I know that pulling the
> stick back makes the plane go up, but there sure are a lot of buttons
> and switches there. 
>
> The next patch will use the information in ra-conflict to properly
> account for partial register use and hopefully make the noconflict
> blocks unnecessary.   It will utilize the offset and width fields from
> the extract wrappers.
>
> I have tested this patch on several platforms and it causes no problems,
> but since nothing is using this information, this is a pretty weak test.  
>
> Thanks,
>
> Kenny
>
>
> 2008-03-04  Kenneth Zadeck <zadeck@naturalbridge.com>
>
>     * fwprop.c (update_df): Support width and offset parameters of
>     df_ref_create.
>     * ra-conflict.c (mark_reg_store, clear_reg_in_live,
>     global_conflicts): Change DF_REF_EXTRACT to either
>     DF_REF_ZERO_EXTRACT or DF_REF_SIGN_EXTRACT.  Change
>     DF_REF_STRICT_LOWER_PART to DF_REF_STRICT_LOW_PART.
>     * df-scan.c (df_ref_record, df_defs_record,
>     df_ref_create_structure, df_def_record_1, 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): Support new width and offset fields.
>     (ref_extract_pool): New storage pool.
>     (df_free_ref): New function.
>     (df_reg_chain_unlink, df_free_collection_rec,
>     df_sort_and_compress_refs): Call df_free_ref.
>     (df_ref_equal_p, df_ref_compare): Compare offset and width fields
>     of df_ref_extract.
>     (df_ref_create_structure): Allocate df_ref_extract if offset and
>     width fields are used.
>     (df_def_record_1): Get offset and width from ZERO_EXTRACT.
>     (df_uses_record): Get offset and width from ZERO_EXTRACT
>     and SIGN_EXTRACT.
>     * global.c (build_insn_chain): Change DF_REF_EXTRACT to either
>     DF_REF_ZERO_EXTRACT or DF_REF_SIGN_EXTRACT.  Change
>     DF_REF_STRICT_LOWER_PART to DF_REF_STRICT_LOW_PART.
>     * df.h (df_ref_flags): Change DF_REF_EXTRACT to either
>     DF_REF_ZERO_EXTRACT or DF_REF_SIGN_EXTRACT.  Change
>     DF_REF_STRICT_LOWER_PART to DF_REF_STRICT_LOW_PART.
>     (df_ref_extract): New structure.
>     (DF_REF_WIDTH, DF_REF_OFFSET): New macros.
>     (df_ref_create): Add width and offset parameters.
>     
>
>
>   


[-- Attachment #2: extract1.diff --]
[-- Type: text/x-patch, Size: 33618 bytes --]

Index: fwprop.c
===================================================================
--- fwprop.c	(revision 132860)
+++ fwprop.c	(working copy)
@@ -642,17 +642,25 @@ update_df (rtx insn, rtx *loc, struct df
     {
       struct df_ref *use = *use_rec;
       struct df_ref *orig_use = use, *new_use;
+      int width = -1;
+      int offset = -1;
       rtx *new_loc = find_occurrence (loc, DF_REF_REG (orig_use));
       use_rec++;
 
       if (!new_loc)
 	continue;
 
+      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);
+	}
+
       /* 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);
+			       type, DF_REF_FLAGS (orig_use) | new_flags, width, offset);
 
       /* Set up the use-def chain.  */
       df_chain_copy (new_use, DF_REF_CHAIN (orig_use));
Index: ra-conflict.c
===================================================================
--- ra-conflict.c	(revision 132860)
+++ ra-conflict.c	(working copy)
@@ -297,7 +297,7 @@ mark_reg_store (sparseset allocnos_live,
     {
       unsigned int start = regno;
       unsigned int last = end_hard_regno (mode, regno);
-      if ((GET_CODE (reg) == SUBREG) && !DF_REF_FLAGS_IS_SET (ref, DF_REF_EXTRACT))
+      if ((GET_CODE (reg) == SUBREG) && !DF_REF_FLAGS_IS_SET (ref, DF_REF_ZERO_EXTRACT))
 	{
 	  start += subreg_regno_offset (regno, GET_MODE (SUBREG_REG (reg)),
 					SUBREG_BYTE (reg), GET_MODE (reg));
@@ -457,7 +457,7 @@ clear_reg_in_live (sparseset allocnos_li
   if (allocnum >= 0)
     {
       if (GET_CODE (reg) == SUBREG
-	  && !DF_REF_FLAGS_IS_SET (def, DF_REF_EXTRACT))
+	  && !DF_REF_FLAGS_IS_SET (def, DF_REF_ZERO_EXTRACT))
 	{
 	  unsigned int start = SUBREG_BYTE (reg);
 	  unsigned int last = start + GET_MODE_SIZE (GET_MODE (reg));
@@ -465,7 +465,7 @@ clear_reg_in_live (sparseset allocnos_li
 	  ra_init_live_subregs (sparseset_bit_p (allocnos_live, allocnum), 
 				live_subregs, live_subregs_used, allocnum, reg);
 
-	  if (!DF_REF_FLAGS_IS_SET (def, DF_REF_STRICT_LOWER_PART))
+	  if (!DF_REF_FLAGS_IS_SET (def, DF_REF_STRICT_LOW_PART))
 	    {
 	      /* Expand the range to cover entire words.
 		 Bytes added here are "don't care".  */
@@ -511,7 +511,7 @@ clear_reg_in_live (sparseset allocnos_li
     {
       unsigned int start = regno;
       if (GET_CODE (reg) == SUBREG
-	  && !DF_REF_FLAGS_IS_SET (def, DF_REF_EXTRACT))
+	  && !DF_REF_FLAGS_IS_SET (def, DF_REF_ZERO_EXTRACT))
 	{
 	  unsigned int last;
 	  start += SUBREG_BYTE (reg);
@@ -864,7 +864,7 @@ global_conflicts (void)
 		  rtx reg = DF_REF_REG (def);
 		  set_reg_in_live (allocnos_live, live_subregs, live_subregs_used, 
 				   &hard_regs_live, reg, 
-				   DF_REF_FLAGS_IS_SET (def, DF_REF_EXTRACT));
+				   DF_REF_FLAGS_IS_SET (def, DF_REF_ZERO_EXTRACT));
 		  if (dump_file)
 		    dump_ref (dump_file, "  adding def", "\n",
 			      reg, DF_REF_REGNO (def), live_subregs, live_subregs_used);
@@ -946,7 +946,7 @@ global_conflicts (void)
 		 use unless that set also happens to wrapped in a
 		 ZERO_EXTRACT. */
 	      if (DF_REF_FLAGS_IS_SET (use, DF_REF_READ_WRITE) 
-		  && (!DF_REF_FLAGS_IS_SET (use, DF_REF_EXTRACT)) 
+		  && (!DF_REF_FLAGS_IS_SET (use, DF_REF_ZERO_EXTRACT)) 
 		  && DF_REF_FLAGS_IS_SET (use, DF_REF_SUBREG))
 		continue;
 	      
@@ -957,7 +957,7 @@ global_conflicts (void)
 	      if (allocnum >= 0)
 		{
 		  if (GET_CODE (reg) == SUBREG
-		      && !DF_REF_FLAGS_IS_SET (use, DF_REF_EXTRACT)) 
+		      && !DF_REF_FLAGS_IS_SET (use, DF_REF_ZERO_EXTRACT)) 
 		    {
 		      unsigned int start = SUBREG_BYTE (reg);
 		      unsigned int last = start + GET_MODE_SIZE (GET_MODE (reg));
Index: df-scan.c
===================================================================
--- df-scan.c	(revision 132860)
+++ 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);
+			   enum df_ref_flags, int, int);
 static void df_def_record_1 (struct df_collection_rec *,
 			     rtx, basic_block, rtx,
 			     enum df_ref_flags);
@@ -104,11 +104,11 @@ 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);
+			    basic_block, rtx, enum df_ref_flags, int, int);
 
 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);
+					       enum df_ref_flags, int, int);
 
 static void df_insn_refs_collect (struct df_collection_rec*, 
 				  basic_block, rtx); 
@@ -160,6 +160,7 @@ static bool regs_ever_live[FIRST_PSEUDO_
 struct df_scan_problem_data
 {
   alloc_pool ref_pool;
+  alloc_pool ref_extract_pool;
   alloc_pool insn_pool;
   alloc_pool reg_pool;
   alloc_pool mw_reg_pool;
@@ -214,6 +215,7 @@ df_scan_free_internal (void)
 
   free_alloc_pool (df_scan->block_pool);
   free_alloc_pool (problem_data->ref_pool);
+  free_alloc_pool (problem_data->ref_extract_pool);
   free_alloc_pool (problem_data->insn_pool);
   free_alloc_pool (problem_data->reg_pool);
   free_alloc_pool (problem_data->mw_reg_pool);
@@ -296,6 +298,9 @@ df_scan_alloc (bitmap all_blocks ATTRIBU
   problem_data->ref_pool 
     = create_alloc_pool ("df_scan_ref pool", 
 			 sizeof (struct df_ref), block_size);
+  problem_data->ref_extract_pool 
+    = create_alloc_pool ("df_scan_ref extract pool", 
+			 sizeof (struct df_ref_extract), block_size);
   problem_data->insn_pool 
     = create_alloc_pool ("df_scan_insn pool", 
 			 sizeof (struct df_insn_info), block_size);
@@ -608,13 +613,19 @@ df_scan_blocks (void)
 
 
 /* Create a new ref of type DF_REF_TYPE for register REG at address
-   LOC within INSN of BB.  */
+   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.  */
 
 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)
+	       enum df_ref_flags ref_flags,
+	       int width, int offset)
 {
   struct df_ref *ref;
   struct df_reg_info **reg_info;
@@ -629,7 +640,7 @@ 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);
+                                 ref_type, ref_flags, width, offset);
 
   if (DF_REF_TYPE (ref) == DF_REF_REG_DEF)
     {
@@ -727,6 +738,18 @@ df_ref_create (rtx reg, rtx *loc, rtx in
    UTILITIES TO CREATE AND DESTROY REFS AND CHAINS.
 ----------------------------------------------------------------------------*/
 
+static void
+df_free_ref (struct df_ref *ref)
+{
+  struct df_scan_problem_data *problem_data
+    = (struct df_scan_problem_data *) df_scan->problem_data;
+
+  if (DF_REF_FLAGS_IS_SET (ref, DF_REF_SIGN_EXTRACT | DF_REF_ZERO_EXTRACT))
+    pool_free (problem_data->ref_extract_pool, (struct df_ref_extract *)ref);
+  else
+    pool_free (problem_data->ref_pool, ref);
+}
+
 
 /* Unlink and delete REF at the reg_use, reg_eq_use or reg_def chain.
    Also delete the def-use or use-def chain if it exists.  */
@@ -736,8 +759,6 @@ df_reg_chain_unlink (struct df_ref *ref)
 {
   struct df_ref *next = DF_REF_NEXT_REG (ref);  
   struct df_ref *prev = DF_REF_PREV_REG (ref);
-  struct df_scan_problem_data *problem_data
-    = (struct df_scan_problem_data *) df_scan->problem_data;
   int id = DF_REF_ID (ref);
   struct df_reg_info *reg_info;
   struct df_ref **refs = NULL;
@@ -808,7 +829,7 @@ df_reg_chain_unlink (struct df_ref *ref)
   if (next)
     DF_REF_PREV_REG (next) = prev;
 
-  pool_free (problem_data->ref_pool, ref);
+  df_free_ref (ref);
 }
 
 
@@ -1058,13 +1079,13 @@ df_free_collection_rec (struct df_collec
 
   if (collection_rec->def_vec)
     for (ref = collection_rec->def_vec; *ref; ref++)
-      pool_free (problem_data->ref_pool, *ref);
+      df_free_ref (*ref);
   if (collection_rec->use_vec)
     for (ref = collection_rec->use_vec; *ref; ref++)
-      pool_free (problem_data->ref_pool, *ref);
+      df_free_ref (*ref);
   if (collection_rec->eq_use_vec)
     for (ref = collection_rec->eq_use_vec; *ref; ref++)
-      pool_free (problem_data->ref_pool, *ref);
+      df_free_ref (*ref);
   if (collection_rec->mw_vec)
     for (mw = collection_rec->mw_vec; *mw; mw++)
       pool_free (problem_data->mw_reg_pool, *mw);
@@ -2045,7 +2066,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);
+			      bb, insn, DF_REF_IN_NOTE, -1, -1);
 	    default:
 	      break;
 	    }
@@ -2115,6 +2136,13 @@ df_ref_equal_p (struct df_ref *ref1, str
 {
   if (!ref2)
     return false;
+
+  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))))
+    return false;
+
   return (ref1 == ref2) ||
     (DF_REF_REG (ref1) == DF_REF_REG (ref2)
      && DF_REF_REGNO (ref1) == DF_REF_REGNO (ref2)
@@ -2163,6 +2191,16 @@ df_ref_compare (const void *r1, const vo
       else
 	return 1;
     }
+
+  /* The flags are the same at this point so it is safe to only look
+     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);
+    }
   return 0;
 }
 
@@ -2179,8 +2217,6 @@ df_swap_refs (struct df_ref **ref_vec, i
 static unsigned int
 df_sort_and_compress_refs (struct df_ref **ref_vec, unsigned int count)
 {
-  struct df_scan_problem_data *problem_data 
-    = (struct df_scan_problem_data *) df_scan->problem_data;
   unsigned int i;
   unsigned int dist = 0;
 
@@ -2215,7 +2251,7 @@ df_sort_and_compress_refs (struct df_ref
       /* Find the next ref that is not equal to the current ref.  */
       while (df_ref_equal_p (ref_vec[i], ref_vec[i + dist + 1]))
 	{
-	  pool_free (problem_data->ref_pool, ref_vec[i + dist + 1]);
+	  df_free_ref (ref_vec[i + dist + 1]);
 	  dist++;
 	}
       /* Copy it down to the next position.  */
@@ -2541,21 +2577,34 @@ df_refs_add_to_chains (struct df_collect
 }
 
 
-/* Allocate a ref and initialize its fields. */
+/* 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
+   if they were constants.  Otherwise they should be -1 if those flags
+   were set.  */
 
 static struct df_ref *
 df_ref_create_structure (struct df_collection_rec *collection_rec,
 			 rtx reg, rtx *loc, 
 			 basic_block bb, rtx insn, 
 			 enum df_ref_type ref_type, 
-			 enum df_ref_flags ref_flags)
+			 enum df_ref_flags ref_flags,
+			 int width, int offset)
 {
   struct df_ref *this_ref;
   int regno = REGNO (GET_CODE (reg) == SUBREG ? SUBREG_REG (reg) : reg);
   struct df_scan_problem_data *problem_data
     = (struct df_scan_problem_data *) df_scan->problem_data;
 
-  this_ref = pool_alloc (problem_data->ref_pool);
+  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;
+    }
+  else
+    this_ref = pool_alloc (problem_data->ref_pool);
   DF_REF_ID (this_ref) = -1;
   DF_REF_REG (this_ref) = reg;
   DF_REF_REGNO (this_ref) =  regno;
@@ -2604,14 +2653,21 @@ df_ref_create_structure (struct df_colle
 
 
 /* Create new references of type DF_REF_TYPE for each part of register REG
-   at address LOC within INSN of BB.  */
+   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.  */
+
 
 static void
 df_ref_record (struct df_collection_rec *collection_rec,
                rtx reg, rtx *loc, 
 	       basic_block bb, rtx insn, 
 	       enum df_ref_type ref_type, 
-	       enum df_ref_flags ref_flags) 
+	       enum df_ref_flags ref_flags,
+	       int width, int offset) 
 {
   unsigned int regno;
 
@@ -2660,7 +2716,7 @@ 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);
+					 bb, insn, ref_type, ref_flags, width, offset);
 
           gcc_assert (ORIGINAL_REGNO (DF_REF_REG (ref)) == i);
 	}
@@ -2669,7 +2725,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);
+                                     ref_type, ref_flags, width, offset);
     }
 }
 
@@ -2703,6 +2759,8 @@ df_def_record_1 (struct df_collection_re
 {
   rtx *loc;
   rtx dst;
+  int offset = -1;
+  int width = -1;
 
  /* We may recursively call ourselves on EXPR_LIST when dealing with PARALLEL
      construct.  */
@@ -2730,16 +2788,24 @@ df_def_record_1 (struct df_collection_re
       return;
     }
 
-  /* Maybe, we should flag the use of STRICT_LOW_PART somehow.  It might
-     be handy for the reg allocator.  */
-  while (GET_CODE (dst) == STRICT_LOW_PART
-	 || GET_CODE (dst) == ZERO_EXTRACT)
-    {
-      flags |= DF_REF_READ_WRITE | DF_REF_PARTIAL;
-      if (GET_CODE (dst) == ZERO_EXTRACT)
-	flags |= DF_REF_EXTRACT;
-      else
-	flags |= DF_REF_STRICT_LOWER_PART;
+  if (GET_CODE (dst) == STRICT_LOW_PART)
+    {
+      flags |= DF_REF_READ_WRITE | DF_REF_PARTIAL | DF_REF_STRICT_LOW_PART;
+
+      loc = &XEXP (dst, 0);
+      dst = *loc;
+    }
+
+  if (GET_CODE (dst) == ZERO_EXTRACT)
+    {
+      flags |= DF_REF_READ_WRITE | DF_REF_PARTIAL | DF_REF_ZERO_EXTRACT;
+      
+      if (GET_CODE (XEXP (dst, 1)) == CONST_INT
+	  && GET_CODE (XEXP (dst, 2)) == CONST_INT)
+	{
+	  width = INTVAL (XEXP (dst, 1));
+	  offset = INTVAL (XEXP (dst, 2));
+	}
 
       loc = &XEXP (dst, 0);
       dst = *loc;
@@ -2749,13 +2815,13 @@ 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);
+		     dst, loc, bb, insn, DF_REF_REG_DEF, flags, width, offset);
 
       /* 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);
+		       dst, NULL, bb, insn, DF_REF_REG_USE, flags, width, offset);
     }
   else if (GET_CODE (dst) == SUBREG && REG_P (SUBREG_REG (dst)))
     {
@@ -2765,7 +2831,7 @@ 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);
+		     dst, loc, bb, insn, DF_REF_REG_DEF, flags, width, offset);
     }
 }
 
@@ -2801,12 +2867,18 @@ df_defs_record (struct df_collection_rec
 }
 
 
-/* Process all the registers used in the rtx at address LOC.  */
+/* 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.  */
 
 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)
+		basic_block bb, rtx insn, enum df_ref_flags flags,
+		int width, int offset)
 {
   RTX_CODE code;
   rtx x;
@@ -2837,7 +2909,7 @@ 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);
+			DF_REF_REG_MEM_STORE, bb, insn, flags, width, offset);
 
       /* If we're clobbering a REG then we have a def so ignore.  */
       return;
@@ -2845,7 +2917,7 @@ 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);
+		      bb, insn, flags & DF_REF_IN_NOTE, width, offset);
       return;
 
     case SUBREG:
@@ -2855,22 +2927,46 @@ 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);
+	  df_uses_record (collection_rec, loc, ref_type, bb, insn, flags, width, offset);
 	  return;
 	}
       /* ... Fall through ...  */
 
     case REG:
       df_ref_record (collection_rec, 
-		     x, loc, bb, insn, ref_type, flags);
+		     x, loc, bb, insn, ref_type, flags, width, offset);
       return;
 
+    case SIGN_EXTRACT:
+    case ZERO_EXTRACT:
+      {
+	/* If the parameters to the zero or sign extract are
+	   constants, strip them off and recurse, otherwise there is
+	   no information that we can gain from this operation.  */
+	if (GET_CODE (XEXP (x, 1)) == CONST_INT
+	    && GET_CODE (XEXP (x, 2)) == CONST_INT)
+	  {
+	    width = INTVAL (XEXP (x, 1));
+	    offset = INTVAL (XEXP (x, 2));
+
+	    if (code == ZERO_EXTRACT)
+	      flags |= DF_REF_ZERO_EXTRACT;
+	    else
+	      flags |= DF_REF_SIGN_EXTRACT;
+
+	    df_uses_record (collection_rec,
+			    &XEXP (x, 0), ref_type, bb, insn, flags, width, offset);
+	    return;
+	  }
+      }
+      break;
+
     case SET:
       {
 	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);
+			&SET_SRC (x), DF_REF_REG_USE, bb, insn, flags, width, offset);
 
 	switch (GET_CODE (dst))
 	  {
@@ -2879,7 +2975,7 @@ 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);
+				  flags | DF_REF_READ_WRITE | DF_REF_SUBREG, width, offset);
 		  break;
 		}
 	      /* Fall through.  */
@@ -2891,7 +2987,7 @@ 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);
+			      DF_REF_REG_MEM_STORE, bb, insn, flags, width, offset);
 	      break;
 	    case STRICT_LOW_PART:
 	      {
@@ -2902,20 +2998,31 @@ 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_LOWER_PART);
+				DF_REF_READ_WRITE | DF_REF_STRICT_LOW_PART, width, offset);
 	      }
 	      break;
 	    case ZERO_EXTRACT:
-	    case SIGN_EXTRACT:
-	      df_uses_record (collection_rec, &XEXP (dst, 0), 
-			      DF_REF_REG_USE, bb, insn, 
-			      DF_REF_READ_WRITE | DF_REF_EXTRACT);
-	      df_uses_record (collection_rec, &XEXP (dst, 1), 
-			      DF_REF_REG_USE, bb, insn, flags);
-	      df_uses_record (collection_rec, &XEXP (dst, 2), 
-			      DF_REF_REG_USE, bb, insn, flags);
-	      dst = XEXP (dst, 0);
+	      {
+		if (GET_CODE (XEXP (dst, 1)) == CONST_INT
+		    && GET_CODE (XEXP (dst, 2)) == CONST_INT)
+		  {
+		    width = INTVAL (XEXP (dst, 1));
+		    offset = INTVAL (XEXP (dst, 2));
+		  }
+		else 
+		  {
+		    df_uses_record (collection_rec, &XEXP (dst, 1), 
+				    DF_REF_REG_USE, bb, insn, flags, width, offset);
+		    df_uses_record (collection_rec, &XEXP (dst, 2), 
+				    DF_REF_REG_USE, bb, insn, flags, width, offset);
+		  }
+
+		df_uses_record (collection_rec, &XEXP (dst, 0), 
+				DF_REF_REG_USE, bb, insn, 
+				DF_REF_READ_WRITE | DF_REF_ZERO_EXTRACT, width, offset);
+	      }
 	      break;
+
 	    default:
 	      gcc_unreachable ();
 	  }
@@ -2962,7 +3069,7 @@ 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);
+			      DF_REF_REG_USE, bb, insn, flags, width, offset);
 	    return;
 	  }
 	break;
@@ -2977,7 +3084,7 @@ 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);
+                     flags | DF_REF_READ_WRITE | DF_REF_PRE_POST_MODIFY, width, offset);
 
       /* ... Fall through to handle uses ...  */
 
@@ -3000,14 +3107,16 @@ df_uses_record (struct df_collection_rec
 		loc = &XEXP (x, 0);
 		goto retry;
 	      }
-	    df_uses_record (collection_rec, &XEXP (x, i), ref_type, bb, insn, flags);
+	    df_uses_record (collection_rec, &XEXP (x, i), ref_type, 
+			    bb, insn, flags, width, offset);
 	  }
 	else if (fmt[i] == 'E')
 	  {
 	    int j;
 	    for (j = 0; j < XVECLEN (x, i); j++)
 	      df_uses_record (collection_rec,
-			      &XVECEXP (x, i, j), ref_type, bb, insn, flags);
+			      &XVECEXP (x, i, j), ref_type, 
+			      bb, insn, flags, width, offset);
 	  }
       }
   }
@@ -3027,11 +3136,21 @@ df_get_conditional_uses (struct df_colle
       struct df_ref *ref = collection_rec->def_vec[i];
       if (DF_REF_FLAGS_IS_SET (ref, DF_REF_CONDITIONAL))
         {
-          struct df_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);
+	  int width = -1;
+	  int offset = -1;
+          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);
+	    }
+
+          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);
           DF_REF_REGNO (use) = DF_REF_REGNO (ref);
         }
     }
@@ -3069,7 +3188,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);
+			DF_REF_REG_USE, bb, insn, flags, -1, -1);
       else if (GET_CODE (XEXP (note, 0)) == CLOBBER)
 	{
 	  if (REG_P (XEXP (XEXP (note, 0), 0)))
@@ -3081,13 +3200,13 @@ df_get_call_refs (struct df_collection_r
 	    }
 	  else
 	    df_uses_record (collection_rec, &XEXP (note, 0),
-		            DF_REF_REG_USE, bb, insn, flags);
+		            DF_REF_REG_USE, bb, insn, flags, -1, -1);
 	}
     }
 
   /* 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);
+		 NULL, bb, insn, DF_REF_REG_USE, DF_REF_CALL_STACK_USAGE | flags, -1, -1);
 
   /* Calls may also reference any of the global registers,
      so they are recorded as used.  */
@@ -3095,9 +3214,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);
+		       NULL, bb, insn, DF_REF_REG_USE, flags, -1, -1);
 	df_ref_record (collection_rec, regno_reg_rtx[i],
-		       NULL, bb, insn, DF_REF_REG_DEF, flags);
+		       NULL, bb, insn, DF_REF_REG_DEF, flags, -1, -1);
       }
 
   is_sibling_call = SIBLING_CALL_P (insn);
@@ -3110,7 +3229,7 @@ df_get_call_refs (struct df_collection_r
 	      || refers_to_regno_p (ui, ui+1, 
 				    current_function_return_rtx, NULL)))
         df_ref_record (collection_rec, regno_reg_rtx[ui], 
-		       NULL, bb, insn, DF_REF_REG_DEF, DF_REF_MAY_CLOBBER | flags);
+		       NULL, bb, insn, DF_REF_REG_DEF, DF_REF_MAY_CLOBBER | flags, -1, -1);
     }
 
   BITMAP_FREE (defs_generated);
@@ -3148,7 +3267,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);
+                          bb, insn, DF_REF_IN_NOTE, -1, -1);
           break;
         case REG_NON_LOCAL_GOTO:
           /* The frame ptr is used by a non-local goto.  */
@@ -3156,13 +3275,13 @@ df_insn_refs_collect (struct df_collecti
                          regno_reg_rtx[FRAME_POINTER_REGNUM],
                          NULL,
                          bb, insn, 
-                         DF_REF_REG_USE, 0);
+                         DF_REF_REG_USE, 0, -1, -1);
 #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);
+                         DF_REF_REG_USE, 0, -1, -1);
 #endif
           break;
         default:
@@ -3176,7 +3295,7 @@ 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);
+		  &PATTERN (insn), DF_REF_REG_USE, bb, insn, 0, -1, -1);
 
   /* DF_REF_CONDITIONAL needs corresponding USES. */
   if (is_cond_exec)
@@ -3259,7 +3378,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);
+			 bb, NULL, DF_REF_REG_DEF, DF_REF_AT_TOP, -1, -1);
 	}
     }
 #endif
@@ -3283,7 +3402,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);
+			 bb, NULL, DF_REF_REG_USE, DF_REF_AT_TOP, -1, -1);
     }
 #endif
 
@@ -3291,7 +3410,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);
+		   bb, NULL, DF_REF_REG_DEF, DF_REF_AT_TOP, -1, -1);
  
   /* Add the artificial uses.  */
   if (bb->index >= NUM_FIXED_BLOCKS)
@@ -3305,7 +3424,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);
+			 bb, NULL, DF_REF_REG_USE, 0, -1, -1);
 	}
     }
 
@@ -3598,7 +3717,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);
+		     ENTRY_BLOCK_PTR, NULL, DF_REF_REG_DEF, 0, -1, -1);
     }
 
   df_canonize_collection_rec (collection_rec);
@@ -3759,7 +3878,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);
+		   EXIT_BLOCK_PTR, NULL, DF_REF_REG_USE, 0, -1, -1);
 
 #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
   /* It is deliberate that this is not put in the exit block uses but
@@ -3769,7 +3888,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);
+		   EXIT_BLOCK_PTR, NULL, DF_REF_REG_USE, 0, -1, -1);
 #endif
 
   df_canonize_collection_rec (collection_rec);
Index: global.c
===================================================================
--- global.c	(revision 132860)
+++ global.c	(working copy)
@@ -1490,7 +1490,7 @@ build_insn_chain (void)
 			/* We can model subregs, but not if they are
 			   wrapped in ZERO_EXTRACTS.  */
 			if (GET_CODE (reg) == SUBREG
-			    && !DF_REF_FLAGS_IS_SET (def, DF_REF_EXTRACT))
+			    && !DF_REF_FLAGS_IS_SET (def, DF_REF_ZERO_EXTRACT))
 			  {
 			    unsigned int start = SUBREG_BYTE (reg);
 			    unsigned int last = start 
@@ -1503,7 +1503,7 @@ build_insn_chain (void)
 						  regno, reg);
 
 			    if (!DF_REF_FLAGS_IS_SET
-				(def, DF_REF_STRICT_LOWER_PART))
+				(def, DF_REF_STRICT_LOW_PART))
 			      {
 				/* Expand the range to cover entire words.
 				   Bytes added here are "don't care".  */
@@ -1566,7 +1566,7 @@ build_insn_chain (void)
 		       precisely so we do not need to look at the
 		       fabricated use. */
 		    if (DF_REF_FLAGS_IS_SET (use, DF_REF_READ_WRITE) 
-			&& !DF_REF_FLAGS_IS_SET (use, DF_REF_EXTRACT) 
+			&& !DF_REF_FLAGS_IS_SET (use, DF_REF_ZERO_EXTRACT) 
 			&& DF_REF_FLAGS_IS_SET (use, DF_REF_SUBREG))
 		      continue;
 		    
@@ -1585,7 +1585,7 @@ build_insn_chain (void)
 		    if (regno < FIRST_PSEUDO_REGISTER || reg_renumber[regno] >= 0)
 		      {
 			if (GET_CODE (reg) == SUBREG
-			    && !DF_REF_FLAGS_IS_SET (use, DF_REF_EXTRACT)) 
+			    && !DF_REF_FLAGS_IS_SET (use, DF_REF_ZERO_EXTRACT)) 
 			  {
 			    unsigned int start = SUBREG_BYTE (reg);
 			    unsigned int last = start 
Index: df.h
===================================================================
--- df.h	(revision 132860)
+++ df.h	(working copy)
@@ -117,14 +117,18 @@ enum df_ref_flags
     DF_REF_MUST_CLOBBER = 1 << 7,
 
 
-    /* This flag is set if this ref is inside a pre/post modify.  */
-    DF_REF_PRE_POST_MODIFY = 1 << 8,
+    /* If the ref has one of the following two flags set, then the
+       struct df_ref can be cast to struct df_ref_extract to access
+       the width and offset fields.  */
+ 
+    /* This flag is set if the ref contains a SIGN_EXTRACT.  */
+    DF_REF_SIGN_EXTRACT = 1 << 8,
 
-    /* This flag is set if the ref contains a ZERO_EXTRACT or SIGN_EXTRACT.  */
-    DF_REF_EXTRACT = 1 << 9,
+    /* This flag is set if the ref contains a ZERO_EXTRACT.  */
+    DF_REF_ZERO_EXTRACT = 1 << 9,
 
-    /* This flag is set if the ref contains a STRICT_LOWER_PART.  */
-    DF_REF_STRICT_LOWER_PART = 1 << 10,
+    /* This flag is set if the ref contains a STRICT_LOW_PART.  */
+    DF_REF_STRICT_LOW_PART = 1 << 10,
 
     /* This flag is set if the ref contains a SUBREG.  */
     DF_REF_SUBREG = 1 << 11,
@@ -138,7 +142,11 @@ enum df_ref_flags
     DF_REF_CALL_STACK_USAGE = 1 << 13,
 
     /* This flag is used for verification of existing refs. */
-    DF_REF_REG_MARKER = 1 << 14
+    DF_REF_REG_MARKER = 1 << 14,
+
+    /* This flag is set if this ref is inside a pre/post modify.  */
+    DF_REF_PRE_POST_MODIFY = 1 << 15
+
   };
 
 /* The possible ordering of refs within the df_ref_info.  */
@@ -381,6 +389,17 @@ struct df_ref
   struct df_ref *prev_reg;     /* Prev ref with same regno and type.  */
 };
 
+/* A df_ref_extract is just a df_ref with a width and offset field at
+   the end of it.  It is used to hold this information if the ref was
+   wrapped by a SIGN_EXTRACT or a ZERO_EXTRACT and to pass this info
+   to passes that wish to process partial regs precisely.  */
+struct df_ref_extract
+{
+  struct df_ref ref;
+  int width;
+  int offset;
+};
+
 /* These links are used for two purposes:
    1) def-use or use-def chains. 
    2) Multiword hard registers that underly a single hardware register.  */
@@ -598,7 +617,10 @@ struct df
 #define DF_REF_IS_REG_MARKED(REF) (DF_REF_FLAGS_IS_SET ((REF),DF_REF_REG_MARKER))
 #define DF_REF_NEXT_REG(REF) ((REF)->next_reg)
 #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)
 /* Macros to determine the reference type.  */
 
 #define DF_REF_REG_DEF_P(REF) (DF_REF_TYPE (REF) == DF_REF_REG_DEF)
@@ -862,7 +884,8 @@ extern void df_grow_reg_info (void);
 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);
+				     enum df_ref_type, enum df_ref_flags,
+				     int, int);
 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);

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [trunk] first of three patches to get rid of no conflict blocks.
  2008-03-04 20:57 ` Kenneth Zadeck
@ 2008-03-05 21:24   ` Ian Lance Taylor
  2008-03-06  0:31     ` Kenneth Zadeck
  0 siblings, 1 reply; 4+ messages in thread
From: Ian Lance Taylor @ 2008-03-05 21:24 UTC (permalink / raw)
  To: Kenneth Zadeck
  Cc: gcc-patches, Park, Seongbae, Bonzini, Paolo, Steven Bosscher,
	Richard Sandiford

Kenneth Zadeck <zadeck@naturalbridge.com> writes:

> 2008-03-04  Kenneth Zadeck <zadeck@naturalbridge.com>
>
>     * fwprop.c (update_df): Support width and offset parameters of
>     df_ref_create.
>     * ra-conflict.c (mark_reg_store, clear_reg_in_live,
>     global_conflicts): Change DF_REF_EXTRACT to either
>     DF_REF_ZERO_EXTRACT or DF_REF_SIGN_EXTRACT.  Change
>     DF_REF_STRICT_LOWER_PART to DF_REF_STRICT_LOW_PART.
>     * df-scan.c (df_ref_record, df_defs_record,
>     df_ref_create_structure, df_def_record_1, 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): Support new width and offset fields.
>     (ref_extract_pool): New storage pool.
>     (df_free_ref): New function.
>     (df_reg_chain_unlink, df_free_collection_rec,
>     df_sort_and_compress_refs): Call df_free_ref.
>     (df_ref_equal_p, df_ref_compare): Compare offset and width fields
>     of df_ref_extract.
>     (df_ref_create_structure): Allocate df_ref_extract if offset and
>     width fields are used.
>     (df_def_record_1): Get offset and width from ZERO_EXTRACT.
>     (df_uses_record): Get offset and width from ZERO_EXTRACT
>     and SIGN_EXTRACT.
>     * global.c (build_insn_chain): Change DF_REF_EXTRACT to either
>     DF_REF_ZERO_EXTRACT or DF_REF_SIGN_EXTRACT.  Change
>     DF_REF_STRICT_LOWER_PART to DF_REF_STRICT_LOW_PART.
>     * df.h (df_ref_flags): Change DF_REF_EXTRACT to either
>     DF_REF_ZERO_EXTRACT or DF_REF_SIGN_EXTRACT.  Change
>     DF_REF_STRICT_LOWER_PART to DF_REF_STRICT_LOW_PART.
>     (df_ref_extract): New structure.
>     (DF_REF_WIDTH, DF_REF_OFFSET): New macros.
>     (df_ref_create): Add width and offset parameters.

This looks OK to me.

Thanks.

Ian

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [trunk] first of three patches to get rid of no conflict blocks.
  2008-03-05 21:24   ` Ian Lance Taylor
@ 2008-03-06  0:31     ` Kenneth Zadeck
  0 siblings, 0 replies; 4+ messages in thread
From: Kenneth Zadeck @ 2008-03-06  0:31 UTC (permalink / raw)
  To: Ian Lance Taylor
  Cc: gcc-patches, Park, Seongbae, Bonzini, Paolo, Steven Bosscher,
	Richard Sandiford

[-- Attachment #1: Type: text/plain, Size: 2089 bytes --]

Ian Lance Taylor wrote:
> Kenneth Zadeck <zadeck@naturalbridge.com> writes:
>
>   
>> 2008-03-04  Kenneth Zadeck <zadeck@naturalbridge.com>
>>
>>     * fwprop.c (update_df): Support width and offset parameters of
>>     df_ref_create.
>>     * ra-conflict.c (mark_reg_store, clear_reg_in_live,
>>     global_conflicts): Change DF_REF_EXTRACT to either
>>     DF_REF_ZERO_EXTRACT or DF_REF_SIGN_EXTRACT.  Change
>>     DF_REF_STRICT_LOWER_PART to DF_REF_STRICT_LOW_PART.
>>     * df-scan.c (df_ref_record, df_defs_record,
>>     df_ref_create_structure, df_def_record_1, 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): Support new width and offset fields.
>>     (ref_extract_pool): New storage pool.
>>     (df_free_ref): New function.
>>     (df_reg_chain_unlink, df_free_collection_rec,
>>     df_sort_and_compress_refs): Call df_free_ref.
>>     (df_ref_equal_p, df_ref_compare): Compare offset and width fields
>>     of df_ref_extract.
>>     (df_ref_create_structure): Allocate df_ref_extract if offset and
>>     width fields are used.
>>     (df_def_record_1): Get offset and width from ZERO_EXTRACT.
>>     (df_uses_record): Get offset and width from ZERO_EXTRACT
>>     and SIGN_EXTRACT.
>>     * global.c (build_insn_chain): Change DF_REF_EXTRACT to either
>>     DF_REF_ZERO_EXTRACT or DF_REF_SIGN_EXTRACT.  Change
>>     DF_REF_STRICT_LOWER_PART to DF_REF_STRICT_LOW_PART.
>>     * df.h (df_ref_flags): Change DF_REF_EXTRACT to either
>>     DF_REF_ZERO_EXTRACT or DF_REF_SIGN_EXTRACT.  Change
>>     DF_REF_STRICT_LOWER_PART to DF_REF_STRICT_LOW_PART.
>>     (df_ref_extract): New structure.
>>     (DF_REF_WIDTH, DF_REF_OFFSET): New macros.
>>     (df_ref_create): Add width and offset parameters.
>>     
>
> This looks OK to me.
>
> Thanks.
>
> Ian
>   
The only difference between what i checked in and your approval was frag
4 of global.c to look for both DF_REF_SIGN_EXTRACT and DF_REF_ZERO_EXTRACT.

Committed as revision 132962

kenny

[-- Attachment #2: extract2.diff --]
[-- Type: text/x-patch, Size: 33652 bytes --]

Index: fwprop.c
===================================================================
--- fwprop.c	(revision 132860)
+++ fwprop.c	(working copy)
@@ -642,17 +642,25 @@ update_df (rtx insn, rtx *loc, struct df
     {
       struct df_ref *use = *use_rec;
       struct df_ref *orig_use = use, *new_use;
+      int width = -1;
+      int offset = -1;
       rtx *new_loc = find_occurrence (loc, DF_REF_REG (orig_use));
       use_rec++;
 
       if (!new_loc)
 	continue;
 
+      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);
+	}
+
       /* 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);
+			       type, DF_REF_FLAGS (orig_use) | new_flags, width, offset);
 
       /* Set up the use-def chain.  */
       df_chain_copy (new_use, DF_REF_CHAIN (orig_use));
Index: ra-conflict.c
===================================================================
--- ra-conflict.c	(revision 132860)
+++ ra-conflict.c	(working copy)
@@ -297,7 +297,7 @@ mark_reg_store (sparseset allocnos_live,
     {
       unsigned int start = regno;
       unsigned int last = end_hard_regno (mode, regno);
-      if ((GET_CODE (reg) == SUBREG) && !DF_REF_FLAGS_IS_SET (ref, DF_REF_EXTRACT))
+      if ((GET_CODE (reg) == SUBREG) && !DF_REF_FLAGS_IS_SET (ref, DF_REF_ZERO_EXTRACT))
 	{
 	  start += subreg_regno_offset (regno, GET_MODE (SUBREG_REG (reg)),
 					SUBREG_BYTE (reg), GET_MODE (reg));
@@ -457,7 +457,7 @@ clear_reg_in_live (sparseset allocnos_li
   if (allocnum >= 0)
     {
       if (GET_CODE (reg) == SUBREG
-	  && !DF_REF_FLAGS_IS_SET (def, DF_REF_EXTRACT))
+	  && !DF_REF_FLAGS_IS_SET (def, DF_REF_ZERO_EXTRACT))
 	{
 	  unsigned int start = SUBREG_BYTE (reg);
 	  unsigned int last = start + GET_MODE_SIZE (GET_MODE (reg));
@@ -465,7 +465,7 @@ clear_reg_in_live (sparseset allocnos_li
 	  ra_init_live_subregs (sparseset_bit_p (allocnos_live, allocnum), 
 				live_subregs, live_subregs_used, allocnum, reg);
 
-	  if (!DF_REF_FLAGS_IS_SET (def, DF_REF_STRICT_LOWER_PART))
+	  if (!DF_REF_FLAGS_IS_SET (def, DF_REF_STRICT_LOW_PART))
 	    {
 	      /* Expand the range to cover entire words.
 		 Bytes added here are "don't care".  */
@@ -511,7 +511,7 @@ clear_reg_in_live (sparseset allocnos_li
     {
       unsigned int start = regno;
       if (GET_CODE (reg) == SUBREG
-	  && !DF_REF_FLAGS_IS_SET (def, DF_REF_EXTRACT))
+	  && !DF_REF_FLAGS_IS_SET (def, DF_REF_ZERO_EXTRACT))
 	{
 	  unsigned int last;
 	  start += SUBREG_BYTE (reg);
@@ -864,7 +864,7 @@ global_conflicts (void)
 		  rtx reg = DF_REF_REG (def);
 		  set_reg_in_live (allocnos_live, live_subregs, live_subregs_used, 
 				   &hard_regs_live, reg, 
-				   DF_REF_FLAGS_IS_SET (def, DF_REF_EXTRACT));
+				   DF_REF_FLAGS_IS_SET (def, DF_REF_ZERO_EXTRACT));
 		  if (dump_file)
 		    dump_ref (dump_file, "  adding def", "\n",
 			      reg, DF_REF_REGNO (def), live_subregs, live_subregs_used);
@@ -946,7 +946,7 @@ global_conflicts (void)
 		 use unless that set also happens to wrapped in a
 		 ZERO_EXTRACT. */
 	      if (DF_REF_FLAGS_IS_SET (use, DF_REF_READ_WRITE) 
-		  && (!DF_REF_FLAGS_IS_SET (use, DF_REF_EXTRACT)) 
+		  && (!DF_REF_FLAGS_IS_SET (use, DF_REF_ZERO_EXTRACT)) 
 		  && DF_REF_FLAGS_IS_SET (use, DF_REF_SUBREG))
 		continue;
 	      
@@ -957,7 +957,7 @@ global_conflicts (void)
 	      if (allocnum >= 0)
 		{
 		  if (GET_CODE (reg) == SUBREG
-		      && !DF_REF_FLAGS_IS_SET (use, DF_REF_EXTRACT)) 
+		      && !DF_REF_FLAGS_IS_SET (use, DF_REF_ZERO_EXTRACT)) 
 		    {
 		      unsigned int start = SUBREG_BYTE (reg);
 		      unsigned int last = start + GET_MODE_SIZE (GET_MODE (reg));
Index: df-scan.c
===================================================================
--- df-scan.c	(revision 132860)
+++ 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);
+			   enum df_ref_flags, int, int);
 static void df_def_record_1 (struct df_collection_rec *,
 			     rtx, basic_block, rtx,
 			     enum df_ref_flags);
@@ -104,11 +104,11 @@ 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);
+			    basic_block, rtx, enum df_ref_flags, int, int);
 
 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);
+					       enum df_ref_flags, int, int);
 
 static void df_insn_refs_collect (struct df_collection_rec*, 
 				  basic_block, rtx); 
@@ -160,6 +160,7 @@ static bool regs_ever_live[FIRST_PSEUDO_
 struct df_scan_problem_data
 {
   alloc_pool ref_pool;
+  alloc_pool ref_extract_pool;
   alloc_pool insn_pool;
   alloc_pool reg_pool;
   alloc_pool mw_reg_pool;
@@ -214,6 +215,7 @@ df_scan_free_internal (void)
 
   free_alloc_pool (df_scan->block_pool);
   free_alloc_pool (problem_data->ref_pool);
+  free_alloc_pool (problem_data->ref_extract_pool);
   free_alloc_pool (problem_data->insn_pool);
   free_alloc_pool (problem_data->reg_pool);
   free_alloc_pool (problem_data->mw_reg_pool);
@@ -296,6 +298,9 @@ df_scan_alloc (bitmap all_blocks ATTRIBU
   problem_data->ref_pool 
     = create_alloc_pool ("df_scan_ref pool", 
 			 sizeof (struct df_ref), block_size);
+  problem_data->ref_extract_pool 
+    = create_alloc_pool ("df_scan_ref extract pool", 
+			 sizeof (struct df_ref_extract), block_size);
   problem_data->insn_pool 
     = create_alloc_pool ("df_scan_insn pool", 
 			 sizeof (struct df_insn_info), block_size);
@@ -608,13 +613,19 @@ df_scan_blocks (void)
 
 
 /* Create a new ref of type DF_REF_TYPE for register REG at address
-   LOC within INSN of BB.  */
+   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.  */
 
 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)
+	       enum df_ref_flags ref_flags,
+	       int width, int offset)
 {
   struct df_ref *ref;
   struct df_reg_info **reg_info;
@@ -629,7 +640,7 @@ 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);
+                                 ref_type, ref_flags, width, offset);
 
   if (DF_REF_TYPE (ref) == DF_REF_REG_DEF)
     {
@@ -727,6 +738,18 @@ df_ref_create (rtx reg, rtx *loc, rtx in
    UTILITIES TO CREATE AND DESTROY REFS AND CHAINS.
 ----------------------------------------------------------------------------*/
 
+static void
+df_free_ref (struct df_ref *ref)
+{
+  struct df_scan_problem_data *problem_data
+    = (struct df_scan_problem_data *) df_scan->problem_data;
+
+  if (DF_REF_FLAGS_IS_SET (ref, DF_REF_SIGN_EXTRACT | DF_REF_ZERO_EXTRACT))
+    pool_free (problem_data->ref_extract_pool, (struct df_ref_extract *)ref);
+  else
+    pool_free (problem_data->ref_pool, ref);
+}
+
 
 /* Unlink and delete REF at the reg_use, reg_eq_use or reg_def chain.
    Also delete the def-use or use-def chain if it exists.  */
@@ -736,8 +759,6 @@ df_reg_chain_unlink (struct df_ref *ref)
 {
   struct df_ref *next = DF_REF_NEXT_REG (ref);  
   struct df_ref *prev = DF_REF_PREV_REG (ref);
-  struct df_scan_problem_data *problem_data
-    = (struct df_scan_problem_data *) df_scan->problem_data;
   int id = DF_REF_ID (ref);
   struct df_reg_info *reg_info;
   struct df_ref **refs = NULL;
@@ -808,7 +829,7 @@ df_reg_chain_unlink (struct df_ref *ref)
   if (next)
     DF_REF_PREV_REG (next) = prev;
 
-  pool_free (problem_data->ref_pool, ref);
+  df_free_ref (ref);
 }
 
 
@@ -1058,13 +1079,13 @@ df_free_collection_rec (struct df_collec
 
   if (collection_rec->def_vec)
     for (ref = collection_rec->def_vec; *ref; ref++)
-      pool_free (problem_data->ref_pool, *ref);
+      df_free_ref (*ref);
   if (collection_rec->use_vec)
     for (ref = collection_rec->use_vec; *ref; ref++)
-      pool_free (problem_data->ref_pool, *ref);
+      df_free_ref (*ref);
   if (collection_rec->eq_use_vec)
     for (ref = collection_rec->eq_use_vec; *ref; ref++)
-      pool_free (problem_data->ref_pool, *ref);
+      df_free_ref (*ref);
   if (collection_rec->mw_vec)
     for (mw = collection_rec->mw_vec; *mw; mw++)
       pool_free (problem_data->mw_reg_pool, *mw);
@@ -2045,7 +2066,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);
+			      bb, insn, DF_REF_IN_NOTE, -1, -1);
 	    default:
 	      break;
 	    }
@@ -2115,6 +2136,13 @@ df_ref_equal_p (struct df_ref *ref1, str
 {
   if (!ref2)
     return false;
+
+  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))))
+    return false;
+
   return (ref1 == ref2) ||
     (DF_REF_REG (ref1) == DF_REF_REG (ref2)
      && DF_REF_REGNO (ref1) == DF_REF_REGNO (ref2)
@@ -2163,6 +2191,16 @@ df_ref_compare (const void *r1, const vo
       else
 	return 1;
     }
+
+  /* The flags are the same at this point so it is safe to only look
+     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);
+    }
   return 0;
 }
 
@@ -2179,8 +2217,6 @@ df_swap_refs (struct df_ref **ref_vec, i
 static unsigned int
 df_sort_and_compress_refs (struct df_ref **ref_vec, unsigned int count)
 {
-  struct df_scan_problem_data *problem_data 
-    = (struct df_scan_problem_data *) df_scan->problem_data;
   unsigned int i;
   unsigned int dist = 0;
 
@@ -2215,7 +2251,7 @@ df_sort_and_compress_refs (struct df_ref
       /* Find the next ref that is not equal to the current ref.  */
       while (df_ref_equal_p (ref_vec[i], ref_vec[i + dist + 1]))
 	{
-	  pool_free (problem_data->ref_pool, ref_vec[i + dist + 1]);
+	  df_free_ref (ref_vec[i + dist + 1]);
 	  dist++;
 	}
       /* Copy it down to the next position.  */
@@ -2541,21 +2577,34 @@ df_refs_add_to_chains (struct df_collect
 }
 
 
-/* Allocate a ref and initialize its fields. */
+/* 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
+   if they were constants.  Otherwise they should be -1 if those flags
+   were set.  */
 
 static struct df_ref *
 df_ref_create_structure (struct df_collection_rec *collection_rec,
 			 rtx reg, rtx *loc, 
 			 basic_block bb, rtx insn, 
 			 enum df_ref_type ref_type, 
-			 enum df_ref_flags ref_flags)
+			 enum df_ref_flags ref_flags,
+			 int width, int offset)
 {
   struct df_ref *this_ref;
   int regno = REGNO (GET_CODE (reg) == SUBREG ? SUBREG_REG (reg) : reg);
   struct df_scan_problem_data *problem_data
     = (struct df_scan_problem_data *) df_scan->problem_data;
 
-  this_ref = pool_alloc (problem_data->ref_pool);
+  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;
+    }
+  else
+    this_ref = pool_alloc (problem_data->ref_pool);
   DF_REF_ID (this_ref) = -1;
   DF_REF_REG (this_ref) = reg;
   DF_REF_REGNO (this_ref) =  regno;
@@ -2604,14 +2653,21 @@ df_ref_create_structure (struct df_colle
 
 
 /* Create new references of type DF_REF_TYPE for each part of register REG
-   at address LOC within INSN of BB.  */
+   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.  */
+
 
 static void
 df_ref_record (struct df_collection_rec *collection_rec,
                rtx reg, rtx *loc, 
 	       basic_block bb, rtx insn, 
 	       enum df_ref_type ref_type, 
-	       enum df_ref_flags ref_flags) 
+	       enum df_ref_flags ref_flags,
+	       int width, int offset) 
 {
   unsigned int regno;
 
@@ -2660,7 +2716,7 @@ 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);
+					 bb, insn, ref_type, ref_flags, width, offset);
 
           gcc_assert (ORIGINAL_REGNO (DF_REF_REG (ref)) == i);
 	}
@@ -2669,7 +2725,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);
+                                     ref_type, ref_flags, width, offset);
     }
 }
 
@@ -2703,6 +2759,8 @@ df_def_record_1 (struct df_collection_re
 {
   rtx *loc;
   rtx dst;
+  int offset = -1;
+  int width = -1;
 
  /* We may recursively call ourselves on EXPR_LIST when dealing with PARALLEL
      construct.  */
@@ -2730,16 +2788,24 @@ df_def_record_1 (struct df_collection_re
       return;
     }
 
-  /* Maybe, we should flag the use of STRICT_LOW_PART somehow.  It might
-     be handy for the reg allocator.  */
-  while (GET_CODE (dst) == STRICT_LOW_PART
-	 || GET_CODE (dst) == ZERO_EXTRACT)
-    {
-      flags |= DF_REF_READ_WRITE | DF_REF_PARTIAL;
-      if (GET_CODE (dst) == ZERO_EXTRACT)
-	flags |= DF_REF_EXTRACT;
-      else
-	flags |= DF_REF_STRICT_LOWER_PART;
+  if (GET_CODE (dst) == STRICT_LOW_PART)
+    {
+      flags |= DF_REF_READ_WRITE | DF_REF_PARTIAL | DF_REF_STRICT_LOW_PART;
+
+      loc = &XEXP (dst, 0);
+      dst = *loc;
+    }
+
+  if (GET_CODE (dst) == ZERO_EXTRACT)
+    {
+      flags |= DF_REF_READ_WRITE | DF_REF_PARTIAL | DF_REF_ZERO_EXTRACT;
+      
+      if (GET_CODE (XEXP (dst, 1)) == CONST_INT
+	  && GET_CODE (XEXP (dst, 2)) == CONST_INT)
+	{
+	  width = INTVAL (XEXP (dst, 1));
+	  offset = INTVAL (XEXP (dst, 2));
+	}
 
       loc = &XEXP (dst, 0);
       dst = *loc;
@@ -2749,13 +2815,13 @@ 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);
+		     dst, loc, bb, insn, DF_REF_REG_DEF, flags, width, offset);
 
       /* 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);
+		       dst, NULL, bb, insn, DF_REF_REG_USE, flags, width, offset);
     }
   else if (GET_CODE (dst) == SUBREG && REG_P (SUBREG_REG (dst)))
     {
@@ -2765,7 +2831,7 @@ 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);
+		     dst, loc, bb, insn, DF_REF_REG_DEF, flags, width, offset);
     }
 }
 
@@ -2801,12 +2867,18 @@ df_defs_record (struct df_collection_rec
 }
 
 
-/* Process all the registers used in the rtx at address LOC.  */
+/* 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.  */
 
 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)
+		basic_block bb, rtx insn, enum df_ref_flags flags,
+		int width, int offset)
 {
   RTX_CODE code;
   rtx x;
@@ -2837,7 +2909,7 @@ 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);
+			DF_REF_REG_MEM_STORE, bb, insn, flags, width, offset);
 
       /* If we're clobbering a REG then we have a def so ignore.  */
       return;
@@ -2845,7 +2917,7 @@ 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);
+		      bb, insn, flags & DF_REF_IN_NOTE, width, offset);
       return;
 
     case SUBREG:
@@ -2855,22 +2927,46 @@ 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);
+	  df_uses_record (collection_rec, loc, ref_type, bb, insn, flags, width, offset);
 	  return;
 	}
       /* ... Fall through ...  */
 
     case REG:
       df_ref_record (collection_rec, 
-		     x, loc, bb, insn, ref_type, flags);
+		     x, loc, bb, insn, ref_type, flags, width, offset);
       return;
 
+    case SIGN_EXTRACT:
+    case ZERO_EXTRACT:
+      {
+	/* If the parameters to the zero or sign extract are
+	   constants, strip them off and recurse, otherwise there is
+	   no information that we can gain from this operation.  */
+	if (GET_CODE (XEXP (x, 1)) == CONST_INT
+	    && GET_CODE (XEXP (x, 2)) == CONST_INT)
+	  {
+	    width = INTVAL (XEXP (x, 1));
+	    offset = INTVAL (XEXP (x, 2));
+
+	    if (code == ZERO_EXTRACT)
+	      flags |= DF_REF_ZERO_EXTRACT;
+	    else
+	      flags |= DF_REF_SIGN_EXTRACT;
+
+	    df_uses_record (collection_rec,
+			    &XEXP (x, 0), ref_type, bb, insn, flags, width, offset);
+	    return;
+	  }
+      }
+      break;
+
     case SET:
       {
 	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);
+			&SET_SRC (x), DF_REF_REG_USE, bb, insn, flags, width, offset);
 
 	switch (GET_CODE (dst))
 	  {
@@ -2879,7 +2975,7 @@ 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);
+				  flags | DF_REF_READ_WRITE | DF_REF_SUBREG, width, offset);
 		  break;
 		}
 	      /* Fall through.  */
@@ -2891,7 +2987,7 @@ 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);
+			      DF_REF_REG_MEM_STORE, bb, insn, flags, width, offset);
 	      break;
 	    case STRICT_LOW_PART:
 	      {
@@ -2902,20 +2998,31 @@ 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_LOWER_PART);
+				DF_REF_READ_WRITE | DF_REF_STRICT_LOW_PART, width, offset);
 	      }
 	      break;
 	    case ZERO_EXTRACT:
-	    case SIGN_EXTRACT:
-	      df_uses_record (collection_rec, &XEXP (dst, 0), 
-			      DF_REF_REG_USE, bb, insn, 
-			      DF_REF_READ_WRITE | DF_REF_EXTRACT);
-	      df_uses_record (collection_rec, &XEXP (dst, 1), 
-			      DF_REF_REG_USE, bb, insn, flags);
-	      df_uses_record (collection_rec, &XEXP (dst, 2), 
-			      DF_REF_REG_USE, bb, insn, flags);
-	      dst = XEXP (dst, 0);
+	      {
+		if (GET_CODE (XEXP (dst, 1)) == CONST_INT
+		    && GET_CODE (XEXP (dst, 2)) == CONST_INT)
+		  {
+		    width = INTVAL (XEXP (dst, 1));
+		    offset = INTVAL (XEXP (dst, 2));
+		  }
+		else 
+		  {
+		    df_uses_record (collection_rec, &XEXP (dst, 1), 
+				    DF_REF_REG_USE, bb, insn, flags, width, offset);
+		    df_uses_record (collection_rec, &XEXP (dst, 2), 
+				    DF_REF_REG_USE, bb, insn, flags, width, offset);
+		  }
+
+		df_uses_record (collection_rec, &XEXP (dst, 0), 
+				DF_REF_REG_USE, bb, insn, 
+				DF_REF_READ_WRITE | DF_REF_ZERO_EXTRACT, width, offset);
+	      }
 	      break;
+
 	    default:
 	      gcc_unreachable ();
 	  }
@@ -2962,7 +3069,7 @@ 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);
+			      DF_REF_REG_USE, bb, insn, flags, width, offset);
 	    return;
 	  }
 	break;
@@ -2977,7 +3084,7 @@ 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);
+                     flags | DF_REF_READ_WRITE | DF_REF_PRE_POST_MODIFY, width, offset);
 
       /* ... Fall through to handle uses ...  */
 
@@ -3000,14 +3107,16 @@ df_uses_record (struct df_collection_rec
 		loc = &XEXP (x, 0);
 		goto retry;
 	      }
-	    df_uses_record (collection_rec, &XEXP (x, i), ref_type, bb, insn, flags);
+	    df_uses_record (collection_rec, &XEXP (x, i), ref_type, 
+			    bb, insn, flags, width, offset);
 	  }
 	else if (fmt[i] == 'E')
 	  {
 	    int j;
 	    for (j = 0; j < XVECLEN (x, i); j++)
 	      df_uses_record (collection_rec,
-			      &XVECEXP (x, i, j), ref_type, bb, insn, flags);
+			      &XVECEXP (x, i, j), ref_type, 
+			      bb, insn, flags, width, offset);
 	  }
       }
   }
@@ -3027,11 +3136,21 @@ df_get_conditional_uses (struct df_colle
       struct df_ref *ref = collection_rec->def_vec[i];
       if (DF_REF_FLAGS_IS_SET (ref, DF_REF_CONDITIONAL))
         {
-          struct df_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);
+	  int width = -1;
+	  int offset = -1;
+          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);
+	    }
+
+          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);
           DF_REF_REGNO (use) = DF_REF_REGNO (ref);
         }
     }
@@ -3069,7 +3188,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);
+			DF_REF_REG_USE, bb, insn, flags, -1, -1);
       else if (GET_CODE (XEXP (note, 0)) == CLOBBER)
 	{
 	  if (REG_P (XEXP (XEXP (note, 0), 0)))
@@ -3081,13 +3200,13 @@ df_get_call_refs (struct df_collection_r
 	    }
 	  else
 	    df_uses_record (collection_rec, &XEXP (note, 0),
-		            DF_REF_REG_USE, bb, insn, flags);
+		            DF_REF_REG_USE, bb, insn, flags, -1, -1);
 	}
     }
 
   /* 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);
+		 NULL, bb, insn, DF_REF_REG_USE, DF_REF_CALL_STACK_USAGE | flags, -1, -1);
 
   /* Calls may also reference any of the global registers,
      so they are recorded as used.  */
@@ -3095,9 +3214,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);
+		       NULL, bb, insn, DF_REF_REG_USE, flags, -1, -1);
 	df_ref_record (collection_rec, regno_reg_rtx[i],
-		       NULL, bb, insn, DF_REF_REG_DEF, flags);
+		       NULL, bb, insn, DF_REF_REG_DEF, flags, -1, -1);
       }
 
   is_sibling_call = SIBLING_CALL_P (insn);
@@ -3110,7 +3229,7 @@ df_get_call_refs (struct df_collection_r
 	      || refers_to_regno_p (ui, ui+1, 
 				    current_function_return_rtx, NULL)))
         df_ref_record (collection_rec, regno_reg_rtx[ui], 
-		       NULL, bb, insn, DF_REF_REG_DEF, DF_REF_MAY_CLOBBER | flags);
+		       NULL, bb, insn, DF_REF_REG_DEF, DF_REF_MAY_CLOBBER | flags, -1, -1);
     }
 
   BITMAP_FREE (defs_generated);
@@ -3148,7 +3267,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);
+                          bb, insn, DF_REF_IN_NOTE, -1, -1);
           break;
         case REG_NON_LOCAL_GOTO:
           /* The frame ptr is used by a non-local goto.  */
@@ -3156,13 +3275,13 @@ df_insn_refs_collect (struct df_collecti
                          regno_reg_rtx[FRAME_POINTER_REGNUM],
                          NULL,
                          bb, insn, 
-                         DF_REF_REG_USE, 0);
+                         DF_REF_REG_USE, 0, -1, -1);
 #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);
+                         DF_REF_REG_USE, 0, -1, -1);
 #endif
           break;
         default:
@@ -3176,7 +3295,7 @@ 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);
+		  &PATTERN (insn), DF_REF_REG_USE, bb, insn, 0, -1, -1);
 
   /* DF_REF_CONDITIONAL needs corresponding USES. */
   if (is_cond_exec)
@@ -3259,7 +3378,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);
+			 bb, NULL, DF_REF_REG_DEF, DF_REF_AT_TOP, -1, -1);
 	}
     }
 #endif
@@ -3283,7 +3402,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);
+			 bb, NULL, DF_REF_REG_USE, DF_REF_AT_TOP, -1, -1);
     }
 #endif
 
@@ -3291,7 +3410,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);
+		   bb, NULL, DF_REF_REG_DEF, DF_REF_AT_TOP, -1, -1);
  
   /* Add the artificial uses.  */
   if (bb->index >= NUM_FIXED_BLOCKS)
@@ -3305,7 +3424,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);
+			 bb, NULL, DF_REF_REG_USE, 0, -1, -1);
 	}
     }
 
@@ -3598,7 +3717,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);
+		     ENTRY_BLOCK_PTR, NULL, DF_REF_REG_DEF, 0, -1, -1);
     }
 
   df_canonize_collection_rec (collection_rec);
@@ -3759,7 +3878,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);
+		   EXIT_BLOCK_PTR, NULL, DF_REF_REG_USE, 0, -1, -1);
 
 #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
   /* It is deliberate that this is not put in the exit block uses but
@@ -3769,7 +3888,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);
+		   EXIT_BLOCK_PTR, NULL, DF_REF_REG_USE, 0, -1, -1);
 #endif
 
   df_canonize_collection_rec (collection_rec);
Index: global.c
===================================================================
--- global.c	(revision 132860)
+++ global.c	(working copy)
@@ -1490,7 +1490,7 @@ build_insn_chain (void)
 			/* We can model subregs, but not if they are
 			   wrapped in ZERO_EXTRACTS.  */
 			if (GET_CODE (reg) == SUBREG
-			    && !DF_REF_FLAGS_IS_SET (def, DF_REF_EXTRACT))
+			    && !DF_REF_FLAGS_IS_SET (def, DF_REF_ZERO_EXTRACT))
 			  {
 			    unsigned int start = SUBREG_BYTE (reg);
 			    unsigned int last = start 
@@ -1503,7 +1503,7 @@ build_insn_chain (void)
 						  regno, reg);
 
 			    if (!DF_REF_FLAGS_IS_SET
-				(def, DF_REF_STRICT_LOWER_PART))
+				(def, DF_REF_STRICT_LOW_PART))
 			      {
 				/* Expand the range to cover entire words.
 				   Bytes added here are "don't care".  */
@@ -1566,7 +1566,7 @@ build_insn_chain (void)
 		       precisely so we do not need to look at the
 		       fabricated use. */
 		    if (DF_REF_FLAGS_IS_SET (use, DF_REF_READ_WRITE) 
-			&& !DF_REF_FLAGS_IS_SET (use, DF_REF_EXTRACT) 
+			&& !DF_REF_FLAGS_IS_SET (use, DF_REF_ZERO_EXTRACT) 
 			&& DF_REF_FLAGS_IS_SET (use, DF_REF_SUBREG))
 		      continue;
 		    
@@ -1585,7 +1585,8 @@ build_insn_chain (void)
 		    if (regno < FIRST_PSEUDO_REGISTER || reg_renumber[regno] >= 0)
 		      {
 			if (GET_CODE (reg) == SUBREG
-			    && !DF_REF_FLAGS_IS_SET (use, DF_REF_EXTRACT)) 
+			    && !DF_REF_FLAGS_IS_SET (use,
+						     DF_REF_SIGN_EXTRACT | DF_REF_ZERO_EXTRACT)) 
 			  {
 			    unsigned int start = SUBREG_BYTE (reg);
 			    unsigned int last = start 
Index: df.h
===================================================================
--- df.h	(revision 132860)
+++ df.h	(working copy)
@@ -117,14 +117,18 @@ enum df_ref_flags
     DF_REF_MUST_CLOBBER = 1 << 7,
 
 
-    /* This flag is set if this ref is inside a pre/post modify.  */
-    DF_REF_PRE_POST_MODIFY = 1 << 8,
+    /* If the ref has one of the following two flags set, then the
+       struct df_ref can be cast to struct df_ref_extract to access
+       the width and offset fields.  */
+ 
+    /* This flag is set if the ref contains a SIGN_EXTRACT.  */
+    DF_REF_SIGN_EXTRACT = 1 << 8,
 
-    /* This flag is set if the ref contains a ZERO_EXTRACT or SIGN_EXTRACT.  */
-    DF_REF_EXTRACT = 1 << 9,
+    /* This flag is set if the ref contains a ZERO_EXTRACT.  */
+    DF_REF_ZERO_EXTRACT = 1 << 9,
 
-    /* This flag is set if the ref contains a STRICT_LOWER_PART.  */
-    DF_REF_STRICT_LOWER_PART = 1 << 10,
+    /* This flag is set if the ref contains a STRICT_LOW_PART.  */
+    DF_REF_STRICT_LOW_PART = 1 << 10,
 
     /* This flag is set if the ref contains a SUBREG.  */
     DF_REF_SUBREG = 1 << 11,
@@ -138,7 +142,11 @@ enum df_ref_flags
     DF_REF_CALL_STACK_USAGE = 1 << 13,
 
     /* This flag is used for verification of existing refs. */
-    DF_REF_REG_MARKER = 1 << 14
+    DF_REF_REG_MARKER = 1 << 14,
+
+    /* This flag is set if this ref is inside a pre/post modify.  */
+    DF_REF_PRE_POST_MODIFY = 1 << 15
+
   };
 
 /* The possible ordering of refs within the df_ref_info.  */
@@ -381,6 +389,17 @@ struct df_ref
   struct df_ref *prev_reg;     /* Prev ref with same regno and type.  */
 };
 
+/* A df_ref_extract is just a df_ref with a width and offset field at
+   the end of it.  It is used to hold this information if the ref was
+   wrapped by a SIGN_EXTRACT or a ZERO_EXTRACT and to pass this info
+   to passes that wish to process partial regs precisely.  */
+struct df_ref_extract
+{
+  struct df_ref ref;
+  int width;
+  int offset;
+};
+
 /* These links are used for two purposes:
    1) def-use or use-def chains. 
    2) Multiword hard registers that underly a single hardware register.  */
@@ -598,7 +617,10 @@ struct df
 #define DF_REF_IS_REG_MARKED(REF) (DF_REF_FLAGS_IS_SET ((REF),DF_REF_REG_MARKER))
 #define DF_REF_NEXT_REG(REF) ((REF)->next_reg)
 #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)
 /* Macros to determine the reference type.  */
 
 #define DF_REF_REG_DEF_P(REF) (DF_REF_TYPE (REF) == DF_REF_REG_DEF)
@@ -862,7 +884,8 @@ extern void df_grow_reg_info (void);
 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);
+				     enum df_ref_type, enum df_ref_flags,
+				     int, int);
 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);

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2008-03-06  0:31 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-03-04 20:53 [trunk] first of three patches to get rid of no conflict blocks Kenneth Zadeck
2008-03-04 20:57 ` Kenneth Zadeck
2008-03-05 21:24   ` Ian Lance Taylor
2008-03-06  0:31     ` Kenneth Zadeck

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).