https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92656
--- Comment #2 from Segher Boessenkool <segher at gcc dot gnu.org> --- Trying 104 -> 105: 104: r125:SI=zero_extend(r101:SI#0) REG_DEAD r101:SI 105: r127:SI={(r100:SI!=0)?r125:SI:r79:SI} REG_DEAD r125:SI REG_DEAD r100:SI REG_DEAD r79:SI Failed to match this instruction: (set (reg/v:SI 127 [ result ]) (if_then_else:SI (ne (reg:SI 100) (const_int 0 [0])) (zero_extend:SI (subreg:HI (reg:SI 101) 0)) (reg/v:SI 79 [ result ]))) Failed to match this instruction: (set (reg/v:SI 127 [ result ]) (if_then_else:SI (ne (reg:SI 100) (const_int 0 [0])) (and:SI (reg:SI 101) (const_int 65535 [0xffff])) (reg/v:SI 79 [ result ]))) Combine does not know r101 has all the high bits clear, apparently. r101 is formed via insn_cost 4 for 77: r94:SI=0x4000 insn_cost 4 for 78: r93:SI=r94:SI+0x2 REG_DEAD r94:SI REG_EQUAL 0x4002 insn_cost 8 for 24: r79:SI=zero_extend(r95:SI#0) REG_DEAD r95:SI insn_cost 4 for 103: r101:SI=r79:SI^r93:SI (insn 24 is a HImode subreg), so it could have seen that. But the way nonzero bits are tracked is not very predictable or dependable (it depends on the order that combine looks at insns, which changes if insns combine where they didn't before, etc.) This whole nonzero_bits thing should be handled by dataflow.