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