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]

Trim surplus zero extends


This test case:

void foo (unsigned char *p)
{
  unsigned long i;

  if (p[0] != 0xff)
    for (i = 1; i <= p[0]; i++)
      p[i] = 0;
}

generates code with an unnecessary zero extend on powerpc64-linux
(also powerpc-linux if using "unsigned long long i", which is a
regression from 2.95 and 3.0).

.foo:
        lbz 11,0(3)		# zero extended byte
        rlwinm 0,11,0,0xff	# not needed
        cmpwi 0,0,255
[snip]

I guess this problem was introduced when all CONST_INTs became sign
extended.

	* combine.c (simplify_comparison): When widening modes, ignore
	sign extension on CONST_INTs.

OK for mainline and branch?  Currently bootstrapping 3.1 powerpc-linux.

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

diff -urpN -xCVS -x*~ gcc-3.1/gcc/combine.c gcc-3.1-patched/gcc/combine.c
--- gcc-3.1/gcc/combine.c	Mon Mar 11 19:28:51 2002
+++ gcc-3.1-patched/gcc/combine.c	Sat Mar 23 00:48:52 2002
@@ -10970,14 +10970,22 @@ simplify_comparison (code, pop0, pop1)
 	 tmode = GET_MODE_WIDER_MODE (tmode))
       if (have_insn_for (COMPARE, tmode))
 	{
+	  int zero_extended;
+
 	  /* If the only nonzero bits in OP0 and OP1 are those in the
 	     narrower mode and this is an equality or unsigned comparison,
 	     we can use the wider mode.  Similarly for sign-extended
 	     values, in which case it is true for all comparisons.  */
-	  if (((code == EQ || code == NE
-		|| code == GEU || code == GTU || code == LEU || code == LTU)
-	       && (nonzero_bits (op0, tmode) & ~GET_MODE_MASK (mode)) == 0
-	       && (nonzero_bits (op1, tmode) & ~GET_MODE_MASK (mode)) == 0)
+	  zero_extended = ((code == EQ || code == NE
+			    || code == GEU || code == GTU
+			    || code == LEU || code == LTU)
+			   && (nonzero_bits (op0, tmode)
+			       & ~GET_MODE_MASK (mode)) == 0
+			   && ((GET_CODE (op1) == CONST_INT
+				|| (nonzero_bits (op1, tmode)
+				    & ~GET_MODE_MASK (mode)) == 0)));
+
+	  if (zero_extended
 	      || ((num_sign_bit_copies (op0, tmode)
 		   > GET_MODE_BITSIZE (tmode) - GET_MODE_BITSIZE (mode))
 		  && (num_sign_bit_copies (op1, tmode)
@@ -10994,6 +10999,8 @@ simplify_comparison (code, pop0, pop1)
 							   XEXP (op0, 1)));
 
 	      op0 = gen_lowpart_for_combine (tmode, op0);
+	      if (zero_extended && GET_CODE (op1) == CONST_INT)
+		op1 = GEN_INT (INTVAL (op1) & GET_MODE_MASK (mode));
 	      op1 = gen_lowpart_for_combine (tmode, op1);
 	      break;
 	    }


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