On Tue, 18 Nov 2014, Richard Biener wrote:
I'll try to replace some more TYPE_MODE during stage3...
Btw, a convenience would be to be able to write
HONOR_NANS (type)
thus effectively make HONOR_* inline functions with a machine_mode
and a type overload (and the type overload properly looking at
element types).
Making those functions inline is not easy, because real.h and tree.h don't
include each other. Here is a version with the functions not inline. I
was tempted to also overload on gcond const* (for the cases that call
gimple_cond_lhs) but the arguments were always gimple and not gcond*, so I
didn't.
Passes bootstrap+testsuite on x86_64-linux-gnu.
2014-12-08 Marc Glisse <[email protected]>
* real.h (HONOR_NANS): Replace macro with 3 overloaded declarations.
* real.c: Include rtl.h and options.h.
(HONOR_NANS): Define three overloads.
* builtins.c (fold_builtin_classify, fold_builtin_unordered_cmp):
Simplify argument of HONOR_NANS.
* fold-const.c (combine_comparisons, fold_truth_not_expr,
fold_cond_expr_with_comparison, merge_truthop_with_opposite_arm,
fold_comparison, fold_binary_loc): Likewise.
* ifcvt.c (noce_try_move, noce_try_minmax): Likewise.
* ipa-inline-analysis.c (add_clause,
set_cond_stmt_execution_predicate): Likewise.
* match.pd: Likewise.
* rtlanal.c (may_trap_p_1): Likewise.
* simplify-rtx.c (simplify_const_relational_operation): Likewise.
* tree-if-conv.c (parse_predicate): Likewise.
* tree-ssa-ccp.c (valid_lattice_transition): Likewise.
* tree-ssa-ifcombine.c (ifcombine_ifandif): Likewise.
* tree-ssa-phiopt.c (minmax_replacement, neg_replacement): Likewise.
* tree-ssa-reassoc.c (eliminate_using_constants): Likewise.
* tree-ssa-tail-merge.c (gimple_equal_p): Likewise.
--
Marc GlisseIndex: builtins.c
===================================================================
--- builtins.c (revision 218467)
+++ builtins.c (working copy)
@@ -9641,34 +9641,34 @@ fold_builtin_classify (location_t loc, t
integer_minus_one_node, integer_one_node);
tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node,
isinf_call, tmp,
integer_zero_node);
}
return tmp;
}
case BUILT_IN_ISFINITE:
- if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg)))
+ if (!HONOR_NANS (arg)
&& !HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
return omit_one_operand_loc (loc, type, integer_one_node, arg);
if (TREE_CODE (arg) == REAL_CST)
{
r = TREE_REAL_CST (arg);
return real_isfinite (&r) ? integer_one_node : integer_zero_node;
}
return NULL_TREE;
case BUILT_IN_ISNAN:
- if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg))))
+ if (!HONOR_NANS (arg))
return omit_one_operand_loc (loc, type, integer_zero_node, arg);
if (TREE_CODE (arg) == REAL_CST)
{
r = TREE_REAL_CST (arg);
return real_isnan (&r) ? integer_one_node : integer_zero_node;
}
arg = builtin_save_expr (arg);
return fold_build2_loc (loc, UNORDERED_EXPR, type, arg, arg);
@@ -9782,27 +9782,26 @@ fold_builtin_unordered_cmp (location_t l
else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
cmp_type = type0;
else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE)
cmp_type = type1;
arg0 = fold_convert_loc (loc, cmp_type, arg0);
arg1 = fold_convert_loc (loc, cmp_type, arg1);
if (unordered_code == UNORDERED_EXPR)
{
- if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
+ if (!HONOR_NANS (arg0))
return omit_two_operands_loc (loc, type, integer_zero_node, arg0, arg1);
return fold_build2_loc (loc, UNORDERED_EXPR, type, arg0, arg1);
}
- code = HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))) ? unordered_code
- : ordered_code;
+ code = HONOR_NANS (arg0) ? unordered_code : ordered_code;
return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
fold_build2_loc (loc, code, type, arg0, arg1));
}
/* Fold __builtin_{,s,u}{add,sub,mul}{,l,ll}_overflow, either into normal
arithmetics if it can never overflow, or into internal functions that
return both result of arithmetics and overflowed boolean flag in
a complex integer result, or some other check for overflow. */
static tree
Index: fold-const.c
===================================================================
--- fold-const.c (revision 218467)
+++ fold-const.c (working copy)
@@ -2585,21 +2585,21 @@ compcode_to_comparison (enum comparison_
and RCODE on the identical operands LL_ARG and LR_ARG. Take into account
the possibility of trapping if the mode has NaNs, and return NULL_TREE
if this makes the transformation invalid. */
tree
combine_comparisons (location_t loc,
enum tree_code code, enum tree_code lcode,
enum tree_code rcode, tree truth_type,
tree ll_arg, tree lr_arg)
{
- bool honor_nans = HONOR_NANS (element_mode (ll_arg));
+ bool honor_nans = HONOR_NANS (ll_arg);
enum comparison_code lcompcode = comparison_to_compcode (lcode);
enum comparison_code rcompcode = comparison_to_compcode (rcode);
int compcode;
switch (code)
{
case TRUTH_AND_EXPR: case TRUTH_ANDIF_EXPR:
compcode = lcompcode & rcompcode;
break;
@@ -3369,21 +3369,21 @@ fold_truth_not_expr (location_t loc, tre
if (TREE_CODE_CLASS (code) == tcc_comparison)
{
tree op_type = TREE_TYPE (TREE_OPERAND (arg, 0));
if (FLOAT_TYPE_P (op_type)
&& flag_trapping_math
&& code != ORDERED_EXPR && code != UNORDERED_EXPR
&& code != NE_EXPR && code != EQ_EXPR)
return NULL_TREE;
- code = invert_tree_comparison (code, HONOR_NANS (TYPE_MODE (op_type)));
+ code = invert_tree_comparison (code, HONOR_NANS (op_type));
if (code == ERROR_MARK)
return NULL_TREE;
return build2_loc (loc, code, type, TREE_OPERAND (arg, 0),
TREE_OPERAND (arg, 1));
}
switch (code)
{
case INTEGER_CST:
@@ -4981,55 +4981,55 @@ fold_cond_expr_with_comparison (location
case NE_EXPR:
return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type,
arg1));
case LE_EXPR:
case LT_EXPR:
case UNLE_EXPR:
case UNLT_EXPR:
/* In C++ a ?: expression can be an lvalue, so put the
operand which will be used if they are equal first
so that we can convert this back to the
corresponding COND_EXPR. */
- if (!HONOR_NANS (element_mode (arg1)))
+ if (!HONOR_NANS (arg1))
{
comp_op0 = fold_convert_loc (loc, comp_type, comp_op0);
comp_op1 = fold_convert_loc (loc, comp_type, comp_op1);
tem = (comp_code == LE_EXPR || comp_code == UNLE_EXPR)
? fold_build2_loc (loc, MIN_EXPR, comp_type, comp_op0,
comp_op1)
: fold_build2_loc (loc, MIN_EXPR, comp_type,
comp_op1, comp_op0);
return pedantic_non_lvalue_loc (loc,
fold_convert_loc (loc, type, tem));
}
break;
case GE_EXPR:
case GT_EXPR:
case UNGE_EXPR:
case UNGT_EXPR:
- if (!HONOR_NANS (element_mode (arg1)))
+ if (!HONOR_NANS (arg1))
{
comp_op0 = fold_convert_loc (loc, comp_type, comp_op0);
comp_op1 = fold_convert_loc (loc, comp_type, comp_op1);
tem = (comp_code == GE_EXPR || comp_code == UNGE_EXPR)
? fold_build2_loc (loc, MAX_EXPR, comp_type, comp_op0,
comp_op1)
: fold_build2_loc (loc, MAX_EXPR, comp_type,
comp_op1, comp_op0);
return pedantic_non_lvalue_loc (loc,
fold_convert_loc (loc, type, tem));
}
break;
case UNEQ_EXPR:
- if (!HONOR_NANS (element_mode (arg1)))
+ if (!HONOR_NANS (arg1))
return pedantic_non_lvalue_loc (loc,
fold_convert_loc (loc, type, arg2));
break;
case LTGT_EXPR:
- if (!HONOR_NANS (element_mode (arg1)))
+ if (!HONOR_NANS (arg1))
return pedantic_non_lvalue_loc (loc,
fold_convert_loc (loc, type, arg1));
break;
default:
gcc_assert (TREE_CODE_CLASS (comp_code) == tcc_comparison);
break;
}
}
/* If this is A op C1 ? A : C2 with C1 and C2 constant integers,
@@ -5310,21 +5310,21 @@ merge_truthop_with_opposite_arm (locatio
if (lhs_code == truthop_code && !rhs_only)
{
tree newlhs = merge_truthop_with_opposite_arm (loc, lhs, cmpop, false);
if (newlhs != NULL_TREE)
{
lhs = newlhs;
lhs_code = TREE_CODE (lhs);
}
}
- inv_code = invert_tree_comparison (code, HONOR_NANS (TYPE_MODE (type)));
+ inv_code = invert_tree_comparison (code, HONOR_NANS (type));
if (inv_code == rhs_code
&& operand_equal_p (TREE_OPERAND (rhs, 0), TREE_OPERAND (cmpop, 0), 0)
&& operand_equal_p (TREE_OPERAND (rhs, 1), TREE_OPERAND (cmpop, 1), 0))
return lhs;
if (!rhs_only && inv_code == lhs_code
&& operand_equal_p (TREE_OPERAND (lhs, 0), TREE_OPERAND (cmpop, 0), 0)
&& operand_equal_p (TREE_OPERAND (lhs, 1), TREE_OPERAND (cmpop, 1), 0))
return rhs;
if (rhs != orig_rhs || lhs != orig_lhs)
return fold_build2_loc (loc, truthop_code, TREE_TYPE (cmpop),
@@ -9247,36 +9247,36 @@ fold_comparison (location_t loc, enum tr
}
/* Simplify comparison of something with itself. (For IEEE
floating-point, we can only do some of these simplifications.) */
if (operand_equal_p (arg0, arg1, 0))
{
switch (code)
{
case EQ_EXPR:
if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
- || ! HONOR_NANS (element_mode (arg0)))
+ || ! HONOR_NANS (arg0))
return constant_boolean_node (1, type);
break;
case GE_EXPR:
case LE_EXPR:
if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
- || ! HONOR_NANS (element_mode (arg0)))
+ || ! HONOR_NANS (arg0))
return constant_boolean_node (1, type);
return fold_build2_loc (loc, EQ_EXPR, type, arg0, arg1);
case NE_EXPR:
/* For NE, we can only do this simplification if integer
or we don't honor IEEE floating point NaNs. */
if (FLOAT_TYPE_P (TREE_TYPE (arg0))
- && HONOR_NANS (element_mode (arg0)))
+ && HONOR_NANS (arg0))
break;
/* ... fall through ... */
case GT_EXPR:
case LT_EXPR:
return constant_boolean_node (0, type);
default:
gcc_unreachable ();
}
}
@@ -10741,21 +10741,21 @@ fold_binary_loc (location_t loc,
if (tem != NULL_TREE)
{
tem = fold_convert_loc (loc, type, tem);
return fold_build2_loc (loc, MULT_EXPR, type, tem, tem);
}
}
/* Fold z * +-I to __complex__ (-+__imag z, +-__real z).
This is not the same for NaNs or if signed zeros are
involved. */
- if (!HONOR_NANS (element_mode (arg0))
+ if (!HONOR_NANS (arg0)
&& !HONOR_SIGNED_ZEROS (element_mode (arg0))
&& COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg0))
&& TREE_CODE (arg1) == COMPLEX_CST
&& real_zerop (TREE_REALPART (arg1)))
{
tree rtype = TREE_TYPE (TREE_TYPE (arg0));
if (real_onep (TREE_IMAGPART (arg1)))
return
fold_build2_loc (loc, COMPLEX_EXPR, type,
negate_expr (fold_build1_loc (loc, IMAGPART_EXPR,
@@ -11673,41 +11673,41 @@ fold_binary_loc (location_t loc,
/* Optimize sin(x)/tan(x) as cos(x) if we don't care about
NaNs or Infinities. */
if (((fcode0 == BUILT_IN_SIN && fcode1 == BUILT_IN_TAN)
|| (fcode0 == BUILT_IN_SINF && fcode1 == BUILT_IN_TANF)
|| (fcode0 == BUILT_IN_SINL && fcode1 == BUILT_IN_TANL)))
{
tree arg00 = CALL_EXPR_ARG (arg0, 0);
tree arg01 = CALL_EXPR_ARG (arg1, 0);
- if (! HONOR_NANS (element_mode (arg00))
+ if (! HONOR_NANS (arg00)
&& ! HONOR_INFINITIES (element_mode (arg00))
&& operand_equal_p (arg00, arg01, 0))
{
tree cosfn = mathfn_built_in (type, BUILT_IN_COS);
if (cosfn != NULL_TREE)
return build_call_expr_loc (loc, cosfn, 1, arg00);
}
}
/* Optimize tan(x)/sin(x) as 1.0/cos(x) if we don't care about
NaNs or Infinities. */
if (((fcode0 == BUILT_IN_TAN && fcode1 == BUILT_IN_SIN)
|| (fcode0 == BUILT_IN_TANF && fcode1 == BUILT_IN_SINF)
|| (fcode0 == BUILT_IN_TANL && fcode1 == BUILT_IN_SINL)))
{
tree arg00 = CALL_EXPR_ARG (arg0, 0);
tree arg01 = CALL_EXPR_ARG (arg1, 0);
- if (! HONOR_NANS (element_mode (arg00))
+ if (! HONOR_NANS (arg00)
&& ! HONOR_INFINITIES (element_mode (arg00))
&& operand_equal_p (arg00, arg01, 0))
{
tree cosfn = mathfn_built_in (type, BUILT_IN_COS);
if (cosfn != NULL_TREE)
{
tree tmp = build_call_expr_loc (loc, cosfn, 1, arg00);
return fold_build2_loc (loc, RDIV_EXPR, type,
build_real (type, dconst1),
@@ -12835,36 +12835,36 @@ fold_binary_loc (location_t loc,
if (TREE_CODE (arg01) == INTEGER_CST
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg1)))
fold_overflow_warning (("assuming signed overflow does not "
"occur when assuming that "
"(X + c) < X is always false"),
WARN_STRICT_OVERFLOW_ALL);
return constant_boolean_node (0, type);
}
/* Convert (X - c) <= X to true. */
- if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1)))
+ if (!HONOR_NANS (arg1)
&& code == LE_EXPR
&& ((code0 == MINUS_EXPR && is_positive >= 0)
|| (code0 == PLUS_EXPR && is_positive <= 0)))
{
if (TREE_CODE (arg01) == INTEGER_CST
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg1)))
fold_overflow_warning (("assuming signed overflow does not "
"occur when assuming that "
"(X - c) <= X is always true"),
WARN_STRICT_OVERFLOW_ALL);
return constant_boolean_node (1, type);
}
/* Convert (X + c) >= X to true. */
- if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1)))
+ if (!HONOR_NANS (arg1)
&& code == GE_EXPR
&& ((code0 == PLUS_EXPR && is_positive >= 0)
|| (code0 == MINUS_EXPR && is_positive <= 0)))
{
if (TREE_CODE (arg01) == INTEGER_CST
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg1)))
fold_overflow_warning (("assuming signed overflow does not "
"occur when assuming that "
"(X + c) >= X is always true"),
WARN_STRICT_OVERFLOW_ALL);
@@ -13057,21 +13057,21 @@ fold_binary_loc (location_t loc,
return fold_build2_loc (loc, TRUTH_ANDIF_EXPR, type,
build2 (GE_EXPR, type,
TREE_OPERAND (arg0, 0), tem),
build2 (LE_EXPR, type,
TREE_OPERAND (arg0, 0), arg1));
/* Convert ABS_EXPR<x> >= 0 to true. */
strict_overflow_p = false;
if (code == GE_EXPR
&& (integer_zerop (arg1)
- || (! HONOR_NANS (element_mode (arg0))
+ || (! HONOR_NANS (arg0)
&& real_zerop (arg1)))
&& tree_expr_nonnegative_warnv_p (arg0, &strict_overflow_p))
{
if (strict_overflow_p)
fold_overflow_warning (("assuming signed overflow does not occur "
"when simplifying comparison of "
"absolute value and zero"),
WARN_STRICT_OVERFLOW_CONDITIONAL);
return omit_one_operand_loc (loc, type,
constant_boolean_node (true, type),
Index: ifcvt.c
===================================================================
--- ifcvt.c (revision 218467)
+++ ifcvt.c (working copy)
@@ -1055,21 +1055,21 @@ noce_try_move (struct noce_if_info *if_i
rtx cond = if_info->cond;
enum rtx_code code = GET_CODE (cond);
rtx y;
rtx_insn *seq;
if (code != NE && code != EQ)
return FALSE;
/* This optimization isn't valid if either A or B could be a NaN
or a signed zero. */
- if (HONOR_NANS (GET_MODE (if_info->x))
+ if (HONOR_NANS (if_info->x)
|| HONOR_SIGNED_ZEROS (GET_MODE (if_info->x)))
return FALSE;
/* Check whether the operands of the comparison are A and in
either order. */
if ((rtx_equal_p (if_info->a, XEXP (cond, 0))
&& rtx_equal_p (if_info->b, XEXP (cond, 1)))
|| (rtx_equal_p (if_info->a, XEXP (cond, 1))
&& rtx_equal_p (if_info->b, XEXP (cond, 0))))
{
@@ -1948,21 +1948,21 @@ noce_try_minmax (struct noce_if_info *if
{
rtx cond, target;
rtx_insn *earliest, *seq;
enum rtx_code code, op;
int unsignedp;
/* ??? Reject modes with NaNs or signed zeros since we don't know how
they will be resolved with an SMIN/SMAX. It wouldn't be too hard
to get the target to tell us... */
if (HONOR_SIGNED_ZEROS (GET_MODE (if_info->x))
- || HONOR_NANS (GET_MODE (if_info->x)))
+ || HONOR_NANS (if_info->x))
return FALSE;
cond = noce_get_alt_condition (if_info, if_info->a, &earliest);
if (!cond)
return FALSE;
/* Verify the condition is of the form we expect, and canonicalize
the comparison code. */
code = GET_CODE (cond);
if (rtx_equal_p (XEXP (cond, 0), if_info->a))
Index: ipa-inline-analysis.c
===================================================================
--- ipa-inline-analysis.c (revision 218467)
+++ ipa-inline-analysis.c (working copy)
@@ -372,23 +372,22 @@ add_clause (conditions conditions, struc
if (clause & (1 << c2))
{
condition *cc1 =
&(*conditions)[c1 - predicate_first_dynamic_condition];
condition *cc2 =
&(*conditions)[c2 - predicate_first_dynamic_condition];
if (cc1->operand_num == cc2->operand_num
&& cc1->val == cc2->val
&& cc2->code != IS_NOT_CONSTANT
&& cc2->code != CHANGED
- && cc1->code == invert_tree_comparison
- (cc2->code,
- HONOR_NANS (TYPE_MODE (TREE_TYPE (cc1->val)))))
+ && cc1->code == invert_tree_comparison (cc2->code,
+ HONOR_NANS (cc1->val)))
return;
}
}
/* We run out of variants. Be conservative in positive direction. */
if (i2 == MAX_CLAUSES)
return;
/* Keep clauses in decreasing order. This makes equivalence testing easy. */
p->clause[i2 + 1] = 0;
@@ -1755,23 +1754,21 @@ set_cond_stmt_execution_predicate (struc
return;
if (!is_gimple_ip_invariant (gimple_cond_rhs (last)))
return;
op = gimple_cond_lhs (last);
/* TODO: handle conditionals like
var = op0 < 4;
if (var != 0). */
if (unmodified_parm_or_parm_agg_item (info, last, op, &index, &aggpos))
{
code = gimple_cond_code (last);
- inverted_code
- = invert_tree_comparison (code,
- HONOR_NANS (TYPE_MODE (TREE_TYPE (op))));
+ inverted_code = invert_tree_comparison (code, HONOR_NANS (op));
FOR_EACH_EDGE (e, ei, bb->succs)
{
enum tree_code this_code = (e->flags & EDGE_TRUE_VALUE
? code : inverted_code);
/* invert_tree_comparison will return ERROR_MARK on FP
comparsions that are not EQ/NE instead of returning proper
unordered one. Be sure it is not confused with NON_CONSTANT. */
if (this_code != ERROR_MARK)
{
Index: match.pd
===================================================================
--- match.pd (revision 218467)
+++ match.pd (working copy)
@@ -66,35 +66,34 @@ along with GCC; see the file COPYING3.
(if (fold_real_zero_addition_p (type, @1, 1))
(non_lvalue @0)))
/* Simplify x - x.
This is unsafe for certain floats even in non-IEEE formats.
In IEEE, it is unsafe because it does wrong for NaNs.
Also note that operand_equal_p is always false if an operand
is volatile. */
(simplify
(minus @0 @0)
- (if (!FLOAT_TYPE_P (type) || !HONOR_NANS (element_mode (type)))
+ (if (!FLOAT_TYPE_P (type) || !HONOR_NANS (type))
{ build_zero_cst (type); }))
(simplify
(mult @0 integer_zerop@1)
@1)
/* Maybe fold x * 0 to 0. The expressions aren't the same
when x is NaN, since x * 0 is also NaN. Nor are they the
same in modes with signed zeros, since multiplying a
negative value by 0 gives -0, not +0. */
(simplify
(mult @0 real_zerop@1)
- (if (!HONOR_NANS (element_mode (type))
- && !HONOR_SIGNED_ZEROS (element_mode (type)))
+ (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (element_mode (type)))
@1))
/* In IEEE floating point, x*1 is not equivalent to x for snans.
Likewise for complex arithmetic with signed zeros. */
(simplify
(mult @0 real_onep)
(if (!HONOR_SNANS (element_mode (type))
&& (!HONOR_SIGNED_ZEROS (element_mode (type))
|| !COMPLEX_FLOAT_TYPE_P (type)))
(non_lvalue @0)))
@@ -143,30 +142,30 @@ along with GCC; see the file COPYING3.
(if (overflow_p
&& (TYPE_UNSIGNED (type)
|| mul != wi::min_value (TYPE_PRECISION (type), SIGNED)))
{ build_zero_cst (type); }))))
/* Optimize A / A to 1.0 if we don't care about
NaNs or Infinities. */
(simplify
(rdiv @0 @0)
(if (FLOAT_TYPE_P (type)
- && ! HONOR_NANS (element_mode (type))
+ && ! HONOR_NANS (type)
&& ! HONOR_INFINITIES (element_mode (type)))
{ build_one_cst (type); }))
/* Optimize -A / A to -1.0 if we don't care about
NaNs or Infinities. */
(simplify
(rdiv:c @0 (negate @0))
(if (FLOAT_TYPE_P (type)
- && ! HONOR_NANS (element_mode (type))
+ && ! HONOR_NANS (type)
&& ! HONOR_INFINITIES (element_mode (type)))
{ build_minus_one_cst (type); }))
/* In IEEE floating point, x/1 is not equivalent to x for snans. */
(simplify
(rdiv @0 real_onep)
(if (!HONOR_SNANS (element_mode (type)))
(non_lvalue @0)))
/* In IEEE floating point, x/-1 is not equivalent to -x for snans. */
@@ -898,29 +897,29 @@ along with GCC; see the file COPYING3.
For now implement what forward_propagate_comparison did. */
(simplify
(bit_not (cmp @0 @1))
(if (VECTOR_TYPE_P (type)
|| (INTEGRAL_TYPE_P (type) && TYPE_PRECISION (type) == 1))
/* Comparison inversion may be impossible for trapping math,
invert_tree_comparison will tell us. But we can't use
a computed operator in the replacement tree thus we have
to play the trick below. */
(with { enum tree_code ic = invert_tree_comparison
- (cmp, HONOR_NANS (element_mode (@0))); }
+ (cmp, HONOR_NANS (@0)); }
(if (ic == icmp)
(icmp @0 @1))
(if (ic == ncmp)
(ncmp @0 @1)))))
(simplify
(bit_xor (cmp @0 @1) integer_truep)
(with { enum tree_code ic = invert_tree_comparison
- (cmp, HONOR_NANS (element_mode (@0))); }
+ (cmp, HONOR_NANS (@0)); }
(if (ic == icmp)
(icmp @0 @1))
(if (ic == ncmp)
(ncmp @0 @1)))))
/* Simplification of math builtins. */
(define_operator_list LOG BUILT_IN_LOGF BUILT_IN_LOG BUILT_IN_LOGL)
(define_operator_list EXP BUILT_IN_EXPF BUILT_IN_EXP BUILT_IN_EXPL)
Index: real.c
===================================================================
--- real.c (revision 218467)
+++ real.c (working copy)
@@ -23,20 +23,22 @@
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
#include "diagnostic-core.h"
#include "real.h"
#include "realmpfr.h"
#include "tm_p.h"
#include "dfp.h"
#include "wide-int.h"
+#include "rtl.h"
+#include "options.h"
/* The floating point model used internally is not exactly IEEE 754
compliant, and close to the description in the ISO C99 standard,
section 5.2.4.2.2 Characteristics of floating types.
Specifically
x = s * b^e * \sum_{k=1}^p f_k * b^{-k}
where
@@ -4975,10 +4977,32 @@ get_max_float (const struct real_format
doubles. The value of the long double is the sum of the
values of the two parts. The most significant part is
required to be the value of the long double rounded to the
nearest double. Rounding means we need a slightly smaller
value for LDBL_MAX. */
buf[4 + fmt->pnan / 4] = "7bde"[fmt->pnan % 4];
}
gcc_assert (strlen (buf) < len);
}
+
+/* True if mode M has a NaN representation and
+ the treatment of NaN operands is important. */
+
+bool
+HONOR_NANS (machine_mode m)
+{
+ return MODE_HAS_NANS (m) && !flag_finite_math_only;
+}
+
+bool
+HONOR_NANS (const_tree t)
+{
+ return HONOR_NANS (element_mode (t));
+}
+
+bool
+HONOR_NANS (const_rtx x)
+{
+ return HONOR_NANS (GET_MODE (x));
+}
+
Index: real.h
===================================================================
--- real.h (revision 218467)
+++ real.h (working copy)
@@ -193,22 +193,23 @@ extern const struct real_format *
(FLOAT_MODE_P (MODE) && FLOAT_MODE_FORMAT (MODE)->has_signed_zero)
#define MODE_HAS_SIGN_DEPENDENT_ROUNDING(MODE) \
(FLOAT_MODE_P (MODE) \
&& FLOAT_MODE_FORMAT (MODE)->has_sign_dependent_rounding)
/* 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 0, 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_finite_math_only)
+extern bool HONOR_NANS (machine_mode);
+extern bool HONOR_NANS (const_tree);
+extern bool HONOR_NANS (const_rtx);
/* Like HONOR_NANs, but true if we honor signaling NaNs (or sNaNs). */
#define HONOR_SNANS(MODE) (flag_signaling_nans && HONOR_NANS (MODE))
/* 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_finite_math_only)
/* Like HONOR_NANS, but true if the given mode distinguishes between
Index: rtlanal.c
===================================================================
--- rtlanal.c (revision 218467)
+++ rtlanal.c (working copy)
@@ -2545,42 +2545,42 @@ may_trap_p_1 (const_rtx x, unsigned flag
case LT:
case LTGT:
case COMPARE:
/* Some floating point comparisons may trap. */
if (!flag_trapping_math)
break;
/* ??? There is no machine independent way to check for tests that trap
when COMPARE is used, though many targets do make this distinction.
For instance, sparc uses CCFPE for compares which generate exceptions
and CCFP for compares which do not generate exceptions. */
- if (HONOR_NANS (GET_MODE (x)))
+ if (HONOR_NANS (x))
return 1;
/* But often the compare has some CC mode, so check operand
modes as well. */
- if (HONOR_NANS (GET_MODE (XEXP (x, 0)))
- || HONOR_NANS (GET_MODE (XEXP (x, 1))))
+ if (HONOR_NANS (XEXP (x, 0))
+ || HONOR_NANS (XEXP (x, 1)))
return 1;
break;
case EQ:
case NE:
if (HONOR_SNANS (GET_MODE (x)))
return 1;
/* Often comparison is CC mode, so check operand modes. */
if (HONOR_SNANS (GET_MODE (XEXP (x, 0)))
|| HONOR_SNANS (GET_MODE (XEXP (x, 1))))
return 1;
break;
case FIX:
/* Conversion of floating point might trap. */
- if (flag_trapping_math && HONOR_NANS (GET_MODE (XEXP (x, 0))))
+ if (flag_trapping_math && HONOR_NANS (XEXP (x, 0)))
return 1;
break;
case NEG:
case ABS:
case SUBREG:
/* These operations don't trap even with floating point. */
break;
default:
Index: simplify-rtx.c
===================================================================
--- simplify-rtx.c (revision 218467)
+++ simplify-rtx.c (working copy)
@@ -4721,21 +4721,21 @@ simplify_const_relational_operation (enu
if (! HONOR_NANS (mode) && code == ORDERED)
return const_true_rtx;
if (! HONOR_NANS (mode) && code == UNORDERED)
return const0_rtx;
/* For modes without NaNs, if the two operands are equal, we know the
result except if they have side-effects. Even with NaNs we know
the result of unordered comparisons and, if signaling NaNs are
irrelevant, also the result of LT/GT/LTGT. */
- if ((! HONOR_NANS (GET_MODE (trueop0))
+ if ((! HONOR_NANS (trueop0)
|| code == UNEQ || code == UNLE || code == UNGE
|| ((code == LT || code == GT || code == LTGT)
&& ! HONOR_SNANS (GET_MODE (trueop0))))
&& rtx_equal_p (trueop0, trueop1)
&& ! side_effects_p (trueop0))
return comparison_result (code, CMP_EQ);
/* If the operands are floating-point constants, see if we can fold
the result. */
if (CONST_DOUBLE_AS_FLOAT_P (trueop0)
Index: tree-if-conv.c
===================================================================
--- tree-if-conv.c (revision 218467)
+++ tree-if-conv.c (working copy)
@@ -304,21 +304,21 @@ parse_predicate (tree cond, tree *op0, t
return gimple_assign_rhs_code (s);
}
else if (gimple_assign_rhs_code (s) == TRUTH_NOT_EXPR)
{
tree op = gimple_assign_rhs1 (s);
tree type = TREE_TYPE (op);
enum tree_code code = parse_predicate (op, op0, op1);
return code == ERROR_MARK ? ERROR_MARK
- : invert_tree_comparison (code, HONOR_NANS (TYPE_MODE (type)));
+ : invert_tree_comparison (code, HONOR_NANS (type));
}
return ERROR_MARK;
}
if (TREE_CODE_CLASS (TREE_CODE (cond)) == tcc_comparison)
{
*op0 = TREE_OPERAND (cond, 0);
*op1 = TREE_OPERAND (cond, 1);
return TREE_CODE (cond);
Index: tree-ssa-ccp.c
===================================================================
--- tree-ssa-ccp.c (revision 218467)
+++ tree-ssa-ccp.c (working copy)
@@ -451,38 +451,38 @@ valid_lattice_transition (ccp_prop_value
/* At least the kinds and types should agree now. */
if (TREE_CODE (old_val.value) != TREE_CODE (new_val.value)
|| !types_compatible_p (TREE_TYPE (old_val.value),
TREE_TYPE (new_val.value)))
return false;
/* For floats and !HONOR_NANS allow transitions from (partial) NaN
to non-NaN. */
tree type = TREE_TYPE (new_val.value);
if (SCALAR_FLOAT_TYPE_P (type)
- && !HONOR_NANS (TYPE_MODE (type)))
+ && !HONOR_NANS (type))
{
if (REAL_VALUE_ISNAN (TREE_REAL_CST (old_val.value)))
return true;
}
else if (VECTOR_FLOAT_TYPE_P (type)
- && !HONOR_NANS (TYPE_MODE (TREE_TYPE (type))))
+ && !HONOR_NANS (type))
{
for (unsigned i = 0; i < VECTOR_CST_NELTS (old_val.value); ++i)
if (!REAL_VALUE_ISNAN
(TREE_REAL_CST (VECTOR_CST_ELT (old_val.value, i)))
&& !operand_equal_p (VECTOR_CST_ELT (old_val.value, i),
VECTOR_CST_ELT (new_val.value, i), 0))
return false;
return true;
}
else if (COMPLEX_FLOAT_TYPE_P (type)
- && !HONOR_NANS (TYPE_MODE (TREE_TYPE (type))))
+ && !HONOR_NANS (type))
{
if (!REAL_VALUE_ISNAN (TREE_REAL_CST (TREE_REALPART (old_val.value)))
&& !operand_equal_p (TREE_REALPART (old_val.value),
TREE_REALPART (new_val.value), 0))
return false;
if (!REAL_VALUE_ISNAN (TREE_REAL_CST (TREE_IMAGPART (old_val.value)))
&& !operand_equal_p (TREE_IMAGPART (old_val.value),
TREE_IMAGPART (new_val.value), 0))
return false;
return true;
Index: tree-ssa-ifcombine.c
===================================================================
--- tree-ssa-ifcombine.c (revision 218467)
+++ tree-ssa-ifcombine.c (working copy)
@@ -512,26 +512,26 @@ ifcombine_ifandif (basic_block inner_con
else if (TREE_CODE_CLASS (gimple_cond_code (inner_cond)) == tcc_comparison
&& TREE_CODE_CLASS (gimple_cond_code (outer_cond)) == tcc_comparison)
{
tree t;
enum tree_code inner_cond_code = gimple_cond_code (inner_cond);
enum tree_code outer_cond_code = gimple_cond_code (outer_cond);
/* Invert comparisons if necessary (and possible). */
if (inner_inv)
inner_cond_code = invert_tree_comparison (inner_cond_code,
- HONOR_NANS (TYPE_MODE (TREE_TYPE (gimple_cond_lhs (inner_cond)))));
+ HONOR_NANS (gimple_cond_lhs (inner_cond)));
if (inner_cond_code == ERROR_MARK)
return false;
if (outer_inv)
outer_cond_code = invert_tree_comparison (outer_cond_code,
- HONOR_NANS (TYPE_MODE (TREE_TYPE (gimple_cond_lhs (outer_cond)))));
+ HONOR_NANS (gimple_cond_lhs (outer_cond)));
if (outer_cond_code == ERROR_MARK)
return false;
/* Don't return false so fast, try maybe_fold_or_comparisons? */
if (!(t = maybe_fold_and_comparisons (inner_cond_code,
gimple_cond_lhs (inner_cond),
gimple_cond_rhs (inner_cond),
outer_cond_code,
gimple_cond_lhs (outer_cond),
gimple_cond_rhs (outer_cond))))
Index: tree-ssa-phiopt.c
===================================================================
--- tree-ssa-phiopt.c (revision 218467)
+++ tree-ssa-phiopt.c (working copy)
@@ -925,21 +925,21 @@ minmax_replacement (basic_block cond_bb,
gcond *cond;
gassign *new_stmt;
edge true_edge, false_edge;
enum tree_code cmp, minmax, ass_code;
tree smaller, larger, arg_true, arg_false;
gimple_stmt_iterator gsi, gsi_from;
type = TREE_TYPE (PHI_RESULT (phi));
/* The optimization may be unsafe due to NaNs. */
- if (HONOR_NANS (TYPE_MODE (type)))
+ if (HONOR_NANS (type))
return false;
cond = as_a <gcond *> (last_stmt (cond_bb));
cmp = gimple_cond_code (cond);
/* This transformation is only valid for order comparisons. Record which
operand is smaller/larger if the result of the comparison is true. */
if (cmp == LT_EXPR || cmp == LE_EXPR)
{
smaller = gimple_cond_lhs (cond);
@@ -1348,22 +1348,21 @@ neg_replacement (basic_block cond_bb, ba
invert = false_edge->dest == middle_bb;
/* Unlike abs_replacement, we can handle arbitrary conditionals here. */
cond = last_stmt (cond_bb);
cond_code = gimple_cond_code (cond);
/* If inversion is needed, first try to invert the test since
that's cheapest. */
if (invert)
{
- bool honor_nans
- = HONOR_NANS (TYPE_MODE (TREE_TYPE (gimple_cond_lhs (cond))));
+ bool honor_nans = HONOR_NANS (gimple_cond_lhs (cond));
enum tree_code new_code = invert_tree_comparison (cond_code, honor_nans);
/* If invert_tree_comparison was successful, then use its return
value as the new code and note that inversion is no longer
needed. */
if (new_code != ERROR_MARK)
{
cond_code = new_code;
invert = false;
}
Index: tree-ssa-reassoc.c
===================================================================
--- tree-ssa-reassoc.c (revision 218467)
+++ tree-ssa-reassoc.c (working copy)
@@ -959,21 +959,21 @@ eliminate_using_constants (enum tree_cod
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Found | 0, removing\n");
ops->pop ();
reassociate_stats.ops_eliminated++;
}
}
break;
case MULT_EXPR:
if (integer_zerop (oelast->op)
|| (FLOAT_TYPE_P (type)
- && !HONOR_NANS (TYPE_MODE (type))
+ && !HONOR_NANS (type)
&& !HONOR_SIGNED_ZEROS (TYPE_MODE (type))
&& real_zerop (oelast->op)))
{
if (ops->length () != 1)
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Found * 0, removing all other ops\n");
reassociate_stats.ops_eliminated += ops->length () - 1;
ops->truncate (1);
Index: tree-ssa-tail-merge.c
===================================================================
--- tree-ssa-tail-merge.c (revision 218467)
+++ tree-ssa-tail-merge.c (working copy)
@@ -1190,22 +1190,21 @@ gimple_equal_p (same_succ same_succ, gim
t2 = gimple_cond_rhs (s2);
if (!gimple_operand_equal_value_p (t1, t2))
return false;
code1 = gimple_expr_code (s1);
code2 = gimple_expr_code (s2);
inv_cond = (bitmap_bit_p (same_succ->inverse, bb1->index)
!= bitmap_bit_p (same_succ->inverse, bb2->index));
if (inv_cond)
{
- bool honor_nans
- = HONOR_NANS (TYPE_MODE (TREE_TYPE (gimple_cond_lhs (s1))));
+ bool honor_nans = HONOR_NANS (t1);
code2 = invert_tree_comparison (code2, honor_nans);
}
return code1 == code2;
default:
return false;
}
}
/* Let GSI skip backwards over local defs. Return the earliest vuse in VUSE.