https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81423
--- Comment #3 from Uroš Bizjak <ubizjak at gmail dot com> --- Following is a c testcase: --cut here-- unsigned long long int ll = 0; unsigned long long int ull1 = 1ULL; unsigned long long int ull2 = 12008284144813806346ULL; unsigned long long int ull3; void foo () { ll = -5597998501375493990LL; ll = (5677365550390624949L - ll) - (ull1 > 0); ull3 = (unsigned int) (2067854353L << (((ll + -2129105131L) ^ 10280750144413668236ULL) - 10280750143997242009ULL)) >> ((2873442921854271231ULL | ull2) - 12098357307243495419ULL); } int main () { foo (); printf ("%llu expected 3998784)\n", ull3); printf ("%x expected 3d0440)\n", ull3); return 0; } --cut here-- The problem is in combine pass, which combines following sequence in the main function: (insn 17 16 18 2 (parallel [ (set (reg:SI 114) (ior:SI (subreg:SI (reg:DI 113 [ ull2 ]) 0) (const_int -8651009 [0xffffffffff7bfeff]))) (clobber (reg:CC 17 flags)) ]) "pr81423.c":15 415 {*iorsi_1} (expr_list:REG_DEAD (reg:DI 113 [ ull2 ]) (expr_list:REG_UNUSED (reg:CC 17 flags) (nil)))) (insn 18 17 19 2 (parallel [ (set (reg:SI 115) (plus:SI (reg:SI 114) (const_int 5 [0x5]))) (clobber (reg:CC 17 flags)) ]) "pr81423.c":16 217 {*addsi_1} (expr_list:REG_DEAD (reg:SI 114) (expr_list:REG_UNUSED (reg:CC 17 flags) (nil)))) (insn 19 18 20 2 (parallel [ (set (reg:SI 116) (lshiftrt:SI (subreg:SI (reg:DI 111) 0) (subreg:QI (reg:SI 115) 0))) (clobber (reg:CC 17 flags)) ]) "pr81423.c":15 544 {*lshrsi3_1} (expr_list:REG_DEAD (reg:SI 115) (expr_list:REG_DEAD (reg:DI 111) (expr_list:REG_UNUSED (reg:CC 17 flags) (nil))))) (insn 20 19 21 2 (set (reg:DI 103 [ _20 ]) (zero_extend:DI (reg:SI 116))) "pr81423.c":15 131 {*zero_extendsidi2} (expr_list:REG_DEAD (reg:SI 116) (nil))) Trying 17, 18, 19 -> 20: Failed to match this instruction: (set (reg:DI 103 [ _20 ]) (zero_extract:DI (reg:DI 111) (const_int 32 [0x20]) (const_int 4 [0x4]))) Failed to match this instruction: (set (reg:DI 103 [ _20 ]) (and:DI (lshiftrt:DI (reg:DI 111) (const_int 4 [0x4])) (const_int 4294967295 [0xffffffff]))) Successfully matched this instruction: (set (reg:DI 116) (ashift:DI (reg:DI 111) (const_int 28 [0x1c]))) Successfully matched this instruction: (set (reg:DI 103 [ _20 ]) (lshiftrt:DI (reg:DI 116) (const_int 32 [0x20]))) allowing combination of insns 17, 18, 19 and 20 original costs 6 + 4 + 4 + 1 = 15 replacement costs 4 + 4 = 8 deferring deletion of insn with uid = 18. deferring deletion of insn with uid = 17. deferring deletion of insn with uid = 16. modifying insn i2 19: {r116:DI=r111:DI<<0x1c;clobber flags:CC;} REG_UNUSED flags:CC REG_DEAD r111:DI deferring rescan insn with uid = 19. modifying insn i3 20: {r103:DI=r116:DI 0>>0x20;clobber flags:CC;} REG_UNUSED flags:CC REG_DEAD r116:DI deferring rescan insn with uid = 20. Please note that we have in the original sequence: (insn 19 18 20 2 (parallel [ (set (reg:SI 116) (lshiftrt:SI (subreg:SI (reg:DI 111) 0) (subreg:QI (reg:SI 115) 0))) (clobber (reg:CC 17 flags)) ]) "pr81423.c":15 544 {*lshrsi3_1} (expr_list:REG_DEAD (reg:SI 115) (expr_list:REG_DEAD (reg:DI 111) (expr_list:REG_UNUSED (reg:CC 17 flags) (nil))))) in effect, this insn is shifting value, truncated to 32 bits, from rax 0x1ed03d04400 2117482857472 by 4 via: 0x0000000000400557 <+71>: add $0x5,%ecx 0x000000000040055a <+74>: shr %cl,%eax resulting in: rax 0x3d0440 3998784 rcx 0x4 4 However, combine tries to create: (set (reg:DI 103 [ _20 ]) (zero_extract:DI (reg:DI 111) (const_int 32 [0x20]) (const_int 4 [0x4]))) trying to extract 32bit value from position 4. This is not correct, due to 32bit left shift in the sequence, the combined insn should zero-extract 28 bits only.