This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Evaluate pow(x,n) at compile-time
- From: Roger Sayle <roger at www dot eyesopen dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 9 Apr 2003 20:10:12 -0600 (MDT)
- Subject: [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