re PR target/56470 (ICE output_operand: invalid shift operand)
authorRichard Earnshaw <rearnsha@arm.com>
Mon, 11 Mar 2013 11:48:34 +0000 (11:48 +0000)
committerRichard Earnshaw <rearnsha@gcc.gnu.org>
Mon, 11 Mar 2013 11:48:34 +0000 (11:48 +0000)
PR target/56470
* arm.c (shift_op): Validate RTL pattern on the fly.
(arm_print_operand, case 'S'): Don't use shift_operator to validate
the RTL.

From-SVN: r196595

gcc/ChangeLog
gcc/config/arm/arm.c

index a3469f4..54dd64c 100644 (file)
@@ -1,3 +1,10 @@
+2013-03-11  Richard Earnshaw  <rearnsha@arm.com>
+
+       PR target/56470
+       * arm.c (shift_op): Validate RTL pattern on the fly.
+       (arm_print_operand, case 'S'): Don't use shift_operator to validate
+       the RTL.
+
 2013-03-10  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
 
        PR target/56347
index c720561..ca36760 100644 (file)
@@ -15430,72 +15430,88 @@ shift_op (rtx op, HOST_WIDE_INT *amountp)
   const char * mnem;
   enum rtx_code code = GET_CODE (op);
 
-  switch (GET_CODE (XEXP (op, 1)))
-    {
-    case REG:
-    case SUBREG:
-      *amountp = -1;
-      break;
-
-    case CONST_INT:
-      *amountp = INTVAL (XEXP (op, 1));
-      break;
-
-    default:
-      gcc_unreachable ();
-    }
-
   switch (code)
     {
     case ROTATE:
-      gcc_assert (*amountp != -1);
-      *amountp = 32 - *amountp;
-      code = ROTATERT;
+      if (!CONST_INT_P (XEXP (op, 1)))
+       {
+         output_operand_lossage ("invalid shift operand");
+         return NULL;
+       }
 
-      /* Fall through.  */
+      code = ROTATERT;
+      *amountp = 32 - INTVAL (XEXP (op, 1));
+      mnem = "ror";
+      break;
 
     case ASHIFT:
     case ASHIFTRT:
     case LSHIFTRT:
     case ROTATERT:
       mnem = arm_shift_nmem(code);
+      if (CONST_INT_P (XEXP (op, 1)))
+       {
+         *amountp = INTVAL (XEXP (op, 1));
+       }
+      else if (REG_P (XEXP (op, 1)))
+       {
+         *amountp = -1;
+         return mnem;
+       }
+      else
+       {
+         output_operand_lossage ("invalid shift operand");
+         return NULL;
+       }
       break;
 
     case MULT:
       /* We never have to worry about the amount being other than a
         power of 2, since this case can never be reloaded from a reg.  */
-      gcc_assert (*amountp != -1);
+      if (!CONST_INT_P (XEXP (op, 1)))
+       {
+         output_operand_lossage ("invalid shift operand");
+         return NULL;
+       }
+
+      *amountp = INTVAL (XEXP (op, 1)) & 0xFFFFFFFF;
+
+      /* Amount must be a power of two.  */
+      if (*amountp & (*amountp - 1))
+       {
+         output_operand_lossage ("invalid shift operand");
+         return NULL;
+       }
+
       *amountp = int_log2 (*amountp);
       return ARM_LSL_NAME;
 
     default:
-      gcc_unreachable ();
+      output_operand_lossage ("invalid shift operand");
+      return NULL;
     }
 
-  if (*amountp != -1)
+  /* This is not 100% correct, but follows from the desire to merge
+     multiplication by a power of 2 with the recognizer for a
+     shift.  >=32 is not a valid shift for "lsl", so we must try and
+     output a shift that produces the correct arithmetical result.
+     Using lsr #32 is identical except for the fact that the carry bit
+     is not set correctly if we set the flags; but we never use the
+     carry bit from such an operation, so we can ignore that.  */
+  if (code == ROTATERT)
+    /* Rotate is just modulo 32.  */
+    *amountp &= 31;
+  else if (*amountp != (*amountp & 31))
     {
-      /* This is not 100% correct, but follows from the desire to merge
-        multiplication by a power of 2 with the recognizer for a
-        shift.  >=32 is not a valid shift for "lsl", so we must try and
-        output a shift that produces the correct arithmetical result.
-        Using lsr #32 is identical except for the fact that the carry bit
-        is not set correctly if we set the flags; but we never use the
-        carry bit from such an operation, so we can ignore that.  */
-      if (code == ROTATERT)
-       /* Rotate is just modulo 32.  */
-       *amountp &= 31;
-      else if (*amountp != (*amountp & 31))
-       {
-         if (code == ASHIFT)
-           mnem = "lsr";
-         *amountp = 32;
-       }
-
-      /* Shifts of 0 are no-ops.  */
-      if (*amountp == 0)
-       return NULL;
+      if (code == ASHIFT)
+       mnem = "lsr";
+      *amountp = 32;
     }
 
+  /* Shifts of 0 are no-ops.  */
+  if (*amountp == 0)
+    return NULL;
+
   return mnem;
 }
 
@@ -17743,12 +17759,6 @@ arm_print_operand (FILE *stream, rtx x, int code)
        HOST_WIDE_INT val;
        const char *shift;
 
-       if (!shift_operator (x, SImode))
-         {
-           output_operand_lossage ("invalid shift operand");
-           break;
-         }
-
        shift = shift_op (x, &val);
 
        if (shift)