On Thu, 15 May 2014, Jakub Jelinek wrote: > Hi! > > fold_binary_loc for (X >> C1) & C2, if X is zero extended narrower > value, decreases prec, but if the shift count is bigger > than the narrower prec, we then attempt to zerobits <<= negative_value. > > In that case the result is necessarily zero though, all possibly non-zero > bits are shifted away, so this patch fixes this case by making sure zerobits > is all ones in that case, which results in (X, 0) folding a few lines below. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/4.9/4.8?
Ok. Thanks, Richard. > 2014-05-15 Jakub Jelinek <ja...@redhat.com> > > PR tree-optimization/61158 > * fold-const.c (fold_binary_loc): If X is zero-extended and > shiftc >= prec, make sure zerobits is all ones instead of > invoking undefined behavior. > > * gcc.dg/pr61158.c: New test. > > --- gcc/fold-const.c.jj 2014-05-14 09:46:07.000000000 +0200 > +++ gcc/fold-const.c 2014-05-14 11:35:19.593730226 +0200 > @@ -11972,11 +11972,17 @@ fold_binary_loc (location_t loc, > /* See if we can shorten the right shift. */ > if (shiftc < prec) > shift_type = inner_type; > + /* Otherwise X >> C1 is all zeros, so we'll optimize > + it into (X, 0) later on by making sure zerobits > + is all ones. */ > } > } > zerobits = ~(unsigned HOST_WIDE_INT) 0; > - zerobits >>= HOST_BITS_PER_WIDE_INT - shiftc; > - zerobits <<= prec - shiftc; > + if (shiftc < prec) > + { > + zerobits >>= HOST_BITS_PER_WIDE_INT - shiftc; > + zerobits <<= prec - shiftc; > + } > /* For arithmetic shift if sign bit could be set, zerobits > can contain actually sign bits, so no transformation is > possible, unless MASK masks them all away. In that > @@ -11994,7 +12000,7 @@ fold_binary_loc (location_t loc, > /* ((X << 16) & 0xff00) is (X, 0). */ > if ((mask & zerobits) == mask) > return omit_one_operand_loc (loc, type, > - build_int_cst (type, 0), arg0); > + build_int_cst (type, 0), arg0); > > newmask = mask | zerobits; > if (newmask != mask && (newmask & (newmask + 1)) == 0) > --- gcc/testsuite/gcc.dg/pr61158.c.jj 2014-05-14 12:18:06.066817887 +0200 > +++ gcc/testsuite/gcc.dg/pr61158.c 2014-05-14 12:18:48.046598622 +0200 > @@ -0,0 +1,12 @@ > +/* PR tree-optimization/61158 */ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-original" } */ > + > +unsigned long long > +foo (unsigned int x) > +{ > + return ((unsigned long long) x & 0x00ff000000000000ULL) >> 40; > +} > + > +/* { dg-final { scan-tree-dump "return 0;" "original" { target { ilp32 || > lp64 } } } } */ > +/* { dg-final { cleanup-tree-dump "original" } } */ > > Jakub > > -- Richard Biener <rguent...@suse.de> SUSE / SUSE Labs SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746 GF: Jeff Hawn, Jennifer Guild, Felix Imend"orffer