https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83565
--- Comment #7 from Segher Boessenkool <segher at gcc dot gnu.org> --- (In reply to Sergei Trofimovich from comment #5) > gcc's try_combine() scares me lots :) It's an acquired taste. > Segher, can you guide me here what changes size of zero_extract in here from > 0x1f to 0x20? Trying 23 -> 24: 23: r359:DI=zero_extract(r358:DI,0x1f,0x1) REG_DEAD r358:DI 24: r356:SI#0=r359:DI REG_DEAD r359:DI Successfully matched this instruction: (set (subreg:DI (reg:SI 356 [ off ]) 0) (lshiftrt:DI (reg:DI 358) (const_int 1 [0x1]))) allowing combination of insns 23 and 24 original costs 4 + 4 = 8 replacement cost 4 deferring deletion of insn with uid = 23. modifying insn i3 24: r356:SI#0=r358:DI 0>>0x1 REG_DEAD r358:DI deferring rescan insn with uid = 24. [ ... ] Trying 24 -> 29: 24: r356:SI#0=r358:DI 0>>0x1 REG_DEAD r358:DI 29: r8:SI=r356:SI REG_DEAD r356:SI Successfully matched this instruction: (set (reg:DI 8 r8) (zero_extract:DI (reg:DI 358) (const_int 32 [0x20]) (const_int 1 [0x1]))) allowing combination of insns 24 and 29 original costs 4 + 4 = 8 replacement cost 4 deferring deletion of insn with uid = 24. modifying insn i3 29: r8:DI=zero_extract(r358:DI,0x20,0x1) REG_DEAD r358:DI deferring rescan insn with uid = 29. r358 is known to have the high half zero: 22: r358:DI=r357:SI#0^r341:SI#0 so this is correct. The zero_extract(31,1) is transformed to a shift right, and that then later is transformed to a zero_extract(32,1); there is no transform from 31 to 32 :-) James' patch looks fine fwiw; it's a backend problem.