From: Jakub Jelinek Date: Fri, 5 May 2017 15:43:22 +0000 (+0200) Subject: re PR tree-optimization/80558 (VRP not handling x & -2 well) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ac699a047f74de2bb8f1d538b07c89075cd25c84;p=gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ff1d4996df1..51471bfc8fe 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2017-05-05 Jakub Jelinek + + 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 Prakhar Bahuguna diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8606518de58..7a1b00207ae 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-05-05 Jakub Jelinek + + PR tree-optimization/80558 + * gcc.dg/tree-ssa/vrp115.c: New test. + 2017-05-05 Andre Vieira Thomas Preud'homme Prakhar Bahuguna 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 00000000000..6d1c9c50b37 --- /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 cb1a3e59e79..cf50e908257 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);