aboutsummaryrefslogtreecommitdiff
path: root/gcc/double-int.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2014-12-12 15:46:57 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2014-12-12 15:46:57 +0000
commit4db4954fc5495758817fdc8c0dc3d29f82509589 (patch)
treeb4ad83f4876c83d62f4f1ff43d1f923c4cd90840 /gcc/double-int.c
parent8f596ff51a4177ce494b6567c83a2fa0bbf12c71 (diff)
downloadgcc-4db4954fc5495758817fdc8c0dc3d29f82509589.zip
gcc-4db4954fc5495758817fdc8c0dc3d29f82509589.tar.gz
gcc-4db4954fc5495758817fdc8c0dc3d29f82509589.tar.bz2
re PR middle-end/64182 (wide-int rounding division is broken)
gcc/ PR middle-end/64182 * wide-int.h (wi::div_round, wi::mod_round): Fix rounding of tied cases. * double-int.c (div_and_round_double): Fix handling of unsigned cases. Use same rounding approach as wide-int.h. gcc/testsuite/ 2014-xx-xx Richard Sandiford <richard.sandiford@arm.com> Joseph Myers <joseph@codesourcery.com> PR middle-end/64182 * gcc.dg/plugin/wide-int-test-1.c, gcc.dg/plugin/wide-int_plugin.c: New test. * gcc.dg/plugin/plugin.exp: Register it. * gnat.dg/round_div.adb: New test. Co-Authored-By: Joseph Myers <joseph@codesourcery.com> From-SVN: r218678
Diffstat (limited to 'gcc/double-int.c')
-rw-r--r--gcc/double-int.c23
1 files changed, 11 insertions, 12 deletions
diff --git a/gcc/double-int.c b/gcc/double-int.c
index f6e340b..9dc501c 100644
--- a/gcc/double-int.c
+++ b/gcc/double-int.c
@@ -569,24 +569,23 @@ div_and_round_double (unsigned code, int uns,
{
unsigned HOST_WIDE_INT labs_rem = *lrem;
HOST_WIDE_INT habs_rem = *hrem;
- unsigned HOST_WIDE_INT labs_den = lden, ltwice;
- HOST_WIDE_INT habs_den = hden, htwice;
+ unsigned HOST_WIDE_INT labs_den = lden, lnegabs_rem, ldiff;
+ HOST_WIDE_INT habs_den = hden, hnegabs_rem, hdiff;
/* Get absolute values. */
- if (*hrem < 0)
+ if (!uns && *hrem < 0)
neg_double (*lrem, *hrem, &labs_rem, &habs_rem);
- if (hden < 0)
+ if (!uns && hden < 0)
neg_double (lden, hden, &labs_den, &habs_den);
- /* If (2 * abs (lrem) >= abs (lden)), adjust the quotient. */
- mul_double ((HOST_WIDE_INT) 2, (HOST_WIDE_INT) 0,
- labs_rem, habs_rem, &ltwice, &htwice);
+ /* If abs(rem) >= abs(den) - abs(rem), adjust the quotient. */
+ neg_double (labs_rem, habs_rem, &lnegabs_rem, &hnegabs_rem);
+ add_double (labs_den, habs_den, lnegabs_rem, hnegabs_rem,
+ &ldiff, &hdiff);
- if (((unsigned HOST_WIDE_INT) habs_den
- < (unsigned HOST_WIDE_INT) htwice)
- || (((unsigned HOST_WIDE_INT) habs_den
- == (unsigned HOST_WIDE_INT) htwice)
- && (labs_den <= ltwice)))
+ if (((unsigned HOST_WIDE_INT) habs_rem
+ > (unsigned HOST_WIDE_INT) hdiff)
+ || (habs_rem == hdiff && labs_rem >= ldiff))
{
if (quo_neg)
/* quo = quo - 1; */