|| TYPE_UNSIGNED (TREE_TYPE (arg0)) == TYPE_UNSIGNED (shorter_type))
&& (TREE_TYPE (arg1_unw) == shorter_type
|| (TREE_CODE (arg1_unw) == INTEGER_CST
- && TREE_CODE (shorter_type) == INTEGER_TYPE
+ && (TREE_CODE (shorter_type) == INTEGER_TYPE
+ || TREE_CODE (shorter_type) == BOOLEAN_TYPE)
&& int_fits_type_p (arg1_unw, shorter_type))))
return fold_build2 (code, type, arg0_unw,
fold_convert (shorter_type, arg1_unw));
&& ptr_difference_const (arg0, arg1, &diff))
return build_int_cst_type (type, diff);
}
-
+
+ /* Fold &a[i] - &a[j] to i-j. */
+ if (TREE_CODE (arg0) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (arg0, 0)) == ARRAY_REF
+ && TREE_CODE (arg1) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (arg1, 0)) == ARRAY_REF)
+ {
+ tree aref0 = TREE_OPERAND (arg0, 0);
+ tree aref1 = TREE_OPERAND (arg1, 0);
+ if (operand_equal_p (TREE_OPERAND (aref0, 0),
+ TREE_OPERAND (aref1, 0), 0))
+ {
+ tree op0 = fold_convert (type, TREE_OPERAND (aref0, 1));
+ tree op1 = fold_convert (type, TREE_OPERAND (aref1, 1));
+ tree esz = array_ref_element_size (aref0);
+ tree diff = build2 (MINUS_EXPR, type, op0, op1);
+ return fold_build2 (MULT_EXPR, type, diff,
+ fold_convert (type, esz));
+
+ }
+ }
+
/* 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. */
case LT_EXPR:
case GT_EXPR:
case LE_EXPR:
- case GE_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, op1, op0);
+
+ /* bool_var != 0 becomes bool_var. */
+ if (TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE && integer_zerop (arg1)
+ && code == NE_EXPR)
+ return non_lvalue (fold_convert (type, arg0));
+
+ /* bool_var == 1 becomes bool_var. */
+ if (TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE && integer_onep (arg1)
+ && code == EQ_EXPR)
+ return non_lvalue (fold_convert (type, arg0));
/* If this is an equality comparison of the address of a non-weak
object against zero, then we know the result. */
return t1;
}
+ /* Fold a comparison of the address of COMPONENT_REFs with the same
+ type and component to a comparison of the address of the base
+ object. In short, &x->a OP &y->a to x OP y and
+ &x->a OP &y.a to x OP &y */
+ if (TREE_CODE (arg0) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (arg0, 0)) == COMPONENT_REF
+ && TREE_CODE (arg1) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (arg1, 0)) == COMPONENT_REF)
+ {
+ tree cref0 = TREE_OPERAND (arg0, 0);
+ tree cref1 = TREE_OPERAND (arg1, 0);
+ if (TREE_OPERAND (cref0, 1) == TREE_OPERAND (cref1, 1))
+ {
+ tree op0 = TREE_OPERAND (cref0, 0);
+ tree op1 = TREE_OPERAND (cref1, 0);
+ return fold_build2 (code, type,
+ build_fold_addr_expr (op0),
+ build_fold_addr_expr (op1));
+ }
+ }
+
/* 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.
return build_complex (type, arg0, arg1);
return NULL_TREE;
+ case ASSERT_EXPR:
+ /* An ASSERT_EXPR should never be passed to fold_binary. */
+ gcc_unreachable ();
+
default:
return NULL_TREE;
} /* switch (code) */
case CONST_DECL:
return fold (DECL_INITIAL (t));
- case ASSERT_EXPR:
- {
- /* Given ASSERT_EXPR <Y, COND>, return Y if COND can be folded
- to boolean_true_node. If COND folds to boolean_false_node,
- return ASSERT_EXPR <Y, 0>. Otherwise, return the original
- expression. */
- tree c = fold (ASSERT_EXPR_COND (t));
- if (c == boolean_true_node)
- return ASSERT_EXPR_VAR (t);
- else if (c == boolean_false_node)
- return build (ASSERT_EXPR, TREE_TYPE (t), ASSERT_EXPR_VAR (t), c);
- else
- return t;
- }
-
default:
return t;
} /* switch (code) */