diff options
author | Roger Sayle <sayle@gcc.gnu.org> | 2003-06-06 12:36:26 +0000 |
---|---|---|
committer | Roger Sayle <sayle@gcc.gnu.org> | 2003-06-06 12:36:26 +0000 |
commit | 07bae5ad21964fd180a8f85e300cf823dfa04b53 (patch) | |
tree | 853d13ba808d4dc5f75ea461cff59feb4787b64b /gcc/fold-const.c | |
parent | 84cd52a9a95c0737455364222901afb418f7c345 (diff) | |
download | gcc-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.c | 63 |
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. */ |