On Thu, 4 May 2017, Jakub Jelinek wrote: > Hi! > > This patch improves value range computation of BIT_{AND,IOR}_EXPR > with one singleton range and one range_int_cst_p, where the singleton > range has n clear least significant bits, then m set bits and either > that is all it has (i.e. negation of a power of 2), or the bits above > those two sets of bits are the same for all values in the range (i.e. > min and max range have those bits identical). > During x86_64-linux and i686-linux bootstraps together this triggers > 214000 times, though I have not actually gathered statistics on whether > the range computed without this patch would be wider in all cases.
You could try to intersect the ranges produced and assert the result is equal to the new one. > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? Ok. Thanks, Richard. > 2017-05-04 Jakub Jelinek <ja...@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. > > * gcc.dg/tree-ssa/vrp115.c: New test. > > --- gcc/tree-vrp.c.jj 2017-04-29 18:13:50.000000000 +0200 > +++ gcc/tree-vrp.c 2017-05-03 16:08:44.525256483 +0200 > @@ -3162,8 +3162,59 @@ extract_range_from_binary_expr_1 (value_ > &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); > --- gcc/testsuite/gcc.dg/tree-ssa/vrp115.c.jj 2017-05-03 16:12:55.514087451 > +0200 > +++ gcc/testsuite/gcc.dg/tree-ssa/vrp115.c 2017-05-03 16:11:35.000000000 > +0200 > @@ -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 (); > + } > +} > > Jakub > > -- Richard Biener <rguent...@suse.de> SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)