/* Fold a constant sub-tree into a single node for C-compiler
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
This file is part of GCC.
static tree fold_relational_const (enum tree_code, tree, tree, tree);
static tree fold_convert_const (enum tree_code, tree, tree);
+/* Return EXPR_LOCATION of T if it is not UNKNOWN_LOCATION.
+ Otherwise, return LOC. */
+
+static location_t
+expr_location_or (tree t, location_t loc)
+{
+ location_t tloc = EXPR_LOCATION (t);
+ return tloc != UNKNOWN_LOCATION ? tloc : loc;
+}
/* Similar to protected_set_expr_location, but never modify x in place,
if location can and needs to be set, unshare it. */
/* Combine two integer constants ARG1 and ARG2 under operation CODE
to produce a new constant. Return NULL_TREE if we don't know how
- to evaluate CODE at compile-time.
-
- If NOTRUNC is nonzero, do not truncate the result to fit the data type. */
+ to evaluate CODE at compile-time. */
tree
-int_const_binop (enum tree_code code, const_tree arg1, const_tree arg2, int notrunc)
+int_const_binop (enum tree_code code, const_tree arg1, const_tree arg2)
{
double_int op1, op2, res, tmp;
tree t;
return NULL_TREE;
}
- if (notrunc)
- {
- t = build_int_cst_wide (TREE_TYPE (arg1), res.low, res.high);
-
- /* Propagate overflow flags ourselves. */
- if (((!uns || is_sizetype) && overflow)
- | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2))
- {
- t = copy_node (t);
- TREE_OVERFLOW (t) = 1;
- }
- }
- else
- t = force_fit_type_double (TREE_TYPE (arg1), res, 1,
- ((!uns || is_sizetype) && overflow)
- | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2));
+ t = force_fit_type_double (TREE_TYPE (arg1), res, 1,
+ ((!uns || is_sizetype) && overflow)
+ | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2));
return t;
}
STRIP_NOPS (arg2);
if (TREE_CODE (arg1) == INTEGER_CST)
- return int_const_binop (code, arg1, arg2, 0);
+ return int_const_binop (code, arg1, arg2);
if (TREE_CODE (arg1) == REAL_CST)
{
}
/* Handle general case of two integer constants. */
- return int_const_binop (code, arg0, arg1, 0);
+ return int_const_binop (code, arg0, arg1);
}
return fold_build2_loc (loc, code, type, arg0, arg1);
|| TREE_CODE (orig) == ERROR_MARK)
return error_mark_node;
- if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (orig))
- return fold_build1_loc (loc, NOP_EXPR, type, arg);
-
switch (TREE_CODE (type))
{
case POINTER_TYPE:
case VOID_TYPE:
tem = fold_ignored_result (arg);
- if (TREE_CODE (tem) == MODIFY_EXPR)
- goto fold_convert_exit;
return fold_build1_loc (loc, NOP_EXPR, type, tem);
default:
+ if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (orig))
+ return fold_build1_loc (loc, NOP_EXPR, type, arg);
gcc_unreachable ();
}
fold_convert_exit:
equal if they have no side effects. If we have two identical
expressions with side effects that should be treated the same due
to the only side effects being identical SAVE_EXPR's, that will
- be detected in the recursive calls below. */
+ be detected in the recursive calls below.
+ If we are taking an invariant address of two identical objects
+ they are necessarily equal as well. */
if (arg0 == arg1 && ! (flags & OEP_ONLY_CONST)
&& (TREE_CODE (arg0) == SAVE_EXPR
+ || (flags & OEP_CONSTANT_ADDRESS_OF)
|| (! TREE_SIDE_EFFECTS (arg0) && ! TREE_SIDE_EFFECTS (arg1))))
return 1;
case ADDR_EXPR:
return operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0),
- 0);
+ TREE_CONSTANT (arg0) && TREE_CONSTANT (arg1)
+ ? OEP_CONSTANT_ADDRESS_OF : 0);
default:
break;
}
return constant_boolean_node (integer_zerop (arg), type);
case TRUTH_AND_EXPR:
- loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 0));
- loc2 = EXPR_LOCATION (TREE_OPERAND (arg, 1));
- if (loc1 == UNKNOWN_LOCATION)
- loc1 = loc;
- if (loc2 == UNKNOWN_LOCATION)
- loc2 = loc;
+ loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
+ loc2 = expr_location_or (TREE_OPERAND (arg, 1), loc);
return build2_loc (loc, TRUTH_OR_EXPR, type,
invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
case TRUTH_OR_EXPR:
- loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 0));
- loc2 = EXPR_LOCATION (TREE_OPERAND (arg, 1));
- if (loc1 == UNKNOWN_LOCATION)
- loc1 = loc;
- if (loc2 == UNKNOWN_LOCATION)
- loc2 = loc;
+ loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
+ loc2 = expr_location_or (TREE_OPERAND (arg, 1), loc);
return build2_loc (loc, TRUTH_AND_EXPR, type,
invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
TREE_OPERAND (arg, 1));
case TRUTH_ANDIF_EXPR:
- loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 0));
- loc2 = EXPR_LOCATION (TREE_OPERAND (arg, 1));
- if (loc1 == UNKNOWN_LOCATION)
- loc1 = loc;
- if (loc2 == UNKNOWN_LOCATION)
- loc2 = loc;
+ loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
+ loc2 = expr_location_or (TREE_OPERAND (arg, 1), loc);
return build2_loc (loc, TRUTH_ORIF_EXPR, type,
invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
case TRUTH_ORIF_EXPR:
- loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 0));
- loc2 = EXPR_LOCATION (TREE_OPERAND (arg, 1));
- if (loc1 == UNKNOWN_LOCATION)
- loc1 = loc;
- if (loc2 == UNKNOWN_LOCATION)
- loc2 = loc;
+ loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
+ loc2 = expr_location_or (TREE_OPERAND (arg, 1), loc);
return build2_loc (loc, TRUTH_ANDIF_EXPR, type,
invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
tree arg1 = TREE_OPERAND (arg, 1);
tree arg2 = TREE_OPERAND (arg, 2);
- loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 1));
- loc2 = EXPR_LOCATION (TREE_OPERAND (arg, 2));
- if (loc1 == UNKNOWN_LOCATION)
- loc1 = loc;
- if (loc2 == UNKNOWN_LOCATION)
- loc2 = loc;
+ loc1 = expr_location_or (TREE_OPERAND (arg, 1), loc);
+ loc2 = expr_location_or (TREE_OPERAND (arg, 2), loc);
/* A COND_EXPR may have a throw as one operand, which
then has void type. Just leave void operands
}
case COMPOUND_EXPR:
- loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 1));
- if (loc1 == UNKNOWN_LOCATION)
- loc1 = loc;
+ loc1 = expr_location_or (TREE_OPERAND (arg, 1), loc);
return build2_loc (loc, COMPOUND_EXPR, type,
TREE_OPERAND (arg, 0),
invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 1)));
case NON_LVALUE_EXPR:
- loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 0));
- if (loc1 == UNKNOWN_LOCATION)
- loc1 = loc;
+ loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
return invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0));
CASE_CONVERT:
/* ... fall through ... */
case FLOAT_EXPR:
- loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 0));
- if (loc1 == UNKNOWN_LOCATION)
- loc1 = loc;
+ loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
return build1_loc (loc, TREE_CODE (arg), type,
invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)));
return build1_loc (loc, TRUTH_NOT_EXPR, type, arg);
case CLEANUP_POINT_EXPR:
- loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 0));
- if (loc1 == UNKNOWN_LOCATION)
- loc1 = loc;
+ loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
return build1_loc (loc, CLEANUP_POINT_EXPR, type,
invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)));
&& flag_strict_volatile_bitfields > 0)
nmode = lmode;
else
- nmode = get_best_mode (lbitsize, lbitpos,
+ nmode = get_best_mode (lbitsize, lbitpos, 0, 0,
const_p ? TYPE_ALIGN (TREE_TYPE (linner))
: MIN (TYPE_ALIGN (TREE_TYPE (linner)),
TYPE_ALIGN (TREE_TYPE (rinner))),
{
if (value != 0 && !TREE_OVERFLOW (value))
{
- low = fold_convert_loc (loc, sizetype, low);
- low = fold_build1_loc (loc, NEGATE_EXPR, sizetype, low);
+ low = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (low), low);
return build_range_check (loc, type,
- fold_build2_loc (loc, POINTER_PLUS_EXPR,
- etype, exp, low),
+ fold_build_pointer_plus_loc (loc, exp, low),
1, build_int_cst (etype, 0), value);
}
return 0;
if ((lhs == 0 || rhs == 0 || operand_equal_p (lhs, rhs, 0))
&& merge_ranges (&in_p, &low, &high, in0_p, low0, high0,
in1_p, low1, high1)
- && 0 != (tem = (build_range_check (UNKNOWN_LOCATION, type,
+ && 0 != (tem = (build_range_check (loc, type,
lhs != 0 ? lhs
: rhs != 0 ? rhs : integer_zero_node,
in_p, low, high))))
? TRUTH_AND_EXPR : TRUTH_OR_EXPR,
type, op0, op1);
- else if (lang_hooks.decls.global_bindings_p () == 0
- && ! CONTAINS_PLACEHOLDER_P (lhs))
+ else if (!lang_hooks.decls.global_bindings_p ()
+ && !CONTAINS_PLACEHOLDER_P (lhs))
{
tree common = save_expr (lhs);
to be relative to a field of that size. */
first_bit = MIN (ll_bitpos, rl_bitpos);
end_bit = MAX (ll_bitpos + ll_bitsize, rl_bitpos + rl_bitsize);
- lnmode = get_best_mode (end_bit - first_bit, first_bit,
+ lnmode = get_best_mode (end_bit - first_bit, first_bit, 0, 0,
TYPE_ALIGN (TREE_TYPE (ll_inner)), word_mode,
volatilep);
if (lnmode == VOIDmode)
first_bit = MIN (lr_bitpos, rr_bitpos);
end_bit = MAX (lr_bitpos + lr_bitsize, rr_bitpos + rr_bitsize);
- rnmode = get_best_mode (end_bit - first_bit, first_bit,
+ rnmode = get_best_mode (end_bit - first_bit, first_bit, 0, 0,
TYPE_ALIGN (TREE_TYPE (lr_inner)), word_mode,
volatilep);
if (rnmode == VOIDmode)
/* If these are the same operation types, we can associate them
assuming no overflow. */
- if (tcode == code
- && 0 != (t1 = int_const_binop (MULT_EXPR,
- fold_convert (ctype, op1),
- fold_convert (ctype, c), 1))
- && 0 != (t1 = force_fit_type_double (ctype, tree_to_double_int (t1),
- (TYPE_UNSIGNED (ctype)
- && tcode != MULT_EXPR) ? -1 : 1,
- TREE_OVERFLOW (t1)))
- && !TREE_OVERFLOW (t1))
- return fold_build2 (tcode, ctype, fold_convert (ctype, op0), t1);
+ if (tcode == code)
+ {
+ double_int mul;
+ int overflow_p;
+ mul = double_int_mul_with_sign
+ (double_int_ext
+ (tree_to_double_int (op1),
+ TYPE_PRECISION (ctype), TYPE_UNSIGNED (ctype)),
+ double_int_ext
+ (tree_to_double_int (c),
+ TYPE_PRECISION (ctype), TYPE_UNSIGNED (ctype)),
+ false, &overflow_p);
+ overflow_p = (((!TYPE_UNSIGNED (ctype)
+ || (TREE_CODE (ctype) == INTEGER_TYPE
+ && TYPE_IS_SIZETYPE (ctype)))
+ && overflow_p)
+ | TREE_OVERFLOW (c) | TREE_OVERFLOW (op1));
+ if (!double_int_fits_to_tree_p (ctype, mul)
+ && ((TYPE_UNSIGNED (ctype) && tcode != MULT_EXPR)
+ || !TYPE_UNSIGNED (ctype)
+ || (TREE_CODE (ctype) == INTEGER_TYPE
+ && TYPE_IS_SIZETYPE (ctype))))
+ overflow_p = 1;
+ if (!overflow_p)
+ return fold_build2 (tcode, ctype, fold_convert (ctype, op0),
+ double_int_to_tree (ctype, mul));
+ }
/* If these operations "cancel" each other, we have the main
optimizations of this pass, which occur when either constant is a
}
\f
/* Return a node which has the indicated constant VALUE (either 0 or
- 1), and is of the indicated TYPE. */
+ 1 for scalars or {-1,-1,..} or {0,0,...} for vectors),
+ and is of the indicated TYPE. */
tree
-constant_boolean_node (int value, tree type)
+constant_boolean_node (bool value, tree type)
{
if (type == integer_type_node)
return value ? integer_one_node : integer_zero_node;
else if (type == boolean_type_node)
return value ? boolean_true_node : boolean_false_node;
+ else if (TREE_CODE (type) == VECTOR_TYPE)
+ return build_vector_from_val (type,
+ build_int_cst (TREE_TYPE (type),
+ value ? -1 : 0));
else
- return build_int_cst (type, value);
+ return fold_convert (type, value ? integer_one_node : integer_zero_node);
}
build_real (TREE_TYPE (arg), dconst0));
/* sqrt(x) < y is x >= 0 && x != +Inf, when y is large. */
- if (lang_hooks.decls.global_bindings_p () != 0
- || CONTAINS_PLACEHOLDER_P (arg))
- return NULL_TREE;
-
arg = save_expr (arg);
return fold_build2_loc (loc, TRUTH_ANDIF_EXPR, type,
fold_build2_loc (loc, GE_EXPR, type, arg,
build_real (TREE_TYPE (arg), c2));
/* sqrt(x) < c is the same as x >= 0 && x < c*c. */
- if (lang_hooks.decls.global_bindings_p () == 0
- && ! CONTAINS_PLACEHOLDER_P (arg))
- {
- arg = save_expr (arg);
- return fold_build2_loc (loc, TRUTH_ANDIF_EXPR, type,
+ arg = save_expr (arg);
+ return fold_build2_loc (loc, TRUTH_ANDIF_EXPR, type,
fold_build2_loc (loc, GE_EXPR, type, arg,
build_real (TREE_TYPE (arg),
dconst0)),
fold_build2_loc (loc, code, type, arg,
build_real (TREE_TYPE (arg),
c2)));
- }
}
}
return omit_one_operand_loc (loc, type, integer_one_node, arg0);
/* x <= +Inf is the same as x == x, i.e. isfinite(x). */
- if (lang_hooks.decls.global_bindings_p () == 0
- && ! CONTAINS_PLACEHOLDER_P (arg0))
- {
- arg0 = save_expr (arg0);
- return fold_build2_loc (loc, EQ_EXPR, type, arg0, arg0);
- }
- break;
+ arg0 = save_expr (arg0);
+ return fold_build2_loc (loc, EQ_EXPR, type, arg0, arg0);
case EQ_EXPR:
case GE_EXPR:
int overflow;
/* We have to do this the hard way to detect unsigned overflow.
- prod = int_const_binop (MULT_EXPR, arg01, arg1, 0); */
+ prod = int_const_binop (MULT_EXPR, arg01, arg1); */
overflow = mul_double_with_sign (TREE_INT_CST_LOW (arg01),
TREE_INT_CST_HIGH (arg01),
TREE_INT_CST_LOW (arg1),
if (unsigned_p)
{
tmp = int_const_binop (MINUS_EXPR, arg01,
- build_int_cst (TREE_TYPE (arg01), 1), 0);
+ build_int_cst (TREE_TYPE (arg01), 1));
lo = prod;
- /* Likewise hi = int_const_binop (PLUS_EXPR, prod, tmp, 0). */
+ /* Likewise hi = int_const_binop (PLUS_EXPR, prod, tmp). */
overflow = add_double_with_sign (TREE_INT_CST_LOW (prod),
TREE_INT_CST_HIGH (prod),
TREE_INT_CST_LOW (tmp),
else if (tree_int_cst_sgn (arg01) >= 0)
{
tmp = int_const_binop (MINUS_EXPR, arg01,
- build_int_cst (TREE_TYPE (arg01), 1), 0);
+ build_int_cst (TREE_TYPE (arg01), 1));
switch (tree_int_cst_sgn (arg1))
{
case -1:
neg_overflow = true;
- lo = int_const_binop (MINUS_EXPR, prod, tmp, 0);
+ lo = int_const_binop (MINUS_EXPR, prod, tmp);
hi = prod;
break;
break;
case 1:
- hi = int_const_binop (PLUS_EXPR, prod, tmp, 0);
+ hi = int_const_binop (PLUS_EXPR, prod, tmp);
lo = prod;
break;
code = swap_tree_comparison (code);
tmp = int_const_binop (PLUS_EXPR, arg01,
- build_int_cst (TREE_TYPE (arg01), 1), 0);
+ build_int_cst (TREE_TYPE (arg01), 1));
switch (tree_int_cst_sgn (arg1))
{
case -1:
- hi = int_const_binop (MINUS_EXPR, prod, tmp, 0);
+ hi = int_const_binop (MINUS_EXPR, prod, tmp);
lo = prod;
break;
case 1:
neg_overflow = true;
- lo = int_const_binop (PLUS_EXPR, prod, tmp, 0);
+ lo = int_const_binop (PLUS_EXPR, prod, tmp);
hi = prod;
break;
int11 = TREE_INT_CST_LOW (arg11);
/* Move min of absolute values to int11. */
- if ((int01 >= 0 ? int01 : -int01)
- < (int11 >= 0 ? int11 : -int11))
+ if (absu_hwi (int01) < absu_hwi (int11))
{
tmp = int01, int01 = int11, int11 = tmp;
alt0 = arg00, arg00 = arg10, arg10 = alt0;
else
maybe_same = arg11;
- if (exact_log2 (abs (int11)) > 0 && int01 % int11 == 0
+ if (exact_log2 (absu_hwi (int11)) > 0 && int01 % int11 == 0
/* The remainder should not be a constant, otherwise we
end up folding i * 4 + 2 to (i * 2 + 1) * 2 which has
increased the number of multiplications necessary. */
if (arg0)
{
if (CONVERT_EXPR_CODE_P (code)
- || code == FLOAT_EXPR || code == ABS_EXPR)
+ || code == FLOAT_EXPR || code == ABS_EXPR || code == NEGATE_EXPR)
{
/* Don't use STRIP_NOPS, because signedness of argument type
matters. */
0)));
return tem;
}
- else if (COMPARISON_CLASS_P (arg0))
- {
- if (TREE_CODE (type) == BOOLEAN_TYPE)
- {
- arg0 = copy_node (arg0);
- TREE_TYPE (arg0) = type;
- return arg0;
- }
- else if (TREE_CODE (type) != INTEGER_TYPE)
- return fold_build3_loc (loc, COND_EXPR, type, arg0,
- fold_build1_loc (loc, code, type,
- integer_one_node),
- fold_build1_loc (loc, code, type,
- integer_zero_node));
- }
}
switch (code)
if (TREE_TYPE (op0) == type)
return op0;
- /* If we have (type) (a CMP b) and type is an integral type, return
- new expression involving the new type. */
- if (COMPARISON_CLASS_P (op0) && INTEGRAL_TYPE_P (type))
- return fold_build2_loc (loc, TREE_CODE (op0), type, TREE_OPERAND (op0, 0),
- TREE_OPERAND (op0, 1));
+ if (COMPARISON_CLASS_P (op0))
+ {
+ /* If we have (type) (a CMP b) and type is an integral type, return
+ new expression involving the new type. Canonicalize
+ (type) (a CMP b) to (a CMP b) ? (type) true : (type) false for
+ non-integral type.
+ Do not fold the result as that would not simplify further, also
+ folding again results in recursions. */
+ if (TREE_CODE (type) == BOOLEAN_TYPE)
+ return build2_loc (loc, TREE_CODE (op0), type,
+ TREE_OPERAND (op0, 0),
+ TREE_OPERAND (op0, 1));
+ else if (!INTEGRAL_TYPE_P (type))
+ return build3_loc (loc, COND_EXPR, type, op0,
+ constant_boolean_node (true, type),
+ constant_boolean_node (false, type));
+ }
/* Handle cases of two conversions in a row. */
if (CONVERT_EXPR_P (op0))
tree arg00 = TREE_OPERAND (arg0, 0);
tree arg01 = TREE_OPERAND (arg0, 1);
- return fold_build2_loc (loc,
- TREE_CODE (arg0), type,
- fold_convert_loc (loc, type, arg00),
- fold_convert_loc (loc, sizetype, arg01));
+ return fold_build_pointer_plus_loc
+ (loc, fold_convert_loc (loc, type, arg00), arg01);
}
/* Convert (T1)(~(T2)X) into ~(T1)X if T1 and T2 are integral types
return res;
}
+/* Fold a binary bitwise/truth expression of code CODE and type TYPE with
+ operands OP0 and OP1. LOC is the location of the resulting expression.
+ ARG0 and ARG1 are the NOP_STRIPed results of OP0 and OP1.
+ Return the folded expression if folding is successful. Otherwise,
+ return NULL_TREE. */
+static tree
+fold_truth_andor (location_t loc, enum tree_code code, tree type,
+ tree arg0, tree arg1, tree op0, tree op1)
+{
+ tree tem;
+
+ /* We only do these simplifications if we are optimizing. */
+ if (!optimize)
+ return NULL_TREE;
+
+ /* 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_loc (loc, TREE_CODE (arg0), type, a00,
+ fold_build2_loc (loc, code, type, a01, a11));
+ else if (commutative && operand_equal_p (a00, a11, 0))
+ return fold_build2_loc (loc, TREE_CODE (arg0), type, a00,
+ fold_build2_loc (loc, code, type, a01, a10));
+ else if (commutative && operand_equal_p (a01, a10, 0))
+ return fold_build2_loc (loc, TREE_CODE (arg0), type, a01,
+ fold_build2_loc (loc, 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_loc (loc, TREE_CODE (arg0), type,
+ fold_build2_loc (loc, code, type, a00, a10),
+ a01);
+ }
+
+ /* See if we can build a range comparison. */
+ if (0 != (tem = fold_range_test (loc, code, type, op0, op1)))
+ return tem;
+
+ if ((code == TRUTH_ANDIF_EXPR && TREE_CODE (arg0) == TRUTH_ORIF_EXPR)
+ || (code == TRUTH_ORIF_EXPR && TREE_CODE (arg0) == TRUTH_ANDIF_EXPR))
+ {
+ tem = merge_truthop_with_opposite_arm (loc, arg0, arg1, true);
+ if (tem)
+ return fold_build2_loc (loc, code, type, tem, arg1);
+ }
+
+ if ((code == TRUTH_ANDIF_EXPR && TREE_CODE (arg1) == TRUTH_ORIF_EXPR)
+ || (code == TRUTH_ORIF_EXPR && TREE_CODE (arg1) == TRUTH_ANDIF_EXPR))
+ {
+ tem = merge_truthop_with_opposite_arm (loc, arg1, arg0, false);
+ if (tem)
+ return fold_build2_loc (loc, code, type, arg0, 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 (loc, code, type,
+ TREE_OPERAND (arg0, 1), arg1)))
+ return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), tem);
+
+ if ((tem = fold_truthop (loc, code, type, arg0, arg1)) != 0)
+ return tem;
+
+ return NULL_TREE;
+}
+
/* Fold a binary expression of code CODE and type TYPE with operands
OP0 and OP1, containing either a MIN-MAX or a MAX-MIN combination.
Return the folded expression if folding is successful. Otherwise,
return NULL_TREE;
t = int_const_binop (sgn0 == -1 ? PLUS_EXPR : MINUS_EXPR,
- cst0, build_int_cst (TREE_TYPE (cst0), 1), 0);
+ cst0, build_int_cst (TREE_TYPE (cst0), 1));
if (code0 != INTEGER_CST)
t = fold_build2_loc (loc, code0, TREE_TYPE (arg0), TREE_OPERAND (arg0, 0), t);
+ t = fold_convert (TREE_TYPE (arg1), t);
/* If swapping might yield to a more canonical form, do so. */
if (swap)
&& (TREE_CODE (lhs) != INTEGER_CST
|| !TREE_OVERFLOW (lhs)))
{
- fold_overflow_warning ("assuming signed overflow does not occur "
- "when changing X +- C1 cmp C2 to "
- "X cmp C1 +- C2",
- WARN_STRICT_OVERFLOW_COMPARISON);
+ if (code != EQ_EXPR && code != NE_EXPR)
+ fold_overflow_warning ("assuming signed overflow does not occur "
+ "when changing X +- C1 cmp C2 to "
+ "X cmp C1 +- C2",
+ WARN_STRICT_OVERFLOW_COMPARISON);
return fold_build2_loc (loc, code, type, variable, lhs);
}
}
&& operand_equal_p (offset0, offset1, 0)))
&& (code == EQ_EXPR
|| code == NE_EXPR
+ || (indirect_base0 && DECL_P (base0))
|| POINTER_TYPE_OVERFLOW_UNDEFINED))
{
6.5.6/8 and /9 with respect to the signed ptrdiff_t. */
else if (bitpos0 == bitpos1
&& ((code == EQ_EXPR || code == NE_EXPR)
+ || (indirect_base0 && DECL_P (base0))
|| POINTER_TYPE_OVERFLOW_UNDEFINED))
{
/* By converting to signed size type we cover middle-end pointer
of lower absolute value than before. */
cst = int_const_binop (TREE_CODE (arg0) == TREE_CODE (arg1)
? MINUS_EXPR : PLUS_EXPR,
- const2, const1, 0);
+ const2, const1);
if (!TREE_OVERFLOW (cst)
&& tree_int_cst_compare (const2, cst) == tree_int_cst_sgn (const2))
{
cst = int_const_binop (TREE_CODE (arg0) == TREE_CODE (arg1)
? MINUS_EXPR : PLUS_EXPR,
- const1, const2, 0);
+ const1, const2);
if (!TREE_OVERFLOW (cst)
&& tree_int_cst_compare (const1, cst) == tree_int_cst_sgn (const1))
{
return fold_build2_loc (loc, cmp_code, type, variable1, const2);
}
- tem = maybe_canonicalize_comparison (loc, code, type, op0, op1);
+ tem = maybe_canonicalize_comparison (loc, code, type, arg0, arg1);
if (tem)
return tem;
code = TREE_CODE (expr);
if (code == ADDR_EXPR)
{
- expr = TREE_OPERAND (expr, 0);
- if (handled_component_p (expr))
- {
- HOST_WIDE_INT bitsize, bitpos;
- tree offset;
- enum machine_mode mode;
- int unsignedp, volatilep;
-
- expr = get_inner_reference (expr, &bitsize, &bitpos, &offset,
- &mode, &unsignedp, &volatilep, false);
- *residue = bitpos / BITS_PER_UNIT;
- if (offset)
- {
- if (TREE_CODE (offset) == INTEGER_CST)
- *residue += TREE_INT_CST_LOW (offset);
- else
- /* We don't handle more complicated offset expressions. */
- return 1;
- }
- }
-
- if (DECL_P (expr)
- && (allow_func_align || TREE_CODE (expr) != FUNCTION_DECL))
- return DECL_ALIGN_UNIT (expr);
+ unsigned int bitalign;
+ bitalign = get_object_alignment_1 (TREE_OPERAND (expr, 0), residue);
+ *residue /= BITS_PER_UNIT;
+ return bitalign / BITS_PER_UNIT;
}
else if (code == POINTER_PLUS_EXPR)
{
}
}
- /* If we get here, we were unable to determine anything useful about the
- expression. */
- return 1;
+ /* If we get here, we were unable to determine anything useful about the
+ expression. */
+ return 1;
}
return fold_build2 (MEM_REF, type,
TREE_OPERAND (iref, 0),
int_const_binop (PLUS_EXPR, arg1,
- TREE_OPERAND (iref, 1), 0));
+ TREE_OPERAND (iref, 1)));
}
/* MEM[&a.b, CST2] -> MEM[&a, offsetof (a, b) + CST2]. */
return fold_build2 (MEM_REF, type,
build_fold_addr_expr (base),
int_const_binop (PLUS_EXPR, arg1,
- size_int (coffset), 0));
+ size_int (coffset)));
}
return NULL_TREE;
fold_convert_loc (loc, sizetype,
arg0)));
- /* index +p PTR -> PTR +p index */
- if (POINTER_TYPE_P (TREE_TYPE (arg1))
- && INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
- return fold_build2_loc (loc, POINTER_PLUS_EXPR, type,
- fold_convert_loc (loc, type, arg1),
- fold_convert_loc (loc, sizetype, arg0));
-
/* (PTR +p B) +p A -> PTR +p (B + A) */
if (TREE_CODE (arg0) == POINTER_PLUS_EXPR)
{
inner = fold_build2_loc (loc, PLUS_EXPR, sizetype,
arg01, fold_convert_loc (loc, sizetype, arg1));
return fold_convert_loc (loc, type,
- fold_build2_loc (loc, POINTER_PLUS_EXPR,
- TREE_TYPE (arg00),
- arg00, inner));
+ fold_build_pointer_plus_loc (loc,
+ arg00, inner));
}
/* PTR_CST +p CST -> CST1 */
/* 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))
+ if (TYPE_OVERFLOW_WRAPS (type)
+ && (((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;
}
/* Optimize x*x as pow(x,2.0), which is expanded as x*x. */
- if (optimize_function_for_speed_p (cfun)
+ if (!in_gimple_form
+ && optimize_function_for_speed_p (cfun)
&& operand_equal_p (arg0, arg1, 0))
{
tree powfn = mathfn_built_in (type, BUILT_IN_POW);
&& reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
return omit_one_operand_loc (loc, type, arg0, TREE_OPERAND (arg1, 0));
+ /* (X & ~Y) | (~X & Y) is X ^ Y */
+ if (TREE_CODE (arg0) == BIT_AND_EXPR
+ && TREE_CODE (arg1) == BIT_AND_EXPR)
+ {
+ tree a0, a1, l0, l1, n0, n1;
+
+ a0 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 0));
+ a1 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 1));
+
+ l0 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
+ l1 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
+
+ n0 = fold_build1_loc (loc, BIT_NOT_EXPR, type, l0);
+ n1 = fold_build1_loc (loc, BIT_NOT_EXPR, type, l1);
+
+ if ((operand_equal_p (n0, a0, 0)
+ && operand_equal_p (n1, a1, 0))
+ || (operand_equal_p (n0, a1, 0)
+ && operand_equal_p (n1, a0, 0)))
+ return fold_build2_loc (loc, BIT_XOR_EXPR, type, l0, n1);
+ }
+
t1 = distribute_bit_expr (loc, code, type, arg0, arg1);
if (t1 != NULL_TREE)
return t1;
if (operand_equal_p (arg0, arg1, 0))
return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
- /* ~X & X is always zero. */
- if (TREE_CODE (arg0) == BIT_NOT_EXPR
+ /* ~X & X, (X == 0) & X, and !X & X are always zero. */
+ if ((TREE_CODE (arg0) == BIT_NOT_EXPR
+ || TREE_CODE (arg0) == TRUTH_NOT_EXPR
+ || (TREE_CODE (arg0) == EQ_EXPR
+ && integer_zerop (TREE_OPERAND (arg0, 1))))
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
return omit_one_operand_loc (loc, type, integer_zero_node, arg1);
- /* X & ~X is always zero. */
- if (TREE_CODE (arg1) == BIT_NOT_EXPR
+ /* X & ~X , X & (X == 0), and X & !X are always zero. */
+ if ((TREE_CODE (arg1) == BIT_NOT_EXPR
+ || TREE_CODE (arg1) == TRUTH_NOT_EXPR
+ || (TREE_CODE (arg1) == EQ_EXPR
+ && integer_zerop (TREE_OPERAND (arg1, 1))))
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
build_int_cst (TREE_TYPE (tem), 1)),
build_int_cst (TREE_TYPE (tem), 0));
}
+ /* Fold !X & 1 as X == 0. */
+ if (TREE_CODE (arg0) == TRUTH_NOT_EXPR
+ && integer_onep (arg1))
+ {
+ tem = TREE_OPERAND (arg0, 0);
+ return fold_build2_loc (loc, EQ_EXPR, type, tem,
+ build_int_cst (TREE_TYPE (tem), 0));
+ }
/* Fold (X ^ Y) & Y as ~X & Y. */
if (TREE_CODE (arg0) == BIT_XOR_EXPR
return fold_build2_loc (loc, RSHIFT_EXPR, type,
TREE_OPERAND (arg0, 0),
- build_int_cst (NULL_TREE, pow2));
+ build_int_cst (integer_type_node, pow2));
}
}
WARN_STRICT_OVERFLOW_MISC);
sh_cnt = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (sh_cnt),
- sh_cnt, build_int_cst (NULL_TREE, pow2));
+ sh_cnt,
+ build_int_cst (TREE_TYPE (sh_cnt),
+ pow2));
return fold_build2_loc (loc, RSHIFT_EXPR, type,
fold_convert_loc (loc, type, arg0), sh_cnt);
}
arg00 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
lshift = build_int_cst (type, -1);
- lshift = int_const_binop (code, lshift, arg1, 0);
+ lshift = int_const_binop (code, lshift, arg1);
return fold_build2_loc (loc, BIT_AND_EXPR, type, arg00, lshift);
}
return fold_build2_loc (loc, code, type, arg0, tem);
}
- truth_andor:
- /* We only do these simplifications if we are optimizing. */
- if (!optimize)
- return NULL_TREE;
-
- /* 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_loc (loc, TREE_CODE (arg0), type, a00,
- fold_build2_loc (loc, code, type, a01, a11));
- else if (commutative && operand_equal_p (a00, a11, 0))
- return fold_build2_loc (loc, TREE_CODE (arg0), type, a00,
- fold_build2_loc (loc, code, type, a01, a10));
- else if (commutative && operand_equal_p (a01, a10, 0))
- return fold_build2_loc (loc, TREE_CODE (arg0), type, a01,
- fold_build2_loc (loc, 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_loc (loc, TREE_CODE (arg0), type,
- fold_build2_loc (loc, code, type, a00, a10),
- a01);
- }
-
- /* See if we can build a range comparison. */
- if (0 != (tem = fold_range_test (loc, code, type, op0, op1)))
- return tem;
-
- if ((code == TRUTH_ANDIF_EXPR && TREE_CODE (arg0) == TRUTH_ORIF_EXPR)
- || (code == TRUTH_ORIF_EXPR && TREE_CODE (arg0) == TRUTH_ANDIF_EXPR))
- {
- tem = merge_truthop_with_opposite_arm (loc, arg0, arg1, true);
- if (tem)
- return fold_build2_loc (loc, code, type, tem, arg1);
- }
-
- if ((code == TRUTH_ANDIF_EXPR && TREE_CODE (arg1) == TRUTH_ORIF_EXPR)
- || (code == TRUTH_ORIF_EXPR && TREE_CODE (arg1) == TRUTH_ANDIF_EXPR))
- {
- tem = merge_truthop_with_opposite_arm (loc, arg1, arg0, false);
- if (tem)
- return fold_build2_loc (loc, code, type, arg0, 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 (loc, code, type,
- TREE_OPERAND (arg0, 1), arg1)))
- return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), tem);
-
- if ((tem = fold_truthop (loc, code, type, arg0, arg1)) != 0)
- return tem;
+ if ((tem = fold_truth_andor (loc, code, type, arg0, arg1, op0, op1))
+ != NULL_TREE)
+ return tem;
return NULL_TREE;
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
return omit_one_operand_loc (loc, type, integer_one_node, arg0);
- goto truth_andor;
+ /* (X && !Y) || (!X && Y) is X ^ Y */
+ if (TREE_CODE (arg0) == TRUTH_AND_EXPR
+ && TREE_CODE (arg1) == TRUTH_AND_EXPR)
+ {
+ tree a0, a1, l0, l1, n0, n1;
+
+ a0 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 0));
+ a1 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 1));
+
+ l0 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
+ l1 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
+
+ n0 = fold_build1_loc (loc, TRUTH_NOT_EXPR, type, l0);
+ n1 = fold_build1_loc (loc, TRUTH_NOT_EXPR, type, l1);
+
+ if ((operand_equal_p (n0, a0, 0)
+ && operand_equal_p (n1, a1, 0))
+ || (operand_equal_p (n0, a1, 0)
+ && operand_equal_p (n1, a0, 0)))
+ return fold_build2_loc (loc, TRUTH_XOR_EXPR, type, l0, n1);
+ }
+
+ if ((tem = fold_truth_andor (loc, code, type, arg0, arg1, op0, op1))
+ != NULL_TREE)
+ return tem;
+
+ return NULL_TREE;
case TRUTH_XOR_EXPR:
/* If the second arg is constant zero, drop it. */
case EQ_EXPR:
case NE_EXPR:
+ STRIP_NOPS (arg0);
+ STRIP_NOPS (arg1);
+
tem = fold_comparison (loc, code, type, op0, op1);
if (tem != NULL_TREE)
return tem;
/* bool_var != 1 becomes !bool_var. */
if (TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE && integer_onep (arg1)
&& code == NE_EXPR)
- return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
- fold_convert_loc (loc, type, arg0));
+ return fold_convert_loc (loc, type,
+ fold_build1_loc (loc, TRUTH_NOT_EXPR,
+ TREE_TYPE (arg0), arg0));
/* bool_var == 0 becomes !bool_var. */
if (TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE && integer_zerop (arg1)
&& code == EQ_EXPR)
- return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
- fold_convert_loc (loc, type, arg0));
+ return fold_convert_loc (loc, type,
+ fold_build1_loc (loc, TRUTH_NOT_EXPR,
+ TREE_TYPE (arg0), arg0));
/* !exp != 0 becomes !exp */
if (TREE_CODE (arg0) == TRUTH_NOT_EXPR && integer_zerop (arg1)
/* Similarly for a NEGATE_EXPR. */
if (TREE_CODE (arg0) == NEGATE_EXPR
&& TREE_CODE (arg1) == INTEGER_CST
- && 0 != (tem = negate_expr (arg1))
+ && 0 != (tem = negate_expr (fold_convert_loc (loc, TREE_TYPE (arg0),
+ arg1)))
&& TREE_CODE (tem) == INTEGER_CST
&& !TREE_OVERFLOW (tem))
return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), tem);
if ((TREE_CODE (arg0) == PLUS_EXPR
|| TREE_CODE (arg0) == POINTER_PLUS_EXPR
|| TREE_CODE (arg0) == MINUS_EXPR)
- && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
+ && operand_equal_p (tree_strip_nop_conversions (TREE_OPERAND (arg0,
+ 0)),
+ arg1, 0)
&& (INTEGRAL_TYPE_P (TREE_TYPE (arg0))
|| POINTER_TYPE_P (TREE_TYPE (arg0))))
{
/* Transform comparisons of the form C - X CMP X if C % 2 == 1. */
if (TREE_CODE (arg0) == MINUS_EXPR
&& TREE_CODE (TREE_OPERAND (arg0, 0)) == INTEGER_CST
- && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0)
+ && operand_equal_p (tree_strip_nop_conversions (TREE_OPERAND (arg0,
+ 1)),
+ arg1, 0)
&& (TREE_INT_CST_LOW (TREE_OPERAND (arg0, 0)) & 1) == 1)
{
return omit_two_operands_loc (loc, type,
{
tem = fold_build2_loc (loc, LSHIFT_EXPR, itype, arg01, arg001);
tem = fold_build2_loc (loc, BIT_AND_EXPR, itype, arg000, tem);
- return fold_build2_loc (loc, code, type, tem, arg1);
+ return fold_build2_loc (loc, code, type, tem,
+ fold_convert_loc (loc, itype, arg1));
}
/* Otherwise, for signed (arithmetic) shifts,
((X >> C1) & C2) != 0 is rewritten as X < 0, and
}
}
- /* 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_loc (loc, 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 (TREE_CODE (arg0) == BIT_AND_EXPR
tree notc = fold_build1_loc (loc, BIT_NOT_EXPR,
TREE_TYPE (TREE_OPERAND (arg0, 1)),
TREE_OPERAND (arg0, 1));
- tree dandnotc = fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (arg0),
- arg1, notc);
+ tree dandnotc
+ = fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (arg0),
+ fold_convert_loc (loc, TREE_TYPE (arg0), arg1),
+ notc);
tree rslt = code == EQ_EXPR ? integer_zero_node : integer_one_node;
if (integer_nonzerop (dandnotc))
return omit_one_operand_loc (loc, type, rslt, arg0);
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
{
tree notd = fold_build1_loc (loc, BIT_NOT_EXPR, TREE_TYPE (arg1), arg1);
- tree candnotd = fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (arg0),
- TREE_OPERAND (arg0, 1), notd);
+ tree candnotd
+ = fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (arg0),
+ TREE_OPERAND (arg0, 1),
+ fold_convert_loc (loc, TREE_TYPE (arg0), notd));
tree rslt = code == EQ_EXPR ? integer_zero_node : integer_one_node;
if (integer_nonzerop (candnotd))
return omit_one_operand_loc (loc, type, rslt, arg0);
if (TREE_CODE (arg0) == BIT_XOR_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0),
- build_int_cst (TREE_TYPE (arg1), 0));
+ build_int_cst (TREE_TYPE (arg0), 0));
/* Likewise (X ^ Y) == X becomes Y == 0. X has no side-effects. */
if (TREE_CODE (arg0) == BIT_XOR_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
&& reorder_operands_p (TREE_OPERAND (arg0, 1), arg1))
return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 1),
- build_int_cst (TREE_TYPE (arg1), 0));
+ build_int_cst (TREE_TYPE (arg0), 0));
/* (X ^ C1) op C2 can be rewritten as X op (C1 ^ C2). */
if (TREE_CODE (arg0) == BIT_XOR_EXPR
&& integer_pow2p (TREE_OPERAND (arg0, 1)))
{
tem = fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (arg0),
- TREE_OPERAND (TREE_OPERAND (arg0, 0), 0),
- TREE_OPERAND (arg0, 1));
+ TREE_OPERAND (TREE_OPERAND (arg0, 0), 0),
+ TREE_OPERAND (arg0, 1));
return fold_build2_loc (loc, code == EQ_EXPR ? NE_EXPR : EQ_EXPR,
- type, tem, arg1);
+ type, tem,
+ fold_convert_loc (loc, TREE_TYPE (arg0),
+ arg1));
}
/* Fold ((X & C) ^ C) eq/ne 0 into (X & C) ne/eq 0, when the
if (TREE_CODE (arg0) == NEGATE_EXPR
&& TREE_CODE (arg1) == NEGATE_EXPR)
return fold_build2_loc (loc, code, type,
- TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg1, 0));
+ TREE_OPERAND (arg0, 0),
+ fold_convert_loc (loc, TREE_TYPE (arg0),
+ TREE_OPERAND (arg1, 0)));
/* Fold (X & C) op (Y & C) as (X ^ Y) & C op 0", and symmetries. */
if (TREE_CODE (arg0) == BIT_AND_EXPR
operand_equal_p guarantees no side-effects so we don't need
to use omit_one_operand on Z. */
if (operand_equal_p (arg01, arg11, 0))
- return fold_build2_loc (loc, code, type, arg00, arg10);
+ return fold_build2_loc (loc, code, type, arg00,
+ fold_convert_loc (loc, TREE_TYPE (arg00),
+ arg10));
if (operand_equal_p (arg01, arg10, 0))
- return fold_build2_loc (loc, code, type, arg00, arg11);
+ return fold_build2_loc (loc, code, type, arg00,
+ fold_convert_loc (loc, TREE_TYPE (arg00),
+ arg11));
if (operand_equal_p (arg00, arg11, 0))
- return fold_build2_loc (loc, code, type, arg01, arg10);
+ return fold_build2_loc (loc, code, type, arg01,
+ fold_convert_loc (loc, TREE_TYPE (arg01),
+ arg10));
if (operand_equal_p (arg00, arg10, 0))
- return fold_build2_loc (loc, code, type, arg01, arg11);
+ return fold_build2_loc (loc, code, type, arg01,
+ fold_convert_loc (loc, TREE_TYPE (arg01),
+ arg11));
/* Optimize (X ^ C1) op (Y ^ C2) as (X ^ (C1 ^ C2)) op Y. */
if (TREE_CODE (arg01) == INTEGER_CST
&& TREE_CODE (arg11) == INTEGER_CST)
- return fold_build2_loc (loc, code, type,
- fold_build2_loc (loc, BIT_XOR_EXPR, itype, arg00,
- fold_build2_loc (loc,
- BIT_XOR_EXPR, itype,
- arg01, arg11)),
- arg10);
+ {
+ tem = fold_build2_loc (loc, BIT_XOR_EXPR, itype, arg01,
+ fold_convert_loc (loc, itype, arg11));
+ tem = fold_build2_loc (loc, BIT_XOR_EXPR, itype, arg00, tem);
+ return fold_build2_loc (loc, code, type, tem,
+ fold_convert_loc (loc, itype, arg10));
+ }
}
/* Attempt to simplify equality/inequality comparisons of complex
|| (TREE_CODE (arg0) == INTEGER_CST
&& TREE_CODE (arg1) == INTEGER_CST))
return build_complex (type, arg0, arg1);
+ if (TREE_CODE (arg0) == REALPART_EXPR
+ && TREE_CODE (arg1) == IMAGPART_EXPR
+ && TREE_TYPE (TREE_OPERAND (arg0, 0)) == type
+ && operand_equal_p (TREE_OPERAND (arg0, 0),
+ TREE_OPERAND (arg1, 0), 0))
+ return omit_one_operand_loc (loc, type, TREE_OPERAND (arg0, 0),
+ TREE_OPERAND (arg1, 0));
return NULL_TREE;
case ASSERT_EXPR:
TREE_OPERAND (arg0, 1))
&& !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (op2))))
{
- tem = fold_truth_not_expr (loc, arg0);
+ location_t loc0 = expr_location_or (arg0, loc);
+ tem = fold_truth_not_expr (loc0, arg0);
if (tem && COMPARISON_CLASS_P (tem))
{
tem = fold_cond_expr_with_comparison (loc, type, tem, op2, op1);
if (truth_value_p (TREE_CODE (arg0))
&& tree_swap_operands_p (op1, op2, false))
{
+ location_t loc0 = expr_location_or (arg0, loc);
/* See if this can be inverted. If it can't, possibly because
it was a floating-point inequality comparison, don't do
anything. */
- tem = fold_truth_not_expr (loc, arg0);
+ tem = fold_truth_not_expr (loc0, arg0);
if (tem)
return fold_build3_loc (loc, code, type, tem, op2, op1);
}
&& truth_value_p (TREE_CODE (arg0))
&& truth_value_p (TREE_CODE (arg1)))
{
+ location_t loc0 = expr_location_or (arg0, loc);
/* Only perform transformation if ARG0 is easily inverted. */
- tem = fold_truth_not_expr (loc, arg0);
+ tem = fold_truth_not_expr (loc0, arg0);
if (tem)
return fold_build2_loc (loc, TRUTH_ORIF_EXPR, type,
fold_convert_loc (loc, type, tem),
&& truth_value_p (TREE_CODE (arg0))
&& truth_value_p (TREE_CODE (op2)))
{
+ location_t loc0 = expr_location_or (arg0, loc);
/* Only perform transformation if ARG0 is easily inverted. */
- tem = fold_truth_not_expr (loc, arg0);
+ tem = fold_truth_not_expr (loc0, arg0);
if (tem)
return fold_build2_loc (loc, TRUTH_ANDIF_EXPR, type,
fold_convert_loc (loc, type, tem),
if (TREE_CODE_CLASS (code) != tcc_type
&& TREE_CODE_CLASS (code) != tcc_declaration
&& code != TREE_LIST
- && code != SSA_NAME)
+ && code != SSA_NAME
+ && CODE_CONTAINS_STRUCT (code, TS_COMMON))
fold_checksum_tree (TREE_CHAIN (expr), ctx, ht);
switch (TREE_CODE_CLASS (code))
{
|| tree_int_cst_sgn (bottom) < 0)))
return 0;
return integer_zerop (int_const_binop (TRUNC_MOD_EXPR,
- top, bottom, 0));
+ top, bottom));
default:
return 0;
CASE_FLT_FN (BUILT_IN_FLOOR):
CASE_FLT_FN (BUILT_IN_FMOD):
CASE_FLT_FN (BUILT_IN_FREXP):
+ CASE_FLT_FN (BUILT_IN_ICEIL):
+ CASE_FLT_FN (BUILT_IN_IFLOOR):
+ CASE_FLT_FN (BUILT_IN_IRINT):
+ CASE_FLT_FN (BUILT_IN_IROUND):
CASE_FLT_FN (BUILT_IN_LCEIL):
CASE_FLT_FN (BUILT_IN_LDEXP):
CASE_FLT_FN (BUILT_IN_LFLOOR):
}
/* *(foo *)&fooarray => fooarray[0] */
else if (TREE_CODE (optype) == ARRAY_TYPE
- && type == TREE_TYPE (optype))
+ && type == TREE_TYPE (optype)
+ && (!in_gimple_form
+ || TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST))
{
tree type_domain = TYPE_DOMAIN (optype);
tree min_val = size_zero_node;
if (type_domain && TYPE_MIN_VALUE (type_domain))
min_val = TYPE_MIN_VALUE (type_domain);
+ if (in_gimple_form
+ && TREE_CODE (min_val) != INTEGER_CST)
+ return NULL_TREE;
return build4_loc (loc, ARRAY_REF, type, op, min_val,
NULL_TREE, NULL_TREE);
}
/* *(foo *)fooarrptr => (*fooarrptr)[0] */
if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
- && type == TREE_TYPE (TREE_TYPE (subtype)))
+ && type == TREE_TYPE (TREE_TYPE (subtype))
+ && (!in_gimple_form
+ || TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST))
{
tree type_domain;
tree min_val = size_zero_node;
type_domain = TYPE_DOMAIN (TREE_TYPE (sub));
if (type_domain && TYPE_MIN_VALUE (type_domain))
min_val = TYPE_MIN_VALUE (type_domain);
+ if (in_gimple_form
+ && TREE_CODE (min_val) != INTEGER_CST)
+ return NULL_TREE;
return build4_loc (loc, ARRAY_REF, type, sub, min_val, NULL_TREE,
NULL_TREE);
}