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] Evaluate pow(x,n) at compile-time


The following patch enables gcc to evaluate pow(x,y) at compile-time,
where x and y are compile-time constants and y is integer valued.

The patch below has been tested on i686-pc-linux-gnu with a full
"make bootstrap", all languages except Ada and treelang, and a
testsuite run with a top-level "make -k check" with no new
regressions.

Ok for mainline?


2003-04-09  Roger Sayle  <roger at eyesopen dot com>

	* real.c (real_powi): New function to calculate the value of
	a real raised to an integer power, i.e. pow(x,n) for int n.
	* real.h (real_powi): Prototype here.
	* builtins.c (fold_builtin):  Avoid local variable mode when
	evaluating sqrt at compile time.  Attempt to evaluate pow at
	compile-time, by checking for an integral exponent.

	* gcc.dg/builtins-12.c: New test case.


Index: real.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/real.c,v
retrieving revision 1.116
diff -c -3 -p -r1.116 real.c
*** real.c	2 Apr 2003 09:13:33 -0000	1.116
--- real.c	9 Apr 2003 20:22:59 -0000
*************** real_sqrt (r, mode, x)
*** 4629,4631 ****
--- 4629,4684 ----
    return true;
  }

+ /* Calculate X raised to the integer exponent N in mode MODE and store
+    the result in R.  The algorithm is the classic "left-to-right binary
+    method" described in section 4.6.3 of Donald Knuth's "Seminumerical
+    Algorithms", "The Art of Computer Programming", Volume 2.  */
+
+ void
+ real_powi (r, mode, x, n)
+      REAL_VALUE_TYPE *r;
+      enum machine_mode mode;
+      const REAL_VALUE_TYPE *x;
+      HOST_WIDE_INT n;
+ {
+   unsigned HOST_WIDE_INT bit;
+   REAL_VALUE_TYPE t;
+   bool init = false;
+   bool neg;
+   int i;
+
+   if (n == 0)
+     {
+       *r = dconst1;
+       return;
+     }
+   else if (n < 0)
+     {
+       /* Don't worry about overflow, from now on n is unsigned.  */
+       neg = true;
+       n = -n;
+     }
+   else
+     neg = false;
+
+   t = *x;
+   bit = (unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1);
+   for (i = 0; i < HOST_BITS_PER_WIDE_INT; i++)
+     {
+       if (init)
+ 	{
+ 	  real_arithmetic (&t, MULT_EXPR, &t, &t);
+ 	  if (n & bit)
+ 	    real_arithmetic (&t, MULT_EXPR, &t, x);
+ 	}
+       else if (n & bit)
+ 	init = true;
+       bit >>= 1;
+     }
+
+   if (neg)
+     real_arithmetic (&t, RDIV_EXPR, &dconst1, &t);
+
+   real_convert (r, mode, &t);
+ }
+
Index: real.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/real.h,v
retrieving revision 1.64
diff -c -3 -p -r1.64 real.h
*** real.h	1 Apr 2003 21:45:27 -0000	1.64
--- real.h	9 Apr 2003 20:22:59 -0000
*************** extern bool real_sqrt			PARAMS ((REAL_VA
*** 365,368 ****
--- 365,374 ----
  						 enum machine_mode,
  						 const REAL_VALUE_TYPE *));

+ /* Calculate R as X raised to the integer exponent N in mode MODE.  */
+ extern void real_powi			PARAMS ((REAL_VALUE_TYPE *,
+ 						 enum machine_mode,
+ 						 const REAL_VALUE_TYPE *,
+ 						 HOST_WIDE_INT));
+
  #endif /* ! GCC_REAL_H */
Index: builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.c,v
retrieving revision 1.185
diff -c -3 -p -r1.185 builtins.c
*** builtins.c	8 Apr 2003 23:24:35 -0000	1.185
--- builtins.c	9 Apr 2003 20:23:00 -0000
*************** fold_builtin (exp)
*** 4724,4735 ****
  	  if (TREE_CODE (arg) == REAL_CST
  	      && ! TREE_CONSTANT_OVERFLOW (arg))
  	    {
- 	      enum machine_mode mode;
  	      REAL_VALUE_TYPE r, x;

  	      x = TREE_REAL_CST (arg);
! 	      mode = TYPE_MODE (type);
! 	      if (real_sqrt (&r, mode, &x)
  		  || (!flag_trapping_math && !flag_errno_math))
  		return build_real (type, r);
  	    }
--- 4724,4733 ----
  	  if (TREE_CODE (arg) == REAL_CST
  	      && ! TREE_CONSTANT_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);
  	    }
*************** fold_builtin (exp)
*** 4940,4945 ****
--- 4938,4964 ----
  		    {
  		      tree arglist = build_tree_list (NULL_TREE, arg0);
  		      return build_function_call_expr (sqrtfn, arglist);
+ 		    }
+ 		}
+
+ 	      /* Attempt to evaluate pow at compile-time.  */
+ 	      if (flag_unsafe_math_optimizations
+ 		  && TREE_CODE (arg0) == REAL_CST
+ 		  && ! TREE_CONSTANT_OVERFLOW (arg0))
+ 		{
+ 		  REAL_VALUE_TYPE cint;
+ 		  HOST_WIDE_INT n;
+
+ 		  n = real_to_integer(&c);
+ 		  real_from_integer (&cint, VOIDmode, n,
+ 				     n < 0 ? -1 : 0, 0);
+ 		  if (real_identical (&c, &cint))
+ 		    {
+ 		      REAL_VALUE_TYPE x;
+
+ 		      x = TREE_REAL_CST (arg0);
+ 		      real_powi (&x, TYPE_MODE (type), &x, n);
+ 		      return build_real (type, x);
  		    }
  		}
  	    }


/* Copyright (C) 2003 Free Software Foundation.

   Check that constant folding of built-in math functions doesn't
   break anything and produces the expected results.

   Written by Roger Sayle, 9th April 2003.  */

/* { dg-do link } */
/* { dg-options "-O2 -ffast-math" } */

extern void link_error(void);

extern double pow(double,double);


int main()
{
  if (pow (2.0, 3.0) != 8.0)
    link_error ();

  if (pow (2.0, -3.0) != 0.125)
    link_error ();

  return 0;
}


Roger
--
Roger Sayle,                         E-mail: roger at eyesopen dot 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]