+2014-12-10 Marc Glisse <marc.glisse@inria.fr>
+
+ * 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.
+
2014-12-10 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/62021
}
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);
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)
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));
}
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;
&& 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;
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);
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);
}
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;
}
}
- 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))
{
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);
/* 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:
/* 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
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 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))
{
}
/* 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)))
}
/* 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)))
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))
{
/* 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;
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);
&& 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;
}
}
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)
{
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
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.
(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); }))
(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); }))
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)
(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)
#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,
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));
+}
+
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))
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 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;
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))))
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;
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
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),
/* 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? */
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));
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
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)))
{
!= 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;