But it *does* try to match an intermediate pattern,
(set (reg:CCGC 17 flags)
(compare:CCGC (reg:CCGC 17 flags)
(const_int 0 [0])))
which can be considered a no-op move. If I add the attached pattern, then the
combination happens in two steps -- 9->12, 12->13 -- and we get what we hoped:
Jeff or Segher, is it worth complicating the can_combine_p test near line 1958
/* Make sure that the value that is to be substituted for the register
does not use any registers whose values alter in between. However,
If the insns are adjacent, a use can't cross a set even though we
think it might (this can happen for a sequence of insns each setting
the same destination; last_set of that register might point to
a NOTE). If INSN has a REG_EQUIV note, the register is always
equivalent to the memory so the substitution is valid even if there
are intervening stores. Also, don't move a volatile asm or
UNSPEC_VOLATILE across any other insns. */
|| (! all_adjacent
&& (((!MEM_P (src)
|| ! find_reg_note (insn, REG_EQUIV, src))
&& use_crosses_set_p (src, DF_INSN_LUID (insn)))
|| (GET_CODE (src) == ASM_OPERANDS && MEM_VOLATILE_P (src))
|| GET_CODE (src) == UNSPEC_VOLATILE))
to notice that the set is one of SUCC or SUCC2, and is thus included in the
insns being combined? That does seem cleaner and more general than the hacky
i386 nop_cmp pattern, but would certainly require tons more testing...