https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93505
--- Comment #11 from Jakub Jelinek <jakub at gcc dot gnu.org> --- As for the expand_binop bug, if I fix it like: --- gcc/optabs.c.jj 2020-01-12 11:54:36.690409230 +0100 +++ gcc/optabs.c 2020-01-30 16:05:43.520649234 +0100 @@ -1226,16 +1226,22 @@ expand_binop (machine_mode mode, optab b unsigned int bits = GET_MODE_PRECISION (int_mode); if (CONST_INT_P (op1)) - newop1 = gen_int_shift_amount (int_mode, bits - INTVAL (op1)); + newop1 + = gen_int_shift_amount (int_mode, (bits - UINTVAL (op1)) % bits); 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, + else if (pow2p_hwi (bits)) + newop1 = expand_binop (GET_MODE (op1), and_optab, + negate_rtx (GET_MODE (op1), op1), + gen_int_mode (bits - 1, GET_MODE (op1)), NULL_RTX, unsignedp, OPTAB_DIRECT); + else + newop1 = NULL_RTX; - temp = expand_binop_directly (icode, int_mode, otheroptab, op0, newop1, - target, unsignedp, methods, last); + temp = NULL_RTX; + if (newop1) + temp = expand_binop_directly (icode, int_mode, otheroptab, op0, newop1, + target, unsignedp, methods, last); if (temp) return temp; } then unfortunately given -O2 on unsigned int bar (unsigned int x, int y) { return x >> y | x << (-y & 31); } powerpc64le-linux emitted assembly changes like: bar: .LFB1: .cfi_startproc - subfic 4,4,32 + neg 4,4 + rlwinm 4,4,0,27,31 rotlw 3,3,4 blr Given unsigned int baz (unsigned int x, int y) { y &= 31; return x >> y | x << (-y & 31); } the change is: bar: .LFB1: .cfi_startproc + neg 4,4 rlwinm 4,4,0,27,31 - subfic 4,4,32 rotlw 3,3,4 blr and so I'd say even if we just don't fix expand_binop, this shows an optimization opportunity for the rs6000 backend if the rotlw instruction only uses bottom 5 bits from the last operand.