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.