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;

Reply via email to