On Fri, Jan 20, 2017 at 11:52 AM, Aldy Hernandez <al...@redhat.com> wrote:
> On 01/20/2017 03:17 AM, Richard Biener wrote:
>>
>> On Thu, Jan 19, 2017 at 5:53 PM, Martin Sebor <mse...@gmail.com> wrote:
>>>
>>> On 01/19/2017 05:45 AM, Richard Biener wrote:
>>>>
>>>>
>>>> On Thu, Jan 19, 2017 at 1:17 PM, Aldy Hernandez <al...@redhat.com>
>>>> wrote:
>>>>>
>>>>>
>>>>> In the attached testcase, we have a clearly bounded case of alloca
>>>>> which
>>>>> is
>>>>> being incorrectly reported:
>>>>>
>>>>> void g (int *p, int *q)
>>>>> {
>>>>>    size_t n = (size_t)(p - q);
>>>>>
>>>>>    if (n < 10)
>>>>>      f (__builtin_alloca (n));
>>>>> }
>>>>>
>>>>> The problem is that VRP gives us an anti-range for `n' which may be out
>>>>> of
>>>>> range:
>>>>>
>>>>>   # RANGE ~[2305843009213693952, 16140901064495857663]
>>>>>    n_9 = (long unsigned int) _4;
>>>>>
>>>>> We do a less than stellar job with casts and VR_ANTI_RANGE's, mostly
>>>>> because
>>>>> we're trying various heuristics to make up for the fact that we have
>>>>> crappy
>>>>> range info from VRP.  More specifically, we're basically punting on an
>>>>> VR_ANTI_RANGE and ignoring that the casted result (n_9) has a bound
>>>>> later
>>>>> on.
>>>>>
>>>>> Luckily, we already have code to check simple ranges coming into the
>>>>> alloca
>>>>> by looking into all the basic blocks feeding it.  The attached patch
>>>>> delays
>>>>> the final decision on anti ranges until we have examined the basic
>>>>> blocks
>>>>> and determined for that we are definitely out of range.
>>>>>
>>>>> I expect all this to disappear with Andrew's upcoming range info
>>>>> overhaul.
>>>>>
>>>>> OK for trunk?
>>>>
>>>>
>>>>
>>>> I _really_ wonder why all the range consuming warnings are not emitted
>>>> from VRP itself (like we do for -Warray-bounds).  There we'd still see
>>>> a range for the argument derived from the if () rather than needing to
>>>> do our own mini-VRP from the needessly "incomplete" range-info on
>>>> SSA vars.
>>>
>>>
>>>
>>> Can you explain why the range info is only available in VRP and
>>> not outside, via the get_range_info() API?  It sounds as though
>>> the API shouldn't be relied on (it was virtually unused before
>>> GCC 7).
>>
>>
>> It's very simple.  Look at the testcase from above
>>
>> void g (int *p, int *q)
>> {
>>    size_t n = (size_t)(p - q);
>>
>>    if (n < 10)
>>      f (__builtin_alloca (n));
>> }
>>
>> The IL outside of VRP is
>>
>>   <bb 2> [100.00%]:
>>   p.0_1 = (long int) p_7(D);
>>   q.1_2 = (long int) q_8(D);
>>   _3 = p.0_1 - q.1_2;
>>   _4 = _3 /[ex] 4;
>>   n_9 = (size_t) _4;
>>   if (n_9 <= 9)
>>     goto <bb 3>; [36.64%]
>>   else
>>     goto <bb 4>; [63.36%]
>>
>>   <bb 3> [36.64%]:
>>   _5 = __builtin_alloca (n_9);
>>   f (_5);
>>
>> so there is no SSA name we can tack a range to covering the n_9 <= 9
>> condition that dominates __builtin_alloca.  Inside VRP we have
>>
>>   <bb 2> [100.00%]:
>>   p.0_1 = (long int) p_7(D);
>>   q.1_2 = (long int) q_8(D);
>>   _3 = p.0_1 - q.1_2;
>>   _4 = _3 /[ex] 4;
>>   n_9 = (size_t) _4;
>>   if (n_9 <= 9)
>>     goto <bb 3>; [36.64%]
>>   else
>>     goto <bb 4>; [63.36%]
>>
>>   <bb 3> [36.64%]:
>>   n_13 = ASSERT_EXPR <n_9, n_9 <= 9>;
>>   _5 = __builtin_alloca (n_13);
>>   f (_5);
>>
>> and viola - now the alloca call uses n_13 which is defined at a point
>> dominated by if (n_9 <= 9) and thus it has an improved range:
>>
>> n_13: [0, 9]  EQUIVALENCES: { n_9 } (1 elements)
>
>
> Yes, I remember getting much better range information when doing things
> within VRP2, however since VRP2 runs after jump threading sometimes I'd get
> more false positives.
>
> Tell you what, for GCC8 I volunteer to rewrite gimple-ssa-warn-alloca.c
> within VRP (or using whatever range information we decide upon or is ready
> for GCC8).  In the meantime, can we fix the PR with my patch (or a similar
> approach)?

Sure.

Richard.

> Aldy

Reply via email to