aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKazu Hirata <kazu@cs.umass.edu>2005-03-06 00:42:56 +0000
committerKazu Hirata <kazu@gcc.gnu.org>2005-03-06 00:42:56 +0000
commit75505450f647279fc6fecc603cedf6702c871dc2 (patch)
tree5f344e5535af0e66a0d00c8427062bf3e9c63dbe
parent5c2ff394f325de79c7b73a4502a8239077c64e0e (diff)
downloadgcc-75505450f647279fc6fecc603cedf6702c871dc2.zip
gcc-75505450f647279fc6fecc603cedf6702c871dc2.tar.gz
gcc-75505450f647279fc6fecc603cedf6702c871dc2.tar.bz2
* fold-const.c (fold): Remove handling of binary expressions.
From-SVN: r95961
-rw-r--r--gcc/ChangeLog2
-rw-r--r--gcc/fold-const.c2598
2 files changed, 2 insertions, 2598 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3224ef2..e6c7fa8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -6,6 +6,8 @@
(NON_TYPE_CHECK): Use TYPE_P instead of
IS_NON_TYPE_CODE_CLASS.
+ * fold-const.c (fold): Remove handling of binary expressions.
+
2005-03-05 James A. Morrison <phython@gcc.gnu.org>
* doc/c-tree.texi: Wrap comments in @r{}.
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 22e2ecd..04f56eb 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -9873,17 +9873,9 @@ tree
fold (tree expr)
{
const tree t = expr;
- const tree type = TREE_TYPE (expr);
- tree t1 = NULL_TREE;
- tree tem;
- tree arg0 = NULL_TREE, arg1 = NULL_TREE;
enum tree_code code = TREE_CODE (t);
enum tree_code_class kind = TREE_CODE_CLASS (code);
- /* WINS will be nonzero when the switch is done
- if all operands are constant. */
- int wins = 1;
-
/* Return right away if a constant. */
if (kind == tcc_constant)
return t;
@@ -9903,2601 +9895,11 @@ fold (tree expr)
}
}
- if (IS_EXPR_CODE_CLASS (kind))
- {
- int len = TREE_CODE_LENGTH (code);
- int i;
- for (i = 0; i < len; i++)
- {
- tree op = TREE_OPERAND (t, i);
- tree subop;
-
- if (op == 0)
- continue; /* Valid for CALL_EXPR, at least. */
-
- /* Strip any conversions that don't change the mode. This is
- safe for every expression, except for a comparison expression
- because its signedness is derived from its operands. So, in
- the latter case, only strip conversions that don't change the
- signedness.
-
- Note that this is done as an internal manipulation within the
- constant folder, in order to find the simplest representation
- of the arguments so that their form can be studied. In any
- cases, the appropriate type conversions should be put back in
- the tree that will get out of the constant folder. */
- if (kind == tcc_comparison)
- STRIP_SIGN_NOPS (op);
- else
- STRIP_NOPS (op);
-
- if (TREE_CODE (op) == COMPLEX_CST)
- subop = TREE_REALPART (op);
- else
- subop = op;
-
- if (TREE_CODE (subop) != INTEGER_CST
- && TREE_CODE (subop) != REAL_CST)
- /* Note that TREE_CONSTANT isn't enough:
- static var addresses are constant but we can't
- do arithmetic on them. */
- wins = 0;
-
- if (i == 0)
- arg0 = op;
- else if (i == 1)
- arg1 = op;
- }
- }
-
- /* If this is a commutative operation, and ARG0 is a constant, move it
- to ARG1 to reduce the number of tests below. */
- if (commutative_tree_code (code)
- && tree_swap_operands_p (arg0, arg1, true))
- return fold (build2 (code, type, TREE_OPERAND (t, 1),
- TREE_OPERAND (t, 0)));
-
- /* Now WINS is set as described above,
- ARG0 is the first operand of EXPR,
- and ARG1 is the second operand (if it has more than one operand).
-
- First check for cases where an arithmetic operation is applied to a
- compound, conditional, or comparison operation. Push the arithmetic
- operation inside the compound or conditional to see if any folding
- can then be done. Convert comparison to conditional for this purpose.
- The also optimizes non-constant cases that used to be done in
- expand_expr.
-
- Before we do that, see if this is a BIT_AND_EXPR or a BIT_IOR_EXPR,
- one of the operands is a comparison and the other is a comparison, a
- BIT_AND_EXPR with the constant 1, or a truth value. In that case, the
- code below would make the expression more complex. Change it to a
- TRUTH_{AND,OR}_EXPR. Likewise, convert a similar NE_EXPR to
- TRUTH_XOR_EXPR and an EQ_EXPR to the inversion of a TRUTH_XOR_EXPR. */
-
- if ((code == BIT_AND_EXPR || code == BIT_IOR_EXPR
- || code == EQ_EXPR || code == NE_EXPR)
- && ((truth_value_p (TREE_CODE (arg0))
- && (truth_value_p (TREE_CODE (arg1))
- || (TREE_CODE (arg1) == BIT_AND_EXPR
- && integer_onep (TREE_OPERAND (arg1, 1)))))
- || (truth_value_p (TREE_CODE (arg1))
- && (truth_value_p (TREE_CODE (arg0))
- || (TREE_CODE (arg0) == BIT_AND_EXPR
- && integer_onep (TREE_OPERAND (arg0, 1)))))))
- {
- tem = fold (build2 (code == BIT_AND_EXPR ? TRUTH_AND_EXPR
- : code == BIT_IOR_EXPR ? TRUTH_OR_EXPR
- : TRUTH_XOR_EXPR,
- type, fold_convert (boolean_type_node, arg0),
- fold_convert (boolean_type_node, arg1)));
-
- if (code == EQ_EXPR)
- tem = invert_truthvalue (tem);
-
- return tem;
- }
-
- if (TREE_CODE_CLASS (code) == tcc_comparison
- && TREE_CODE (arg0) == COMPOUND_EXPR)
- return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
- fold (build2 (code, type, TREE_OPERAND (arg0, 1), arg1)));
- else if (TREE_CODE_CLASS (code) == tcc_comparison
- && TREE_CODE (arg1) == COMPOUND_EXPR)
- return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
- fold (build2 (code, type, arg0, TREE_OPERAND (arg1, 1))));
- else if (TREE_CODE_CLASS (code) == tcc_binary
- || TREE_CODE_CLASS (code) == tcc_comparison)
- {
- if (TREE_CODE (arg0) == COMPOUND_EXPR)
- return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
- fold (build2 (code, type, TREE_OPERAND (arg0, 1),
- arg1)));
- if (TREE_CODE (arg1) == COMPOUND_EXPR
- && reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
- return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
- fold (build2 (code, type,
- arg0, TREE_OPERAND (arg1, 1))));
-
- if (TREE_CODE (arg0) == COND_EXPR || COMPARISON_CLASS_P (arg0))
- {
- tem = fold_binary_op_with_conditional_arg (t, code, arg0, arg1,
- /*cond_first_p=*/1);
- if (tem != NULL_TREE)
- return tem;
- }
-
- if (TREE_CODE (arg1) == COND_EXPR || COMPARISON_CLASS_P (arg1))
- {
- tem = fold_binary_op_with_conditional_arg (t, code, arg1, arg0,
- /*cond_first_p=*/0);
- if (tem != NULL_TREE)
- return tem;
- }
- }
-
switch (code)
{
case CONST_DECL:
return fold (DECL_INITIAL (t));
- case RANGE_EXPR:
- if (TREE_CONSTANT (t) != wins)
- {
- tem = copy_node (t);
- TREE_CONSTANT (tem) = wins;
- TREE_INVARIANT (tem) = wins;
- return tem;
- }
- return t;
-
- case PLUS_EXPR:
- /* A + (-B) -> A - B */
- if (TREE_CODE (arg1) == NEGATE_EXPR)
- return fold (build2 (MINUS_EXPR, type, arg0, TREE_OPERAND (arg1, 0)));
- /* (-A) + B -> B - A */
- if (TREE_CODE (arg0) == NEGATE_EXPR
- && reorder_operands_p (TREE_OPERAND (arg0, 0), arg1))
- return fold (build2 (MINUS_EXPR, type, arg1, TREE_OPERAND (arg0, 0)));
-
- if (TREE_CODE (type) == COMPLEX_TYPE)
- {
- tem = fold_complex_add (type, arg0, arg1, PLUS_EXPR);
- if (tem)
- return tem;
- }
-
- if (! FLOAT_TYPE_P (type))
- {
- if (integer_zerop (arg1))
- return non_lvalue (fold_convert (type, arg0));
-
- /* 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
- && integer_zerop (const_binop (BIT_AND_EXPR,
- 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 (((TREE_CODE (arg0) == PLUS_EXPR
- || TREE_CODE (arg0) == MINUS_EXPR)
- && TREE_CODE (arg1) == MULT_EXPR)
- || ((TREE_CODE (arg1) == PLUS_EXPR
- || TREE_CODE (arg1) == MINUS_EXPR)
- && TREE_CODE (arg0) == MULT_EXPR))
- {
- tree parg0, parg1, parg, marg;
- enum tree_code pcode;
-
- if (TREE_CODE (arg1) == MULT_EXPR)
- parg = arg0, marg = arg1;
- else
- parg = arg1, marg = arg0;
- pcode = TREE_CODE (parg);
- parg0 = TREE_OPERAND (parg, 0);
- parg1 = TREE_OPERAND (parg, 1);
- STRIP_NOPS (parg0);
- STRIP_NOPS (parg1);
-
- if (TREE_CODE (parg0) == MULT_EXPR
- && TREE_CODE (parg1) != MULT_EXPR)
- return fold (build2 (pcode, type,
- fold (build2 (PLUS_EXPR, type,
- fold_convert (type, parg0),
- fold_convert (type, marg))),
- fold_convert (type, parg1)));
- if (TREE_CODE (parg0) != MULT_EXPR
- && TREE_CODE (parg1) == MULT_EXPR)
- return fold (build2 (PLUS_EXPR, type,
- fold_convert (type, parg0),
- fold (build2 (pcode, type,
- fold_convert (type, marg),
- fold_convert (type,
- parg1)))));
- }
-
- if (TREE_CODE (arg0) == MULT_EXPR && TREE_CODE (arg1) == MULT_EXPR)
- {
- tree arg00, arg01, arg10, arg11;
- tree alt0 = NULL_TREE, alt1 = NULL_TREE, same;
-
- /* (A * C) + (B * C) -> (A+B) * C.
- We are most concerned about the case where C is a constant,
- but other combinations show up during loop reduction. Since
- it is not difficult, try all four possibilities. */
-
- arg00 = TREE_OPERAND (arg0, 0);
- arg01 = TREE_OPERAND (arg0, 1);
- arg10 = TREE_OPERAND (arg1, 0);
- arg11 = TREE_OPERAND (arg1, 1);
- same = NULL_TREE;
-
- if (operand_equal_p (arg01, arg11, 0))
- same = arg01, alt0 = arg00, alt1 = arg10;
- else if (operand_equal_p (arg00, arg10, 0))
- same = arg00, alt0 = arg01, alt1 = arg11;
- else if (operand_equal_p (arg00, arg11, 0))
- same = arg00, alt0 = arg01, alt1 = arg10;
- else if (operand_equal_p (arg01, arg10, 0))
- same = arg01, alt0 = arg00, alt1 = arg11;
-
- /* No identical multiplicands; see if we can find a common
- power-of-two factor in non-power-of-two multiplies. This
- can help in multi-dimensional array access. */
- else if (TREE_CODE (arg01) == INTEGER_CST
- && TREE_CODE (arg11) == INTEGER_CST
- && TREE_INT_CST_HIGH (arg01) == 0
- && TREE_INT_CST_HIGH (arg11) == 0)
- {
- HOST_WIDE_INT int01, int11, tmp;
- int01 = TREE_INT_CST_LOW (arg01);
- int11 = TREE_INT_CST_LOW (arg11);
-
- /* Move min of absolute values to int11. */
- if ((int01 >= 0 ? int01 : -int01)
- < (int11 >= 0 ? int11 : -int11))
- {
- tmp = int01, int01 = int11, int11 = tmp;
- alt0 = arg00, arg00 = arg10, arg10 = alt0;
- alt0 = arg01, arg01 = arg11, arg11 = alt0;
- }
-
- if (exact_log2 (int11) > 0 && int01 % int11 == 0)
- {
- alt0 = fold (build2 (MULT_EXPR, type, arg00,
- build_int_cst (NULL_TREE,
- int01 / int11)));
- alt1 = arg10;
- same = arg11;
- }
- }
-
- if (same)
- return fold (build2 (MULT_EXPR, type,
- fold (build2 (PLUS_EXPR, type,
- fold_convert (type, alt0),
- fold_convert (type, alt1))),
- same));
- }
-
- /* Try replacing &a[i1] + c * i2 with &a[i1 + i2], if c is step
- of the array. Loop optimizer sometimes produce this type of
- expressions. */
- if (TREE_CODE (arg0) == ADDR_EXPR
- && TREE_CODE (arg1) == MULT_EXPR)
- {
- tem = try_move_mult_to_index (PLUS_EXPR, arg0, arg1);
- if (tem)
- return fold_convert (type, fold (tem));
- }
- else if (TREE_CODE (arg1) == ADDR_EXPR
- && TREE_CODE (arg0) == MULT_EXPR)
- {
- tem = try_move_mult_to_index (PLUS_EXPR, arg1, arg0);
- if (tem)
- return fold_convert (type, fold (tem));
- }
- }
- else
- {
- /* See if ARG1 is zero and X + ARG1 reduces to X. */
- if (fold_real_zero_addition_p (TREE_TYPE (arg0), arg1, 0))
- return non_lvalue (fold_convert (type, arg0));
-
- /* Likewise if the operands are reversed. */
- if (fold_real_zero_addition_p (TREE_TYPE (arg1), arg0, 0))
- return non_lvalue (fold_convert (type, arg1));
-
- /* Convert X + -C into X - C. */
- if (TREE_CODE (arg1) == REAL_CST
- && REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg1)))
- {
- tem = fold_negate_const (arg1, type);
- if (!TREE_OVERFLOW (arg1) || !flag_trapping_math)
- return fold (build2 (MINUS_EXPR, type,
- fold_convert (type, arg0),
- fold_convert (type, tem)));
- }
-
- /* Convert x+x into x*2.0. */
- if (operand_equal_p (arg0, arg1, 0)
- && SCALAR_FLOAT_TYPE_P (type))
- return fold (build2 (MULT_EXPR, type, arg0,
- build_real (type, dconst2)));
-
- /* Convert x*c+x into x*(c+1). */
- if (flag_unsafe_math_optimizations
- && TREE_CODE (arg0) == MULT_EXPR
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == REAL_CST
- && ! TREE_CONSTANT_OVERFLOW (TREE_OPERAND (arg0, 1))
- && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
- {
- REAL_VALUE_TYPE c;
-
- c = TREE_REAL_CST (TREE_OPERAND (arg0, 1));
- real_arithmetic (&c, PLUS_EXPR, &c, &dconst1);
- return fold (build2 (MULT_EXPR, type, arg1,
- build_real (type, c)));
- }
-
- /* Convert x+x*c into x*(c+1). */
- if (flag_unsafe_math_optimizations
- && TREE_CODE (arg1) == MULT_EXPR
- && TREE_CODE (TREE_OPERAND (arg1, 1)) == REAL_CST
- && ! TREE_CONSTANT_OVERFLOW (TREE_OPERAND (arg1, 1))
- && operand_equal_p (TREE_OPERAND (arg1, 0), arg0, 0))
- {
- REAL_VALUE_TYPE c;
-
- c = TREE_REAL_CST (TREE_OPERAND (arg1, 1));
- real_arithmetic (&c, PLUS_EXPR, &c, &dconst1);
- return fold (build2 (MULT_EXPR, type, arg0,
- build_real (type, c)));
- }
-
- /* Convert x*c1+x*c2 into x*(c1+c2). */
- if (flag_unsafe_math_optimizations
- && TREE_CODE (arg0) == MULT_EXPR
- && TREE_CODE (arg1) == MULT_EXPR
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == REAL_CST
- && ! TREE_CONSTANT_OVERFLOW (TREE_OPERAND (arg0, 1))
- && TREE_CODE (TREE_OPERAND (arg1, 1)) == REAL_CST
- && ! TREE_CONSTANT_OVERFLOW (TREE_OPERAND (arg1, 1))
- && operand_equal_p (TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg1, 0), 0))
- {
- REAL_VALUE_TYPE c1, c2;
-
- c1 = TREE_REAL_CST (TREE_OPERAND (arg0, 1));
- c2 = TREE_REAL_CST (TREE_OPERAND (arg1, 1));
- real_arithmetic (&c1, PLUS_EXPR, &c1, &c2);
- return fold (build2 (MULT_EXPR, type,
- TREE_OPERAND (arg0, 0),
- build_real (type, c1)));
- }
- /* Convert a + (b*c + d*e) into (a + b*c) + d*e. */
- if (flag_unsafe_math_optimizations
- && TREE_CODE (arg1) == PLUS_EXPR
- && TREE_CODE (arg0) != MULT_EXPR)
- {
- tree tree10 = TREE_OPERAND (arg1, 0);
- tree tree11 = TREE_OPERAND (arg1, 1);
- if (TREE_CODE (tree11) == MULT_EXPR
- && TREE_CODE (tree10) == MULT_EXPR)
- {
- tree tree0;
- tree0 = fold (build2 (PLUS_EXPR, type, arg0, tree10));
- return fold (build2 (PLUS_EXPR, type, tree0, tree11));
- }
- }
- /* Convert (b*c + d*e) + a into b*c + (d*e +a). */
- if (flag_unsafe_math_optimizations
- && TREE_CODE (arg0) == PLUS_EXPR
- && TREE_CODE (arg1) != MULT_EXPR)
- {
- tree tree00 = TREE_OPERAND (arg0, 0);
- tree tree01 = TREE_OPERAND (arg0, 1);
- if (TREE_CODE (tree01) == MULT_EXPR
- && TREE_CODE (tree00) == MULT_EXPR)
- {
- tree tree0;
- tree0 = fold (build2 (PLUS_EXPR, type, tree01, arg1));
- return fold (build2 (PLUS_EXPR, type, tree00, tree0));
- }
- }
- }
-
- bit_rotate:
- /* (A << C1) + (A >> C2) if A is unsigned and C1+C2 is the size of A
- is a rotate of A by C1 bits. */
- /* (A << B) + (A >> (Z - B)) if A is unsigned and Z is the size of A
- is a rotate of A by B bits. */
- {
- enum tree_code code0, code1;
- code0 = TREE_CODE (arg0);
- code1 = TREE_CODE (arg1);
- if (((code0 == RSHIFT_EXPR && code1 == LSHIFT_EXPR)
- || (code1 == RSHIFT_EXPR && code0 == LSHIFT_EXPR))
- && operand_equal_p (TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg1, 0), 0)
- && TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
- {
- tree tree01, tree11;
- enum tree_code code01, code11;
-
- tree01 = TREE_OPERAND (arg0, 1);
- tree11 = TREE_OPERAND (arg1, 1);
- STRIP_NOPS (tree01);
- STRIP_NOPS (tree11);
- code01 = TREE_CODE (tree01);
- code11 = TREE_CODE (tree11);
- if (code01 == INTEGER_CST
- && code11 == INTEGER_CST
- && TREE_INT_CST_HIGH (tree01) == 0
- && TREE_INT_CST_HIGH (tree11) == 0
- && ((TREE_INT_CST_LOW (tree01) + TREE_INT_CST_LOW (tree11))
- == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))))
- return build2 (LROTATE_EXPR, type, TREE_OPERAND (arg0, 0),
- code0 == LSHIFT_EXPR ? tree01 : tree11);
- else if (code11 == MINUS_EXPR)
- {
- tree tree110, tree111;
- tree110 = TREE_OPERAND (tree11, 0);
- tree111 = TREE_OPERAND (tree11, 1);
- STRIP_NOPS (tree110);
- STRIP_NOPS (tree111);
- if (TREE_CODE (tree110) == INTEGER_CST
- && 0 == compare_tree_int (tree110,
- TYPE_PRECISION
- (TREE_TYPE (TREE_OPERAND
- (arg0, 0))))
- && operand_equal_p (tree01, tree111, 0))
- return build2 ((code0 == LSHIFT_EXPR
- ? LROTATE_EXPR
- : RROTATE_EXPR),
- type, TREE_OPERAND (arg0, 0), tree01);
- }
- else if (code01 == MINUS_EXPR)
- {
- tree tree010, tree011;
- tree010 = TREE_OPERAND (tree01, 0);
- tree011 = TREE_OPERAND (tree01, 1);
- STRIP_NOPS (tree010);
- STRIP_NOPS (tree011);
- if (TREE_CODE (tree010) == INTEGER_CST
- && 0 == compare_tree_int (tree010,
- TYPE_PRECISION
- (TREE_TYPE (TREE_OPERAND
- (arg0, 0))))
- && operand_equal_p (tree11, tree011, 0))
- return build2 ((code0 != LSHIFT_EXPR
- ? LROTATE_EXPR
- : RROTATE_EXPR),
- type, TREE_OPERAND (arg0, 0), tree11);
- }
- }
- }
-
- associate:
- /* In most languages, can't associate operations on floats through
- parentheses. Rather than remember where the parentheses were, we
- don't associate floats at all, unless the user has specified
- -funsafe-math-optimizations. */
-
- if (! wins
- && (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations))
- {
- tree var0, con0, lit0, minus_lit0;
- tree var1, con1, lit1, minus_lit1;
-
- /* Split both trees into variables, constants, and literals. Then
- associate each group together, the constants with literals,
- then the result with variables. This increases the chances of
- literals being recombined later and of generating relocatable
- expressions for the sum of a constant and literal. */
- var0 = split_tree (arg0, code, &con0, &lit0, &minus_lit0, 0);
- var1 = split_tree (arg1, code, &con1, &lit1, &minus_lit1,
- code == MINUS_EXPR);
-
- /* Only do something if we found more than two objects. Otherwise,
- nothing has changed and we risk infinite recursion. */
- if (2 < ((var0 != 0) + (var1 != 0)
- + (con0 != 0) + (con1 != 0)
- + (lit0 != 0) + (lit1 != 0)
- + (minus_lit0 != 0) + (minus_lit1 != 0)))
- {
- /* Recombine MINUS_EXPR operands by using PLUS_EXPR. */
- if (code == MINUS_EXPR)
- code = PLUS_EXPR;
-
- var0 = associate_trees (var0, var1, code, type);
- con0 = associate_trees (con0, con1, code, type);
- lit0 = associate_trees (lit0, lit1, code, type);
- minus_lit0 = associate_trees (minus_lit0, minus_lit1, code, type);
-
- /* Preserve the MINUS_EXPR if the negative part of the literal is
- greater than the positive part. Otherwise, the multiplicative
- folding code (i.e extract_muldiv) may be fooled in case
- unsigned constants are subtracted, like in the following
- example: ((X*2 + 4) - 8U)/2. */
- if (minus_lit0 && lit0)
- {
- if (TREE_CODE (lit0) == INTEGER_CST
- && TREE_CODE (minus_lit0) == INTEGER_CST
- && tree_int_cst_lt (lit0, minus_lit0))
- {
- minus_lit0 = associate_trees (minus_lit0, lit0,
- MINUS_EXPR, type);
- lit0 = 0;
- }
- else
- {
- lit0 = associate_trees (lit0, minus_lit0,
- MINUS_EXPR, type);
- minus_lit0 = 0;
- }
- }
- if (minus_lit0)
- {
- if (con0 == 0)
- return fold_convert (type,
- associate_trees (var0, minus_lit0,
- MINUS_EXPR, type));
- else
- {
- con0 = associate_trees (con0, minus_lit0,
- MINUS_EXPR, type);
- return fold_convert (type,
- associate_trees (var0, con0,
- PLUS_EXPR, type));
- }
- }
-
- con0 = associate_trees (con0, lit0, code, type);
- return fold_convert (type, associate_trees (var0, con0,
- code, type));
- }
- }
-
- binary:
- if (wins)
- t1 = const_binop (code, arg0, arg1, 0);
- if (t1 != NULL_TREE)
- {
- /* The return value should always have
- the same type as the original expression. */
- if (TREE_TYPE (t1) != type)
- t1 = fold_convert (type, t1);
-
- return t1;
- }
- return t;
-
- case MINUS_EXPR:
- /* A - (-B) -> A + B */
- if (TREE_CODE (arg1) == NEGATE_EXPR)
- return fold (build2 (PLUS_EXPR, type, arg0, TREE_OPERAND (arg1, 0)));
- /* (-A) - B -> (-B) - A where B is easily negated and we can swap. */
- if (TREE_CODE (arg0) == NEGATE_EXPR
- && (FLOAT_TYPE_P (type)
- || (INTEGRAL_TYPE_P (type) && flag_wrapv && !flag_trapv))
- && negate_expr_p (arg1)
- && reorder_operands_p (arg0, arg1))
- return fold (build2 (MINUS_EXPR, type, negate_expr (arg1),
- TREE_OPERAND (arg0, 0)));
-
- if (TREE_CODE (type) == COMPLEX_TYPE)
- {
- tem = fold_complex_add (type, arg0, arg1, MINUS_EXPR);
- if (tem)
- return tem;
- }
-
- if (! FLOAT_TYPE_P (type))
- {
- if (! wins && integer_zerop (arg0))
- return negate_expr (fold_convert (type, arg1));
- if (integer_zerop (arg1))
- return non_lvalue (fold_convert (type, arg0));
-
- /* 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))
- return fold (build2 (BIT_AND_EXPR, type,
- fold (build1 (BIT_NOT_EXPR, type,
- TREE_OPERAND (arg1, 0))),
- arg0));
- if (operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
- return fold (build2 (BIT_AND_EXPR, type,
- fold (build1 (BIT_NOT_EXPR, type,
- TREE_OPERAND (arg1, 1))),
- 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
- && TREE_CODE (arg1) == BIT_AND_EXPR
- && operand_equal_p (TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg1, 0), 0))
- {
- tree mask0 = TREE_OPERAND (arg0, 1);
- tree mask1 = TREE_OPERAND (arg1, 1);
- tree tem = fold (build1 (BIT_NOT_EXPR, type, mask0));
-
- if (operand_equal_p (tem, mask1, 0))
- {
- tem = fold (build2 (BIT_XOR_EXPR, type,
- TREE_OPERAND (arg0, 0), mask1));
- return fold (build2 (MINUS_EXPR, type, tem, mask1));
- }
- }
- }
-
- /* See if ARG1 is zero and X - ARG1 reduces to X. */
- else if (fold_real_zero_addition_p (TREE_TYPE (arg0), arg1, 1))
- return non_lvalue (fold_convert (type, arg0));
-
- /* (ARG0 - ARG1) is the same as (-ARG1 + ARG0). So check whether
- ARG0 is zero and X + ARG0 reduces to X, since that would mean
- (-ARG1 + ARG0) reduces to -ARG1. */
- else if (!wins && fold_real_zero_addition_p (TREE_TYPE (arg1), arg0, 0))
- return negate_expr (fold_convert (type, arg1));
-
- /* Fold &x - &x. This can happen from &x.foo - &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. */
-
- if ((! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
- && operand_equal_p (arg0, arg1, 0))
- return fold_convert (type, integer_zero_node);
-
- /* A - B -> A + (-B) if B is easily negatable. */
- if (!wins && negate_expr_p (arg1)
- && ((FLOAT_TYPE_P (type)
- /* Avoid this transformation if B is a positive REAL_CST. */
- && (TREE_CODE (arg1) != REAL_CST
- || REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg1))))
- || (INTEGRAL_TYPE_P (type) && flag_wrapv && !flag_trapv)))
- return fold (build2 (PLUS_EXPR, type, arg0, negate_expr (arg1)));
-
- /* Try folding difference of addresses. */
- {
- HOST_WIDE_INT diff;
-
- if ((TREE_CODE (arg0) == ADDR_EXPR
- || TREE_CODE (arg1) == ADDR_EXPR)
- && ptr_difference_const (arg0, arg1, &diff))
- return build_int_cst_type (type, diff);
- }
-
- /* Try replacing &a[i1] - c * i2 with &a[i1 - i2], if c is step
- of the array. Loop optimizer sometimes produce this type of
- expressions. */
- if (TREE_CODE (arg0) == ADDR_EXPR
- && TREE_CODE (arg1) == MULT_EXPR)
- {
- tem = try_move_mult_to_index (MINUS_EXPR, arg0, arg1);
- if (tem)
- return fold_convert (type, fold (tem));
- }
-
- if (TREE_CODE (arg0) == MULT_EXPR
- && TREE_CODE (arg1) == MULT_EXPR
- && (!FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations))
- {
- /* (A * C) - (B * C) -> (A-B) * C. */
- if (operand_equal_p (TREE_OPERAND (arg0, 1),
- TREE_OPERAND (arg1, 1), 0))
- return fold (build2 (MULT_EXPR, type,
- fold (build2 (MINUS_EXPR, type,
- TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg1, 0))),
- TREE_OPERAND (arg0, 1)));
- /* (A * C1) - (A * C2) -> A * (C1-C2). */
- if (operand_equal_p (TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg1, 0), 0))
- return fold (build2 (MULT_EXPR, type,
- TREE_OPERAND (arg0, 0),
- fold (build2 (MINUS_EXPR, type,
- TREE_OPERAND (arg0, 1),
- TREE_OPERAND (arg1, 1)))));
- }
-
- goto associate;
-
- case MULT_EXPR:
- /* (-A) * (-B) -> A * B */
- if (TREE_CODE (arg0) == NEGATE_EXPR && negate_expr_p (arg1))
- return fold (build2 (MULT_EXPR, type,
- TREE_OPERAND (arg0, 0),
- negate_expr (arg1)));
- if (TREE_CODE (arg1) == NEGATE_EXPR && negate_expr_p (arg0))
- return fold (build2 (MULT_EXPR, type,
- negate_expr (arg0),
- TREE_OPERAND (arg1, 0)));
-
- if (TREE_CODE (type) == COMPLEX_TYPE)
- {
- tem = fold_complex_mult (type, arg0, arg1);
- if (tem)
- return tem;
- }
-
- if (! FLOAT_TYPE_P (type))
- {
- if (integer_zerop (arg1))
- return omit_one_operand (type, arg1, arg0);
- if (integer_onep (arg1))
- return non_lvalue (fold_convert (type, arg0));
-
- /* (a * (1 << b)) is (a << b) */
- if (TREE_CODE (arg1) == LSHIFT_EXPR
- && integer_onep (TREE_OPERAND (arg1, 0)))
- return fold (build2 (LSHIFT_EXPR, type, arg0,
- TREE_OPERAND (arg1, 1)));
- if (TREE_CODE (arg0) == LSHIFT_EXPR
- && integer_onep (TREE_OPERAND (arg0, 0)))
- return fold (build2 (LSHIFT_EXPR, type, arg1,
- TREE_OPERAND (arg0, 1)));
-
- if (TREE_CODE (arg1) == INTEGER_CST
- && 0 != (tem = extract_muldiv (TREE_OPERAND (t, 0),
- fold_convert (type, arg1),
- code, NULL_TREE)))
- return fold_convert (type, tem);
-
- }
- else
- {
- /* 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. */
- if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0)))
- && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0)))
- && real_zerop (arg1))
- return omit_one_operand (type, arg1, arg0);
- /* In IEEE floating point, x*1 is not equivalent to x for snans. */
- if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
- && real_onep (arg1))
- return non_lvalue (fold_convert (type, arg0));
-
- /* Transform x * -1.0 into -x. */
- if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
- && real_minus_onep (arg1))
- return fold_convert (type, negate_expr (arg0));
-
- /* Convert (C1/X)*C2 into (C1*C2)/X. */
- if (flag_unsafe_math_optimizations
- && TREE_CODE (arg0) == RDIV_EXPR
- && TREE_CODE (arg1) == REAL_CST
- && TREE_CODE (TREE_OPERAND (arg0, 0)) == REAL_CST)
- {
- tree tem = const_binop (MULT_EXPR, TREE_OPERAND (arg0, 0),
- arg1, 0);
- if (tem)
- return fold (build2 (RDIV_EXPR, type, tem,
- TREE_OPERAND (arg0, 1)));
- }
-
- /* Strip sign operations from X in X*X, i.e. -Y*-Y -> Y*Y. */
- if (operand_equal_p (arg0, arg1, 0))
- {
- tree tem = fold_strip_sign_ops (arg0);
- if (tem != NULL_TREE)
- {
- tem = fold_convert (type, tem);
- return fold (build2 (MULT_EXPR, type, tem, tem));
- }
- }
-
- if (flag_unsafe_math_optimizations)
- {
- enum built_in_function fcode0 = builtin_mathfn_code (arg0);
- enum built_in_function fcode1 = builtin_mathfn_code (arg1);
-
- /* Optimizations of root(...)*root(...). */
- if (fcode0 == fcode1 && BUILTIN_ROOT_P (fcode0))
- {
- tree rootfn, arg, arglist;
- tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
- tree arg10 = TREE_VALUE (TREE_OPERAND (arg1, 1));
-
- /* Optimize sqrt(x)*sqrt(x) as x. */
- if (BUILTIN_SQRT_P (fcode0)
- && operand_equal_p (arg00, arg10, 0)
- && ! HONOR_SNANS (TYPE_MODE (type)))
- return arg00;
-
- /* Optimize root(x)*root(y) as root(x*y). */
- rootfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
- arg = fold (build2 (MULT_EXPR, type, arg00, arg10));
- arglist = build_tree_list (NULL_TREE, arg);
- return build_function_call_expr (rootfn, arglist);
- }
-
- /* Optimize expN(x)*expN(y) as expN(x+y). */
- if (fcode0 == fcode1 && BUILTIN_EXPONENT_P (fcode0))
- {
- tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
- tree arg = build2 (PLUS_EXPR, type,
- TREE_VALUE (TREE_OPERAND (arg0, 1)),
- TREE_VALUE (TREE_OPERAND (arg1, 1)));
- tree arglist = build_tree_list (NULL_TREE, fold (arg));
- return build_function_call_expr (expfn, arglist);
- }
-
- /* Optimizations of pow(...)*pow(...). */
- if ((fcode0 == BUILT_IN_POW && fcode1 == BUILT_IN_POW)
- || (fcode0 == BUILT_IN_POWF && fcode1 == BUILT_IN_POWF)
- || (fcode0 == BUILT_IN_POWL && fcode1 == BUILT_IN_POWL))
- {
- tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
- tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0,
- 1)));
- tree arg10 = TREE_VALUE (TREE_OPERAND (arg1, 1));
- tree arg11 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg1,
- 1)));
-
- /* Optimize pow(x,y)*pow(z,y) as pow(x*z,y). */
- if (operand_equal_p (arg01, arg11, 0))
- {
- tree powfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
- tree arg = build2 (MULT_EXPR, type, arg00, arg10);
- tree arglist = tree_cons (NULL_TREE, fold (arg),
- build_tree_list (NULL_TREE,
- arg01));
- return build_function_call_expr (powfn, arglist);
- }
-
- /* Optimize pow(x,y)*pow(x,z) as pow(x,y+z). */
- if (operand_equal_p (arg00, arg10, 0))
- {
- tree powfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
- tree arg = fold (build2 (PLUS_EXPR, type, arg01, arg11));
- tree arglist = tree_cons (NULL_TREE, arg00,
- build_tree_list (NULL_TREE,
- arg));
- return build_function_call_expr (powfn, arglist);
- }
- }
-
- /* Optimize tan(x)*cos(x) as sin(x). */
- if (((fcode0 == BUILT_IN_TAN && fcode1 == BUILT_IN_COS)
- || (fcode0 == BUILT_IN_TANF && fcode1 == BUILT_IN_COSF)
- || (fcode0 == BUILT_IN_TANL && fcode1 == BUILT_IN_COSL)
- || (fcode0 == BUILT_IN_COS && fcode1 == BUILT_IN_TAN)
- || (fcode0 == BUILT_IN_COSF && fcode1 == BUILT_IN_TANF)
- || (fcode0 == BUILT_IN_COSL && fcode1 == BUILT_IN_TANL))
- && operand_equal_p (TREE_VALUE (TREE_OPERAND (arg0, 1)),
- TREE_VALUE (TREE_OPERAND (arg1, 1)), 0))
- {
- tree sinfn = mathfn_built_in (type, BUILT_IN_SIN);
-
- if (sinfn != NULL_TREE)
- return build_function_call_expr (sinfn,
- TREE_OPERAND (arg0, 1));
- }
-
- /* Optimize x*pow(x,c) as pow(x,c+1). */
- if (fcode1 == BUILT_IN_POW
- || fcode1 == BUILT_IN_POWF
- || fcode1 == BUILT_IN_POWL)
- {
- tree arg10 = TREE_VALUE (TREE_OPERAND (arg1, 1));
- tree arg11 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg1,
- 1)));
- if (TREE_CODE (arg11) == REAL_CST
- && ! TREE_CONSTANT_OVERFLOW (arg11)
- && operand_equal_p (arg0, arg10, 0))
- {
- tree powfn = TREE_OPERAND (TREE_OPERAND (arg1, 0), 0);
- REAL_VALUE_TYPE c;
- tree arg, arglist;
-
- c = TREE_REAL_CST (arg11);
- real_arithmetic (&c, PLUS_EXPR, &c, &dconst1);
- arg = build_real (type, c);
- arglist = build_tree_list (NULL_TREE, arg);
- arglist = tree_cons (NULL_TREE, arg0, arglist);
- return build_function_call_expr (powfn, arglist);
- }
- }
-
- /* Optimize pow(x,c)*x as pow(x,c+1). */
- if (fcode0 == BUILT_IN_POW
- || fcode0 == BUILT_IN_POWF
- || fcode0 == BUILT_IN_POWL)
- {
- tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
- tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0,
- 1)));
- if (TREE_CODE (arg01) == REAL_CST
- && ! TREE_CONSTANT_OVERFLOW (arg01)
- && operand_equal_p (arg1, arg00, 0))
- {
- tree powfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
- REAL_VALUE_TYPE c;
- tree arg, arglist;
-
- c = TREE_REAL_CST (arg01);
- real_arithmetic (&c, PLUS_EXPR, &c, &dconst1);
- arg = build_real (type, c);
- arglist = build_tree_list (NULL_TREE, arg);
- arglist = tree_cons (NULL_TREE, arg1, arglist);
- return build_function_call_expr (powfn, arglist);
- }
- }
-
- /* Optimize x*x as pow(x,2.0), which is expanded as x*x. */
- if (! optimize_size
- && operand_equal_p (arg0, arg1, 0))
- {
- tree powfn = mathfn_built_in (type, BUILT_IN_POW);
-
- if (powfn)
- {
- tree arg = build_real (type, dconst2);
- tree arglist = build_tree_list (NULL_TREE, arg);
- arglist = tree_cons (NULL_TREE, arg0, arglist);
- return build_function_call_expr (powfn, arglist);
- }
- }
- }
- }
- goto associate;
-
- case BIT_IOR_EXPR:
- bit_ior:
- if (integer_all_onesp (arg1))
- return omit_one_operand (type, arg1, arg0);
- if (integer_zerop (arg1))
- return non_lvalue (fold_convert (type, arg0));
- if (operand_equal_p (arg0, arg1, 0))
- return non_lvalue (fold_convert (type, arg0));
-
- /* ~X | X is -1. */
- if (TREE_CODE (arg0) == BIT_NOT_EXPR
- && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
- {
- t1 = build_int_cst (type, -1);
- t1 = force_fit_type (t1, 0, false, false);
- return omit_one_operand (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_int_cst (type, -1);
- t1 = force_fit_type (t1, 0, false, false);
- return omit_one_operand (type, t1, arg0);
- }
-
- t1 = distribute_bit_expr (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 (BIT_NOT_EXPR, type,
- build2 (BIT_AND_EXPR, type,
- TREE_OPERAND (arg0, 0),
- 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:
- if (integer_zerop (arg1))
- return non_lvalue (fold_convert (type, arg0));
- if (integer_all_onesp (arg1))
- return fold (build1 (BIT_NOT_EXPR, type, arg0));
- if (operand_equal_p (arg0, arg1, 0))
- return omit_one_operand (type, integer_zero_node, arg0);
-
- /* ~X ^ X is -1. */
- if (TREE_CODE (arg0) == BIT_NOT_EXPR
- && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
- {
- t1 = build_int_cst (type, -1);
- t1 = force_fit_type (t1, 0, false, false);
- return omit_one_operand (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_int_cst (type, -1);
- t1 = force_fit_type (t1, 0, false, false);
- return omit_one_operand (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
- && integer_zerop (const_binop (BIT_AND_EXPR,
- TREE_OPERAND (arg0, 1),
- TREE_OPERAND (arg1, 1), 0)))
- {
- code = BIT_IOR_EXPR;
- goto bit_ior;
- }
-
- /* See if this can be simplified into a rotate first. If that
- is unsuccessful continue in the association code. */
- goto bit_rotate;
-
- case BIT_AND_EXPR:
- if (integer_all_onesp (arg1))
- return non_lvalue (fold_convert (type, arg0));
- if (integer_zerop (arg1))
- return omit_one_operand (type, arg1, arg0);
- if (operand_equal_p (arg0, arg1, 0))
- return non_lvalue (fold_convert (type, arg0));
-
- /* ~X & X is always zero. */
- if (TREE_CODE (arg0) == BIT_NOT_EXPR
- && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
- return omit_one_operand (type, integer_zero_node, arg1);
-
- /* X & ~X is always zero. */
- if (TREE_CODE (arg1) == BIT_NOT_EXPR
- && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
- return omit_one_operand (type, integer_zero_node, arg0);
-
- t1 = distribute_bit_expr (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))))
- {
- unsigned int prec
- = TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)));
-
- if (prec < BITS_PER_WORD && prec < HOST_BITS_PER_WIDE_INT
- && (~TREE_INT_CST_LOW (arg1)
- & (((HOST_WIDE_INT) 1 << prec) - 1)) == 0)
- return fold_convert (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 (BIT_NOT_EXPR, type,
- build2 (BIT_IOR_EXPR, type,
- TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg1, 0))));
- }
-
- goto associate;
-
- case RDIV_EXPR:
- /* Don't touch a floating-point divide by zero unless the mode
- of the constant can represent infinity. */
- if (TREE_CODE (arg1) == REAL_CST
- && !MODE_HAS_INFINITIES (TYPE_MODE (TREE_TYPE (arg1)))
- && real_zerop (arg1))
- return t;
-
- /* (-A) / (-B) -> A / B */
- if (TREE_CODE (arg0) == NEGATE_EXPR && negate_expr_p (arg1))
- return fold (build2 (RDIV_EXPR, type,
- TREE_OPERAND (arg0, 0),
- negate_expr (arg1)));
- if (TREE_CODE (arg1) == NEGATE_EXPR && negate_expr_p (arg0))
- return fold (build2 (RDIV_EXPR, type,
- negate_expr (arg0),
- TREE_OPERAND (arg1, 0)));
-
- /* In IEEE floating point, x/1 is not equivalent to x for snans. */
- if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
- && real_onep (arg1))
- return non_lvalue (fold_convert (type, arg0));
-
- /* In IEEE floating point, x/-1 is not equivalent to -x for snans. */
- if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
- && real_minus_onep (arg1))
- return non_lvalue (fold_convert (type, negate_expr (arg0)));
-
- /* If ARG1 is a constant, we can convert this to a multiply by the
- reciprocal. This does not have the same rounding properties,
- so only do this if -funsafe-math-optimizations. We can actually
- always safely do it if ARG1 is a power of two, but it's hard to
- tell if it is or not in a portable manner. */
- if (TREE_CODE (arg1) == REAL_CST)
- {
- if (flag_unsafe_math_optimizations
- && 0 != (tem = const_binop (code, build_real (type, dconst1),
- arg1, 0)))
- return fold (build2 (MULT_EXPR, type, arg0, tem));
- /* Find the reciprocal if optimizing and the result is exact. */
- if (optimize)
- {
- REAL_VALUE_TYPE r;
- r = TREE_REAL_CST (arg1);
- if (exact_real_inverse (TYPE_MODE(TREE_TYPE(arg0)), &r))
- {
- tem = build_real (type, r);
- return fold (build2 (MULT_EXPR, type, arg0, tem));
- }
- }
- }
- /* Convert A/B/C to A/(B*C). */
- if (flag_unsafe_math_optimizations
- && TREE_CODE (arg0) == RDIV_EXPR)
- return fold (build2 (RDIV_EXPR, type, TREE_OPERAND (arg0, 0),
- fold (build2 (MULT_EXPR, type,
- TREE_OPERAND (arg0, 1), arg1))));
-
- /* Convert A/(B/C) to (A/B)*C. */
- if (flag_unsafe_math_optimizations
- && TREE_CODE (arg1) == RDIV_EXPR)
- return fold (build2 (MULT_EXPR, type,
- fold (build2 (RDIV_EXPR, type, arg0,
- TREE_OPERAND (arg1, 0))),
- TREE_OPERAND (arg1, 1)));
-
- /* Convert C1/(X*C2) into (C1/C2)/X. */
- if (flag_unsafe_math_optimizations
- && TREE_CODE (arg1) == MULT_EXPR
- && TREE_CODE (arg0) == REAL_CST
- && TREE_CODE (TREE_OPERAND (arg1, 1)) == REAL_CST)
- {
- tree tem = const_binop (RDIV_EXPR, arg0,
- TREE_OPERAND (arg1, 1), 0);
- if (tem)
- return fold (build2 (RDIV_EXPR, type, tem,
- TREE_OPERAND (arg1, 0)));
- }
-
- if (TREE_CODE (type) == COMPLEX_TYPE)
- {
- tem = fold_complex_div (type, arg0, arg1, code);
- if (tem)
- return tem;
- }
-
- if (flag_unsafe_math_optimizations)
- {
- enum built_in_function fcode = builtin_mathfn_code (arg1);
- /* Optimize x/expN(y) into x*expN(-y). */
- if (BUILTIN_EXPONENT_P (fcode))
- {
- tree expfn = TREE_OPERAND (TREE_OPERAND (arg1, 0), 0);
- tree arg = negate_expr (TREE_VALUE (TREE_OPERAND (arg1, 1)));
- tree arglist = build_tree_list (NULL_TREE,
- fold_convert (type, arg));
- arg1 = build_function_call_expr (expfn, arglist);
- return fold (build2 (MULT_EXPR, type, arg0, arg1));
- }
-
- /* Optimize x/pow(y,z) into x*pow(y,-z). */
- if (fcode == BUILT_IN_POW
- || fcode == BUILT_IN_POWF
- || fcode == BUILT_IN_POWL)
- {
- tree powfn = TREE_OPERAND (TREE_OPERAND (arg1, 0), 0);
- tree arg10 = TREE_VALUE (TREE_OPERAND (arg1, 1));
- tree arg11 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg1, 1)));
- tree neg11 = fold_convert (type, negate_expr (arg11));
- tree arglist = tree_cons(NULL_TREE, arg10,
- build_tree_list (NULL_TREE, neg11));
- arg1 = build_function_call_expr (powfn, arglist);
- return fold (build2 (MULT_EXPR, type, arg0, arg1));
- }
- }
-
- if (flag_unsafe_math_optimizations)
- {
- enum built_in_function fcode0 = builtin_mathfn_code (arg0);
- enum built_in_function fcode1 = builtin_mathfn_code (arg1);
-
- /* Optimize sin(x)/cos(x) as tan(x). */
- if (((fcode0 == BUILT_IN_SIN && fcode1 == BUILT_IN_COS)
- || (fcode0 == BUILT_IN_SINF && fcode1 == BUILT_IN_COSF)
- || (fcode0 == BUILT_IN_SINL && fcode1 == BUILT_IN_COSL))
- && operand_equal_p (TREE_VALUE (TREE_OPERAND (arg0, 1)),
- TREE_VALUE (TREE_OPERAND (arg1, 1)), 0))
- {
- tree tanfn = mathfn_built_in (type, BUILT_IN_TAN);
-
- if (tanfn != NULL_TREE)
- return build_function_call_expr (tanfn,
- TREE_OPERAND (arg0, 1));
- }
-
- /* Optimize cos(x)/sin(x) as 1.0/tan(x). */
- if (((fcode0 == BUILT_IN_COS && fcode1 == BUILT_IN_SIN)
- || (fcode0 == BUILT_IN_COSF && fcode1 == BUILT_IN_SINF)
- || (fcode0 == BUILT_IN_COSL && fcode1 == BUILT_IN_SINL))
- && operand_equal_p (TREE_VALUE (TREE_OPERAND (arg0, 1)),
- TREE_VALUE (TREE_OPERAND (arg1, 1)), 0))
- {
- tree tanfn = mathfn_built_in (type, BUILT_IN_TAN);
-
- if (tanfn != NULL_TREE)
- {
- tree tmp = TREE_OPERAND (arg0, 1);
- tmp = build_function_call_expr (tanfn, tmp);
- return fold (build2 (RDIV_EXPR, type,
- build_real (type, dconst1), tmp));
- }
- }
-
- /* Optimize pow(x,c)/x as pow(x,c-1). */
- if (fcode0 == BUILT_IN_POW
- || fcode0 == BUILT_IN_POWF
- || fcode0 == BUILT_IN_POWL)
- {
- tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
- tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0, 1)));
- if (TREE_CODE (arg01) == REAL_CST
- && ! TREE_CONSTANT_OVERFLOW (arg01)
- && operand_equal_p (arg1, arg00, 0))
- {
- tree powfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
- REAL_VALUE_TYPE c;
- tree arg, arglist;
-
- c = TREE_REAL_CST (arg01);
- real_arithmetic (&c, MINUS_EXPR, &c, &dconst1);
- arg = build_real (type, c);
- arglist = build_tree_list (NULL_TREE, arg);
- arglist = tree_cons (NULL_TREE, arg1, arglist);
- return build_function_call_expr (powfn, arglist);
- }
- }
- }
- goto binary;
-
- case TRUNC_DIV_EXPR:
- case ROUND_DIV_EXPR:
- case FLOOR_DIV_EXPR:
- case CEIL_DIV_EXPR:
- case EXACT_DIV_EXPR:
- if (integer_onep (arg1))
- return non_lvalue (fold_convert (type, arg0));
- if (integer_zerop (arg1))
- return t;
- /* X / -1 is -X. */
- if (!TYPE_UNSIGNED (type)
- && TREE_CODE (arg1) == INTEGER_CST
- && TREE_INT_CST_LOW (arg1) == (unsigned HOST_WIDE_INT) -1
- && TREE_INT_CST_HIGH (arg1) == -1)
- return fold_convert (type, negate_expr (arg0));
-
- /* If arg0 is a multiple of arg1, then rewrite to the fastest div
- operation, EXACT_DIV_EXPR.
-
- Note that only CEIL_DIV_EXPR and FLOOR_DIV_EXPR are rewritten now.
- At one time others generated faster code, it's not clear if they do
- after the last round to changes to the DIV code in expmed.c. */
- if ((code == CEIL_DIV_EXPR || code == FLOOR_DIV_EXPR)
- && multiple_of_p (type, arg0, arg1))
- return fold (build2 (EXACT_DIV_EXPR, type, arg0, arg1));
-
- if (TREE_CODE (arg1) == INTEGER_CST
- && 0 != (tem = extract_muldiv (TREE_OPERAND (t, 0), arg1,
- code, NULL_TREE)))
- return fold_convert (type, tem);
-
- if (TREE_CODE (type) == COMPLEX_TYPE)
- {
- tem = fold_complex_div (type, arg0, arg1, code);
- if (tem)
- return tem;
- }
- goto binary;
-
- case CEIL_MOD_EXPR:
- case FLOOR_MOD_EXPR:
- case ROUND_MOD_EXPR:
- case TRUNC_MOD_EXPR:
- /* X % 1 is always zero, but be sure to preserve any side
- effects in X. */
- if (integer_onep (arg1))
- return omit_one_operand (type, integer_zero_node, arg0);
-
- /* X % 0, return X % 0 unchanged so that we can get the
- proper warnings and errors. */
- if (integer_zerop (arg1))
- return t;
-
- /* 0 % X is always zero, but be sure to preserve any side
- effects in X. Place this after checking for X == 0. */
- if (integer_zerop (arg0))
- return omit_one_operand (type, integer_zero_node, arg1);
-
- /* X % -1 is zero. */
- if (!TYPE_UNSIGNED (type)
- && TREE_CODE (arg1) == INTEGER_CST
- && TREE_INT_CST_LOW (arg1) == (unsigned HOST_WIDE_INT) -1
- && TREE_INT_CST_HIGH (arg1) == -1)
- return omit_one_operand (type, integer_zero_node, arg0);
-
- /* Optimize unsigned TRUNC_MOD_EXPR by a power of two into a
- BIT_AND_EXPR, i.e. "X % C" into "X & C2". */
- if (code == TRUNC_MOD_EXPR
- && TYPE_UNSIGNED (type)
- && integer_pow2p (arg1))
- {
- unsigned HOST_WIDE_INT high, low;
- tree mask;
- int l;
-
- l = tree_log2 (arg1);
- if (l >= HOST_BITS_PER_WIDE_INT)
- {
- high = ((unsigned HOST_WIDE_INT) 1
- << (l - HOST_BITS_PER_WIDE_INT)) - 1;
- low = -1;
- }
- else
- {
- high = 0;
- low = ((unsigned HOST_WIDE_INT) 1 << l) - 1;
- }
-
- mask = build_int_cst_wide (type, low, high);
- return fold (build2 (BIT_AND_EXPR, type,
- fold_convert (type, arg0), mask));
- }
-
- /* X % -C is the same as X % C. */
- if (code == TRUNC_MOD_EXPR
- && !TYPE_UNSIGNED (type)
- && TREE_CODE (arg1) == INTEGER_CST
- && TREE_INT_CST_HIGH (arg1) < 0
- && !flag_trapv
- /* Avoid this transformation if C is INT_MIN, i.e. C == -C. */
- && !sign_bit_p (arg1, arg1))
- return fold (build2 (code, type, fold_convert (type, arg0),
- fold_convert (type, negate_expr (arg1))));
-
- /* X % -Y is the same as X % Y. */
- if (code == TRUNC_MOD_EXPR
- && !TYPE_UNSIGNED (type)
- && TREE_CODE (arg1) == NEGATE_EXPR
- && !flag_trapv)
- return fold (build2 (code, type, fold_convert (type, arg0),
- fold_convert (type, TREE_OPERAND (arg1, 0))));
-
- if (TREE_CODE (arg1) == INTEGER_CST
- && 0 != (tem = extract_muldiv (TREE_OPERAND (t, 0), arg1,
- code, NULL_TREE)))
- return fold_convert (type, tem);
-
- goto binary;
-
- case LROTATE_EXPR:
- case RROTATE_EXPR:
- if (integer_all_onesp (arg0))
- return omit_one_operand (type, arg0, arg1);
- goto shift;
-
- case RSHIFT_EXPR:
- /* Optimize -1 >> x for arithmetic right shifts. */
- if (integer_all_onesp (arg0) && !TYPE_UNSIGNED (type))
- return omit_one_operand (type, arg0, arg1);
- /* ... fall through ... */
-
- case LSHIFT_EXPR:
- shift:
- if (integer_zerop (arg1))
- return non_lvalue (fold_convert (type, arg0));
- if (integer_zerop (arg0))
- return omit_one_operand (type, arg0, arg1);
-
- /* Since negative shift count is not well-defined,
- don't try to compute it in the compiler. */
- if (TREE_CODE (arg1) == INTEGER_CST && tree_int_cst_sgn (arg1) < 0)
- return t;
- /* Rewrite an LROTATE_EXPR by a constant into an
- RROTATE_EXPR by a new constant. */
- if (code == LROTATE_EXPR && TREE_CODE (arg1) == INTEGER_CST)
- {
- tree tem = build_int_cst (NULL_TREE,
- GET_MODE_BITSIZE (TYPE_MODE (type)));
- tem = fold_convert (TREE_TYPE (arg1), tem);
- tem = const_binop (MINUS_EXPR, tem, arg1, 0);
- return fold (build2 (RROTATE_EXPR, type, arg0, tem));
- }
-
- /* If we have a rotate of a bit operation with the rotate count and
- the second operand of the bit operation both constant,
- permute the two operations. */
- if (code == RROTATE_EXPR && TREE_CODE (arg1) == INTEGER_CST
- && (TREE_CODE (arg0) == BIT_AND_EXPR
- || TREE_CODE (arg0) == BIT_IOR_EXPR
- || TREE_CODE (arg0) == BIT_XOR_EXPR)
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
- return fold (build2 (TREE_CODE (arg0), type,
- fold (build2 (code, type,
- TREE_OPERAND (arg0, 0), arg1)),
- fold (build2 (code, type,
- TREE_OPERAND (arg0, 1), arg1))));
-
- /* Two consecutive rotates adding up to the width of the mode can
- be ignored. */
- if (code == RROTATE_EXPR && TREE_CODE (arg1) == INTEGER_CST
- && TREE_CODE (arg0) == RROTATE_EXPR
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
- && TREE_INT_CST_HIGH (arg1) == 0
- && TREE_INT_CST_HIGH (TREE_OPERAND (arg0, 1)) == 0
- && ((TREE_INT_CST_LOW (arg1)
- + TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1)))
- == (unsigned int) GET_MODE_BITSIZE (TYPE_MODE (type))))
- return TREE_OPERAND (arg0, 0);
-
- goto binary;
-
- case MIN_EXPR:
- if (operand_equal_p (arg0, arg1, 0))
- return omit_one_operand (type, arg0, arg1);
- if (INTEGRAL_TYPE_P (type)
- && operand_equal_p (arg1, TYPE_MIN_VALUE (type), OEP_ONLY_CONST))
- return omit_one_operand (type, arg1, arg0);
- goto associate;
-
- case MAX_EXPR:
- if (operand_equal_p (arg0, arg1, 0))
- return omit_one_operand (type, arg0, arg1);
- if (INTEGRAL_TYPE_P (type)
- && TYPE_MAX_VALUE (type)
- && operand_equal_p (arg1, TYPE_MAX_VALUE (type), OEP_ONLY_CONST))
- return omit_one_operand (type, arg1, arg0);
- goto associate;
-
- case TRUTH_ANDIF_EXPR:
- /* Note that the operands of this must be ints
- and their values must be 0 or 1.
- ("true" is a fixed value perhaps depending on the language.) */
- /* If first arg is constant zero, return it. */
- if (integer_zerop (arg0))
- return fold_convert (type, arg0);
- case TRUTH_AND_EXPR:
- /* If either arg is constant true, drop it. */
- if (TREE_CODE (arg0) == INTEGER_CST && ! integer_zerop (arg0))
- return non_lvalue (fold_convert (type, arg1));
- if (TREE_CODE (arg1) == INTEGER_CST && ! integer_zerop (arg1)
- /* Preserve sequence points. */
- && (code != TRUTH_ANDIF_EXPR || ! TREE_SIDE_EFFECTS (arg0)))
- return non_lvalue (fold_convert (type, arg0));
- /* If second arg is constant zero, result is zero, but first arg
- must be evaluated. */
- if (integer_zerop (arg1))
- return omit_one_operand (type, arg1, arg0);
- /* Likewise for first arg, but note that only the TRUTH_AND_EXPR
- case will be handled here. */
- if (integer_zerop (arg0))
- return omit_one_operand (type, arg0, arg1);
-
- /* !X && X is always false. */
- if (TREE_CODE (arg0) == TRUTH_NOT_EXPR
- && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
- return omit_one_operand (type, integer_zero_node, arg1);
- /* X && !X is always false. */
- if (TREE_CODE (arg1) == TRUTH_NOT_EXPR
- && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
- return omit_one_operand (type, integer_zero_node, arg0);
-
- /* A < X && A + 1 > Y ==> A < X && A >= Y. Normally A + 1 > Y
- means A >= Y && A != MAX, but in this case we know that
- A < X <= MAX. */
-
- if (!TREE_SIDE_EFFECTS (arg0)
- && !TREE_SIDE_EFFECTS (arg1))
- {
- tem = fold_to_nonsharp_ineq_using_bound (arg0, arg1);
- if (tem)
- return fold (build2 (code, type, tem, arg1));
-
- tem = fold_to_nonsharp_ineq_using_bound (arg1, arg0);
- if (tem)
- return fold (build2 (code, type, arg0, tem));
- }
-
- truth_andor:
- /* We only do these simplifications if we are optimizing. */
- if (!optimize)
- return t;
-
- /* Check for things like (A || B) && (A || C). We can convert this
- to A || (B && C). Note that either operator can be any of the four
- truth and/or operations and the transformation will still be
- valid. Also note that we only care about order for the
- ANDIF and ORIF operators. If B contains side effects, this
- might change the truth-value of A. */
- if (TREE_CODE (arg0) == TREE_CODE (arg1)
- && (TREE_CODE (arg0) == TRUTH_ANDIF_EXPR
- || TREE_CODE (arg0) == TRUTH_ORIF_EXPR
- || TREE_CODE (arg0) == TRUTH_AND_EXPR
- || TREE_CODE (arg0) == TRUTH_OR_EXPR)
- && ! TREE_SIDE_EFFECTS (TREE_OPERAND (arg0, 1)))
- {
- tree a00 = TREE_OPERAND (arg0, 0);
- tree a01 = TREE_OPERAND (arg0, 1);
- tree a10 = TREE_OPERAND (arg1, 0);
- tree a11 = TREE_OPERAND (arg1, 1);
- int commutative = ((TREE_CODE (arg0) == TRUTH_OR_EXPR
- || TREE_CODE (arg0) == TRUTH_AND_EXPR)
- && (code == TRUTH_AND_EXPR
- || code == TRUTH_OR_EXPR));
-
- if (operand_equal_p (a00, a10, 0))
- return fold (build2 (TREE_CODE (arg0), type, a00,
- fold (build2 (code, type, a01, a11))));
- else if (commutative && operand_equal_p (a00, a11, 0))
- return fold (build2 (TREE_CODE (arg0), type, a00,
- fold (build2 (code, type, a01, a10))));
- else if (commutative && operand_equal_p (a01, a10, 0))
- return fold (build2 (TREE_CODE (arg0), type, a01,
- fold (build2 (code, type, a00, a11))));
-
- /* This case if tricky because we must either have commutative
- operators or else A10 must not have side-effects. */
-
- else if ((commutative || ! TREE_SIDE_EFFECTS (a10))
- && operand_equal_p (a01, a11, 0))
- return fold (build2 (TREE_CODE (arg0), type,
- fold (build2 (code, type, a00, a10)),
- a01));
- }
-
- /* See if we can build a range comparison. */
- if (0 != (tem = fold_range_test (t)))
- return tem;
-
- /* Check for the possibility of merging component references. If our
- lhs is another similar operation, try to merge its rhs with our
- rhs. Then try to merge our lhs and rhs. */
- if (TREE_CODE (arg0) == code
- && 0 != (tem = fold_truthop (code, type,
- TREE_OPERAND (arg0, 1), arg1)))
- return fold (build2 (code, type, TREE_OPERAND (arg0, 0), tem));
-
- if ((tem = fold_truthop (code, type, arg0, arg1)) != 0)
- return tem;
-
- return t;
-
- case TRUTH_ORIF_EXPR:
- /* Note that the operands of this must be ints
- and their values must be 0 or true.
- ("true" is a fixed value perhaps depending on the language.) */
- /* If first arg is constant true, return it. */
- if (TREE_CODE (arg0) == INTEGER_CST && ! integer_zerop (arg0))
- return fold_convert (type, arg0);
- case TRUTH_OR_EXPR:
- /* If either arg is constant zero, drop it. */
- if (TREE_CODE (arg0) == INTEGER_CST && integer_zerop (arg0))
- return non_lvalue (fold_convert (type, arg1));
- if (TREE_CODE (arg1) == INTEGER_CST && integer_zerop (arg1)
- /* Preserve sequence points. */
- && (code != TRUTH_ORIF_EXPR || ! TREE_SIDE_EFFECTS (arg0)))
- return non_lvalue (fold_convert (type, arg0));
- /* If second arg is constant true, result is true, but we must
- evaluate first arg. */
- if (TREE_CODE (arg1) == INTEGER_CST && ! integer_zerop (arg1))
- return omit_one_operand (type, arg1, arg0);
- /* Likewise for first arg, but note this only occurs here for
- TRUTH_OR_EXPR. */
- if (TREE_CODE (arg0) == INTEGER_CST && ! integer_zerop (arg0))
- return omit_one_operand (type, arg0, arg1);
-
- /* !X || X is always true. */
- if (TREE_CODE (arg0) == TRUTH_NOT_EXPR
- && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
- return omit_one_operand (type, integer_one_node, arg1);
- /* X || !X is always true. */
- if (TREE_CODE (arg1) == TRUTH_NOT_EXPR
- && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
- return omit_one_operand (type, integer_one_node, arg0);
-
- goto truth_andor;
-
- case TRUTH_XOR_EXPR:
- /* If the second arg is constant zero, drop it. */
- if (integer_zerop (arg1))
- return non_lvalue (fold_convert (type, arg0));
- /* If the second arg is constant true, this is a logical inversion. */
- if (integer_onep (arg1))
- return non_lvalue (fold_convert (type, invert_truthvalue (arg0)));
- /* Identical arguments cancel to zero. */
- if (operand_equal_p (arg0, arg1, 0))
- return omit_one_operand (type, integer_zero_node, arg0);
-
- /* !X ^ X is always true. */
- if (TREE_CODE (arg0) == TRUTH_NOT_EXPR
- && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
- return omit_one_operand (type, integer_one_node, arg1);
-
- /* X ^ !X is always true. */
- if (TREE_CODE (arg1) == TRUTH_NOT_EXPR
- && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
- return omit_one_operand (type, integer_one_node, arg0);
-
- return t;
-
- case EQ_EXPR:
- case NE_EXPR:
- case LT_EXPR:
- case GT_EXPR:
- case LE_EXPR:
- case GE_EXPR:
- /* If one arg is a real or integer constant, put it last. */
- if (tree_swap_operands_p (arg0, arg1, true))
- return fold (build2 (swap_tree_comparison (code), type, arg1, arg0));
-
- /* If this is an equality comparison of the address of a non-weak
- object against zero, then we know the result. */
- if ((code == EQ_EXPR || code == NE_EXPR)
- && TREE_CODE (arg0) == ADDR_EXPR
- && DECL_P (TREE_OPERAND (arg0, 0))
- && ! DECL_WEAK (TREE_OPERAND (arg0, 0))
- && integer_zerop (arg1))
- return constant_boolean_node (code != EQ_EXPR, type);
-
- /* 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 ((code == EQ_EXPR || code == NE_EXPR)
- && TREE_CODE (arg0) == ADDR_EXPR
- && DECL_P (TREE_OPERAND (arg0, 0))
- && ! DECL_WEAK (TREE_OPERAND (arg0, 0))
- && ! lookup_attribute ("alias",
- DECL_ATTRIBUTES (TREE_OPERAND (arg0, 0)))
- && ! DECL_EXTERNAL (TREE_OPERAND (arg0, 0))
- && TREE_CODE (arg1) == ADDR_EXPR
- && DECL_P (TREE_OPERAND (arg1, 0))
- && ! DECL_WEAK (TREE_OPERAND (arg1, 0))
- && ! lookup_attribute ("alias",
- DECL_ATTRIBUTES (TREE_OPERAND (arg1, 0)))
- && ! DECL_EXTERNAL (TREE_OPERAND (arg1, 0)))
- return constant_boolean_node (operand_equal_p (arg0, arg1, 0)
- ? code == EQ_EXPR : code != EQ_EXPR,
- type);
-
- /* If this is a comparison of two exprs that look like an
- ARRAY_REF of the same object, then we can fold this to a
- comparison of the two offsets. */
- if (COMPARISON_CLASS_P (t))
- {
- tree base0, offset0, base1, offset1;
-
- if (extract_array_ref (arg0, &base0, &offset0)
- && extract_array_ref (arg1, &base1, &offset1)
- && operand_equal_p (base0, base1, 0))
- {
- if (offset0 == NULL_TREE
- && offset1 == NULL_TREE)
- {
- offset0 = integer_zero_node;
- offset1 = integer_zero_node;
- }
- else if (offset0 == NULL_TREE)
- offset0 = build_int_cst (TREE_TYPE (offset1), 0);
- else if (offset1 == NULL_TREE)
- offset1 = build_int_cst (TREE_TYPE (offset0), 0);
-
- if (TREE_TYPE (offset0) == TREE_TYPE (offset1))
- return fold (build2 (code, type, offset0, offset1));
- }
- }
-
- 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 (code, type, fold_convert (newtype, targ0),
- fold_convert (newtype, targ1)));
-
- /* (-a) CMP (-b) -> b CMP a */
- if (TREE_CODE (arg0) == NEGATE_EXPR
- && TREE_CODE (arg1) == NEGATE_EXPR)
- return fold (build2 (code, type, TREE_OPERAND (arg1, 0),
- TREE_OPERAND (arg0, 0)));
-
- if (TREE_CODE (arg1) == REAL_CST)
- {
- REAL_VALUE_TYPE cst;
- cst = TREE_REAL_CST (arg1);
-
- /* (-a) CMP CST -> a swap(CMP) (-CST) */
- if (TREE_CODE (arg0) == NEGATE_EXPR)
- return
- fold (build2 (swap_tree_comparison (code), type,
- TREE_OPERAND (arg0, 0),
- build_real (TREE_TYPE (arg1),
- REAL_VALUE_NEGATE (cst))));
-
- /* IEEE doesn't distinguish +0 and -0 in comparisons. */
- /* a CMP (-0) -> a CMP 0 */
- if (REAL_VALUE_MINUS_ZERO (cst))
- return fold (build2 (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 (TYPE_MODE (TREE_TYPE (arg1))))
- {
- tem = (code == NE_EXPR) ? integer_one_node : integer_zero_node;
- return omit_one_operand (type, tem, arg0);
- }
-
- /* Fold comparisons against infinity. */
- if (REAL_VALUE_ISINF (cst))
- {
- tem = fold_inf_compare (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), 0))
- && ! TREE_CONSTANT_OVERFLOW (tem))
- return fold (build2 (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. */
- if (flag_unsafe_math_optimizations
- && 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, 0))
- && ! TREE_CONSTANT_OVERFLOW (tem))
- return fold (build2 (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 (fcode, code, type, arg0, arg1);
- if (tem != NULL_TREE)
- return tem;
- }
- }
- }
-
- /* Convert foo++ == CONST into ++foo == CONST + INCR. */
- if (TREE_CONSTANT (arg1)
- && (TREE_CODE (arg0) == POSTINCREMENT_EXPR
- || TREE_CODE (arg0) == POSTDECREMENT_EXPR)
- /* This optimization is invalid for ordered comparisons
- if CONST+INCR overflows or if foo+incr might overflow.
- This optimization is invalid for floating point due to rounding.
- For pointer types we assume overflow doesn't happen. */
- && (POINTER_TYPE_P (TREE_TYPE (arg0))
- || (INTEGRAL_TYPE_P (TREE_TYPE (arg0))
- && (code == EQ_EXPR || code == NE_EXPR))))
- {
- tree varop, newconst;
-
- if (TREE_CODE (arg0) == POSTINCREMENT_EXPR)
- {
- newconst = fold (build2 (PLUS_EXPR, TREE_TYPE (arg0),
- arg1, TREE_OPERAND (arg0, 1)));
- varop = build2 (PREINCREMENT_EXPR, TREE_TYPE (arg0),
- TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg0, 1));
- }
- else
- {
- newconst = fold (build2 (MINUS_EXPR, TREE_TYPE (arg0),
- arg1, TREE_OPERAND (arg0, 1)));
- varop = build2 (PREDECREMENT_EXPR, TREE_TYPE (arg0),
- TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg0, 1));
- }
-
-
- /* If VAROP is a reference to a bitfield, we must mask
- the constant by the width of the field. */
- if (TREE_CODE (TREE_OPERAND (varop, 0)) == COMPONENT_REF
- && DECL_BIT_FIELD (TREE_OPERAND (TREE_OPERAND (varop, 0), 1))
- && host_integerp (DECL_SIZE (TREE_OPERAND
- (TREE_OPERAND (varop, 0), 1)), 1))
- {
- tree fielddecl = TREE_OPERAND (TREE_OPERAND (varop, 0), 1);
- HOST_WIDE_INT size = tree_low_cst (DECL_SIZE (fielddecl), 1);
- tree folded_compare, shift;
-
- /* First check whether the comparison would come out
- always the same. If we don't do that we would
- change the meaning with the masking. */
- folded_compare = fold (build2 (code, type,
- TREE_OPERAND (varop, 0), arg1));
- if (integer_zerop (folded_compare)
- || integer_onep (folded_compare))
- return omit_one_operand (type, folded_compare, varop);
-
- shift = build_int_cst (NULL_TREE,
- TYPE_PRECISION (TREE_TYPE (varop)) - size);
- shift = fold_convert (TREE_TYPE (varop), shift);
- newconst = fold (build2 (LSHIFT_EXPR, TREE_TYPE (varop),
- newconst, shift));
- newconst = fold (build2 (RSHIFT_EXPR, TREE_TYPE (varop),
- newconst, shift));
- }
-
- return fold (build2 (code, type, varop, newconst));
- }
-
- /* Change X >= C to X > (C - 1) and X < C to X <= (C - 1) if C > 0.
- This transformation affects the cases which are handled in later
- optimizations involving comparisons with non-negative constants. */
- if (TREE_CODE (arg1) == INTEGER_CST
- && TREE_CODE (arg0) != INTEGER_CST
- && tree_int_cst_sgn (arg1) > 0)
- {
- switch (code)
- {
- case GE_EXPR:
- arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
- return fold (build2 (GT_EXPR, type, arg0, arg1));
-
- case LT_EXPR:
- arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
- return fold (build2 (LE_EXPR, type, arg0, arg1));
-
- default:
- break;
- }
- }
-
- /* Comparisons with the highest or lowest possible integer of
- the specified size will have known values.
-
- This is quite similar to fold_relational_hi_lo, however,
- attempts to share the code have been nothing but trouble. */
- {
- int width = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (arg1)));
-
- if (TREE_CODE (arg1) == INTEGER_CST
- && ! TREE_CONSTANT_OVERFLOW (arg1)
- && width <= 2 * HOST_BITS_PER_WIDE_INT
- && (INTEGRAL_TYPE_P (TREE_TYPE (arg1))
- || POINTER_TYPE_P (TREE_TYPE (arg1))))
- {
- HOST_WIDE_INT signed_max_hi;
- unsigned HOST_WIDE_INT signed_max_lo;
- unsigned HOST_WIDE_INT max_hi, max_lo, min_hi, min_lo;
-
- if (width <= HOST_BITS_PER_WIDE_INT)
- {
- signed_max_lo = ((unsigned HOST_WIDE_INT) 1 << (width - 1))
- - 1;
- signed_max_hi = 0;
- max_hi = 0;
-
- if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
- {
- max_lo = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1;
- min_lo = 0;
- min_hi = 0;
- }
- else
- {
- max_lo = signed_max_lo;
- min_lo = ((unsigned HOST_WIDE_INT) -1 << (width - 1));
- min_hi = -1;
- }
- }
- else
- {
- width -= HOST_BITS_PER_WIDE_INT;
- signed_max_lo = -1;
- signed_max_hi = ((unsigned HOST_WIDE_INT) 1 << (width - 1))
- - 1;
- max_lo = -1;
- min_lo = 0;
-
- if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
- {
- max_hi = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1;
- min_hi = 0;
- }
- else
- {
- max_hi = signed_max_hi;
- min_hi = ((unsigned HOST_WIDE_INT) -1 << (width - 1));
- }
- }
-
- if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1) == max_hi
- && TREE_INT_CST_LOW (arg1) == max_lo)
- switch (code)
- {
- case GT_EXPR:
- return omit_one_operand (type, integer_zero_node, arg0);
-
- case GE_EXPR:
- return fold (build2 (EQ_EXPR, type, arg0, arg1));
-
- case LE_EXPR:
- return omit_one_operand (type, integer_one_node, arg0);
-
- case LT_EXPR:
- return fold (build2 (NE_EXPR, type, arg0, arg1));
-
- /* The GE_EXPR and LT_EXPR cases above are not normally
- reached because of previous transformations. */
-
- default:
- break;
- }
- else if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1)
- == max_hi
- && TREE_INT_CST_LOW (arg1) == max_lo - 1)
- switch (code)
- {
- case GT_EXPR:
- arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0);
- return fold (build2 (EQ_EXPR, type, arg0, arg1));
- case LE_EXPR:
- arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0);
- return fold (build2 (NE_EXPR, type, arg0, arg1));
- default:
- break;
- }
- else if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1)
- == min_hi
- && TREE_INT_CST_LOW (arg1) == min_lo)
- switch (code)
- {
- case LT_EXPR:
- return omit_one_operand (type, integer_zero_node, arg0);
-
- case LE_EXPR:
- return fold (build2 (EQ_EXPR, type, arg0, arg1));
-
- case GE_EXPR:
- return omit_one_operand (type, integer_one_node, arg0);
-
- case GT_EXPR:
- return fold (build2 (NE_EXPR, type, arg0, arg1));
-
- default:
- break;
- }
- else if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1)
- == min_hi
- && TREE_INT_CST_LOW (arg1) == min_lo + 1)
- switch (code)
- {
- case GE_EXPR:
- arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
- return fold (build2 (NE_EXPR, type, arg0, arg1));
- case LT_EXPR:
- arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
- return fold (build2 (EQ_EXPR, type, arg0, arg1));
- default:
- break;
- }
-
- else if (!in_gimple_form
- && TREE_INT_CST_HIGH (arg1) == signed_max_hi
- && TREE_INT_CST_LOW (arg1) == signed_max_lo
- && TYPE_UNSIGNED (TREE_TYPE (arg1))
- /* signed_type does not work on pointer types. */
- && INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
- {
- /* The following case also applies to X < signed_max+1
- and X >= signed_max+1 because previous transformations. */
- if (code == LE_EXPR || code == GT_EXPR)
- {
- tree st0, st1;
- st0 = lang_hooks.types.signed_type (TREE_TYPE (arg0));
- st1 = lang_hooks.types.signed_type (TREE_TYPE (arg1));
- return fold
- (build2 (code == LE_EXPR ? GE_EXPR: LT_EXPR,
- type, fold_convert (st0, arg0),
- fold_convert (st1, integer_zero_node)));
- }
- }
- }
- }
-
- /* If this is an EQ or NE comparison of a constant with a PLUS_EXPR or
- a MINUS_EXPR of a constant, we can convert it into a comparison with
- a revised constant as long as no overflow occurs. */
- if ((code == EQ_EXPR || code == NE_EXPR)
- && TREE_CODE (arg1) == INTEGER_CST
- && (TREE_CODE (arg0) == PLUS_EXPR
- || TREE_CODE (arg0) == MINUS_EXPR)
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
- && 0 != (tem = const_binop (TREE_CODE (arg0) == PLUS_EXPR
- ? MINUS_EXPR : PLUS_EXPR,
- arg1, TREE_OPERAND (arg0, 1), 0))
- && ! TREE_CONSTANT_OVERFLOW (tem))
- return fold (build2 (code, type, TREE_OPERAND (arg0, 0), tem));
-
- /* Similarly for a NEGATE_EXPR. */
- else if ((code == EQ_EXPR || code == NE_EXPR)
- && TREE_CODE (arg0) == NEGATE_EXPR
- && TREE_CODE (arg1) == INTEGER_CST
- && 0 != (tem = negate_expr (arg1))
- && TREE_CODE (tem) == INTEGER_CST
- && ! TREE_CONSTANT_OVERFLOW (tem))
- return fold (build2 (code, type, TREE_OPERAND (arg0, 0), tem));
-
- /* If we have X - Y == 0, we can convert that to X == Y and similarly
- for !=. Don't do this for ordered comparisons due to overflow. */
- else if ((code == NE_EXPR || code == EQ_EXPR)
- && integer_zerop (arg1) && TREE_CODE (arg0) == MINUS_EXPR)
- return fold (build2 (code, type,
- TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1)));
-
- else if (TREE_CODE (TREE_TYPE (arg0)) == INTEGER_TYPE
- && TREE_CODE (arg0) == NOP_EXPR)
- {
- /* 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 (code, type, arg0, arg1);
- if (tem)
- return tem;
-
- /* Or if we are changing signedness. */
- tem = fold_sign_changed_comparison (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. */
- else if (TREE_CODE (arg1) == INTEGER_CST
- && (TREE_CODE (arg0) == MIN_EXPR
- || TREE_CODE (arg0) == MAX_EXPR)
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
- return optimize_minmax_comparison (t);
-
- /* If we are comparing an ABS_EXPR with a constant, we can
- convert all the cases into explicit comparisons, but they may
- well not be faster than doing the ABS and one comparison.
- But ABS (X) <= C is a range comparison, which becomes a subtraction
- and a comparison, and is probably faster. */
- else if (code == LE_EXPR && TREE_CODE (arg1) == INTEGER_CST
- && TREE_CODE (arg0) == ABS_EXPR
- && ! TREE_SIDE_EFFECTS (arg0)
- && (0 != (tem = negate_expr (arg1)))
- && TREE_CODE (tem) == INTEGER_CST
- && ! TREE_CONSTANT_OVERFLOW (tem))
- return fold (build2 (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. */
- else if (code == GE_EXPR
- && tree_expr_nonnegative_p (arg0)
- && (integer_zerop (arg1)
- || (! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0)))
- && real_zerop (arg1))))
- return omit_one_operand (type, integer_one_node, arg0);
-
- /* Convert ABS_EXPR<x> < 0 to false. */
- else if (code == LT_EXPR
- && tree_expr_nonnegative_p (arg0)
- && (integer_zerop (arg1) || real_zerop (arg1)))
- return omit_one_operand (type, integer_zero_node, arg0);
-
- /* Convert ABS_EXPR<x> == 0 or ABS_EXPR<x> != 0 to x == 0 or x != 0. */
- else if ((code == EQ_EXPR || code == NE_EXPR)
- && TREE_CODE (arg0) == ABS_EXPR
- && (integer_zerop (arg1) || real_zerop (arg1)))
- return fold (build2 (code, type, TREE_OPERAND (arg0, 0), arg1));
-
- /* If this is an EQ or NE comparison with zero and ARG0 is
- (1 << foo) & bar, convert it to (bar >> foo) & 1. Both require
- two operations, but the latter can be done in one less insn
- on machines that have only two-operand insns or on which a
- constant cannot be the first operand. */
- if (integer_zerop (arg1) && (code == EQ_EXPR || code == NE_EXPR)
- && TREE_CODE (arg0) == BIT_AND_EXPR)
- {
- tree arg00 = TREE_OPERAND (arg0, 0);
- tree arg01 = TREE_OPERAND (arg0, 1);
- if (TREE_CODE (arg00) == LSHIFT_EXPR
- && integer_onep (TREE_OPERAND (arg00, 0)))
- return
- fold (build2 (code, type,
- build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
- build2 (RSHIFT_EXPR, TREE_TYPE (arg00),
- arg01, TREE_OPERAND (arg00, 1)),
- fold_convert (TREE_TYPE (arg0),
- integer_one_node)),
- arg1));
- else if (TREE_CODE (TREE_OPERAND (arg0, 1)) == LSHIFT_EXPR
- && integer_onep (TREE_OPERAND (TREE_OPERAND (arg0, 1), 0)))
- return
- fold (build2 (code, type,
- build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
- build2 (RSHIFT_EXPR, TREE_TYPE (arg01),
- arg00, TREE_OPERAND (arg01, 1)),
- fold_convert (TREE_TYPE (arg0),
- integer_one_node)),
- arg1));
- }
-
- /* If this is an NE or EQ comparison of zero against the result of a
- signed MOD operation whose second operand is a power of 2, make
- the MOD operation unsigned since it is simpler and equivalent. */
- if ((code == NE_EXPR || code == EQ_EXPR)
- && integer_zerop (arg1)
- && !TYPE_UNSIGNED (TREE_TYPE (arg0))
- && (TREE_CODE (arg0) == TRUNC_MOD_EXPR
- || TREE_CODE (arg0) == CEIL_MOD_EXPR
- || TREE_CODE (arg0) == FLOOR_MOD_EXPR
- || TREE_CODE (arg0) == ROUND_MOD_EXPR)
- && integer_pow2p (TREE_OPERAND (arg0, 1)))
- {
- tree newtype = lang_hooks.types.unsigned_type (TREE_TYPE (arg0));
- tree newmod = fold (build2 (TREE_CODE (arg0), newtype,
- fold_convert (newtype,
- TREE_OPERAND (arg0, 0)),
- fold_convert (newtype,
- TREE_OPERAND (arg0, 1))));
-
- return fold (build2 (code, type, newmod,
- fold_convert (newtype, arg1)));
- }
-
- /* If this is an NE comparison of zero with an AND of one, remove the
- comparison since the AND will give the correct value. */
- if (code == NE_EXPR && integer_zerop (arg1)
- && TREE_CODE (arg0) == BIT_AND_EXPR
- && integer_onep (TREE_OPERAND (arg0, 1)))
- return fold_convert (type, arg0);
-
- /* If we have (A & C) == C where C is a power of 2, convert this into
- (A & C) != 0. Similarly for NE_EXPR. */
- if ((code == EQ_EXPR || code == NE_EXPR)
- && TREE_CODE (arg0) == BIT_AND_EXPR
- && integer_pow2p (TREE_OPERAND (arg0, 1))
- && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
- return fold (build2 (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
- arg0, fold_convert (TREE_TYPE (arg0),
- integer_zero_node)));
-
- /* If we have (A & C) != 0 or (A & C) == 0 and C is a power of
- 2, then fold the expression into shifts and logical operations. */
- tem = fold_single_bit_test (code, arg0, arg1, type);
- if (tem)
- return tem;
-
- /* If we have (A & C) == D where D & ~C != 0, convert this into 0.
- Similarly for NE_EXPR. */
- if ((code == EQ_EXPR || code == NE_EXPR)
- && TREE_CODE (arg0) == BIT_AND_EXPR
- && TREE_CODE (arg1) == INTEGER_CST
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
- {
- tree notc = fold (build1 (BIT_NOT_EXPR,
- TREE_TYPE (TREE_OPERAND (arg0, 1)),
- TREE_OPERAND (arg0, 1)));
- tree dandnotc = fold (build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
- arg1, notc));
- tree rslt = code == EQ_EXPR ? integer_zero_node : integer_one_node;
- if (integer_nonzerop (dandnotc))
- return omit_one_operand (type, rslt, arg0);
- }
-
- /* If we have (A | C) == D where C & ~D != 0, convert this into 0.
- Similarly for NE_EXPR. */
- if ((code == EQ_EXPR || code == NE_EXPR)
- && TREE_CODE (arg0) == BIT_IOR_EXPR
- && TREE_CODE (arg1) == INTEGER_CST
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
- {
- tree notd = fold (build1 (BIT_NOT_EXPR, TREE_TYPE (arg1), arg1));
- tree candnotd = fold (build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
- TREE_OPERAND (arg0, 1), notd));
- tree rslt = code == EQ_EXPR ? integer_zero_node : integer_one_node;
- if (integer_nonzerop (candnotd))
- return omit_one_operand (type, rslt, arg0);
- }
-
- /* If X is unsigned, convert X < (1 << Y) into X >> Y == 0
- and similarly for >= into !=. */
- if ((code == LT_EXPR || code == GE_EXPR)
- && TYPE_UNSIGNED (TREE_TYPE (arg0))
- && TREE_CODE (arg1) == LSHIFT_EXPR
- && integer_onep (TREE_OPERAND (arg1, 0)))
- return build2 (code == LT_EXPR ? EQ_EXPR : NE_EXPR, type,
- build2 (RSHIFT_EXPR, TREE_TYPE (arg0), arg0,
- TREE_OPERAND (arg1, 1)),
- fold_convert (TREE_TYPE (arg0), integer_zero_node));
-
- else if ((code == LT_EXPR || code == GE_EXPR)
- && TYPE_UNSIGNED (TREE_TYPE (arg0))
- && (TREE_CODE (arg1) == NOP_EXPR
- || TREE_CODE (arg1) == CONVERT_EXPR)
- && TREE_CODE (TREE_OPERAND (arg1, 0)) == LSHIFT_EXPR
- && integer_onep (TREE_OPERAND (TREE_OPERAND (arg1, 0), 0)))
- return
- build2 (code == LT_EXPR ? EQ_EXPR : NE_EXPR, type,
- fold_convert (TREE_TYPE (arg0),
- build2 (RSHIFT_EXPR, TREE_TYPE (arg0), arg0,
- TREE_OPERAND (TREE_OPERAND (arg1, 0),
- 1))),
- fold_convert (TREE_TYPE (arg0), integer_zero_node));
-
- /* 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 (TYPE_MODE (TREE_TYPE (arg0))))
- return constant_boolean_node (1, type);
- break;
-
- case GE_EXPR:
- case LE_EXPR:
- if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
- || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
- return constant_boolean_node (1, type);
- return fold (build2 (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 (TYPE_MODE (TREE_TYPE (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
- to check: the two values can either be equal, the first can be
- greater, or the second can be greater. Fold the expression for
- those three values. Since each value must be 0 or 1, we have
- eight possibilities, each of which corresponds to the constant 0
- or 1 or one of the six possible comparisons.
-
- This handles common cases like (a > b) == 0 but also handles
- expressions like ((x > y) - (y > x)) > 0, which supposedly
- occur in macroized code. */
-
- if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg0) != INTEGER_CST)
- {
- tree cval1 = 0, cval2 = 0;
- int save_p = 0;
-
- if (twoval_comparison_p (arg0, &cval1, &cval2, &save_p)
- /* Don't handle degenerate cases here; they should already
- have been handled anyway. */
- && cval1 != 0 && cval2 != 0
- && ! (TREE_CONSTANT (cval1) && TREE_CONSTANT (cval2))
- && TREE_TYPE (cval1) == TREE_TYPE (cval2)
- && INTEGRAL_TYPE_P (TREE_TYPE (cval1))
- && TYPE_MAX_VALUE (TREE_TYPE (cval1))
- && TYPE_MAX_VALUE (TREE_TYPE (cval2))
- && ! operand_equal_p (TYPE_MIN_VALUE (TREE_TYPE (cval1)),
- TYPE_MAX_VALUE (TREE_TYPE (cval2)), 0))
- {
- tree maxval = TYPE_MAX_VALUE (TREE_TYPE (cval1));
- tree minval = TYPE_MIN_VALUE (TREE_TYPE (cval1));
-
- /* We can't just pass T to eval_subst in case cval1 or cval2
- was the same as ARG1. */
-
- tree high_result
- = fold (build2 (code, type,
- eval_subst (arg0, cval1, maxval,
- cval2, minval),
- arg1));
- tree equal_result
- = fold (build2 (code, type,
- eval_subst (arg0, cval1, maxval,
- cval2, maxval),
- arg1));
- tree low_result
- = fold (build2 (code, type,
- eval_subst (arg0, cval1, minval,
- cval2, maxval),
- arg1));
-
- /* All three of these results should be 0 or 1. Confirm they
- are. Then use those values to select the proper code
- to use. */
-
- if ((integer_zerop (high_result)
- || integer_onep (high_result))
- && (integer_zerop (equal_result)
- || integer_onep (equal_result))
- && (integer_zerop (low_result)
- || integer_onep (low_result)))
- {
- /* Make a 3-bit mask with the high-order bit being the
- value for `>', the next for '=', and the low for '<'. */
- switch ((integer_onep (high_result) * 4)
- + (integer_onep (equal_result) * 2)
- + integer_onep (low_result))
- {
- case 0:
- /* Always false. */
- return omit_one_operand (type, integer_zero_node, arg0);
- case 1:
- code = LT_EXPR;
- break;
- case 2:
- code = EQ_EXPR;
- break;
- case 3:
- code = LE_EXPR;
- break;
- case 4:
- code = GT_EXPR;
- break;
- case 5:
- code = NE_EXPR;
- break;
- case 6:
- code = GE_EXPR;
- break;
- case 7:
- /* Always true. */
- return omit_one_operand (type, integer_one_node, arg0);
- }
-
- tem = build2 (code, type, cval1, cval2);
- if (save_p)
- return save_expr (tem);
- else
- return fold (tem);
- }
- }
- }
-
- /* If this is a comparison of a field, we may be able to simplify it. */
- if (((TREE_CODE (arg0) == COMPONENT_REF
- && lang_hooks.can_use_bit_fields_p ())
- || TREE_CODE (arg0) == BIT_FIELD_REF)
- && (code == EQ_EXPR || code == NE_EXPR)
- /* Handle the constant case even without -O
- to make sure the warnings are given. */
- && (optimize || TREE_CODE (arg1) == INTEGER_CST))
- {
- t1 = optimize_bit_field_compare (code, type, arg0, arg1);
- if (t1)
- return t1;
- }
-
- /* If this is a comparison of complex values and either or both sides
- are a COMPLEX_EXPR or COMPLEX_CST, it is best to split up the
- comparisons and join them with a TRUTH_ANDIF_EXPR or TRUTH_ORIF_EXPR.
- This may prevent needless evaluations. */
- if ((code == EQ_EXPR || code == NE_EXPR)
- && TREE_CODE (TREE_TYPE (arg0)) == COMPLEX_TYPE
- && (TREE_CODE (arg0) == COMPLEX_EXPR
- || TREE_CODE (arg1) == COMPLEX_EXPR
- || TREE_CODE (arg0) == COMPLEX_CST
- || TREE_CODE (arg1) == COMPLEX_CST))
- {
- tree subtype = TREE_TYPE (TREE_TYPE (arg0));
- tree real0, imag0, real1, imag1;
-
- arg0 = save_expr (arg0);
- arg1 = save_expr (arg1);
- real0 = fold (build1 (REALPART_EXPR, subtype, arg0));
- imag0 = fold (build1 (IMAGPART_EXPR, subtype, arg0));
- real1 = fold (build1 (REALPART_EXPR, subtype, arg1));
- imag1 = fold (build1 (IMAGPART_EXPR, subtype, arg1));
-
- return fold (build2 ((code == EQ_EXPR ? TRUTH_ANDIF_EXPR
- : TRUTH_ORIF_EXPR),
- type,
- fold (build2 (code, type, real0, real1)),
- fold (build2 (code, type, imag0, imag1))));
- }
-
- /* Optimize comparisons of strlen vs zero to a compare of the
- first character of the string vs zero. To wit,
- strlen(ptr) == 0 => *ptr == 0
- strlen(ptr) != 0 => *ptr != 0
- Other cases should reduce to one of these two (or a constant)
- due to the return value of strlen being unsigned. */
- if ((code == EQ_EXPR || code == NE_EXPR)
- && integer_zerop (arg1)
- && TREE_CODE (arg0) == CALL_EXPR)
- {
- tree fndecl = get_callee_fndecl (arg0);
- tree arglist;
-
- if (fndecl
- && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STRLEN
- && (arglist = TREE_OPERAND (arg0, 1))
- && TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) == POINTER_TYPE
- && ! TREE_CHAIN (arglist))
- return fold (build2 (code, type,
- build1 (INDIRECT_REF, char_type_node,
- TREE_VALUE (arglist)),
- fold_convert (char_type_node,
- integer_zero_node)));
- }
-
- /* We can fold X/C1 op C2 where C1 and C2 are integer constants
- into a single range test. */
- if ((TREE_CODE (arg0) == TRUNC_DIV_EXPR
- || TREE_CODE (arg0) == EXACT_DIV_EXPR)
- && TREE_CODE (arg1) == INTEGER_CST
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
- && !integer_zerop (TREE_OPERAND (arg0, 1))
- && !TREE_OVERFLOW (TREE_OPERAND (arg0, 1))
- && !TREE_OVERFLOW (arg1))
- {
- t1 = fold_div_compare (code, type, arg0, arg1);
- if (t1 != NULL_TREE)
- return t1;
- }
-
- if ((code == EQ_EXPR || code == NE_EXPR)
- && !TREE_SIDE_EFFECTS (arg0)
- && integer_zerop (arg1)
- && tree_expr_nonzero_p (arg0))
- return constant_boolean_node (code==NE_EXPR, type);
-
- t1 = fold_relational_const (code, type, arg0, arg1);
- return t1 == NULL_TREE ? t : t1;
-
- case UNORDERED_EXPR:
- case ORDERED_EXPR:
- case UNLT_EXPR:
- case UNLE_EXPR:
- case UNGT_EXPR:
- case UNGE_EXPR:
- case UNEQ_EXPR:
- case LTGT_EXPR:
- if (TREE_CODE (arg0) == REAL_CST && TREE_CODE (arg1) == REAL_CST)
- {
- t1 = fold_relational_const (code, type, arg0, arg1);
- if (t1 != NULL_TREE)
- return t1;
- }
-
- /* If the first operand is NaN, the result is constant. */
- if (TREE_CODE (arg0) == REAL_CST
- && REAL_VALUE_ISNAN (TREE_REAL_CST (arg0))
- && (code != LTGT_EXPR || ! flag_trapping_math))
- {
- t1 = (code == ORDERED_EXPR || code == LTGT_EXPR)
- ? integer_zero_node
- : integer_one_node;
- return omit_one_operand (type, t1, arg1);
- }
-
- /* If the second operand is NaN, the result is constant. */
- if (TREE_CODE (arg1) == REAL_CST
- && REAL_VALUE_ISNAN (TREE_REAL_CST (arg1))
- && (code != LTGT_EXPR || ! flag_trapping_math))
- {
- t1 = (code == ORDERED_EXPR || code == LTGT_EXPR)
- ? integer_zero_node
- : integer_one_node;
- return omit_one_operand (type, t1, arg0);
- }
-
- /* Simplify unordered comparison of something with itself. */
- if ((code == UNLE_EXPR || code == UNGE_EXPR || code == UNEQ_EXPR)
- && operand_equal_p (arg0, arg1, 0))
- return constant_boolean_node (1, type);
-
- if (code == LTGT_EXPR
- && !flag_trapping_math
- && operand_equal_p (arg0, arg1, 0))
- return constant_boolean_node (0, type);
-
- /* Fold (double)float1 CMP (double)float2 into float1 CMP float2. */
- {
- 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);
-
- if (TYPE_PRECISION (newtype) < TYPE_PRECISION (TREE_TYPE (arg0)))
- return fold (build2 (code, type, fold_convert (newtype, targ0),
- fold_convert (newtype, targ1)));
- }
-
- return t;
-
- case COMPOUND_EXPR:
- /* When pedantic, a compound expression can be neither an lvalue
- nor an integer constant expression. */
- if (TREE_SIDE_EFFECTS (arg0) || TREE_CONSTANT (arg1))
- return t;
- /* Don't let (0, 0) be null pointer constant. */
- tem = integer_zerop (arg1) ? build1 (NOP_EXPR, type, arg1)
- : fold_convert (type, arg1);
- return pedantic_non_lvalue (tem);
-
- case COMPLEX_EXPR:
- if (wins)
- return build_complex (type, arg0, arg1);
- return t;
-
default:
return t;
} /* switch (code) */