re PR tree-optimization/49984 (VRP does not handle BIT_XOR_EXPR)
authorRichard Guenther <rguenther@suse.de>
Fri, 5 Aug 2011 10:16:48 +0000 (10:16 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 5 Aug 2011 10:16:48 +0000 (10:16 +0000)
2011-08-05  Richard Guenther  <rguenther@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.

From-SVN: r177425

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/vrp59.c [new file with mode: 0644]
gcc/tree-vrp.c

index 5859bea2c350d69962fa58282871e3486bf3555a..d86d24bbcca091cdd1966232ca690775a30d8c09 100644 (file)
@@ -1,3 +1,8 @@
+2011-08-05  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/49984
+       * tree-vrp.c (extract_range_from_binary_expr_1): Handle BIT_XOR_EXPR.
+
 2011-08-05  Richard Guenther  <rguenther@suse.de>
 
        * tree-vrp.c (zero_nonzero_bits_from_vr): Make sure to always
index 666fcd6a1676df35bb363609534f545e7067f876..78017058ccb271a2d845407d42e7d438396ddcbe 100644 (file)
@@ -1,3 +1,8 @@
+2011-08-05  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/49984
+       * gcc.dg/tree-ssa/vrp59.c: New testcase.
+
 2011-08-05  Richard Guenther  <rguenther@suse.de>
 
        * gcc.dg/tree-ssa/vrp51.c: Disable CCP.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp59.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp59.c
new file mode 100644 (file)
index 0000000..30b26f5
--- /dev/null
@@ -0,0 +1,35 @@
+/* { dg-do compile } */\r
+/* { dg-options "-O2 -fno-tree-ccp -fdump-tree-vrp1" } */\r
+\r
+int f(int x)\r
+{\r
+  if (x >= 0 && x <= 3)\r
+    {\r
+      x = x ^ 3;\r
+      x = x & 3;\r
+    }\r
+  return x;\r
+}\r
+\r
+int g(int x)\r
+{\r
+  if (x >= 0 && x <= 3)\r
+    {\r
+      x = x ^ 2;\r
+      x = x & 3;\r
+    }\r
+  return x;\r
+}\r
+\r
+int h(int x)\r
+{\r
+  if (x >= 0 && x <= 3)\r
+    {\r
+      x = x ^ 1;\r
+      x = x & 3;\r
+    }\r
+  return x;\r
+}\r
+\r
+/* { dg-final { scan-tree-dump-not " & 3;" "vrp1" } } */\r
+/* { dg-final { cleanup-tree-dump "vrp1" } } */\r
index 121746efab677f55ca3c4d6d4e2f4c9201252f7c..eb6fc9dcc8c9a09402d7fcff1a33cc2ed984f54d 100644 (file)
@@ -2214,7 +2214,8 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
       && code != MIN_EXPR
       && code != MAX_EXPR
       && code != BIT_AND_EXPR
-      && code != BIT_IOR_EXPR)
+      && code != BIT_IOR_EXPR
+      && code != BIT_XOR_EXPR)
     {
       set_value_range_to_varying (vr);
       return;
@@ -2635,7 +2636,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
       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)
+  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;
@@ -2694,6 +2695,35 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
          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);