https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118638
--- Comment #22 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The releases/gcc-14 branch has been updated by Jakub Jelinek <ja...@gcc.gnu.org>: https://gcc.gnu.org/g:1dac899a10581dbcd55144456cca92d061190762 commit r14-11289-g1dac899a10581dbcd55144456cca92d061190762 Author: Jakub Jelinek <ja...@redhat.com> Date: Tue Jan 28 10:14:05 2025 +0100 combine: Fix up make_extraction [PR118638] The following testcase is miscompiled at -Os on x86_64-linux. The problem is during make_compound_operation of (ashiftrt:SI (ashift:SI (mult:SI (reg:SI 107 [ a_5 ]) (const_int 3 [0x3])) (const_int 31 [0x1f])) (const_int 31 [0x1f])) where it incorrectly returns (mult:SI (sign_extract:SI (reg:SI 107 [ a_5 ]) (const_int 2 [0x2]) (const_int 0 [0])) (const_int 3 [0x3])) which isn't obviously true, the former returns either 0 or -1 depending on the least significant bit of the multiplication, the latter returns either 0 or -3 depending on the second least significant bit of the multiplication argument. The bug has been introduced in PR96998 r11-4563, which added handling of x * (2^N) similar to x << N. In the above case, pos is 0 and len is 1, sign extracting a single least significant bit of the multiplication. As 3 is not a power of 2, shift_amt is -1. But IN_RANGE (-1, 1, 1 - 1) is still true, because the basic requirement of IN_RANGE that LOWER is not greater than UPPER is violated. The intention of using 1 as LOWER is to avoid matching multiplication by 1, that really shouldn't appear in the IL. But to avoid violating IN_RANGE requirement, we need to verify that len is at least 2. I've added this len > 1 check to the inner if rather than outer because I think for GCC 16 we should add a further optimization. In the particular case of 1 least significant bit sign extraction from multiplication by 3, we could actually say it is equivalent to (sign_extract:SI (reg:SI 107 [ a_5 ]) (const_int 1 [0x2]) (const_int 0 [0])) That is because 3 is an odd number and multiplication by 2 will yield the least significant bit 0 (we are sign extracting just one) and so the multiplication doesn't change anything on the outcome. More generally, even for larger len, multiplication by C which is (1 << X) + 1 where X is >= len should be optimizable just to extraction of the multiplicand's least significant len bits. 2025-01-28 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/118638 * combine.cc (make_extraction): Only optimize (mult x 2^n) if len is larger than 1. * gcc.c-torture/execute/pr118638.c: New test. (cherry picked from commit b529a417249335724d1f74bcf3167f6f9a623823)