Jakub Jelinek <ja...@redhat.com> writes: > As the testcase shows, wide_int unsigned division is broken for > 64bit > precision division of unsigned dividend which have 63rd bit set, and all > higher bits cleared (thus is normalized as 2 HWIs, first with MSB set, > the second 0) and divisor of 1, we return just a single HWI, which is > equivalent to all higher bits set too. If the divisor is > 1, there is > no such problem, as the MSB will not be set after the division. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > > 2016-01-29 Jakub Jelinek <ja...@redhat.com> > > PR tree-optimization/69546 > * wide-int.cc (wi::divmod_internal): For unsigned division > where both operands fit into uhwi, if o1 is 1 and o0 has > msb set, if divident_prec is larger than bits per hwi, > clear another quotient word and return 2 instead of 1. > > * gcc.dg/torture/pr69546.c: New test. > > --- gcc/wide-int.cc.jj 2016-01-26 11:46:39.000000000 +0100 > +++ gcc/wide-int.cc 2016-01-29 11:59:33.348852003 +0100 > @@ -1788,15 +1788,25 @@ wi::divmod_internal (HOST_WIDE_INT *quot > { > unsigned HOST_WIDE_INT o0 = dividend.to_uhwi (); > unsigned HOST_WIDE_INT o1 = divisor.to_uhwi (); > + unsigned int quotient_len = 1; > > if (quotient) > - quotient[0] = o0 / o1; > + { > + quotient[0] = o0 / o1; > + if (o1 == 1 > + && (HOST_WIDE_INT) o0 < 0 > + && dividend_prec > HOST_BITS_PER_WIDE_INT) > + { > + quotient[1] = 0; > + quotient_len = 2; > + } > + } > if (remainder) > { > remainder[0] = o0 % o1; > *remainder_len = 1; > } > - return 1; > + return quotient_len; > }
Might be wrong, but couldn't the same thing happen for the remainder, e.g. for 0xfffffffe % 0xffffffff ? Maybe we should have a helper function to handle storing uhwis in an array and returning the length. Certainly seems like this function has had its fair share of bugs. Thanks for fixing another. Richard