Commit 71925bc0 by Richard Sandiford Committed by Richard Sandiford

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
parent 145d3bf2
2002-03-07 Richard Sandiford <rsandifo@redhat.com>
* 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.
2002-03-07 Richard Earnshaw <rearnsha@arm.com> 2002-03-07 Richard Earnshaw <rearnsha@arm.com>
* combine.c (simplify_comparison): If simplifying a logical shift * combine.c (simplify_comparison): If simplifying a logical shift
......
...@@ -1470,6 +1470,7 @@ expand_builtin_mathfn (exp, target, subtarget) ...@@ -1470,6 +1470,7 @@ expand_builtin_mathfn (exp, target, subtarget)
rtx op0, insns; rtx op0, insns;
tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
tree arglist = TREE_OPERAND (exp, 1); tree arglist = TREE_OPERAND (exp, 1);
enum machine_mode argmode;
if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
return 0; return 0;
...@@ -1518,8 +1519,8 @@ expand_builtin_mathfn (exp, target, subtarget) ...@@ -1518,8 +1519,8 @@ expand_builtin_mathfn (exp, target, subtarget)
/* Compute into TARGET. /* Compute into TARGET.
Set TARGET to wherever the result comes back. */ Set TARGET to wherever the result comes back. */
target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))), argmode = TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist)));
builtin_optab, op0, target, 0); target = expand_unop (argmode, builtin_optab, op0, target, 0);
/* If we were unable to expand via the builtin, stop the /* If we were unable to expand via the builtin, stop the
sequence (without outputting the insns) and return 0, causing sequence (without outputting the insns) and return 0, causing
...@@ -1530,18 +1531,12 @@ expand_builtin_mathfn (exp, target, subtarget) ...@@ -1530,18 +1531,12 @@ expand_builtin_mathfn (exp, target, subtarget)
return 0; return 0;
} }
/* If errno must be maintained and if we are not allowing unsafe /* If errno must be maintained, we must set it to EDOM for NaN results. */
math optimizations, check the result. */
if (flag_errno_math && ! flag_unsafe_math_optimizations) if (flag_errno_math && HONOR_NANS (argmode))
{ {
rtx lab1; rtx lab1;
/* Don't define the builtin FP instructions
if your machine is not IEEE. */
if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT)
abort ();
lab1 = gen_label_rtx (); lab1 = gen_label_rtx ();
/* Test the result; if it is NaN, set errno=EDOM because /* Test the result; if it is NaN, set errno=EDOM because
......
...@@ -2202,10 +2202,15 @@ truthvalue_conversion (expr) ...@@ -2202,10 +2202,15 @@ truthvalue_conversion (expr)
break; break;
case MINUS_EXPR: case MINUS_EXPR:
/* With IEEE arithmetic, x - x may not equal 0, so we can't optimize /* Perhaps reduce (x - y) != 0 to (x != y). The expressions
this case. */ aren't guaranteed to the be same for modes that can represent
if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT infinity, since if x and y are both +infinity, or both
&& TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE) -infinity, then x - y is not a number.
Note that this transformation is safe when x or y is NaN.
(x - y) is then NaN, and both (x - y) != 0 and x != y will
be false. */
if (HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (TREE_OPERAND (expr, 0)))))
break; break;
/* fall through... */ /* fall through... */
case BIT_XOR_EXPR: case BIT_XOR_EXPR:
...@@ -3051,6 +3056,81 @@ strip_array_types (type) ...@@ -3051,6 +3056,81 @@ strip_array_types (type)
return type; return type;
} }
static tree expand_unordered_cmp PARAMS ((tree, tree, enum tree_code,
enum tree_code));
/* Expand a call to an unordered comparison function such as
__builtin_isgreater(). FUNCTION is the function's declaration and
PARAMS a list of the values passed. For __builtin_isunordered(),
UNORDERED_CODE is UNORDERED_EXPR and ORDERED_CODE is NOP_EXPR. In
other cases, UNORDERED_CODE and ORDERED_CODE are comparison codes
that give the opposite of the desired result. UNORDERED_CODE is
used for modes that can hold NaNs and ORDERED_CODE is used for the
rest. */
static tree
expand_unordered_cmp (function, params, unordered_code, ordered_code)
tree function, params;
enum tree_code unordered_code, ordered_code;
{
tree arg0, arg1, type;
enum tree_code code0, code1;
/* Check that we have exactly two arguments. */
if (params == 0 || TREE_CHAIN (params) == 0)
{
error ("too few arguments to function `%s'",
IDENTIFIER_POINTER (DECL_NAME (function)));
return error_mark_node;
}
else if (TREE_CHAIN (TREE_CHAIN (params)) != 0)
{
error ("too many arguments to function `%s'",
IDENTIFIER_POINTER (DECL_NAME (function)));
return error_mark_node;
}
arg0 = TREE_VALUE (params);
arg1 = TREE_VALUE (TREE_CHAIN (params));
code0 = TREE_CODE (TREE_TYPE (arg0));
code1 = TREE_CODE (TREE_TYPE (arg1));
/* Make sure that the arguments have a common type of REAL. */
type = 0;
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
type = common_type (TREE_TYPE (arg0), TREE_TYPE (arg1));
if (type == 0 || TREE_CODE (type) != REAL_TYPE)
{
error ("non-floating-point argument to function `%s'",
IDENTIFIER_POINTER (DECL_NAME (function)));
return error_mark_node;
}
if (unordered_code == UNORDERED_EXPR)
{
if (MODE_HAS_NANS (TYPE_MODE (type)))
return build_binary_op (unordered_code,
convert (type, arg0),
convert (type, arg1),
0);
else
return integer_zero_node;
}
return build_unary_op (TRUTH_NOT_EXPR,
build_binary_op (MODE_HAS_NANS (TYPE_MODE (type))
? unordered_code
: ordered_code,
convert (type, arg0),
convert (type, arg1),
0),
0);
}
/* Recognize certain built-in functions so we can make tree-codes /* Recognize certain built-in functions so we can make tree-codes
other than CALL_EXPR. We do this when it enables fold-const.c other than CALL_EXPR. We do this when it enables fold-const.c
to do something useful. */ to do something useful. */
...@@ -3063,8 +3143,6 @@ tree ...@@ -3063,8 +3143,6 @@ tree
expand_tree_builtin (function, params, coerced_params) expand_tree_builtin (function, params, coerced_params)
tree function, params, coerced_params; tree function, params, coerced_params;
{ {
enum tree_code code;
if (DECL_BUILT_IN_CLASS (function) != BUILT_IN_NORMAL) if (DECL_BUILT_IN_CLASS (function) != BUILT_IN_NORMAL)
return NULL_TREE; return NULL_TREE;
...@@ -3103,72 +3181,22 @@ expand_tree_builtin (function, params, coerced_params) ...@@ -3103,72 +3181,22 @@ expand_tree_builtin (function, params, coerced_params)
return build_unary_op (IMAGPART_EXPR, TREE_VALUE (coerced_params), 0); return build_unary_op (IMAGPART_EXPR, TREE_VALUE (coerced_params), 0);
case BUILT_IN_ISGREATER: case BUILT_IN_ISGREATER:
if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT) return expand_unordered_cmp (function, params, UNLE_EXPR, LE_EXPR);
code = UNLE_EXPR;
else
code = LE_EXPR;
goto unordered_cmp;
case BUILT_IN_ISGREATEREQUAL: case BUILT_IN_ISGREATEREQUAL:
if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT) return expand_unordered_cmp (function, params, UNLT_EXPR, LT_EXPR);
code = UNLT_EXPR;
else
code = LT_EXPR;
goto unordered_cmp;
case BUILT_IN_ISLESS: case BUILT_IN_ISLESS:
if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT) return expand_unordered_cmp (function, params, UNGE_EXPR, GE_EXPR);
code = UNGE_EXPR;
else
code = GE_EXPR;
goto unordered_cmp;
case BUILT_IN_ISLESSEQUAL: case BUILT_IN_ISLESSEQUAL:
if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT) return expand_unordered_cmp (function, params, UNGT_EXPR, GT_EXPR);
code = UNGT_EXPR;
else
code = GT_EXPR;
goto unordered_cmp;
case BUILT_IN_ISLESSGREATER: case BUILT_IN_ISLESSGREATER:
if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT) return expand_unordered_cmp (function, params, UNEQ_EXPR, EQ_EXPR);
code = UNEQ_EXPR;
else
code = EQ_EXPR;
goto unordered_cmp;
case BUILT_IN_ISUNORDERED: case BUILT_IN_ISUNORDERED:
if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT) return expand_unordered_cmp (function, params, UNORDERED_EXPR, NOP_EXPR);
return integer_zero_node;
code = UNORDERED_EXPR;
goto unordered_cmp;
unordered_cmp:
{
tree arg0, arg1;
if (params == 0
|| TREE_CHAIN (params) == 0)
{
error ("too few arguments to function `%s'",
IDENTIFIER_POINTER (DECL_NAME (function)));
return error_mark_node;
}
else if (TREE_CHAIN (TREE_CHAIN (params)) != 0)
{
error ("too many arguments to function `%s'",
IDENTIFIER_POINTER (DECL_NAME (function)));
return error_mark_node;
}
arg0 = TREE_VALUE (params);
arg1 = TREE_VALUE (TREE_CHAIN (params));
arg0 = build_binary_op (code, arg0, arg1, 0);
if (code != UNORDERED_EXPR)
arg0 = build_unary_op (TRUTH_NOT_EXPR, arg0, 0);
return arg0;
}
break;
default: default:
break; break;
......
...@@ -3978,12 +3978,14 @@ combine_simplify_rtx (x, op0_mode, last, in_dest) ...@@ -3978,12 +3978,14 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
if (GET_CODE (XEXP (x, 0)) == NOT) if (GET_CODE (XEXP (x, 0)) == NOT)
return plus_constant (XEXP (XEXP (x, 0), 0), 1); return plus_constant (XEXP (XEXP (x, 0), 0), 1);
/* (neg (minus X Y)) can become (minus Y X). */ /* (neg (minus X Y)) can become (minus Y X). This transformation
isn't safe for modes with signed zeros, since if X and Y are
both +0, (minus Y X) is the same as (minus X Y). If the rounding
mode is towards +infinity (or -infinity) then the two expressions
will be rounded differently. */
if (GET_CODE (XEXP (x, 0)) == MINUS if (GET_CODE (XEXP (x, 0)) == MINUS
&& (! FLOAT_MODE_P (mode) && !HONOR_SIGNED_ZEROS (mode)
/* x-y != -(y-x) with IEEE floating point. */ && !HONOR_SIGN_DEPENDENT_ROUNDING (mode))
|| TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
|| flag_unsafe_math_optimizations))
return gen_binary (MINUS, mode, XEXP (XEXP (x, 0), 1), return gen_binary (MINUS, mode, XEXP (XEXP (x, 0), 1),
XEXP (XEXP (x, 0), 0)); XEXP (XEXP (x, 0), 0));
...@@ -4145,10 +4147,11 @@ combine_simplify_rtx (x, op0_mode, last, in_dest) ...@@ -4145,10 +4147,11 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
if (XEXP (x, 1) == const0_rtx) if (XEXP (x, 1) == const0_rtx)
return XEXP (x, 0); return XEXP (x, 0);
/* In IEEE floating point, x-0 is not the same as x. */ /* x - 0 is the same as x unless x's mode has signed zeros and
if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT allows rounding towards -infinity. Under those conditions,
|| ! FLOAT_MODE_P (GET_MODE (XEXP (x, 0))) 0 - 0 is -0. */
|| flag_unsafe_math_optimizations) if (!(HONOR_SIGNED_ZEROS (GET_MODE (XEXP (x, 0)))
&& HONOR_SIGN_DEPENDENT_ROUNDING (GET_MODE (XEXP (x, 0))))
&& XEXP (x, 1) == CONST0_RTX (GET_MODE (XEXP (x, 0)))) && XEXP (x, 1) == CONST0_RTX (GET_MODE (XEXP (x, 0))))
return XEXP (x, 0); return XEXP (x, 0);
break; break;
......
...@@ -3981,19 +3981,18 @@ fold_rtx (x, insn) ...@@ -3981,19 +3981,18 @@ fold_rtx (x, insn)
& HASH_MASK), mode_arg0)) & HASH_MASK), mode_arg0))
&& p0->first_same_value == p1->first_same_value)) && p0->first_same_value == p1->first_same_value))
{ {
/* Sadly two equal NaNs are not equivalent. */ /* Sadly two equal NaNs are not equivalent. */
if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT if (!HONOR_NANS (mode_arg0))
|| ! FLOAT_MODE_P (mode_arg0) return ((code == EQ || code == LE || code == GE
|| flag_unsafe_math_optimizations) || code == LEU || code == GEU || code == UNEQ
return ((code == EQ || code == LE || code == GE || code == UNLE || code == UNGE
|| code == LEU || code == GEU || code == UNEQ || code == ORDERED)
|| code == UNLE || code == UNGE || code == ORDERED) ? true_rtx : false_rtx);
? true_rtx : false_rtx); /* Take care for the FP compares we can resolve. */
/* Take care for the FP compares we can resolve. */ if (code == UNEQ || code == UNLE || code == UNGE)
if (code == UNEQ || code == UNLE || code == UNGE) return true_rtx;
return true_rtx; if (code == LTGT || code == LT || code == GT)
if (code == LTGT || code == LT || code == GT) return false_rtx;
return false_rtx;
} }
/* If FOLDED_ARG0 is a register, see if the comparison we are /* If FOLDED_ARG0 is a register, see if the comparison we are
......
...@@ -465,4 +465,24 @@ You Lose! You must define PREFERRED_DEBUGGING_TYPE! ...@@ -465,4 +465,24 @@ You Lose! You must define PREFERRED_DEBUGGING_TYPE!
#define MODE_BASE_REG_CLASS(MODE) BASE_REG_CLASS #define MODE_BASE_REG_CLASS(MODE) BASE_REG_CLASS
#endif #endif
#ifndef MODE_HAS_NANS
#define MODE_HAS_NANS(MODE) \
(FLOAT_MODE_P (MODE) && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
#endif
#ifndef MODE_HAS_INFINITIES
#define MODE_HAS_INFINITIES(MODE) \
(FLOAT_MODE_P (MODE) && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
#endif
#ifndef MODE_HAS_SIGNED_ZEROS
#define MODE_HAS_SIGNED_ZEROS(MODE) \
(FLOAT_MODE_P (MODE) && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
#endif
#ifndef MODE_HAS_SIGN_DEPENDENT_ROUNDING
#define MODE_HAS_SIGN_DEPENDENT_ROUNDING(MODE) \
(FLOAT_MODE_P (MODE) && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
#endif
#endif /* ! GCC_DEFAULTS_H */ #endif /* ! GCC_DEFAULTS_H */
...@@ -1336,6 +1336,55 @@ defined for them. ...@@ -1336,6 +1336,55 @@ defined for them.
The ordering of the component words of floating point values stored in The ordering of the component words of floating point values stored in
memory is controlled by @code{FLOAT_WORDS_BIG_ENDIAN}. memory is controlled by @code{FLOAT_WORDS_BIG_ENDIAN}.
@findex MODE_HAS_NANS
@item MODE_HAS_NANS (@var{mode})
When defined, this macro should be true if @var{mode} has a NaN
representation. The compiler assumes that NaNs are not equal to
anything (including themselves) and that addition, subtraction,
multiplication and division all return NaNs when one operand is
NaN@.
By default, this macro is true if @var{mode} is a floating-point
mode and the target floating-point format is IEEE@.
@findex MODE_HAS_INFINITIES
@item MODE_HAS_INFINITIES (@var{mode})
This macro should be true if @var{mode} can represent infinity. At
present, the compiler uses this macro to decide whether @samp{x - x}
is always defined. By default, the macro is true when @var{mode}
is a floating-point mode and the target format is IEEE@.
@findex MODE_HAS_SIGNED_ZEROS
@item MODE_HAS_SIGNED_ZEROS (@var{mode})
True if @var{mode} distinguishes between positive and negative zero.
The rules are expected to follow the IEEE standard:
@itemize @bullet
@item
@samp{x + x} has the same sign as @samp{x}.
@item
If the sum of two values with opposite sign is zero, the result is
positive for all rounding modes expect towards @minus{}infinity, for
which it is negative.
@item
The sign of a product or quotient is negative when exactly one
of the operands is negative.
@end itemize
The default definition is true if @var{mode} is a floating-point
mode and the target format is IEEE@.
@findex MODE_HAS_SIGN_DEPENDENT_ROUNDING
@item MODE_HAS_SIGN_DEPENDENT_ROUNDING (@var{mode})
If defined, this macro should be true for @var{mode} if it has at
least one rounding mode in which @samp{x} and @samp{-x} can be
rounded to numbers of different magnitude. Two such modes are
towards @minus{}infinity and towards +infinity.
The default definition of this macro is true if @var{mode} is
a floating-point mode and the target format is IEEE@.
@end table @end table
@deftypefn {Target Hook} bool TARGET_MS_BITFIELD_LAYOUT_P (tree @var{record_type}) @deftypefn {Target Hook} bool TARGET_MS_BITFIELD_LAYOUT_P (tree @var{record_type})
......
...@@ -633,4 +633,27 @@ extern int flag_non_call_exceptions; ...@@ -633,4 +633,27 @@ extern int flag_non_call_exceptions;
/* Nonzero means put zero initialized data in the bss section. */ /* Nonzero means put zero initialized data in the bss section. */
extern int flag_zero_initialized_in_bss; extern int flag_zero_initialized_in_bss;
/* True if the given mode has a NaN representation and the treatment of
NaN operands is important. Certain optimizations, such as folding
x * 0 into x, are not correct for NaN operands, and are normally
disabled for modes with NaNs. The user can ask for them to be
done anyway using the -funsafe-math-optimizations switch. */
#define HONOR_NANS(MODE) \
(MODE_HAS_NANS (MODE) && !flag_unsafe_math_optimizations)
/* As for HONOR_NANS, but true if the mode can represent infinity and
the treatment of infinite values is important. */
#define HONOR_INFINITIES(MODE) \
(MODE_HAS_INFINITIES (MODE) && !flag_unsafe_math_optimizations)
/* Like HONOR_NANS, but true if the given mode distinguishes between
postive and negative zero, and the sign of zero is important. */
#define HONOR_SIGNED_ZEROS(MODE) \
(MODE_HAS_SIGNED_ZEROS (MODE) && !flag_unsafe_math_optimizations)
/* Like HONOR_NANS, but true if given mode supports sign-dependent rounding,
and the rounding mode is important. */
#define HONOR_SIGN_DEPENDENT_ROUNDING(MODE) \
(MODE_HAS_SIGN_DEPENDENT_ROUNDING (MODE) && !flag_unsafe_math_optimizations)
#endif /* ! GCC_FLAGS_H */ #endif /* ! GCC_FLAGS_H */
...@@ -1295,12 +1295,11 @@ noce_try_minmax (if_info) ...@@ -1295,12 +1295,11 @@ noce_try_minmax (if_info)
if (no_new_pseudos) if (no_new_pseudos)
return FALSE; return FALSE;
/* ??? Reject FP modes since we don't know how 0 vs -0 or NaNs /* ??? Reject modes with NaNs or signed zeros since we don't know how
will be resolved with an SMIN/SMAX. It wouldn't be too hard they will be resolved with an SMIN/SMAX. It wouldn't be too hard
to get the target to tell us... */ to get the target to tell us... */
if (FLOAT_MODE_P (GET_MODE (if_info->x)) if (HONOR_SIGNED_ZEROS (GET_MODE (if_info->x))
&& TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT || HONOR_NANS (GET_MODE (if_info->x)))
&& ! flag_unsafe_math_optimizations)
return FALSE; return FALSE;
cond = noce_get_alt_condition (if_info, if_info->a, &earliest); cond = noce_get_alt_condition (if_info, if_info->a, &earliest);
......
...@@ -704,11 +704,6 @@ reversed_comparison_code_parts (code, arg0, arg1, insn) ...@@ -704,11 +704,6 @@ reversed_comparison_code_parts (code, arg0, arg1, insn)
break; break;
} }
/* In case we give up IEEE compatibility, all comparisons are reversible. */
if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
|| flag_unsafe_math_optimizations)
return reverse_condition (code);
if (GET_MODE_CLASS (mode) == MODE_CC if (GET_MODE_CLASS (mode) == MODE_CC
#ifdef HAVE_cc0 #ifdef HAVE_cc0
|| arg0 == cc0_rtx || arg0 == cc0_rtx
...@@ -757,11 +752,12 @@ reversed_comparison_code_parts (code, arg0, arg1, insn) ...@@ -757,11 +752,12 @@ reversed_comparison_code_parts (code, arg0, arg1, insn)
} }
} }
/* An integer condition. */ /* Test for an integer condition, or a floating-point comparison
in which NaNs can be ignored. */
if (GET_CODE (arg0) == CONST_INT if (GET_CODE (arg0) == CONST_INT
|| (GET_MODE (arg0) != VOIDmode || (GET_MODE (arg0) != VOIDmode
&& GET_MODE_CLASS (mode) != MODE_CC && GET_MODE_CLASS (mode) != MODE_CC
&& ! FLOAT_MODE_P (mode))) && !HONOR_NANS (mode)))
return reverse_condition (code); return reverse_condition (code);
return UNKNOWN; return UNKNOWN;
...@@ -840,10 +836,6 @@ enum rtx_code ...@@ -840,10 +836,6 @@ enum rtx_code
reverse_condition_maybe_unordered (code) reverse_condition_maybe_unordered (code)
enum rtx_code code; enum rtx_code code;
{ {
/* Non-IEEE formats don't have unordered conditions. */
if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT)
return reverse_condition (code);
switch (code) switch (code)
{ {
case EQ: case EQ:
......
...@@ -981,16 +981,15 @@ simplify_binary_operation (code, mode, op0, op1) ...@@ -981,16 +981,15 @@ simplify_binary_operation (code, mode, op0, op1)
switch (code) switch (code)
{ {
case PLUS: case PLUS:
/* In IEEE floating point, x+0 is not the same as x. Similarly /* Maybe simplify x + 0 to x. The two expressions are equivalent
for the other optimizations below. */ when x is NaN, infinite, or finite and non-zero. They aren't
if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT when x is -0 and the rounding mode is not towards -infinity,
&& FLOAT_MODE_P (mode) && ! flag_unsafe_math_optimizations) since (-0) + 0 is then 0. */
break; if (!HONOR_SIGNED_ZEROS (mode) && trueop1 == CONST0_RTX (mode))
if (trueop1 == CONST0_RTX (mode))
return op0; 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) if (GET_CODE (op0) == NEG)
return simplify_gen_binary (MINUS, mode, op1, XEXP (op0, 0)); return simplify_gen_binary (MINUS, mode, op1, XEXP (op0, 0));
else if (GET_CODE (op1) == NEG) else if (GET_CODE (op1) == NEG)
...@@ -1122,12 +1121,6 @@ simplify_binary_operation (code, mode, op0, op1) ...@@ -1122,12 +1121,6 @@ simplify_binary_operation (code, mode, op0, op1)
break; break;
case MINUS: 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, /* 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 but since it is zero except in very strange circumstances, we
will treat it as zero with -funsafe-math-optimizations. */ will treat it as zero with -funsafe-math-optimizations. */
...@@ -1136,16 +1129,23 @@ simplify_binary_operation (code, mode, op0, op1) ...@@ -1136,16 +1129,23 @@ simplify_binary_operation (code, mode, op0, op1)
&& (! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)) && (! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations))
return CONST0_RTX (mode); return CONST0_RTX (mode);
/* Change subtraction from zero into negation. */ /* Change subtraction from zero into negation. (0 - x) is the
if (trueop0 == CONST0_RTX (mode)) 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); return gen_rtx_NEG (mode, op1);
/* (-1 - a) is ~a. */ /* (-1 - a) is ~a. */
if (trueop0 == constm1_rtx) if (trueop0 == constm1_rtx)
return gen_rtx_NOT (mode, op1); return gen_rtx_NOT (mode, op1);
/* Subtracting 0 has no effect. */ /* Subtracting 0 has no effect unless the mode has signed zeros
if (trueop1 == CONST0_RTX (mode)) 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; return op0;
/* See if this is something like X * C - X or vice versa or /* See if this is something like X * C - X or vice versa or
...@@ -1202,7 +1202,7 @@ simplify_binary_operation (code, mode, op0, op1) ...@@ -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) if (GET_CODE (op1) == NEG)
return simplify_gen_binary (PLUS, mode, op0, XEXP (op1, 0)); return simplify_gen_binary (PLUS, mode, op0, XEXP (op1, 0));
...@@ -1248,9 +1248,12 @@ simplify_binary_operation (code, mode, op0, op1) ...@@ -1248,9 +1248,12 @@ simplify_binary_operation (code, mode, op0, op1)
return tem ? tem : gen_rtx_NEG (mode, op0); return tem ? tem : gen_rtx_NEG (mode, op0);
} }
/* In IEEE floating point, x*0 is not always 0. */ /* Maybe simplify x * 0 to 0. The reduction is not valid if
if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT x is NaN, since x * 0 is then also NaN. Nor is it valid
|| ! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations) 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) && trueop1 == CONST0_RTX (mode)
&& ! side_effects_p (op0)) && ! side_effects_p (op0))
return op1; return op1;
...@@ -1361,9 +1364,12 @@ simplify_binary_operation (code, mode, op0, op1) ...@@ -1361,9 +1364,12 @@ simplify_binary_operation (code, mode, op0, op1)
return op0; return op0;
} }
/* In IEEE floating point, 0/x is not always 0. */ /* Maybe change 0 / x to 0. This transformation isn't safe for
if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT modes with NaNs, since 0 / 0 will then be NaN rather than 0.
|| ! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations) 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) && trueop0 == CONST0_RTX (mode)
&& ! side_effects_p (op1)) && ! side_effects_p (op1))
return op0; return op0;
...@@ -2018,12 +2024,9 @@ simplify_relational_operation (code, mode, op0, op1) ...@@ -2018,12 +2024,9 @@ simplify_relational_operation (code, mode, op0, op1)
if (flag_unsafe_math_optimizations && code == UNORDERED) if (flag_unsafe_math_optimizations && code == UNORDERED)
return const0_rtx; 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. */ result. */
if (rtx_equal_p (trueop0, trueop1) if (!HONOR_NANS (GET_MODE (trueop0)) && rtx_equal_p (trueop0, trueop1))
&& (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
|| ! FLOAT_MODE_P (GET_MODE (trueop0))
|| flag_unsafe_math_optimizations))
equal = 1, op0lt = 0, op0ltu = 0, op1lt = 0, op1ltu = 0; equal = 1, op0lt = 0, op0ltu = 0, op1lt = 0, op1ltu = 0;
/* If the operands are floating-point constants, see if we can fold /* If the operands are floating-point constants, see if we can fold
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment