[PATCH] Fix PPC combine ICE

Alan Modra amodra@bigpond.net.au
Thu Mar 14 06:37:00 GMT 2002


On Thu, Mar 14, 2002 at 12:45:24PM +0100, Franz Sirl wrote:
> 
> 	* config/rs6000/rs6000.c (rs6000_emit_move): Properly handle
> 	CONST_INTs.

Isn't this just papering over the real problem?  The bad const_int
shouldn't be generated in the first place.  I have a patch somewhere
to a combine problem or two.  Hmm, maybe this is the one.  It's against
3.0, so you'll likely need to do some adjusting.  Don't blindly apply
to 3.2!  If it wasn't so late here, I'd tidy this up for 3.2, but
this might point you in the right direction.  Then again, it may be
for totally different bugs..

--- gcc-ppc64.orig/gcc/combine.c	Wed Nov  7 11:39:16 2001
+++ gcc-ppc64/gcc/combine.c	Thu Mar  7 16:45:56 2002
@@ -10867,46 +10872,43 @@ simplify_comparison (code, pop0, pop1)
 	     in both M1 and M2 and the SUBREG is either paradoxical or
 	     represents the low part, permute the SUBREG and the AND and
 	     try again.  */
-	  if (GET_CODE (XEXP (op0, 0)) == SUBREG
-	      && (0
+	  if (GET_CODE (XEXP (op0, 0)) == SUBREG)
+	    {
+	      tmode = GET_MODE (SUBREG_REG (XEXP (op0, 0)));
+	      if ((0
 #ifdef WORD_REGISTER_OPERATIONS
-		  || ((mode_width
-		       > (GET_MODE_BITSIZE
-			   (GET_MODE (SUBREG_REG (XEXP (op0, 0))))))
-		      && mode_width <= BITS_PER_WORD)
+		   || ((mode_width > (GET_MODE_BITSIZE (tmode)))
+		       && mode_width <= BITS_PER_WORD)
 #endif
-		  || ((mode_width
-		       <= (GET_MODE_BITSIZE
-			   (GET_MODE (SUBREG_REG (XEXP (op0, 0))))))
-		      && subreg_lowpart_p (XEXP (op0, 0))))
+		   || ((mode_width <= (GET_MODE_BITSIZE (tmode)))
+		       && subreg_lowpart_p (XEXP (op0, 0))))
 #ifndef WORD_REGISTER_OPERATIONS
-	      /* It is unsafe to commute the AND into the SUBREG if the SUBREG
-		 is paradoxical and WORD_REGISTER_OPERATIONS is not defined.
-		 As originally written the upper bits have a defined value
-		 due to the AND operation.  However, if we commute the AND
-		 inside the SUBREG then they no longer have defined values
-		 and the meaning of the code has been changed.  */
-	      && (GET_MODE_SIZE (GET_MODE (XEXP (op0, 0)))
-		  <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (XEXP (op0, 0)))))
+		  /* It is unsafe to commute the AND into the SUBREG if the
+		     SUBREG is paradoxical and WORD_REGISTER_OPERATIONS is
+		     not defined.  As originally written the upper bits
+		     have a defined value due to the AND operation.
+		     However, if we commute the AND inside the SUBREG then
+		     they no longer have defined values and the meaning of
+		     the code has been changed.  */
+		  && (GET_MODE_SIZE (GET_MODE (XEXP (op0, 0)))
+		      <= GET_MODE_SIZE (tmode))
 #endif
-	      && GET_CODE (XEXP (op0, 1)) == CONST_INT
-	      && mode_width <= HOST_BITS_PER_WIDE_INT
-	      && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (XEXP (op0, 0))))
-		  <= HOST_BITS_PER_WIDE_INT)
-	      && (INTVAL (XEXP (op0, 1)) & ~mask) == 0
-	      && 0 == (~GET_MODE_MASK (GET_MODE (SUBREG_REG (XEXP (op0, 0))))
-		       & INTVAL (XEXP (op0, 1)))
-	      && (unsigned HOST_WIDE_INT) INTVAL (XEXP (op0, 1)) != mask
-	      && ((unsigned HOST_WIDE_INT) INTVAL (XEXP (op0, 1))
-		  != GET_MODE_MASK (GET_MODE (SUBREG_REG (XEXP (op0, 0))))))
-
-	    {
-	      op0
-		= gen_lowpart_for_combine
-		  (mode,
-		   gen_binary (AND, GET_MODE (SUBREG_REG (XEXP (op0, 0))),
-			       SUBREG_REG (XEXP (op0, 0)), XEXP (op0, 1)));
-	      continue;
+		  && GET_CODE (XEXP (op0, 1)) == CONST_INT
+		  && mode_width <= HOST_BITS_PER_WIDE_INT
+		  && (GET_MODE_BITSIZE (tmode) <= HOST_BITS_PER_WIDE_INT)
+		  && (INTVAL (XEXP (op0, 1)) & ~mask) == 0
+		  && 0 == (~GET_MODE_MASK (tmode) & INTVAL (XEXP (op0, 1)))
+		  && (unsigned HOST_WIDE_INT) INTVAL (XEXP (op0, 1)) != mask
+		  && ((unsigned HOST_WIDE_INT) INTVAL (XEXP (op0, 1))
+		      != GET_MODE_MASK (tmode)))
+		{
+		  const_op = trunc_int_for_mode (INTVAL (XEXP (op0, 1)), tmode);
+		  op0 = gen_lowpart_for_combine
+		    (mode,
+		     gen_binary (AND, tmode, SUBREG_REG (XEXP (op0, 0)),
+				 GEN_INT (const_op)));
+		  continue;
+		}
 	    }
 
 	  /* Convert (ne (and (lshiftrt (not X)) 1) 0) to
@@ -11124,14 +11126,22 @@ simplify_comparison (code, pop0, pop1)
 	 tmode = GET_MODE_WIDER_MODE (tmode))
       if (cmp_optab->handlers[(int) tmode].insn_code != CODE_FOR_nothing)
 	{
+	  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)
@@ -11149,6 +11159,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;
 	    }

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre



More information about the Gcc-patches mailing list