aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2017-05-05 17:43:22 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2017-05-05 17:43:22 +0200
commitac699a047f74de2bb8f1d538b07c89075cd25c84 (patch)
treed406a59213928fe0dded5f9492923ddd28567856 /gcc
parent655b5fc85b56cf9ac46af952041abf56ca383faa (diff)
downloadgcc-ac699a047f74de2bb8f1d538b07c89075cd25c84.zip
gcc-ac699a047f74de2bb8f1d538b07c89075cd25c84.tar.gz
gcc-ac699a047f74de2bb8f1d538b07c89075cd25c84.tar.bz2
re PR tree-optimization/80558 (VRP not handling x & -2 well)
PR tree-optimization/80558 * tree-vrp.c (extract_range_from_binary_expr_1): Optimize [x, y] op z into [x op, y op z] for op & or | if conditions are met. * gcc.dg/tree-ssa/vrp115.c: New test. From-SVN: r247641
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp115.c50
-rw-r--r--gcc/tree-vrp.c53
4 files changed, 114 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ff1d499..51471bf 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2017-05-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/80558
+ * tree-vrp.c (extract_range_from_binary_expr_1): Optimize
+ [x, y] op z into [x op, y op z] for op & or | if conditions
+ are met.
+
2017-05-05 Andre Vieira <andre.simoesdiasvieira@arm.com>
Prakhar Bahuguna <prakhar.bahuguna@arm.com>
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 8606518..7a1b002 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2017-05-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/80558
+ * gcc.dg/tree-ssa/vrp115.c: New test.
+
2017-05-05 Andre Vieira <andre.simoesdiasvieira@arm.com>
Thomas Preud'homme <thomas.preudhomme@arm.com>
Prakhar Bahuguna <prakhar.bahuguna@arm.com>
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp115.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp115.c
new file mode 100644
index 0000000..6d1c9c5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp115.c
@@ -0,0 +1,50 @@
+/* PR tree-optimization/80558 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+/* { dg-final { scan-tree-dump-not "link_error" "evrp" } } */
+
+void link_error (void);
+
+void
+f1 (int x)
+{
+ if (x >= 5 && x <= 19)
+ {
+ x &= -2;
+ if (x < 4 || x > 18)
+ link_error ();
+ }
+}
+
+void
+f2 (int x)
+{
+ if (x >= 5 && x <= 19)
+ {
+ x |= 7;
+ if (x < 7 || x > 23)
+ link_error ();
+ }
+}
+
+void
+f3 (int x)
+{
+ if (x >= -18 && x <= 19)
+ {
+ x |= 7;
+ if (x < -17 || x > 23)
+ link_error ();
+ }
+}
+
+void
+f4 (int x)
+{
+ if (x >= 1603 && x <= 2015)
+ {
+ x &= 496;
+ if (x < 64 || x > 464)
+ link_error ();
+ }
+}
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index cb1a3e5..cf50e90 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -2865,8 +2865,59 @@ extract_range_from_binary_expr_1 (value_range *vr,
&may_be_nonzero1,
&must_be_nonzero1);
+ if (code == BIT_AND_EXPR || code == BIT_IOR_EXPR)
+ {
+ value_range *vr0p = NULL, *vr1p = NULL;
+ if (range_int_cst_singleton_p (&vr1))
+ {
+ vr0p = &vr0;
+ vr1p = &vr1;
+ }
+ else if (range_int_cst_singleton_p (&vr0))
+ {
+ vr0p = &vr1;
+ vr1p = &vr0;
+ }
+ /* For op & or | attempt to optimize:
+ [x, y] op z into [x op z, y op z]
+ if z is a constant which (for op | its bitwise not) has n
+ consecutive least significant bits cleared followed by m 1
+ consecutive bits set immediately above it and either
+ m + n == precision, or (x >> (m + n)) == (y >> (m + n)).
+ The least significant n bits of all the values in the range are
+ cleared or set, the m bits above it are preserved and any bits
+ above these are required to be the same for all values in the
+ range. */
+ if (vr0p && range_int_cst_p (vr0p))
+ {
+ wide_int w = vr1p->min;
+ int m = 0, n = 0;
+ if (code == BIT_IOR_EXPR)
+ w = ~w;
+ if (wi::eq_p (w, 0))
+ n = TYPE_PRECISION (expr_type);
+ else
+ {
+ n = wi::ctz (w);
+ w = ~(w | wi::mask (n, false, w.get_precision ()));
+ if (wi::eq_p (w, 0))
+ m = TYPE_PRECISION (expr_type) - n;
+ else
+ m = wi::ctz (w) - n;
+ }
+ wide_int mask = wi::mask (m + n, true, w.get_precision ());
+ if (wi::eq_p (mask & vr0p->min, mask & vr0p->max))
+ {
+ min = int_const_binop (code, vr0p->min, vr1p->min);
+ max = int_const_binop (code, vr0p->max, vr1p->min);
+ }
+ }
+ }
+
type = VR_RANGE;
- if (code == BIT_AND_EXPR)
+ if (min && max)
+ /* Optimized above already. */;
+ else if (code == BIT_AND_EXPR)
{
min = wide_int_to_tree (expr_type,
must_be_nonzero0 & must_be_nonzero1);