[Bug target/93505] [8/9/10 Regression] wrong code or ICE with __builtin_bswap64() and rotation at -Og
jakub at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Thu Jan 30 10:44:00 GMT 2020
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93505
--- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Still bisecting it, but I'd say the bug is in expand_binop:
/* If we were trying to rotate, and that didn't work, try rotating
the other direction before falling back to shifts and bitwise-or. */
if (((binoptab == rotl_optab
&& (icode = optab_handler (rotr_optab, mode)) != CODE_FOR_nothing)
|| (binoptab == rotr_optab
&& (icode = optab_handler (rotl_optab, mode)) != CODE_FOR_nothing))
&& is_int_mode (mode, &int_mode))
{
optab otheroptab = (binoptab == rotl_optab ? rotr_optab : rotl_optab);
rtx newop1;
unsigned int bits = GET_MODE_PRECISION (int_mode);
if (CONST_INT_P (op1))
newop1 = gen_int_shift_amount (int_mode, bits - INTVAL (op1));
else if (targetm.shift_truncation_mask (int_mode) == bits - 1)
newop1 = negate_rtx (GET_MODE (op1), op1);
else
newop1 = expand_binop (GET_MODE (op1), sub_optab,
gen_int_mode (bits, GET_MODE (op1)), op1,
NULL_RTX, unsignedp, OPTAB_DIRECT);
temp = expand_binop_directly (icode, int_mode, otheroptab, op0, newop1,
target, unsignedp, methods, last);
if (temp)
return temp;
}
The above is wrong if op1 is or might be 0 and targetm.shift_truncation_mask
(int_mode) != bits - 1,
because for original valid rotate by 0 it will create invalid rotate in the
other direction by bits
which is out of bounds rotation count.
So, I'd say we should either mask the result of subtraction with bits - 1, or
perhaps better
do a negate + and, i.e. -op1 & (bits - 1).
More information about the Gcc-bugs
mailing list