This removes one weakness in BIT_IOR_EXPR handling which gives
up even if we can compute a fully negative range.  The following
thus extends zero_nonzero_bits_from_vr to extract sign-bit
information (I believe that's the only bit we know sth about
when both vr.min and vr.max are negative).  It also adjusts
BIT_IOR_EXPR handling to not give up for the min < max < 0 case.

Boostrapped on x86_64-unknown-linux-gnu, testing in progress.

I guess BIT_AND_EXPR handling will show a similar weakness but
a similar testcase (as added below) already passes.  So I suppose
we have to obfuscate it a bit more ;)

Richard.

2011-08-05  Richard Guenther  <rguent...@suse.de>

        * tree-vrp.c (zero_nonzero_bits_from_vr): Pass in a type.
        For ranges with negative values return information about the
        sign-bit.
        (extract_range_from_binary_expr_1): Adjust BIT_IOR_EXPR handling
        to handle sign-bit information for ranges with negative values.
        (simplify_bit_ops_using_ranges): Adjust.

        * gcc.dg/tree-ssa/vrp60.c: New testcase.

Index: gcc/tree-vrp.c
===================================================================
*** gcc/tree-vrp.c      (revision 177425)
--- gcc/tree-vrp.c      (working copy)
*************** vrp_int_const_binop (enum tree_code code
*** 2138,2144 ****
     the bit is 1, otherwise it might be 0 or 1.  */
  
  static bool
! zero_nonzero_bits_from_vr (value_range_t *vr, double_int *may_be_nonzero,
                           double_int *must_be_nonzero)
  {
    may_be_nonzero->low = ALL_ONES;
--- 2138,2145 ----
     the bit is 1, otherwise it might be 0 or 1.  */
  
  static bool
! zero_nonzero_bits_from_vr (value_range_t *vr, tree type,
!                          double_int *may_be_nonzero,
                           double_int *must_be_nonzero)
  {
    may_be_nonzero->low = ALL_ONES;
*************** zero_nonzero_bits_from_vr (value_range_t
*** 2178,2183 ****
--- 2179,2192 ----
              must_be_nonzero->low &= ~mask;
            }
        }
+       else if (tree_int_cst_sgn (vr->max) < 0)
+       {
+         /* The only thing we know when the range covers only negative
+            values is that the sign bit must be set.  */
+         *may_be_nonzero = double_int_minus_one;
+         *must_be_nonzero
+           = double_int_setbit (double_int_zero, TYPE_PRECISION (type) - 1);
+       }
        return true;
      }
    return false;
*************** extract_range_from_binary_expr_1 (value_
*** 2642,2650 ****
        double_int may_be_nonzero0, may_be_nonzero1;
        double_int must_be_nonzero0, must_be_nonzero1;
  
!       int_cst_range0 = zero_nonzero_bits_from_vr (&vr0, &may_be_nonzero0,
                                                  &must_be_nonzero0);
!       int_cst_range1 = zero_nonzero_bits_from_vr (&vr1, &may_be_nonzero1,
                                                  &must_be_nonzero1);
  
        type = VR_RANGE;
--- 2651,2661 ----
        double_int may_be_nonzero0, may_be_nonzero1;
        double_int must_be_nonzero0, must_be_nonzero1;
  
!       int_cst_range0 = zero_nonzero_bits_from_vr (&vr0, expr_type,
!                                                 &may_be_nonzero0,
                                                  &must_be_nonzero0);
!       int_cst_range1 = zero_nonzero_bits_from_vr (&vr1, expr_type,
!                                                 &may_be_nonzero1,
                                                  &must_be_nonzero1);
  
        type = VR_RANGE;
*************** extract_range_from_binary_expr_1 (value_
*** 2683,2699 ****
          max = double_int_to_tree (expr_type,
                                    double_int_ior (may_be_nonzero0,
                                                    may_be_nonzero1));
-         if (tree_int_cst_sgn (max) < 0)
-           max = NULL_TREE;
          if (int_cst_range0)
!           {
!             if (tree_int_cst_sgn (min) < 0)
!               min = vr0.min;
!             else
!               min = vrp_int_const_binop (MAX_EXPR, min, vr0.min);
!           }
          if (int_cst_range1)
            min = vrp_int_const_binop (MAX_EXPR, min, vr1.min);
        }
        else if (code == BIT_XOR_EXPR)
        {
--- 2694,2709 ----
          max = double_int_to_tree (expr_type,
                                    double_int_ior (may_be_nonzero0,
                                                    may_be_nonzero1));
          if (int_cst_range0)
!           min = vrp_int_const_binop (MAX_EXPR, min, vr0.min);
          if (int_cst_range1)
            min = vrp_int_const_binop (MAX_EXPR, min, vr1.min);
+         if (tree_int_cst_sgn (min) < 0)
+           ;
+         else if (tree_int_cst_sgn (max) >= 0)
+           ;
+         else
+           min = max = NULL_TREE;
        }
        else if (code == BIT_XOR_EXPR)
        {
*************** simplify_bit_ops_using_ranges (gimple_st
*** 6984,6992 ****
    else
      return false;
  
!   if (!zero_nonzero_bits_from_vr (&vr0, &may_be_nonzero0, &must_be_nonzero0))
      return false;
!   if (!zero_nonzero_bits_from_vr (&vr1, &may_be_nonzero1, &must_be_nonzero1))
      return false;
  
    switch (gimple_assign_rhs_code (stmt))
--- 6994,7004 ----
    else
      return false;
  
!   if (!zero_nonzero_bits_from_vr (&vr0, TREE_TYPE (op0),
!                                 &may_be_nonzero0, &must_be_nonzero0))
      return false;
!   if (!zero_nonzero_bits_from_vr (&vr1, TREE_TYPE (op1),
!                                 &may_be_nonzero1, &must_be_nonzero1))
      return false;
  
    switch (gimple_assign_rhs_code (stmt))
Index: gcc/testsuite/gcc.dg/tree-ssa/vrp60.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/vrp60.c       (revision 0)
--- gcc/testsuite/gcc.dg/tree-ssa/vrp60.c       (revision 0)
***************
*** 0 ****
--- 1,31 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fno-tree-ccp -fno-tree-dominator-opts -fdump-tree-vrp1" 
} */
+ 
+ int foo (int x, int b)
+ {
+   int cst;
+   if (b)
+     cst = -__INT_MAX__ - 1;
+   else
+     cst = -__INT_MAX__;
+   x = x | cst;
+   if (x >= 0)
+     return 12345;
+   return x;
+ }
+ 
+ int bar (int x, int b)
+ {
+   int cst;
+   if (b)
+     cst = __INT_MAX__;
+   else
+     cst = __INT_MAX__ - 1;
+   x = x & cst;
+   if (x < 0)
+     return 12345;
+   return x;
+ }
+ 
+ /* { dg-final { scan-tree-dump-not "12345" "vrp1" } } */
+ /* { dg-final { cleanup-tree-dump "vrp1" } } */

Reply via email to