#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
+#include "backend.h"
+#include "predict.h"
+#include "tree.h"
+#include "gimple.h"
+#include "rtl.h"
#include "flags.h"
#include "alias.h"
-#include "symtab.h"
-#include "tree.h"
#include "fold-const.h"
#include "stor-layout.h"
#include "calls.h"
#include "tree-iterator.h"
#include "realmpfr.h"
-#include "rtl.h"
-#include "hard-reg-set.h"
-#include "function.h"
#include "insn-config.h"
#include "expmed.h"
#include "dojump.h"
#include "intl.h"
#include "langhooks.h"
#include "md5.h"
-#include "predict.h"
-#include "basic-block.h"
-#include "tree-ssa-alias.h"
#include "internal-fn.h"
#include "tree-eh.h"
-#include "gimple-expr.h"
-#include "gimple.h"
#include "gimplify.h"
#include "tree-dfa.h"
#include "builtins.h"
#include "generic-match.h"
#include "optabs.h"
+#ifndef LOAD_EXTEND_OP
+#define LOAD_EXTEND_OP(M) UNKNOWN
+#endif
+
/* Nonzero if we are folding constants inside an initializer; zero
otherwise. */
int folding_initializer = 0;
static int operand_equal_for_comparison_p (tree, tree, tree);
static int twoval_comparison_p (tree, tree *, tree *, int *);
static tree eval_subst (location_t, tree, tree, tree, tree, tree);
-static tree distribute_bit_expr (location_t, enum tree_code, tree, tree, tree);
static tree make_bit_field_ref (location_t, tree, tree,
HOST_WIDE_INT, HOST_WIDE_INT, int);
static tree optimize_bit_field_compare (location_t, enum tree_code,
enum tree_code, tree,
tree, tree,
tree, tree, int);
-static tree fold_mathfn_compare (location_t,
- enum built_in_function, enum tree_code,
- tree, tree, tree);
-static tree fold_inf_compare (location_t, enum tree_code, tree, tree, tree);
static tree fold_div_compare (location_t, enum tree_code, tree, tree, tree);
static bool reorder_operands_p (const_tree, const_tree);
static tree fold_negate_const (tree, tree);
type, arg);
}
-/* Given a bit-wise operation CODE applied to ARG0 and ARG1, see if both
- operands are another bit-wise operation with a common input. If so,
- distribute the bit operations to save an operation and possibly two if
- constants are involved. For example, convert
- (A | B) & (A | C) into A | (B & C)
- Further simplification will occur if B and C are constants.
-
- If this optimization cannot be done, 0 will be returned. */
-
-static tree
-distribute_bit_expr (location_t loc, enum tree_code code, tree type,
- tree arg0, tree arg1)
-{
- tree common;
- tree left, right;
-
- if (TREE_CODE (arg0) != TREE_CODE (arg1)
- || TREE_CODE (arg0) == code
- || (TREE_CODE (arg0) != BIT_AND_EXPR
- && TREE_CODE (arg0) != BIT_IOR_EXPR))
- return 0;
-
- if (operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0), 0))
- {
- common = TREE_OPERAND (arg0, 0);
- left = TREE_OPERAND (arg0, 1);
- right = TREE_OPERAND (arg1, 1);
- }
- else if (operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 1), 0))
- {
- common = TREE_OPERAND (arg0, 0);
- left = TREE_OPERAND (arg0, 1);
- right = TREE_OPERAND (arg1, 0);
- }
- else if (operand_equal_p (TREE_OPERAND (arg0, 1), TREE_OPERAND (arg1, 0), 0))
- {
- common = TREE_OPERAND (arg0, 1);
- left = TREE_OPERAND (arg0, 0);
- right = TREE_OPERAND (arg1, 1);
- }
- else if (operand_equal_p (TREE_OPERAND (arg0, 1), TREE_OPERAND (arg1, 1), 0))
- {
- common = TREE_OPERAND (arg0, 1);
- left = TREE_OPERAND (arg0, 0);
- right = TREE_OPERAND (arg1, 0);
- }
- else
- return 0;
-
- common = fold_convert_loc (loc, type, common);
- left = fold_convert_loc (loc, type, left);
- right = fold_convert_loc (loc, type, right);
- return fold_build2_loc (loc, TREE_CODE (arg0), type, common,
- fold_build2_loc (loc, code, type, left, right));
-}
-
/* Knowing that ARG0 and ARG1 are both RDIV_EXPRs, simplify a binary operation
with code CODE. This optimization is unsafe. */
static tree
return negate && !HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type));
}
-/* Subroutine of fold() that checks comparisons of built-in math
- functions against real constants.
-
- FCODE is the DECL_FUNCTION_CODE of the built-in, 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_mathfn_compare (location_t loc,
- enum built_in_function fcode, enum tree_code code,
- tree type, tree arg0, tree arg1)
-{
- REAL_VALUE_TYPE c;
-
- if (BUILTIN_SQRT_P (fcode))
- {
- tree arg = CALL_EXPR_ARG (arg0, 0);
- machine_mode mode = TYPE_MODE (TREE_TYPE (arg0));
-
- c = TREE_REAL_CST (arg1);
- if (REAL_VALUE_NEGATIVE (c))
- {
- /* sqrt(x) < y is always false, if y is negative. */
- if (code == EQ_EXPR || code == LT_EXPR || code == LE_EXPR)
- return omit_one_operand_loc (loc, type, integer_zero_node, arg);
-
- /* sqrt(x) > y is always true, if y is negative and we
- don't care about NaNs, i.e. negative values of x. */
- if (code == NE_EXPR || !HONOR_NANS (mode))
- return omit_one_operand_loc (loc, type, integer_one_node, arg);
-
- /* sqrt(x) > y is the same as x >= 0, if y is negative. */
- return fold_build2_loc (loc, GE_EXPR, type, arg,
- build_real (TREE_TYPE (arg), dconst0));
- }
- else if (code == GT_EXPR || code == GE_EXPR)
- {
- REAL_VALUE_TYPE c2;
-
- REAL_ARITHMETIC (c2, MULT_EXPR, c, c);
- real_convert (&c2, mode, &c2);
-
- if (REAL_VALUE_ISINF (c2))
- {
- /* sqrt(x) > y is x == +Inf, when y is very large. */
- if (HONOR_INFINITIES (mode))
- return fold_build2_loc (loc, EQ_EXPR, type, arg,
- build_real (TREE_TYPE (arg), c2));
-
- /* sqrt(x) > y is always false, when y is very large
- and we don't care about infinities. */
- return omit_one_operand_loc (loc, type, integer_zero_node, arg);
- }
-
- /* sqrt(x) > c is the same as x > c*c. */
- return fold_build2_loc (loc, code, type, arg,
- build_real (TREE_TYPE (arg), c2));
- }
- else if (code == LT_EXPR || code == LE_EXPR)
- {
- REAL_VALUE_TYPE c2;
-
- REAL_ARITHMETIC (c2, MULT_EXPR, c, c);
- real_convert (&c2, mode, &c2);
-
- 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_loc (loc, 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_build2_loc (loc, 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_build2_loc (loc, GE_EXPR, type, arg,
- build_real (TREE_TYPE (arg), dconst0));
-
- /* sqrt(x) < y is x >= 0 && x != +Inf, when y is large. */
- arg = save_expr (arg);
- return fold_build2_loc (loc, TRUTH_ANDIF_EXPR, type,
- fold_build2_loc (loc, GE_EXPR, type, arg,
- build_real (TREE_TYPE (arg),
- dconst0)),
- fold_build2_loc (loc, 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_build2_loc (loc, code, type, arg,
- build_real (TREE_TYPE (arg), c2));
-
- /* sqrt(x) < c is the same as x >= 0 && x < c*c. */
- arg = save_expr (arg);
- return fold_build2_loc (loc, TRUTH_ANDIF_EXPR, type,
- fold_build2_loc (loc, GE_EXPR, type, arg,
- build_real (TREE_TYPE (arg),
- dconst0)),
- fold_build2_loc (loc, 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 (location_t loc, enum tree_code code, tree type,
- tree arg0, tree arg1)
-{
- 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_loc (loc, 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_loc (loc, type, integer_one_node, arg0);
-
- /* x <= +Inf is the same as x == x, i.e. isfinite(x). */
- arg0 = save_expr (arg0);
- return fold_build2_loc (loc, EQ_EXPR, type, arg0, arg0);
-
- 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_build2_loc (loc, 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_build2_loc (loc, 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_build2_loc (loc, neg ? GE_EXPR : LE_EXPR, type,
- arg0, build_real (TREE_TYPE (arg0), max));
-
- temp = fold_build2_loc (loc, neg ? LT_EXPR : GT_EXPR, type,
- arg0, build_real (TREE_TYPE (arg0), max));
- return fold_build1_loc (loc, TRUTH_NOT_EXPR, type, temp);
-
- default:
- break;
- }
-
- return NULL_TREE;
-}
-
/* Subroutine of fold() that optimizes comparisons of a division by
a nonzero integer constant against an integer constant, i.e.
X/C1 op C2.
/* 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
&& !flag_syntax_only) ? 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);
return 0;
}
-/* Fold comparison ARG0 CODE ARG1 (with result in TYPE), where
- ARG0 is extended to a wider type. */
-
-static tree
-fold_widened_comparison (location_t loc, enum tree_code code,
- tree type, tree arg0, tree arg1)
-{
- tree arg0_unw = get_unwidened (arg0, NULL_TREE);
- tree arg1_unw;
- tree shorter_type, outer_type;
- tree min, max;
- bool above, below;
-
- if (arg0_unw == arg0)
- return NULL_TREE;
- shorter_type = TREE_TYPE (arg0_unw);
-
- /* Disable this optimization if we're casting a function pointer
- type on targets that require function pointer canonicalization. */
- if (targetm.have_canonicalize_funcptr_for_compare ()
- && TREE_CODE (shorter_type) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (shorter_type)) == FUNCTION_TYPE)
- return NULL_TREE;
-
- if (TYPE_PRECISION (TREE_TYPE (arg0)) <= TYPE_PRECISION (shorter_type))
- return NULL_TREE;
-
- arg1_unw = get_unwidened (arg1, NULL_TREE);
-
- /* If possible, express the comparison in the shorter mode. */
- if ((code == EQ_EXPR || code == NE_EXPR
- || TYPE_UNSIGNED (TREE_TYPE (arg0)) == TYPE_UNSIGNED (shorter_type))
- && (TREE_TYPE (arg1_unw) == shorter_type
- || ((TYPE_PRECISION (shorter_type)
- >= TYPE_PRECISION (TREE_TYPE (arg1_unw)))
- && (TYPE_UNSIGNED (shorter_type)
- == TYPE_UNSIGNED (TREE_TYPE (arg1_unw))))
- || (TREE_CODE (arg1_unw) == INTEGER_CST
- && (TREE_CODE (shorter_type) == INTEGER_TYPE
- || TREE_CODE (shorter_type) == BOOLEAN_TYPE)
- && int_fits_type_p (arg1_unw, shorter_type))))
- return fold_build2_loc (loc, code, type, arg0_unw,
- fold_convert_loc (loc, shorter_type, arg1_unw));
-
- if (TREE_CODE (arg1_unw) != INTEGER_CST
- || TREE_CODE (shorter_type) != INTEGER_TYPE
- || !int_fits_type_p (arg1_unw, shorter_type))
- return NULL_TREE;
-
- /* If we are comparing with the integer that does not fit into the range
- of the shorter type, the result is known. */
- outer_type = TREE_TYPE (arg1_unw);
- min = lower_bound_in_type (outer_type, shorter_type);
- max = upper_bound_in_type (outer_type, shorter_type);
-
- above = integer_nonzerop (fold_relational_const (LT_EXPR, type,
- max, arg1_unw));
- below = integer_nonzerop (fold_relational_const (LT_EXPR, type,
- arg1_unw, min));
-
- switch (code)
- {
- case EQ_EXPR:
- if (above || below)
- return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
- break;
-
- case NE_EXPR:
- if (above || below)
- return omit_one_operand_loc (loc, type, integer_one_node, arg0);
- break;
-
- case LT_EXPR:
- case LE_EXPR:
- if (above)
- return omit_one_operand_loc (loc, type, integer_one_node, arg0);
- else if (below)
- return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
-
- case GT_EXPR:
- case GE_EXPR:
- if (above)
- return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
- else if (below)
- return omit_one_operand_loc (loc, type, integer_one_node, arg0);
-
- default:
- break;
- }
-
- return NULL_TREE;
-}
-
-/* Fold comparison ARG0 CODE ARG1 (with result in TYPE), where for
- ARG0 just the signedness is changed. */
-
-static tree
-fold_sign_changed_comparison (location_t loc, enum tree_code code, tree type,
- tree arg0, tree arg1)
-{
- tree arg0_inner;
- tree inner_type, outer_type;
-
- if (!CONVERT_EXPR_P (arg0))
- return NULL_TREE;
-
- outer_type = TREE_TYPE (arg0);
- arg0_inner = TREE_OPERAND (arg0, 0);
- inner_type = TREE_TYPE (arg0_inner);
-
- /* Disable this optimization if we're casting a function pointer
- type on targets that require function pointer canonicalization. */
- if (targetm.have_canonicalize_funcptr_for_compare ()
- && TREE_CODE (inner_type) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (inner_type)) == FUNCTION_TYPE)
- return NULL_TREE;
-
- if (TYPE_PRECISION (inner_type) != TYPE_PRECISION (outer_type))
- return NULL_TREE;
-
- if (TREE_CODE (arg1) != INTEGER_CST
- && !(CONVERT_EXPR_P (arg1)
- && TREE_TYPE (TREE_OPERAND (arg1, 0)) == inner_type))
- return NULL_TREE;
-
- if (TYPE_UNSIGNED (inner_type) != TYPE_UNSIGNED (outer_type)
- && code != NE_EXPR
- && code != EQ_EXPR)
- return NULL_TREE;
-
- if (POINTER_TYPE_P (inner_type) != POINTER_TYPE_P (outer_type))
- return NULL_TREE;
-
- if (TREE_CODE (arg1) == INTEGER_CST)
- arg1 = force_fit_type (inner_type, wi::to_widest (arg1), 0,
- TREE_OVERFLOW (arg1));
- else
- arg1 = fold_convert_loc (loc, inner_type, arg1);
-
- return fold_build2_loc (loc, code, type, arg0_inner, arg1);
-}
-
/* Fold A < X && A + 1 > Y to A < X && A >= Y. Normally A + 1 > Y
means A >= Y && A != MAX, but in this case we know that
cst &= HOST_WIDE_INT_M1U
<< (TYPE_PRECISION (TREE_TYPE (and1)) - 1);
change = (cst == 0);
-#ifdef LOAD_EXTEND_OP
if (change
&& !flag_syntax_only
&& (LOAD_EXTEND_OP (TYPE_MODE (TREE_TYPE (and0)))
and0 = fold_convert_loc (loc, uns, and0);
and1 = fold_convert_loc (loc, uns, and1);
}
-#endif
}
if (change)
{
enum tree_code code0 = TREE_CODE (arg0);
tree t, cst0 = NULL_TREE;
int sgn0;
- bool swap = false;
-
- /* Match A +- CST code arg1 and CST code arg1. We can change the
- first form only if overflow is undefined. */
- if (!(((ANY_INTEGRAL_TYPE_P (TREE_TYPE (arg0))
- && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0)))
- /* In principle pointers also have undefined overflow behavior,
- but that causes problems elsewhere. */
- && !POINTER_TYPE_P (TREE_TYPE (arg0))
- && (code0 == MINUS_EXPR
- || code0 == PLUS_EXPR)
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
- || code0 == INTEGER_CST))
+
+ /* Match A +- CST code arg1. We can change this only if overflow
+ is undefined. */
+ if (!((ANY_INTEGRAL_TYPE_P (TREE_TYPE (arg0))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0)))
+ /* In principle pointers also have undefined overflow behavior,
+ but that causes problems elsewhere. */
+ && !POINTER_TYPE_P (TREE_TYPE (arg0))
+ && (code0 == MINUS_EXPR
+ || code0 == PLUS_EXPR)
+ && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST))
return NULL_TREE;
/* Identify the constant in arg0 and its sign. */
- if (code0 == INTEGER_CST)
- cst0 = arg0;
- else
- cst0 = TREE_OPERAND (arg0, 1);
+ cst0 = TREE_OPERAND (arg0, 1);
sgn0 = tree_int_cst_sgn (cst0);
/* Overflowed constants and zero will cause problems. */
/* See if we can reduce the magnitude of the constant in
arg0 by changing the comparison code. */
- if (code0 == INTEGER_CST)
- {
- /* CST <= arg1 -> CST-1 < arg1. */
- if (code == LE_EXPR && sgn0 == 1)
- code = LT_EXPR;
- /* -CST < arg1 -> -CST-1 <= arg1. */
- else if (code == LT_EXPR && sgn0 == -1)
- code = LE_EXPR;
- /* CST > arg1 -> CST-1 >= arg1. */
- else if (code == GT_EXPR && sgn0 == 1)
- code = GE_EXPR;
- /* -CST >= arg1 -> -CST-1 > arg1. */
- else if (code == GE_EXPR && sgn0 == -1)
- code = GT_EXPR;
- else
- return NULL_TREE;
- /* arg1 code' CST' might be more canonical. */
- swap = true;
- }
+ /* A - CST < arg1 -> A - CST-1 <= arg1. */
+ if (code == LT_EXPR
+ && code0 == ((sgn0 == -1) ? PLUS_EXPR : MINUS_EXPR))
+ code = LE_EXPR;
+ /* A + CST > arg1 -> A + CST-1 >= arg1. */
+ else if (code == GT_EXPR
+ && code0 == ((sgn0 == -1) ? MINUS_EXPR : PLUS_EXPR))
+ code = GE_EXPR;
+ /* A + CST <= arg1 -> A + CST-1 < arg1. */
+ else if (code == LE_EXPR
+ && code0 == ((sgn0 == -1) ? MINUS_EXPR : PLUS_EXPR))
+ code = LT_EXPR;
+ /* A - CST >= arg1 -> A - CST-1 > arg1. */
+ else if (code == GE_EXPR
+ && code0 == ((sgn0 == -1) ? PLUS_EXPR : MINUS_EXPR))
+ code = GT_EXPR;
else
- {
- /* A - CST < arg1 -> A - CST-1 <= arg1. */
- if (code == LT_EXPR
- && code0 == ((sgn0 == -1) ? PLUS_EXPR : MINUS_EXPR))
- code = LE_EXPR;
- /* A + CST > arg1 -> A + CST-1 >= arg1. */
- else if (code == GT_EXPR
- && code0 == ((sgn0 == -1) ? MINUS_EXPR : PLUS_EXPR))
- code = GE_EXPR;
- /* A + CST <= arg1 -> A + CST-1 < arg1. */
- else if (code == LE_EXPR
- && code0 == ((sgn0 == -1) ? MINUS_EXPR : PLUS_EXPR))
- code = LT_EXPR;
- /* A - CST >= arg1 -> A - CST-1 > arg1. */
- else if (code == GE_EXPR
- && code0 == ((sgn0 == -1) ? PLUS_EXPR : MINUS_EXPR))
- code = GT_EXPR;
- else
- return NULL_TREE;
- *strict_overflow_p = true;
- }
+ return NULL_TREE;
+ *strict_overflow_p = true;
/* Now build the constant reduced in magnitude. But not if that
would produce one outside of its types range. */
|| (sgn0 == -1
&& TYPE_MAX_VALUE (TREE_TYPE (cst0))
&& tree_int_cst_equal (cst0, TYPE_MAX_VALUE (TREE_TYPE (cst0))))))
- /* We cannot swap the comparison here as that would cause us to
- endlessly recurse. */
return NULL_TREE;
t = int_const_binop (sgn0 == -1 ? PLUS_EXPR : MINUS_EXPR,
cst0, build_int_cst (TREE_TYPE (cst0), 1));
- if (code0 != INTEGER_CST)
- t = fold_build2_loc (loc, code0, TREE_TYPE (arg0), TREE_OPERAND (arg0, 0), t);
+ t = fold_build2_loc (loc, code0, TREE_TYPE (arg0), TREE_OPERAND (arg0, 0), t);
t = fold_convert (TREE_TYPE (arg1), t);
- /* If swapping might yield to a more canonical form, do so. */
- if (swap)
- return fold_build2_loc (loc, swap_tree_comparison (code), type, arg1, t);
- else
- return fold_build2_loc (loc, code, type, t, arg1);
+ return fold_build2_loc (loc, code, type, t, arg1);
}
/* Canonicalize the comparison ARG0 CODE ARG1 with type TYPE with undefined
}
}
- /* Transform comparisons of the form X - Y CMP 0 to X CMP Y. */
- if (TREE_CODE (arg0) == MINUS_EXPR
- && equality_code
- && integer_zerop (arg1))
- {
- /* ??? The transformation is valid for the other operators if overflow
- is undefined for the type, but performing it here badly interacts
- with the transformation in fold_cond_expr_with_comparison which
- attempts to synthetize ABS_EXPR. */
- if (!equality_code)
- fold_overflow_warning ("assuming signed overflow does not occur "
- "when changing X - Y cmp 0 to X cmp Y",
- WARN_STRICT_OVERFLOW_COMPARISON);
- return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg0, 1));
- }
-
/* For comparisons of pointers we can decompose it to a compile time
comparison of the base objects and the offsets into the object.
This requires at least one operand being an ADDR_EXPR or a
}
}
- /* A local variable can never be pointed to by
- the default SSA name of an incoming parameter. */
- if ((TREE_CODE (arg0) == ADDR_EXPR
- && indirect_base0
- && TREE_CODE (base0) == VAR_DECL
- && auto_var_in_fn_p (base0, current_function_decl)
- && !indirect_base1
- && TREE_CODE (base1) == SSA_NAME
- && SSA_NAME_IS_DEFAULT_DEF (base1)
- && TREE_CODE (SSA_NAME_VAR (base1)) == PARM_DECL)
- || (TREE_CODE (arg1) == ADDR_EXPR
- && indirect_base1
- && TREE_CODE (base1) == VAR_DECL
- && auto_var_in_fn_p (base1, current_function_decl)
- && !indirect_base0
- && TREE_CODE (base0) == SSA_NAME
- && SSA_NAME_IS_DEFAULT_DEF (base0)
- && TREE_CODE (SSA_NAME_VAR (base0)) == PARM_DECL))
- {
- if (code == NE_EXPR)
- return constant_boolean_node (1, type);
- else if (code == EQ_EXPR)
- return constant_boolean_node (0, type);
- }
/* If we have equivalent bases we might be able to simplify. */
- else if (indirect_base0 == indirect_base1
- && operand_equal_p (base0, base1, 0))
+ if (indirect_base0 == indirect_base1
+ && operand_equal_p (base0, base1, 0))
{
/* We can fold this expression to a constant if the non-constant
offset parts are equal. */
}
}
- /* Transform comparisons of the form X * C1 CMP 0 to X CMP 0 in the
- signed arithmetic case. That form is created by the compiler
- often enough for folding it to be of value. One example is in
- computing loop trip counts after Operator Strength Reduction. */
- if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (arg0))
- && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))
- && TREE_CODE (arg0) == MULT_EXPR
- && (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
- && !TREE_OVERFLOW (TREE_OPERAND (arg0, 1)))
- && integer_zerop (arg1))
- {
- tree const1 = TREE_OPERAND (arg0, 1);
- tree const2 = arg1; /* zero */
- tree variable1 = TREE_OPERAND (arg0, 0);
- enum tree_code cmp_code = code;
-
- /* Handle unfolded multiplication by zero. */
- if (integer_zerop (const1))
- return fold_build2_loc (loc, cmp_code, type, const1, const2);
-
- fold_overflow_warning (("assuming signed overflow does not occur when "
- "eliminating multiplication in comparison "
- "with zero"),
- WARN_STRICT_OVERFLOW_COMPARISON);
-
- /* If const1 is negative we swap the sense of the comparison. */
- if (tree_int_cst_sgn (const1) < 0)
- cmp_code = swap_tree_comparison (cmp_code);
-
- return fold_build2_loc (loc, cmp_code, type, variable1, const2);
- }
-
tem = maybe_canonicalize_comparison (loc, code, type, arg0, arg1);
if (tem)
return tem;
- if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
- {
- tree targ0 = strip_float_extensions (arg0);
- tree targ1 = strip_float_extensions (arg1);
- tree newtype = TREE_TYPE (targ0);
-
- if (TYPE_PRECISION (TREE_TYPE (targ1)) > TYPE_PRECISION (newtype))
- newtype = TREE_TYPE (targ1);
-
- /* Fold (double)float1 CMP (double)float2 into float1 CMP float2. */
- if (TYPE_PRECISION (newtype) < TYPE_PRECISION (TREE_TYPE (arg0)))
- return fold_build2_loc (loc, code, type,
- fold_convert_loc (loc, newtype, targ0),
- fold_convert_loc (loc, newtype, targ1));
-
- if (TREE_CODE (arg1) == REAL_CST)
- {
- REAL_VALUE_TYPE cst;
- cst = TREE_REAL_CST (arg1);
-
- /* IEEE doesn't distinguish +0 and -0 in comparisons. */
- /* a CMP (-0) -> a CMP 0 */
- if (REAL_VALUE_MINUS_ZERO (cst))
- return fold_build2_loc (loc, code, type, arg0,
- build_real (TREE_TYPE (arg1), dconst0));
-
- /* x != NaN is always true, other ops are always false. */
- if (REAL_VALUE_ISNAN (cst)
- && ! HONOR_SNANS (arg1))
- {
- tem = (code == NE_EXPR) ? integer_one_node : integer_zero_node;
- return omit_one_operand_loc (loc, type, tem, arg0);
- }
-
- /* Fold comparisons against infinity. */
- if (REAL_VALUE_ISINF (cst)
- && MODE_HAS_INFINITIES (TYPE_MODE (TREE_TYPE (arg1))))
- {
- tem = fold_inf_compare (loc, code, type, arg0, arg1);
- if (tem != NULL_TREE)
- return tem;
- }
- }
-
- /* If this is a comparison of a real constant with a PLUS_EXPR
- or a MINUS_EXPR of a real constant, we can convert it into a
- comparison with a revised real constant as long as no overflow
- occurs when unsafe_math_optimizations are enabled. */
- if (flag_unsafe_math_optimizations
- && TREE_CODE (arg1) == REAL_CST
- && (TREE_CODE (arg0) == PLUS_EXPR
- || TREE_CODE (arg0) == MINUS_EXPR)
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == REAL_CST
- && 0 != (tem = const_binop (TREE_CODE (arg0) == PLUS_EXPR
- ? MINUS_EXPR : PLUS_EXPR,
- arg1, TREE_OPERAND (arg0, 1)))
- && !TREE_OVERFLOW (tem))
- return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), tem);
-
- /* Likewise, we can simplify a comparison of a real constant with
- a MINUS_EXPR whose first operand is also a real constant, i.e.
- (c1 - x) < c2 becomes x > c1-c2. Reordering is allowed on
- floating-point types only if -fassociative-math is set. */
- if (flag_associative_math
- && TREE_CODE (arg1) == REAL_CST
- && TREE_CODE (arg0) == MINUS_EXPR
- && TREE_CODE (TREE_OPERAND (arg0, 0)) == REAL_CST
- && 0 != (tem = const_binop (MINUS_EXPR, TREE_OPERAND (arg0, 0),
- arg1))
- && !TREE_OVERFLOW (tem))
- return fold_build2_loc (loc, swap_tree_comparison (code), type,
- TREE_OPERAND (arg0, 1), tem);
-
- /* Fold comparisons against built-in math functions. */
- if (TREE_CODE (arg1) == REAL_CST
- && flag_unsafe_math_optimizations
- && ! flag_errno_math)
- {
- enum built_in_function fcode = builtin_mathfn_code (arg0);
-
- if (fcode != END_BUILTINS)
- {
- tem = fold_mathfn_compare (loc, fcode, code, type, arg0, arg1);
- if (tem != NULL_TREE)
- return tem;
- }
- }
- }
-
- if (TREE_CODE (TREE_TYPE (arg0)) == INTEGER_TYPE
- && CONVERT_EXPR_P (arg0))
- {
- /* If we are widening one operand of an integer comparison,
- see if the other operand is similarly being widened. Perhaps we
- can do the comparison in the narrower type. */
- tem = fold_widened_comparison (loc, code, type, arg0, arg1);
- if (tem)
- return tem;
-
- /* Or if we are changing signedness. */
- tem = fold_sign_changed_comparison (loc, code, type, arg0, arg1);
- if (tem)
- return tem;
- }
-
/* If this is comparing a constant with a MIN_EXPR or a MAX_EXPR of a
constant, we can simplify it. */
if (TREE_CODE (arg1) == INTEGER_CST
return tem;
}
- /* 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 (arg0))
- return constant_boolean_node (1, type);
- break;
-
- case GE_EXPR:
- case LE_EXPR:
- if (! FLOAT_TYPE_P (TREE_TYPE (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 (arg0))
- break;
- /* ... fall through ... */
- case GT_EXPR:
- case LT_EXPR:
- return constant_boolean_node (0, type);
- default:
- gcc_unreachable ();
- }
- }
-
/* If we are comparing an expression that just has comparisons
of two integer values, arithmetic expressions of those comparisons,
and constants, we can simplify it. There are only three cases
return tem;
}
- /* Fold ~X op ~Y as Y op X. */
- if (TREE_CODE (arg0) == BIT_NOT_EXPR
- && TREE_CODE (arg1) == BIT_NOT_EXPR)
- {
- tree cmp_type = TREE_TYPE (TREE_OPERAND (arg0, 0));
- return fold_build2_loc (loc, code, type,
- fold_convert_loc (loc, cmp_type,
- TREE_OPERAND (arg1, 0)),
- TREE_OPERAND (arg0, 0));
- }
-
- /* Fold ~X op C as X op' ~C, where op' is the swapped comparison. */
- if (TREE_CODE (arg0) == BIT_NOT_EXPR
- && (TREE_CODE (arg1) == INTEGER_CST || TREE_CODE (arg1) == VECTOR_CST))
- {
- tree cmp_type = TREE_TYPE (TREE_OPERAND (arg0, 0));
- return fold_build2_loc (loc, swap_tree_comparison (code), type,
- TREE_OPERAND (arg0, 0),
- fold_build1_loc (loc, BIT_NOT_EXPR, cmp_type,
- fold_convert_loc (loc, cmp_type, arg1)));
- }
-
return NULL_TREE;
}
}
-/* Subroutine of fold_binary. If P is the value of EXPR, computes
- power-of-two M and (arbitrary) N such that M divides (P-N). This condition
- guarantees that P and N have the same least significant log2(M) bits.
- N is not otherwise constrained. In particular, N is not normalized to
- 0 <= N < M as is common. In general, the precise value of P is unknown.
- M is chosen as large as possible such that constant N can be determined.
-
- Returns M and sets *RESIDUE to N.
-
- If ALLOW_FUNC_ALIGN is true, do take functions' DECL_ALIGN_UNIT into
- account. This is not always possible due to PR 35705.
- */
-
-static unsigned HOST_WIDE_INT
-get_pointer_modulus_and_residue (tree expr, unsigned HOST_WIDE_INT *residue,
- bool allow_func_align)
-{
- enum tree_code code;
-
- *residue = 0;
-
- code = TREE_CODE (expr);
- if (code == ADDR_EXPR)
- {
- unsigned int bitalign;
- get_object_alignment_1 (TREE_OPERAND (expr, 0), &bitalign, residue);
- *residue /= BITS_PER_UNIT;
- return bitalign / BITS_PER_UNIT;
- }
- else if (code == POINTER_PLUS_EXPR)
- {
- tree op0, op1;
- unsigned HOST_WIDE_INT modulus;
- enum tree_code inner_code;
-
- op0 = TREE_OPERAND (expr, 0);
- STRIP_NOPS (op0);
- modulus = get_pointer_modulus_and_residue (op0, residue,
- allow_func_align);
-
- op1 = TREE_OPERAND (expr, 1);
- STRIP_NOPS (op1);
- inner_code = TREE_CODE (op1);
- if (inner_code == INTEGER_CST)
- {
- *residue += TREE_INT_CST_LOW (op1);
- return modulus;
- }
- else if (inner_code == MULT_EXPR)
- {
- op1 = TREE_OPERAND (op1, 1);
- if (TREE_CODE (op1) == INTEGER_CST)
- {
- unsigned HOST_WIDE_INT align;
-
- /* Compute the greatest power-of-2 divisor of op1. */
- align = TREE_INT_CST_LOW (op1);
- align &= -align;
-
- /* If align is non-zero and less than *modulus, replace
- *modulus with align., If align is 0, then either op1 is 0
- or the greatest power-of-2 divisor of op1 doesn't fit in an
- unsigned HOST_WIDE_INT. In either case, no additional
- constraint is imposed. */
- if (align)
- modulus = MIN (modulus, align);
-
- return modulus;
- }
- }
- }
-
- /* If we get here, we were unable to determine anything useful about the
- expression. */
- return 1;
-}
-
/* Helper function for fold_vec_perm. Store elements of VECTOR_CST or
CONSTRUCTOR ARG into array ELTS and return true if successful. */
if (! FLOAT_TYPE_P (type))
{
- /* If we are adding two BIT_AND_EXPR's, both of which are and'ing
- with a constant, and the two constants have no bits in common,
- we should treat this as a BIT_IOR_EXPR since this may produce more
- simplifications. */
- if (TREE_CODE (arg0) == BIT_AND_EXPR
- && TREE_CODE (arg1) == BIT_AND_EXPR
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
- && TREE_CODE (TREE_OPERAND (arg1, 1)) == INTEGER_CST
- && wi::bit_and (TREE_OPERAND (arg0, 1),
- TREE_OPERAND (arg1, 1)) == 0)
- {
- code = BIT_IOR_EXPR;
- goto bit_ior;
- }
-
/* Reassociate (plus (plus (mult) (foo)) (mult)) as
(plus (plus (mult) (mult)) (foo)) so that we can
take advantage of the factoring cases below. */
if (! FLOAT_TYPE_P (type))
{
- /* Fold A - (A & B) into ~B & A. */
- if (!TREE_SIDE_EFFECTS (arg0)
- && TREE_CODE (arg1) == BIT_AND_EXPR)
- {
- if (operand_equal_p (arg0, TREE_OPERAND (arg1, 1), 0))
- {
- tree arg10 = fold_convert_loc (loc, type,
- TREE_OPERAND (arg1, 0));
- return fold_build2_loc (loc, BIT_AND_EXPR, type,
- fold_build1_loc (loc, BIT_NOT_EXPR,
- type, arg10),
- fold_convert_loc (loc, type, arg0));
- }
- if (operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
- {
- tree arg11 = fold_convert_loc (loc,
- type, TREE_OPERAND (arg1, 1));
- return fold_build2_loc (loc, BIT_AND_EXPR, type,
- fold_build1_loc (loc, BIT_NOT_EXPR,
- type, arg11),
- fold_convert_loc (loc, type, arg0));
- }
- }
-
/* Fold (A & ~B) - (A & B) into (A ^ B) - B, where B is
any power of 2 minus 1. */
if (TREE_CODE (arg0) == BIT_AND_EXPR
goto associate;
case BIT_IOR_EXPR:
- bit_ior:
/* Canonicalize (X & C1) | C2. */
if (TREE_CODE (arg0) == BIT_AND_EXPR
&& TREE_CODE (arg1) == INTEGER_CST
return fold_build2_loc (loc, BIT_XOR_EXPR, type, l0, n1);
}
- t1 = distribute_bit_expr (loc, code, type, arg0, arg1);
- if (t1 != NULL_TREE)
- return t1;
-
- /* Convert (or (not arg0) (not arg1)) to (not (and (arg0) (arg1))).
-
- This results in more efficient code for machines without a NAND
- instruction. Combine will canonicalize to the first form
- which will allow use of NAND instructions provided by the
- backend if they exist. */
- if (TREE_CODE (arg0) == BIT_NOT_EXPR
- && TREE_CODE (arg1) == BIT_NOT_EXPR)
- {
- return
- fold_build1_loc (loc, BIT_NOT_EXPR, type,
- build2 (BIT_AND_EXPR, type,
- fold_convert_loc (loc, type,
- TREE_OPERAND (arg0, 0)),
- fold_convert_loc (loc, type,
- TREE_OPERAND (arg1, 0))));
- }
-
/* See if this can be simplified into a rotate first. If that
is unsuccessful continue in the association code. */
goto bit_rotate;
case BIT_XOR_EXPR:
- /* ~X ^ X is -1. */
- if (TREE_CODE (arg0) == BIT_NOT_EXPR
- && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
- {
- t1 = build_zero_cst (type);
- t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
- return omit_one_operand_loc (loc, type, t1, arg1);
- }
-
- /* X ^ ~X is -1. */
- if (TREE_CODE (arg1) == BIT_NOT_EXPR
- && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
- {
- t1 = build_zero_cst (type);
- t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
- return omit_one_operand_loc (loc, type, t1, arg0);
- }
-
- /* If we are XORing two BIT_AND_EXPR's, both of which are and'ing
- with a constant, and the two constants have no bits in common,
- we should treat this as a BIT_IOR_EXPR since this may produce more
- simplifications. */
- if (TREE_CODE (arg0) == BIT_AND_EXPR
- && TREE_CODE (arg1) == BIT_AND_EXPR
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
- && TREE_CODE (TREE_OPERAND (arg1, 1)) == INTEGER_CST
- && wi::bit_and (TREE_OPERAND (arg0, 1),
- TREE_OPERAND (arg1, 1)) == 0)
- {
- code = BIT_IOR_EXPR;
- goto bit_ior;
- }
-
- /* (X | Y) ^ X -> Y & ~ X*/
- if (TREE_CODE (arg0) == BIT_IOR_EXPR
- && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
- {
- tree t2 = TREE_OPERAND (arg0, 1);
- t1 = fold_build1_loc (loc, BIT_NOT_EXPR, TREE_TYPE (arg1),
- arg1);
- t1 = fold_build2_loc (loc, BIT_AND_EXPR, type,
- fold_convert_loc (loc, type, t2),
- fold_convert_loc (loc, type, t1));
- return t1;
- }
-
- /* (Y | X) ^ X -> Y & ~ X*/
- if (TREE_CODE (arg0) == BIT_IOR_EXPR
- && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
- {
- tree t2 = TREE_OPERAND (arg0, 0);
- t1 = fold_build1_loc (loc, BIT_NOT_EXPR, TREE_TYPE (arg1),
- arg1);
- t1 = fold_build2_loc (loc, BIT_AND_EXPR, type,
- fold_convert_loc (loc, type, t2),
- fold_convert_loc (loc, type, t1));
- return t1;
- }
-
- /* X ^ (X | Y) -> Y & ~ X*/
- if (TREE_CODE (arg1) == BIT_IOR_EXPR
- && operand_equal_p (TREE_OPERAND (arg1, 0), arg0, 0))
- {
- tree t2 = TREE_OPERAND (arg1, 1);
- t1 = fold_build1_loc (loc, BIT_NOT_EXPR, TREE_TYPE (arg0),
- arg0);
- t1 = fold_build2_loc (loc, BIT_AND_EXPR, type,
- fold_convert_loc (loc, type, t2),
- fold_convert_loc (loc, type, t1));
- return t1;
- }
-
- /* X ^ (Y | X) -> Y & ~ X*/
- if (TREE_CODE (arg1) == BIT_IOR_EXPR
- && operand_equal_p (TREE_OPERAND (arg1, 1), arg0, 0))
- {
- tree t2 = TREE_OPERAND (arg1, 0);
- t1 = fold_build1_loc (loc, BIT_NOT_EXPR, TREE_TYPE (arg0),
- arg0);
- t1 = fold_build2_loc (loc, BIT_AND_EXPR, type,
- fold_convert_loc (loc, type, t2),
- fold_convert_loc (loc, type, t1));
- return t1;
- }
-
- /* Convert ~X ^ ~Y to X ^ Y. */
- if (TREE_CODE (arg0) == BIT_NOT_EXPR
- && TREE_CODE (arg1) == BIT_NOT_EXPR)
- return fold_build2_loc (loc, code, type,
- fold_convert_loc (loc, type,
- TREE_OPERAND (arg0, 0)),
- fold_convert_loc (loc, type,
- TREE_OPERAND (arg1, 0)));
-
- /* Convert ~X ^ C to X ^ ~C. */
- if (TREE_CODE (arg0) == BIT_NOT_EXPR
- && TREE_CODE (arg1) == INTEGER_CST)
- return fold_build2_loc (loc, code, type,
- fold_convert_loc (loc, type,
- TREE_OPERAND (arg0, 0)),
- fold_build1_loc (loc, BIT_NOT_EXPR, type, arg1));
-
/* Fold (X & 1) ^ 1 as (X & 1) == 0. */
if (TREE_CODE (arg0) == BIT_AND_EXPR
&& INTEGRAL_TYPE_P (type)
return fold_build2_loc (loc, EQ_EXPR, type, arg0,
build_zero_cst (TREE_TYPE (arg0)));
- /* Fold (X & Y) ^ Y as ~X & Y. */
- if (TREE_CODE (arg0) == BIT_AND_EXPR
- && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
- {
- tem = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
- return fold_build2_loc (loc, BIT_AND_EXPR, type,
- fold_build1_loc (loc, BIT_NOT_EXPR, type, tem),
- fold_convert_loc (loc, type, arg1));
- }
- /* Fold (X & Y) ^ X as ~Y & X. */
- if (TREE_CODE (arg0) == BIT_AND_EXPR
- && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
- && reorder_operands_p (TREE_OPERAND (arg0, 1), arg1))
- {
- tem = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
- return fold_build2_loc (loc, BIT_AND_EXPR, type,
- fold_build1_loc (loc, BIT_NOT_EXPR, type, tem),
- fold_convert_loc (loc, type, arg1));
- }
- /* Fold X ^ (X & Y) as X & ~Y. */
- if (TREE_CODE (arg1) == BIT_AND_EXPR
- && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
- {
- tem = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 1));
- return fold_build2_loc (loc, BIT_AND_EXPR, type,
- fold_convert_loc (loc, type, arg0),
- fold_build1_loc (loc, BIT_NOT_EXPR, type, tem));
- }
- /* Fold X ^ (Y & X) as ~Y & X. */
- if (TREE_CODE (arg1) == BIT_AND_EXPR
- && operand_equal_p (arg0, TREE_OPERAND (arg1, 1), 0)
- && reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
- {
- tem = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 0));
- return fold_build2_loc (loc, BIT_AND_EXPR, type,
- fold_build1_loc (loc, BIT_NOT_EXPR, type, tem),
- fold_convert_loc (loc, type, arg0));
- }
-
/* See if this can be simplified into a rotate first. If that
is unsuccessful continue in the association code. */
goto bit_rotate;
}
}
- t1 = distribute_bit_expr (loc, code, type, arg0, arg1);
- if (t1 != NULL_TREE)
- return t1;
/* Simplify ((int)c & 0377) into (int)c, if c is unsigned char. */
if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg0) == NOP_EXPR
&& TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
}
- /* Convert (and (not arg0) (not arg1)) to (not (or (arg0) (arg1))).
-
- This results in more efficient code for machines without a NOR
- instruction. Combine will canonicalize to the first form
- which will allow use of NOR instructions provided by the
- backend if they exist. */
- if (TREE_CODE (arg0) == BIT_NOT_EXPR
- && TREE_CODE (arg1) == BIT_NOT_EXPR)
- {
- return fold_build1_loc (loc, BIT_NOT_EXPR, type,
- build2 (BIT_IOR_EXPR, type,
- fold_convert_loc (loc, type,
- TREE_OPERAND (arg0, 0)),
- fold_convert_loc (loc, type,
- TREE_OPERAND (arg1, 0))));
- }
-
- /* If arg0 is derived from the address of an object or function, we may
- be able to fold this expression using the object or function's
- alignment. */
- if (POINTER_TYPE_P (TREE_TYPE (arg0)) && tree_fits_uhwi_p (arg1))
- {
- unsigned HOST_WIDE_INT modulus, residue;
- unsigned HOST_WIDE_INT low = tree_to_uhwi (arg1);
-
- modulus = get_pointer_modulus_and_residue (arg0, &residue,
- integer_onep (arg1));
-
- /* This works because modulus is a power of 2. If this weren't the
- case, we'd have to replace it by its greatest power-of-2
- divisor: modulus & -modulus. */
- if (low < modulus)
- return build_int_cst (type, residue & low);
- }
-
goto associate;
case RDIV_EXPR:
prec = element_precision (type);
- /* Turn (a OP c1) OP c2 into a OP (c1+c2). */
- if (TREE_CODE (op0) == code && tree_fits_uhwi_p (arg1)
- && tree_to_uhwi (arg1) < prec
- && tree_fits_uhwi_p (TREE_OPERAND (arg0, 1))
- && tree_to_uhwi (TREE_OPERAND (arg0, 1)) < prec)
- {
- unsigned int low = (tree_to_uhwi (TREE_OPERAND (arg0, 1))
- + tree_to_uhwi (arg1));
-
- /* Deal with a OP (c1 + c2) being undefined but (a OP c1) OP c2
- being well defined. */
- if (low >= prec)
- {
- if (code == LROTATE_EXPR || code == RROTATE_EXPR)
- low = low % prec;
- else if (TYPE_UNSIGNED (type) || code == LSHIFT_EXPR)
- return omit_one_operand_loc (loc, type, build_zero_cst (type),
- TREE_OPERAND (arg0, 0));
- else
- low = prec - 1;
- }
-
- return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0),
- build_int_cst (TREE_TYPE (arg1), low));
- }
-
/* Transform (x >> c) << c into x & (-1<<c), or transform (x << c) >> c
into x & ((unsigned)-1 >> c) for unsigned types. */
if (((code == LSHIFT_EXPR && TREE_CODE (arg0) == RSHIFT_EXPR)
prec) == 0)
return TREE_OPERAND (arg0, 0);
- /* Fold (X & C2) << C1 into (X << C1) & (C2 << C1)
- (X & C2) >> C1 into (X >> C1) & (C2 >> C1)
- if the latter can be further optimized. */
- if ((code == LSHIFT_EXPR || code == RSHIFT_EXPR)
- && TREE_CODE (arg0) == BIT_AND_EXPR
- && TREE_CODE (arg1) == INTEGER_CST
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
- {
- tree mask = fold_build2_loc (loc, code, type,
- fold_convert_loc (loc, type,
- TREE_OPERAND (arg0, 1)),
- arg1);
- tree shift = fold_build2_loc (loc, code, type,
- fold_convert_loc (loc, type,
- TREE_OPERAND (arg0, 0)),
- arg1);
- tem = fold_binary_loc (loc, BIT_AND_EXPR, type, shift, mask);
- if (tem)
- return tem;
- }
-
return NULL_TREE;
case MIN_EXPR:
if (tem != NULL_TREE)
return tem;
- /* bool_var != 0 becomes bool_var. */
- if (TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE && integer_zerop (arg1)
- && code == NE_EXPR)
- return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
-
- /* bool_var == 1 becomes bool_var. */
- if (TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE && integer_onep (arg1)
- && code == EQ_EXPR)
- return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
-
/* bool_var != 1 becomes !bool_var. */
if (TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE && integer_onep (arg1)
&& code == NE_EXPR)
&& code == NE_EXPR)
return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
- /* If this is an equality comparison of the address of two non-weak,
- unaliased symbols neither of which are extern (since we do not
- have access to attributes for externs), then we know the result. */
- if (TREE_CODE (arg0) == ADDR_EXPR
- && DECL_P (TREE_OPERAND (arg0, 0))
- && TREE_CODE (arg1) == ADDR_EXPR
- && DECL_P (TREE_OPERAND (arg1, 0)))
- {
- int equal;
-
- if (decl_in_symtab_p (TREE_OPERAND (arg0, 0))
- && decl_in_symtab_p (TREE_OPERAND (arg1, 0)))
- equal = symtab_node::get_create (TREE_OPERAND (arg0, 0))
- ->equal_address_to (symtab_node::get_create
- (TREE_OPERAND (arg1, 0)));
- else
- equal = TREE_OPERAND (arg0, 0) == TREE_OPERAND (arg1, 0);
- if (equal != 2)
- return constant_boolean_node (equal
- ? code == EQ_EXPR : code != EQ_EXPR,
- type);
- }
-
/* Similarly for a BIT_XOR_EXPR; X ^ C1 == C2 is X == (C1 ^ C2). */
if (TREE_CODE (arg0) == BIT_XOR_EXPR
&& TREE_CODE (arg1) == INTEGER_CST