PR 28634: dbr_schedule makes an invalid FP transformation

Richard Sandiford richard@codesourcery.com
Mon Aug 14 07:45:00 GMT 2006


This patch fixes PR rtl-optimization/28634, a 4.1 and 4.2 regression.
The bug has actually been there for a long time, but whether it triggers
for this testcase or not depends on how the loop is optimised.

If a branch is likely taken, dbr_schedule will consider filling its
delay slot with an addition from the branch target.  If it does so,
it will insert a compensating subtract for when the branch isn't taken.

The problem is, it assumes A + X - X == A for floating-point modes too,
which is of course not true.  This patch makes the optimization conditional
on flag_unsafe_math_optimizations for FP modes.

Regression tested on mipsisa64-elf (all multilibs).  Also bootstrapped
& regression tested on x86_64-linux-gnu as a sanity check.  OK for
trunk and 4.1?  Given the nature of the bug, it is likely to be a
4.0 regression for _some_ testcase, but as I haven't got an example
to hand, I won't push for 4.0.

Richard


gcc/
	PR rtl-optimization/28634
	* reorg.c (fill_slots_from_thread): Do not assume A + X - X == A
	for floating-point modes unless flag_unsafe_math_optimizations.

gcc/testsuite/
	PR rtl-optimization/28634
	* gcc.c-torture/execute/ieee/pr28634.c: New test.

Index: gcc/reorg.c
===================================================================
--- gcc/reorg.c	(revision 115818)
+++ gcc/reorg.c	(working copy)
@@ -2817,6 +2817,8 @@ fill_slots_from_thread (rtx insn, rtx co
       dest = SET_DEST (pat), src = SET_SRC (pat);
       if ((GET_CODE (src) == PLUS || GET_CODE (src) == MINUS)
 	  && rtx_equal_p (XEXP (src, 0), dest)
+	  && (!FLOAT_MODE_P (GET_MODE (src))
+	      || flag_unsafe_math_optimizations)
 	  && ! reg_overlap_mentioned_p (dest, XEXP (src, 1))
 	  && ! side_effects_p (pat))
 	{
Index: gcc/testsuite/gcc.c-torture/execute/ieee/pr28634.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/ieee/pr28634.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/ieee/pr28634.c	(revision 0)
@@ -0,0 +1,15 @@
+/* PR rtl-optimization/28634.  On targets with delayed branches,
+   dbr_schedule could do the next iteration's addition in the
+   branch delay slot, then subtract the value again if the branch
+   wasn't taken.  This can lead to rounding errors.  */
+double x = -0x1.0p53;
+double y = 1;
+int
+main (void)
+{
+  while (y > 0)
+    y += x;
+  if (y != x + 1)
+    abort ();
+  exit (0);
+}



More information about the Gcc-patches mailing list