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...

Reply via email to