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: