[PATCH] Constant folding pow(x,y) for constant y.
Roger Sayle
roger@www.eyesopen.com
Mon Mar 31 01:40:00 GMT 2003
The following patch is another installment in my series of constant
folding optimizations for the pow(3) builtin-function. This round
performs constant folding of pow(x,y) where y is a constant.
This patch also contains a additional call to "fold" when
building exp(x/2.0), and constant folding of sin(0.0) and
cos(0.0). These hunks didn't seem significant enough to
post separately.
The following patch has been tested by a complete bootstrap on
i686-pc-linux-gnu, all languages except Ada and treelang, and
regression tested with a top-level "make -k check" (except for
libjava due to timeouts) with no new regressions.
Ok for mainline?
2002-03-30 Roger Sayle <roger@eyesopen.com>
* emit-rtl.c (dconstm2, dconsthalf): New real constants.
(init_emit_once): Initialize dconstm2 and dconsthalf here.
* real.h (dconstm2, dconsthalf): Add prototypes here.
* real.c (real_sqrt): Use dconsthalf rather than local copy.
* builtins.c (fold_builtin): When optimizing sqrt(exp(x)) as
exp(x/2.0) remember to fold the division if possible.
Fold sin(0.0) as 0.0, cos(0.0) as 1.0, pow(x,1.0) as x,
pow(x,-1.0) as 1.0/x, pow(x,2.0) as x*x, pow(x,-2.0) as
1.0/(x*x) and pow(x,0.5) as sqrt(x).
* gcc.dg/builtins-3.c: Add new tests for sin and cos.
* gcc.dg/builtins-7.c: New test case.
* gcc.dg/builtins-8.c: New test case.
Index: emit-rtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/emit-rtl.c,v
retrieving revision 1.316
diff -c -3 -p -r1.316 emit-rtl.c
*** emit-rtl.c 13 Mar 2003 09:02:50 -0000 1.316
--- emit-rtl.c 30 Mar 2003 23:13:10 -0000
*************** REAL_VALUE_TYPE dconst0;
*** 111,116 ****
--- 111,118 ----
REAL_VALUE_TYPE dconst1;
REAL_VALUE_TYPE dconst2;
REAL_VALUE_TYPE dconstm1;
+ REAL_VALUE_TYPE dconstm2;
+ REAL_VALUE_TYPE dconsthalf;
/* All references to the following fixed hard registers go through
these unique rtl objects. On machines where the frame-pointer and
*************** init_emit_once (line_numbers)
*** 5552,5557 ****
--- 5554,5563 ----
REAL_VALUE_FROM_INT (dconst1, 1, 0, double_mode);
REAL_VALUE_FROM_INT (dconst2, 2, 0, double_mode);
REAL_VALUE_FROM_INT (dconstm1, -1, -1, double_mode);
+ REAL_VALUE_FROM_INT (dconstm2, -2, -1, double_mode);
+
+ dconsthalf = dconst1;
+ dconsthalf.exp--;
for (i = 0; i <= 2; i++)
{
Index: real.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/real.h,v
retrieving revision 1.62
diff -c -3 -p -r1.62 real.h
*** real.h 27 Mar 2003 22:42:02 -0000 1.62
--- real.h 30 Mar 2003 23:13:10 -0000
*************** extern void real_ldexp PARAMS ((REAL_VA
*** 322,333 ****
/* **** End of software floating point emulator interface macros **** */
! /* Constant real values 0, 1, 2, and -1. */
extern REAL_VALUE_TYPE dconst0;
extern REAL_VALUE_TYPE dconst1;
extern REAL_VALUE_TYPE dconst2;
extern REAL_VALUE_TYPE dconstm1;
/* Function to return a real value (not a tree node)
from a given integer constant. */
--- 322,335 ----
/* **** End of software floating point emulator interface macros **** */
! /* Constant real values 0, 1, 2, -1, -2 and 0.5. */
extern REAL_VALUE_TYPE dconst0;
extern REAL_VALUE_TYPE dconst1;
extern REAL_VALUE_TYPE dconst2;
extern REAL_VALUE_TYPE dconstm1;
+ extern REAL_VALUE_TYPE dconstm2;
+ extern REAL_VALUE_TYPE dconsthalf;
/* Function to return a real value (not a tree node)
from a given integer constant. */
Index: real.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/real.c,v
retrieving revision 1.112
diff -c -3 -p -r1.112 real.c
*** real.c 27 Mar 2003 22:41:58 -0000 1.112
--- real.c 30 Mar 2003 23:13:11 -0000
*************** real_sqrt (r, mode, x)
*** 4423,4429 ****
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;
--- 4423,4428 ----
*************** real_sqrt (r, mode, x)
*** 4452,4459 ****
if (!init)
{
! real_arithmetic (&half, RDIV_EXPR, &dconst1, &dconst2);
! real_arithmetic (&halfthree, PLUS_EXPR, &dconst1, &half);
init = true;
}
--- 4451,4457 ----
if (!init)
{
! real_arithmetic (&halfthree, PLUS_EXPR, &dconst1, &dconsthalf);
init = true;
}
*************** real_sqrt (r, mode, x)
*** 4467,4473 ****
/* 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);
--- 4465,4471 ----
/* 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, &dconsthalf);
real_arithmetic (&h, MINUS_EXPR, &halfthree, &t);
real_arithmetic (&t, MULT_EXPR, &i, &h);
*************** real_sqrt (r, mode, x)
*** 4484,4490 ****
real_arithmetic (&h, MULT_EXPR, &t, &i);
real_arithmetic (&i, MINUS_EXPR, &dconst1, &h);
real_arithmetic (&h, MULT_EXPR, &t, &i);
! real_arithmetic (&i, MULT_EXPR, &half, &h);
real_arithmetic (&h, PLUS_EXPR, &t, &i);
/* ??? We need a Tuckerman test to get the last bit. */
--- 4482,4488 ----
real_arithmetic (&h, MULT_EXPR, &t, &i);
real_arithmetic (&i, MINUS_EXPR, &dconst1, &h);
real_arithmetic (&h, MULT_EXPR, &t, &i);
! real_arithmetic (&i, MULT_EXPR, &dconsthalf, &h);
real_arithmetic (&h, PLUS_EXPR, &t, &i);
/* ??? We need a Tuckerman test to get the last bit. */
Index: builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.c,v
retrieving revision 1.183
diff -c -3 -p -r1.183 builtins.c
*** builtins.c 24 Mar 2003 01:24:37 -0000 1.183
--- builtins.c 30 Mar 2003 23:13:12 -0000
*************** fold_builtin (exp)
*** 4743,4757 ****
|| fcode == BUILT_IN_EXPL))
{
tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
! arg = build (RDIV_EXPR, type,
! TREE_VALUE (TREE_OPERAND (arg, 1)),
! build_real (type, dconst2));
arglist = build_tree_list (NULL_TREE, arg);
return build_function_call_expr (expfn, arglist);
}
}
break;
case BUILT_IN_EXP:
case BUILT_IN_EXPF:
case BUILT_IN_EXPL:
--- 4743,4783 ----
|| fcode == BUILT_IN_EXPL))
{
tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
! arg = fold (build (RDIV_EXPR, type,
! TREE_VALUE (TREE_OPERAND (arg, 1)),
! build_real (type, dconst2)));
arglist = build_tree_list (NULL_TREE, arg);
return build_function_call_expr (expfn, arglist);
}
}
break;
+ case BUILT_IN_SIN:
+ case BUILT_IN_SINF:
+ case BUILT_IN_SINL:
+ if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+ {
+ tree arg = TREE_VALUE (arglist);
+
+ /* Optimize sin(0.0) = 0.0. */
+ if (real_zerop (arg))
+ return build_real (type, dconst0);
+ }
+ break;
+
+ case BUILT_IN_COS:
+ case BUILT_IN_COSF:
+ case BUILT_IN_COSL:
+ if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+ {
+ tree arg = TREE_VALUE (arglist);
+
+ /* Optimize cos(0.0) = 1.0. */
+ if (real_zerop (arg))
+ return build_real (type, dconst1);
+ }
+ break;
+
case BUILT_IN_EXP:
case BUILT_IN_EXPF:
case BUILT_IN_EXPL:
*************** fold_builtin (exp)
*** 4816,4828 ****
tree arg0 = TREE_VALUE (arglist);
tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- /* Optimize pow(x,0.0) = 1.0. */
- if (real_zerop (arg1))
- return omit_one_operand (type, build_real (type, dconst1), arg0);
-
/* Optimize pow(1.0,y) = 1.0. */
if (real_onep (arg0))
return omit_one_operand (type, build_real (type, dconst1), arg1);
}
break;
--- 4842,4916 ----
tree arg0 = TREE_VALUE (arglist);
tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
/* Optimize pow(1.0,y) = 1.0. */
if (real_onep (arg0))
return omit_one_operand (type, build_real (type, dconst1), arg1);
+
+ if (TREE_CODE (arg1) == REAL_CST
+ && ! TREE_CONSTANT_OVERFLOW (arg1))
+ {
+ REAL_VALUE_TYPE c;
+ c = TREE_REAL_CST (arg1);
+
+ /* Optimize pow(x,0.0) = 1.0. */
+ if (REAL_VALUES_EQUAL (c, dconst0))
+ return omit_one_operand (type, build_real (type, dconst1),
+ arg0);
+
+ /* Optimize pow(x,1.0) = x. */
+ if (REAL_VALUES_EQUAL (c, dconst1))
+ return arg0;
+
+ /* Optimize pow(x,-1.0) = 1.0/x. */
+ if (REAL_VALUES_EQUAL (c, dconstm1))
+ return fold (build (RDIV_EXPR, type,
+ build_real (type, dconst1),
+ arg0));
+
+ /* Optimize pow(x,2.0) = x*x. */
+ if (REAL_VALUES_EQUAL (c, dconst2)
+ && (*lang_hooks.decls.global_bindings_p) () == 0
+ && ! contains_placeholder_p (arg0))
+ {
+ arg0 = save_expr (arg0);
+ return fold (build (MULT_EXPR, type, arg0, arg0));
+ }
+
+ /* Optimize pow(x,-2.0) = 1.0/(x*x). */
+ if (flag_unsafe_math_optimizations
+ && REAL_VALUES_EQUAL (c, dconstm2)
+ && (*lang_hooks.decls.global_bindings_p) () == 0
+ && ! contains_placeholder_p (arg0))
+ {
+ arg0 = save_expr (arg0);
+ return fold (build (RDIV_EXPR, type,
+ build_real (type, dconst1),
+ fold (build (MULT_EXPR, type,
+ arg0, arg0))));
+ }
+
+ /* Optimize pow(x,0.5) = sqrt(x). */
+ if (flag_unsafe_math_optimizations
+ && REAL_VALUES_EQUAL (c, dconsthalf))
+ {
+ tree sqrtfn;
+
+ if (fcode == BUILT_IN_POW)
+ sqrtfn = implicit_built_in_decls[BUILT_IN_SQRT];
+ else if (fcode == BUILT_IN_POWF)
+ sqrtfn = implicit_built_in_decls[BUILT_IN_SQRTF];
+ else if (fcode == BUILT_IN_POWL)
+ sqrtfn = implicit_built_in_decls[BUILT_IN_SQRTL];
+ else
+ sqrtfn = NULL_TREE;
+
+ if (sqrtfn != NULL_TREE)
+ {
+ tree arglist = build_tree_list (NULL_TREE, arg0);
+ return build_function_call_expr (sqrtfn, arglist);
+ }
+ }
+ }
}
break;
Index: testsuite/gcc.dg/builtins-3.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/builtins-3.c,v
retrieving revision 1.2
diff -c -3 -p -r1.2 builtins-3.c
*** testsuite/gcc.dg/builtins-3.c 16 Dec 2002 18:22:43 -0000 1.2
--- testsuite/gcc.dg/builtins-3.c 30 Mar 2003 23:13:12 -0000
***************
*** 1,7 ****
! /* Copyright (C) 2002 Free Software Foundation.
Verify that built-in math function constant folding of constant
! arguments is correctly performed by the by the compiler.
Written by Roger Sayle, 16th August 2002. */
--- 1,7 ----
! /* Copyright (C) 2002, 2003 Free Software Foundation.
Verify that built-in math function constant folding of constant
! arguments is correctly performed by the compiler.
Written by Roger Sayle, 16th August 2002. */
*************** int main()
*** 24,29 ****
--- 24,35 ----
if (log (1.0) != 0.0)
link_error ();
+ if (sin (0.0) != 0.0)
+ link_error ();
+
+ if (cos (0.0) != 1.0)
+ link_error ();
+
if (sqrtf (0.0f) != 0.0f)
link_error ();
*************** int main()
*** 37,42 ****
--- 43,54 ----
if (logf (1.0f) != 0.0f)
link_error ();
+ if (sinf (0.0f) != 0.0f)
+ link_error ();
+
+ if (cosf (0.0f) != 1.0f)
+ link_error ();
+
if (sqrtl (0.0l) != 0.0l)
link_error ();
*************** int main()
*** 48,53 ****
--- 60,71 ----
link_error ();
if (logl (1.0l) != 0.0l)
+ link_error ();
+
+ if (sinl (0.0l) != 0.0l)
+ link_error ();
+
+ if (cosl (0.0l) != 1.0l)
link_error ();
return 0;
/* Copyright (C) 2003 Free Software Foundation.
Verify that built-in math function constant folding of constant
arguments is correctly performed by the compiler.
Written by Roger Sayle, 30th March 2003. */
/* { dg-do link } */
/* { dg-options "-O2 -ffast-math" } */
extern void link_error(void);
void test(double x)
{
if (pow (x, 1.0) != x)
link_error ();
}
void testf(float x)
{
if (powf (x, 1.0f) != x)
link_error ();
}
void testl(long double x)
{
if (powl (x, 1.0l) != x)
link_error ();
}
int main()
{
test (2.0);
testf (2.0f);
testl (2.0l);
return 0;
}
/* Copyright (C) 2003 Free Software Foundation.
Verify that built-in math function constant folding of functions
with one constant argument is correctly performed by the compiler.
Written by Roger Sayle, 30th March 2003. */
/* { dg-do run } */
/* { dg-options "-O2 -ffast-math" } */
extern void abort(void);
void test(double x)
{
if (pow(x,-1.0) != 1.0/x)
abort ();
if (pow(x,2.0) != x*x)
abort ();
if (pow(x,-2.0) != 1.0/(x*x))
abort ();
if (pow(x,0.5) != sqrt(x))
abort ();
}
int main()
{
test (1.0);
test (2.0);
return 0;
}
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
More information about the Gcc-patches
mailing list