On Wed, Aug 22, 2012 at 1:55 PM, Marc Glisse <marc.gli...@inria.fr> wrote: > Hello, > > when I adapted VRP PLUS_EXPR handling for __int128, I missed one place where > double_int can overflow. Note that I have no idea if that helps for bug > 54317, but that's where I noticed the issue.
Ok. Thanks, Richard. > 2012-08-21 Marc Glisse <marc.gli...@inria.fr> > > PR tree-optimization/54317 > > gcc/ > * tree-vrp.c (extract_range_from_binary_expr_1): Test for > double_int overflow. > Remove dead tests. > > gcc/testsuite/ > * gcc.dg/tree-ssa/vrp79.c: New testcase. > > -- > Marc Glisse > Index: testsuite/gcc.dg/tree-ssa/vrp79.c > =================================================================== > --- testsuite/gcc.dg/tree-ssa/vrp79.c (revision 0) > +++ testsuite/gcc.dg/tree-ssa/vrp79.c (revision 0) > @@ -0,0 +1,23 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-optimized" } */ > + > +#ifdef __SIZEOF_INT128__ > +typedef unsigned __int128 NT; > +#else > +typedef unsigned long long NT; > +#endif > + > +extern void do_not_go_away (); > + > +void f (NT x, NT y) > +{ > + NT n = 1; > + n <<= (8 * sizeof (NT) - 1); > + if (x > n) return; > + if (y > n) return; > + NT z = x + y; > + if (z == 42) do_not_go_away (); > +} > + > +/* { dg-final { scan-tree-dump "do_not_go_away" "optimized" } } */ > +/* { dg-final { cleanup-tree-dump "optimized" } } */ > > Property changes on: testsuite/gcc.dg/tree-ssa/vrp79.c > ___________________________________________________________________ > Added: svn:keywords > + Author Date Id Revision URL > Added: svn:eol-style > + native > > Index: tree-vrp.c > =================================================================== > --- tree-vrp.c (revision 190590) > +++ tree-vrp.c (working copy) > @@ -2467,32 +2467,35 @@ extract_range_from_binary_expr_1 (value_ > && max_ovf == 1) > { > /* Underflow and overflow, drop to VR_VARYING. */ > set_value_range_to_varying (vr); > return; > } > else > { > /* Min underflow or max overflow. The range kind > changes to VR_ANTI_RANGE. */ > + bool covers = false; > double_int tem = tmin; > gcc_assert ((min_ovf == -1 && max_ovf == 0) > || (max_ovf == 1 && min_ovf == 0)); > type = VR_ANTI_RANGE; > tmin = double_int_add (tmax, double_int_one); > + if (double_int_cmp (tmin, tmax, uns) < 0) > + covers = true; > tmax = double_int_add (tem, double_int_minus_one); > + if (double_int_cmp (tmax, tem, uns) > 0) > + covers = true; > /* If the anti-range would cover nothing, drop to varying. > Likewise if the anti-range bounds are outside of the > types values. */ > - if (double_int_cmp (tmin, tmax, uns) > 0 > - || double_int_cmp (tmin, type_min, uns) < 0 > - || double_int_cmp (tmax, type_max, uns) > 0) > + if (covers || double_int_cmp (tmin, tmax, uns) > 0) > { > set_value_range_to_varying (vr); > return; > } > min = double_int_to_tree (expr_type, tmin); > max = double_int_to_tree (expr_type, tmax); > } > } > else > { >