https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126139
Bug ID: 126139
Summary: phiopt does not if-convert half diamonds with multiple
PHIs
Product: gcc
Version: 16.0
Status: UNCONFIRMED
Keywords: missed-optimization
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: ktkachov at gcc dot gnu.org
Target Milestone: ---
734.vpr_r from SPEC2026 has a missed opportunity on GCC (~6%) due to missed
if-conversion for the testcase:
void
minmax (const int *a, int n, int *pmin, int *pmax)
{
int lo = a[0];
int hi = a[0];
for (int i = 1; i < n; i++)
{
int x = a[i];
if (x < lo)
lo = x;
else if (x > hi)
hi = x;
}
*pmin = lo;
*pmax = hi;
}
LLVM generates for aarch64 at -O3:
minmax:
ldr w8, [x0]
cmp w1, #2
b.lt .LBB0_4
mov w10, w1
add x9, x0, #4
sub x11, x10, #1
mov w10, w8
.LBB0_2:
ldr w12, [x9], #4
cmp w12, w10
csel w13, w12, w10, gt
cmp w12, w8
csel w10, w10, w13, lt
csel w8, w12, w8, lt
subs x11, x11, #1
b.ne .LBB0_2
str w8, [x2]
str w10, [x3]
ret
.LBB0_4:
str w8, [x2]
str w8, [x3]
ret
whereas GCC generates fewer CSELs. At late phiopt the GIMPLE looks like this:
if (x_17 < lo_23)
goto <bb 5>; [50.00%]
else
goto <bb 4>; [50.00%]
<bb 4> [local count: 477815112]:
_18 = MAX_EXPR <x_17, hi_25>;
<bb 5>:
# lo_4 = PHI <x_17(3), lo_23(4)>
# hi_6 = PHI <hi_25(3), _18(4)>
RTL if-convert can't catch it because the MIN/MAX expressions in the arms use
cmp+csel and so clobber the flags