#include "coretypes.h"
#include "tm.h"
#include "flags.h"
-#include "hash-set.h"
-#include "machmode.h"
-#include "vec.h"
-#include "double-int.h"
-#include "input.h"
#include "alias.h"
#include "symtab.h"
-#include "wide-int.h"
-#include "inchash.h"
#include "tree.h"
#include "fold-const.h"
#include "stor-layout.h"
#include "tree-iterator.h"
#include "realmpfr.h"
#include "rtl.h"
-#include "hashtab.h"
#include "hard-reg-set.h"
#include "function.h"
-#include "statistics.h"
-#include "real.h"
-#include "fixed-value.h"
#include "insn-config.h"
#include "expmed.h"
#include "dojump.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"
return OP_SAME (0);
case TARGET_MEM_REF:
- flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_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|OEP_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)),
&& (MR_DEPENDENCE_BASE (arg0)
== MR_DEPENDENCE_BASE (arg1))
&& (TYPE_ALIGN (TREE_TYPE (arg0))
- == TYPE_ALIGN (TREE_TYPE (arg1)))))
- && OP_SAME (0) && OP_SAME (1));
+ == 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:
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);
/* 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);
}
}
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))
fold_convert_loc (loc, type,
TREE_OPERAND (arg0, 0)));
- /* 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 A - (A & B) into ~B & A. */
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
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:
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:
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);
-
/* Similarly for a BIT_XOR_EXPR; X ^ C1 == C2 is X == (C1 ^ C2). */
if (TREE_CODE (arg0) == BIT_XOR_EXPR
&& TREE_CODE (arg1) == INTEGER_CST
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)
#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;
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);
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))
{
if (code == LE_EXPR || code == GT_EXPR)
{
- tree tem = op0;
- op0 = op1;
- op1 = tem;
+ std::swap (op0, op1);
code = swap_tree_comparison (code);
}