On Mon, 5 Dec 2016, Jakub Jelinek wrote:

> Hi!
> 
> As shown on the testcase, with K&R definitions and fn prototypes with
> promoted types, we can end up computing caller's value ranges in wider
> type than the parameter actually has in the function.
> The problem with that is that wide_int_storage::from can actually wrap
> around, so either as in the testcase we end up with invalid range (minimum
> larger than maximum), or just with a range that doesn't cover all the values
> the parameter can have.
> The patch punts if the range bounds cast to type aren't equal to the
> original values.  Similarly (just theoretical), for pointers it only
> optimizes if the caller's precision as at most as wide as the pointer,
> if it would be wider, even ~[0, 0] range could actually be a NULL pointer
> (some multiple of ~(uintptr_t)0 + (uintmax_t) 1).
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Ok, but I wonder whether this also addresses PR78365 which has a
patch pending (to be reviewed by IPA maintainers) that makes propagation
across such calls more sensible by recording type information in
the jump functions.

Thanks,
Richard.

> 2016-12-05  Jakub Jelinek  <ja...@redhat.com>
> 
>       PR tree-optimization/78681
>       * ipa-prop.c (ipcp_update_vr): Punt if vr[i].min precision is bigger
>       then type's precision and vr[i].min or vr[i].max in type would wrap.
> 
>       * gcc.c-torture/compile/pr78681.c: New test.
> 
> --- gcc/ipa-prop.c.jj 2016-11-25 18:11:05.000000000 +0100
> +++ gcc/ipa-prop.c    2016-12-05 18:48:48.853882864 +0100
> @@ -5709,8 +5709,23 @@ ipcp_update_vr (struct cgraph_node *node
>       {
>         tree type = TREE_TYPE (ddef);
>         unsigned prec = TYPE_PRECISION (type);
> +       unsigned mprec = wi::get_precision (vr[i].min);
> +       gcc_assert (mprec == wi::get_precision (vr[i].max));
>         if (INTEGRAL_TYPE_P (TREE_TYPE (ddef)))
>           {
> +           if (prec < mprec)
> +             {
> +               /* If there is a disagreement between callers and callee
> +                  on the argument type, e.g. when using K&R function
> +                  definitions, punt if vr[i].min or vr[i].max are outside
> +                  of type's precision.  */
> +               wide_int m = wi::ext (vr[i].min, prec, TYPE_SIGN (type));
> +               if (m != vr[i].min)
> +                 continue;
> +               m = wi::ext (vr[i].max, prec, TYPE_SIGN (type));
> +               if (m != vr[i].max)
> +                 continue;
> +             }
>             if (dump_file)
>               {
>                 fprintf (dump_file, "Setting value range of param %u ", i);
> @@ -5729,6 +5744,7 @@ ipcp_update_vr (struct cgraph_node *node
>           }
>         else if (POINTER_TYPE_P (TREE_TYPE (ddef))
>                  && vr[i].type == VR_ANTI_RANGE
> +                && mprec <= prec
>                  && wi::eq_p (vr[i].min, 0)
>                  && wi::eq_p (vr[i].max, 0))
>           {
> --- gcc/testsuite/gcc.c-torture/compile/pr78681.c.jj  2016-12-05 
> 19:51:15.353646309 +0100
> +++ gcc/testsuite/gcc.c-torture/compile/pr78681.c     2016-12-05 
> 19:50:57.000000000 +0100
> @@ -0,0 +1,27 @@
> +/* PR tree-optimization/78681 */
> +
> +struct S { char b; };
> +char d, e, f, l, m;
> +struct S n;
> +int bar (char, char);
> +static void foo (struct S *, int, int, int, int);
> +
> +static void
> +foo (x, g, h, i, j)
> +  struct S *x;
> +  char g, h, i, j;
> +{
> +  char k;
> +  for (k = 0; k <= j; k++)
> +    if (bar (g, k))
> +      for (; i; k++)
> +     if (d)
> +       x->b = g;
> +}
> +
> +void
> +baz (int q)
> +{
> +  foo (&n, m, l, f, 1);
> +  foo (&n, m, e, f, e - 1);
> +}
> 
>       Jakub
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 
21284 (AG Nuernberg)

Reply via email to