[PR,middle-end/79123] cast false positive in -Walloca-larger-than=
diff mbox

Message ID CAFiYyc2J4YTMFwZ_FMRLBZgyP6LOuihTSgOs9tpiwoMGxoyAdA@mail.gmail.com
State New
Headers show

Commit Message

Richard Biener Jan. 24, 2017, 10:11 a.m. UTC
On Mon, Jan 23, 2017 at 4:55 PM, Martin Sebor <msebor@gmail.com> wrote:
>>> Yes, I see that.  But when I change size_t to unsigned int (in LP64)
>>> like so:
>>>
>>>   void g (int *p, int *q)
>>>   {
>>>     unsigned n = (unsigned)(p - q);
>>>
>>>     if (n < 10)
>>>       f (__builtin_alloca (n));
>>>   }
>>>
>>> -Walloca-larger-than=100 still complains:
>>>
>>>   warning: argument to ‘alloca’ may be too large
>>>   note: limit is 100 bytes, but argument may be as large as 4294967295
>>>
>>> and the VRP dump shows
>>>
>>>   _5: [0, 4294967295]
>>>   _14: [0, 4294967295]
>>>   ...
>>>     _3 = p.0_1 - q.1_2;
>>>     _4 = _3 /[ex] 4;
>>>     n_10 = (unsigned int) _4;
>>>     if (n_10 <= 9)
>>>       goto <bb 3>; [36.64%]
>>>     else
>>>       goto <bb 4>; [63.36%]
>>>
>>>     <bb 3> [36.64%]:
>>>     _14 = _4 & 4294967295;
>>>     _5 = (long unsigned int) _14;
>>>     _6 = __builtin_alloca (_5);
>>>
>>> so it seems that even in VRP itself the range information isn't
>>> quite good enough to avoid false positives.  (Perhaps that's one
>>> the missed cases you mention below?)
>>
>>
>> Well, you see that there's no obvious way to use the n_10 <= 9 conditional
>> here.  VRP would need to register a [0, 9] range for the lower half of
>> n_10
>> and then figure after seeing
>>
>>>     _14 = _4 & 4294967295;
>>
>>
>> that _14 is now [0, 9].
>>
>> That's a neat trick VRP cannot handle at the moment (there's no way the
>> lattice can encode a range for a sub-set of all bits of a SSA name).
>
>
> Sure.  My point is just that it looks like there will be some false
> positives whether the warnings are implemented as part of the VRP
> pass or elsewhere.  (I admit I haven't studied the implementation
> of the VRP pass to understand whether these false positives are
> avoidable and I'm happy to take your word if if you say they can.)
>
>> Your source is bogus in the way that (unsigned)(p - q) might truncate
>> the pointer difference.
>
>
> The problem is independent of the pointer difference and can be
> reproduced by any conversion from a wider type to a narrower
> unsigned type (even the safe ones), as the test case in bug 79191
> I opened for it shows:
>
>   void f (unsigned long n)
>   {
>     if (n > 3)
>       __builtin_abort ();
>   }
>
>   void h (unsigned long m)
>   {
>     unsigned n = m;
>
>     if (n < 3)
>       f (n);
>   }

Sure, but that's essentially the same issue:

  <bb 2> [100.00%]:
  n_2 = (unsigned int) m_1(D);
  if (n_2 <= 2)
    goto <bb 3>; [54.00%]
  else
    goto <bb 5>; [46.00%]

  <bb 3> [54.00%]:
  m_6 = ASSERT_EXPR <m_1(D), m_1(D) <= 18446744069414584322>;
  _5 = m_6 & 4294967295;
  if (_5 > 3)

we can't express that m_6 has a known range for bits 0..31.

But of course this shows that the canonicalization of truncation to bit-and
is bad or happening too early.  w/o it we have

  <bb 2> [0.00%]:
  n_4 = (unsigned int) m_3(D);
  if (n_4 <= 2)
    goto <bb 3>; [0.00%]
  else
    goto <bb 5>; [0.00%]

  <bb 3> [100.00%]:
  _1 = (long unsigned int) n_4;
  if (_1 > 3)

which we can perfectly optimize (a much loved single-use test could
have us here).



Richard.

> Martin
>

Patch
diff mbox

Index: gcc/match.pd
===================================================================
--- gcc/match.pd        (revision 244859)
+++ gcc/match.pd        (working copy)
@@ -1840,7 +1840,8 @@  DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
         && final_int && inter_int && inside_int
         && final_prec == inside_prec
         && final_prec > inter_prec
-        && inter_unsignedp)
+        && inter_unsignedp
+        && single_use (@1))
      (convert (bit_and @0 { wide_int_to_tree
                              (inside_type,
                               wi::mask (inter_prec, false,