summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>2003-03-31 14:30:29 +0000
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>2003-03-31 14:30:29 +0000
commit77e8926908df33778b3152c8f9e653b67462bdef (patch)
treeae8fad7cd3fde47e1b9f8cb921dd6289d19b33cf /gcc
parent503cb1bd228d5d0fe73f0508984e050df7e9f342 (diff)
downloadgcc-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/ChangeLog12
-rw-r--r--gcc/builtins.c102
-rw-r--r--gcc/emit-rtl.c6
-rw-r--r--gcc/real.c8
-rw-r--r--gcc/real.h4
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/builtins-3.c22
-rw-r--r--gcc/testsuite/gcc.dg/builtins-7.c39
-rw-r--r--gcc/testsuite/gcc.dg/builtins-8.c34
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;
+}
+