https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118682
--- Comment #1 from Jakub Jelinek <jakub at gcc dot gnu.org> --- I was thinking about --- gcc/combine.cc.jj 2025-01-28 10:13:59.158871918 +0100 +++ gcc/combine.cc 2025-01-28 10:37:32.160477873 +0100 @@ -7637,6 +7637,15 @@ make_extraction (machine_mode mode, rtx if (new_rtx) return gen_rtx_MULT (mode, new_rtx, XEXP (inner, 1)); } + /* We're extracting the least significant bits of an rtx + (mult X (const_int Y<<Z + 1)), where Z >= LEN. Multiplication + by Y<<Z will guarantee all LEN least significant bits zero, + and so the LEN least significant bits of (mult X (const_int Y<<Z + 1)) + will be equal to LEN least significant bits of X. */ + else if ((INTVAL (XEXP (inner, 1)) & 1) != 0 + && (unsigned) ctz_hwi (INTVAL (XEXP (inner, 1)) - 1) >= len) + return make_extraction (mode, XEXP (inner, 0), 0, 0, len, + unsignedp, in_dest, in_compare); } else if (GET_CODE (inner) == TRUNCATE /* If trying or potentionally trying to extract but maybe this isn't needed. make_extraction later calls force_to_mode which calls force_int_to_mode which for MULT will do the binop stuff, use force_to_mode on the MULT operands. On the X it doesn't really do anything when extracting 1 bit, but on (const_int 3) it returns const1_rtx and so it will try MULT by const1_rtx instead of 3 and simplify_gen_binary simplifies that to just the other operand.