For signed min / -1 we set the overflow flag (good) but also returned a quotient of 0. It should be 0x80...0 instead. Since that's also the value of the original dividend, we can just copy the representation over.
The value for division by 0 is probably pretty arbitrary. double-int.c seems to treat it as division by one: if (hden == 0 && lden == 0) overflow = 1, lden = 1; and while not important, it has the nice feature that here too we could just copy the original dividend, rather than treat it differently from signed min / -1. This fixes libjava's Divide_1, which was the last remaining regression on x86_64-linux-gnu. I have a couple of other patches queued up, but I'm still running tests to compare the asm output for the gcc and g++ testsuites on a range of targets. (FWIW, the first round of these tests picked up the same bug as Divide_1, in the output for gcc.c-torture/compile/20010404-1.c.) OK to install? Thanks, Richard Index: gcc/wide-int.cc =================================================================== --- gcc/wide-int.cc 2014-04-24 09:51:08.056774754 +0100 +++ gcc/wide-int.cc 2014-04-24 11:52:35.996541888 +0100 @@ -1726,8 +1726,10 @@ wi::divmod_internal (HOST_WIDE_INT *quot && wi::only_sign_bit_p (dividend)) overflow = true; - /* If overflow is set, just get out. There will only be grief by - continuing. */ + /* Handle the overflow cases. Viewed as unsigned value, the quotient of + (signed min / -1) has the same representation as the orignal dividend. + We have traditionally made division by zero act as division by one, + so there too we use the original dividend. */ if (overflow) { if (remainder) @@ -1738,8 +1741,9 @@ wi::divmod_internal (HOST_WIDE_INT *quot if (oflow != 0) *oflow = true; if (quotient) - quotient[0] = 0; - return 1; + for (unsigned int i = 0; i < dividend_len; ++i) + quotient[i] = dividend_val[i]; + return dividend_len; } if (oflow)