re PR tree-optimization/64322 (More optimize opportunity for constant folding)
authorJakub Jelinek <jakub@redhat.com>
Wed, 17 Dec 2014 09:29:12 +0000 (10:29 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 17 Dec 2014 09:29:12 +0000 (10:29 +0100)
PR tree-optimization/64322
* tree-vrp.c (extract_range_from_binary_expr_1): Attempt to derive
range for RSHIFT_EXPR even if vr0 range is not VR_RANGE or is symbolic.

* gcc.dg/tree-ssa/vrp95.c: New test.

From-SVN: r218812

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

index badd40e7c54919ebe499a029bdf62b20e5c2b184..631d7268013bb8b54616801e225b18fcdf4f6918 100644 (file)
@@ -1,3 +1,9 @@
+2014-12-17  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/64322
+       * tree-vrp.c (extract_range_from_binary_expr_1): Attempt to derive
+       range for RSHIFT_EXPR even if vr0 range is not VR_RANGE or is symbolic.
+
 2014-12-17  Tobias Burnus  <burnus@net-b.de>
 
        PR fortran/54687
index 9f6fd3147472150117e97d07ebb3157ebd153d00..fbafb565dacc40cc7d6cd3dd1ead330835f14c80 100644 (file)
@@ -1,5 +1,8 @@
 2014-12-17  Jakub Jelinek  <jakub@redhat.com>
 
+       PR tree-optimization/64322
+       * gcc.dg/tree-ssa/vrp95.c: New test.
+
        PR sanitizer/64289
        * c-c++-common/ubsan/pr64289.c: New test.
 
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp95.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp95.c
new file mode 100644 (file)
index 0000000..be208ba
--- /dev/null
@@ -0,0 +1,50 @@
+/* PR tree-optimization/64322 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp1" } */
+
+extern void link_error ();
+extern void required_check ();
+
+long long int
+foo (long long int x)
+{
+  x >>= sizeof (long long int) * __CHAR_BIT__ - 1;
+  if (x != 0 && x != -1)
+    link_error ();
+  return x;
+}
+
+unsigned long long int
+bar (unsigned long long int x)
+{
+  x >>= sizeof (long long int) * __CHAR_BIT__ - 1;
+  if (x != 0 && x != 1)
+    link_error ();
+  return x;
+}
+
+long long int
+baz (long long int x)
+{
+  x = (x >> sizeof (long long int) * __CHAR_BIT__ - 1) << 1;
+  x = x / 0x100000000LL;
+  if (x != 0)
+    link_error ();
+  return x;
+}
+
+unsigned long long int
+range (unsigned long long int x, int y)
+{
+  y &= 3;
+  x >>= sizeof (long long int) * __CHAR_BIT__ - 1 - y;
+  if (x > 15)
+    link_error ();
+  if (x == 15)
+    required_check ();
+  return x;
+}
+
+/* { dg-final { scan-tree-dump-not "link_error" "vrp1" } } */
+/* { dg-final { scan-tree-dump "required_check" "vrp1" } } */
+/* { dg-final { cleanup-tree-dump "vrp1" } } */
index bd238d57700d254dab64b17cf53209ea861987f9..c49c9424885ca646a3bcfb6e57b38c0f75efee73 100644 (file)
@@ -2434,6 +2434,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
       && code != MAX_EXPR
       && code != PLUS_EXPR
       && code != MINUS_EXPR
+      && code != RSHIFT_EXPR
       && (vr0.type == VR_VARYING
          || vr1.type == VR_VARYING
          || vr0.type != vr1.type
@@ -2948,6 +2949,15 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
        {
          if (code == RSHIFT_EXPR)
            {
+             /* Even if vr0 is VARYING or otherwise not usable, we can derive
+                useful ranges just from the shift count.  E.g.
+                x >> 63 for signed 64-bit x is always [-1, 0].  */
+             if (vr0.type != VR_RANGE || symbolic_range_p (&vr0))
+               {
+                 vr0.type = type = VR_RANGE;
+                 vr0.min = vrp_val_min (expr_type);
+                 vr0.max = vrp_val_max (expr_type);
+               }
              extract_range_from_multiplicative_op_1 (vr, code, &vr0, &vr1);
              return;
            }