https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64993
Bug ID: 64993 Summary: Missed ccmp optimization with simple code Product: gcc Version: 5.0 Status: UNCONFIRMED Severity: enhancement Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: pinskia at gcc dot gnu.org Take: int foo_c (int a, int b) { if (a > 9 && b < 34) return 4; else return 26; } --- CUT --- Currently we produce: foo_c: cmp w0, 9 mov w0, 33 ccmp w1, w0, 0, gt mov w2, 4 cset w1, le mov w0, 26 cmp w1, wzr csel w0, w2, w0, ne ret But the cset/cmp is not needed. The reason is the following check is false: It is failing this check: /* 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)) --- CUT --- If we have: int foo_c (int a, int b, int c, int d) { if (a > 9 && b < 34) return c; else return d; } --- CUT --- the cset/cmp is optimized away.