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]

Re: Tail calls and floating-point types


Richard Henderson <rth@redhat.com> writes:
> Yeah, a check for HONOR_SIGNED_ZEROS would do the trick.

I realised later that the transformed code was doing the multiplications
and additions in the opposite order to the original.  That's obviously
much more serious than the toy -0 example from my earlier message.
New testcases attached.

The patch below fixes all three tests.  Would it be OK if it passes
bootstrap?  Or would a different check be better?  The tree-ssa code
is still new to me so I'm not sure how this sort of thing should
be written.

Richard


	* tree-tailcall.c (process_assignment): Only do accumulator
	optimisations if the function has an integral return type.

testsuite/
	* gcc.c-torture/execute/ieee/acc1.c: New test.
	* gcc.c-torture/execute/ieee/acc2.c: New test.
	* gcc.c-torture/execute/ieee/mzero6.c: New test.

Index: tree-tailcall.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-tailcall.c,v
retrieving revision 2.24
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r2.24 tree-tailcall.c
*** tree-tailcall.c	7 Sep 2004 10:22:44 -0000	2.24
--- tree-tailcall.c	10 Sep 2004 06:51:36 -0000
*************** process_assignment (tree ass, tree stmt,
*** 283,288 ****
--- 283,295 ----
    if (TREE_CODE_CLASS (code) != '2')
      return false;
  
+   /* Accumulator optimizations will reverse the order of operations.
+      We can only do that for floating-point types if we're assuming
+      that addition and multiplication are associative.  */
+   if (!flag_unsafe_math_optimizations)
+     if (FLOAT_TYPE_P (TREE_TYPE (DECL_RESULT (current_function_decl))))
+       return false;
+ 
    /* We only handle the code like
  
       x = call ();
*** /dev/null	Fri Apr 23 00:21:55 2004
--- testsuite/gcc.c-torture/execute/ieee/acc1.c	Thu Sep  9 22:09:12 2004
***************
*** 0 ****
--- 1,18 ----
+ /* Tail call optimizations would reverse the order of additions in func().  */
+ 
+ double func (const double *array)
+ {
+   double d = *array;
+   if (d == 0.0)
+     return d;
+   else
+     return d + func (array + 1);
+ }
+ 
+ int main ()
+ {
+   double values[] = { 0.1e-100, 1.0, -1.0, 0.0 };
+   if (func (values) != 0.1e-100)
+     abort ();
+   exit (0);
+ }
*** /dev/null	Fri Apr 23 00:21:55 2004
--- testsuite/gcc.c-torture/execute/ieee/acc2.c	Fri Sep 10 07:50:19 2004
***************
*** 0 ****
--- 1,19 ----
+ /* Tail call optimizations would reverse the order of multiplications
+    in func().  */
+ 
+ double func (const double *array)
+ {
+   double d = *array;
+   if (d == 1.0)
+     return d;
+   else
+     return d * func (array + 1);
+ }
+ 
+ int main ()
+ {
+   double values[] = { __DBL_MAX__, 2.0, 0.5, 1.0 };
+   if (func (values) != __DBL_MAX__)
+     abort ();
+   exit (0);
+ }
*** /dev/null	Fri Apr 23 00:21:55 2004
--- testsuite/gcc.c-torture/execute/ieee/mzero6.c	Thu Sep  9 22:07:33 2004
***************
*** 0 ****
--- 1,24 ----
+ /* Tail call optimizations would convert func() into the moral equivalent of:
+ 
+        double acc = 0.0;
+        for (int i = 0; i <= n; i++)
+ 	 acc += d;
+        return acc;
+ 
+    which mishandles the case where 'd' is -0.  They also initialised 'acc'
+    to a zero int rather than a zero double.  */
+ 
+ double func (double d, int n)
+ {
+   if (n == 0)
+     return d;
+   else
+     return d + func (d, n - 1);
+ }
+ 
+ int main ()
+ {
+   if (__builtin_copysign (1.0, func (0.0 / -5.0, 10)) != -1.0)
+     abort ();
+   exit (0);
+ }


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