http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46316
--- Comment #16 from davidxl <xinliangli at gmail dot com> 2010-11-08 08:18:31 UTC --- The revised patch: Index: gcc/tree-vrp.c =================================================================== --- gcc/tree-vrp.c (revision 166426) +++ gcc/tree-vrp.c (working copy) @@ -3403,13 +3403,18 @@ adjust_range_with_scev (value_range_t *v { value_range_t maxvr = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL }; double_int dtmp; - dtmp = double_int_mul (tree_to_double_int (step), - double_int_sub (loop->nb_iterations_upper_bound, - double_int_one)); + bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (step)); + int overflow = 0; + + dtmp = double_int_mul_with_sign (tree_to_double_int (step), + double_int_sub ( + loop->nb_iterations_upper_bound, + double_int_one), + unsigned_p, &overflow); tem = double_int_to_tree (TREE_TYPE (init), dtmp); /* If the multiplication overflowed we can't do a meaningful adjustment. */ - if (double_int_equal_p (dtmp, tree_to_double_int (tem))) + if (!overflow && double_int_equal_p (dtmp, tree_to_double_int (tem))) { extract_range_from_binary_expr (&maxvr, PLUS_EXPR, TREE_TYPE (init), init, tem); Index: gcc/double-int.c =================================================================== --- gcc/double-int.c (revision 166426) +++ gcc/double-int.c (working copy) @@ -718,6 +718,19 @@ double_int_mul (double_int a, double_int return ret; } +/* Returns A * B. If the operation overflows according to UNSIGNED_P, + *OVERFLOW is set to nonzero. */ + +double_int +double_int_mul_with_sign (double_int a, double_int b, + bool unsigned_p, int *overflow) +{ + double_int ret; + *overflow = mul_double_with_sign (a.low, a.high, b.low, b.high, + &ret.low, &ret.high, unsigned_p); + return ret; +} + /* Returns A + B. */ double_int Index: gcc/double-int.h =================================================================== --- gcc/double-int.h (revision 166426) +++ gcc/double-int.h (working copy) @@ -132,6 +132,7 @@ double_int_fits_in_uhwi_p (double_int cs 2 * HOST_BITS_PER_WIDE_INT bits. */ double_int double_int_mul (double_int, double_int); +double_int double_int_mul_with_sign (double_int, double_int, bool, int *); double_int double_int_add (double_int, double_int); double_int double_int_sub (double_int, double_int); double_int double_int_neg (double_int);