https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69400

--- Comment #8 from rguenther at suse dot de <rguenther at suse dot de> ---
nOn Thu, 21 Jan 2016, jakub at gcc dot gnu.org wrote:

> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69400
> 
> --- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
> (In reply to Richard Biener from comment #6)
> > so in int_const_binop we end up with val = {-2 }, len = 1 (that's still
> 
> I think already this is wrong, because I think val = { -2 }, len = 1 for
> precision 128 is 0xfffffffffffffffffffffffffffffffeU128 rather than
> 0xfffffffffffffffeU128.  But I could be wrong.  It would be nice if all the
> rules were clearly documented.
> 
> At least, if I e.g. in the testcase swap -2 with 0xffffffffffffffffULL, so 
> that
> int_const_binop_1 converts the (__uint128_t) -2 to wide_int when calling
> wi::mod_trunc, then arg2 is:
> $10 = {<wide_int_storage> = {val = {-2, 0, 140737488343280}, len = 1, 
> precision
> = 128}, static is_sign_extended = <optimized out>}
> Thus, IMNSHO { -2 }, 1 is (__uint128_t) -2 rather than (__uint128_t) -2ULL.

Ok, so things go wrong then with building the wide-int result using
the "reduced" divisor_blocks_needed.  Thus

  if (remainder)
    {
      wi_pack ((unsigned HOST_WIDE_INT *) remainder, b_remainder, n);
      *remainder_len = canonize (remainder, (n + 1) / 2, dividend_prec);

should "extend" the remainder (if UNSINGED?) to the divisor len and
canonize should be fed with that instead?

Index: wide-int.cc
===================================================================
--- wide-int.cc (revision 232666)
+++ wide-int.cc (working copy)
@@ -1860,6 +1860,11 @@ wi::divmod_internal (HOST_WIDE_INT *quot
   if (remainder)
     {
       wi_pack ((unsigned HOST_WIDE_INT *) remainder, b_remainder, n);
+      if (sgn == UNSIGNED && n < divisor_blocks_needed)
+       {
+         remainder[(n + 1) / 2] = 0;
+         n++;
+       }
       *remainder_len = canonize (remainder, (n + 1) / 2, dividend_prec);
       /* The remainder is always the same sign as the dividend.  */
       if (dividend_neg)

fixes the particular testcase.  Similar adjustment needed for
the quotiend

Reply via email to