Jakub Jelinek <ja...@redhat.com> writes:
> On Sat, Jan 30, 2016 at 12:31:05PM +0000, Richard Sandiford wrote:
>> Might be wrong, but couldn't the same thing happen for the remainder,
>> e.g. for 0xfffffffe % 0xffffffff ?
>
> You're right, that is broken too.  Adjusted patch below.
>
>>  Maybe we should have a helper
>> function to handle storing uhwis in an array and returning the length.
>
> Any suggestion how to call it, whether to put it in wi namespace, somewhere
> else etc.?

I think it should be local to wide-int.cc rather than in wi::.  Users of
the public interface should always be using wi::uhwi (...).  We only get
into this mess because we're trying to operate on the arrays directly,
rather than using the abstractions in the public interface.

Not sure what to call it.  Maybe canonize_uhwi?  Like canonize, except
that it takes a uhwi instead of a length.

> Can that be done as a follow-up?  Certainly it would need
> to take the uhwi to store, pointer to the array of hwis, and precision.

Yeah, guess it can wait.

> 2016-01-30  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.
>       Similarly for remainder with msb in HWI set, if dividend_prec
>       is larger than bits per hwi.
>
>       * gcc.dg/torture/pr69546.c: New test.
>
> --- gcc/wide-int.cc.jj        2016-01-29 12:12:43.486930641 +0100
> +++ gcc/wide-int.cc   2016-01-30 14:08:18.293537813 +0100
> @@ -1788,15 +1788,32 @@ 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;
> +       if ((HOST_WIDE_INT) remainder[0] < 0
> +           && dividend_prec > HOST_BITS_PER_WIDE_INT)
> +         {
> +           remainder[1] = 0;
> +           *remainder_len = 2;
> +         }
> +       else
> +         *remainder_len = 1;
>       }
> -      return 1;
> +      return quotient_len;
>      }

LGTM, thanks.

Richard

Reply via email to