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]

Fix old bug in div_and_round_double


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.


-- 
Eric Botcazou
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);
-- { dg-do run }
-- { dg-options "-gnato -O" }

procedure Overflow_Fixed is

  type Unsigned_8_Bit is mod 2**8;

  procedure Fixed_To_Eight (Value : Duration) is
    Item : Unsigned_8_Bit;
  begin
    Item := Unsigned_8_Bit(Value);
    raise Program_Error;
  exception
    when Constraint_Error => null; -- expected case
  end;

begin
  Fixed_To_Eight (-0.5);
end;

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