aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2014-12-17 09:29:12 +0000
committerJakub Jelinek <jakub@redhat.com>2014-12-17 09:29:12 +0000
commitfb2b5c025a9f3a43a4e2f1c162fa58f3d84e52ff (patch)
tree1a8656d47d66e823737ac3e415884b56dda90702
parent419b48903483ae5bdd1dd67103d5a7a3a0c24923 (diff)
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. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@218812 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp95.c50
-rw-r--r--gcc/tree-vrp.c10
4 files changed, 69 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index badd40e7c54..631d7268013 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9f6fd314747..fbafb565dac 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..be208bafd60
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp95.c
@@ -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" } } */
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index bd238d57700..c49c9424885 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -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;
}