This patch makes the shift code in simplify-rtx.c more like the CONST_INT
handling on mainline. There we have:
case LSHIFTRT:
case ASHIFT:
case ASHIFTRT:
/* Truncate the shift if SHIFT_COUNT_TRUNCATED, otherwise make sure
the value is in range. We can't return any old value for
out-of-range arguments because either the middle-end (via
shift_truncation_mask) or the back-end might be relying on
target-specific knowledge. Nor can we rely on
shift_truncation_mask, since the shift might not be part of an
ashlM3, lshrM3 or ashrM3 instruction. */
if (SHIFT_COUNT_TRUNCATED)
arg1 = (unsigned HOST_WIDE_INT) arg1 % width;
else if (arg1 < 0 || arg1 >= GET_MODE_BITSIZE (mode))
return 0;
val = (code == ASHIFT
? ((unsigned HOST_WIDE_INT) arg0) << arg1
: ((unsigned HOST_WIDE_INT) arg0) >> arg1);
/* Sign-extend the result for arithmetic right shifts. */
if (code == ASHIFTRT && arg0s < 0 && arg1 > 0)
val |= HOST_WIDE_INT_M1U << (width - arg1);
break;
case ROTATERT:
if (arg1 < 0)
return 0;
arg1 %= width;
val = ((((unsigned HOST_WIDE_INT) arg0) << (width - arg1))
| (((unsigned HOST_WIDE_INT) arg0) >> arg1));
break;
case ROTATE:
if (arg1 < 0)
return 0;
arg1 %= width;
val = ((((unsigned HOST_WIDE_INT) arg0) << arg1)
| (((unsigned HOST_WIDE_INT) arg0) >> (width - arg1)));
break;
The main points being:
- We don't care whether a shift (as opposed to rotate) amount appears
negative if SHIFT_COUNT_TRUNCATED, since the macro means there's
no such thing as a negative shift.
- !SHIFT_COUNT_TRUNCATED means that the target-independent code doesn't
know how the target handles out-of-range shifts, so it shouldn't try
to simplify them.
- With that change, the bitsize argument is redundant, since we already
ensure that the argument is in [0, width), where width <= bitsize.
- We treat all nonnegative rotate amounts as being modulo the width,
regardless of SHIFT_COUNT_TRUNCATED. This goes back to the very
early days of GCC so I don't think we should change it here.
Tested on powerpc64-linux-gnu and by comparing assembly code. OK to install?
Thanks,
Richard
Index: gcc/simplify-rtx.c
===================================================================
--- gcc/simplify-rtx.c 2013-11-04 09:07:28.343111332 +0000
+++ gcc/simplify-rtx.c 2013-11-04 21:08:24.937662430 +0000
@@ -3703,7 +3703,6 @@ simplify_const_binary_operation (enum rt
{
wide_int result;
bool overflow;
- unsigned int bitsize = GET_MODE_BITSIZE (mode);
rtx_mode_t pop0 = std::make_pair (op0, mode);
rtx_mode_t pop1 = std::make_pair (op1, mode);
@@ -3785,36 +3784,46 @@ simplify_const_binary_operation (enum rt
case LSHIFTRT:
case ASHIFTRT:
case ASHIFT:
- case ROTATE:
- case ROTATERT:
{
wide_int wop1 = pop1;
- if (wi::neg_p (wop1))
- return NULL_RTX;
-
if (SHIFT_COUNT_TRUNCATED)
wop1 = wi::umod_trunc (wop1, width);
+ else if (wi::geu_p (wop1, width))
+ return NULL_RTX;
switch (code)
{
case LSHIFTRT:
- result = wi::lrshift (pop0, wop1, bitsize);
+ result = wi::lrshift (pop0, wop1);
break;
case ASHIFTRT:
- result = wi::arshift (pop0, wop1, bitsize);
+ result = wi::arshift (pop0, wop1);
break;
case ASHIFT:
- result = wi::lshift (pop0, wop1, bitsize);
+ result = wi::lshift (pop0, wop1);
break;
+ default:
+ gcc_unreachable ();
+ }
+ break;
+ }
+ case ROTATE:
+ case ROTATERT:
+ {
+ if (wi::neg_p (pop1))
+ return NULL_RTX;
+
+ switch (code)
+ {
case ROTATE:
- result = wi::lrotate (pop0, wop1);
+ result = wi::lrotate (pop0, pop1);
break;
case ROTATERT:
- result = wi::rrotate (pop0, wop1);
+ result = wi::rrotate (pop0, pop1);
break;
default: