+ if (REAL_VALUE_ISINF (c2))
+ {
+ /* sqrt(x) < y is always true, when y is a very large
+ value and we don't care about NaNs or Infinities. */
+ if (! HONOR_NANS (mode) && ! HONOR_INFINITIES (mode))
+ return omit_one_operand (type,
+ fold_convert (type, integer_one_node),
+ arg);
+
+ /* sqrt(x) < y is x != +Inf when y is very large and we
+ don't care about NaNs. */
+ if (! HONOR_NANS (mode))
+ return fold (build (NE_EXPR, type, arg,
+ build_real (TREE_TYPE (arg), c2)));
+
+ /* sqrt(x) < y is x >= 0 when y is very large and we
+ don't care about Infinities. */
+ if (! HONOR_INFINITIES (mode))
+ return fold (build (GE_EXPR, type, arg,
+ build_real (TREE_TYPE (arg), dconst0)));
+
+ /* sqrt(x) < y is x >= 0 && x != +Inf, when y is large. */
+ if ((*lang_hooks.decls.global_bindings_p) () != 0
+ || CONTAINS_PLACEHOLDER_P (arg))
+ return NULL_TREE;
+
+ arg = save_expr (arg);
+ return fold (build (TRUTH_ANDIF_EXPR, type,
+ fold (build (GE_EXPR, type, arg,
+ build_real (TREE_TYPE (arg),
+ dconst0))),
+ fold (build (NE_EXPR, type, arg,
+ build_real (TREE_TYPE (arg),
+ c2)))));
+ }
+
+ /* sqrt(x) < c is the same as x < c*c, if we ignore NaNs. */
+ if (! HONOR_NANS (mode))
+ return fold (build (code, type, arg,
+ build_real (TREE_TYPE (arg), c2)));
+
+ /* sqrt(x) < c is the same as x >= 0 && x < c*c. */
+ if ((*lang_hooks.decls.global_bindings_p) () == 0
+ && ! CONTAINS_PLACEHOLDER_P (arg))
+ {
+ arg = save_expr (arg);
+ return fold (build (TRUTH_ANDIF_EXPR, type,
+ fold (build (GE_EXPR, type, arg,
+ build_real (TREE_TYPE (arg),
+ dconst0))),
+ fold (build (code, type, arg,
+ build_real (TREE_TYPE (arg),
+ c2)))));
+ }
+ }
+ }
+
+ return NULL_TREE;
+}
+
+/* Subroutine of fold() that optimizes comparisons against Infinities,
+ either +Inf or -Inf.
+
+ CODE is the comparison operator: EQ_EXPR, NE_EXPR, GT_EXPR, LT_EXPR,
+ GE_EXPR or LE_EXPR. TYPE is the type of the result and ARG0 and ARG1
+ are the operands of the comparison. ARG1 must be a TREE_REAL_CST.
+
+ The function returns the constant folded tree if a simplification
+ can be made, and NULL_TREE otherwise. */
+
+static tree
+fold_inf_compare (enum tree_code code, tree type, tree arg0, tree arg1)
+{
+ enum machine_mode mode;
+ REAL_VALUE_TYPE max;
+ tree temp;
+ bool neg;
+
+ mode = TYPE_MODE (TREE_TYPE (arg0));
+
+ /* For negative infinity swap the sense of the comparison. */
+ neg = REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg1));
+ if (neg)
+ code = swap_tree_comparison (code);
+
+ switch (code)
+ {
+ case GT_EXPR:
+ /* x > +Inf is always false, if with ignore sNANs. */
+ if (HONOR_SNANS (mode))
+ return NULL_TREE;
+ return omit_one_operand (type,
+ fold_convert (type, integer_zero_node),
+ arg0);
+
+ case LE_EXPR:
+ /* x <= +Inf is always true, if we don't case about NaNs. */
+ if (! HONOR_NANS (mode))
+ return omit_one_operand (type,
+ fold_convert (type, integer_one_node),
+ arg0);
+
+ /* x <= +Inf is the same as x == x, i.e. isfinite(x). */
+ if ((*lang_hooks.decls.global_bindings_p) () == 0
+ && ! CONTAINS_PLACEHOLDER_P (arg0))
+ {
+ arg0 = save_expr (arg0);
+ return fold (build (EQ_EXPR, type, arg0, arg0));
+ }
+ break;
+
+ case EQ_EXPR:
+ case GE_EXPR:
+ /* x == +Inf and x >= +Inf are always equal to x > DBL_MAX. */
+ real_maxval (&max, neg, mode);
+ return fold (build (neg ? LT_EXPR : GT_EXPR, type,
+ arg0, build_real (TREE_TYPE (arg0), max)));
+
+ case LT_EXPR:
+ /* x < +Inf is always equal to x <= DBL_MAX. */
+ real_maxval (&max, neg, mode);
+ return fold (build (neg ? GE_EXPR : LE_EXPR, type,
+ arg0, build_real (TREE_TYPE (arg0), max)));
+
+ case NE_EXPR:
+ /* x != +Inf is always equal to !(x > DBL_MAX). */
+ real_maxval (&max, neg, mode);
+ if (! HONOR_NANS (mode))
+ return fold (build (neg ? GE_EXPR : LE_EXPR, type,
+ arg0, build_real (TREE_TYPE (arg0), max)));
+ temp = fold (build (neg ? LT_EXPR : GT_EXPR, type,
+ arg0, build_real (TREE_TYPE (arg0), max)));
+ return fold (build1 (TRUTH_NOT_EXPR, type, temp));
+
+ default:
+ break;
+ }
+
+ return NULL_TREE;
+}
+
+/* If CODE with arguments ARG0 and ARG1 represents a single bit
+ equality/inequality test, then return a simplified form of
+ the test using shifts and logical operations. Otherwise return
+ NULL. TYPE is the desired result type. */
+
+tree
+fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
+ tree result_type)
+{
+ /* If this is a TRUTH_NOT_EXPR, it may have a single bit test inside
+ operand 0. */
+ if (code == TRUTH_NOT_EXPR)
+ {
+ code = TREE_CODE (arg0);
+ if (code != NE_EXPR && code != EQ_EXPR)
+ return NULL_TREE;
+
+ /* Extract the arguments of the EQ/NE. */
+ arg1 = TREE_OPERAND (arg0, 1);
+ arg0 = TREE_OPERAND (arg0, 0);
+
+ /* This requires us to invert the code. */
+ code = (code == EQ_EXPR ? NE_EXPR : EQ_EXPR);
+ }
+
+ /* If this is testing a single bit, we can optimize the test. */
+ if ((code == NE_EXPR || code == EQ_EXPR)
+ && TREE_CODE (arg0) == BIT_AND_EXPR && integer_zerop (arg1)
+ && integer_pow2p (TREE_OPERAND (arg0, 1)))
+ {
+ tree inner = TREE_OPERAND (arg0, 0);
+ tree type = TREE_TYPE (arg0);
+ int bitnum = tree_log2 (TREE_OPERAND (arg0, 1));
+ enum machine_mode operand_mode = TYPE_MODE (type);
+ int ops_unsigned;
+ tree signed_type, unsigned_type, intermediate_type;
+ tree arg00;
+
+ /* If we have (A & C) != 0 where C is the sign bit of A, convert
+ this into A < 0. Similarly for (A & C) == 0 into A >= 0. */
+ arg00 = sign_bit_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1));
+ if (arg00 != NULL_TREE)
+ {
+ tree stype = (*lang_hooks.types.signed_type) (TREE_TYPE (arg00));
+ return fold (build (code == EQ_EXPR ? GE_EXPR : LT_EXPR, result_type,
+ fold_convert (stype, arg00),
+ fold_convert (stype, integer_zero_node)));
+ }
+
+ /* At this point, we know that arg0 is not testing the sign bit. */
+ if (TYPE_PRECISION (type) - 1 == bitnum)
+ abort ();
+
+ /* Otherwise we have (A & C) != 0 where C is a single bit,
+ convert that into ((A >> C2) & 1). Where C2 = log2(C).
+ Similarly for (A & C) == 0. */
+
+ /* If INNER is a right shift of a constant and it plus BITNUM does
+ not overflow, adjust BITNUM and INNER. */
+ if (TREE_CODE (inner) == RSHIFT_EXPR
+ && TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST
+ && TREE_INT_CST_HIGH (TREE_OPERAND (inner, 1)) == 0
+ && bitnum < TYPE_PRECISION (type)
+ && 0 > compare_tree_int (TREE_OPERAND (inner, 1),
+ bitnum - TYPE_PRECISION (type)))
+ {
+ bitnum += TREE_INT_CST_LOW (TREE_OPERAND (inner, 1));
+ inner = TREE_OPERAND (inner, 0);
+ }
+
+ /* If we are going to be able to omit the AND below, we must do our
+ operations as unsigned. If we must use the AND, we have a choice.
+ Normally unsigned is faster, but for some machines signed is. */
+#ifdef LOAD_EXTEND_OP
+ ops_unsigned = (LOAD_EXTEND_OP (operand_mode) == SIGN_EXTEND ? 0 : 1);
+#else
+ ops_unsigned = 1;
+#endif
+
+ signed_type = (*lang_hooks.types.type_for_mode) (operand_mode, 0);
+ unsigned_type = (*lang_hooks.types.type_for_mode) (operand_mode, 1);
+ intermediate_type = ops_unsigned ? unsigned_type : signed_type;
+ inner = fold_convert (intermediate_type, inner);
+
+ if (bitnum != 0)
+ inner = build (RSHIFT_EXPR, intermediate_type,
+ inner, size_int (bitnum));
+
+ if (code == EQ_EXPR)
+ inner = build (BIT_XOR_EXPR, intermediate_type,
+ inner, integer_one_node);
+
+ /* Put the AND last so it can combine with more things. */
+ inner = build (BIT_AND_EXPR, intermediate_type,
+ inner, integer_one_node);
+
+ /* Make sure to return the proper type. */
+ inner = fold_convert (result_type, inner);
+
+ return inner;
+ }
+ return NULL_TREE;
+}
+
+/* Check whether we are allowed to reorder operands arg0 and arg1,
+ such that the evaluation of arg1 occurs before arg0. */
+
+static bool
+reorder_operands_p (tree arg0, tree arg1)
+{
+ if (! flag_evaluation_order)
+ return true;
+ if (TREE_CONSTANT (arg0) || TREE_CONSTANT (arg1))
+ return true;
+ return ! TREE_SIDE_EFFECTS (arg0)
+ && ! TREE_SIDE_EFFECTS (arg1);
+}
+
+/* Test whether it is preferable two swap two operands, ARG0 and
+ ARG1, for example because ARG0 is an integer constant and ARG1
+ isn't. If REORDER is true, only recommend swapping if we can
+ evaluate the operands in reverse order. */
+
+static bool
+tree_swap_operands_p (tree arg0, tree arg1, bool reorder)
+{
+ STRIP_SIGN_NOPS (arg0);
+ STRIP_SIGN_NOPS (arg1);
+
+ if (TREE_CODE (arg1) == INTEGER_CST)
+ return 0;
+ if (TREE_CODE (arg0) == INTEGER_CST)
+ return 1;
+
+ if (TREE_CODE (arg1) == REAL_CST)
+ return 0;
+ if (TREE_CODE (arg0) == REAL_CST)
+ return 1;
+
+ if (TREE_CODE (arg1) == COMPLEX_CST)
+ return 0;
+ if (TREE_CODE (arg0) == COMPLEX_CST)
+ return 1;
+
+ if (TREE_CONSTANT (arg1))
+ return 0;
+ if (TREE_CONSTANT (arg0))
+ return 1;
+
+ if (optimize_size)
+ return 0;
+
+ if (reorder && flag_evaluation_order
+ && (TREE_SIDE_EFFECTS (arg0) || TREE_SIDE_EFFECTS (arg1)))
+ return 0;
+
+ if (DECL_P (arg1))
+ return 0;
+ if (DECL_P (arg0))
+ return 1;
+
+ return 0;
+}
+
+/* Perform constant folding and related simplification of EXPR.
+ The related simplifications include x*1 => x, x*0 => 0, etc.,
+ and application of the associative law.
+ NOP_EXPR conversions may be removed freely (as long as we
+ are careful not to change the C type of the overall expression)
+ We cannot simplify through a CONVERT_EXPR, FIX_EXPR or FLOAT_EXPR,
+ but we can constant-fold them if they have constant operands. */
+
+#ifdef ENABLE_FOLD_CHECKING
+# define fold(x) fold_1 (x)
+static tree fold_1 (tree);
+static
+#endif
+tree
+fold (tree expr)
+{
+ tree t = expr, orig_t;
+ tree t1 = NULL_TREE;
+ tree tem;
+ tree type = TREE_TYPE (expr);
+ tree arg0 = NULL_TREE, arg1 = NULL_TREE;
+ enum tree_code code = TREE_CODE (t);
+ int kind = TREE_CODE_CLASS (code);
+ int invert;
+ /* WINS will be nonzero when the switch is done
+ if all operands are constant. */
+ int wins = 1;
+
+ /* Don't try to process an RTL_EXPR since its operands aren't trees.
+ Likewise for a SAVE_EXPR that's already been evaluated. */
+ if (code == RTL_EXPR || (code == SAVE_EXPR && SAVE_EXPR_RTL (t) != 0))
+ return t;
+
+ /* Return right away if a constant. */
+ if (kind == 'c')
+ return t;
+
+ orig_t = t;
+
+ if (code == NOP_EXPR || code == FLOAT_EXPR || code == CONVERT_EXPR)
+ {
+ tree subop;
+
+ /* Special case for conversion ops that can have fixed point args. */
+ arg0 = TREE_OPERAND (t, 0);
+
+ /* Don't use STRIP_NOPS, because signedness of argument type matters. */
+ if (arg0 != 0)
+ STRIP_SIGN_NOPS (arg0);
+
+ if (arg0 != 0 && TREE_CODE (arg0) == COMPLEX_CST)
+ subop = TREE_REALPART (arg0);
+ else
+ subop = arg0;