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