/* 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.
#include "tm_p.h"
#include "target.h"
#include "diagnostic-core.h"
-#include "toplev.h"
#include "intl.h"
#include "ggc.h"
#include "hashtab.h"
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:
return value ? integer_one_node : integer_zero_node;
else if (type == boolean_type_node)
return value ? boolean_true_node : boolean_false_node;
+ else if (type)
+ return build_int_cst_type (type, value);
else
- return build_int_cst (type, value);
+ return build_int_cst (NULL_TREE, value);
}
}
/* This transformation is only worthwhile if we don't have to wrap ARG
- in a SAVE_EXPR and the operation can be simplified on at least one
- of the branches once its pushed inside the COND_EXPR. */
+ in a SAVE_EXPR and the operation can be simplified without recursing
+ on at least one of the branches once its pushed inside the COND_EXPR. */
if (!TREE_CONSTANT (arg)
&& (TREE_SIDE_EFFECTS (arg)
+ || TREE_CODE (arg) == COND_EXPR || TREE_CODE (arg) == VEC_COND_EXPR
|| TREE_CONSTANT (true_value) || TREE_CONSTANT (false_value)))
return NULL_TREE;
&& TREE_TYPE (TREE_OPERAND (arg1, 0)) == inner_type))
return NULL_TREE;
- if ((TYPE_UNSIGNED (inner_type) != TYPE_UNSIGNED (outer_type)
- || POINTER_TYPE_P (inner_type) != POINTER_TYPE_P (outer_type))
+ if (TYPE_UNSIGNED (inner_type) != TYPE_UNSIGNED (outer_type)
&& code != NE_EXPR
&& code != EQ_EXPR)
return NULL_TREE;
+ if (POINTER_TYPE_P (inner_type) != POINTER_TYPE_P (outer_type))
+ return NULL_TREE;
+
if (TREE_CODE (arg1) == INTEGER_CST)
arg1 = force_fit_type_double (inner_type, tree_to_double_int (arg1),
0, TREE_OVERFLOW (arg1));
&& (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);
}
}
&& TREE_CODE (arg1) == INTEGER_CST
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
{
- unsigned HOST_WIDE_INT hi1, lo1, hi2, lo2, hi3, lo3, mlo, mhi;
+ double_int c1, c2, c3, msk;
int width = TYPE_PRECISION (type), w;
- hi1 = TREE_INT_CST_HIGH (TREE_OPERAND (arg0, 1));
- lo1 = TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1));
- hi2 = TREE_INT_CST_HIGH (arg1);
- lo2 = TREE_INT_CST_LOW (arg1);
+ c1 = tree_to_double_int (TREE_OPERAND (arg0, 1));
+ c2 = tree_to_double_int (arg1);
/* If (C1&C2) == C1, then (X&C1)|C2 becomes (X,C2). */
- if ((hi1 & hi2) == hi1 && (lo1 & lo2) == lo1)
+ if (double_int_equal_p (double_int_and (c1, c2), c1))
return omit_one_operand_loc (loc, type, arg1,
- TREE_OPERAND (arg0, 0));
+ TREE_OPERAND (arg0, 0));
- if (width > HOST_BITS_PER_WIDE_INT)
- {
- mhi = (unsigned HOST_WIDE_INT) -1
- >> (2 * HOST_BITS_PER_WIDE_INT - width);
- mlo = -1;
- }
- else
- {
- mhi = 0;
- mlo = (unsigned HOST_WIDE_INT) -1
- >> (HOST_BITS_PER_WIDE_INT - width);
- }
+ msk = double_int_mask (width);
/* If (C1|C2) == ~0 then (X&C1)|C2 becomes X|C2. */
- if ((~(hi1 | hi2) & mhi) == 0 && (~(lo1 | lo2) & mlo) == 0)
+ if (double_int_zero_p (double_int_and_not (msk,
+ double_int_ior (c1, c2))))
return fold_build2_loc (loc, BIT_IOR_EXPR, type,
- TREE_OPERAND (arg0, 0), arg1);
+ TREE_OPERAND (arg0, 0), arg1);
/* Minimize the number of bits set in C1, i.e. C1 := C1 & ~C2,
unless (C1 & ~C2) | (C2 & C3) for some C3 is a mask of some
mode which allows further optimizations. */
- hi1 &= mhi;
- lo1 &= mlo;
- hi2 &= mhi;
- lo2 &= mlo;
- hi3 = hi1 & ~hi2;
- lo3 = lo1 & ~lo2;
+ c1 = double_int_and (c1, msk);
+ c2 = double_int_and (c2, msk);
+ c3 = double_int_and_not (c1, c2);
for (w = BITS_PER_UNIT;
w <= width && w <= HOST_BITS_PER_WIDE_INT;
w <<= 1)
{
unsigned HOST_WIDE_INT mask
= (unsigned HOST_WIDE_INT) -1 >> (HOST_BITS_PER_WIDE_INT - w);
- if (((lo1 | lo2) & mask) == mask
- && (lo1 & ~mask) == 0 && hi1 == 0)
+ if (((c1.low | c2.low) & mask) == mask
+ && (c1.low & ~mask) == 0 && c1.high == 0)
{
- hi3 = 0;
- lo3 = mask;
+ c3 = uhwi_to_double_int (mask);
break;
}
}
- if (hi3 != hi1 || lo3 != lo1)
+ if (!double_int_equal_p (c3, c1))
return fold_build2_loc (loc, BIT_IOR_EXPR, type,
- fold_build2_loc (loc, BIT_AND_EXPR, type,
- TREE_OPERAND (arg0, 0),
- build_int_cst_wide (type,
- lo3, hi3)),
- arg1);
+ fold_build2_loc (loc, BIT_AND_EXPR, type,
+ TREE_OPERAND (arg0, 0),
+ double_int_to_tree (type,
+ c3)),
+ arg1);
}
/* (X & Y) | Y is (X, Y). */
}
/* *(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);
}