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