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)