OSDN Git Service

gcc/
authorkazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 21 Dec 2005 05:58:02 +0000 (05:58 +0000)
committerkazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 21 Dec 2005 05:58:02 +0000 (05:58 +0000)
PR tree-optimization/25382.
* tree-vrp.c (extract_range_from_binary_expr): Extract a range
from BIT_AND_EXPR.

gcc/testsuite/
PR tree-optimization/25382.
* gcc.dg/tree-ssa/pr25382.c: New.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@108898 138bc75d-0d04-0410-961f-82ee72b054a4

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

index 2423146..7c34089 100644 (file)
@@ -1,3 +1,9 @@
+2005-12-21  Kazu Hirata  <kazu@codesourcery.com>
+
+       PR tree-optimization/25382.
+       * tree-vrp.c (extract_range_from_binary_expr): Extract a range
+       from BIT_AND_EXPR.
+
 2005-12-21  Janis Johnson  <janis187@us.ibm.com>
            Ben Elliston  <bje@au.ibm.com>
 
index 5b21ca8..090eaf8 100644 (file)
@@ -1,3 +1,8 @@
+2005-12-21  Kazu Hirata  <kazu@codesourcery.com>
+
+       PR tree-optimization/25382.
+       * gcc.dg/tree-ssa/pr25382.c: New.
+
 2005-12-20  Richard Guenther  <rguenther@suse.de>
 
        PR middle-end/24306
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr25382.c b/gcc/testsuite/gcc.dg/tree-ssa/pr25382.c
new file mode 100644 (file)
index 0000000..72277f9
--- /dev/null
@@ -0,0 +1,19 @@
+/* PR tree-optimization/25382
+   VRP used to ignore BIT_AND_EXPRs for the purpose of distilling ranges.
+   Check that VRP now gets ranges from BIT_AND_EXPRs.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp" } */
+
+int
+foo (int a)
+{
+  int b = a & 0xff;
+  if (b > 300)
+    return 2;
+  else
+    return 1;
+}
+
+/* { dg-final { scan-tree-dump-times "Folding predicate b_.* > 300 to 0" 1 "vrp" } } */
+/* { dg-final { cleanup-tree-dump "vrp" } } */
index 04353f5..a9609fa 100644 (file)
@@ -1184,6 +1184,7 @@ extract_range_from_binary_expr (value_range_t *vr, tree expr)
       && code != ROUND_DIV_EXPR
       && code != MIN_EXPR
       && code != MAX_EXPR
+      && code != BIT_AND_EXPR
       && code != TRUTH_ANDIF_EXPR
       && code != TRUTH_ORIF_EXPR
       && code != TRUTH_AND_EXPR
@@ -1220,13 +1221,16 @@ extract_range_from_binary_expr (value_range_t *vr, tree expr)
     }
 
   /* Refuse to operate on VARYING ranges, ranges of different kinds
-     and symbolic ranges.  TODO, we may be able to derive anti-ranges
-     in some cases.  */
-  if (vr0.type == VR_VARYING
-      || vr1.type == VR_VARYING
-      || vr0.type != vr1.type
-      || symbolic_range_p (&vr0)
-      || symbolic_range_p (&vr1))
+     and symbolic ranges.  As an exception, we allow BIT_AND_EXPR
+     because we may be able to derive a useful range even if one of
+     the operands is VR_VARYING or symbolic range.  TODO, we may be
+     able to derive anti-ranges in some cases.  */
+  if (code != BIT_AND_EXPR
+      && (vr0.type == VR_VARYING
+         || vr1.type == VR_VARYING
+         || vr0.type != vr1.type
+         || symbolic_range_p (&vr0)
+         || symbolic_range_p (&vr1)))
     {
       set_value_range_to_varying (vr);
       return;
@@ -1406,6 +1410,31 @@ extract_range_from_binary_expr (value_range_t *vr, tree expr)
       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)
+    {
+      if (vr0.type == VR_RANGE
+         && vr0.min == vr0.max
+         && tree_expr_nonnegative_p (vr0.max)
+         && TREE_CODE (vr0.max) == INTEGER_CST)
+       {
+         min = fold_convert (TREE_TYPE (expr), integer_zero_node);
+         max = vr0.max;
+       }
+      else if (vr1.type == VR_RANGE
+         && vr1.min == vr1.max
+         && tree_expr_nonnegative_p (vr1.max)
+         && TREE_CODE (vr1.max) == INTEGER_CST)
+       {
+         vr0.type = VR_RANGE;
+         min = fold_convert (TREE_TYPE (expr), integer_zero_node);
+         max = vr1.max;
+       }
+      else
+       {
+         set_value_range_to_varying (vr);
+         return;
+       }
+    }
   else
     gcc_unreachable ();