https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79123
--- Comment #2 from Aldy Hernandez <aldyh at gcc dot gnu.org> ---
[Just thinking out loud here.]
Yeah. There's no correct range information available. For the argument to
alloca we have:
# RANGE ~[2305843009213693952, 16140901064495857663]
n_9 = (long unsigned int) _4;
if (n_9 <= 104)
goto <bb 3>; [36.64%]
else
goto <bb 5>; [63.36%]
<bb 5> [63.36%]:
goto <bb 4>; [100.00%]
<bb 3> [36.64%]:
_5 = __builtin_alloca (n_9);
And the anti range of ~[2305843009213693952, 16140901064495857663] can hold a
value that is greater than 100 because it is essentially:
(gdb) p/x 2305843009213693952-1
$4 = 0x1fffffffffffffff
[0..0x1fffffffffffffff] and the union of whatever comes after
16140901064495857663.
We do a horrible job dealing with VR_ANTI_RANGE's. As you point out, we're
basically punting on an VR_ANTI_RANGE and ignoring that the casted result (n_9)
has a bound later on:
else if (range_type == VR_ANTI_RANGE)
{
// There may be some wrapping around going on. Catch it
// with this heuristic. Hopefully, this VR_ANTI_RANGE
// nonsense will go away, and we won't have to catch the
// sign conversion problems with this crap.
if (cast_from_signed_p (len, invalid_casted_type))
return alloca_type_and_limit (ALLOCA_CAST_FROM_SIGNED);
}
The above code was there to handle simple cases like:
int n;
...
if (n < 2000)
{
p = __builtin_alloca (n);
f (p);
}
where we have a VR_ANTI_RANGE leading to a cast
<bb 3> [36.64%]:
# RANGE ~[2000, 18446744071562067967]
_1 = (long unsigned int) n_3(D);
p_6 = __builtin_alloca (_1);
...but the casted result (_1) has no known bound so this can be diagnosed.
What we should do is somehow realize that in the original testcase, the casted
result has a known bound, and perhaps punt down to the code that checks the
BB's leading up to the alloca use:
// If we couldn't find anything, try a few heuristics for things we
// can easily determine. Check these misc cases but only accept
// them if all predecessors have a known bound.
Oh that we had better range info...