diff mbox

Fix old bug in div_and_round_double

Message ID 3615860.z70LMau7zY@polaris
State New
Headers show

Commit Message

Eric Botcazou May 27, 2014, 8:29 p.m. UTC
This is an old bug in div_and_round_double for ROUND_DIV_EXPR: when the code 
detects that it needs to adjust the quotient, it needs to decide whether it 
increases or decreases it by 1.  This only depends on the expected sign of the 
quotient, but the test reads:

	    if (*hquo < 0)

So if the quotient is 0, the code will always bump it, thus yielding 1, even 
if the expected quotient is negative.  This causes the attached Ada testcase 
to fail at -O on all active branches... except for mainline, because of the 
correct implementation of the same test in wi::div_round:

	      if (wi::neg_p (x, sgn) != wi::neg_p (y, sgn))
		return quotient - 1;
	      else
		return quotient + 1;

It turns out that div_and_round_double has a predicate quo_neg that implements 
the same test as the wide-int one and ought to be used here.

Tested on x86_64-suse-linux (of course this probably doesn't mean anything on 
the mainline, but it was also test with 4.7 and 4.9 compilers) and applied on 
the mainline as obvious.


2014-05-27  Eric Botcazou  <ebotcazou@adacore.com>

	* double-int.c (div_and_round_double) <ROUND_DIV_EXPR>: Use the proper
	predicate to detect a negative quotient.


2014-05-27  Eric Botcazou  <ebotcazou@adacore.com>

	* gnat.dg/overflow_fixed.adb: New test.

Comments

Richard Biener May 28, 2014, 7:57 a.m. UTC | #1
On Tue, May 27, 2014 at 10:29 PM, Eric Botcazou <ebotcazou@adacore.com> wrote:
> This is an old bug in div_and_round_double for ROUND_DIV_EXPR: when the code
> detects that it needs to adjust the quotient, it needs to decide whether it
> increases or decreases it by 1.  This only depends on the expected sign of the
> quotient, but the test reads:
>
>             if (*hquo < 0)
>
> So if the quotient is 0, the code will always bump it, thus yielding 1, even
> if the expected quotient is negative.  This causes the attached Ada testcase
> to fail at -O on all active branches... except for mainline, because of the
> correct implementation of the same test in wi::div_round:
>
>               if (wi::neg_p (x, sgn) != wi::neg_p (y, sgn))
>                 return quotient - 1;
>               else
>                 return quotient + 1;
>
> It turns out that div_and_round_double has a predicate quo_neg that implements
> the same test as the wide-int one and ought to be used here.
>
> Tested on x86_64-suse-linux (of course this probably doesn't mean anything on
> the mainline, but it was also test with 4.7 and 4.9 compilers) and applied on
> the mainline as obvious.

I suppose you also install on branches?

Thanks,
Richard.

>
> 2014-05-27  Eric Botcazou  <ebotcazou@adacore.com>
>
>         * double-int.c (div_and_round_double) <ROUND_DIV_EXPR>: Use the proper
>         predicate to detect a negative quotient.
>
>
> 2014-05-27  Eric Botcazou  <ebotcazou@adacore.com>
>
>         * gnat.dg/overflow_fixed.adb: New test.
>
>
> --
> Eric Botcazou
Eric Botcazou May 28, 2014, 10:17 a.m. UTC | #2
> I suppose you also install on branches?

No plan to do so since this isn't a regression, unless you insist. :-)
Richard Biener May 28, 2014, 10:21 a.m. UTC | #3
On Wed, May 28, 2014 at 12:17 PM, Eric Botcazou <ebotcazou@adacore.com> wrote:
>> I suppose you also install on branches?
>
> No plan to do so since this isn't a regression, unless you insist. :-)

Well, a wrong-code bug plus a very obvious fix certainly qualifies.

Richard.

> --
> Eric Botcazou
Eric Botcazou May 28, 2014, 10:23 a.m. UTC | #4
> Well, a wrong-code bug plus a very obvious fix certainly qualifies.

Fine with me, onto which branch(es) do you want me to put it?
Richard Biener May 28, 2014, 10:35 a.m. UTC | #5
On Wed, May 28, 2014 at 12:23 PM, Eric Botcazou <ebotcazou@adacore.com> wrote:
>> Well, a wrong-code bug plus a very obvious fix certainly qualifies.
>
> Fine with me, onto which branch(es) do you want me to put it?

Where you have tested it already, no need to spend extra cycles.

Richard.

> --
> Eric Botcazou
diff mbox

Patch

Index: double-int.c
===================================================================
--- double-int.c	(revision 210911)
+++ double-int.c	(working copy)
@@ -588,7 +588,7 @@  div_and_round_double (unsigned code, int
 		 == (unsigned HOST_WIDE_INT) htwice)
 		&& (labs_den <= ltwice)))
 	  {
-	    if (*hquo < 0)
+	    if (quo_neg)
 	      /* quo = quo - 1;  */
 	      add_double (*lquo, *hquo,
 			  (HOST_WIDE_INT) -1, (HOST_WIDE_INT) -1, lquo, hquo);