http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46316
--- Comment #13 from davidxl <xinliangli at gmail dot com> 2010-11-08 07:13:03 UTC --- (In reply to comment #12) > Won't there be similar problem when using TImode IVs on 64-bit targets (e.g. > __int128 or int __attribute__((mode (TI)))) ? > Normally overflows are detected when doing computations on trees rather than > just in double_int. yes. The following is the fix to this particular problem. Index: tree-vrp.c =================================================================== --- tree-vrp.c (revision 166426) +++ tree-vrp.c (working copy) @@ -3402,24 +3402,34 @@ adjust_range_with_scev (value_range_t *v || get_value_range (init)->type == VR_RANGE)) { 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)); - 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))) - { - extract_range_from_binary_expr (&maxvr, PLUS_EXPR, - TREE_TYPE (init), init, tem); - /* Likewise if the addition did. */ - if (maxvr.type == VR_RANGE) - { - tmin = maxvr.min; - tmax = maxvr.max; - } - } + double_int upper_bound_m1, step_int, dtmp; + bool unsigned_p; + + upper_bound_m1 = double_int_sub (loop->nb_iterations_upper_bound, + double_int_one); + step_int = tree_to_double_int (step); + dtmp = double_int_mul (step_int, upper_bound_m1); + unsigned_p = TYPE_UNSIGNED (TREE_TYPE (step)); + /* Check overflow. */ + if (double_int_equal_p (upper_bound_m1, + double_int_div (dtmp, step_int, + unsigned_p, ROUND_DIV_EXPR))) + { + 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))) + { + extract_range_from_binary_expr (&maxvr, PLUS_EXPR, + TREE_TYPE (init), init, tem); + /* Likewise if the addition did. */ + if (maxvr.type == VR_RANGE) + { + tmin = maxvr.min; + tmax = maxvr.max; + } + } + } } if (vr->type == VR_VARYING || vr->type == VR_UNDEFINED)