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]

[PATCH] validate_replace_rtx_1 fix for SUBREG_BYTE branch


Hi!

I apparently forgot about VOIDmode CONST_DOUBLEs, so if a VOIDmode
CONST_DOUBLE is being substituted into a SUBREG, compiler would crash.
Bootstrapped in the rh7 compiler on i386/alpha/sparc, regression tested.
Bootstrapped in subreg-byte-branch gcc.

2001-01-05  Jakub Jelinek  <jakub@redhat.com>

	* recog.c (validate_replace_rtx_1): Simplify SUBREG of VOIDmode
	CONST_DOUBLE.

--- gcc/recog.c.jj	Tue Nov 21 11:30:16 2000
+++ gcc/recog.c	Fri Jan  5 22:43:13 2001
@@ -500,6 +500,9 @@ validate_replace_rtx_1 (loc, from, to, o
 	 about inner mode may be lost.  */
       if (CONSTANT_P (to) && rtx_equal_p (SUBREG_REG (x), from))
         {
+	  int offset, part;
+	  unsigned HOST_WIDE_INT i;
+
 	  /* A paradoxical SUBREG of a VOIDmode constant is the same constant,
 	     since we are saying that the high bits don't matter.  */
 	  if (GET_MODE (to) == VOIDmode
@@ -514,44 +517,62 @@ validate_replace_rtx_1 (loc, from, to, o
 		}
 	    }
 
-	  if (GET_CODE (to) == CONST_INT)
+	  offset = SUBREG_BYTE (x) * BITS_PER_UNIT;
+	  switch (GET_CODE (to))
 	    {
-	      /* Avoid creating bogus SUBREGs */
-	      enum machine_mode mode = GET_MODE (x);
-	      enum machine_mode inner_mode = GET_MODE (from);
-	      int offset;
-	      unsigned HOST_WIDE_INT i;
-
-	      if (GET_MODE_CLASS (mode) != MODE_INT)
-		abort ();
-
-	      offset = SUBREG_BYTE (x);
-	      if (BYTES_BIG_ENDIAN || WORDS_BIG_ENDIAN)
-		{
-		  if (WORDS_BIG_ENDIAN)
-		    offset = GET_MODE_SIZE (inner_mode)
-			     - GET_MODE_SIZE (mode) - offset;
-		  if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
-		      && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
-		    offset = (offset + UNITS_PER_WORD - GET_MODE_SIZE (mode)
-			      - 2 * (offset % UNITS_PER_WORD));
-		}
-
-	      offset *= BITS_PER_UNIT;
-	      i = INTVAL (to);
-
-	      if (offset >= HOST_BITS_PER_WIDE_INT)
-		to = ((HOST_WIDE_INT) i < 0) ? constm1_rtx : const0_rtx;
-	      else
-		{
-		  i >>= offset;
-		  if (GET_MODE_BITSIZE (mode) < HOST_BITS_PER_WIDE_INT)
-		    i = trunc_int_for_mode (i, mode);
-		  to = GEN_INT (i);
-		}
+	    case CONST_DOUBLE:
+	      if (GET_MODE (to) != VOIDmode)
+		break;
+
+	      part = offset >= HOST_BITS_PER_WIDE_INT;
+	      if ((BITS_PER_WORD > HOST_BITS_PER_WIDE_INT
+		   && BYTES_BIG_ENDIAN)
+		  || (BITS_PER_WORD <= HOST_BITS_PER_WIDE_INT
+		      && WORDS_BIG_ENDIAN))
+		part = !part;
+	      i = (&CONST_DOUBLE_LOW (to))[part];
+	      offset %= HOST_BITS_PER_WIDE_INT;
+
+	      /* FALLTHROUGH */
+	    case CONST_INT:
+	      if (GET_CODE (to) == CONST_INT)
+		i = INTVAL (to);
+
+	      {
+		/* Avoid creating bogus SUBREGs */
+		enum machine_mode mode = GET_MODE (x);
+		enum machine_mode inner_mode = GET_MODE (from);
+
+		if (GET_MODE_CLASS (mode) != MODE_INT)
+		  abort ();
+
+		if (BYTES_BIG_ENDIAN || WORDS_BIG_ENDIAN)
+		  {
+		    if (WORDS_BIG_ENDIAN)
+		      offset = GET_MODE_BITSIZE (inner_mode)
+			       - GET_MODE_BITSIZE (mode) - offset;
+		    if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
+			&& GET_MODE_SIZE (mode) < UNITS_PER_WORD)
+		      offset = offset + BITS_PER_WORD - GET_MODE_BITSIZE (mode)
+			       - 2 * (offset % BITS_PER_WORD);
+		  }
+
+		if (offset >= HOST_BITS_PER_WIDE_INT)
+		  to = ((HOST_WIDE_INT) i < 0) ? constm1_rtx : const0_rtx;
+		else
+		  {
+		    i >>= offset;
+		    if (GET_MODE_BITSIZE (mode) < HOST_BITS_PER_WIDE_INT)
+		      i = trunc_int_for_mode (i, mode);
+		    to = GEN_INT (i);
+		  }
+
+		validate_change (object, loc, to, 1);
+		return;
+	      }
 
-	      validate_change (object, loc, to, 1);
-	      return;
+	    default:
+	      break;
 	    }
         }
 

	Jakub

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