/* Fold a constant sub-tree into a single node for C-compiler
- Copyright (C) 1987-2014 Free Software Foundation, Inc.
+ Copyright (C) 1987-2015 Free Software Foundation, Inc.
This file is part of GCC.
#include "coretypes.h"
#include "tm.h"
#include "flags.h"
+#include "alias.h"
+#include "symtab.h"
#include "tree.h"
+#include "fold-const.h"
#include "stor-layout.h"
#include "calls.h"
#include "tree-iterator.h"
#include "realmpfr.h"
#include "rtl.h"
+#include "hard-reg-set.h"
+#include "function.h"
+#include "insn-config.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "emit-rtl.h"
+#include "varasm.h"
+#include "stmt.h"
#include "expr.h"
#include "tm_p.h"
#include "target.h"
#include "langhooks.h"
#include "md5.h"
#include "predict.h"
-#include "vec.h"
-#include "hashtab.h"
-#include "hash-set.h"
-#include "machmode.h"
-#include "hard-reg-set.h"
-#include "input.h"
-#include "function.h"
#include "basic-block.h"
#include "tree-ssa-alias.h"
#include "internal-fn.h"
#include "tree-eh.h"
#include "gimple-expr.h"
-#include "is-a.h"
#include "gimple.h"
#include "gimplify.h"
#include "tree-dfa.h"
-#include "hash-table.h" /* Required for ENABLE_FOLD_CHECKING. */
#include "builtins.h"
-#include "hash-map.h"
-#include "plugin-api.h"
-#include "ipa-ref.h"
#include "cgraph.h"
#include "generic-match.h"
#include "optabs.h"
switch (TREE_CODE (t))
{
case INTEGER_CST:
- if (TYPE_OVERFLOW_WRAPS (type))
+ if (INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_WRAPS (type))
return true;
/* Check that -CST will not overflow type. */
case INTEGER_CST:
tem = fold_negate_const (t, type);
if (TREE_OVERFLOW (tem) == TREE_OVERFLOW (t)
- || (!TYPE_OVERFLOW_TRAPS (type)
+ || (ANY_INTEGRAL_TYPE_P (type)
+ && !TYPE_OVERFLOW_TRAPS (type)
&& TYPE_OVERFLOW_WRAPS (type))
|| (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0)
return tem;
STRIP_NOPS (arg2);
if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg2) == INTEGER_CST)
- return int_const_binop (code, arg1, arg2);
+ {
+ if (code == POINTER_PLUS_EXPR)
+ return int_const_binop (PLUS_EXPR,
+ arg1, fold_convert (TREE_TYPE (arg1), arg2));
+
+ return int_const_binop (code, arg1, arg2);
+ }
if (TREE_CODE (arg1) == REAL_CST && TREE_CODE (arg2) == REAL_CST)
{
return t;
}
- if (TREE_CODE (arg1) == FIXED_CST && TREE_CODE (arg2) == FIXED_CST)
+ if (TREE_CODE (arg1) == FIXED_CST)
{
FIXED_VALUE_TYPE f1;
FIXED_VALUE_TYPE f2;
case MINUS_EXPR:
case MULT_EXPR:
case TRUNC_DIV_EXPR:
+ if (TREE_CODE (arg2) != FIXED_CST)
+ return NULL_TREE;
f2 = TREE_FIXED_CST (arg2);
break;
case LSHIFT_EXPR:
case RSHIFT_EXPR:
{
+ if (TREE_CODE (arg2) != INTEGER_CST)
+ return NULL_TREE;
wide_int w2 = arg2;
f2.data.high = w2.elt (1);
f2.data.low = w2.elt (0);
{
if (TREE_CODE_CLASS (code) == tcc_comparison)
return fold_relational_const (code, type, arg1, arg2);
- else
- return const_binop (code, arg1, arg2);
+
+ /* ??? Until we make the const_binop worker take the type of the
+ result as argument put those cases that need it here. */
+ switch (code)
+ {
+ case COMPLEX_EXPR:
+ if ((TREE_CODE (arg1) == REAL_CST
+ && TREE_CODE (arg2) == REAL_CST)
+ || (TREE_CODE (arg1) == INTEGER_CST
+ && TREE_CODE (arg2) == INTEGER_CST))
+ return build_complex (type, arg1, arg2);
+ return NULL_TREE;
+
+ case VEC_PACK_TRUNC_EXPR:
+ case VEC_PACK_FIX_TRUNC_EXPR:
+ {
+ unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
+ tree *elts;
+
+ gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)) == nelts / 2
+ && TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg2)) == nelts / 2);
+ if (TREE_CODE (arg1) != VECTOR_CST
+ || TREE_CODE (arg2) != VECTOR_CST)
+ return NULL_TREE;
+
+ elts = XALLOCAVEC (tree, nelts);
+ if (!vec_cst_ctor_to_array (arg1, elts)
+ || !vec_cst_ctor_to_array (arg2, elts + nelts / 2))
+ return NULL_TREE;
+
+ for (i = 0; i < nelts; i++)
+ {
+ elts[i] = fold_convert_const (code == VEC_PACK_TRUNC_EXPR
+ ? NOP_EXPR : FIX_TRUNC_EXPR,
+ TREE_TYPE (type), elts[i]);
+ if (elts[i] == NULL_TREE || !CONSTANT_CLASS_P (elts[i]))
+ return NULL_TREE;
+ }
+
+ return build_vector (type, elts);
+ }
+
+ case VEC_WIDEN_MULT_LO_EXPR:
+ case VEC_WIDEN_MULT_HI_EXPR:
+ case VEC_WIDEN_MULT_EVEN_EXPR:
+ case VEC_WIDEN_MULT_ODD_EXPR:
+ {
+ unsigned int nelts = TYPE_VECTOR_SUBPARTS (type);
+ unsigned int out, ofs, scale;
+ tree *elts;
+
+ gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)) == nelts * 2
+ && TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg2)) == nelts * 2);
+ if (TREE_CODE (arg1) != VECTOR_CST || TREE_CODE (arg2) != VECTOR_CST)
+ return NULL_TREE;
+
+ elts = XALLOCAVEC (tree, nelts * 4);
+ if (!vec_cst_ctor_to_array (arg1, elts)
+ || !vec_cst_ctor_to_array (arg2, elts + nelts * 2))
+ return NULL_TREE;
+
+ if (code == VEC_WIDEN_MULT_LO_EXPR)
+ scale = 0, ofs = BYTES_BIG_ENDIAN ? nelts : 0;
+ else if (code == VEC_WIDEN_MULT_HI_EXPR)
+ scale = 0, ofs = BYTES_BIG_ENDIAN ? 0 : nelts;
+ else if (code == VEC_WIDEN_MULT_EVEN_EXPR)
+ scale = 1, ofs = 0;
+ else /* if (code == VEC_WIDEN_MULT_ODD_EXPR) */
+ scale = 1, ofs = 1;
+
+ for (out = 0; out < nelts; out++)
+ {
+ unsigned int in1 = (out << scale) + ofs;
+ unsigned int in2 = in1 + nelts * 2;
+ tree t1, t2;
+
+ t1 = fold_convert_const (NOP_EXPR, TREE_TYPE (type), elts[in1]);
+ t2 = fold_convert_const (NOP_EXPR, TREE_TYPE (type), elts[in2]);
+
+ if (t1 == NULL_TREE || t2 == NULL_TREE)
+ return NULL_TREE;
+ elts[out] = const_binop (MULT_EXPR, t1, t2);
+ if (elts[out] == NULL_TREE || !CONSTANT_CLASS_P (elts[out]))
+ return NULL_TREE;
+ }
+
+ return build_vector (type, elts);
+ }
+
+ default:;
+ }
+
+ if (TREE_CODE_CLASS (code) != tcc_binary)
+ return NULL_TREE;
+
+ /* Make sure type and arg0 have the same saturating flag. */
+ gcc_checking_assert (TYPE_SATURATING (type)
+ == TYPE_SATURATING (TREE_TYPE (arg1)));
+
+ return const_binop (code, arg1, arg2);
}
/* Compute CODE ARG1 with resulting type TYPE with ARG1 being constant.
}
case ABS_EXPR:
- return fold_abs_const (arg0, type);
+ if (TREE_CODE (arg0) == INTEGER_CST || TREE_CODE (arg0) == REAL_CST)
+ return fold_abs_const (arg0, type);
+ break;
case CONJ_EXPR:
if (TREE_CODE (arg0) == COMPLEX_CST)
enum tree_code rcode, tree truth_type,
tree ll_arg, tree lr_arg)
{
- bool honor_nans = HONOR_NANS (element_mode (ll_arg));
+ bool honor_nans = HONOR_NANS (ll_arg);
enum comparison_code lcompcode = comparison_to_compcode (lcode);
enum comparison_code rcompcode = comparison_to_compcode (rcode);
int compcode;
return 1;
- if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0))))
+ if (!HONOR_SIGNED_ZEROS (arg0))
{
/* If we do not distinguish between signed and unsigned zero,
consider them equal. */
case ADDR_EXPR:
return operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0),
TREE_CONSTANT (arg0) && TREE_CONSTANT (arg1)
- ? OEP_CONSTANT_ADDRESS_OF : 0);
+ ? OEP_CONSTANT_ADDRESS_OF | OEP_ADDRESS_OF : 0);
default:
break;
}
switch (TREE_CODE (arg0))
{
case INDIRECT_REF:
- flags &= ~OEP_CONSTANT_ADDRESS_OF;
+ if (!(flags & OEP_ADDRESS_OF)
+ && (TYPE_ALIGN (TREE_TYPE (arg0))
+ != TYPE_ALIGN (TREE_TYPE (arg1))))
+ return 0;
+ flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF);
return OP_SAME (0);
case REALPART_EXPR:
return OP_SAME (0);
case TARGET_MEM_REF:
- flags &= ~OEP_CONSTANT_ADDRESS_OF;
- /* Require equal extra operands and then fall through to MEM_REF
- handling of the two common operands. */
- if (!OP_SAME_WITH_NULL (2)
- || !OP_SAME_WITH_NULL (3)
- || !OP_SAME_WITH_NULL (4))
- return 0;
- /* Fallthru. */
case MEM_REF:
- flags &= ~OEP_CONSTANT_ADDRESS_OF;
/* Require equal access sizes, and similar pointer types.
We can have incomplete types for array references of
variable-sized arrays from the Fortran frontend
though. Also verify the types are compatible. */
- return ((TYPE_SIZE (TREE_TYPE (arg0)) == TYPE_SIZE (TREE_TYPE (arg1))
+ if (!((TYPE_SIZE (TREE_TYPE (arg0)) == TYPE_SIZE (TREE_TYPE (arg1))
|| (TYPE_SIZE (TREE_TYPE (arg0))
&& TYPE_SIZE (TREE_TYPE (arg1))
&& operand_equal_p (TYPE_SIZE (TREE_TYPE (arg0)),
TYPE_SIZE (TREE_TYPE (arg1)), flags)))
&& types_compatible_p (TREE_TYPE (arg0), TREE_TYPE (arg1))
- && alias_ptr_types_compatible_p
- (TREE_TYPE (TREE_OPERAND (arg0, 1)),
- TREE_TYPE (TREE_OPERAND (arg1, 1)))
- && OP_SAME (0) && OP_SAME (1));
+ && ((flags & OEP_ADDRESS_OF)
+ || (alias_ptr_types_compatible_p
+ (TREE_TYPE (TREE_OPERAND (arg0, 1)),
+ TREE_TYPE (TREE_OPERAND (arg1, 1)))
+ && (MR_DEPENDENCE_CLIQUE (arg0)
+ == MR_DEPENDENCE_CLIQUE (arg1))
+ && (MR_DEPENDENCE_BASE (arg0)
+ == MR_DEPENDENCE_BASE (arg1))
+ && (TYPE_ALIGN (TREE_TYPE (arg0))
+ == TYPE_ALIGN (TREE_TYPE (arg1)))))))
+ return 0;
+ flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF);
+ return (OP_SAME (0) && OP_SAME (1)
+ /* TARGET_MEM_REF require equal extra operands. */
+ && (TREE_CODE (arg0) != TARGET_MEM_REF
+ || (OP_SAME_WITH_NULL (2)
+ && OP_SAME_WITH_NULL (3)
+ && OP_SAME_WITH_NULL (4))));
case ARRAY_REF:
case ARRAY_RANGE_REF:
may have different types but same value here. */
if (!OP_SAME (0))
return 0;
- flags &= ~OEP_CONSTANT_ADDRESS_OF;
+ flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF);
return ((tree_int_cst_equal (TREE_OPERAND (arg0, 1),
TREE_OPERAND (arg1, 1))
|| OP_SAME (1))
if (!OP_SAME_WITH_NULL (0)
|| !OP_SAME (1))
return 0;
- flags &= ~OEP_CONSTANT_ADDRESS_OF;
+ flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF);
return OP_SAME_WITH_NULL (2);
case BIT_FIELD_REF:
if (!OP_SAME (0))
return 0;
- flags &= ~OEP_CONSTANT_ADDRESS_OF;
+ flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF);
return OP_SAME (1) && OP_SAME (2);
default:
switch (TREE_CODE (arg0))
{
case ADDR_EXPR:
+ return operand_equal_p (TREE_OPERAND (arg0, 0),
+ TREE_OPERAND (arg1, 0),
+ flags | OEP_ADDRESS_OF);
+
case TRUTH_NOT_EXPR:
return OP_SAME (0);
switch (TREE_CODE (arg0))
{
case CALL_EXPR:
- /* If the CALL_EXPRs call different functions, then they
- clearly can not be equal. */
- if (! operand_equal_p (CALL_EXPR_FN (arg0), CALL_EXPR_FN (arg1),
- flags))
+ if ((CALL_EXPR_FN (arg0) == NULL_TREE)
+ != (CALL_EXPR_FN (arg1) == NULL_TREE))
+ /* If not both CALL_EXPRs are either internal or normal function
+ functions, then they are not equal. */
return 0;
+ else if (CALL_EXPR_FN (arg0) == NULL_TREE)
+ {
+ /* If the CALL_EXPRs call different internal functions, then they
+ are not equal. */
+ if (CALL_EXPR_IFN (arg0) != CALL_EXPR_IFN (arg1))
+ return 0;
+ }
+ else
+ {
+ /* If the CALL_EXPRs call different functions, then they are not
+ equal. */
+ if (! operand_equal_p (CALL_EXPR_FN (arg0), CALL_EXPR_FN (arg1),
+ flags))
+ return 0;
+ }
{
unsigned int cef = call_expr_flags (arg0);
&& code != NE_EXPR && code != EQ_EXPR)
return NULL_TREE;
- code = invert_tree_comparison (code, HONOR_NANS (TYPE_MODE (op_type)));
+ code = invert_tree_comparison (code, HONOR_NANS (op_type));
if (code == ERROR_MARK)
return NULL_TREE;
operand which will be used if they are equal first
so that we can convert this back to the
corresponding COND_EXPR. */
- if (!HONOR_NANS (element_mode (arg1)))
+ if (!HONOR_NANS (arg1))
{
comp_op0 = fold_convert_loc (loc, comp_type, comp_op0);
comp_op1 = fold_convert_loc (loc, comp_type, comp_op1);
case GT_EXPR:
case UNGE_EXPR:
case UNGT_EXPR:
- if (!HONOR_NANS (element_mode (arg1)))
+ if (!HONOR_NANS (arg1))
{
comp_op0 = fold_convert_loc (loc, comp_type, comp_op0);
comp_op1 = fold_convert_loc (loc, comp_type, comp_op1);
}
break;
case UNEQ_EXPR:
- if (!HONOR_NANS (element_mode (arg1)))
+ if (!HONOR_NANS (arg1))
return pedantic_non_lvalue_loc (loc,
fold_convert_loc (loc, type, arg2));
break;
case LTGT_EXPR:
- if (!HONOR_NANS (element_mode (arg1)))
+ if (!HONOR_NANS (arg1))
return pedantic_non_lvalue_loc (loc,
fold_convert_loc (loc, type, arg1));
break;
}
}
- inv_code = invert_tree_comparison (code, HONOR_NANS (TYPE_MODE (type)));
+ inv_code = invert_tree_comparison (code, HONOR_NANS (type));
if (inv_code == rhs_code
&& operand_equal_p (TREE_OPERAND (rhs, 0), TREE_OPERAND (cmpop, 0), 0)
&& operand_equal_p (TREE_OPERAND (rhs, 1), TREE_OPERAND (cmpop, 1), 0))
|| EXPRESSION_CLASS_P (op0))
/* ... and has wrapping overflow, and its type is smaller
than ctype, then we cannot pass through as widening. */
- && ((TYPE_OVERFLOW_WRAPS (TREE_TYPE (op0))
+ && (((ANY_INTEGRAL_TYPE_P (TREE_TYPE (op0))
+ && TYPE_OVERFLOW_WRAPS (TREE_TYPE (op0)))
&& (TYPE_PRECISION (ctype)
> TYPE_PRECISION (TREE_TYPE (op0))))
/* ... or this is a truncation (t is narrower than op0),
/* ... or has undefined overflow while the converted to
type has not, we cannot do the operation in the inner type
as that would introduce undefined overflow. */
- || (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op0))
+ || ((ANY_INTEGRAL_TYPE_P (TREE_TYPE (op0))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op0)))
&& !TYPE_OVERFLOW_UNDEFINED (type))))
break;
/* If OP1 was not easily negatable, the constant may be OP0. */
if (TREE_CODE (op0) == INTEGER_CST)
{
- tree tem = op0;
- op0 = op1;
- op1 = tem;
- tem = t1;
- t1 = t2;
- t2 = tem;
+ std::swap (op0, op1);
+ std::swap (t1, t2);
}
}
&& integer_onep (TREE_OPERAND (arg0, 1)))
|| (TREE_CODE (arg0) == PLUS_EXPR
&& integer_all_onesp (TREE_OPERAND (arg0, 1)))))
- return fold_build1_loc (loc, NEGATE_EXPR, type,
- fold_convert_loc (loc, type,
- TREE_OPERAND (arg0, 0)));
+ {
+ /* Perform the negation in ARG0's type and only then convert
+ to TYPE as to avoid introducing undefined behavior. */
+ tree t = fold_build1_loc (loc, NEGATE_EXPR,
+ TREE_TYPE (TREE_OPERAND (arg0, 0)),
+ TREE_OPERAND (arg0, 0));
+ return fold_convert_loc (loc, type, t);
+ }
/* Convert ~(X ^ Y) to ~X ^ Y or X ^ ~Y if ~X or ~Y simplify. */
else if (TREE_CODE (arg0) == BIT_XOR_EXPR
&& (tem = fold_unary_loc (loc, BIT_NOT_EXPR, type,
/* Match A +- CST code arg1 and CST code arg1. We can change the
first form only if overflow is undefined. */
- if (!((TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))
+ if (!(((ANY_INTEGRAL_TYPE_P (TREE_TYPE (arg0))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0)))
/* In principle pointers also have undefined overflow behavior,
but that causes problems elsewhere. */
&& !POINTER_TYPE_P (TREE_TYPE (arg0))
/* Transform comparisons of the form X +- C1 CMP C2 to X CMP C2 -+ C1. */
if ((TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
- && (equality_code || TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0)))
+ && (equality_code
+ || (ANY_INTEGRAL_TYPE_P (TREE_TYPE (arg0))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))))
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
&& !TREE_OVERFLOW (TREE_OPERAND (arg0, 1))
&& TREE_CODE (arg1) == INTEGER_CST
}
}
/* For non-equal bases we can simplify if they are addresses
- of local binding decls or constants. */
+ declarations with different addresses. */
else if (indirect_base0 && indirect_base1
/* We know that !operand_equal_p (base0, base1, 0)
because the if condition was false. But make
&& base0 != base1
&& TREE_CODE (arg0) == ADDR_EXPR
&& TREE_CODE (arg1) == ADDR_EXPR
- && (((TREE_CODE (base0) == VAR_DECL
- || TREE_CODE (base0) == PARM_DECL)
- && (targetm.binds_local_p (base0)
- || CONSTANT_CLASS_P (base1)))
- || CONSTANT_CLASS_P (base0))
- && (((TREE_CODE (base1) == VAR_DECL
- || TREE_CODE (base1) == PARM_DECL)
- && (targetm.binds_local_p (base1)
- || CONSTANT_CLASS_P (base0)))
- || CONSTANT_CLASS_P (base1)))
+ && DECL_P (base0)
+ && DECL_P (base1)
+ /* Watch for aliases. */
+ && (!decl_in_symtab_p (base0)
+ || !decl_in_symtab_p (base1)
+ || !symtab_node::get_create (base0)->equal_address_to
+ (symtab_node::get_create (base1))))
{
if (code == EQ_EXPR)
return omit_two_operands_loc (loc, type, boolean_false_node,
X CMP Y +- C2 +- C1 for signed X, Y. This is valid if
the resulting offset is smaller in absolute value than the
original one and has the same sign. */
- if (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))
+ if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (arg0))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))
&& (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
&& (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
&& !TREE_OVERFLOW (TREE_OPERAND (arg0, 1)))
signed arithmetic case. That form is created by the compiler
often enough for folding it to be of value. One example is in
computing loop trip counts after Operator Strength Reduction. */
- if (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))
+ if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (arg0))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))
&& TREE_CODE (arg0) == MULT_EXPR
&& (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
&& !TREE_OVERFLOW (TREE_OPERAND (arg0, 1)))
fold_convert_loc (loc, newtype, targ0),
fold_convert_loc (loc, newtype, targ1));
- /* (-a) CMP (-b) -> b CMP a */
- if (TREE_CODE (arg0) == NEGATE_EXPR
- && TREE_CODE (arg1) == NEGATE_EXPR)
- return fold_build2_loc (loc, 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_loc (loc, 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))
/* x != NaN is always true, other ops are always false. */
if (REAL_VALUE_ISNAN (cst)
- && ! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1))))
+ && ! HONOR_SNANS (arg1))
{
tem = (code == NE_EXPR) ? integer_one_node : integer_zero_node;
return omit_one_operand_loc (loc, type, tem, arg0);
{
case EQ_EXPR:
if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
- || ! HONOR_NANS (element_mode (arg0)))
+ || ! HONOR_NANS (arg0))
return constant_boolean_node (1, type);
break;
case GE_EXPR:
case LE_EXPR:
if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
- || ! HONOR_NANS (element_mode (arg0)))
+ || ! HONOR_NANS (arg0))
return constant_boolean_node (1, type);
return fold_build2_loc (loc, EQ_EXPR, type, arg0, arg1);
/* 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 (element_mode (arg0)))
+ && HONOR_NANS (arg0))
break;
/* ... fall through ... */
case GT_EXPR:
constant but we can't do arithmetic on them. */
if (CONSTANT_CLASS_P (arg0) && CONSTANT_CLASS_P (arg1))
{
- if (kind == tcc_binary)
- {
- /* Make sure type and arg0 have the same saturating flag. */
- gcc_checking_assert (TYPE_SATURATING (type)
- == TYPE_SATURATING (TREE_TYPE (arg0)));
- tem = const_binop (code, arg0, arg1);
- }
- else if (kind == tcc_comparison)
- tem = fold_relational_const (code, type, arg0, arg1);
- else
- tem = NULL_TREE;
-
+ tem = const_binop (code, type, arg0, arg1);
if (tem != NULL_TREE)
{
if (TREE_TYPE (tem) != type)
fold_convert_loc (loc, sizetype,
arg0)));
- /* PTR_CST +p CST -> CST1 */
- if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
- return fold_build2_loc (loc, PLUS_EXPR, type, arg0,
- fold_convert_loc (loc, type, arg1));
-
return NULL_TREE;
case PLUS_EXPR:
/* Reassociate (plus (plus (mult) (foo)) (mult)) as
(plus (plus (mult) (mult)) (foo)) so that we can
take advantage of the factoring cases below. */
- if (TYPE_OVERFLOW_WRAPS (type)
+ if (ANY_INTEGRAL_TYPE_P (type)
+ && TYPE_OVERFLOW_WRAPS (type)
&& (((TREE_CODE (arg0) == PLUS_EXPR
|| TREE_CODE (arg0) == MINUS_EXPR)
&& TREE_CODE (arg1) == MULT_EXPR)
tem = build2_loc (loc, LROTATE_EXPR,
TREE_TYPE (TREE_OPERAND (arg0, 0)),
TREE_OPERAND (arg0, 0),
- code0 == LSHIFT_EXPR ? tree01 : tree11);
+ code0 == LSHIFT_EXPR
+ ? TREE_OPERAND (arg0, 1)
+ : TREE_OPERAND (arg1, 1));
return fold_convert_loc (loc, type, tem);
}
else if (code11 == MINUS_EXPR)
? LROTATE_EXPR
: RROTATE_EXPR),
TREE_TYPE (TREE_OPERAND (arg0, 0)),
- TREE_OPERAND (arg0, 0), tree01));
+ TREE_OPERAND (arg0, 0),
+ TREE_OPERAND (arg0, 1)));
}
else if (code01 == MINUS_EXPR)
{
? LROTATE_EXPR
: RROTATE_EXPR),
TREE_TYPE (TREE_OPERAND (arg0, 0)),
- TREE_OPERAND (arg0, 0), tree11));
+ TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 1)));
}
}
}
/* Don't introduce overflows through reassociation. */
if (!any_overflows
- && ((lit0 && TREE_OVERFLOW (lit0))
- || (minus_lit0 && TREE_OVERFLOW (minus_lit0))))
+ && ((lit0 && TREE_OVERFLOW_P (lit0))
+ || (minus_lit0 && TREE_OVERFLOW_P (minus_lit0))))
return NULL_TREE;
if (minus_lit0)
negate_expr (arg1)),
fold_convert_loc (loc, type,
TREE_OPERAND (arg0, 0)));
- /* Convert -A - 1 to ~A. */
- if (TREE_CODE (arg0) == NEGATE_EXPR
- && integer_each_onep (arg1)
- && !TYPE_OVERFLOW_TRAPS (type))
- return fold_build1_loc (loc, BIT_NOT_EXPR, type,
- fold_convert_loc (loc, type,
- TREE_OPERAND (arg0, 0)));
-
- /* Convert -1 - A to ~A. */
- if (TREE_CODE (type) != COMPLEX_TYPE
- && integer_all_onesp (arg0))
- return fold_build1_loc (loc, BIT_NOT_EXPR, type, op1);
-
-
- /* X - (X / Y) * Y is X % Y. */
- if ((INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type))
- && TREE_CODE (arg1) == MULT_EXPR
- && TREE_CODE (TREE_OPERAND (arg1, 0)) == TRUNC_DIV_EXPR
- && operand_equal_p (arg0,
- TREE_OPERAND (TREE_OPERAND (arg1, 0), 0), 0)
- && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg1, 0), 1),
- TREE_OPERAND (arg1, 1), 0))
- return
- fold_convert_loc (loc, type,
- fold_build2_loc (loc, TRUNC_MOD_EXPR, TREE_TYPE (arg0),
- arg0, TREE_OPERAND (arg1, 1)));
if (! FLOAT_TYPE_P (type))
{
fold_convert_loc (loc, type,
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);
- }
-
/* Fold &a[i] - &a[j] to i-j. */
if (TREE_CODE (arg0) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (arg0, 0)) == ARRAY_REF
/* Fold z * +-I to __complex__ (-+__imag z, +-__real z).
This is not the same for NaNs or if signed zeros are
involved. */
- if (!HONOR_NANS (element_mode (arg0))
+ if (!HONOR_NANS (arg0)
&& !HONOR_SIGNED_ZEROS (element_mode (arg0))
&& COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg0))
&& TREE_CODE (arg1) == COMPLEX_CST
return build_int_cst (type, residue & low);
}
- /* Fold (X << C1) & C2 into (X << C1) & (C2 | ((1 << C1) - 1))
- (X >> C1) & C2 into (X >> C1) & (C2 | ~((type) -1 >> C1))
- if the new mask might be further optimized. */
- if ((TREE_CODE (arg0) == LSHIFT_EXPR
- || TREE_CODE (arg0) == RSHIFT_EXPR)
- && TYPE_PRECISION (TREE_TYPE (arg0)) <= HOST_BITS_PER_WIDE_INT
- && TREE_CODE (arg1) == INTEGER_CST
- && tree_fits_uhwi_p (TREE_OPERAND (arg0, 1))
- && tree_to_uhwi (TREE_OPERAND (arg0, 1)) > 0
- && (tree_to_uhwi (TREE_OPERAND (arg0, 1))
- < TYPE_PRECISION (TREE_TYPE (arg0))))
- {
- unsigned int shiftc = tree_to_uhwi (TREE_OPERAND (arg0, 1));
- unsigned HOST_WIDE_INT mask = TREE_INT_CST_LOW (arg1);
- unsigned HOST_WIDE_INT newmask, zerobits = 0;
- tree shift_type = TREE_TYPE (arg0);
-
- if (TREE_CODE (arg0) == LSHIFT_EXPR)
- zerobits = ((((unsigned HOST_WIDE_INT) 1) << shiftc) - 1);
- else if (TREE_CODE (arg0) == RSHIFT_EXPR
- && TYPE_PRECISION (TREE_TYPE (arg0))
- == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (arg0))))
- {
- prec = TYPE_PRECISION (TREE_TYPE (arg0));
- tree arg00 = TREE_OPERAND (arg0, 0);
- /* See if more bits can be proven as zero because of
- zero extension. */
- if (TREE_CODE (arg00) == NOP_EXPR
- && TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg00, 0))))
- {
- tree inner_type = TREE_TYPE (TREE_OPERAND (arg00, 0));
- if (TYPE_PRECISION (inner_type)
- == GET_MODE_PRECISION (TYPE_MODE (inner_type))
- && TYPE_PRECISION (inner_type) < prec)
- {
- prec = TYPE_PRECISION (inner_type);
- /* See if we can shorten the right shift. */
- if (shiftc < prec)
- shift_type = inner_type;
- /* Otherwise X >> C1 is all zeros, so we'll optimize
- it into (X, 0) later on by making sure zerobits
- is all ones. */
- }
- }
- zerobits = ~(unsigned HOST_WIDE_INT) 0;
- if (shiftc < prec)
- {
- zerobits >>= HOST_BITS_PER_WIDE_INT - shiftc;
- zerobits <<= prec - shiftc;
- }
- /* For arithmetic shift if sign bit could be set, zerobits
- can contain actually sign bits, so no transformation is
- possible, unless MASK masks them all away. In that
- case the shift needs to be converted into logical shift. */
- if (!TYPE_UNSIGNED (TREE_TYPE (arg0))
- && prec == TYPE_PRECISION (TREE_TYPE (arg0)))
- {
- if ((mask & zerobits) == 0)
- shift_type = unsigned_type_for (TREE_TYPE (arg0));
- else
- zerobits = 0;
- }
- }
-
- /* ((X << 16) & 0xff00) is (X, 0). */
- if ((mask & zerobits) == mask)
- return omit_one_operand_loc (loc, type,
- build_int_cst (type, 0), arg0);
-
- newmask = mask | zerobits;
- if (newmask != mask && (newmask & (newmask + 1)) == 0)
- {
- /* Only do the transformation if NEWMASK is some integer
- mode's mask. */
- for (prec = BITS_PER_UNIT;
- prec < HOST_BITS_PER_WIDE_INT; prec <<= 1)
- if (newmask == (((unsigned HOST_WIDE_INT) 1) << prec) - 1)
- break;
- if (prec < HOST_BITS_PER_WIDE_INT
- || newmask == ~(unsigned HOST_WIDE_INT) 0)
- {
- tree newmaskt;
-
- if (shift_type != TREE_TYPE (arg0))
- {
- tem = fold_build2_loc (loc, TREE_CODE (arg0), shift_type,
- fold_convert_loc (loc, shift_type,
- TREE_OPERAND (arg0, 0)),
- TREE_OPERAND (arg0, 1));
- tem = fold_convert_loc (loc, type, tem);
- }
- else
- tem = op0;
- newmaskt = build_int_cst_type (TREE_TYPE (op1), newmask);
- if (!tree_int_cst_equal (newmaskt, arg1))
- return fold_build2_loc (loc, BIT_AND_EXPR, type, tem, newmaskt);
- }
- }
- }
-
goto associate;
case RDIV_EXPR:
tree arg00 = CALL_EXPR_ARG (arg0, 0);
tree arg01 = CALL_EXPR_ARG (arg1, 0);
- if (! HONOR_NANS (element_mode (arg00))
+ if (! HONOR_NANS (arg00)
&& ! HONOR_INFINITIES (element_mode (arg00))
&& operand_equal_p (arg00, arg01, 0))
{
tree arg00 = CALL_EXPR_ARG (arg0, 0);
tree arg01 = CALL_EXPR_ARG (arg1, 0);
- if (! HONOR_NANS (element_mode (arg00))
+ if (! HONOR_NANS (arg00)
&& ! HONOR_INFINITIES (element_mode (arg00))
&& operand_equal_p (arg00, arg01, 0))
{
case FLOOR_MOD_EXPR:
case ROUND_MOD_EXPR:
case TRUNC_MOD_EXPR:
- /* X % -Y is the same as X % Y. */
- if (code == TRUNC_MOD_EXPR
- && !TYPE_UNSIGNED (type)
- && TREE_CODE (arg1) == NEGATE_EXPR
- && !TYPE_OVERFLOW_TRAPS (type))
- return fold_build2_loc (loc, code, type, fold_convert_loc (loc, type, arg0),
- fold_convert_loc (loc, type,
- TREE_OPERAND (arg1, 0)));
-
strict_overflow_p = false;
if (TREE_CODE (arg1) == INTEGER_CST
&& 0 != (tem = extract_muldiv (op0, arg1, code, NULL_TREE,
return fold_convert_loc (loc, type, tem);
}
- /* Optimize TRUNC_MOD_EXPR by a power of two into a BIT_AND_EXPR,
- i.e. "X % C" into "X & (C - 1)", if X and C are positive. */
- if ((code == TRUNC_MOD_EXPR || code == FLOOR_MOD_EXPR)
- && (TYPE_UNSIGNED (type)
- || tree_expr_nonnegative_warnv_p (op0, &strict_overflow_p)))
- {
- tree c = arg1;
- /* Also optimize A % (C << N) where C is a power of 2,
- to A & ((C << N) - 1). */
- if (TREE_CODE (arg1) == LSHIFT_EXPR)
- c = TREE_OPERAND (arg1, 0);
-
- if (integer_pow2p (c) && tree_int_cst_sgn (c) > 0)
- {
- tree mask
- = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (arg1), arg1,
- build_int_cst (TREE_TYPE (arg1), 1));
- if (strict_overflow_p)
- fold_overflow_warning (("assuming signed overflow does not "
- "occur when simplifying "
- "X % (power of two)"),
- WARN_STRICT_OVERFLOW_MISC);
- return fold_build2_loc (loc, BIT_AND_EXPR, type,
- fold_convert_loc (loc, type, arg0),
- fold_convert_loc (loc, type, mask));
- }
- }
-
return NULL_TREE;
case LROTATE_EXPR:
unaliased symbols neither of which are extern (since we do not
have access to attributes for externs), then we know the result. */
if (TREE_CODE (arg0) == ADDR_EXPR
- && VAR_OR_FUNCTION_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))
+ && DECL_P (TREE_OPERAND (arg0, 0))
&& TREE_CODE (arg1) == ADDR_EXPR
- && VAR_OR_FUNCTION_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)))
- {
- /* We know that we're looking at the address of two
- non-weak, unaliased, static _DECL nodes.
-
- It is both wasteful and incorrect to call operand_equal_p
- to compare the two ADDR_EXPR nodes. It is wasteful in that
- all we need to do is test pointer equality for the arguments
- to the two ADDR_EXPR nodes. It is incorrect to use
- operand_equal_p as that function is NOT equivalent to a
- C equality test. It can in fact return false for two
- objects which would test as equal using the C equality
- operator. */
- bool equal = TREE_OPERAND (arg0, 0) == TREE_OPERAND (arg1, 0);
- return constant_boolean_node (equal
- ? code == EQ_EXPR : code != EQ_EXPR,
- type);
- }
-
- /* Similarly for a NEGATE_EXPR. */
- if (TREE_CODE (arg0) == NEGATE_EXPR
- && TREE_CODE (arg1) == INTEGER_CST
- && 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);
+ && DECL_P (TREE_OPERAND (arg1, 0)))
+ {
+ int equal;
+
+ if (decl_in_symtab_p (TREE_OPERAND (arg0, 0))
+ && decl_in_symtab_p (TREE_OPERAND (arg1, 0)))
+ equal = symtab_node::get_create (TREE_OPERAND (arg0, 0))
+ ->equal_address_to (symtab_node::get_create
+ (TREE_OPERAND (arg1, 0)));
+ else
+ equal = TREE_OPERAND (arg0, 0) == TREE_OPERAND (arg1, 0);
+ if (equal != 2)
+ return constant_boolean_node (equal
+ ? code == EQ_EXPR : code != EQ_EXPR,
+ type);
+ }
/* Similarly for a BIT_XOR_EXPR; X ^ C1 == C2 is X == (C1 ^ C2). */
if (TREE_CODE (arg0) == BIT_XOR_EXPR
return omit_one_operand_loc (loc, type, rslt, arg0);
}
- /* If we have (A | C) == D where C & ~D != 0, convert this into 0.
- Similarly for NE_EXPR. */
- if (TREE_CODE (arg0) == BIT_IOR_EXPR
- && TREE_CODE (arg1) == INTEGER_CST
- && 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),
- 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 this is a comparison of a field, we may be able to simplify it. */
if ((TREE_CODE (arg0) == COMPONENT_REF
|| TREE_CODE (arg0) == BIT_FIELD_REF)
}
}
- /* (X ^ Y) == 0 becomes X == Y, and (X ^ Y) != 0 becomes X != Y. */
- if (integer_zerop (arg1)
- && TREE_CODE (arg0) == BIT_XOR_EXPR)
- return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg0, 1));
-
- /* (X ^ Y) == Y becomes X == 0. We know that Y has no side-effects. */
- 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_zero_cst (TREE_TYPE (arg0)));
- /* 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_zero_cst (TREE_TYPE (arg0)));
-
- /* (X ^ C1) op C2 can be rewritten as X op (C1 ^ C2). */
- if (TREE_CODE (arg0) == BIT_XOR_EXPR
- && TREE_CODE (arg1) == INTEGER_CST
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
- return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0),
- fold_build2_loc (loc, BIT_XOR_EXPR, TREE_TYPE (arg1),
- TREE_OPERAND (arg0, 1), arg1));
-
/* Fold (~X & C) == 0 into (X & C) != 0 and (~X & C) != 0 into
(X & C) == 0 when C is a single bit. */
if (TREE_CODE (arg0) == BIT_AND_EXPR
return omit_one_operand_loc (loc, type, res, arg0);
}
- /* Fold -X op -Y as X op Y, where op is eq/ne. */
- if (TREE_CODE (arg0) == NEGATE_EXPR
- && TREE_CODE (arg1) == NEGATE_EXPR)
- return fold_build2_loc (loc, code, type,
- 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
&& TREE_CODE (arg1) == BIT_AND_EXPR)
if ((TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
&& ((TREE_CODE (TREE_OPERAND (arg0, 1)) == REAL_CST
- && !HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0))))
+ && !HONOR_SNANS (arg0))
|| (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg1)))))
{
}
/* Convert (X - c) <= X to true. */
- if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1)))
+ if (!HONOR_NANS (arg1)
&& code == LE_EXPR
&& ((code0 == MINUS_EXPR && is_positive >= 0)
|| (code0 == PLUS_EXPR && is_positive <= 0)))
}
/* Convert (X + c) >= X to true. */
- if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1)))
+ if (!HONOR_NANS (arg1)
&& code == GE_EXPR
&& ((code0 == PLUS_EXPR && is_positive >= 0)
|| (code0 == MINUS_EXPR && is_positive <= 0)))
strict_overflow_p = false;
if (code == GE_EXPR
&& (integer_zerop (arg1)
- || (! HONOR_NANS (element_mode (arg0))
+ || (! HONOR_NANS (arg0)
&& real_zerop (arg1)))
&& tree_expr_nonnegative_warnv_p (arg0, &strict_overflow_p))
{
: fold_convert_loc (loc, type, arg1);
return pedantic_non_lvalue_loc (loc, tem);
- case COMPLEX_EXPR:
- if ((TREE_CODE (arg0) == REAL_CST
- && TREE_CODE (arg1) == REAL_CST)
- || (TREE_CODE (arg0) == INTEGER_CST
- && TREE_CODE (arg1) == INTEGER_CST))
- return build_complex (type, arg0, arg1);
- return NULL_TREE;
-
case ASSERT_EXPR:
/* An ASSERT_EXPR should never be passed to fold_binary. */
gcc_unreachable ();
- case VEC_PACK_TRUNC_EXPR:
- case VEC_PACK_FIX_TRUNC_EXPR:
- {
- unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
- tree *elts;
-
- gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)) == nelts / 2
- && TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)) == nelts / 2);
- if (TREE_CODE (arg0) != VECTOR_CST || TREE_CODE (arg1) != VECTOR_CST)
- return NULL_TREE;
-
- elts = XALLOCAVEC (tree, nelts);
- if (!vec_cst_ctor_to_array (arg0, elts)
- || !vec_cst_ctor_to_array (arg1, elts + nelts / 2))
- return NULL_TREE;
-
- for (i = 0; i < nelts; i++)
- {
- elts[i] = fold_convert_const (code == VEC_PACK_TRUNC_EXPR
- ? NOP_EXPR : FIX_TRUNC_EXPR,
- TREE_TYPE (type), elts[i]);
- if (elts[i] == NULL_TREE || !CONSTANT_CLASS_P (elts[i]))
- return NULL_TREE;
- }
-
- return build_vector (type, elts);
- }
-
- case VEC_WIDEN_MULT_LO_EXPR:
- case VEC_WIDEN_MULT_HI_EXPR:
- case VEC_WIDEN_MULT_EVEN_EXPR:
- case VEC_WIDEN_MULT_ODD_EXPR:
- {
- unsigned int nelts = TYPE_VECTOR_SUBPARTS (type);
- unsigned int out, ofs, scale;
- tree *elts;
-
- gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)) == nelts * 2
- && TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)) == nelts * 2);
- if (TREE_CODE (arg0) != VECTOR_CST || TREE_CODE (arg1) != VECTOR_CST)
- return NULL_TREE;
-
- elts = XALLOCAVEC (tree, nelts * 4);
- if (!vec_cst_ctor_to_array (arg0, elts)
- || !vec_cst_ctor_to_array (arg1, elts + nelts * 2))
- return NULL_TREE;
-
- if (code == VEC_WIDEN_MULT_LO_EXPR)
- scale = 0, ofs = BYTES_BIG_ENDIAN ? nelts : 0;
- else if (code == VEC_WIDEN_MULT_HI_EXPR)
- scale = 0, ofs = BYTES_BIG_ENDIAN ? 0 : nelts;
- else if (code == VEC_WIDEN_MULT_EVEN_EXPR)
- scale = 1, ofs = 0;
- else /* if (code == VEC_WIDEN_MULT_ODD_EXPR) */
- scale = 1, ofs = 1;
-
- for (out = 0; out < nelts; out++)
- {
- unsigned int in1 = (out << scale) + ofs;
- unsigned int in2 = in1 + nelts * 2;
- tree t1, t2;
-
- t1 = fold_convert_const (NOP_EXPR, TREE_TYPE (type), elts[in1]);
- t2 = fold_convert_const (NOP_EXPR, TREE_TYPE (type), elts[in2]);
-
- if (t1 == NULL_TREE || t2 == NULL_TREE)
- return NULL_TREE;
- elts[out] = const_binop (MULT_EXPR, t1, t2);
- if (elts[out] == NULL_TREE || !CONSTANT_CLASS_P (elts[out]))
- return NULL_TREE;
- }
-
- return build_vector (type, elts);
- }
-
default:
return NULL_TREE;
} /* switch (code) */
#undef fold
static void fold_checksum_tree (const_tree, struct md5_ctx *,
- hash_table<pointer_hash<const tree_node> > *);
+ hash_table<nofree_ptr_hash<const tree_node> > *);
static void fold_check_failed (const_tree, const_tree);
void print_fold_checksum (const_tree);
tree ret;
struct md5_ctx ctx;
unsigned char checksum_before[16], checksum_after[16];
- hash_table<pointer_hash<const tree_node> > ht (32);
+ hash_table<nofree_ptr_hash<const tree_node> > ht (32);
md5_init_ctx (&ctx);
fold_checksum_tree (expr, &ctx, &ht);
{
struct md5_ctx ctx;
unsigned char checksum[16], cnt;
- hash_table<pointer_hash<const tree_node> > ht (32);
+ hash_table<nofree_ptr_hash<const tree_node> > ht (32);
md5_init_ctx (&ctx);
fold_checksum_tree (expr, &ctx, &ht);
static void
fold_checksum_tree (const_tree expr, struct md5_ctx *ctx,
- hash_table<pointer_hash <const tree_node> > *ht)
+ hash_table<nofree_ptr_hash <const tree_node> > *ht)
{
const tree_node **slot;
enum tree_code code;
*slot = expr;
code = TREE_CODE (expr);
if (TREE_CODE_CLASS (code) == tcc_declaration
- && DECL_ASSEMBLER_NAME_SET_P (expr))
+ && HAS_DECL_ASSEMBLER_NAME_P (expr))
{
- /* Allow DECL_ASSEMBLER_NAME to be modified. */
+ /* Allow DECL_ASSEMBLER_NAME and symtab_node to be modified. */
memcpy ((char *) &buf, expr, tree_size (expr));
SET_DECL_ASSEMBLER_NAME ((tree)&buf, NULL);
+ buf.decl_with_vis.symtab_node = NULL;
expr = (tree) &buf;
}
else if (TREE_CODE_CLASS (code) == tcc_type
int i;
unsigned char checksum[16];
struct md5_ctx ctx;
- hash_table<pointer_hash<const tree_node> > ht (32);
+ hash_table<nofree_ptr_hash<const tree_node> > ht (32);
md5_init_ctx (&ctx);
fold_checksum_tree (t, &ctx, &ht);
#ifdef ENABLE_FOLD_CHECKING
unsigned char checksum_before[16], checksum_after[16];
struct md5_ctx ctx;
- hash_table<pointer_hash<const tree_node> > ht (32);
+ hash_table<nofree_ptr_hash<const tree_node> > ht (32);
md5_init_ctx (&ctx);
fold_checksum_tree (op0, &ctx, &ht);
checksum_after_op0[16],
checksum_after_op1[16];
struct md5_ctx ctx;
- hash_table<pointer_hash<const tree_node> > ht (32);
+ hash_table<nofree_ptr_hash<const tree_node> > ht (32);
md5_init_ctx (&ctx);
fold_checksum_tree (op0, &ctx, &ht);
checksum_after_op1[16],
checksum_after_op2[16];
struct md5_ctx ctx;
- hash_table<pointer_hash<const tree_node> > ht (32);
+ hash_table<nofree_ptr_hash<const tree_node> > ht (32);
md5_init_ctx (&ctx);
fold_checksum_tree (op0, &ctx, &ht);
checksum_after_fn[16],
checksum_after_arglist[16];
struct md5_ctx ctx;
- hash_table<pointer_hash<const tree_node> > ht (32);
+ hash_table<nofree_ptr_hash<const tree_node> > ht (32);
int i;
md5_init_ctx (&ctx);
#endif
tem = fold_builtin_call_array (loc, type, fn, nargs, argarray);
+ if (!tem)
+ tem = build_call_array_loc (loc, type, fn, nargs, argarray);
#ifdef ENABLE_FOLD_CHECKING
md5_init_ctx (&ctx);
case ABS_EXPR:
/* We can't return 1 if flag_wrapv is set because
ABS_EXPR<INT_MIN> = INT_MIN. */
- if (!INTEGRAL_TYPE_P (type))
+ if (!ANY_INTEGRAL_TYPE_P (type))
return true;
if (TYPE_OVERFLOW_UNDEFINED (type))
{
|| (tree_expr_nonnegative_warnv_p (op0, strict_overflow_p)
&& tree_expr_nonnegative_warnv_p (op1, strict_overflow_p)))
{
- if (TYPE_OVERFLOW_UNDEFINED (type))
+ if (ANY_INTEGRAL_TYPE_P (type)
+ && TYPE_OVERFLOW_UNDEFINED (type))
*strict_overflow_p = true;
return true;
}
{
case POINTER_PLUS_EXPR:
case PLUS_EXPR:
- if (TYPE_OVERFLOW_UNDEFINED (type))
+ if (ANY_INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_UNDEFINED (type))
{
/* With the presence of negative values it is hard
to say something. */
if (code == LE_EXPR || code == GT_EXPR)
{
- tree tem = op0;
- op0 = op1;
- op1 = tem;
+ std::swap (op0, op1);
code = swap_tree_comparison (code);
}
return value;
overflow_p = TREE_OVERFLOW (value);
- val &= ~(divisor - 1);
- val += divisor;
+ val += divisor - 1;
+ val &= - (int) divisor;
if (val == 0)
overflow_p = true;
t = build_int_cst (TREE_TYPE (value), divisor - 1);
value = size_binop_loc (loc, PLUS_EXPR, value, t);
- t = build_int_cst (TREE_TYPE (value), -divisor);
+ t = build_int_cst (TREE_TYPE (value), - (int) divisor);
value = size_binop_loc (loc, BIT_AND_EXPR, value, t);
}
}
}
return NULL_TREE;
}
+
+/* Return OFF converted to a pointer offset type suitable as offset for
+ POINTER_PLUS_EXPR. Use location LOC for this conversion. */
+tree
+convert_to_ptrofftype_loc (location_t loc, tree off)
+{
+ return fold_convert_loc (loc, sizetype, off);
+}
+
+/* Build and fold a POINTER_PLUS_EXPR at LOC offsetting PTR by OFF. */
+tree
+fold_build_pointer_plus_loc (location_t loc, tree ptr, tree off)
+{
+ return fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (ptr),
+ ptr, convert_to_ptrofftype_loc (loc, off));
+}
+
+/* Build and fold a POINTER_PLUS_EXPR at LOC offsetting PTR by OFF. */
+tree
+fold_build_pointer_plus_hwi_loc (location_t loc, tree ptr, HOST_WIDE_INT off)
+{
+ return fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (ptr),
+ ptr, size_int (off));
+}