[PATCH]: PR middle-end/29335 use MPFR for builtin sqrt

Kaveh R. GHAZI ghazi@caip.rutgers.edu
Wed Jan 31 03:46:00 GMT 2007


GCC currently uses real.c:real_sqrt() for calculating builtin sqrt with
constant args at compile-time.  Although I've never detected any
inaccuracies with it, there's a comment in the code which says getting the
last but right may needs a "Tuckerman test".  It also seems redundant now
that MPFR is available.

Roger, you implemented real_sqrt, right?  Thoughts on switching GCC to use
MPFR for builtin sqrt?  (There's a couple of uses of real_sqrt left, so we
can't remove that function yet.)  The MPFR mechanism punts on non-finite
args and/or return values, BTW.  As with builtin cabs, I don't think
that's a big deal, but I'm willing to consider other opinions.

Tested on sparc-sun-solaris2.10, no regressions.

Okay for mainline?

		Thanks,
		--Kaveh


2007-01-25  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>

	PR middle-end/29335
	* builtins.c (fold_builtin_sqrt): Use MPFR for constant args.

testsuite:
	* gcc.dg/torture/builtin-math-2.c: Add sqrt cases.
	* gcc.dg/torture/builtin-math-3.c: Likewise.

diff -rup orig/egcc-SVN20070125/gcc/builtins.c egcc-SVN20070125/gcc/builtins.c
--- orig/egcc-SVN20070125/gcc/builtins.c	2007-01-25 22:33:21.000000000 -0500
+++ egcc-SVN20070125/gcc/builtins.c	2007-01-25 22:48:19.382491809 -0500
@@ -7094,22 +7094,15 @@ fold_builtin_sqrt (tree arglist, tree ty

   enum built_in_function fcode;
   tree arg = TREE_VALUE (arglist);
-
+  tree res;
+
   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
     return NULL_TREE;

-  /* Optimize sqrt of constant value.  */
-  if (TREE_CODE (arg) == REAL_CST
-      && !TREE_OVERFLOW (arg))
-    {
-      REAL_VALUE_TYPE r, x;
-
-      x = TREE_REAL_CST (arg);
-      if (real_sqrt (&r, TYPE_MODE (type), &x)
-	  || (!flag_trapping_math && !flag_errno_math))
-	return build_real (type, r);
-    }
-
+  /* Calculate the result when the argument is a constant.  */
+  if ((res = do_mpfr_arg1 (arg, type, mpfr_sqrt, &dconst0, NULL, true)))
+    return res;
+
   /* Optimize sqrt(expN(x)) = expN(x*0.5).  */
   fcode = builtin_mathfn_code (arg);
   if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
diff -rup orig/egcc-SVN20070125/gcc/testsuite/gcc.dg/torture/builtin-math-2.c egcc-SVN20070125/gcc/testsuite/gcc.dg/torture/builtin-math-2.c
--- orig/egcc-SVN20070125/gcc/testsuite/gcc.dg/torture/builtin-math-2.c	2006-11-10 09:46:03.000000000 -0500
+++ egcc-SVN20070125/gcc/testsuite/gcc.dg/torture/builtin-math-2.c	2007-01-25 22:57:51.347611502 -0500
@@ -145,6 +145,11 @@ void bar()
   fool (__builtin_fmal (__LDBL_MAX__, __LDBL_MAX__, 0.0L));
   fool (__builtin_fmal (__LDBL_MAX__, 1.0L, __LDBL_MAX__));
   fool (__builtin_fmal (__LDBL_MIN__, __LDBL_MIN__, 0.0L));
+
+  /* The sqrt arg must be [0 ... Inf] inclusive.  */
+  TESTIT (sqrt, -0.5);
+  TESTIT (sqrt, -0.0);
+  TESTIT (sqrt, 0.0);
 }

 /* { dg-final { scan-tree-dump-times "exp2 " 9 "original" } } */
@@ -183,4 +188,7 @@ void bar()
 /* { dg-final { scan-tree-dump-times "fma " 3 "original" } } */
 /* { dg-final { scan-tree-dump-times "fmaf" 3 "original" } } */
 /* { dg-final { scan-tree-dump-times "fmal" 3 "original" } } */
+/* { dg-final { scan-tree-dump-times "sqrt " 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "sqrtf" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "sqrtl" 1 "original" } } */
 /* { dg-final { cleanup-tree-dump "original" } } */
diff -rup orig/egcc-SVN20070125/gcc/testsuite/gcc.dg/torture/builtin-math-3.c egcc-SVN20070125/gcc/testsuite/gcc.dg/torture/builtin-math-3.c
--- orig/egcc-SVN20070125/gcc/testsuite/gcc.dg/torture/builtin-math-3.c	2007-01-19 20:02:10.000000000 -0500
+++ egcc-SVN20070125/gcc/testsuite/gcc.dg/torture/builtin-math-3.c	2007-01-25 23:03:01.592914142 -0500
@@ -363,5 +363,12 @@ int main (void)
   if (__builtin_fmal(0.5L,__LDBL_MIN__, __LDBL_MIN__) != __LDBL_MIN__*1.5L)
     link_error (__LINE__);

+  TESTIT (sqrt, -0.0, -0.0); /* sqrt(-0) == -0 */
+  TESTIT (sqrt, 0.0, 0.0); /* sqrt(0) == 0 */
+  TESTIT (sqrt, 1.0, 1.0); /* sqrt(1) == 1 */
+  TESTIT (sqrt, 4.0, 2.0); /* sqrt(4) == 2 */
+  TESTIT_R (sqrt, 1.5, 1.22, 1.23); /* sqrt(1.5) == 1.224... */
+  TESTIT_R (sqrt, 2.0, 1.41, 1.42); /* sqrt(2) == 1.414... */
+
   return 0;
 }



More information about the Gcc-patches mailing list