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.

Reply via email to