diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2014-12-12 15:46:57 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2014-12-12 15:46:57 +0000 |
commit | 4db4954fc5495758817fdc8c0dc3d29f82509589 (patch) | |
tree | b4ad83f4876c83d62f4f1ff43d1f923c4cd90840 /gcc/double-int.c | |
parent | 8f596ff51a4177ce494b6567c83a2fa0bbf12c71 (diff) | |
download | gcc-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.c | 23 |
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, <wice, &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; */ |