https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81914
--- Comment #6 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Another testcase, which has even higher prediction of not returning -1:
int
cmp (int a, int b)
{
if (a < b)
return -1;
if (a > b)
return 1;
return 0;
}
In the #c0 case, we have in the IL:
<bb 2> :
if (a_3(D) >= b_4(D))
goto <bb 3>; [INV]
else
goto <bb 4>; [INV]
<bb 3> :
_1 = a_3(D) > b_4(D);
iftmp.0_6 = (int) _1;
<bb 4> :
# iftmp.0_2 = PHI <iftmp.0_6(3), -1(2)>
return iftmp.0_2;
while in this one:
<bb 2>:
if (a_2(D) < b_3(D))
goto <bb 5>;
else
goto <bb 3>;
<bb 3>:
if (a_2(D) > b_3(D))
goto <bb 5>;
else
goto <bb 4>;
<bb 4>:
<bb 5>:
# _1 = PHI <-1(2), 1(3), 0(4)>
return _1;
In any case, I think it is worth recognizing these patterns.
We should also consider other examples, e.g. from gcc itself:
static int
oecount_cmp (const void *p1, const void *p2)
{
const oecount *c1 = (const oecount *)p1;
const oecount *c2 = (const oecount *)p2;
if (c1->cnt != c2->cnt)
return c1->cnt > c2->cnt ? 1 : -1;
else
/* If counts are identical, use unique IDs to stabilize qsort. */
return c1->id > c2->id ? 1 : -1;
}
static int
tm_alias_pair_cmp (const void *x, const void *y)
{
const tm_alias_pair *p1 = (const tm_alias_pair *) x;
const tm_alias_pair *p2 = (const tm_alias_pair *) y;
if (p1->uid < p2->uid)
return -1;
if (p1->uid > p2->uid)
return 1;
return 0;
}
int
type_warning_cmp (const void *p1, const void *p2)
{
const odr_type_warn_count *t1 = (const odr_type_warn_count *)p1;
const odr_type_warn_count *t2 = (const odr_type_warn_count *)p2;
if (t1->dyn_count < t2->dyn_count)
return 1;
if (t1->dyn_count > t2->dyn_count)
return -1;
return t2->count - t1->count;
}
static int
stack_var_cmp (const void *a, const void *b)
{
size_t ia = *(const size_t *)a;
size_t ib = *(const size_t *)b;
unsigned int aligna = stack_vars[ia].alignb;
unsigned int alignb = stack_vars[ib].alignb;
HOST_WIDE_INT sizea = stack_vars[ia].size;
HOST_WIDE_INT sizeb = stack_vars[ib].size;
tree decla = stack_vars[ia].decl;
tree declb = stack_vars[ib].decl;
bool largea, largeb;
unsigned int uida, uidb;
/* Primary compare on "large" alignment. Large comes first. */
largea = (aligna * BITS_PER_UNIT > MAX_SUPPORTED_STACK_ALIGNMENT);
largeb = (alignb * BITS_PER_UNIT > MAX_SUPPORTED_STACK_ALIGNMENT);
if (largea != largeb)
return (int)largeb - (int)largea;
/* Secondary compare on size, decreasing */
if (sizea > sizeb)
return -1;
if (sizea < sizeb)
return 1;
/* Tertiary compare on true alignment, decreasing. */
if (aligna < alignb)
return -1;
if (aligna > alignb)
return 1;
/* Final compare on ID for sort stability, increasing.
Two SSA names are compared by their version, SSA names come before
non-SSA names, and two normal decls are compared by their DECL_UID. */
if (TREE_CODE (decla) == SSA_NAME)
{
if (TREE_CODE (declb) == SSA_NAME)
uida = SSA_NAME_VERSION (decla), uidb = SSA_NAME_VERSION (declb);
else
return -1;
}
else if (TREE_CODE (declb) == SSA_NAME)
return 1;
else
uida = DECL_UID (decla), uidb = DECL_UID (declb);
if (uida < uidb)
return 1;
if (uida > uidb)
return -1;
return 0;
}
etc. Perhaps catching everything is too hard for heuristics, but at least
figuring a pattern of these <=> comparisons, or consecutive comparisons like:
if (uida < uidb)
return 1;
if (uida > uidb)
return -1;
is highly desirable.