https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126792

            Bug ID: 126792
           Summary: Missed optimisation of FP min/max
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Keywords: missed-optimization
          Severity: enhancement
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: ktkachov at gcc dot gnu.org
  Target Milestone: ---

typedef unsigned char Quantum;
#define Min(x, y) (((x) < (y)) ? (x) : (y))
#define Max(x, y) (((x) > (y)) ? (x) : (y))

/* GraphicsMagick gem.c:997-998.  */
double
f1 (Quantum r, Quantum g, Quantum b)
{
  return (double) Min (r, Min (g, b));
}

double
f2 (Quantum r, Quantum g, Quantum b)
{
  return (double) Max (r, Max (g, b));
}

float
f3 (int a, int b, int c)
{
  return (float) Min (a, Min (b, c));
}

on aarch64 with -O2 GCC generates:
f1:
        and     w1, w1, 255
        and     w2, w2, 255
        cmp     w1, w2
        and     w0, w0, 255
        csel    w3, w1, w2, cc
        cmp     w0, w3, uxtb
        bcs     .L2
        scvtf   d0, w0
        ret
.L2:
        cmp     w2, w1
        bls     .L4
        scvtf   d0, w1
        ret
.L4:
        scvtf   d0, w2
        ret
f2:
        and     w1, w1, 255
        and     w2, w2, 255
        cmp     w1, w2
        and     w0, w0, 255
        csel    w3, w1, w2, hi
        cmp     w0, w3, uxtb
        bls     .L7
        scvtf   d0, w0
        ret
.L7:
        cmp     w2, w1
        bcs     .L9
        scvtf   d0, w1
        ret
.L9:
        scvtf   d0, w2
        ret
f3:
        cmp     w2, w1
        csel    w3, w2, w1, le
        cmp     w3, w0
        ble     .L11
        scvtf   s0, w0
        ret
.L11:
        cmp     w2, w1
        ble     .L13
        scvtf   s0, w1
        ret
.L13:
        scvtf   s0, w2
        ret

LLVM generates:
f1:
        and     w8, w2, #0xff
        and     w9, w1, #0xff
        and     w10, w0, #0xff
        cmp     w9, w8
        csel    w8, w9, w8, lo
        cmp     w10, w8
        csel    w8, w10, w8, lo
        ucvtf   d0, w8
        ret

f2:
        and     w8, w2, #0xff
        and     w9, w1, #0xff
        and     w10, w0, #0xff
        cmp     w9, w8
        csel    w8, w9, w8, hi
        cmp     w10, w8
        csel    w8, w10, w8, hi
        ucvtf   d0, w8
        ret

f3:
        cmp     w1, w2
        csel    w8, w1, w2, lt
        cmp     w0, w8
        csel    w8, w0, w8, lt
        scvtf   s0, w8
        ret

i.e. LLVM seems to recognise the min/max operations gracefully before doing the
int->fp conversion, GCC gets lost somewhere and generates branches

Reply via email to