This fixes PR49840 - make sure to properly treat integers as wide as a double-int correctly in range_fits_type_p.
Bootstrapped and tested on i686-linux-gnu, applied to trunk. Richard. 2011-07-26 Richard Guenther <rguent...@suse.de> PR tree-optimization/49840 * tree-vrp.c (range_fits_type_p): Properly handle full double-int precision. Index: gcc/tree-vrp.c =================================================================== *** gcc/tree-vrp.c (revision 176786) --- gcc/tree-vrp.c (working copy) *************** simplify_conversion_using_ranges (gimple *** 7423,7440 **** static bool range_fits_type_p (value_range_t *vr, unsigned precision, bool unsigned_p) { double_int tem; ! /* We can only handle constant ranges. */ if (vr->type != VR_RANGE || TREE_CODE (vr->min) != INTEGER_CST || TREE_CODE (vr->max) != INTEGER_CST) return false; tem = double_int_ext (tree_to_double_int (vr->min), precision, unsigned_p); if (!double_int_equal_p (tree_to_double_int (vr->min), tem)) return false; - tem = double_int_ext (tree_to_double_int (vr->max), precision, unsigned_p); if (!double_int_equal_p (tree_to_double_int (vr->max), tem)) return false; --- 7456,7495 ---- static bool range_fits_type_p (value_range_t *vr, unsigned precision, bool unsigned_p) { + tree src_type; + unsigned src_precision; double_int tem; ! /* We can only handle integral and pointer types. */ ! src_type = TREE_TYPE (vr->min); ! if (!INTEGRAL_TYPE_P (src_type) ! && !POINTER_TYPE_P (src_type)) ! return false; ! ! /* An extension is always fine, so is an identity transform. */ ! src_precision = TYPE_PRECISION (TREE_TYPE (vr->min)); ! if (src_precision < precision ! || (src_precision == precision ! && TYPE_UNSIGNED (src_type) == unsigned_p)) ! return true; ! ! /* Now we can only handle ranges with constant bounds. */ if (vr->type != VR_RANGE || TREE_CODE (vr->min) != INTEGER_CST || TREE_CODE (vr->max) != INTEGER_CST) return false; + /* For precision-preserving sign-changes the MSB of the double-int + has to be clear. */ + if (src_precision == precision + && (TREE_INT_CST_HIGH (vr->min) | TREE_INT_CST_HIGH (vr->max)) < 0) + return false; + + /* Then we can perform the conversion on both ends and compare + the result for equality. */ tem = double_int_ext (tree_to_double_int (vr->min), precision, unsigned_p); if (!double_int_equal_p (tree_to_double_int (vr->min), tem)) return false; tem = double_int_ext (tree_to_double_int (vr->max), precision, unsigned_p); if (!double_int_equal_p (tree_to_double_int (vr->max), tem)) return false;