summaryrefslogtreecommitdiff
path: root/gcc/builtins.c
diff options
context:
space:
mode:
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>2005-02-09 21:56:35 +0000
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>2005-02-09 21:56:35 +0000
commit198d9bbee87d11cad4547476146f84d5495c0260 (patch)
treeb165cf0028ec1a832fc59f34df44d639c9c318a2 /gcc/builtins.c
parentd1001cc93ca3fc8a93e1048911c52dab4a56d6da (diff)
downloadgcc-198d9bbee87d11cad4547476146f84d5495c0260.tar.gz
* fold-const.c (fold_strip_sign_ops): New function to simplify a
floating point expression ignoring the sign of the result. (fold) <ABS_EXPR>: Use it to simplify fabs(x). (fold) <MULT_EXPR>: Use it to simplify x*x. * tree.h (fold_strip_sign_ops): Prototype here. * builtins.c (fold_builtin_copysign): Take an additional FNDECL argument. Use fold_strip_sign_ops to simplify the first argument. (fold_builtin_pow): Use fold_strip_sign_ops to simplify the first argument when the second argument is an even integer constant, but only with -funsafe_math_optimizations. (fold_builtin_1): Update call to fold_builtin_copysign. * gcc.dg/builtins-48.c: New test case. * gcc.dg/builtins-49.c: New test case. * gcc.dg/builtins-50.c: New test case. * gcc.dg/builtins-51.c: New test case. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@94779 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r--gcc/builtins.c48
1 files changed, 34 insertions, 14 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 36316156c5f..56e7eb00e39 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -169,7 +169,7 @@ static tree fold_builtin_memcmp (tree);
static tree fold_builtin_strcmp (tree);
static tree fold_builtin_strncmp (tree);
static tree fold_builtin_signbit (tree);
-static tree fold_builtin_copysign (tree, tree);
+static tree fold_builtin_copysign (tree, tree, tree);
static tree fold_builtin_isascii (tree);
static tree fold_builtin_toascii (tree);
static tree fold_builtin_isdigit (tree);
@@ -6844,7 +6844,10 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type)
if (TREE_CODE (arg1) == REAL_CST
&& ! TREE_CONSTANT_OVERFLOW (arg1))
{
+ REAL_VALUE_TYPE cint;
REAL_VALUE_TYPE c;
+ HOST_WIDE_INT n;
+
c = TREE_REAL_CST (arg1);
/* Optimize pow(x,0.0) = 1.0. */
@@ -6874,17 +6877,14 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type)
}
}
- /* Attempt to evaluate pow at compile-time. */
- if (TREE_CODE (arg0) == REAL_CST
- && ! TREE_CONSTANT_OVERFLOW (arg0))
+ /* Check for an integer exponent. */
+ n = real_to_integer (&c);
+ real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
+ if (real_identical (&c, &cint))
{
- 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))
+ /* Attempt to evaluate pow at compile-time. */
+ if (TREE_CODE (arg0) == REAL_CST
+ && ! TREE_CONSTANT_OVERFLOW (arg0))
{
REAL_VALUE_TYPE x;
bool inexact;
@@ -6894,6 +6894,18 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type)
if (flag_unsafe_math_optimizations || !inexact)
return build_real (type, x);
}
+
+ /* Strip sign ops from even integer powers. */
+ if ((n & 1) == 0 && flag_unsafe_math_optimizations)
+ {
+ tree narg0 = fold_strip_sign_ops (arg0);
+ if (narg0)
+ {
+ arglist = build_tree_list (NULL_TREE, arg1);
+ arglist = tree_cons (NULL_TREE, narg0, arglist);
+ return build_function_call_expr (fndecl, arglist);
+ }
+ }
}
}
@@ -7447,9 +7459,9 @@ fold_builtin_signbit (tree exp)
Return NULL_TREE if no simplification can be made. */
static tree
-fold_builtin_copysign (tree arglist, tree type)
+fold_builtin_copysign (tree fndecl, tree arglist, tree type)
{
- tree arg1, arg2;
+ tree arg1, arg2, tem;
if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
return NULL_TREE;
@@ -7483,6 +7495,14 @@ fold_builtin_copysign (tree arglist, tree type)
fold (build1 (ABS_EXPR, type, arg1)),
arg2);
+ /* Strip sign changing operations for the first argument. */
+ tem = fold_strip_sign_ops (arg1);
+ if (tem)
+ {
+ arglist = tree_cons (NULL_TREE, tem, TREE_CHAIN (arglist));
+ return build_function_call_expr (fndecl, arglist);
+ }
+
return NULL_TREE;
}
@@ -8056,7 +8076,7 @@ fold_builtin_1 (tree exp, bool ignore)
case BUILT_IN_COPYSIGN:
case BUILT_IN_COPYSIGNF:
case BUILT_IN_COPYSIGNL:
- return fold_builtin_copysign (arglist, type);
+ return fold_builtin_copysign (fndecl, arglist, type);
case BUILT_IN_FINITE:
case BUILT_IN_FINITEF: