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).