aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorRoger Sayle <sayle@gcc.gnu.org>2003-06-06 12:36:26 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2003-06-06 12:36:26 +0000
commit07bae5ad21964fd180a8f85e300cf823dfa04b53 (patch)
tree853d13ba808d4dc5f75ea461cff59feb4787b64b /gcc/fold-const.c
parent84cd52a9a95c0737455364222901afb418f7c345 (diff)
downloadgcc-07bae5ad21964fd180a8f85e300cf823dfa04b53.zip
gcc-07bae5ad21964fd180a8f85e300cf823dfa04b53.tar.gz
gcc-07bae5ad21964fd180a8f85e300cf823dfa04b53.tar.bz2
fold-const.c (fold <ABS_EXPR>): Re-fold the result of folding fabs(-x) into fabs(x).
* fold-const.c (fold <ABS_EXPR>): Re-fold the result of folding fabs(-x) into fabs(x). Use tree_expr_nonnegative_p to determine when the ABS_EXPR (fabs or abs) is not required. (tree_expr_nonnegative_p): Move the logic that sqrt and exp are always nonnegative from fold to here. Additionally, cabs and fabs are always non-negative, and pow and atan are non-negative if their first argument is non-negative. * builtins.c (fold_builtin_cabs): New function to fold cabs{,f,l}. Evaluate cabs of a constant at compile-time. Convert cabs of a non-complex argument into fabs. Convert cabs(z) into sqrt(z.r*z.r + z.i*z.i) at the tree-level with -ffast-math or -funsafe-math-optimizations or -ffast-math. (fold_builtin): Convert BUILT_IN_FABS{,F,L} into an ABS_EXPR. Fold BUILT_IN_CABS{,F,L} using fold_builtin_cabs. * gcc.dg/builtins-2.c: Add some more tests. * gcc.dg/builtins-18.c: New test case. * gcc.dg/builtins-19.c: New test case. From-SVN: r67541
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c63
1 files changed, 47 insertions, 16 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index e81e809..aa99e40 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -5405,29 +5405,19 @@ fold (expr)
REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
}
}
- else if (TREE_CODE (arg0) == ABS_EXPR || TREE_CODE (arg0) == NEGATE_EXPR)
- return build1 (ABS_EXPR, type, TREE_OPERAND (arg0, 0));
+ else if (TREE_CODE (arg0) == NEGATE_EXPR)
+ return fold (build1 (ABS_EXPR, type, TREE_OPERAND (arg0, 0)));
/* Convert fabs((double)float) into (double)fabsf(float). */
else if (TREE_CODE (arg0) == NOP_EXPR
&& TREE_CODE (type) == REAL_TYPE)
{
tree targ0 = strip_float_extensions (arg0);
if (targ0 != arg0)
- return convert (type, build1 (ABS_EXPR, TREE_TYPE (targ0), targ0));
-
- }
- else
- {
- /* fabs(sqrt(x)) = sqrt(x) and fabs(exp(x)) = exp(x). */
- enum built_in_function fcode = builtin_mathfn_code (arg0);
- if (fcode == BUILT_IN_SQRT
- || fcode == BUILT_IN_SQRTF
- || fcode == BUILT_IN_SQRTL
- || fcode == BUILT_IN_EXP
- || fcode == BUILT_IN_EXPF
- || fcode == BUILT_IN_EXPL)
- t = arg0;
+ return convert (type, fold (build1 (ABS_EXPR, TREE_TYPE (targ0),
+ targ0)));
}
+ else if (tree_expr_nonnegative_p (arg0))
+ return arg0;
return t;
case CONJ_EXPR:
@@ -7928,6 +7918,47 @@ tree_expr_nonnegative_p (t)
case RTL_EXPR:
return rtl_expr_nonnegative_p (RTL_EXPR_RTL (t));
+ case CALL_EXPR:
+ if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR)
+ {
+ tree fndecl = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
+ tree arglist = TREE_OPERAND (t, 1);
+ if (TREE_CODE (fndecl) == FUNCTION_DECL
+ && DECL_BUILT_IN (fndecl)
+ && DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_MD)
+ switch (DECL_FUNCTION_CODE (fndecl))
+ {
+ case BUILT_IN_CABS:
+ case BUILT_IN_CABSL:
+ case BUILT_IN_CABSF:
+ case BUILT_IN_EXP:
+ case BUILT_IN_EXPF:
+ case BUILT_IN_EXPL:
+ case BUILT_IN_FABS:
+ case BUILT_IN_FABSF:
+ case BUILT_IN_FABSL:
+ case BUILT_IN_SQRT:
+ case BUILT_IN_SQRTF:
+ case BUILT_IN_SQRTL:
+ return 1;
+
+ case BUILT_IN_ATAN:
+ case BUILT_IN_ATANF:
+ case BUILT_IN_ATANL:
+ return tree_expr_nonnegative_p (TREE_VALUE (arglist));
+
+ case BUILT_IN_POW:
+ case BUILT_IN_POWF:
+ case BUILT_IN_POWL:
+ return tree_expr_nonnegative_p (TREE_VALUE (arglist));
+
+ default:
+ break;
+ }
+ }
+
+ /* ... fall through ... */
+
default:
if (truth_value_p (TREE_CODE (t)))
/* Truth values evaluate to 0 or 1, which is nonnegative. */