diff options
author | Richard Sandiford <rsandifo@redhat.com> | 2002-03-07 11:37:16 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2002-03-07 11:37:16 +0000 |
commit | 71925bc04f24a40ab8ac587e08609cf91299e293 (patch) | |
tree | 74f74ccd7ea753279bc20a10577c6a90a6a4ba38 /gcc/simplify-rtx.c | |
parent | 145d3bf292a6cfc66a6396285003765db9424a8f (diff) | |
download | gcc-71925bc04f24a40ab8ac587e08609cf91299e293.zip gcc-71925bc04f24a40ab8ac587e08609cf91299e293.tar.gz gcc-71925bc04f24a40ab8ac587e08609cf91299e293.tar.bz2 |
defaults.h (MODE_HAS_NANS, [...]): New.
* defaults.h (MODE_HAS_NANS, MODE_HAS_INFINITIES): New.
(MODE_HAS_SIGNED_ZEROS, MODE_HAS_SIGN_DEPENDENT_ROUNDING): New.
* flags.h (HONOR_NANS, HONOR_INFINITIES, HONOR_SIGNED_ZEROS): New.
(HONOR_SIGN_DEPENDENT_ROUNDING): New.
* builtins.c (expand_builtin_mathfn): Use HONOR_NANS.
* c-common.c (truthvalue_conversion): Reduce x - y != 0 to x != y
unless x and y could be infinite.
(expand_unordered_cmp): New, mostly split from expand_tree_builtin.
Check that the common type of both arguments is a real, even for
targets without unordered comparisons. Allow an integer argument
to be compared against a real.
(expand_tree_builtin): Use expand_unordered_cmp.
* combine.c (combine_simplify_rtx): Use the new HONOR_... macros.
* cse.c (fold_rtx): Likewise. Fix indentation.
* fold-const.c (fold_real_zero_addition_p): New.
(fold): Use it, and the new HONOR_... macros.
* ifcvt.c (noce_try_minmax): Use the new HONOR_... macros.
* jump.c (reversed_comparison_code_parts): After searching for
the true comparison mode, use HONOR_NANS to decide whether it
can be safely reversed.
(reverse_condition_maybe_unordered): Remove IEEE check.
* simplify-rtx.c (simplify_binary_operation): Use the new macros
to decide which simplifications are valid. Allow the following
simplifications for IEEE: (-a + b) to (b - a), (a + -b) to (a - b),
and (a - -b) to (a + b).
(simplify_relational_operation): Use HONOR_NANS.
* doc/tm.texi: Document the MODE_HAS_... macros.
From-SVN: r50401
Diffstat (limited to 'gcc/simplify-rtx.c')
-rw-r--r-- | gcc/simplify-rtx.c | 63 |
1 files changed, 33 insertions, 30 deletions
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index b50a339..88ca32b 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -981,16 +981,15 @@ simplify_binary_operation (code, mode, op0, op1) switch (code) { case PLUS: - /* In IEEE floating point, x+0 is not the same as x. Similarly - for the other optimizations below. */ - if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT - && FLOAT_MODE_P (mode) && ! flag_unsafe_math_optimizations) - break; - - if (trueop1 == CONST0_RTX (mode)) + /* Maybe simplify x + 0 to x. The two expressions are equivalent + when x is NaN, infinite, or finite and non-zero. They aren't + when x is -0 and the rounding mode is not towards -infinity, + since (-0) + 0 is then 0. */ + if (!HONOR_SIGNED_ZEROS (mode) && trueop1 == CONST0_RTX (mode)) return op0; - /* ((-a) + b) -> (b - a) and similarly for (a + (-b)) */ + /* ((-a) + b) -> (b - a) and similarly for (a + (-b)). These + transformations are safe even for IEEE. */ if (GET_CODE (op0) == NEG) return simplify_gen_binary (MINUS, mode, op1, XEXP (op0, 0)); else if (GET_CODE (op1) == NEG) @@ -1122,12 +1121,6 @@ simplify_binary_operation (code, mode, op0, op1) break; case MINUS: - /* None of these optimizations can be done for IEEE - floating point. */ - if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT - && FLOAT_MODE_P (mode) && ! flag_unsafe_math_optimizations) - break; - /* We can't assume x-x is 0 even with non-IEEE floating point, but since it is zero except in very strange circumstances, we will treat it as zero with -funsafe-math-optimizations. */ @@ -1136,16 +1129,23 @@ simplify_binary_operation (code, mode, op0, op1) && (! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)) return CONST0_RTX (mode); - /* Change subtraction from zero into negation. */ - if (trueop0 == CONST0_RTX (mode)) + /* Change subtraction from zero into negation. (0 - x) is the + same as -x when x is NaN, infinite, or finite and non-zero. + But if the mode has signed zeros, and does not round towards + -infinity, then 0 - 0 is 0, not -0. */ + if (!HONOR_SIGNED_ZEROS (mode) && trueop0 == CONST0_RTX (mode)) return gen_rtx_NEG (mode, op1); /* (-1 - a) is ~a. */ if (trueop0 == constm1_rtx) return gen_rtx_NOT (mode, op1); - /* Subtracting 0 has no effect. */ - if (trueop1 == CONST0_RTX (mode)) + /* Subtracting 0 has no effect unless the mode has signed zeros + and supports rounding towards -infinity. In such a case, + 0 - 0 is -0. */ + if (!(HONOR_SIGNED_ZEROS (mode) + && HONOR_SIGN_DEPENDENT_ROUNDING (mode)) + && trueop1 == CONST0_RTX (mode)) return op0; /* See if this is something like X * C - X or vice versa or @@ -1202,7 +1202,7 @@ simplify_binary_operation (code, mode, op0, op1) } } - /* (a - (-b)) -> (a + b). */ + /* (a - (-b)) -> (a + b). True even for IEEE. */ if (GET_CODE (op1) == NEG) return simplify_gen_binary (PLUS, mode, op0, XEXP (op1, 0)); @@ -1248,9 +1248,12 @@ simplify_binary_operation (code, mode, op0, op1) return tem ? tem : gen_rtx_NEG (mode, op0); } - /* In IEEE floating point, x*0 is not always 0. */ - if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT - || ! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations) + /* Maybe simplify x * 0 to 0. The reduction is not valid if + x is NaN, since x * 0 is then also NaN. Nor is it valid + when the mode has signed zeros, since multiplying a negative + number by 0 will give -0, not 0. */ + if (!HONOR_NANS (mode) + && !HONOR_SIGNED_ZEROS (mode) && trueop1 == CONST0_RTX (mode) && ! side_effects_p (op0)) return op1; @@ -1361,9 +1364,12 @@ simplify_binary_operation (code, mode, op0, op1) return op0; } - /* In IEEE floating point, 0/x is not always 0. */ - if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT - || ! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations) + /* Maybe change 0 / x to 0. This transformation isn't safe for + modes with NaNs, since 0 / 0 will then be NaN rather than 0. + Nor is it safe for modes with signed zeros, since dividing + 0 by a negative number gives -0, not 0. */ + if (!HONOR_NANS (mode) + && !HONOR_SIGNED_ZEROS (mode) && trueop0 == CONST0_RTX (mode) && ! side_effects_p (op1)) return op0; @@ -2018,12 +2024,9 @@ simplify_relational_operation (code, mode, op0, op1) if (flag_unsafe_math_optimizations && code == UNORDERED) return const0_rtx; - /* For non-IEEE floating-point, if the two operands are equal, we know the + /* For modes without NaNs, if the two operands are equal, we know the result. */ - if (rtx_equal_p (trueop0, trueop1) - && (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT - || ! FLOAT_MODE_P (GET_MODE (trueop0)) - || flag_unsafe_math_optimizations)) + if (!HONOR_NANS (GET_MODE (trueop0)) && rtx_equal_p (trueop0, trueop1)) equal = 1, op0lt = 0, op0ltu = 0, op1lt = 0, op1ltu = 0; /* If the operands are floating-point constants, see if we can fold |