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]

[PATCH] Constant fold sqrt at compile time (take 2)


On Thu, 31 Oct 2002, Richard Henderson wrote:
> > Can this now be replaced with the less restrictive
> > "flag_signaling_nans", and evaluate everything
> > except "sqrt(sNaN)"?
>
> I expect so.

This is the next iteration of my patch to evaluate sqrt with a constant
argument at compile time.  Richard Henderson pointed out that there
was no reason worry about errno in real.c, as GCC always generates
code to test for a NaN return value if errno needs to be updated.
This both simplifies the real_sqrt interface and produces better code.

The final form and implementation of real_sqrt is still under
development.  As with my original patch, the implementation below
serves as a framework for further investigation, and approximates
sqrt to about 2 ulps.  For this reason, this functionality is
currently guarded by "-ffast-math" until a "perfectly rounded"
solution is implemented/contributed.

One feature that would be nice, is for real.c to provide a
real_issnan (for testing for signaling NaNs) in addition to
the current real_isnan.


The revision below has been tested on the 3.4 BIB with a complete
bootstrap (all languages except Ada and treelang) and "make -k check"
on i686-pc-linux-gnu with no new regressions.


Ok for the gcc-3_4-basic-improvements-branch?


2002-11-02  Roger Sayle  <roger@eyesopen.com>

	* real.c (real_sqrt): New function to calculate square roots.
	* real.h (real_sqrt): Add function prototype.
	* builtins.c (fold_builtin): Fold sqrt of constant argument.
	* simplify-rtx.c (simplify_unary_operation): Simplify sqrt
	of constant argument.


Index: real.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/real.c,v
retrieving revision 1.75.4.7
diff -c -3 -p -r1.75.4.7 real.c
*** real.c	28 Oct 2002 19:47:07 -0000	1.75.4.7
--- real.c	2 Nov 2002 11:10:37 -0000
*************** const struct real_format *real_format_fo
*** 4381,4383 ****
--- 4381,4456 ----
    NULL,				/* XFmode */
    &ieee_quad_format		/* TFmode */
  };
+
+
+ /* Calculate the square root of X in mode MODE, and store the result
+    in R.  */
+
+ void
+ real_sqrt (r, mode, x)
+      REAL_VALUE_TYPE *r;
+      enum machine_mode mode;
+      const REAL_VALUE_TYPE *x;
+ {
+   static REAL_VALUE_TYPE halfthree;
+   static REAL_VALUE_TYPE half;
+   static bool init = false;
+   REAL_VALUE_TYPE h, t, i;
+   int iter, exp;
+
+   /* sqrt(-0.0) is -0.0.  */
+   if (real_isnegzero (x))
+     {
+       *r = *x;
+       return;
+     }
+
+   /* Negative arguments return NaN.  */
+   if (real_isneg (x))
+     {
+       /* Mode is ignored for canonical NaN.  */
+       real_nan (r, "", 1, SFmode);
+       return;
+     }
+
+   /* Infinity and NaN return themselves.  */
+   if (real_isinf (x) || real_isnan (x))
+     {
+       *r = *x;
+       return;
+     }
+
+   if (!init)
+     {
+       real_arithmetic (&half, RDIV_EXPR, &dconst1, &dconst2);
+       real_arithmetic (&halfthree, PLUS_EXPR, &dconst1, &half);
+       init = true;
+     }
+
+   /* Initial guess for reciprocal sqrt, i.  */
+   exp = real_exponent (x);
+   real_ldexp (&i, &dconst1, -exp/2);
+
+   /* Newton's iteration for reciprocal sqrt, i */
+   for (iter = 0; iter < 16; iter++)
+     {
+       /* i(n+1) = i(n) * (1.5 - 0.5*i(n)*i(n)*x).  */
+       real_arithmetic (&t, MULT_EXPR, x, &i);
+       real_arithmetic (&h, MULT_EXPR, &t, &i);
+       real_arithmetic (&t, MULT_EXPR, &h, &half);
+       real_arithmetic (&h, MINUS_EXPR, &halfthree, &t);
+       real_arithmetic (&t, MULT_EXPR, &i, &h);
+
+       /* Check for early convergence.  */
+       if (iter >= 6 && real_identical (&i, &t))
+ 	break;
+
+       /* ??? Unroll loop to avoid copying.  */
+       i = t;
+     }
+
+   /* Final result is original value, x, multiplied by i.  */
+   real_arithmetic (&t, MULT_EXPR, &i, x);
+   real_convert (r, mode, &t);
+ }
+
Index: real.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/real.h,v
retrieving revision 1.44.8.6
diff -c -3 -p -r1.44.8.6 real.h
*** real.h	28 Oct 2002 19:47:08 -0000	1.44.8.6
--- real.h	2 Nov 2002 11:10:38 -0000
*************** extern bool exact_real_inverse	PARAMS ((
*** 346,350 ****
--- 346,354 ----
  /* In tree.c: wrap up a REAL_VALUE_TYPE in a tree node.  */
  extern tree build_real			PARAMS ((tree, REAL_VALUE_TYPE));

+ /* Calculate R as the square root of X in the given machine mode.  */
+ extern void real_sqrt			PARAMS ((REAL_VALUE_TYPE *,
+ 						 enum machine_mode,
+ 						 const REAL_VALUE_TYPE *));

  #endif /* ! GCC_REAL_H */
Index: builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.c,v
retrieving revision 1.159.4.3
diff -c -3 -p -r1.159.4.3 builtins.c
*** builtins.c	17 Sep 2002 22:58:36 -0000	1.159.4.3
--- builtins.c	2 Nov 2002 11:10:38 -0000
*************** fold_builtin (exp)
*** 4241,4249 ****
  	  enum built_in_function fcode;
  	  tree arg = TREE_VALUE (arglist);

! 	  /* Optimize sqrt(0.0) = 0.0 and sqrt(1.0) = 1.0.  */
! 	  if (real_zerop (arg) || real_onep (arg))
! 	    return arg;

  	  /* Optimize sqrt(exp(x)) = exp(x/2.0).  */
  	  fcode = builtin_mathfn_code (arg);
--- 4241,4260 ----
  	  enum built_in_function fcode;
  	  tree arg = TREE_VALUE (arglist);

! 	  /* Optimize sqrt of constant value.  */
! 	  if (flag_unsafe_math_optimizations
! 	      && TREE_CODE (arg) == REAL_CST
! 	      && ! TREE_CONSTANT_OVERFLOW (arg))
! 	    {
! 	      REAL_VALUE_TYPE r, x;
!
! 	      x = TREE_REAL_CST (arg);
! 	      if (!flag_signaling_nans || !real_isnan (&x))
! 	      {
! 		real_sqrt (&r, TYPE_MODE (TREE_TYPE (arg)), &x);
! 		return build_real (TREE_TYPE (arg), r);
! 	      }
! 	    }

  	  /* Optimize sqrt(exp(x)) = exp(x/2.0).  */
  	  fcode = builtin_mathfn_code (arg);
Index: simplify-rtx.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/simplify-rtx.c,v
retrieving revision 1.118.4.6
diff -c -3 -p -r1.118.4.6 simplify-rtx.c
*** simplify-rtx.c	21 Oct 2002 17:52:02 -0000	1.118.4.6
--- simplify-rtx.c	2 Nov 2002 11:10:39 -0000
*************** simplify_unary_operation (code, mode, op
*** 571,585 ****
    else if (GET_CODE (trueop) == CONST_DOUBLE
  	   && GET_MODE_CLASS (mode) == MODE_FLOAT)
      {
!       REAL_VALUE_TYPE d;
        REAL_VALUE_FROM_CONST_DOUBLE (d, trueop);

        switch (code)
  	{
  	case SQRT:
! 	  /* We don't attempt to optimize this.  */
! 	  return 0;
!
  	case ABS:
  	  d = REAL_VALUE_ABS (d);
  	  break;
--- 571,589 ----
    else if (GET_CODE (trueop) == CONST_DOUBLE
  	   && GET_MODE_CLASS (mode) == MODE_FLOAT)
      {
!       REAL_VALUE_TYPE d, t;
        REAL_VALUE_FROM_CONST_DOUBLE (d, trueop);

        switch (code)
  	{
  	case SQRT:
! 	  if (! flag_unsafe_math_optimizations)
! 	    return 0;
! 	  if (flag_signaling_nans && real_isnan (&d))
! 	    return 0;
! 	  real_sqrt (&t, mode, &d);
! 	  d = t;
! 	  break;
  	case ABS:
  	  d = REAL_VALUE_ABS (d);
  	  break;

Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833


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