diff options
author | sayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-03-31 14:30:29 +0000 |
---|---|---|
committer | sayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-03-31 14:30:29 +0000 |
commit | 77e8926908df33778b3152c8f9e653b67462bdef (patch) | |
tree | ae8fad7cd3fde47e1b9f8cb921dd6289d19b33cf /gcc | |
parent | 503cb1bd228d5d0fe73f0508984e050df7e9f342 (diff) | |
download | gcc-77e8926908df33778b3152c8f9e653b67462bdef.tar.gz |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@65088 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/builtins.c | 102 | ||||
-rw-r--r-- | gcc/emit-rtl.c | 6 | ||||
-rw-r--r-- | gcc/real.c | 8 | ||||
-rw-r--r-- | gcc/real.h | 4 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/builtins-3.c | 22 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/builtins-7.c | 39 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/builtins-8.c | 34 |
9 files changed, 218 insertions, 15 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fd3e32a6af9..c7b59f0071f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2003-03-31 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). + 2003-03-31 Kazu Hirata <kazu@cs.umass.edu> * config/h8300/h8300.md (a new peephole2): New. diff --git a/gcc/builtins.c b/gcc/builtins.c index b6fe4b4fbe6..d446185c8c5 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -4743,15 +4743,41 @@ fold_builtin (exp) || 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)); + 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: @@ -4816,13 +4842,75 @@ fold_builtin (exp) 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); + + 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; diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index ad30637ee0a..4aab67494d4 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -111,6 +111,8 @@ REAL_VALUE_TYPE dconst0; 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 @@ -5552,6 +5554,10 @@ init_emit_once (line_numbers) 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++) { diff --git a/gcc/real.c b/gcc/real.c index f6074f99639..04bf718a743 100644 --- a/gcc/real.c +++ b/gcc/real.c @@ -4423,7 +4423,6 @@ real_sqrt (r, mode, x) 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; @@ -4452,8 +4451,7 @@ real_sqrt (r, mode, x) if (!init) { - real_arithmetic (&half, RDIV_EXPR, &dconst1, &dconst2); - real_arithmetic (&halfthree, PLUS_EXPR, &dconst1, &half); + real_arithmetic (&halfthree, PLUS_EXPR, &dconst1, &dconsthalf); init = true; } @@ -4467,7 +4465,7 @@ real_sqrt (r, mode, x) /* 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 (&t, MULT_EXPR, &h, &dconsthalf); real_arithmetic (&h, MINUS_EXPR, &halfthree, &t); real_arithmetic (&t, MULT_EXPR, &i, &h); @@ -4484,7 +4482,7 @@ real_sqrt (r, mode, x) 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 (&i, MULT_EXPR, &dconsthalf, &h); real_arithmetic (&h, PLUS_EXPR, &t, &i); /* ??? We need a Tuckerman test to get the last bit. */ diff --git a/gcc/real.h b/gcc/real.h index d16231acae8..9507af2270d 100644 --- a/gcc/real.h +++ b/gcc/real.h @@ -322,12 +322,14 @@ extern void real_ldexp PARAMS ((REAL_VALUE_TYPE *, /* **** End of software floating point emulator interface macros **** */ -/* Constant real values 0, 1, 2, and -1. */ +/* 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. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2469ea4ed73..fdc97e104e2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2003-03-31 Roger Sayle <roger@eyesopen.com> + + * 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. + 2003-03-31 Richard Sandiford <rsandifo@redhat.com> * gcc.c-torture/execute/ieee/20030331-1.c: New test. diff --git a/gcc/testsuite/gcc.dg/builtins-3.c b/gcc/testsuite/gcc.dg/builtins-3.c index 49bea5e126e..3c2dbfd7f52 100644 --- a/gcc/testsuite/gcc.dg/builtins-3.c +++ b/gcc/testsuite/gcc.dg/builtins-3.c @@ -1,7 +1,7 @@ -/* Copyright (C) 2002 Free Software Foundation. +/* Copyright (C) 2002, 2003 Free Software Foundation. Verify that built-in math function constant folding of constant - arguments is correctly performed by the by the compiler. + arguments is correctly performed by the compiler. Written by Roger Sayle, 16th August 2002. */ @@ -24,6 +24,12 @@ int main() 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 (); @@ -37,6 +43,12 @@ int main() 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 (); @@ -50,6 +62,12 @@ int main() 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; } diff --git a/gcc/testsuite/gcc.dg/builtins-7.c b/gcc/testsuite/gcc.dg/builtins-7.c new file mode 100644 index 00000000000..84c0e154fa0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtins-7.c @@ -0,0 +1,39 @@ +/* Copyright (C) 2003 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, 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; +} + diff --git a/gcc/testsuite/gcc.dg/builtins-8.c b/gcc/testsuite/gcc.dg/builtins-8.c new file mode 100644 index 00000000000..99d1a70d01a --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtins-8.c @@ -0,0 +1,34 @@ +/* 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; +} + |