diff options
author | Roger Sayle <roger@eyesopen.com> | 2005-02-09 21:56:35 +0000 |
---|---|---|
committer | Roger Sayle <sayle@gcc.gnu.org> | 2005-02-09 21:56:35 +0000 |
commit | e3bb43c0fef35c410538453c6a70a22822e03b10 (patch) | |
tree | b165cf0028ec1a832fc59f34df44d639c9c318a2 /gcc/fold-const.c | |
parent | 08c2481a791a11ac8aee6652c6fb8c57faf4d584 (diff) | |
download | gcc-e3bb43c0fef35c410538453c6a70a22822e03b10.zip gcc-e3bb43c0fef35c410538453c6a70a22822e03b10.tar.gz gcc-e3bb43c0fef35c410538453c6a70a22822e03b10.tar.bz2 |
fold-const.c (fold_strip_sign_ops): New function to simplify a floating point expression ignoring the sign of the...
* 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.
From-SVN: r94779
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r-- | gcc/fold-const.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 294f94c..de54258 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -6776,6 +6776,14 @@ fold (tree expr) } else if (tree_expr_nonnegative_p (arg0)) return arg0; + + /* Strip sign ops from argument. */ + if (TREE_CODE (type) == REAL_TYPE) + { + tem = fold_strip_sign_ops (arg0); + if (tem) + return fold (build1 (ABS_EXPR, type, fold_convert (type, tem))); + } return t; case CONJ_EXPR: @@ -7429,6 +7437,17 @@ fold (tree expr) TREE_OPERAND (arg0, 1))); } + /* Strip sign operations from X in X*X, i.e. -Y*-Y -> Y*Y. */ + if (operand_equal_p (arg0, arg1, 0)) + { + tree tem = fold_strip_sign_ops (arg0); + if (tem != NULL_TREE) + { + tem = fold_convert (type, tem); + return fold (build2 (MULT_EXPR, type, tem, tem)); + } + } + if (flag_unsafe_math_optimizations) { enum built_in_function fcode0 = builtin_mathfn_code (arg0); @@ -11229,3 +11248,38 @@ ptr_difference_const (tree e1, tree e2, HOST_WIDE_INT *diff) *diff += (bitpos1 - bitpos2) / BITS_PER_UNIT; return true; } + +/* Simplify the floating point expression EXP when the sign of the + result is not significant. Return NULL_TREE if no simplification + is possible. */ + +tree +fold_strip_sign_ops (tree exp) +{ + tree arg0, arg1; + + switch (TREE_CODE (exp)) + { + case ABS_EXPR: + case NEGATE_EXPR: + arg0 = fold_strip_sign_ops (TREE_OPERAND (exp, 0)); + return arg0 ? arg0 : TREE_OPERAND (exp, 0); + + case MULT_EXPR: + case RDIV_EXPR: + if (HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (TREE_TYPE (exp)))) + return NULL_TREE; + arg0 = fold_strip_sign_ops (TREE_OPERAND (exp, 0)); + arg1 = fold_strip_sign_ops (TREE_OPERAND (exp, 1)); + if (arg0 != NULL_TREE || arg1 != NULL_TREE) + return fold (build2 (TREE_CODE (exp), TREE_TYPE (exp), + arg0 ? arg0 : TREE_OPERAND (exp, 0), + arg1 ? arg1 : TREE_OPERAND (exp, 1))); + break; + + default: + break; + } + return NULL_TREE; +} + |