On Tue, 16 Dec 2014, Jakub Jelinek wrote: > Hi! > > If for RSHIFT_EXPR vr0 is not VR_RANGE or is symbolic, currently we make > the result VARYING, even when we can do much better just by trying to > shift the min and max values down. > Divisions/modulo already handles it similarly, and +/-/& also handle it. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
Ok. Thanks, Richard. > 2014-12-16 Jakub Jelinek <ja...@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. > > * gcc.dg/tree-ssa/vrp95.c: New test. > > --- gcc/tree-vrp.c.jj 2014-12-01 14:57:30.000000000 +0100 > +++ gcc/tree-vrp.c 2014-12-16 10:17:27.543111649 +0100 > @@ -2434,6 +2434,7 @@ extract_range_from_binary_expr_1 (value_ > && 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_ > { > 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; > } > --- gcc/testsuite/gcc.dg/tree-ssa/vrp95.c.jj 2014-12-16 12:11:19.048361844 > +0100 > +++ gcc/testsuite/gcc.dg/tree-ssa/vrp95.c 2014-12-16 12:24:47.080308362 > +0100 > @@ -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" } } */ > > Jakub > > -- Richard Biener <rguent...@suse.de> SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Jennifer Guild, Dilip Upmanyu, Graham Norton HRB 21284 (AG Nuernberg)