This adds BIT_XOR_EXPR support to propagation, similar to how we
have BIT_IOR_EXPR and BIT_AND_EXPR support (but without the
adjustment for constant vr0/1 min/max which I think we cannot do
for XOR).

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

Richard.

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

        PR tree-optimization/49984
        * tree-vrp.c (extract_range_from_binary_expr_1): Handle BIT_XOR_EXPR.

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

Index: gcc/tree-vrp.c
===================================================================
*** gcc/tree-vrp.c      (revision 177423)
--- gcc/tree-vrp.c      (working copy)
*************** extract_range_from_binary_expr_1 (value_
*** 2214,2220 ****
        && code != MIN_EXPR
        && code != MAX_EXPR
        && code != BIT_AND_EXPR
!       && code != BIT_IOR_EXPR)
      {
        set_value_range_to_varying (vr);
        return;
--- 2214,2221 ----
        && code != MIN_EXPR
        && code != MAX_EXPR
        && code != BIT_AND_EXPR
!       && code != BIT_IOR_EXPR
!       && code != BIT_XOR_EXPR)
      {
        set_value_range_to_varying (vr);
        return;
*************** extract_range_from_binary_expr_1 (value_
*** 2635,2641 ****
        min = vrp_int_const_binop (code, vr0.min, vr1.max);
        max = vrp_int_const_binop (code, vr0.max, vr1.min);
      }
!   else if (code == BIT_AND_EXPR || code == BIT_IOR_EXPR)
      {
        bool int_cst_range0, int_cst_range1;
        double_int may_be_nonzero0, may_be_nonzero1;
--- 2636,2642 ----
        min = vrp_int_const_binop (code, vr0.min, vr1.max);
        max = vrp_int_const_binop (code, vr0.max, vr1.min);
      }
!   else if (code == BIT_AND_EXPR || code == BIT_IOR_EXPR || code == 
BIT_XOR_EXPR)
      {
        bool int_cst_range0, int_cst_range1;
        double_int may_be_nonzero0, may_be_nonzero1;
*************** extract_range_from_binary_expr_1 (value_
*** 2694,2699 ****
--- 2695,2729 ----
          if (int_cst_range1)
            min = vrp_int_const_binop (MAX_EXPR, min, vr1.min);
        }
+       else if (code == BIT_XOR_EXPR)
+       {
+         double_int result_zero_bits, result_one_bits;
+         result_zero_bits
+           = double_int_ior (double_int_and (must_be_nonzero0,
+                                             must_be_nonzero1),
+                             double_int_not
+                               (double_int_ior (may_be_nonzero0,
+                                                may_be_nonzero1)));
+         result_one_bits
+           = double_int_ior (double_int_and
+                               (must_be_nonzero0,
+                                double_int_not (may_be_nonzero1)),
+                             double_int_and
+                               (must_be_nonzero1,
+                                double_int_not (may_be_nonzero0)));
+         max = double_int_to_tree (expr_type,
+                                   double_int_not (result_zero_bits));
+         min = double_int_to_tree (expr_type, result_one_bits);
+         /* Return a [min, max] range if we know the
+            result range is either positive or negative.  */
+         if (tree_int_cst_sgn (max) >= 0)
+           /* The range is bound by a lower value of 0.  */;
+         else if (tree_int_cst_sgn (min) < 0)
+           /* The range is bound by an upper value of -1.  */;
+         else
+           /* We don't know whether the sign bit is set or not.  */
+           max = min = NULL_TREE;
+       }
        else
        {
          set_value_range_to_varying (vr);
Index: gcc/testsuite/gcc.dg/tree-ssa/vrp59.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/vrp59.c       (revision 0)
--- gcc/testsuite/gcc.dg/tree-ssa/vrp59.c       (revision 0)
***************
*** 0 ****
--- 1,35 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fno-tree-ccp -fdump-tree-vrp1" } */
+ 
+ int f(int x)
+ {
+   if (x >= 0 && x <= 3)
+     {
+       x = x ^ 3;
+       x = x & 3;
+     }
+   return x;
+ }
+ 
+ int g(int x)
+ {
+   if (x >= 0 && x <= 3)
+     {
+       x = x ^ 2;
+       x = x & 3;
+     }
+   return x;
+ }
+ 
+ int h(int x)
+ {
+   if (x >= 0 && x <= 3)
+     {
+       x = x ^ 1;
+       x = x & 3;
+     }
+   return x;
+ }
+ 
+ /* { dg-final { scan-tree-dump-not " & 3;" "vrp1" } } */
+ /* { dg-final { cleanup-tree-dump "vrp1" } } */

Reply via email to