static tree fold_negate_const (tree, tree);
static tree fold_not_const (tree, tree);
static tree fold_relational_const (enum tree_code, tree, tree, tree);
+static tree fold_convert_const (enum tree_code, tree, tree);
/* We know that A1 + B1 = SUM1, using 2's complement arithmetic and ignoring
of type CODE and returns the quotient.
Otherwise returns NULL_TREE. */
-static tree
+tree
div_if_zero_remainder (enum tree_code code, const_tree arg1, const_tree arg2)
{
unsigned HOST_WIDE_INT int1l, int2l;
if (fold_deferred_overflow_warning != NULL
&& code != 0
&& code < (int) fold_deferred_overflow_code)
- fold_deferred_overflow_code = code;
+ fold_deferred_overflow_code = (enum warn_strict_overflow_code) code;
return;
}
return build_complex (type, real, imag);
}
+ if (TREE_CODE (arg1) == VECTOR_CST)
+ {
+ tree type = TREE_TYPE(arg1);
+ int count = TYPE_VECTOR_SUBPARTS (type), i;
+ tree elements1, elements2, list = NULL_TREE;
+
+ if(TREE_CODE(arg2) != VECTOR_CST)
+ return NULL_TREE;
+
+ elements1 = TREE_VECTOR_CST_ELTS (arg1);
+ elements2 = TREE_VECTOR_CST_ELTS (arg2);
+
+ for (i = 0; i < count; i++)
+ {
+ tree elem1, elem2, elem;
+
+ /* The trailing elements can be empty and should be treated as 0 */
+ if(!elements1)
+ elem1 = fold_convert_const (NOP_EXPR, TREE_TYPE (type), integer_zero_node);
+ else
+ {
+ elem1 = TREE_VALUE(elements1);
+ elements1 = TREE_CHAIN (elements1);
+ }
+
+ if(!elements2)
+ elem2 = fold_convert_const (NOP_EXPR, TREE_TYPE (type), integer_zero_node);
+ else
+ {
+ elem2 = TREE_VALUE(elements2);
+ elements2 = TREE_CHAIN (elements2);
+ }
+
+ elem = const_binop (code, elem1, elem2, notrunc);
+
+ /* It is possible that const_binop cannot handle the given
+ code and return NULL_TREE */
+ if(elem == NULL_TREE)
+ return NULL_TREE;
+
+ list = tree_cons (NULL_TREE, elem, list);
+ }
+ return build_vector(type, nreverse(list));
+ }
return NULL_TREE;
}
bool honor_nans = HONOR_NANS (TYPE_MODE (TREE_TYPE (ll_arg)));
enum comparison_code lcompcode = comparison_to_compcode (lcode);
enum comparison_code rcompcode = comparison_to_compcode (rcode);
- enum comparison_code compcode;
+ int compcode;
switch (code)
{
else if (compcode == COMPCODE_FALSE)
return constant_boolean_node (false, truth_type);
else
- return fold_build2 (compcode_to_comparison (compcode),
- truth_type, ll_arg, lr_arg);
+ {
+ enum tree_code tcode;
+
+ tcode = compcode_to_comparison ((enum comparison_code) compcode);
+ return fold_build2 (tcode, truth_type, ll_arg, lr_arg);
+ }
}
\f
/* Return nonzero if two operands (typically of the same tree node)
tree
fold_truth_not_expr (tree arg)
{
- tree type = TREE_TYPE (arg);
+ tree t, type = TREE_TYPE (arg);
enum tree_code code = TREE_CODE (arg);
/* If this is a comparison, we can simply invert it, except for
&& code != ORDERED_EXPR && code != UNORDERED_EXPR
&& code != NE_EXPR && code != EQ_EXPR)
return NULL_TREE;
- else
- {
- code = invert_tree_comparison (code,
- HONOR_NANS (TYPE_MODE (op_type)));
- if (code == ERROR_MARK)
- return NULL_TREE;
- else
- return build2 (code, type,
- TREE_OPERAND (arg, 0), TREE_OPERAND (arg, 1));
- }
+
+ code = invert_tree_comparison (code, HONOR_NANS (TYPE_MODE (op_type)));
+ if (code == ERROR_MARK)
+ return NULL_TREE;
+
+ t = build2 (code, type, TREE_OPERAND (arg, 0), TREE_OPERAND (arg, 1));
+ if (EXPR_HAS_LOCATION (arg))
+ SET_EXPR_LOCATION (t, EXPR_LOCATION (arg));
+ return t;
}
switch (code)
return constant_boolean_node (integer_zerop (arg), type);
case TRUTH_AND_EXPR:
- return build2 (TRUTH_OR_EXPR, type,
- invert_truthvalue (TREE_OPERAND (arg, 0)),
- invert_truthvalue (TREE_OPERAND (arg, 1)));
+ t = build2 (TRUTH_OR_EXPR, type,
+ invert_truthvalue (TREE_OPERAND (arg, 0)),
+ invert_truthvalue (TREE_OPERAND (arg, 1)));
+ break;
case TRUTH_OR_EXPR:
- return build2 (TRUTH_AND_EXPR, type,
- invert_truthvalue (TREE_OPERAND (arg, 0)),
- invert_truthvalue (TREE_OPERAND (arg, 1)));
+ t = build2 (TRUTH_AND_EXPR, type,
+ invert_truthvalue (TREE_OPERAND (arg, 0)),
+ invert_truthvalue (TREE_OPERAND (arg, 1)));
+ break;
case TRUTH_XOR_EXPR:
/* Here we can invert either operand. We invert the first operand
negation of the second operand. */
if (TREE_CODE (TREE_OPERAND (arg, 1)) == TRUTH_NOT_EXPR)
- return build2 (TRUTH_XOR_EXPR, type, TREE_OPERAND (arg, 0),
- TREE_OPERAND (TREE_OPERAND (arg, 1), 0));
+ t = build2 (TRUTH_XOR_EXPR, type, TREE_OPERAND (arg, 0),
+ TREE_OPERAND (TREE_OPERAND (arg, 1), 0));
else
- return build2 (TRUTH_XOR_EXPR, type,
- invert_truthvalue (TREE_OPERAND (arg, 0)),
- TREE_OPERAND (arg, 1));
+ t = build2 (TRUTH_XOR_EXPR, type,
+ invert_truthvalue (TREE_OPERAND (arg, 0)),
+ TREE_OPERAND (arg, 1));
+ break;
case TRUTH_ANDIF_EXPR:
- return build2 (TRUTH_ORIF_EXPR, type,
- invert_truthvalue (TREE_OPERAND (arg, 0)),
- invert_truthvalue (TREE_OPERAND (arg, 1)));
+ t = build2 (TRUTH_ORIF_EXPR, type,
+ invert_truthvalue (TREE_OPERAND (arg, 0)),
+ invert_truthvalue (TREE_OPERAND (arg, 1)));
+ break;
case TRUTH_ORIF_EXPR:
- return build2 (TRUTH_ANDIF_EXPR, type,
- invert_truthvalue (TREE_OPERAND (arg, 0)),
- invert_truthvalue (TREE_OPERAND (arg, 1)));
+ t = build2 (TRUTH_ANDIF_EXPR, type,
+ invert_truthvalue (TREE_OPERAND (arg, 0)),
+ invert_truthvalue (TREE_OPERAND (arg, 1)));
+ break;
case TRUTH_NOT_EXPR:
return TREE_OPERAND (arg, 0);
/* A COND_EXPR may have a throw as one operand, which
then has void type. Just leave void operands
as they are. */
- return build3 (COND_EXPR, type, TREE_OPERAND (arg, 0),
- VOID_TYPE_P (TREE_TYPE (arg1))
- ? arg1 : invert_truthvalue (arg1),
- VOID_TYPE_P (TREE_TYPE (arg2))
- ? arg2 : invert_truthvalue (arg2));
+ t = build3 (COND_EXPR, type, TREE_OPERAND (arg, 0),
+ VOID_TYPE_P (TREE_TYPE (arg1))
+ ? arg1 : invert_truthvalue (arg1),
+ VOID_TYPE_P (TREE_TYPE (arg2))
+ ? arg2 : invert_truthvalue (arg2));
+ break;
}
case COMPOUND_EXPR:
- return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg, 0),
- invert_truthvalue (TREE_OPERAND (arg, 1)));
+ t = build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg, 0),
+ invert_truthvalue (TREE_OPERAND (arg, 1)));
+ break;
case NON_LVALUE_EXPR:
return invert_truthvalue (TREE_OPERAND (arg, 0));
case NOP_EXPR:
if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
- return build1 (TRUTH_NOT_EXPR, type, arg);
+ {
+ t = build1 (TRUTH_NOT_EXPR, type, arg);
+ break;
+ }
+
+ /* ... fall through ... */
case CONVERT_EXPR:
case FLOAT_EXPR:
- return build1 (TREE_CODE (arg), type,
- invert_truthvalue (TREE_OPERAND (arg, 0)));
+ t = build1 (TREE_CODE (arg), type,
+ invert_truthvalue (TREE_OPERAND (arg, 0)));
+ break;
case BIT_AND_EXPR:
if (!integer_onep (TREE_OPERAND (arg, 1)))
- break;
- return build2 (EQ_EXPR, type, arg,
- build_int_cst (type, 0));
+ return NULL_TREE;
+ t = build2 (EQ_EXPR, type, arg, build_int_cst (type, 0));
+ break;
case SAVE_EXPR:
- return build1 (TRUTH_NOT_EXPR, type, arg);
+ t = build1 (TRUTH_NOT_EXPR, type, arg);
+ break;
case CLEANUP_POINT_EXPR:
- return build1 (CLEANUP_POINT_EXPR, type,
- invert_truthvalue (TREE_OPERAND (arg, 0)));
+ t = build1 (CLEANUP_POINT_EXPR, type,
+ invert_truthvalue (TREE_OPERAND (arg, 0)));
+ break;
default:
+ t = NULL_TREE;
break;
}
- return NULL_TREE;
+ if (t && EXPR_HAS_LOCATION (arg))
+ SET_EXPR_LOCATION (t, EXPR_LOCATION (arg));
+
+ return t;
}
/* Return a simplified tree node for the truth-negation of ARG. This
static tree
build_range_check (tree type, tree exp, int in_p, tree low, tree high)
{
- tree etype = TREE_TYPE (exp);
- tree value;
+ tree etype = TREE_TYPE (exp), value;
+ enum tree_code code;
#ifdef HAVE_canonicalize_funcptr_for_compare
/* Disable this optimization for function pointer expressions
/* Optimize (c>=low) && (c<=high) into (c-low>=0) && (c-low<=high-low).
This requires wrap-around arithmetics for the type of the expression. */
- switch (TREE_CODE (etype))
+ code = TREE_CODE (etype);
+ switch (code)
{
case INTEGER_TYPE:
+ case ENUMERAL_TYPE:
+ case BOOLEAN_TYPE:
/* There is no requirement that LOW be within the range of ETYPE
if the latter is a subtype. It must, however, be within the base
type of ETYPE. So be sure we do the subtraction in that type. */
- if (TREE_TYPE (etype))
- etype = TREE_TYPE (etype);
- break;
+ if (code == INTEGER_TYPE && TREE_TYPE (etype))
+ {
+ etype = TREE_TYPE (etype);
+ /* But not in an enumeral or boolean type though. */
+ code = TREE_CODE (etype);
+ }
- case ENUMERAL_TYPE:
- case BOOLEAN_TYPE:
- etype = lang_hooks.types.type_for_size (TYPE_PRECISION (etype),
- TYPE_UNSIGNED (etype));
+ if (code != INTEGER_TYPE)
+ etype = lang_hooks.types.type_for_size (TYPE_PRECISION (etype),
+ TYPE_UNSIGNED (etype));
break;
default:
break;
case GT_EXPR:
- /* If C1 is C2 - 1, this is max(A, C2). */
+ /* If C1 is C2 - 1, this is max(A, C2), but use ARG00's type for
+ MAX_EXPR, to preserve the signedness of the comparison. */
if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type),
OEP_ONLY_CONST)
&& operand_equal_p (arg01,
const_binop (MINUS_EXPR, arg2,
build_int_cst (type, 1), 0),
OEP_ONLY_CONST))
- return pedantic_non_lvalue (fold_build2 (MAX_EXPR,
- type,
- fold_convert (type, arg1),
- arg2));
+ return pedantic_non_lvalue (fold_convert (type,
+ fold_build2 (MAX_EXPR, TREE_TYPE (arg00),
+ arg00,
+ fold_convert (TREE_TYPE (arg00),
+ arg2))));
break;
case GE_EXPR:
- /* If C1 is C2 + 1, this is max(A, C2). */
+ /* If C1 is C2 + 1, this is max(A, C2), with the same care as above. */
if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type),
OEP_ONLY_CONST)
&& operand_equal_p (arg01,
const_binop (PLUS_EXPR, arg2,
build_int_cst (type, 1), 0),
OEP_ONLY_CONST))
- return pedantic_non_lvalue (fold_build2 (MAX_EXPR,
- type,
- fold_convert (type, arg1),
- arg2));
+ return pedantic_non_lvalue (fold_convert (type,
+ fold_build2 (MAX_EXPR, TREE_TYPE (arg00),
+ arg00,
+ fold_convert (TREE_TYPE (arg00),
+ arg2))));
break;
case NE_EXPR:
break;
else
maybe_same = arg11;
- if (exact_log2 (abs (int11)) > 0 && int01 % int11 == 0)
+ if (exact_log2 (abs (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. */
+ && TREE_CODE (arg10) != INTEGER_CST)
{
alt0 = fold_build2 (MULT_EXPR, TREE_TYPE (arg00), arg00,
build_int_cst (TREE_TYPE (arg00),
}
}
- if (flag_unsafe_math_optimizations
+ if (flag_unsafe_math_optimizations
&& (TREE_CODE (arg0) == RDIV_EXPR || TREE_CODE (arg0) == MULT_EXPR)
&& (TREE_CODE (arg1) == RDIV_EXPR || TREE_CODE (arg1) == MULT_EXPR)
&& (tem = distribute_real_division (code, type, arg0, arg1)))
}
}
- if (flag_unsafe_math_optimizations
+ if (FLOAT_TYPE_P (type)
+ && flag_unsafe_math_optimizations
&& (TREE_CODE (arg0) == RDIV_EXPR || TREE_CODE (arg0) == MULT_EXPR)
&& (TREE_CODE (arg1) == RDIV_EXPR || TREE_CODE (arg1) == MULT_EXPR)
&& (tem = distribute_real_division (code, type, arg0, arg1)))
&& !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. */
+ /* In IEEE floating point, x*1 is not equivalent to x for snans.
+ Likewise for complex arithmetic with signed zeros. */
if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
+ && (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0)))
+ || !COMPLEX_FLOAT_TYPE_P (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)))
+ && (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0)))
+ || !COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg0)))
&& real_minus_onep (arg1))
return fold_convert (type, negate_expr (arg0));
if (code == LROTATE_EXPR || code == RROTATE_EXPR)
low = low % TYPE_PRECISION (type);
else if (TYPE_UNSIGNED (type) || code == LSHIFT_EXPR)
- return build_int_cst (type, 0);
+ return omit_one_operand (type, build_int_cst (type, 0),
+ TREE_OPERAND (arg0, 0));
else
low = TYPE_PRECISION (type) - 1;
}
fold_convert (TREE_TYPE (arg0), arg1),
TREE_OPERAND (arg0, 1)));
- /* Transform comparisons of the form X +- C CMP X. */
- if ((TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
+ /* Transform comparisons of the form X +- Y CMP X to Y CMP 0. */
+ 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)
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
&& (INTEGRAL_TYPE_P (TREE_TYPE (arg0))
|| POINTER_TYPE_P (TREE_TYPE (arg0))))
{
- tree cst = TREE_OPERAND (arg0, 1);
+ tree val = TREE_OPERAND (arg0, 1);
+ return omit_two_operands (type,
+ fold_build2 (code, type,
+ val,
+ build_int_cst (TREE_TYPE (val),
+ 0)),
+ TREE_OPERAND (arg0, 0), arg1);
+ }
- if (code == EQ_EXPR
- && !integer_zerop (cst))
- return omit_two_operands (type, boolean_false_node,
- TREE_OPERAND (arg0, 0), arg1);
- else
- return omit_two_operands (type, boolean_true_node,
- TREE_OPERAND (arg0, 0), arg1);
+ /* 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)
+ && (TREE_INT_CST_LOW (TREE_OPERAND (arg0, 0)) & 1) == 1)
+ {
+ return omit_two_operands (type,
+ code == NE_EXPR
+ ? boolean_true_node : boolean_false_node,
+ TREE_OPERAND (arg0, 1), arg1);
}
/* If we have X - Y == 0, we can convert that to X == Y and similarly
if (!base)
return false;
- /* Weak declarations may link to NULL. */
- if (VAR_OR_FUNCTION_DECL_P (base))
- return !DECL_WEAK (base);
+ /* Weak declarations may link to NULL. Other things may also be NULL
+ so protect with -fdelete-null-pointer-checks; but not variables
+ allocated on the stack. */
+ if (DECL_P (base)
+ && (flag_delete_null_pointer_checks
+ || (TREE_CODE (base) == VAR_DECL && !TREE_STATIC (base))))
+ return !VAR_OR_FUNCTION_DECL_P (base) || !DECL_WEAK (base);
/* Constants are never weak. */
if (CONSTANT_CLASS_P (base))