diff options
author | kazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-03-05 18:09:17 +0000 |
---|---|---|
committer | kazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-03-05 18:09:17 +0000 |
commit | fef10b60f2ec159642c85f2aa5be6d4d5913299e (patch) | |
tree | 5462d07749e6eaf32fff4ab5a9f3241c08fcaba6 /gcc/fold-const.c | |
parent | 69e41517c264e4262d21e817e4947c8d4adbc5c6 (diff) | |
download | gcc-fef10b60f2ec159642c85f2aa5be6d4d5913299e.tar.gz |
* fold-const.c (fold_binary): New.
(fold): Call fold_binary on binary expressions.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@95938 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r-- | gcc/fold-const.c | 2617 |
1 files changed, 2617 insertions, 0 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c index df9e8a26d22..22e2ecd7bc1 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -7014,6 +7014,2621 @@ fold_unary (tree expr) } /* switch (code) */ } +/* Fold a binary expression EXPR. Return the folded expression if + folding is successful. Otherwise, return the original + expression. */ + +static tree +fold_binary (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; + int i; + + gcc_assert (IS_EXPR_CODE_CLASS (kind) + && TREE_CODE_LENGTH (code) == 2); + + for (i = 0; i < 2; 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 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) */ +} + /* Fold a ternary expression EXPR. Return the folded expression if folding is successful. Otherwise, return the original expression. */ @@ -7279,6 +9894,8 @@ fold (tree expr) { case 1: return fold_unary (expr); + case 2: + return fold_binary (expr); case 3: return fold_ternary (expr); default: |