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]

[RFA/RFC] three very small combine cleanups 3/3: remove (use (mem)) idiom


This patch removes one strange combine-ism, a (use (mem ...)) that
is used to mark ZERO_EXTRACT or SIGN_EXTRACT operations that go
beyond the mem's mode.  For example, combine wrap a USE outside
a HImode memory access, if we tried to access 4 bits starting
at bit 14 (and ending at the invalid bit 17).

I have no clue how this can happen.  One possibility that came
to mind is masking a bitfield that originarily spanned two words,
as in these two test cases:

 struct a {
   unsigned a : 28;
   unsigned b : 8;
   unsigned c : 28;
 };

 char f (struct a *x)
 {
   return x->b & 15;
 }

or

 struct a {
   unsigned a : 4;
   unsigned b : 8;
   unsigned c : 4;
 };

 char f (struct a *x)
 {
   return x->b & 15;
 }

I'm proposing to remove traces of this construct, because code
for the above testcases did not have any change respectively on
powerpc-apple-darwin8.3.0 and avr-unknown-none.

I'm CCing Kenner in case he knows more about this strangeness.

Paolo

2005-12-18  Paolo Bonzini  <bonzini@gnu.org>

        * combine.c (expand_compound_operation,
	expand_field_assignment): Don't wrap MEMs in a USE rtx.
	(force_to_mode, simplify_shift_const): Don't look for USEs.

Index: combine.c
===================================================================
--- combine.c	(revision 108634)
+++ combine.c	(working copy)
@@ -5414,7 +5417,7 @@ expand_compound_operation (rtx x)
 	 with a (use (mem ...)) construct that only combine understands
 	 and is used only for this purpose.  */
       if (len + pos > GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))))
-	SUBST (XEXP (x, 0), gen_rtx_USE (GET_MODE (x), XEXP (x, 0)));
+	SUBST (XEXP (x, 0), gen_rtx_CLOBBER (GET_MODE (x), const0_rtx));
 
       if (BITS_BIG_ENDIAN)
 	pos = GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) - len - pos;
@@ -5573,10 +5576,10 @@ expand_field_assignment (rtx x)
 	  pos = XEXP (SET_DEST (x), 2);
 
 	  /* If the position is constant and spans the width of INNER,
-	     surround INNER  with a USE to indicate this.  */
+	     protect from an invalid transformation.  */
 	  if (GET_CODE (pos) == CONST_INT
 	      && INTVAL (pos) + len > GET_MODE_BITSIZE (GET_MODE (inner)))
-	    inner = gen_rtx_USE (GET_MODE (SET_DEST (x)), inner);
+	    inner = gen_rtx_CLOBBER (GET_MODE (SET_DEST (x)), const0_rtx);
 
 	  if (BITS_BIG_ENDIAN)
 	    {
@@ -6632,15 +6635,6 @@ force_to_mode (rtx x, enum machine_mode 
 	 generating something that won't match.  */
       return x;
 
-    case USE:
-      /* X is a (use (mem ..)) that was made from a bit-field extraction that
-	 spanned the boundary of the MEM.  If we are now masking so it is
-	 within that boundary, we don't need the USE any more.  */
-      if (! BITS_BIG_ENDIAN
-	  && (mask & ~GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
-	return force_to_mode (XEXP (x, 0), mode, mask, next_select);
-      break;
-
     case SIGN_EXTEND:
     case ZERO_EXTEND:
     case ZERO_EXTRACT:
@@ -8422,33 +8418,6 @@ simplify_shift_const (rtx x, enum rtx_co
 	    }
 	  break;
 
-	case USE:
-	  /* Similar to the case above, except that we can only do this if
-	     the resulting mode is the same as that of the underlying
-	     MEM and adjust the address depending on the *bits* endianness
-	     because of the way that bit-field extract insns are defined.  */
-	  if ((code == ASHIFTRT || code == LSHIFTRT)
-	      && (tmode = mode_for_size (GET_MODE_BITSIZE (mode) - count,
-					 MODE_INT, 1)) != BLKmode
-	      && tmode == GET_MODE (XEXP (varop, 0)))
-	    {
-	      if (BITS_BIG_ENDIAN)
-		new = XEXP (varop, 0);
-	      else
-		{
-		  new = copy_rtx (XEXP (varop, 0));
-		  SUBST (XEXP (new, 0),
-			 plus_constant (XEXP (new, 0),
-					count / BITS_PER_UNIT));
-		}
-
-	      varop = gen_rtx_fmt_e (code == ASHIFTRT ? SIGN_EXTEND
-				     : ZERO_EXTEND, mode, new);
-	      count = 0;
-	      continue;
-	    }
-	  break;
-
 	case SUBREG:
 	  /* If VAROP is a SUBREG, strip it as long as the inner operand has
 	     the same number of words as what we've seen so far.  Then store

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