public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Fix wide_int unsigned division (PR tree-optimization/69546)
@ 2016-01-29 14:20 Jakub Jelinek
  2016-01-30 12:31 ` Richard Sandiford
  0 siblings, 1 reply; 6+ messages in thread
From: Jakub Jelinek @ 2016-01-29 14:20 UTC (permalink / raw)
  To: Mike Stump, Richard Sandiford, Richard Biener; +Cc: gcc-patches

Hi!

As the testcase shows, wide_int unsigned division is broken for > 64bit
precision division of unsigned dividend which have 63rd bit set, and all
higher bits cleared (thus is normalized as 2 HWIs, first with MSB set,
the second 0) and divisor of 1, we return just a single HWI, which is
equivalent to all higher bits set too.  If the divisor is > 1, there is
no such problem, as the MSB will not be set after the division.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2016-01-29  Jakub Jelinek  <jakub@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.

	* gcc.dg/torture/pr69546.c: New test.

--- gcc/wide-int.cc.jj	2016-01-26 11:46:39.000000000 +0100
+++ gcc/wide-int.cc	2016-01-29 11:59:33.348852003 +0100
@@ -1788,15 +1788,25 @@ 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;
 	}
-      return 1;
+      return quotient_len;
     }
 
   /* Make the divisor and dividend positive and remember what we
--- gcc/testsuite/gcc.dg/torture/pr69546.c.jj	2016-01-29 12:06:03.148516651 +0100
+++ gcc/testsuite/gcc.dg/torture/pr69546.c	2016-01-29 12:08:17.847672967 +0100
@@ -0,0 +1,26 @@
+/* PR tree-optimization/69546 */
+/* { dg-do run { target int128 } } */
+
+unsigned __int128 __attribute__ ((noinline, noclone))
+foo (unsigned long long x)
+{
+  unsigned __int128 y = ~0ULL;
+  x >>= 63;
+  return y / (x | 1);
+}
+
+unsigned __int128 __attribute__ ((noinline, noclone))
+bar (unsigned long long x)
+{
+  unsigned __int128 y = ~33ULL;
+  x >>= 63;
+  return y / (x | 1);
+}
+
+int
+main ()
+{
+  if (foo (1) != ~0ULL || bar (17) != ~33ULL)
+    __builtin_abort ();
+  return 0;
+}

	Jakub

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2016-02-02 15:49 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-29 14:20 [PATCH] Fix wide_int unsigned division (PR tree-optimization/69546) Jakub Jelinek
2016-01-30 12:31 ` Richard Sandiford
2016-01-30 13:15   ` [PATCH] Fix wide_int unsigned division (PR tree-optimization/69546, take 2) Jakub Jelinek
2016-01-30 14:04     ` Richard Sandiford
2016-02-01 20:25       ` Jakub Jelinek
2016-02-02 15:49         ` Richard Sandiford

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).