summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>2013-03-11 11:48:34 +0000
committerrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>2013-03-11 11:48:34 +0000
commitf8825f5de7862e860f8b86db3f05f7d6b7f8ba80 (patch)
tree178fb59e89fbf75745000cba0fd09e9b6d1ad098
parent97927869223333276563f9cf5465819fe2fe6c40 (diff)
downloadgcc-f8825f5de7862e860f8b86db3f05f7d6b7f8ba80.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@196595 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/config/arm/arm.c106
2 files changed, 65 insertions, 48 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a3469f47b07..54dd64c7059 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index c720561f165..ca367608c96 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -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)