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