aboutsummaryrefslogtreecommitdiff
path: root/gcc/simplify-rtx.c
diff options
context:
space:
mode:
authorRichard Sandiford <rsandifo@redhat.com>2002-03-07 11:37:16 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2002-03-07 11:37:16 +0000
commit71925bc04f24a40ab8ac587e08609cf91299e293 (patch)
tree74f74ccd7ea753279bc20a10577c6a90a6a4ba38 /gcc/simplify-rtx.c
parent145d3bf292a6cfc66a6396285003765db9424a8f (diff)
downloadgcc-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.c63
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