This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[wide-int] Fix signed min / -1 quotient


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)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]