/* 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
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
This file is part of GCC.
@@ This would also make life easier when this technology is used
@@ for cross-compilers. */
-/* The entry points in this file are fold, size_int_wide, size_binop
- and force_fit_type_double.
+/* The entry points in this file are fold, size_int_wide and size_binop.
fold takes a tree as argument and returns a simplified tree.
size_int takes an integer value, and creates a tree constant
with type from `sizetype'.
- force_fit_type_double takes a constant, an overflowable flag and a
- prior overflow indicator. It forces the value to fit the type and
- sets TREE_OVERFLOW.
-
Note: Since the folders get called on non-gimple code as well as
gimple code, we need to handle GIMPLE tuples as well as their
corresponding tree equivalents. */
#include "tm.h"
#include "flags.h"
#include "tree.h"
-#include "real.h"
-#include "fixed-value.h"
+#include "realmpfr.h"
#include "rtl.h"
#include "expr.h"
#include "tm_p.h"
#include "target.h"
-#include "toplev.h"
+#include "diagnostic-core.h"
#include "intl.h"
#include "ggc.h"
#include "hashtab.h"
#include "langhooks.h"
#include "md5.h"
#include "gimple.h"
+#include "tree-flow.h"
/* Nonzero if we are folding constants inside an initializer; zero
otherwise. */
COMPCODE_TRUE = 15
};
-static void encode (HOST_WIDE_INT *, unsigned HOST_WIDE_INT, HOST_WIDE_INT);
-static void decode (HOST_WIDE_INT *, unsigned HOST_WIDE_INT *, HOST_WIDE_INT *);
static bool negate_mathfn_p (enum built_in_function);
static bool negate_expr_p (tree);
static tree negate_expr (tree);
static tree split_tree (tree, enum tree_code, tree *, tree *, tree *, int);
-static tree associate_trees (tree, tree, enum tree_code, tree);
-static tree const_binop (enum tree_code, tree, tree, int);
+static tree associate_trees (location_t, tree, tree, enum tree_code, tree);
+static tree const_binop (enum tree_code, tree, tree);
static enum comparison_code comparison_to_compcode (enum tree_code);
static enum tree_code compcode_to_comparison (enum comparison_code);
static int operand_equal_for_comparison_p (tree, tree, tree);
static int twoval_comparison_p (tree, tree *, tree *, int *);
-static tree eval_subst (tree, tree, tree, tree, tree);
-static tree pedantic_omit_one_operand (tree, tree, tree);
-static tree distribute_bit_expr (enum tree_code, tree, tree, tree);
-static tree make_bit_field_ref (tree, tree, HOST_WIDE_INT, HOST_WIDE_INT, int);
-static tree optimize_bit_field_compare (enum tree_code, tree, tree, tree);
-static tree decode_field_reference (tree, HOST_WIDE_INT *, HOST_WIDE_INT *,
+static tree eval_subst (location_t, tree, tree, tree, tree, tree);
+static tree pedantic_omit_one_operand_loc (location_t, tree, tree, tree);
+static tree distribute_bit_expr (location_t, enum tree_code, tree, tree, tree);
+static tree make_bit_field_ref (location_t, tree, tree,
+ HOST_WIDE_INT, HOST_WIDE_INT, int);
+static tree optimize_bit_field_compare (location_t, enum tree_code,
+ tree, tree, tree);
+static tree decode_field_reference (location_t, tree, HOST_WIDE_INT *,
+ HOST_WIDE_INT *,
enum machine_mode *, int *, int *,
tree *, tree *);
static int all_ones_mask_p (const_tree, int);
static tree range_predecessor (tree);
static tree range_successor (tree);
extern tree make_range (tree, int *, tree *, tree *, bool *);
-extern tree build_range_check (tree, tree, int, tree, tree);
extern bool merge_ranges (int *, tree *, tree *, int, tree, tree, int,
tree, tree);
-static tree fold_range_test (enum tree_code, tree, tree, tree);
-static tree fold_cond_expr_with_comparison (tree, tree, tree, tree);
+static tree fold_range_test (location_t, enum tree_code, tree, tree, tree);
+static tree fold_cond_expr_with_comparison (location_t, tree, tree, tree, tree);
static tree unextend (tree, int, int, tree);
-static tree fold_truthop (enum tree_code, tree, tree, tree);
-static tree optimize_minmax_comparison (enum tree_code, tree, tree, tree);
+static tree fold_truthop (location_t, enum tree_code, tree, tree, tree);
+static tree optimize_minmax_comparison (location_t, enum tree_code,
+ tree, tree, tree);
static tree extract_muldiv (tree, tree, enum tree_code, tree, bool *);
static tree extract_muldiv_1 (tree, tree, enum tree_code, tree, bool *);
-static tree fold_binary_op_with_conditional_arg (enum tree_code, tree,
+static tree fold_binary_op_with_conditional_arg (location_t,
+ enum tree_code, tree,
tree, tree,
tree, tree, int);
-static tree fold_mathfn_compare (enum built_in_function, enum tree_code,
+static tree fold_mathfn_compare (location_t,
+ enum built_in_function, enum tree_code,
tree, tree, tree);
-static tree fold_inf_compare (enum tree_code, tree, tree, tree);
-static tree fold_div_compare (enum tree_code, tree, tree, tree);
+static tree fold_inf_compare (location_t, enum tree_code, tree, tree, tree);
+static tree fold_div_compare (location_t, enum tree_code, tree, tree, tree);
static bool reorder_operands_p (const_tree, const_tree);
static tree fold_negate_const (tree, tree);
-static tree fold_not_const (tree, tree);
+static tree fold_not_const (const_tree, tree);
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. */
-/* We know that A1 + B1 = SUM1, using 2's complement arithmetic and ignoring
- overflow. Suppose A, B and SUM have the same respective signs as A1, B1,
- and SUM1. Then this yields nonzero if overflow occurred during the
- addition.
-
- Overflow occurs if A and B have the same sign, but A and SUM differ in
- sign. Use `^' to test whether signs differ, and `< 0' to isolate the
- sign. */
-#define OVERFLOW_SUM_SIGN(a, b, sum) ((~((a) ^ (b)) & ((a) ^ (sum))) < 0)
-\f
-/* To do constant folding on INTEGER_CST nodes requires two-word arithmetic.
- We do that by representing the two-word integer in 4 words, with only
- HOST_BITS_PER_WIDE_INT / 2 bits stored in each word, as a positive
- number. The value of the word is LOWPART + HIGHPART * BASE. */
-
-#define LOWPART(x) \
- ((x) & (((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2)) - 1))
-#define HIGHPART(x) \
- ((unsigned HOST_WIDE_INT) (x) >> HOST_BITS_PER_WIDE_INT / 2)
-#define BASE ((unsigned HOST_WIDE_INT) 1 << HOST_BITS_PER_WIDE_INT / 2)
-
-/* Unpack a two-word integer into 4 words.
- LOW and HI are the integer, as two `HOST_WIDE_INT' pieces.
- WORDS points to the array of HOST_WIDE_INTs. */
-
-static void
-encode (HOST_WIDE_INT *words, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi)
-{
- words[0] = LOWPART (low);
- words[1] = HIGHPART (low);
- words[2] = LOWPART (hi);
- words[3] = HIGHPART (hi);
-}
-
-/* Pack an array of 4 words into a two-word integer.
- WORDS points to the array of words.
- The integer is stored into *LOW and *HI as two `HOST_WIDE_INT' pieces. */
-
-static void
-decode (HOST_WIDE_INT *words, unsigned HOST_WIDE_INT *low,
- HOST_WIDE_INT *hi)
-{
- *low = words[0] + words[1] * BASE;
- *hi = words[2] + words[3] * BASE;
-}
-\f
-/* Force the double-word integer L1, H1 to be within the range of the
- integer type TYPE. Stores the properly truncated and sign-extended
- double-word integer in *LV, *HV. Returns true if the operation
- overflows, that is, argument and result are different. */
-
-int
-fit_double_type (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
- unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv, const_tree type)
-{
- unsigned HOST_WIDE_INT low0 = l1;
- HOST_WIDE_INT high0 = h1;
- unsigned int prec;
- int sign_extended_type;
-
- if (POINTER_TYPE_P (type)
- || TREE_CODE (type) == OFFSET_TYPE)
- prec = POINTER_SIZE;
- else
- prec = TYPE_PRECISION (type);
-
- /* Size types *are* sign extended. */
- sign_extended_type = (!TYPE_UNSIGNED (type)
- || (TREE_CODE (type) == INTEGER_TYPE
- && TYPE_IS_SIZETYPE (type)));
-
- /* First clear all bits that are beyond the type's precision. */
- if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
- ;
- else if (prec > HOST_BITS_PER_WIDE_INT)
- h1 &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
- else
- {
- h1 = 0;
- if (prec < HOST_BITS_PER_WIDE_INT)
- l1 &= ~((HOST_WIDE_INT) (-1) << prec);
- }
-
- /* Then do sign extension if necessary. */
- if (!sign_extended_type)
- /* No sign extension */;
- else if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
- /* Correct width already. */;
- else if (prec > HOST_BITS_PER_WIDE_INT)
- {
- /* Sign extend top half? */
- if (h1 & ((unsigned HOST_WIDE_INT)1
- << (prec - HOST_BITS_PER_WIDE_INT - 1)))
- h1 |= (HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT);
- }
- else if (prec == HOST_BITS_PER_WIDE_INT)
- {
- if ((HOST_WIDE_INT)l1 < 0)
- h1 = -1;
- }
- else
- {
- /* Sign extend bottom half? */
- if (l1 & ((unsigned HOST_WIDE_INT)1 << (prec - 1)))
- {
- h1 = -1;
- l1 |= (HOST_WIDE_INT)(-1) << prec;
- }
- }
-
- *lv = l1;
- *hv = h1;
-
- /* If the value didn't fit, signal overflow. */
- return l1 != low0 || h1 != high0;
-}
-
-/* We force the double-int HIGH:LOW to the range of the type TYPE by
- sign or zero extending it.
- OVERFLOWABLE indicates if we are interested
- in overflow of the value, when >0 we are only interested in signed
- overflow, for <0 we are interested in any overflow. OVERFLOWED
- indicates whether overflow has already occurred. CONST_OVERFLOWED
- indicates whether constant overflow has already occurred. We force
- T's value to be within range of T's type (by setting to 0 or 1 all
- the bits outside the type's range). We set TREE_OVERFLOWED if,
- OVERFLOWED is nonzero,
- or OVERFLOWABLE is >0 and signed overflow occurs
- or OVERFLOWABLE is <0 and any overflow occurs
- We return a new tree node for the extended double-int. The node
- is shared if no overflow flags are set. */
-
-tree
-force_fit_type_double (tree type, unsigned HOST_WIDE_INT low,
- HOST_WIDE_INT high, int overflowable,
- bool overflowed)
-{
- int sign_extended_type;
- bool overflow;
-
- /* Size types *are* sign extended. */
- sign_extended_type = (!TYPE_UNSIGNED (type)
- || (TREE_CODE (type) == INTEGER_TYPE
- && TYPE_IS_SIZETYPE (type)));
-
- overflow = fit_double_type (low, high, &low, &high, type);
-
- /* If we need to set overflow flags, return a new unshared node. */
- if (overflowed || overflow)
- {
- if (overflowed
- || overflowable < 0
- || (overflowable > 0 && sign_extended_type))
- {
- tree t = make_node (INTEGER_CST);
- TREE_INT_CST_LOW (t) = low;
- TREE_INT_CST_HIGH (t) = high;
- TREE_TYPE (t) = type;
- TREE_OVERFLOW (t) = 1;
- return t;
- }
- }
-
- /* Else build a shared node. */
- return build_int_cst_wide (type, low, high);
-}
-\f
-/* Add two doubleword integers with doubleword result.
- Return nonzero if the operation overflows according to UNSIGNED_P.
- Each argument is given as two `HOST_WIDE_INT' pieces.
- One argument is L1 and H1; the other, L2 and H2.
- The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV. */
-
-int
-add_double_with_sign (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
- unsigned HOST_WIDE_INT l2, HOST_WIDE_INT h2,
- unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv,
- bool unsigned_p)
+static location_t
+expr_location_or (tree t, location_t loc)
{
- unsigned HOST_WIDE_INT l;
- HOST_WIDE_INT h;
-
- l = l1 + l2;
- h = h1 + h2 + (l < l1);
-
- *lv = l;
- *hv = h;
-
- if (unsigned_p)
- return (unsigned HOST_WIDE_INT) h < (unsigned HOST_WIDE_INT) h1;
- else
- return OVERFLOW_SUM_SIGN (h1, h2, h);
+ location_t tloc = EXPR_LOCATION (t);
+ return tloc != UNKNOWN_LOCATION ? tloc : loc;
}
-/* Negate a doubleword integer with doubleword result.
- Return nonzero if the operation overflows, assuming it's signed.
- The argument is given as two `HOST_WIDE_INT' pieces in L1 and H1.
- The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV. */
-
-int
-neg_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
- unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv)
-{
- if (l1 == 0)
- {
- *lv = 0;
- *hv = - h1;
- return (*hv & h1) < 0;
- }
- else
- {
- *lv = -l1;
- *hv = ~h1;
- return 0;
- }
-}
-\f
-/* Multiply two doubleword integers with doubleword result.
- Return nonzero if the operation overflows according to UNSIGNED_P.
- Each argument is given as two `HOST_WIDE_INT' pieces.
- One argument is L1 and H1; the other, L2 and H2.
- The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV. */
+/* Similar to protected_set_expr_location, but never modify x in place,
+ if location can and needs to be set, unshare it. */
-int
-mul_double_with_sign (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
- unsigned HOST_WIDE_INT l2, HOST_WIDE_INT h2,
- unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv,
- bool unsigned_p)
+static inline tree
+protected_set_expr_location_unshare (tree x, location_t loc)
{
- HOST_WIDE_INT arg1[4];
- HOST_WIDE_INT arg2[4];
- HOST_WIDE_INT prod[4 * 2];
- unsigned HOST_WIDE_INT carry;
- int i, j, k;
- unsigned HOST_WIDE_INT toplow, neglow;
- HOST_WIDE_INT tophigh, neghigh;
-
- encode (arg1, l1, h1);
- encode (arg2, l2, h2);
-
- memset (prod, 0, sizeof prod);
-
- for (i = 0; i < 4; i++)
- {
- carry = 0;
- for (j = 0; j < 4; j++)
- {
- k = i + j;
- /* This product is <= 0xFFFE0001, the sum <= 0xFFFF0000. */
- carry += arg1[i] * arg2[j];
- /* Since prod[p] < 0xFFFF, this sum <= 0xFFFFFFFF. */
- carry += prod[k];
- prod[k] = LOWPART (carry);
- carry = HIGHPART (carry);
- }
- prod[i + 4] = carry;
- }
-
- decode (prod, lv, hv);
- decode (prod + 4, &toplow, &tophigh);
-
- /* Unsigned overflow is immediate. */
- if (unsigned_p)
- return (toplow | tophigh) != 0;
-
- /* Check for signed overflow by calculating the signed representation of the
- top half of the result; it should agree with the low half's sign bit. */
- if (h1 < 0)
- {
- neg_double (l2, h2, &neglow, &neghigh);
- add_double (neglow, neghigh, toplow, tophigh, &toplow, &tophigh);
- }
- if (h2 < 0)
+ if (CAN_HAVE_LOCATION_P (x)
+ && EXPR_LOCATION (x) != loc
+ && !(TREE_CODE (x) == SAVE_EXPR
+ || TREE_CODE (x) == TARGET_EXPR
+ || TREE_CODE (x) == BIND_EXPR))
{
- neg_double (l1, h1, &neglow, &neghigh);
- add_double (neglow, neghigh, toplow, tophigh, &toplow, &tophigh);
+ x = copy_node (x);
+ SET_EXPR_LOCATION (x, loc);
}
- return (*hv < 0 ? ~(toplow & tophigh) : toplow | tophigh) != 0;
+ return x;
}
-\f
-/* Shift the doubleword integer in L1, H1 left by COUNT places
- keeping only PREC bits of result.
- Shift right if COUNT is negative.
- ARITH nonzero specifies arithmetic shifting; otherwise use logical shift.
- Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV. */
-void
-lshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
- HOST_WIDE_INT count, unsigned int prec,
- unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv, int arith)
-{
- unsigned HOST_WIDE_INT signmask;
- if (count < 0)
- {
- rshift_double (l1, h1, -count, prec, lv, hv, arith);
- return;
- }
-
- if (SHIFT_COUNT_TRUNCATED)
- count %= prec;
-
- if (count >= 2 * HOST_BITS_PER_WIDE_INT)
- {
- /* Shifting by the host word size is undefined according to the
- ANSI standard, so we must handle this as a special case. */
- *hv = 0;
- *lv = 0;
- }
- else if (count >= HOST_BITS_PER_WIDE_INT)
- {
- *hv = l1 << (count - HOST_BITS_PER_WIDE_INT);
- *lv = 0;
- }
- else
- {
- *hv = (((unsigned HOST_WIDE_INT) h1 << count)
- | (l1 >> (HOST_BITS_PER_WIDE_INT - count - 1) >> 1));
- *lv = l1 << count;
- }
-
- /* Sign extend all bits that are beyond the precision. */
-
- signmask = -((prec > HOST_BITS_PER_WIDE_INT
- ? ((unsigned HOST_WIDE_INT) *hv
- >> (prec - HOST_BITS_PER_WIDE_INT - 1))
- : (*lv >> (prec - 1))) & 1);
-
- if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
- ;
- else if (prec >= HOST_BITS_PER_WIDE_INT)
- {
- *hv &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
- *hv |= signmask << (prec - HOST_BITS_PER_WIDE_INT);
- }
- else
- {
- *hv = signmask;
- *lv &= ~((unsigned HOST_WIDE_INT) (-1) << prec);
- *lv |= signmask << prec;
- }
-}
-
-/* Shift the doubleword integer in L1, H1 right by COUNT places
- keeping only PREC bits of result. COUNT must be positive.
- ARITH nonzero specifies arithmetic shifting; otherwise use logical shift.
- Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV. */
-
-void
-rshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
- HOST_WIDE_INT count, unsigned int prec,
- unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv,
- int arith)
-{
- unsigned HOST_WIDE_INT signmask;
-
- signmask = (arith
- ? -((unsigned HOST_WIDE_INT) h1 >> (HOST_BITS_PER_WIDE_INT - 1))
- : 0);
-
- if (SHIFT_COUNT_TRUNCATED)
- count %= prec;
-
- if (count >= 2 * HOST_BITS_PER_WIDE_INT)
- {
- /* Shifting by the host word size is undefined according to the
- ANSI standard, so we must handle this as a special case. */
- *hv = 0;
- *lv = 0;
- }
- else if (count >= HOST_BITS_PER_WIDE_INT)
- {
- *hv = 0;
- *lv = (unsigned HOST_WIDE_INT) h1 >> (count - HOST_BITS_PER_WIDE_INT);
- }
- else
- {
- *hv = (unsigned HOST_WIDE_INT) h1 >> count;
- *lv = ((l1 >> count)
- | ((unsigned HOST_WIDE_INT) h1 << (HOST_BITS_PER_WIDE_INT - count - 1) << 1));
- }
-
- /* Zero / sign extend all bits that are beyond the precision. */
-
- if (count >= (HOST_WIDE_INT)prec)
- {
- *hv = signmask;
- *lv = signmask;
- }
- else if ((prec - count) >= 2 * HOST_BITS_PER_WIDE_INT)
- ;
- else if ((prec - count) >= HOST_BITS_PER_WIDE_INT)
- {
- *hv &= ~((HOST_WIDE_INT) (-1) << (prec - count - HOST_BITS_PER_WIDE_INT));
- *hv |= signmask << (prec - count - HOST_BITS_PER_WIDE_INT);
- }
- else
- {
- *hv = signmask;
- *lv &= ~((unsigned HOST_WIDE_INT) (-1) << (prec - count));
- *lv |= signmask << (prec - count);
- }
-}
-\f
-/* Rotate the doubleword integer in L1, H1 left by COUNT places
- keeping only PREC bits of result.
- Rotate right if COUNT is negative.
- Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV. */
-
-void
-lrotate_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
- HOST_WIDE_INT count, unsigned int prec,
- unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv)
-{
- unsigned HOST_WIDE_INT s1l, s2l;
- HOST_WIDE_INT s1h, s2h;
-
- count %= prec;
- if (count < 0)
- count += prec;
-
- lshift_double (l1, h1, count, prec, &s1l, &s1h, 0);
- rshift_double (l1, h1, prec - count, prec, &s2l, &s2h, 0);
- *lv = s1l | s2l;
- *hv = s1h | s2h;
-}
-
-/* Rotate the doubleword integer in L1, H1 left by COUNT places
- keeping only PREC bits of result. COUNT must be positive.
- Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV. */
-
-void
-rrotate_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
- HOST_WIDE_INT count, unsigned int prec,
- unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv)
-{
- unsigned HOST_WIDE_INT s1l, s2l;
- HOST_WIDE_INT s1h, s2h;
-
- count %= prec;
- if (count < 0)
- count += prec;
+/* We know that A1 + B1 = SUM1, using 2's complement arithmetic and ignoring
+ overflow. Suppose A, B and SUM have the same respective signs as A1, B1,
+ and SUM1. Then this yields nonzero if overflow occurred during the
+ addition.
- rshift_double (l1, h1, count, prec, &s1l, &s1h, 0);
- lshift_double (l1, h1, prec - count, prec, &s2l, &s2h, 0);
- *lv = s1l | s2l;
- *hv = s1h | s2h;
-}
+ Overflow occurs if A and B have the same sign, but A and SUM differ in
+ sign. Use `^' to test whether signs differ, and `< 0' to isolate the
+ sign. */
+#define OVERFLOW_SUM_SIGN(a, b, sum) ((~((a) ^ (b)) & ((a) ^ (sum))) < 0)
\f
-/* Divide doubleword integer LNUM, HNUM by doubleword integer LDEN, HDEN
- for a quotient (stored in *LQUO, *HQUO) and remainder (in *LREM, *HREM).
- CODE is a tree code for a kind of division, one of
- TRUNC_DIV_EXPR, FLOOR_DIV_EXPR, CEIL_DIV_EXPR, ROUND_DIV_EXPR
- or EXACT_DIV_EXPR
- It controls how the quotient is rounded to an integer.
- Return nonzero if the operation overflows.
- UNS nonzero says do unsigned division. */
-
-int
-div_and_round_double (enum tree_code code, int uns,
- unsigned HOST_WIDE_INT lnum_orig, /* num == numerator == dividend */
- HOST_WIDE_INT hnum_orig,
- unsigned HOST_WIDE_INT lden_orig, /* den == denominator == divisor */
- HOST_WIDE_INT hden_orig,
- unsigned HOST_WIDE_INT *lquo,
- HOST_WIDE_INT *hquo, unsigned HOST_WIDE_INT *lrem,
- HOST_WIDE_INT *hrem)
-{
- int quo_neg = 0;
- HOST_WIDE_INT num[4 + 1]; /* extra element for scaling. */
- HOST_WIDE_INT den[4], quo[4];
- int i, j;
- unsigned HOST_WIDE_INT work;
- unsigned HOST_WIDE_INT carry = 0;
- unsigned HOST_WIDE_INT lnum = lnum_orig;
- HOST_WIDE_INT hnum = hnum_orig;
- unsigned HOST_WIDE_INT lden = lden_orig;
- HOST_WIDE_INT hden = hden_orig;
- int overflow = 0;
-
- if (hden == 0 && lden == 0)
- overflow = 1, lden = 1;
-
- /* Calculate quotient sign and convert operands to unsigned. */
- if (!uns)
- {
- if (hnum < 0)
- {
- quo_neg = ~ quo_neg;
- /* (minimum integer) / (-1) is the only overflow case. */
- if (neg_double (lnum, hnum, &lnum, &hnum)
- && ((HOST_WIDE_INT) lden & hden) == -1)
- overflow = 1;
- }
- if (hden < 0)
- {
- quo_neg = ~ quo_neg;
- neg_double (lden, hden, &lden, &hden);
- }
- }
-
- if (hnum == 0 && hden == 0)
- { /* single precision */
- *hquo = *hrem = 0;
- /* This unsigned division rounds toward zero. */
- *lquo = lnum / lden;
- goto finish_up;
- }
-
- if (hnum == 0)
- { /* trivial case: dividend < divisor */
- /* hden != 0 already checked. */
- *hquo = *lquo = 0;
- *hrem = hnum;
- *lrem = lnum;
- goto finish_up;
- }
-
- memset (quo, 0, sizeof quo);
-
- memset (num, 0, sizeof num); /* to zero 9th element */
- memset (den, 0, sizeof den);
-
- encode (num, lnum, hnum);
- encode (den, lden, hden);
-
- /* Special code for when the divisor < BASE. */
- if (hden == 0 && lden < (unsigned HOST_WIDE_INT) BASE)
- {
- /* hnum != 0 already checked. */
- for (i = 4 - 1; i >= 0; i--)
- {
- work = num[i] + carry * BASE;
- quo[i] = work / lden;
- carry = work % lden;
- }
- }
- else
- {
- /* Full double precision division,
- with thanks to Don Knuth's "Seminumerical Algorithms". */
- int num_hi_sig, den_hi_sig;
- unsigned HOST_WIDE_INT quo_est, scale;
-
- /* Find the highest nonzero divisor digit. */
- for (i = 4 - 1;; i--)
- if (den[i] != 0)
- {
- den_hi_sig = i;
- break;
- }
-
- /* Insure that the first digit of the divisor is at least BASE/2.
- This is required by the quotient digit estimation algorithm. */
-
- scale = BASE / (den[den_hi_sig] + 1);
- if (scale > 1)
- { /* scale divisor and dividend */
- carry = 0;
- for (i = 0; i <= 4 - 1; i++)
- {
- work = (num[i] * scale) + carry;
- num[i] = LOWPART (work);
- carry = HIGHPART (work);
- }
-
- num[4] = carry;
- carry = 0;
- for (i = 0; i <= 4 - 1; i++)
- {
- work = (den[i] * scale) + carry;
- den[i] = LOWPART (work);
- carry = HIGHPART (work);
- if (den[i] != 0) den_hi_sig = i;
- }
- }
-
- num_hi_sig = 4;
-
- /* Main loop */
- for (i = num_hi_sig - den_hi_sig - 1; i >= 0; i--)
- {
- /* Guess the next quotient digit, quo_est, by dividing the first
- two remaining dividend digits by the high order quotient digit.
- quo_est is never low and is at most 2 high. */
- unsigned HOST_WIDE_INT tmp;
-
- num_hi_sig = i + den_hi_sig + 1;
- work = num[num_hi_sig] * BASE + num[num_hi_sig - 1];
- if (num[num_hi_sig] != den[den_hi_sig])
- quo_est = work / den[den_hi_sig];
- else
- quo_est = BASE - 1;
-
- /* Refine quo_est so it's usually correct, and at most one high. */
- tmp = work - quo_est * den[den_hi_sig];
- if (tmp < BASE
- && (den[den_hi_sig - 1] * quo_est
- > (tmp * BASE + num[num_hi_sig - 2])))
- quo_est--;
-
- /* Try QUO_EST as the quotient digit, by multiplying the
- divisor by QUO_EST and subtracting from the remaining dividend.
- Keep in mind that QUO_EST is the I - 1st digit. */
-
- carry = 0;
- for (j = 0; j <= den_hi_sig; j++)
- {
- work = quo_est * den[j] + carry;
- carry = HIGHPART (work);
- work = num[i + j] - LOWPART (work);
- num[i + j] = LOWPART (work);
- carry += HIGHPART (work) != 0;
- }
-
- /* If quo_est was high by one, then num[i] went negative and
- we need to correct things. */
- if (num[num_hi_sig] < (HOST_WIDE_INT) carry)
- {
- quo_est--;
- carry = 0; /* add divisor back in */
- for (j = 0; j <= den_hi_sig; j++)
- {
- work = num[i + j] + den[j] + carry;
- carry = HIGHPART (work);
- num[i + j] = LOWPART (work);
- }
-
- num [num_hi_sig] += carry;
- }
-
- /* Store the quotient digit. */
- quo[i] = quo_est;
- }
- }
-
- decode (quo, lquo, hquo);
-
- finish_up:
- /* If result is negative, make it so. */
- if (quo_neg)
- neg_double (*lquo, *hquo, lquo, hquo);
-
- /* Compute trial remainder: rem = num - (quo * den) */
- mul_double (*lquo, *hquo, lden_orig, hden_orig, lrem, hrem);
- neg_double (*lrem, *hrem, lrem, hrem);
- add_double (lnum_orig, hnum_orig, *lrem, *hrem, lrem, hrem);
-
- switch (code)
- {
- case TRUNC_DIV_EXPR:
- case TRUNC_MOD_EXPR: /* round toward zero */
- case EXACT_DIV_EXPR: /* for this one, it shouldn't matter */
- return overflow;
-
- case FLOOR_DIV_EXPR:
- case FLOOR_MOD_EXPR: /* round toward negative infinity */
- if (quo_neg && (*lrem != 0 || *hrem != 0)) /* ratio < 0 && rem != 0 */
- {
- /* quo = quo - 1; */
- add_double (*lquo, *hquo, (HOST_WIDE_INT) -1, (HOST_WIDE_INT) -1,
- lquo, hquo);
- }
- else
- return overflow;
- break;
-
- case CEIL_DIV_EXPR:
- case CEIL_MOD_EXPR: /* round toward positive infinity */
- if (!quo_neg && (*lrem != 0 || *hrem != 0)) /* ratio > 0 && rem != 0 */
- {
- add_double (*lquo, *hquo, (HOST_WIDE_INT) 1, (HOST_WIDE_INT) 0,
- lquo, hquo);
- }
- else
- return overflow;
- break;
-
- case ROUND_DIV_EXPR:
- case ROUND_MOD_EXPR: /* round to closest integer */
- {
- unsigned HOST_WIDE_INT labs_rem = *lrem;
- HOST_WIDE_INT habs_rem = *hrem;
- unsigned HOST_WIDE_INT labs_den = lden, ltwice;
- HOST_WIDE_INT habs_den = hden, htwice;
-
- /* Get absolute values. */
- if (*hrem < 0)
- neg_double (*lrem, *hrem, &labs_rem, &habs_rem);
- if (hden < 0)
- neg_double (lden, hden, &labs_den, &habs_den);
-
- /* If (2 * abs (lrem) >= abs (lden)), adjust the quotient. */
- mul_double ((HOST_WIDE_INT) 2, (HOST_WIDE_INT) 0,
- labs_rem, habs_rem, <wice, &htwice);
-
- if (((unsigned HOST_WIDE_INT) habs_den
- < (unsigned HOST_WIDE_INT) htwice)
- || (((unsigned HOST_WIDE_INT) habs_den
- == (unsigned HOST_WIDE_INT) htwice)
- && (labs_den <= ltwice)))
- {
- if (*hquo < 0)
- /* quo = quo - 1; */
- add_double (*lquo, *hquo,
- (HOST_WIDE_INT) -1, (HOST_WIDE_INT) -1, lquo, hquo);
- else
- /* quo = quo + 1; */
- add_double (*lquo, *hquo, (HOST_WIDE_INT) 1, (HOST_WIDE_INT) 0,
- lquo, hquo);
- }
- else
- return overflow;
- }
- break;
-
- default:
- gcc_unreachable ();
- }
-
- /* Compute true remainder: rem = num - (quo * den) */
- mul_double (*lquo, *hquo, lden_orig, hden_orig, lrem, hrem);
- neg_double (*lrem, *hrem, lrem, hrem);
- add_double (lnum_orig, hnum_orig, *lrem, *hrem, lrem, hrem);
- return overflow;
-}
-
/* If ARG2 divides ARG1 with zero remainder, carries out the division
of type CODE and returns the quotient.
Otherwise returns NULL_TREE. */
tree
div_if_zero_remainder (enum tree_code code, const_tree arg1, const_tree arg2)
{
- unsigned HOST_WIDE_INT int1l, int2l;
- HOST_WIDE_INT int1h, int2h;
- unsigned HOST_WIDE_INT quol, reml;
- HOST_WIDE_INT quoh, remh;
- tree type = TREE_TYPE (arg1);
- int uns = TYPE_UNSIGNED (type);
+ double_int quo, rem;
+ int uns;
- int1l = TREE_INT_CST_LOW (arg1);
- int1h = TREE_INT_CST_HIGH (arg1);
- /* &obj[0] + -128 really should be compiled as &obj[-8] rather than
- &obj[some_exotic_number]. */
- if (POINTER_TYPE_P (type))
- {
- uns = false;
- type = signed_type_for (type);
- fit_double_type (int1l, int1h, &int1l, &int1h,
- type);
- }
- else
- fit_double_type (int1l, int1h, &int1l, &int1h, type);
- int2l = TREE_INT_CST_LOW (arg2);
- int2h = TREE_INT_CST_HIGH (arg2);
+ /* The sign of the division is according to operand two, that
+ does the correct thing for POINTER_PLUS_EXPR where we want
+ a signed division. */
+ uns = TYPE_UNSIGNED (TREE_TYPE (arg2));
+ if (TREE_CODE (TREE_TYPE (arg2)) == INTEGER_TYPE
+ && TYPE_IS_SIZETYPE (TREE_TYPE (arg2)))
+ uns = false;
- div_and_round_double (code, uns, int1l, int1h, int2l, int2h,
- &quol, &quoh, &reml, &remh);
- if (remh != 0 || reml != 0)
- return NULL_TREE;
+ quo = double_int_divmod (tree_to_double_int (arg1),
+ tree_to_double_int (arg2),
+ uns, code, &rem);
- return build_int_cst_wide (type, quol, quoh);
+ if (double_int_zero_p (rem))
+ return build_int_cst_wide (TREE_TYPE (arg1), quo.low, quo.high);
+
+ return NULL_TREE;
}
\f
/* This is nonzero if we should defer warnings about undefined
locus = input_location;
else
locus = gimple_location (stmt);
- warning (OPT_Wstrict_overflow, "%H%s", &locus, warnmsg);
+ warning_at (locus, OPT_Wstrict_overflow, "%s", warnmsg);
}
/* Stop deferring overflow warnings, ignoring any deferred
CASE_FLT_FN (BUILT_IN_NEARBYINT):
CASE_FLT_FN (BUILT_IN_RINT):
return !flag_rounding_math;
-
+
default:
break;
}
&& TYPE_OVERFLOW_WRAPS (type));
case FIXED_CST:
- case REAL_CST:
case NEGATE_EXPR:
return true;
+ case REAL_CST:
+ /* We want to canonicalize to positive real constants. Pretend
+ that only negative ones can be easily negated. */
+ return REAL_VALUE_NEGATIVE (TREE_REAL_CST (t));
+
case COMPLEX_CST:
return negate_expr_p (TREE_REALPART (t))
&& negate_expr_p (TREE_IMAGPART (t));
returned. */
static tree
-fold_negate_expr (tree t)
+fold_negate_expr (location_t loc, tree t)
{
tree type = TREE_TYPE (t);
tree tem;
/* Convert - (~A) to A + 1. */
case BIT_NOT_EXPR:
if (INTEGRAL_TYPE_P (type))
- return fold_build2 (PLUS_EXPR, type, TREE_OPERAND (t, 0),
+ return fold_build2_loc (loc, PLUS_EXPR, type, TREE_OPERAND (t, 0),
build_int_cst (type, 1));
break;
-
+
case INTEGER_CST:
tem = fold_negate_const (t, type);
if (TREE_OVERFLOW (tem) == TREE_OVERFLOW (t)
case COMPLEX_EXPR:
if (negate_expr_p (t))
- return fold_build2 (COMPLEX_EXPR, type,
- fold_negate_expr (TREE_OPERAND (t, 0)),
- fold_negate_expr (TREE_OPERAND (t, 1)));
+ return fold_build2_loc (loc, COMPLEX_EXPR, type,
+ fold_negate_expr (loc, TREE_OPERAND (t, 0)),
+ fold_negate_expr (loc, TREE_OPERAND (t, 1)));
break;
-
+
case CONJ_EXPR:
if (negate_expr_p (t))
- return fold_build1 (CONJ_EXPR, type,
- fold_negate_expr (TREE_OPERAND (t, 0)));
+ return fold_build1_loc (loc, CONJ_EXPR, type,
+ fold_negate_expr (loc, TREE_OPERAND (t, 0)));
break;
case NEGATE_EXPR:
TREE_OPERAND (t, 1)))
{
tem = negate_expr (TREE_OPERAND (t, 1));
- return fold_build2 (MINUS_EXPR, type,
+ return fold_build2_loc (loc, MINUS_EXPR, type,
tem, TREE_OPERAND (t, 0));
}
if (negate_expr_p (TREE_OPERAND (t, 0)))
{
tem = negate_expr (TREE_OPERAND (t, 0));
- return fold_build2 (MINUS_EXPR, type,
+ return fold_build2_loc (loc, MINUS_EXPR, type,
tem, TREE_OPERAND (t, 1));
}
}
if (!HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type))
&& !HONOR_SIGNED_ZEROS (TYPE_MODE (type))
&& reorder_operands_p (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1)))
- return fold_build2 (MINUS_EXPR, type,
+ return fold_build2_loc (loc, MINUS_EXPR, type,
TREE_OPERAND (t, 1), TREE_OPERAND (t, 0));
break;
{
tem = TREE_OPERAND (t, 1);
if (negate_expr_p (tem))
- return fold_build2 (TREE_CODE (t), type,
+ return fold_build2_loc (loc, TREE_CODE (t), type,
TREE_OPERAND (t, 0), negate_expr (tem));
tem = TREE_OPERAND (t, 0);
if (negate_expr_p (tem))
- return fold_build2 (TREE_CODE (t), type,
+ return fold_build2_loc (loc, TREE_CODE (t), type,
negate_expr (tem), TREE_OPERAND (t, 1));
}
break;
&& (TREE_CODE (tem) != INTEGER_CST
|| integer_onep (tem)))
fold_overflow_warning (warnmsg, WARN_STRICT_OVERFLOW_MISC);
- return fold_build2 (TREE_CODE (t), type,
+ return fold_build2_loc (loc, TREE_CODE (t), type,
TREE_OPERAND (t, 0), negate_expr (tem));
}
tem = TREE_OPERAND (t, 0);
&& (TREE_CODE (tem) != INTEGER_CST
|| tree_int_cst_equal (tem, TYPE_MIN_VALUE (type))))
fold_overflow_warning (warnmsg, WARN_STRICT_OVERFLOW_MISC);
- return fold_build2 (TREE_CODE (t), type,
+ return fold_build2_loc (loc, TREE_CODE (t), type,
negate_expr (tem), TREE_OPERAND (t, 1));
}
}
{
tem = strip_float_extensions (t);
if (tem != t && negate_expr_p (tem))
- return fold_convert (type, negate_expr (tem));
+ return fold_convert_loc (loc, type, negate_expr (tem));
}
break;
fndecl = get_callee_fndecl (t);
arg = negate_expr (CALL_EXPR_ARG (t, 0));
- return build_call_expr (fndecl, 1, arg);
+ return build_call_expr_loc (loc, fndecl, 1, arg);
}
break;
tree ntype = TYPE_UNSIGNED (type)
? signed_type_for (type)
: unsigned_type_for (type);
- tree temp = fold_convert (ntype, TREE_OPERAND (t, 0));
- temp = fold_build2 (RSHIFT_EXPR, ntype, temp, op1);
- return fold_convert (type, temp);
+ tree temp = fold_convert_loc (loc, ntype, TREE_OPERAND (t, 0));
+ temp = fold_build2_loc (loc, RSHIFT_EXPR, ntype, temp, op1);
+ return fold_convert_loc (loc, type, temp);
}
}
break;
negate_expr (tree t)
{
tree type, tem;
+ location_t loc;
if (t == NULL_TREE)
return NULL_TREE;
+ loc = EXPR_LOCATION (t);
type = TREE_TYPE (t);
STRIP_SIGN_NOPS (t);
- tem = fold_negate_expr (t);
+ tem = fold_negate_expr (loc, t);
if (!tem)
- tem = build1 (NEGATE_EXPR, TREE_TYPE (t), t);
- return fold_convert (type, tem);
+ tem = build1_loc (loc, NEGATE_EXPR, TREE_TYPE (t), t);
+ return fold_convert_loc (loc, type, tem);
}
\f
/* Split a tree IN into a constant, literal and variable parts that could be
return var;
}
-/* Re-associate trees split by the above function. T1 and T2 are either
- expressions to associate or null. Return the new expression, if any. If
+/* Re-associate trees split by the above function. T1 and T2 are
+ either expressions to associate or null. Return the new
+ expression, if any. LOC is the location of the new expression. If
we build an operation, do it in TYPE and with CODE. */
static tree
-associate_trees (tree t1, tree t2, enum tree_code code, tree type)
+associate_trees (location_t loc, tree t1, tree t2, enum tree_code code, tree type)
{
if (t1 == 0)
return t2;
if (code == PLUS_EXPR)
{
if (TREE_CODE (t1) == NEGATE_EXPR)
- return build2 (MINUS_EXPR, type, fold_convert (type, t2),
- fold_convert (type, TREE_OPERAND (t1, 0)));
+ return build2_loc (loc, MINUS_EXPR, type,
+ fold_convert_loc (loc, type, t2),
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (t1, 0)));
else if (TREE_CODE (t2) == NEGATE_EXPR)
- return build2 (MINUS_EXPR, type, fold_convert (type, t1),
- fold_convert (type, TREE_OPERAND (t2, 0)));
+ return build2_loc (loc, MINUS_EXPR, type,
+ fold_convert_loc (loc, type, t1),
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (t2, 0)));
else if (integer_zerop (t2))
- return fold_convert (type, t1);
+ return fold_convert_loc (loc, type, t1);
}
else if (code == MINUS_EXPR)
{
if (integer_zerop (t2))
- return fold_convert (type, t1);
+ return fold_convert_loc (loc, type, t1);
}
- return build2 (code, type, fold_convert (type, t1),
- fold_convert (type, t2));
+ return build2_loc (loc, code, type, fold_convert_loc (loc, type, t1),
+ fold_convert_loc (loc, type, t2));
}
- return fold_build2 (code, type, fold_convert (type, t1),
- fold_convert (type, t2));
+ return fold_build2_loc (loc, code, type, fold_convert_loc (loc, type, t1),
+ fold_convert_loc (loc, type, t2));
}
\f
/* Check whether TYPE1 and TYPE2 are equivalent integer types, suitable
tree
int_const_binop (enum tree_code code, const_tree arg1, const_tree arg2, int notrunc)
{
- unsigned HOST_WIDE_INT int1l, int2l;
- HOST_WIDE_INT int1h, int2h;
- unsigned HOST_WIDE_INT low;
- HOST_WIDE_INT hi;
- unsigned HOST_WIDE_INT garbagel;
- HOST_WIDE_INT garbageh;
+ double_int op1, op2, res, tmp;
tree t;
tree type = TREE_TYPE (arg1);
- int uns = TYPE_UNSIGNED (type);
- int is_sizetype
+ bool uns = TYPE_UNSIGNED (type);
+ bool is_sizetype
= (TREE_CODE (type) == INTEGER_TYPE && TYPE_IS_SIZETYPE (type));
- int overflow = 0;
+ bool overflow = false;
- int1l = TREE_INT_CST_LOW (arg1);
- int1h = TREE_INT_CST_HIGH (arg1);
- int2l = TREE_INT_CST_LOW (arg2);
- int2h = TREE_INT_CST_HIGH (arg2);
+ op1 = tree_to_double_int (arg1);
+ op2 = tree_to_double_int (arg2);
switch (code)
{
case BIT_IOR_EXPR:
- low = int1l | int2l, hi = int1h | int2h;
+ res = double_int_ior (op1, op2);
break;
case BIT_XOR_EXPR:
- low = int1l ^ int2l, hi = int1h ^ int2h;
+ res = double_int_xor (op1, op2);
break;
case BIT_AND_EXPR:
- low = int1l & int2l, hi = int1h & int2h;
+ res = double_int_and (op1, op2);
break;
case RSHIFT_EXPR:
- int2l = -int2l;
+ res = double_int_rshift (op1, double_int_to_shwi (op2),
+ TYPE_PRECISION (type), !uns);
+ break;
+
case LSHIFT_EXPR:
/* It's unclear from the C standard whether shifts can overflow.
The following code ignores overflow; perhaps a C standard
interpretation ruling is needed. */
- lshift_double (int1l, int1h, int2l, TYPE_PRECISION (type),
- &low, &hi, !uns);
+ res = double_int_lshift (op1, double_int_to_shwi (op2),
+ TYPE_PRECISION (type), !uns);
break;
case RROTATE_EXPR:
- int2l = - int2l;
+ res = double_int_rrotate (op1, double_int_to_shwi (op2),
+ TYPE_PRECISION (type));
+ break;
+
case LROTATE_EXPR:
- lrotate_double (int1l, int1h, int2l, TYPE_PRECISION (type),
- &low, &hi);
+ res = double_int_lrotate (op1, double_int_to_shwi (op2),
+ TYPE_PRECISION (type));
break;
case PLUS_EXPR:
- overflow = add_double (int1l, int1h, int2l, int2h, &low, &hi);
+ overflow = add_double (op1.low, op1.high, op2.low, op2.high,
+ &res.low, &res.high);
break;
case MINUS_EXPR:
- neg_double (int2l, int2h, &low, &hi);
- add_double (int1l, int1h, low, hi, &low, &hi);
- overflow = OVERFLOW_SUM_SIGN (hi, int2h, int1h);
+ neg_double (op2.low, op2.high, &res.low, &res.high);
+ add_double (op1.low, op1.high, res.low, res.high,
+ &res.low, &res.high);
+ overflow = OVERFLOW_SUM_SIGN (res.high, op2.high, op1.high);
break;
case MULT_EXPR:
- overflow = mul_double (int1l, int1h, int2l, int2h, &low, &hi);
+ overflow = mul_double (op1.low, op1.high, op2.low, op2.high,
+ &res.low, &res.high);
break;
case TRUNC_DIV_EXPR:
case FLOOR_DIV_EXPR: case CEIL_DIV_EXPR:
case EXACT_DIV_EXPR:
/* This is a shortcut for a common special case. */
- if (int2h == 0 && (HOST_WIDE_INT) int2l > 0
+ if (op2.high == 0 && (HOST_WIDE_INT) op2.low > 0
&& !TREE_OVERFLOW (arg1)
&& !TREE_OVERFLOW (arg2)
- && int1h == 0 && (HOST_WIDE_INT) int1l >= 0)
+ && op1.high == 0 && (HOST_WIDE_INT) op1.low >= 0)
{
if (code == CEIL_DIV_EXPR)
- int1l += int2l - 1;
+ op1.low += op2.low - 1;
- low = int1l / int2l, hi = 0;
+ res.low = op1.low / op2.low, res.high = 0;
break;
}
/* ... fall through ... */
case ROUND_DIV_EXPR:
- if (int2h == 0 && int2l == 0)
+ if (double_int_zero_p (op2))
return NULL_TREE;
- if (int2h == 0 && int2l == 1)
+ if (double_int_one_p (op2))
{
- low = int1l, hi = int1h;
+ res = op1;
break;
}
- if (int1l == int2l && int1h == int2h
- && ! (int1l == 0 && int1h == 0))
+ if (double_int_equal_p (op1, op2)
+ && ! double_int_zero_p (op1))
{
- low = 1, hi = 0;
+ res = double_int_one;
break;
}
- overflow = div_and_round_double (code, uns, int1l, int1h, int2l, int2h,
- &low, &hi, &garbagel, &garbageh);
+ overflow = div_and_round_double (code, uns,
+ op1.low, op1.high, op2.low, op2.high,
+ &res.low, &res.high,
+ &tmp.low, &tmp.high);
break;
case TRUNC_MOD_EXPR:
case FLOOR_MOD_EXPR: case CEIL_MOD_EXPR:
/* This is a shortcut for a common special case. */
- if (int2h == 0 && (HOST_WIDE_INT) int2l > 0
+ if (op2.high == 0 && (HOST_WIDE_INT) op2.low > 0
&& !TREE_OVERFLOW (arg1)
&& !TREE_OVERFLOW (arg2)
- && int1h == 0 && (HOST_WIDE_INT) int1l >= 0)
+ && op1.high == 0 && (HOST_WIDE_INT) op1.low >= 0)
{
if (code == CEIL_MOD_EXPR)
- int1l += int2l - 1;
- low = int1l % int2l, hi = 0;
+ op1.low += op2.low - 1;
+ res.low = op1.low % op2.low, res.high = 0;
break;
}
/* ... fall through ... */
case ROUND_MOD_EXPR:
- if (int2h == 0 && int2l == 0)
+ if (double_int_zero_p (op2))
return NULL_TREE;
overflow = div_and_round_double (code, uns,
- int1l, int1h, int2l, int2h,
- &garbagel, &garbageh, &low, &hi);
+ op1.low, op1.high, op2.low, op2.high,
+ &tmp.low, &tmp.high,
+ &res.low, &res.high);
break;
case MIN_EXPR:
- case MAX_EXPR:
- if (uns)
- low = (((unsigned HOST_WIDE_INT) int1h
- < (unsigned HOST_WIDE_INT) int2h)
- || (((unsigned HOST_WIDE_INT) int1h
- == (unsigned HOST_WIDE_INT) int2h)
- && int1l < int2l));
- else
- low = (int1h < int2h
- || (int1h == int2h && int1l < int2l));
+ res = double_int_min (op1, op2, uns);
+ break;
- if (low == (code == MIN_EXPR))
- low = int1l, hi = int1h;
- else
- low = int2l, hi = int2h;
+ case MAX_EXPR:
+ res = double_int_max (op1, op2, uns);
break;
default:
if (notrunc)
{
- t = build_int_cst_wide (TREE_TYPE (arg1), low, hi);
+ t = build_int_cst_wide (TREE_TYPE (arg1), res.low, res.high);
/* Propagate overflow flags ourselves. */
if (((!uns || is_sizetype) && overflow)
}
}
else
- t = force_fit_type_double (TREE_TYPE (arg1), low, hi, 1,
+ t = force_fit_type_double (TREE_TYPE (arg1), res, 1,
((!uns || is_sizetype) && overflow)
| TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2));
/* Combine two constants ARG1 and ARG2 under operation CODE to produce a new
constant. We assume ARG1 and ARG2 have the same data type, or at least
are the same kind of constant and the same machine mode. Return zero if
- combining the constants is not allowed in the current operating mode.
-
- If NOTRUNC is nonzero, do not truncate the result to fit the data type. */
+ combining the constants is not allowed in the current operating mode. */
static tree
-const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
+const_binop (enum tree_code code, tree arg1, tree arg2)
{
/* Sanity check for the recursive cases. */
if (!arg1 || !arg2)
STRIP_NOPS (arg2);
if (TREE_CODE (arg1) == INTEGER_CST)
- return int_const_binop (code, arg1, arg2, notrunc);
+ return int_const_binop (code, arg1, arg2, 0);
if (TREE_CODE (arg1) == REAL_CST)
{
{
case PLUS_EXPR:
case MINUS_EXPR:
- real = const_binop (code, r1, r2, notrunc);
- imag = const_binop (code, i1, i2, notrunc);
+ real = const_binop (code, r1, r2);
+ imag = const_binop (code, i1, i2);
break;
case MULT_EXPR:
+ if (COMPLEX_FLOAT_TYPE_P (type))
+ return do_mpc_arg2 (arg1, arg2, type,
+ /* do_nonfinite= */ folding_initializer,
+ mpc_mul);
+
real = const_binop (MINUS_EXPR,
- const_binop (MULT_EXPR, r1, r2, notrunc),
- const_binop (MULT_EXPR, i1, i2, notrunc),
- notrunc);
+ const_binop (MULT_EXPR, r1, r2),
+ const_binop (MULT_EXPR, i1, i2));
imag = const_binop (PLUS_EXPR,
- const_binop (MULT_EXPR, r1, i2, notrunc),
- const_binop (MULT_EXPR, i1, r2, notrunc),
- notrunc);
+ const_binop (MULT_EXPR, r1, i2),
+ const_binop (MULT_EXPR, i1, r2));
break;
case RDIV_EXPR:
+ if (COMPLEX_FLOAT_TYPE_P (type))
+ return do_mpc_arg2 (arg1, arg2, type,
+ /* do_nonfinite= */ folding_initializer,
+ mpc_div);
+ /* Fallthru ... */
+ case TRUNC_DIV_EXPR:
+ case CEIL_DIV_EXPR:
+ case FLOOR_DIV_EXPR:
+ case ROUND_DIV_EXPR:
+ if (flag_complex_method == 0)
{
+ /* Keep this algorithm in sync with
+ tree-complex.c:expand_complex_div_straight().
+
+ Expand complex division to scalars, straightforward algorithm.
+ a / b = ((ar*br + ai*bi)/t) + i((ai*br - ar*bi)/t)
+ t = br*br + bi*bi
+ */
tree magsquared
= const_binop (PLUS_EXPR,
- const_binop (MULT_EXPR, r2, r2, notrunc),
- const_binop (MULT_EXPR, i2, i2, notrunc),
- notrunc);
+ const_binop (MULT_EXPR, r2, r2),
+ const_binop (MULT_EXPR, i2, i2));
tree t1
= const_binop (PLUS_EXPR,
- const_binop (MULT_EXPR, r1, r2, notrunc),
- const_binop (MULT_EXPR, i1, i2, notrunc),
- notrunc);
+ const_binop (MULT_EXPR, r1, r2),
+ const_binop (MULT_EXPR, i1, i2));
tree t2
= const_binop (MINUS_EXPR,
- const_binop (MULT_EXPR, i1, r2, notrunc),
- const_binop (MULT_EXPR, r1, i2, notrunc),
- notrunc);
+ const_binop (MULT_EXPR, i1, r2),
+ const_binop (MULT_EXPR, r1, i2));
- if (INTEGRAL_TYPE_P (TREE_TYPE (r1)))
- code = TRUNC_DIV_EXPR;
+ real = const_binop (code, t1, magsquared);
+ imag = const_binop (code, t2, magsquared);
+ }
+ else
+ {
+ /* Keep this algorithm in sync with
+ tree-complex.c:expand_complex_div_wide().
- real = const_binop (code, t1, magsquared, notrunc);
- imag = const_binop (code, t2, magsquared, notrunc);
+ Expand complex division to scalars, modified algorithm to minimize
+ overflow with wide input ranges. */
+ tree compare = fold_build2 (LT_EXPR, boolean_type_node,
+ fold_abs_const (r2, TREE_TYPE (type)),
+ fold_abs_const (i2, TREE_TYPE (type)));
+
+ if (integer_nonzerop (compare))
+ {
+ /* In the TRUE branch, we compute
+ ratio = br/bi;
+ div = (br * ratio) + bi;
+ tr = (ar * ratio) + ai;
+ ti = (ai * ratio) - ar;
+ tr = tr / div;
+ ti = ti / div; */
+ tree ratio = const_binop (code, r2, i2);
+ tree div = const_binop (PLUS_EXPR, i2,
+ const_binop (MULT_EXPR, r2, ratio));
+ real = const_binop (MULT_EXPR, r1, ratio);
+ real = const_binop (PLUS_EXPR, real, i1);
+ real = const_binop (code, real, div);
+
+ imag = const_binop (MULT_EXPR, i1, ratio);
+ imag = const_binop (MINUS_EXPR, imag, r1);
+ imag = const_binop (code, imag, div);
+ }
+ else
+ {
+ /* In the FALSE branch, we compute
+ ratio = d/c;
+ divisor = (d * ratio) + c;
+ tr = (b * ratio) + a;
+ ti = b - (a * ratio);
+ tr = tr / div;
+ ti = ti / div; */
+ tree ratio = const_binop (code, i2, r2);
+ tree div = const_binop (PLUS_EXPR, r2,
+ const_binop (MULT_EXPR, i2, ratio));
+
+ real = const_binop (MULT_EXPR, i1, ratio);
+ real = const_binop (PLUS_EXPR, real, r1);
+ real = const_binop (code, real, div);
+
+ imag = const_binop (MULT_EXPR, r1, ratio);
+ imag = const_binop (MINUS_EXPR, i1, imag);
+ imag = const_binop (code, imag, div);
+ }
}
break;
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);
{
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);
-
+
+ elem = const_binop (code, elem1, elem2);
+
/* 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 build_vector(type, nreverse(list));
}
return NULL_TREE;
}
If the operands are constant, so is the result. */
tree
-size_binop (enum tree_code code, tree arg0, tree arg1)
+size_binop_loc (location_t loc, enum tree_code code, tree arg0, tree arg1)
{
tree type = TREE_TYPE (arg0);
return int_const_binop (code, arg0, arg1, 0);
}
- return fold_build2 (code, type, arg0, arg1);
+ return fold_build2_loc (loc, code, type, arg0, arg1);
}
/* Given two values, either both of sizetype or both of bitsizetype,
in signed type corresponding to the type of the operands. */
tree
-size_diffop (tree arg0, tree arg1)
+size_diffop_loc (location_t loc, tree arg0, tree arg1)
{
tree type = TREE_TYPE (arg0);
tree ctype;
/* If the type is already signed, just do the simple thing. */
if (!TYPE_UNSIGNED (type))
- return size_binop (MINUS_EXPR, arg0, arg1);
+ return size_binop_loc (loc, MINUS_EXPR, arg0, arg1);
if (type == sizetype)
ctype = ssizetype;
type and subtract. The hardware will do the right thing with any
overflow in the subtraction. */
if (TREE_CODE (arg0) != INTEGER_CST || TREE_CODE (arg1) != INTEGER_CST)
- return size_binop (MINUS_EXPR, fold_convert (ctype, arg0),
- fold_convert (ctype, arg1));
+ return size_binop_loc (loc, MINUS_EXPR,
+ fold_convert_loc (loc, ctype, arg0),
+ fold_convert_loc (loc, ctype, arg1));
/* If ARG0 is larger than ARG1, subtract and return the result in CTYPE.
Otherwise, subtract the other way, convert to CTYPE (we know that can't
if (tree_int_cst_equal (arg0, arg1))
return build_int_cst (ctype, 0);
else if (tree_int_cst_lt (arg1, arg0))
- return fold_convert (ctype, size_binop (MINUS_EXPR, arg0, arg1));
+ return fold_convert_loc (loc, ctype,
+ size_binop_loc (loc, MINUS_EXPR, arg0, arg1));
else
- return size_binop (MINUS_EXPR, build_int_cst (ctype, 0),
- fold_convert (ctype, size_binop (MINUS_EXPR,
- arg1, arg0)));
+ return size_binop_loc (loc, MINUS_EXPR, build_int_cst (ctype, 0),
+ fold_convert_loc (loc, ctype,
+ size_binop_loc (loc,
+ MINUS_EXPR,
+ arg1, arg0)));
}
\f
/* A subroutine of fold_convert_const handling conversions of an
/* Given an integer constant, make new constant with new type,
appropriately sign-extended or truncated. */
- t = force_fit_type_double (type, TREE_INT_CST_LOW (arg1),
- TREE_INT_CST_HIGH (arg1),
- /* Don't set the overflow when
- converting from a pointer, */
- !POINTER_TYPE_P (TREE_TYPE (arg1))
- /* or to a sizetype with same signedness
- and the precision is unchanged.
- ??? sizetype is always sign-extended,
- but its signedness depends on the
- frontend. Thus we see spurious overflows
- here if we do not check this. */
- && !((TYPE_PRECISION (TREE_TYPE (arg1))
- == TYPE_PRECISION (type))
- && (TYPE_UNSIGNED (TREE_TYPE (arg1))
- == TYPE_UNSIGNED (type))
- && ((TREE_CODE (TREE_TYPE (arg1)) == INTEGER_TYPE
- && TYPE_IS_SIZETYPE (TREE_TYPE (arg1)))
- || (TREE_CODE (type) == INTEGER_TYPE
- && TYPE_IS_SIZETYPE (type)))),
+ t = force_fit_type_double (type, tree_to_double_int (arg1),
+ !POINTER_TYPE_P (TREE_TYPE (arg1)),
(TREE_INT_CST_HIGH (arg1) < 0
&& (TYPE_UNSIGNED (type)
< TYPE_UNSIGNED (TREE_TYPE (arg1))))
C and C++ standards that simply state that the behavior of
FP-to-integer conversion is unspecified upon overflow. */
- HOST_WIDE_INT high, low;
+ double_int val;
REAL_VALUE_TYPE r;
REAL_VALUE_TYPE x = TREE_REAL_CST (arg1);
if (REAL_VALUE_ISNAN (r))
{
overflow = 1;
- high = 0;
- low = 0;
+ val = double_int_zero;
}
/* See if R is less than the lower bound or greater than the
if (REAL_VALUES_LESS (r, l))
{
overflow = 1;
- high = TREE_INT_CST_HIGH (lt);
- low = TREE_INT_CST_LOW (lt);
+ val = tree_to_double_int (lt);
}
}
if (REAL_VALUES_LESS (u, r))
{
overflow = 1;
- high = TREE_INT_CST_HIGH (ut);
- low = TREE_INT_CST_LOW (ut);
+ val = tree_to_double_int (ut);
}
}
}
if (! overflow)
- REAL_VALUE_TO_INT (&low, &high, r);
+ real_to_integer2 ((HOST_WIDE_INT *) &val.low, &val.high, &r);
- t = force_fit_type_double (type, low, high, -1,
- overflow | TREE_OVERFLOW (arg1));
+ t = force_fit_type_double (type, val, -1, overflow | TREE_OVERFLOW (arg1));
return t;
}
mode = TREE_FIXED_CST (arg1).mode;
if (GET_MODE_FBIT (mode) < 2 * HOST_BITS_PER_WIDE_INT)
{
- lshift_double (temp.low, temp.high,
- - GET_MODE_FBIT (mode), 2 * HOST_BITS_PER_WIDE_INT,
- &temp.low, &temp.high, SIGNED_FIXED_POINT_MODE_P (mode));
+ temp = double_int_rshift (temp, GET_MODE_FBIT (mode),
+ HOST_BITS_PER_DOUBLE_INT,
+ SIGNED_FIXED_POINT_MODE_P (mode));
/* Left shift temp to temp_trunc by fbit. */
- lshift_double (temp.low, temp.high,
- GET_MODE_FBIT (mode), 2 * HOST_BITS_PER_WIDE_INT,
- &temp_trunc.low, &temp_trunc.high,
- SIGNED_FIXED_POINT_MODE_P (mode));
+ temp_trunc = double_int_lshift (temp, GET_MODE_FBIT (mode),
+ HOST_BITS_PER_DOUBLE_INT,
+ SIGNED_FIXED_POINT_MODE_P (mode));
}
else
{
- temp.low = 0;
- temp.high = 0;
- temp_trunc.low = 0;
- temp_trunc.high = 0;
+ temp = double_int_zero;
+ temp_trunc = double_int_zero;
}
/* If FIXED_CST is negative, we need to round the value toward 0.
By checking if the fractional bits are not zero to add 1 to temp. */
- if (SIGNED_FIXED_POINT_MODE_P (mode) && temp_trunc.high < 0
+ if (SIGNED_FIXED_POINT_MODE_P (mode)
+ && double_int_negative_p (temp_trunc)
&& !double_int_equal_p (TREE_FIXED_CST (arg1).data, temp_trunc))
- {
- double_int one;
- one.low = 1;
- one.high = 0;
- temp = double_int_add (temp, one);
- }
+ temp = double_int_add (temp, double_int_one);
/* Given a fixed-point constant, make new constant with new type,
appropriately sign-extended or truncated. */
- t = force_fit_type_double (type, temp.low, temp.high, -1,
- (temp.high < 0
+ t = force_fit_type_double (type, temp, -1,
+ (double_int_negative_p (temp)
&& (TYPE_UNSIGNED (type)
< TYPE_UNSIGNED (TREE_TYPE (arg1))))
| TREE_OVERFLOW (arg1));
static tree
build_zero_vector (tree type)
{
- tree elem, list;
- int i, units;
+ tree t;
- elem = fold_convert_const (NOP_EXPR, TREE_TYPE (type), integer_zero_node);
- units = TYPE_VECTOR_SUBPARTS (type);
-
- list = NULL_TREE;
- for (i = 0; i < units; i++)
- list = tree_cons (NULL_TREE, elem, list);
- return build_vector (type, list);
+ t = fold_convert_const (NOP_EXPR, TREE_TYPE (type), integer_zero_node);
+ return build_vector_from_val (type, t);
}
/* Returns true, if ARG is convertible to TYPE using a NOP_EXPR. */
simple conversions in preference to calling the front-end's convert. */
tree
-fold_convert (tree type, tree arg)
+fold_convert_loc (location_t loc, tree type, tree arg)
{
tree orig = TREE_TYPE (arg);
tree tem;
return error_mark_node;
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (orig))
- return fold_build1 (NOP_EXPR, type, arg);
+ return fold_build1_loc (loc, NOP_EXPR, type, arg);
switch (TREE_CODE (type))
{
+ case POINTER_TYPE:
+ case REFERENCE_TYPE:
+ /* Handle conversions between pointers to different address spaces. */
+ if (POINTER_TYPE_P (orig)
+ && (TYPE_ADDR_SPACE (TREE_TYPE (type))
+ != TYPE_ADDR_SPACE (TREE_TYPE (orig))))
+ return fold_build1_loc (loc, ADDR_SPACE_CONVERT_EXPR, type, arg);
+ /* fall through */
+
case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
- case POINTER_TYPE: case REFERENCE_TYPE:
case OFFSET_TYPE:
if (TREE_CODE (arg) == INTEGER_CST)
{
}
if (INTEGRAL_TYPE_P (orig) || POINTER_TYPE_P (orig)
|| TREE_CODE (orig) == OFFSET_TYPE)
- return fold_build1 (NOP_EXPR, type, arg);
+ return fold_build1_loc (loc, NOP_EXPR, type, arg);
if (TREE_CODE (orig) == COMPLEX_TYPE)
- {
- tem = fold_build1 (REALPART_EXPR, TREE_TYPE (orig), arg);
- return fold_convert (type, tem);
- }
+ return fold_convert_loc (loc, type,
+ fold_build1_loc (loc, REALPART_EXPR,
+ TREE_TYPE (orig), arg));
gcc_assert (TREE_CODE (orig) == VECTOR_TYPE
&& tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (orig)));
- return fold_build1 (NOP_EXPR, type, arg);
+ return fold_build1_loc (loc, NOP_EXPR, type, arg);
case REAL_TYPE:
if (TREE_CODE (arg) == INTEGER_CST)
case INTEGER_TYPE:
case BOOLEAN_TYPE: case ENUMERAL_TYPE:
case POINTER_TYPE: case REFERENCE_TYPE:
- return fold_build1 (FLOAT_EXPR, type, arg);
+ return fold_build1_loc (loc, FLOAT_EXPR, type, arg);
case REAL_TYPE:
- return fold_build1 (NOP_EXPR, type, arg);
+ return fold_build1_loc (loc, NOP_EXPR, type, arg);
case FIXED_POINT_TYPE:
- return fold_build1 (FIXED_CONVERT_EXPR, type, arg);
+ return fold_build1_loc (loc, FIXED_CONVERT_EXPR, type, arg);
case COMPLEX_TYPE:
- tem = fold_build1 (REALPART_EXPR, TREE_TYPE (orig), arg);
- return fold_convert (type, tem);
+ tem = fold_build1_loc (loc, REALPART_EXPR, TREE_TYPE (orig), arg);
+ return fold_convert_loc (loc, type, tem);
default:
gcc_unreachable ();
{
tem = fold_convert_const (FIXED_CONVERT_EXPR, type, arg);
if (tem != NULL_TREE)
- return tem;
+ goto fold_convert_exit;
}
switch (TREE_CODE (orig))
case ENUMERAL_TYPE:
case BOOLEAN_TYPE:
case REAL_TYPE:
- return fold_build1 (FIXED_CONVERT_EXPR, type, arg);
+ return fold_build1_loc (loc, FIXED_CONVERT_EXPR, type, arg);
case COMPLEX_TYPE:
- tem = fold_build1 (REALPART_EXPR, TREE_TYPE (orig), arg);
- return fold_convert (type, tem);
+ tem = fold_build1_loc (loc, REALPART_EXPR, TREE_TYPE (orig), arg);
+ return fold_convert_loc (loc, type, tem);
default:
gcc_unreachable ();
case POINTER_TYPE: case REFERENCE_TYPE:
case REAL_TYPE:
case FIXED_POINT_TYPE:
- return build2 (COMPLEX_EXPR, type,
- fold_convert (TREE_TYPE (type), arg),
- fold_convert (TREE_TYPE (type), integer_zero_node));
+ return fold_build2_loc (loc, COMPLEX_EXPR, type,
+ fold_convert_loc (loc, TREE_TYPE (type), arg),
+ fold_convert_loc (loc, TREE_TYPE (type),
+ integer_zero_node));
case COMPLEX_TYPE:
{
tree rpart, ipart;
if (TREE_CODE (arg) == COMPLEX_EXPR)
{
- rpart = fold_convert (TREE_TYPE (type), TREE_OPERAND (arg, 0));
- ipart = fold_convert (TREE_TYPE (type), TREE_OPERAND (arg, 1));
- return fold_build2 (COMPLEX_EXPR, type, rpart, ipart);
+ rpart = fold_convert_loc (loc, TREE_TYPE (type),
+ TREE_OPERAND (arg, 0));
+ ipart = fold_convert_loc (loc, TREE_TYPE (type),
+ TREE_OPERAND (arg, 1));
+ return fold_build2_loc (loc, COMPLEX_EXPR, type, rpart, ipart);
}
arg = save_expr (arg);
- rpart = fold_build1 (REALPART_EXPR, TREE_TYPE (orig), arg);
- ipart = fold_build1 (IMAGPART_EXPR, TREE_TYPE (orig), arg);
- rpart = fold_convert (TREE_TYPE (type), rpart);
- ipart = fold_convert (TREE_TYPE (type), ipart);
- return fold_build2 (COMPLEX_EXPR, type, rpart, ipart);
+ rpart = fold_build1_loc (loc, REALPART_EXPR, TREE_TYPE (orig), arg);
+ ipart = fold_build1_loc (loc, IMAGPART_EXPR, TREE_TYPE (orig), arg);
+ rpart = fold_convert_loc (loc, TREE_TYPE (type), rpart);
+ ipart = fold_convert_loc (loc, TREE_TYPE (type), ipart);
+ return fold_build2_loc (loc, COMPLEX_EXPR, type, rpart, ipart);
}
default:
gcc_assert (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (orig)));
gcc_assert (INTEGRAL_TYPE_P (orig) || POINTER_TYPE_P (orig)
|| TREE_CODE (orig) == VECTOR_TYPE);
- return fold_build1 (VIEW_CONVERT_EXPR, type, arg);
+ return fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, arg);
case VOID_TYPE:
tem = fold_ignored_result (arg);
- if (TREE_CODE (tem) == MODIFY_EXPR)
- return tem;
- return fold_build1 (NOP_EXPR, type, tem);
+ return fold_build1_loc (loc, NOP_EXPR, type, tem);
default:
gcc_unreachable ();
}
+ fold_convert_exit:
+ protected_set_expr_location_unshare (tem, loc);
+ return tem;
}
\f
/* Return false if expr can be assumed not to be an lvalue, true
case SSA_NAME:
case COMPONENT_REF:
+ case MEM_REF:
case INDIRECT_REF:
- case ALIGN_INDIRECT_REF:
- case MISALIGNED_INDIRECT_REF:
case ARRAY_REF:
case ARRAY_RANGE_REF:
case BIT_FIELD_REF:
case TARGET_EXPR:
case COND_EXPR:
case BIND_EXPR:
- case MIN_EXPR:
- case MAX_EXPR:
break;
default:
/* Return an expr equal to X but certainly not valid as an lvalue. */
tree
-non_lvalue (tree x)
+non_lvalue_loc (location_t loc, tree x)
{
/* While we are in GIMPLE, NON_LVALUE_EXPR doesn't mean anything to
us. */
if (! maybe_lvalue_p (x))
return x;
- return build1 (NON_LVALUE_EXPR, TREE_TYPE (x), x);
+ return build1_loc (loc, NON_LVALUE_EXPR, TREE_TYPE (x), x);
}
/* Nonzero means lvalues are limited to those valid in pedantic ANSI C.
pedantic lvalue. Otherwise, return X. */
static tree
-pedantic_non_lvalue (tree x)
+pedantic_non_lvalue_loc (location_t loc, tree x)
{
if (pedantic_lvalues)
- return non_lvalue (x);
- else
- return x;
+ return non_lvalue_loc (loc, x);
+
+ return protected_set_expr_location_unshare (x, loc);
}
\f
/* Given a tree comparison code, return the code that is the logical inverse
if this makes the transformation invalid. */
tree
-combine_comparisons (enum tree_code code, enum tree_code lcode,
+combine_comparisons (location_t loc,
+ enum tree_code code, enum tree_code lcode,
enum tree_code rcode, tree truth_type,
tree ll_arg, tree lr_arg)
{
enum tree_code tcode;
tcode = compcode_to_comparison ((enum comparison_code) compcode);
- return fold_build2 (tcode, truth_type, ll_arg, lr_arg);
+ return fold_build2_loc (loc, tcode, truth_type, ll_arg, lr_arg);
}
}
\f
operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
{
/* If either is ERROR_MARK, they aren't equal. */
- if (TREE_CODE (arg0) == ERROR_MARK || TREE_CODE (arg1) == ERROR_MARK)
+ if (TREE_CODE (arg0) == ERROR_MARK || TREE_CODE (arg1) == ERROR_MARK
+ || TREE_TYPE (arg0) == error_mark_node
+ || TREE_TYPE (arg1) == error_mark_node)
+ return 0;
+
+ /* Similar, if either does not have a type (like a released SSA name),
+ they aren't equal. */
+ if (!TREE_TYPE (arg0) || !TREE_TYPE (arg1))
return 0;
/* Check equality of integer constants before bailing out due to
|| POINTER_TYPE_P (TREE_TYPE (arg0)) != POINTER_TYPE_P (TREE_TYPE (arg1)))
return 0;
+ /* We cannot consider pointers to different address space equal. */
+ if (POINTER_TYPE_P (TREE_TYPE (arg0)) && POINTER_TYPE_P (TREE_TYPE (arg1))
+ && (TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (arg0)))
+ != TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (arg1)))))
+ return 0;
+
/* If both types don't have the same precision, then it is not safe
to strip NOPs. */
if (TYPE_PRECISION (TREE_TYPE (arg0)) != TYPE_PRECISION (TREE_TYPE (arg1)))
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;
TREE_REAL_CST (arg1)))
return 1;
-
+
if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0))))
{
/* If we do not distinguish between signed and unsigned zero,
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;
}
switch (TREE_CODE (arg0))
{
case INDIRECT_REF:
- case ALIGN_INDIRECT_REF:
- case MISALIGNED_INDIRECT_REF:
case REALPART_EXPR:
case IMAGPART_EXPR:
return OP_SAME (0);
+ case MEM_REF:
+ /* Require equal access sizes, and similar pointer types.
+ We can have incomplete types for array references of
+ variable-sized arrays from the Fortran frontent
+ though. */
+ return ((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)))
+ && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg0, 1)))
+ == TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg1, 1))))
+ && OP_SAME (0) && OP_SAME (1));
+
case ARRAY_REF:
case ARRAY_RANGE_REF:
/* Operands 2 and 3 may be null.
case TRUTH_ORIF_EXPR:
return OP_SAME (0) && OP_SAME (1);
+ case FMA_EXPR:
+ case WIDEN_MULT_PLUS_EXPR:
+ case WIDEN_MULT_MINUS_EXPR:
+ if (!OP_SAME (2))
+ return 0;
+ /* The multiplcation operands are commutative. */
+ /* FALLTHRU */
+
case TRUTH_AND_EXPR:
case TRUTH_OR_EXPR:
case TRUTH_XOR_EXPR:
TREE_OPERAND (arg1, 0), flags));
case COND_EXPR:
+ case VEC_COND_EXPR:
+ case DOT_PROD_EXPR:
return OP_SAME (0) && OP_SAME (1) && OP_SAME (2);
-
+
default:
return 0;
}
NEW1 and OLD1. */
static tree
-eval_subst (tree arg, tree old0, tree new0, tree old1, tree new1)
+eval_subst (location_t loc, tree arg, tree old0, tree new0,
+ tree old1, tree new1)
{
tree type = TREE_TYPE (arg);
enum tree_code code = TREE_CODE (arg);
switch (tclass)
{
case tcc_unary:
- return fold_build1 (code, type,
- eval_subst (TREE_OPERAND (arg, 0),
+ return fold_build1_loc (loc, code, type,
+ eval_subst (loc, TREE_OPERAND (arg, 0),
old0, new0, old1, new1));
case tcc_binary:
- return fold_build2 (code, type,
- eval_subst (TREE_OPERAND (arg, 0),
+ return fold_build2_loc (loc, code, type,
+ eval_subst (loc, TREE_OPERAND (arg, 0),
old0, new0, old1, new1),
- eval_subst (TREE_OPERAND (arg, 1),
+ eval_subst (loc, TREE_OPERAND (arg, 1),
old0, new0, old1, new1));
case tcc_expression:
switch (code)
{
case SAVE_EXPR:
- return eval_subst (TREE_OPERAND (arg, 0), old0, new0, old1, new1);
+ return eval_subst (loc, TREE_OPERAND (arg, 0), old0, new0,
+ old1, new1);
case COMPOUND_EXPR:
- return eval_subst (TREE_OPERAND (arg, 1), old0, new0, old1, new1);
+ return eval_subst (loc, TREE_OPERAND (arg, 1), old0, new0,
+ old1, new1);
case COND_EXPR:
- return fold_build3 (code, type,
- eval_subst (TREE_OPERAND (arg, 0),
+ return fold_build3_loc (loc, code, type,
+ eval_subst (loc, TREE_OPERAND (arg, 0),
old0, new0, old1, new1),
- eval_subst (TREE_OPERAND (arg, 1),
+ eval_subst (loc, TREE_OPERAND (arg, 1),
old0, new0, old1, new1),
- eval_subst (TREE_OPERAND (arg, 2),
+ eval_subst (loc, TREE_OPERAND (arg, 2),
old0, new0, old1, new1));
default:
break;
else if (arg1 == old1 || operand_equal_p (arg1, old1, 0))
arg1 = new1;
- return fold_build2 (code, type, arg0, arg1);
+ return fold_build2_loc (loc, code, type, arg0, arg1);
}
default:
the conversion of RESULT to TYPE. */
tree
-omit_one_operand (tree type, tree result, tree omitted)
+omit_one_operand_loc (location_t loc, tree type, tree result, tree omitted)
{
- tree t = fold_convert (type, result);
+ tree t = fold_convert_loc (loc, type, result);
/* If the resulting operand is an empty statement, just return the omitted
statement casted to void. */
if (IS_EMPTY_STMT (t) && TREE_SIDE_EFFECTS (omitted))
- return build1 (NOP_EXPR, void_type_node, fold_ignored_result (omitted));
+ return build1_loc (loc, NOP_EXPR, void_type_node,
+ fold_ignored_result (omitted));
if (TREE_SIDE_EFFECTS (omitted))
- return build2 (COMPOUND_EXPR, type, fold_ignored_result (omitted), t);
+ return build2_loc (loc, COMPOUND_EXPR, type,
+ fold_ignored_result (omitted), t);
- return non_lvalue (t);
+ return non_lvalue_loc (loc, t);
}
/* Similar, but call pedantic_non_lvalue instead of non_lvalue. */
static tree
-pedantic_omit_one_operand (tree type, tree result, tree omitted)
+pedantic_omit_one_operand_loc (location_t loc, tree type, tree result,
+ tree omitted)
{
- tree t = fold_convert (type, result);
+ tree t = fold_convert_loc (loc, type, result);
/* If the resulting operand is an empty statement, just return the omitted
statement casted to void. */
if (IS_EMPTY_STMT (t) && TREE_SIDE_EFFECTS (omitted))
- return build1 (NOP_EXPR, void_type_node, fold_ignored_result (omitted));
+ return build1_loc (loc, NOP_EXPR, void_type_node,
+ fold_ignored_result (omitted));
if (TREE_SIDE_EFFECTS (omitted))
- return build2 (COMPOUND_EXPR, type, fold_ignored_result (omitted), t);
+ return build2_loc (loc, COMPOUND_EXPR, type,
+ fold_ignored_result (omitted), t);
- return pedantic_non_lvalue (t);
+ return pedantic_non_lvalue_loc (loc, t);
}
/* Return a tree for the case when the result of an expression is RESULT
just do the conversion of RESULT to TYPE. */
tree
-omit_two_operands (tree type, tree result, tree omitted1, tree omitted2)
+omit_two_operands_loc (location_t loc, tree type, tree result,
+ tree omitted1, tree omitted2)
{
- tree t = fold_convert (type, result);
+ tree t = fold_convert_loc (loc, type, result);
if (TREE_SIDE_EFFECTS (omitted2))
- t = build2 (COMPOUND_EXPR, type, omitted2, t);
+ t = build2_loc (loc, COMPOUND_EXPR, type, omitted2, t);
if (TREE_SIDE_EFFECTS (omitted1))
- t = build2 (COMPOUND_EXPR, type, omitted1, t);
+ t = build2_loc (loc, COMPOUND_EXPR, type, omitted1, t);
- return TREE_CODE (t) != COMPOUND_EXPR ? non_lvalue (t) : t;
+ return TREE_CODE (t) != COMPOUND_EXPR ? non_lvalue_loc (loc, t) : t;
}
\f
problems with the dominator optimizer. */
tree
-fold_truth_not_expr (tree arg)
+fold_truth_not_expr (location_t loc, tree arg)
{
- tree t, type = TREE_TYPE (arg);
+ tree type = TREE_TYPE (arg);
enum tree_code code = TREE_CODE (arg);
+ location_t loc1, loc2;
/* If this is a comparison, we can simply invert it, except for
floating-point non-equality comparisons, in which case we just
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;
+ return build2_loc (loc, code, type, TREE_OPERAND (arg, 0),
+ TREE_OPERAND (arg, 1));
}
switch (code)
return constant_boolean_node (integer_zerop (arg), type);
case TRUTH_AND_EXPR:
- t = build2 (TRUTH_OR_EXPR, type,
- invert_truthvalue (TREE_OPERAND (arg, 0)),
- invert_truthvalue (TREE_OPERAND (arg, 1)));
- break;
+ 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:
- t = build2 (TRUTH_AND_EXPR, type,
- invert_truthvalue (TREE_OPERAND (arg, 0)),
- invert_truthvalue (TREE_OPERAND (arg, 1)));
- break;
+ 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)));
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)
- t = build2 (TRUTH_XOR_EXPR, type, TREE_OPERAND (arg, 0),
- TREE_OPERAND (TREE_OPERAND (arg, 1), 0));
+ return build2_loc (loc, TRUTH_XOR_EXPR, type, TREE_OPERAND (arg, 0),
+ TREE_OPERAND (TREE_OPERAND (arg, 1), 0));
else
- t = build2 (TRUTH_XOR_EXPR, type,
- invert_truthvalue (TREE_OPERAND (arg, 0)),
- TREE_OPERAND (arg, 1));
- break;
+ return build2_loc (loc, TRUTH_XOR_EXPR, type,
+ invert_truthvalue_loc (loc, TREE_OPERAND (arg, 0)),
+ TREE_OPERAND (arg, 1));
case TRUTH_ANDIF_EXPR:
- t = build2 (TRUTH_ORIF_EXPR, type,
- invert_truthvalue (TREE_OPERAND (arg, 0)),
- invert_truthvalue (TREE_OPERAND (arg, 1)));
- break;
+ 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:
- t = build2 (TRUTH_ANDIF_EXPR, type,
- invert_truthvalue (TREE_OPERAND (arg, 0)),
- invert_truthvalue (TREE_OPERAND (arg, 1)));
- break;
+ 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)));
case TRUTH_NOT_EXPR:
return TREE_OPERAND (arg, 0);
{
tree arg1 = TREE_OPERAND (arg, 1);
tree arg2 = TREE_OPERAND (arg, 2);
+
+ 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
as they are. */
- 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;
+ return build3_loc (loc, COND_EXPR, type, TREE_OPERAND (arg, 0),
+ VOID_TYPE_P (TREE_TYPE (arg1))
+ ? arg1 : invert_truthvalue_loc (loc1, arg1),
+ VOID_TYPE_P (TREE_TYPE (arg2))
+ ? arg2 : invert_truthvalue_loc (loc2, arg2));
}
case COMPOUND_EXPR:
- t = build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg, 0),
- invert_truthvalue (TREE_OPERAND (arg, 1)));
- break;
+ 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:
- return invert_truthvalue (TREE_OPERAND (arg, 0));
+ loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
+ return invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0));
CASE_CONVERT:
if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
- {
- t = build1 (TRUTH_NOT_EXPR, type, arg);
- break;
- }
+ return build1_loc (loc, TRUTH_NOT_EXPR, type, arg);
/* ... fall through ... */
case FLOAT_EXPR:
- t = build1 (TREE_CODE (arg), type,
- invert_truthvalue (TREE_OPERAND (arg, 0)));
- break;
+ 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)));
case BIT_AND_EXPR:
if (!integer_onep (TREE_OPERAND (arg, 1)))
return NULL_TREE;
- t = build2 (EQ_EXPR, type, arg, build_int_cst (type, 0));
- break;
+ return build2_loc (loc, EQ_EXPR, type, arg, build_int_cst (type, 0));
case SAVE_EXPR:
- t = build1 (TRUTH_NOT_EXPR, type, arg);
- break;
+ return build1_loc (loc, TRUTH_NOT_EXPR, type, arg);
case CLEANUP_POINT_EXPR:
- t = build1 (CLEANUP_POINT_EXPR, type,
- invert_truthvalue (TREE_OPERAND (arg, 0)));
- break;
+ 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)));
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
problems with the dominator optimizer. */
tree
-invert_truthvalue (tree arg)
+invert_truthvalue_loc (location_t loc, tree arg)
{
tree tem;
if (TREE_CODE (arg) == ERROR_MARK)
return arg;
- tem = fold_truth_not_expr (arg);
+ tem = fold_truth_not_expr (loc, arg);
if (!tem)
- tem = build1 (TRUTH_NOT_EXPR, TREE_TYPE (arg), arg);
+ tem = build1_loc (loc, TRUTH_NOT_EXPR, TREE_TYPE (arg), arg);
return tem;
}
If this optimization cannot be done, 0 will be returned. */
static tree
-distribute_bit_expr (enum tree_code code, tree type, tree arg0, tree arg1)
+distribute_bit_expr (location_t loc, enum tree_code code, tree type,
+ tree arg0, tree arg1)
{
tree common;
tree left, right;
else
return 0;
- common = fold_convert (type, common);
- left = fold_convert (type, left);
- right = fold_convert (type, right);
- return fold_build2 (TREE_CODE (arg0), type, common,
- fold_build2 (code, type, left, right));
+ common = fold_convert_loc (loc, type, common);
+ left = fold_convert_loc (loc, type, left);
+ right = fold_convert_loc (loc, type, right);
+ return fold_build2_loc (loc, TREE_CODE (arg0), type, common,
+ fold_build2_loc (loc, code, type, left, right));
}
/* Knowing that ARG0 and ARG1 are both RDIV_EXPRs, simplify a binary operation
with code CODE. This optimization is unsafe. */
static tree
-distribute_real_division (enum tree_code code, tree type, tree arg0, tree arg1)
+distribute_real_division (location_t loc, enum tree_code code, tree type,
+ tree arg0, tree arg1)
{
bool mul0 = TREE_CODE (arg0) == MULT_EXPR;
bool mul1 = TREE_CODE (arg1) == MULT_EXPR;
if (mul0 == mul1
&& operand_equal_p (TREE_OPERAND (arg0, 1),
TREE_OPERAND (arg1, 1), 0))
- return fold_build2 (mul0 ? MULT_EXPR : RDIV_EXPR, type,
- fold_build2 (code, type,
+ return fold_build2_loc (loc, mul0 ? MULT_EXPR : RDIV_EXPR, type,
+ fold_build2_loc (loc, code, type,
TREE_OPERAND (arg0, 0),
TREE_OPERAND (arg1, 0)),
TREE_OPERAND (arg0, 1));
if (!mul1)
real_arithmetic (&r1, RDIV_EXPR, &dconst1, &r1);
real_arithmetic (&r0, code, &r0, &r1);
- return fold_build2 (MULT_EXPR, type,
+ return fold_build2_loc (loc, MULT_EXPR, type,
TREE_OPERAND (arg0, 0),
build_real (type, r0));
}
starting at BITPOS. The field is unsigned if UNSIGNEDP is nonzero. */
static tree
-make_bit_field_ref (tree inner, tree type, HOST_WIDE_INT bitsize,
- HOST_WIDE_INT bitpos, int unsignedp)
+make_bit_field_ref (location_t loc, tree inner, tree type,
+ HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos, int unsignedp)
{
tree result, bftype;
tree size = TYPE_SIZE (TREE_TYPE (inner));
if ((INTEGRAL_TYPE_P (TREE_TYPE (inner))
|| POINTER_TYPE_P (TREE_TYPE (inner)))
- && host_integerp (size, 0)
+ && host_integerp (size, 0)
&& tree_low_cst (size, 0) == bitsize)
- return fold_convert (type, inner);
+ return fold_convert_loc (loc, type, inner);
}
bftype = type;
|| TYPE_UNSIGNED (bftype) == !unsignedp)
bftype = build_nonstandard_integer_type (bitsize, 0);
- result = build3 (BIT_FIELD_REF, bftype, inner,
- size_int (bitsize), bitsize_int (bitpos));
+ result = build3_loc (loc, BIT_FIELD_REF, bftype, inner,
+ size_int (bitsize), bitsize_int (bitpos));
if (bftype != type)
- result = fold_convert (type, result);
+ result = fold_convert_loc (loc, type, result);
return result;
}
tree. Otherwise we return zero. */
static tree
-optimize_bit_field_compare (enum tree_code code, tree compare_type,
- tree lhs, tree rhs)
+optimize_bit_field_compare (location_t loc, enum tree_code code,
+ tree compare_type, tree lhs, tree rhs)
{
HOST_WIDE_INT lbitpos, lbitsize, rbitpos, rbitsize, nbitpos, nbitsize;
tree type = TREE_TYPE (lhs);
/* See if we can find a mode to refer to this field. We should be able to,
but fail if we can't. */
- nmode = get_best_mode (lbitsize, lbitpos,
- const_p ? TYPE_ALIGN (TREE_TYPE (linner))
- : MIN (TYPE_ALIGN (TREE_TYPE (linner)),
- TYPE_ALIGN (TREE_TYPE (rinner))),
- word_mode, lvolatilep || rvolatilep);
+ if (lvolatilep
+ && GET_MODE_BITSIZE (lmode) > 0
+ && flag_strict_volatile_bitfields > 0)
+ nmode = lmode;
+ else
+ nmode = get_best_mode (lbitsize, lbitpos,
+ const_p ? TYPE_ALIGN (TREE_TYPE (linner))
+ : MIN (TYPE_ALIGN (TREE_TYPE (linner)),
+ TYPE_ALIGN (TREE_TYPE (rinner))),
+ word_mode, lvolatilep || rvolatilep);
if (nmode == VOIDmode)
return 0;
/* Make the mask to be used against the extracted field. */
mask = build_int_cst_type (unsigned_type, -1);
- mask = const_binop (LSHIFT_EXPR, mask, size_int (nbitsize - lbitsize), 0);
+ mask = const_binop (LSHIFT_EXPR, mask, size_int (nbitsize - lbitsize));
mask = const_binop (RSHIFT_EXPR, mask,
- size_int (nbitsize - lbitsize - lbitpos), 0);
+ size_int (nbitsize - lbitsize - lbitpos));
if (! const_p)
/* If not comparing with constant, just rework the comparison
and return. */
- return fold_build2 (code, compare_type,
- fold_build2 (BIT_AND_EXPR, unsigned_type,
- make_bit_field_ref (linner,
+ return fold_build2_loc (loc, code, compare_type,
+ fold_build2_loc (loc, BIT_AND_EXPR, unsigned_type,
+ make_bit_field_ref (loc, linner,
unsigned_type,
nbitsize, nbitpos,
1),
mask),
- fold_build2 (BIT_AND_EXPR, unsigned_type,
- make_bit_field_ref (rinner,
+ fold_build2_loc (loc, BIT_AND_EXPR, unsigned_type,
+ make_bit_field_ref (loc, rinner,
unsigned_type,
nbitsize, nbitpos,
1),
if (lunsignedp)
{
if (! integer_zerop (const_binop (RSHIFT_EXPR,
- fold_convert (unsigned_type, rhs),
- size_int (lbitsize), 0)))
+ fold_convert_loc (loc,
+ unsigned_type, rhs),
+ size_int (lbitsize))))
{
warning (0, "comparison is always %d due to width of bit-field",
code == NE_EXPR);
}
else
{
- tree tem = const_binop (RSHIFT_EXPR, fold_convert (signed_type, rhs),
- size_int (lbitsize - 1), 0);
+ tree tem = const_binop (RSHIFT_EXPR,
+ fold_convert_loc (loc, signed_type, rhs),
+ size_int (lbitsize - 1));
if (! integer_zerop (tem) && ! integer_all_onesp (tem))
{
warning (0, "comparison is always %d due to width of bit-field",
/* Make a new bitfield reference, shift the constant over the
appropriate number of bits and mask it with the computed mask
(in case this was a signed field). If we changed it, make a new one. */
- lhs = make_bit_field_ref (linner, unsigned_type, nbitsize, nbitpos, 1);
+ lhs = make_bit_field_ref (loc, linner, unsigned_type, nbitsize, nbitpos, 1);
if (lvolatilep)
{
TREE_SIDE_EFFECTS (lhs) = 1;
rhs = const_binop (BIT_AND_EXPR,
const_binop (LSHIFT_EXPR,
- fold_convert (unsigned_type, rhs),
- size_int (lbitpos), 0),
- mask, 0);
+ fold_convert_loc (loc, unsigned_type, rhs),
+ size_int (lbitpos)),
+ mask);
- return build2 (code, compare_type,
- build2 (BIT_AND_EXPR, unsigned_type, lhs, mask),
- rhs);
+ lhs = build2_loc (loc, code, compare_type,
+ build2 (BIT_AND_EXPR, unsigned_type, lhs, mask), rhs);
+ return lhs;
}
\f
/* Subroutine for fold_truthop: decode a field reference.
do anything with. */
static tree
-decode_field_reference (tree exp, HOST_WIDE_INT *pbitsize,
+decode_field_reference (location_t loc, tree exp, HOST_WIDE_INT *pbitsize,
HOST_WIDE_INT *pbitpos, enum machine_mode *pmode,
int *punsignedp, int *pvolatilep,
tree *pmask, tree *pand_mask)
mask = build_int_cst_type (unsigned_type, -1);
- mask = const_binop (LSHIFT_EXPR, mask, size_int (precision - *pbitsize), 0);
- mask = const_binop (RSHIFT_EXPR, mask, size_int (precision - *pbitsize), 0);
+ mask = const_binop (LSHIFT_EXPR, mask, size_int (precision - *pbitsize));
+ mask = const_binop (RSHIFT_EXPR, mask, size_int (precision - *pbitsize));
/* Merge it with the mask we found in the BIT_AND_EXPR, if any. */
if (and_mask != 0)
- mask = fold_build2 (BIT_AND_EXPR, unsigned_type,
- fold_convert (unsigned_type, and_mask), mask);
+ mask = fold_build2_loc (loc, BIT_AND_EXPR, unsigned_type,
+ fold_convert_loc (loc, unsigned_type, and_mask), mask);
*pmask = mask;
*pand_mask = and_mask;
tree_int_cst_equal (mask,
const_binop (RSHIFT_EXPR,
const_binop (LSHIFT_EXPR, tmask,
- size_int (precision - size),
- 0),
- size_int (precision - size), 0));
+ size_int (precision - size)),
+ size_int (precision - size)));
}
/* Subroutine for fold: determine if VAL is the INTEGER_CONST that
tree exp_type = NULL_TREE, arg0_type = NULL_TREE;
int in_p, n_in_p;
tree low, high, n_low, n_high;
+ location_t loc = EXPR_LOCATION (exp);
/* Start with simply saying "EXP != 0" and then look at the code of EXP
and see if we can refine the range. Some of the cases below may not
n_high = range_binop (MINUS_EXPR, exp_type,
build_int_cst (exp_type, 0),
0, low, 0);
- low = n_low, high = n_high;
- exp = arg0;
- continue;
+ if (n_high != 0 && TREE_OVERFLOW (n_high))
+ break;
+ goto normalize;
case BIT_NOT_EXPR:
/* ~ X -> -X - 1 */
- exp = build2 (MINUS_EXPR, exp_type, negate_expr (arg0),
- build_int_cst (exp_type, 1));
+ exp = build2_loc (loc, MINUS_EXPR, exp_type, negate_expr (arg0),
+ build_int_cst (exp_type, 1));
continue;
case PLUS_EXPR: case MINUS_EXPR:
if (TYPE_OVERFLOW_UNDEFINED (arg0_type))
*strict_overflow_p = true;
+ normalize:
/* Check for an unsigned range which has wrapped around the maximum
value thus making n_high < n_low, and normalize it. */
if (n_low && n_high && tree_int_cst_lt (n_high, n_low))
n_low = low, n_high = high;
if (n_low != 0)
- n_low = fold_convert (arg0_type, n_low);
+ n_low = fold_convert_loc (loc, arg0_type, n_low);
if (n_high != 0)
- n_high = fold_convert (arg0_type, n_high);
+ n_high = fold_convert_loc (loc, arg0_type, n_high);
/* If we're converting arg0 from an unsigned type, to exp,
: TYPE_MAX_VALUE (arg0_type);
if (TYPE_PRECISION (exp_type) == TYPE_PRECISION (arg0_type))
- high_positive = fold_build2 (RSHIFT_EXPR, arg0_type,
- fold_convert (arg0_type,
- high_positive),
+ high_positive = fold_build2_loc (loc, RSHIFT_EXPR, arg0_type,
+ fold_convert_loc (loc, arg0_type,
+ high_positive),
build_int_cst (arg0_type, 1));
/* If the low bound is specified, "and" the range with the
{
if (! merge_ranges (&n_in_p, &n_low, &n_high,
1, n_low, n_high, 1,
- fold_convert (arg0_type,
- integer_zero_node),
+ fold_convert_loc (loc, arg0_type,
+ integer_zero_node),
high_positive))
break;
that will be interpreted as negative. */
if (! merge_ranges (&n_in_p, &n_low, &n_high,
0, n_low, n_high, 1,
- fold_convert (arg0_type,
- integer_zero_node),
+ fold_convert_loc (loc, arg0_type,
+ integer_zero_node),
high_positive))
break;
on IN_P) the range. Return 0 if the test couldn't be created. */
tree
-build_range_check (tree type, tree exp, int in_p, tree low, tree high)
+build_range_check (location_t loc, tree type, tree exp, int in_p,
+ tree low, tree high)
{
tree etype = TREE_TYPE (exp), value;
if (! in_p)
{
- value = build_range_check (type, exp, 1, low, high);
+ value = build_range_check (loc, type, exp, 1, low, high);
if (value != 0)
- return invert_truthvalue (value);
+ return invert_truthvalue_loc (loc, value);
return 0;
}
return build_int_cst (type, 1);
if (low == 0)
- return fold_build2 (LE_EXPR, type, exp,
- fold_convert (etype, high));
+ return fold_build2_loc (loc, LE_EXPR, type, exp,
+ fold_convert_loc (loc, etype, high));
if (high == 0)
- return fold_build2 (GE_EXPR, type, exp,
- fold_convert (etype, low));
+ return fold_build2_loc (loc, GE_EXPR, type, exp,
+ fold_convert_loc (loc, etype, low));
if (operand_equal_p (low, high, 0))
- return fold_build2 (EQ_EXPR, type, exp,
- fold_convert (etype, low));
+ return fold_build2_loc (loc, EQ_EXPR, type, exp,
+ fold_convert_loc (loc, etype, low));
if (integer_zerop (low))
{
if (! TYPE_UNSIGNED (etype))
{
etype = unsigned_type_for (etype);
- high = fold_convert (etype, high);
- exp = fold_convert (etype, exp);
+ high = fold_convert_loc (loc, etype, high);
+ exp = fold_convert_loc (loc, etype, exp);
}
- return build_range_check (type, exp, 1, 0, high);
+ return build_range_check (loc, type, exp, 1, 0, high);
}
/* Optimize (c>=1) && (c<=127) into (signed char)c > 0. */
= build_nonstandard_integer_type (TYPE_PRECISION (etype), 0);
else
etype = signed_etype;
- exp = fold_convert (etype, exp);
+ exp = fold_convert_loc (loc, etype, exp);
}
- return fold_build2 (GT_EXPR, type, exp,
+ return fold_build2_loc (loc, GT_EXPR, type, exp,
build_int_cst (etype, 0));
}
}
/* Check if (unsigned) INT_MAX + 1 == (unsigned) INT_MIN
for the type in question, as we rely on this here. */
utype = unsigned_type_for (etype);
- maxv = fold_convert (utype, TYPE_MAX_VALUE (etype));
+ maxv = fold_convert_loc (loc, utype, TYPE_MAX_VALUE (etype));
maxv = range_binop (PLUS_EXPR, NULL_TREE, maxv, 1,
integer_one_node, 1);
- minv = fold_convert (utype, TYPE_MIN_VALUE (etype));
+ minv = fold_convert_loc (loc, utype, TYPE_MIN_VALUE (etype));
if (integer_zerop (range_binop (NE_EXPR, integer_type_node,
minv, 1, maxv, 1)))
return 0;
}
- high = fold_convert (etype, high);
- low = fold_convert (etype, low);
- exp = fold_convert (etype, exp);
+ high = fold_convert_loc (loc, etype, high);
+ low = fold_convert_loc (loc, etype, low);
+ exp = fold_convert_loc (loc, etype, exp);
- value = const_binop (MINUS_EXPR, high, low, 0);
+ value = const_binop (MINUS_EXPR, high, low);
if (POINTER_TYPE_P (etype))
{
if (value != 0 && !TREE_OVERFLOW (value))
{
- low = fold_convert (sizetype, low);
- low = fold_build1 (NEGATE_EXPR, sizetype, low);
- return build_range_check (type,
- fold_build2 (POINTER_PLUS_EXPR, etype, exp, low),
+ low = fold_convert_loc (loc, sizetype, low);
+ low = fold_build1_loc (loc, NEGATE_EXPR, sizetype, low);
+ return build_range_check (loc, type,
+ fold_build2_loc (loc, POINTER_PLUS_EXPR,
+ etype, exp, low),
1, build_int_cst (etype, 0), value);
}
return 0;
}
if (value != 0 && !TREE_OVERFLOW (value))
- return build_range_check (type,
- fold_build2 (MINUS_EXPR, etype, exp, low),
+ return build_range_check (loc, type,
+ fold_build2_loc (loc, MINUS_EXPR, etype, exp, low),
1, build_int_cst (etype, 0), value);
return 0;
anymore, or NULL_TREE if no folding opportunity is found. */
static tree
-fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
+fold_cond_expr_with_comparison (location_t loc, tree type,
+ tree arg0, tree arg1, tree arg2)
{
enum tree_code comp_code = TREE_CODE (arg0);
tree arg00 = TREE_OPERAND (arg0, 0);
{
case EQ_EXPR:
case UNEQ_EXPR:
- tem = fold_convert (arg1_type, arg1);
- return pedantic_non_lvalue (fold_convert (type, negate_expr (tem)));
+ tem = fold_convert_loc (loc, arg1_type, arg1);
+ return pedantic_non_lvalue_loc (loc,
+ fold_convert_loc (loc, type,
+ negate_expr (tem)));
case NE_EXPR:
case LTGT_EXPR:
- return pedantic_non_lvalue (fold_convert (type, arg1));
+ return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1));
case UNGE_EXPR:
case UNGT_EXPR:
if (flag_trapping_math)
case GE_EXPR:
case GT_EXPR:
if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
- arg1 = fold_convert (signed_type_for
+ arg1 = fold_convert_loc (loc, signed_type_for
(TREE_TYPE (arg1)), arg1);
- tem = fold_build1 (ABS_EXPR, TREE_TYPE (arg1), arg1);
- return pedantic_non_lvalue (fold_convert (type, tem));
+ tem = fold_build1_loc (loc, ABS_EXPR, TREE_TYPE (arg1), arg1);
+ return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, tem));
case UNLE_EXPR:
case UNLT_EXPR:
if (flag_trapping_math)
case LE_EXPR:
case LT_EXPR:
if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
- arg1 = fold_convert (signed_type_for
+ arg1 = fold_convert_loc (loc, signed_type_for
(TREE_TYPE (arg1)), arg1);
- tem = fold_build1 (ABS_EXPR, TREE_TYPE (arg1), arg1);
- return negate_expr (fold_convert (type, tem));
+ tem = fold_build1_loc (loc, ABS_EXPR, TREE_TYPE (arg1), arg1);
+ return negate_expr (fold_convert_loc (loc, type, tem));
default:
gcc_assert (TREE_CODE_CLASS (comp_code) == tcc_comparison);
break;
&& integer_zerop (arg01) && integer_zerop (arg2))
{
if (comp_code == NE_EXPR)
- return pedantic_non_lvalue (fold_convert (type, arg1));
+ return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1));
else if (comp_code == EQ_EXPR)
return build_int_cst (type, 0);
}
switch (comp_code)
{
case EQ_EXPR:
- return pedantic_non_lvalue (fold_convert (type, arg2));
+ return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, arg2));
case NE_EXPR:
- return pedantic_non_lvalue (fold_convert (type, arg1));
+ return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1));
case LE_EXPR:
case LT_EXPR:
case UNLE_EXPR:
corresponding COND_EXPR. */
if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
{
- comp_op0 = fold_convert (comp_type, comp_op0);
- comp_op1 = fold_convert (comp_type, comp_op1);
+ comp_op0 = fold_convert_loc (loc, comp_type, comp_op0);
+ comp_op1 = fold_convert_loc (loc, comp_type, comp_op1);
tem = (comp_code == LE_EXPR || comp_code == UNLE_EXPR)
- ? fold_build2 (MIN_EXPR, comp_type, comp_op0, comp_op1)
- : fold_build2 (MIN_EXPR, comp_type, comp_op1, comp_op0);
- return pedantic_non_lvalue (fold_convert (type, tem));
+ ? fold_build2_loc (loc, MIN_EXPR, comp_type, comp_op0, comp_op1)
+ : fold_build2_loc (loc, MIN_EXPR, comp_type,
+ comp_op1, comp_op0);
+ return pedantic_non_lvalue_loc (loc,
+ fold_convert_loc (loc, type, tem));
}
break;
case GE_EXPR:
case UNGT_EXPR:
if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
{
- comp_op0 = fold_convert (comp_type, comp_op0);
- comp_op1 = fold_convert (comp_type, comp_op1);
+ comp_op0 = fold_convert_loc (loc, comp_type, comp_op0);
+ comp_op1 = fold_convert_loc (loc, comp_type, comp_op1);
tem = (comp_code == GE_EXPR || comp_code == UNGE_EXPR)
- ? fold_build2 (MAX_EXPR, comp_type, comp_op0, comp_op1)
- : fold_build2 (MAX_EXPR, comp_type, comp_op1, comp_op0);
- return pedantic_non_lvalue (fold_convert (type, tem));
+ ? fold_build2_loc (loc, MAX_EXPR, comp_type, comp_op0, comp_op1)
+ : fold_build2_loc (loc, MAX_EXPR, comp_type,
+ comp_op1, comp_op0);
+ return pedantic_non_lvalue_loc (loc,
+ fold_convert_loc (loc, type, tem));
}
break;
case UNEQ_EXPR:
if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
- return pedantic_non_lvalue (fold_convert (type, arg2));
+ return pedantic_non_lvalue_loc (loc,
+ fold_convert_loc (loc, type, arg2));
break;
case LTGT_EXPR:
if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
- return pedantic_non_lvalue (fold_convert (type, arg1));
+ return pedantic_non_lvalue_loc (loc,
+ fold_convert_loc (loc, type, arg1));
break;
default:
gcc_assert (TREE_CODE_CLASS (comp_code) == tcc_comparison);
switch (comp_code)
{
case EQ_EXPR:
+ if (TREE_CODE (arg1) == INTEGER_CST)
+ break;
/* We can replace A with C1 in this case. */
- arg1 = fold_convert (type, arg01);
- return fold_build3 (COND_EXPR, type, arg0, arg1, arg2);
+ arg1 = fold_convert_loc (loc, type, arg01);
+ return fold_build3_loc (loc, COND_EXPR, type, arg0, arg1, arg2);
case LT_EXPR:
- /* If C1 is C2 + 1, this is min(A, C2). */
+ /* If C1 is C2 + 1, this is min(A, C2), but use ARG00's type for
+ MIN_EXPR, to preserve the signedness of the comparison. */
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),
+ build_int_cst (type, 1)),
OEP_ONLY_CONST))
- return pedantic_non_lvalue (fold_build2 (MIN_EXPR,
- type,
- fold_convert (type, arg1),
- arg2));
+ {
+ tem = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (arg00), arg00,
+ fold_convert_loc (loc, TREE_TYPE (arg00),
+ arg2));
+ return pedantic_non_lvalue_loc (loc,
+ fold_convert_loc (loc, type, tem));
+ }
break;
case LE_EXPR:
- /* If C1 is C2 - 1, this is min(A, C2). */
+ /* If C1 is C2 - 1, this is min(A, C2), with the same care
+ as above. */
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),
+ build_int_cst (type, 1)),
OEP_ONLY_CONST))
- return pedantic_non_lvalue (fold_build2 (MIN_EXPR,
- type,
- fold_convert (type, arg1),
- arg2));
+ {
+ tem = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (arg00), arg00,
+ fold_convert_loc (loc, TREE_TYPE (arg00),
+ arg2));
+ return pedantic_non_lvalue_loc (loc,
+ fold_convert_loc (loc, type, tem));
+ }
break;
case GT_EXPR:
OEP_ONLY_CONST)
&& operand_equal_p (arg01,
const_binop (MINUS_EXPR, arg2,
- build_int_cst (type, 1), 0),
+ build_int_cst (type, 1)),
OEP_ONLY_CONST))
- return pedantic_non_lvalue (fold_convert (type,
- fold_build2 (MAX_EXPR, TREE_TYPE (arg00),
- arg00,
- fold_convert (TREE_TYPE (arg00),
- arg2))));
+ {
+ tem = fold_build2_loc (loc, MAX_EXPR, TREE_TYPE (arg00), arg00,
+ fold_convert_loc (loc, TREE_TYPE (arg00),
+ arg2));
+ return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, tem));
+ }
break;
case GE_EXPR:
OEP_ONLY_CONST)
&& operand_equal_p (arg01,
const_binop (PLUS_EXPR, arg2,
- build_int_cst (type, 1), 0),
+ build_int_cst (type, 1)),
OEP_ONLY_CONST))
- return pedantic_non_lvalue (fold_convert (type,
- fold_build2 (MAX_EXPR, TREE_TYPE (arg00),
- arg00,
- fold_convert (TREE_TYPE (arg00),
- arg2))));
+ {
+ tem = fold_build2_loc (loc, MAX_EXPR, TREE_TYPE (arg00), arg00,
+ fold_convert_loc (loc, TREE_TYPE (arg00),
+ arg2));
+ return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, tem));
+ }
break;
case NE_EXPR:
break;
merge it into some range test. Return the new tree if so. */
static tree
-fold_range_test (enum tree_code code, tree type, tree op0, tree op1)
+fold_range_test (location_t loc, enum tree_code code, tree type,
+ tree op0, tree op1)
{
int or_op = (code == TRUTH_ORIF_EXPR
|| code == TRUTH_OR_EXPR);
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 (type,
+ && 0 != (tem = (build_range_check (UNKNOWN_LOCATION, type,
lhs != 0 ? lhs
: rhs != 0 ? rhs : integer_zero_node,
in_p, low, high))))
{
if (strict_overflow_p)
fold_overflow_warning (warnmsg, WARN_STRICT_OVERFLOW_COMPARISON);
- return or_op ? invert_truthvalue (tem) : tem;
+ return or_op ? invert_truthvalue_loc (loc, tem) : tem;
}
/* On machines where the branch cost is expensive, if this is a
unless we are at top level or LHS contains a PLACEHOLDER_EXPR, in
which cases we can't do this. */
if (simple_operand_p (lhs))
- return build2 (code == TRUTH_ANDIF_EXPR
- ? TRUTH_AND_EXPR : TRUTH_OR_EXPR,
- type, op0, op1);
+ return build2_loc (loc, code == TRUTH_ANDIF_EXPR
+ ? TRUTH_AND_EXPR : TRUTH_OR_EXPR,
+ type, op0, op1);
else if (lang_hooks.decls.global_bindings_p () == 0
&& ! CONTAINS_PLACEHOLDER_P (lhs))
{
tree common = save_expr (lhs);
- if (0 != (lhs = build_range_check (type, common,
+ if (0 != (lhs = build_range_check (loc, type, common,
or_op ? ! in0_p : in0_p,
low0, high0))
- && (0 != (rhs = build_range_check (type, common,
+ && (0 != (rhs = build_range_check (loc, type, common,
or_op ? ! in1_p : in1_p,
low1, high1))))
{
if (strict_overflow_p)
fold_overflow_warning (warnmsg,
WARN_STRICT_OVERFLOW_COMPARISON);
- return build2 (code == TRUTH_ANDIF_EXPR
- ? TRUTH_AND_EXPR : TRUTH_OR_EXPR,
- type, lhs, rhs);
+ return build2_loc (loc, code == TRUTH_ANDIF_EXPR
+ ? TRUTH_AND_EXPR : TRUTH_OR_EXPR,
+ type, lhs, rhs);
}
}
}
/* We work by getting just the sign bit into the low-order bit, then
into the high-order bit, then sign-extend. We then XOR that value
with C. */
- temp = const_binop (RSHIFT_EXPR, c, size_int (p - 1), 0);
- temp = const_binop (BIT_AND_EXPR, temp, size_int (1), 0);
+ temp = const_binop (RSHIFT_EXPR, c, size_int (p - 1));
+ temp = const_binop (BIT_AND_EXPR, temp, size_int (1));
/* We must use a signed type in order to get an arithmetic right shift.
However, we must also avoid introducing accidental overflows, so that
if (TYPE_UNSIGNED (type))
temp = fold_convert (signed_type_for (type), temp);
- temp = const_binop (LSHIFT_EXPR, temp, size_int (modesize - 1), 0);
- temp = const_binop (RSHIFT_EXPR, temp, size_int (modesize - p - 1), 0);
+ temp = const_binop (LSHIFT_EXPR, temp, size_int (modesize - 1));
+ temp = const_binop (RSHIFT_EXPR, temp, size_int (modesize - p - 1));
if (mask != 0)
temp = const_binop (BIT_AND_EXPR, temp,
- fold_convert (TREE_TYPE (c), mask), 0);
+ fold_convert (TREE_TYPE (c), mask));
/* If necessary, convert the type back to match the type of C. */
if (TYPE_UNSIGNED (type))
temp = fold_convert (type, temp);
- return fold_convert (type, const_binop (BIT_XOR_EXPR, c, temp, 0));
+ return fold_convert (type, const_binop (BIT_XOR_EXPR, c, temp));
}
\f
+/* For an expression that has the form
+ (A && B) || ~B
+ or
+ (A || B) && ~B,
+ we can drop one of the inner expressions and simplify to
+ A || ~B
+ or
+ A && ~B
+ LOC is the location of the resulting expression. OP is the inner
+ logical operation; the left-hand side in the examples above, while CMPOP
+ is the right-hand side. RHS_ONLY is used to prevent us from accidentally
+ removing a condition that guards another, as in
+ (A != NULL && A->...) || A == NULL
+ which we must not transform. If RHS_ONLY is true, only eliminate the
+ right-most operand of the inner logical operation. */
+
+static tree
+merge_truthop_with_opposite_arm (location_t loc, tree op, tree cmpop,
+ bool rhs_only)
+{
+ tree type = TREE_TYPE (cmpop);
+ enum tree_code code = TREE_CODE (cmpop);
+ enum tree_code truthop_code = TREE_CODE (op);
+ tree lhs = TREE_OPERAND (op, 0);
+ tree rhs = TREE_OPERAND (op, 1);
+ tree orig_lhs = lhs, orig_rhs = rhs;
+ enum tree_code rhs_code = TREE_CODE (rhs);
+ enum tree_code lhs_code = TREE_CODE (lhs);
+ enum tree_code inv_code;
+
+ if (TREE_SIDE_EFFECTS (op) || TREE_SIDE_EFFECTS (cmpop))
+ return NULL_TREE;
+
+ if (TREE_CODE_CLASS (code) != tcc_comparison)
+ return NULL_TREE;
+
+ if (rhs_code == truthop_code)
+ {
+ tree newrhs = merge_truthop_with_opposite_arm (loc, rhs, cmpop, rhs_only);
+ if (newrhs != NULL_TREE)
+ {
+ rhs = newrhs;
+ rhs_code = TREE_CODE (rhs);
+ }
+ }
+ if (lhs_code == truthop_code && !rhs_only)
+ {
+ tree newlhs = merge_truthop_with_opposite_arm (loc, lhs, cmpop, false);
+ if (newlhs != NULL_TREE)
+ {
+ lhs = newlhs;
+ lhs_code = TREE_CODE (lhs);
+ }
+ }
+
+ inv_code = invert_tree_comparison (code, HONOR_NANS (TYPE_MODE (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))
+ return lhs;
+ if (!rhs_only && inv_code == lhs_code
+ && operand_equal_p (TREE_OPERAND (lhs, 0), TREE_OPERAND (cmpop, 0), 0)
+ && operand_equal_p (TREE_OPERAND (lhs, 1), TREE_OPERAND (cmpop, 1), 0))
+ return rhs;
+ if (rhs != orig_rhs || lhs != orig_lhs)
+ return fold_build2_loc (loc, truthop_code, TREE_TYPE (cmpop),
+ lhs, rhs);
+ return NULL_TREE;
+}
+
/* Find ways of folding logical expressions of LHS and RHS:
Try to merge two comparisons to the same innermost item.
Look for range tests like "ch >= '0' && ch <= '9'".
We return the simplified tree or 0 if no optimization is possible. */
static tree
-fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs)
+fold_truthop (location_t loc, enum tree_code code, tree truth_type,
+ tree lhs, tree rhs)
{
/* If this is the "or" of two comparisons, we can do something if
the comparisons are NE_EXPR. If this is the "and", we can do something
if (simple_operand_p (ll_arg)
&& simple_operand_p (lr_arg))
{
- tree result;
if (operand_equal_p (ll_arg, rl_arg, 0)
&& operand_equal_p (lr_arg, rr_arg, 0))
{
- result = combine_comparisons (code, lcode, rcode,
+ result = combine_comparisons (loc, code, lcode, rcode,
truth_type, ll_arg, lr_arg);
if (result)
return result;
else if (operand_equal_p (ll_arg, rr_arg, 0)
&& operand_equal_p (lr_arg, rl_arg, 0))
{
- result = combine_comparisons (code, lcode,
+ result = combine_comparisons (loc, code, lcode,
swap_tree_comparison (rcode),
truth_type, ll_arg, lr_arg);
if (result)
&& rcode == NE_EXPR && integer_zerop (rr_arg)
&& TREE_TYPE (ll_arg) == TREE_TYPE (rl_arg)
&& INTEGRAL_TYPE_P (TREE_TYPE (ll_arg)))
- return build2 (NE_EXPR, truth_type,
- build2 (BIT_IOR_EXPR, TREE_TYPE (ll_arg),
- ll_arg, rl_arg),
- build_int_cst (TREE_TYPE (ll_arg), 0));
+ return build2_loc (loc, NE_EXPR, truth_type,
+ build2 (BIT_IOR_EXPR, TREE_TYPE (ll_arg),
+ ll_arg, rl_arg),
+ build_int_cst (TREE_TYPE (ll_arg), 0));
/* Convert (a == 0) && (b == 0) into (a | b) == 0. */
if (code == TRUTH_AND_EXPR
&& rcode == EQ_EXPR && integer_zerop (rr_arg)
&& TREE_TYPE (ll_arg) == TREE_TYPE (rl_arg)
&& INTEGRAL_TYPE_P (TREE_TYPE (ll_arg)))
- return build2 (EQ_EXPR, truth_type,
- build2 (BIT_IOR_EXPR, TREE_TYPE (ll_arg),
- ll_arg, rl_arg),
- build_int_cst (TREE_TYPE (ll_arg), 0));
+ return build2_loc (loc, EQ_EXPR, truth_type,
+ build2 (BIT_IOR_EXPR, TREE_TYPE (ll_arg),
+ ll_arg, rl_arg),
+ build_int_cst (TREE_TYPE (ll_arg), 0));
if (LOGICAL_OP_NON_SHORT_CIRCUIT)
{
if (code != orig_code || lhs != orig_lhs || rhs != orig_rhs)
- return build2 (code, truth_type, lhs, rhs);
+ return build2_loc (loc, code, truth_type, lhs, rhs);
return NULL_TREE;
}
}
return 0;
volatilep = 0;
- ll_inner = decode_field_reference (ll_arg,
+ ll_inner = decode_field_reference (loc, ll_arg,
&ll_bitsize, &ll_bitpos, &ll_mode,
&ll_unsignedp, &volatilep, &ll_mask,
&ll_and_mask);
- lr_inner = decode_field_reference (lr_arg,
+ lr_inner = decode_field_reference (loc, lr_arg,
&lr_bitsize, &lr_bitpos, &lr_mode,
&lr_unsignedp, &volatilep, &lr_mask,
&lr_and_mask);
- rl_inner = decode_field_reference (rl_arg,
+ rl_inner = decode_field_reference (loc, rl_arg,
&rl_bitsize, &rl_bitpos, &rl_mode,
&rl_unsignedp, &volatilep, &rl_mask,
&rl_and_mask);
- rr_inner = decode_field_reference (rr_arg,
+ rr_inner = decode_field_reference (loc, rr_arg,
&rr_bitsize, &rr_bitpos, &rr_mode,
&rr_unsignedp, &volatilep, &rr_mask,
&rr_and_mask);
xrl_bitpos = lnbitsize - xrl_bitpos - rl_bitsize;
}
- ll_mask = const_binop (LSHIFT_EXPR, fold_convert (lntype, ll_mask),
- size_int (xll_bitpos), 0);
- rl_mask = const_binop (LSHIFT_EXPR, fold_convert (lntype, rl_mask),
- size_int (xrl_bitpos), 0);
+ ll_mask = const_binop (LSHIFT_EXPR, fold_convert_loc (loc, lntype, ll_mask),
+ size_int (xll_bitpos));
+ rl_mask = const_binop (LSHIFT_EXPR, fold_convert_loc (loc, lntype, rl_mask),
+ size_int (xrl_bitpos));
if (l_const)
{
- l_const = fold_convert (lntype, l_const);
+ l_const = fold_convert_loc (loc, lntype, l_const);
l_const = unextend (l_const, ll_bitsize, ll_unsignedp, ll_and_mask);
- l_const = const_binop (LSHIFT_EXPR, l_const, size_int (xll_bitpos), 0);
+ l_const = const_binop (LSHIFT_EXPR, l_const, size_int (xll_bitpos));
if (! integer_zerop (const_binop (BIT_AND_EXPR, l_const,
- fold_build1 (BIT_NOT_EXPR,
- lntype, ll_mask),
- 0)))
+ fold_build1_loc (loc, BIT_NOT_EXPR,
+ lntype, ll_mask))))
{
warning (0, "comparison is always %d", wanted_code == NE_EXPR);
}
if (r_const)
{
- r_const = fold_convert (lntype, r_const);
+ r_const = fold_convert_loc (loc, lntype, r_const);
r_const = unextend (r_const, rl_bitsize, rl_unsignedp, rl_and_mask);
- r_const = const_binop (LSHIFT_EXPR, r_const, size_int (xrl_bitpos), 0);
+ r_const = const_binop (LSHIFT_EXPR, r_const, size_int (xrl_bitpos));
if (! integer_zerop (const_binop (BIT_AND_EXPR, r_const,
- fold_build1 (BIT_NOT_EXPR,
- lntype, rl_mask),
- 0)))
+ fold_build1_loc (loc, BIT_NOT_EXPR,
+ lntype, rl_mask))))
{
warning (0, "comparison is always %d", wanted_code == NE_EXPR);
xrr_bitpos = rnbitsize - xrr_bitpos - rr_bitsize;
}
- lr_mask = const_binop (LSHIFT_EXPR, fold_convert (rntype, lr_mask),
- size_int (xlr_bitpos), 0);
- rr_mask = const_binop (LSHIFT_EXPR, fold_convert (rntype, rr_mask),
- size_int (xrr_bitpos), 0);
+ lr_mask = const_binop (LSHIFT_EXPR, fold_convert_loc (loc,
+ rntype, lr_mask),
+ size_int (xlr_bitpos));
+ rr_mask = const_binop (LSHIFT_EXPR, fold_convert_loc (loc,
+ rntype, rr_mask),
+ size_int (xrr_bitpos));
/* Make a mask that corresponds to both fields being compared.
Do this for both items being compared. If the operands are the
same size and the bits being compared are in the same position
then we can do this by masking both and comparing the masked
results. */
- ll_mask = const_binop (BIT_IOR_EXPR, ll_mask, rl_mask, 0);
- lr_mask = const_binop (BIT_IOR_EXPR, lr_mask, rr_mask, 0);
+ ll_mask = const_binop (BIT_IOR_EXPR, ll_mask, rl_mask);
+ lr_mask = const_binop (BIT_IOR_EXPR, lr_mask, rr_mask);
if (lnbitsize == rnbitsize && xll_bitpos == xlr_bitpos)
{
- lhs = make_bit_field_ref (ll_inner, lntype, lnbitsize, lnbitpos,
+ lhs = make_bit_field_ref (loc, ll_inner, lntype, lnbitsize, lnbitpos,
ll_unsignedp || rl_unsignedp);
if (! all_ones_mask_p (ll_mask, lnbitsize))
lhs = build2 (BIT_AND_EXPR, lntype, lhs, ll_mask);
- rhs = make_bit_field_ref (lr_inner, rntype, rnbitsize, rnbitpos,
+ rhs = make_bit_field_ref (loc, lr_inner, rntype, rnbitsize, rnbitpos,
lr_unsignedp || rr_unsignedp);
if (! all_ones_mask_p (lr_mask, rnbitsize))
rhs = build2 (BIT_AND_EXPR, rntype, rhs, lr_mask);
- return build2 (wanted_code, truth_type, lhs, rhs);
+ return build2_loc (loc, wanted_code, truth_type, lhs, rhs);
}
/* There is still another way we can do something: If both pairs of
{
tree type;
- lhs = make_bit_field_ref (ll_inner, lntype, ll_bitsize + rl_bitsize,
+ lhs = make_bit_field_ref (loc, ll_inner, lntype,
+ ll_bitsize + rl_bitsize,
MIN (ll_bitpos, rl_bitpos), ll_unsignedp);
- rhs = make_bit_field_ref (lr_inner, rntype, lr_bitsize + rr_bitsize,
+ rhs = make_bit_field_ref (loc, lr_inner, rntype,
+ lr_bitsize + rr_bitsize,
MIN (lr_bitpos, rr_bitpos), lr_unsignedp);
ll_mask = const_binop (RSHIFT_EXPR, ll_mask,
- size_int (MIN (xll_bitpos, xrl_bitpos)), 0);
+ size_int (MIN (xll_bitpos, xrl_bitpos)));
lr_mask = const_binop (RSHIFT_EXPR, lr_mask,
- size_int (MIN (xlr_bitpos, xrr_bitpos)), 0);
+ size_int (MIN (xlr_bitpos, xrr_bitpos)));
/* Convert to the smaller type before masking out unwanted bits. */
type = lntype;
{
if (lnbitsize > rnbitsize)
{
- lhs = fold_convert (rntype, lhs);
- ll_mask = fold_convert (rntype, ll_mask);
+ lhs = fold_convert_loc (loc, rntype, lhs);
+ ll_mask = fold_convert_loc (loc, rntype, ll_mask);
type = rntype;
}
else if (lnbitsize < rnbitsize)
{
- rhs = fold_convert (lntype, rhs);
- lr_mask = fold_convert (lntype, lr_mask);
+ rhs = fold_convert_loc (loc, lntype, rhs);
+ lr_mask = fold_convert_loc (loc, lntype, lr_mask);
type = lntype;
}
}
if (! all_ones_mask_p (lr_mask, lr_bitsize + rr_bitsize))
rhs = build2 (BIT_AND_EXPR, type, rhs, lr_mask);
- return build2 (wanted_code, truth_type, lhs, rhs);
+ return build2_loc (loc, wanted_code, truth_type, lhs, rhs);
}
return 0;
common between the masks, those bits of the constants must be the same.
If not, the condition is always false. Test for this to avoid generating
incorrect code below. */
- result = const_binop (BIT_AND_EXPR, ll_mask, rl_mask, 0);
+ result = const_binop (BIT_AND_EXPR, ll_mask, rl_mask);
if (! integer_zerop (result)
- && simple_cst_equal (const_binop (BIT_AND_EXPR, result, l_const, 0),
- const_binop (BIT_AND_EXPR, result, r_const, 0)) != 1)
+ && simple_cst_equal (const_binop (BIT_AND_EXPR, result, l_const),
+ const_binop (BIT_AND_EXPR, result, r_const)) != 1)
{
if (wanted_code == NE_EXPR)
{
reference we will make. Unless the mask is all ones the width of
that field, perform the mask operation. Then compare with the
merged constant. */
- result = make_bit_field_ref (ll_inner, lntype, lnbitsize, lnbitpos,
+ result = make_bit_field_ref (loc, ll_inner, lntype, lnbitsize, lnbitpos,
ll_unsignedp || rl_unsignedp);
- ll_mask = const_binop (BIT_IOR_EXPR, ll_mask, rl_mask, 0);
+ ll_mask = const_binop (BIT_IOR_EXPR, ll_mask, rl_mask);
if (! all_ones_mask_p (ll_mask, lnbitsize))
- result = build2 (BIT_AND_EXPR, lntype, result, ll_mask);
+ result = build2_loc (loc, BIT_AND_EXPR, lntype, result, ll_mask);
- return build2 (wanted_code, truth_type, result,
- const_binop (BIT_IOR_EXPR, l_const, r_const, 0));
+ return build2_loc (loc, wanted_code, truth_type, result,
+ const_binop (BIT_IOR_EXPR, l_const, r_const));
}
\f
/* Optimize T, which is a comparison of a MIN_EXPR or MAX_EXPR with a
constant. */
static tree
-optimize_minmax_comparison (enum tree_code code, tree type, tree op0, tree op1)
+optimize_minmax_comparison (location_t loc, enum tree_code code, tree type,
+ tree op0, tree op1)
{
tree arg0 = op0;
enum tree_code op_code;
op_code = TREE_CODE (arg0);
minmax_const = TREE_OPERAND (arg0, 1);
- comp_const = fold_convert (TREE_TYPE (arg0), op1);
+ comp_const = fold_convert_loc (loc, TREE_TYPE (arg0), op1);
consts_equal = tree_int_cst_equal (minmax_const, comp_const);
consts_lt = tree_int_cst_lt (minmax_const, comp_const);
inner = TREE_OPERAND (arg0, 0);
{
case NE_EXPR: case LT_EXPR: case LE_EXPR:
{
- tree tem = optimize_minmax_comparison (invert_tree_comparison (code, false),
- type, op0, op1);
+ tree tem
+ = optimize_minmax_comparison (loc,
+ invert_tree_comparison (code, false),
+ type, op0, op1);
if (tem)
- return invert_truthvalue (tem);
+ return invert_truthvalue_loc (loc, tem);
return NULL_TREE;
}
case GE_EXPR:
return
- fold_build2 (TRUTH_ORIF_EXPR, type,
+ fold_build2_loc (loc, TRUTH_ORIF_EXPR, type,
optimize_minmax_comparison
- (EQ_EXPR, type, arg0, comp_const),
+ (loc, EQ_EXPR, type, arg0, comp_const),
optimize_minmax_comparison
- (GT_EXPR, type, arg0, comp_const));
+ (loc, GT_EXPR, type, arg0, comp_const));
case EQ_EXPR:
if (op_code == MAX_EXPR && consts_equal)
/* MAX (X, 0) == 0 -> X <= 0 */
- return fold_build2 (LE_EXPR, type, inner, comp_const);
+ return fold_build2_loc (loc, LE_EXPR, type, inner, comp_const);
else if (op_code == MAX_EXPR && consts_lt)
/* MAX (X, 0) == 5 -> X == 5 */
- return fold_build2 (EQ_EXPR, type, inner, comp_const);
+ return fold_build2_loc (loc, EQ_EXPR, type, inner, comp_const);
else if (op_code == MAX_EXPR)
/* MAX (X, 0) == -1 -> false */
- return omit_one_operand (type, integer_zero_node, inner);
+ return omit_one_operand_loc (loc, type, integer_zero_node, inner);
else if (consts_equal)
/* MIN (X, 0) == 0 -> X >= 0 */
- return fold_build2 (GE_EXPR, type, inner, comp_const);
+ return fold_build2_loc (loc, GE_EXPR, type, inner, comp_const);
else if (consts_lt)
/* MIN (X, 0) == 5 -> false */
- return omit_one_operand (type, integer_zero_node, inner);
+ return omit_one_operand_loc (loc, type, integer_zero_node, inner);
else
/* MIN (X, 0) == -1 -> X == -1 */
- return fold_build2 (EQ_EXPR, type, inner, comp_const);
+ return fold_build2_loc (loc, EQ_EXPR, type, inner, comp_const);
case GT_EXPR:
if (op_code == MAX_EXPR && (consts_equal || consts_lt))
/* MAX (X, 0) > 0 -> X > 0
MAX (X, 0) > 5 -> X > 5 */
- return fold_build2 (GT_EXPR, type, inner, comp_const);
+ return fold_build2_loc (loc, GT_EXPR, type, inner, comp_const);
else if (op_code == MAX_EXPR)
/* MAX (X, 0) > -1 -> true */
- return omit_one_operand (type, integer_one_node, inner);
+ return omit_one_operand_loc (loc, type, integer_one_node, inner);
else if (op_code == MIN_EXPR && (consts_equal || consts_lt))
/* MIN (X, 0) > 0 -> false
MIN (X, 0) > 5 -> false */
- return omit_one_operand (type, integer_zero_node, inner);
+ return omit_one_operand_loc (loc, type, integer_zero_node, inner);
else
/* MIN (X, 0) > -1 -> X > -1 */
- return fold_build2 (GT_EXPR, type, inner, comp_const);
+ return fold_build2_loc (loc, GT_EXPR, type, inner, comp_const);
default:
return NULL_TREE;
/* For a constant, we can always simplify if we are a multiply
or (for divide and modulus) if it is a multiple of our constant. */
if (code == MULT_EXPR
- || integer_zerop (const_binop (TRUNC_MOD_EXPR, t, c, 0)))
+ || integer_zerop (const_binop (TRUNC_MOD_EXPR, t, c)))
return const_binop (code, fold_convert (ctype, t),
- fold_convert (ctype, c), 0);
+ fold_convert (ctype, c));
break;
CASE_CONVERT: case NON_LVALUE_EXPR:
&& 0 != (t1 = fold_convert (ctype,
const_binop (LSHIFT_EXPR,
size_one_node,
- op1, 0)))
+ op1)))
&& !TREE_OVERFLOW (t1))
return extract_muldiv (build2 (tcode == LSHIFT_EXPR
? MULT_EXPR : FLOOR_DIV_EXPR,
- ctype, fold_convert (ctype, op0), t1),
+ ctype,
+ fold_convert (ctype, op0),
+ t1),
c, code, wide_type, strict_overflow_p);
break;
/* If this was a subtraction, negate OP1 and set it to be an addition.
This simplifies the logic below. */
if (tcode == MINUS_EXPR)
- tcode = PLUS_EXPR, op1 = negate_expr (op1);
+ {
+ tcode = PLUS_EXPR, op1 = negate_expr (op1);
+ /* 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;
+ }
+ }
if (TREE_CODE (op1) != INTEGER_CST)
break;
/* If it's a multiply or a division/modulus operation of a multiple
of our constant, do the operation and verify it doesn't overflow. */
if (code == MULT_EXPR
- || integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c, 0)))
+ || integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c)))
{
op1 = const_binop (code, fold_convert (ctype, op1),
- fold_convert (ctype, c), 0);
+ fold_convert (ctype, c));
/* We allow the constant to overflow with wrapping semantics. */
if (op1 == 0
|| (TREE_OVERFLOW (op1) && !TYPE_OVERFLOW_WRAPS (ctype)))
|| (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
&& TYPE_IS_SIZETYPE (TREE_TYPE (t))))
&& TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST
- && integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c, 0)))
+ && integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c)))
{
*strict_overflow_p = true;
return omit_one_operand (type, integer_zero_node, op0);
/* 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),
+ && 0 != (t1 = int_const_binop (MULT_EXPR,
+ fold_convert (ctype, op1),
fold_convert (ctype, c), 1))
- && 0 != (t1 = force_fit_type_double (ctype, TREE_INT_CST_LOW (t1),
- TREE_INT_CST_HIGH (t1),
+ && 0 != (t1 = force_fit_type_double (ctype, tree_to_double_int (t1),
(TYPE_UNSIGNED (ctype)
&& tcode != MULT_EXPR) ? -1 : 1,
TREE_OVERFLOW (t1)))
&& code != FLOOR_MOD_EXPR && code != ROUND_MOD_EXPR
&& code != MULT_EXPR)))
{
- if (integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c, 0)))
+ if (integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c)))
{
if (TYPE_OVERFLOW_UNDEFINED (ctype))
*strict_overflow_p = true;
return fold_build2 (tcode, ctype, fold_convert (ctype, op0),
fold_convert (ctype,
const_binop (TRUNC_DIV_EXPR,
- op1, c, 0)));
+ op1, c)));
}
- else if (integer_zerop (const_binop (TRUNC_MOD_EXPR, c, op1, 0)))
+ else if (integer_zerop (const_binop (TRUNC_MOD_EXPR, c, op1)))
{
if (TYPE_OVERFLOW_UNDEFINED (ctype))
*strict_overflow_p = true;
return fold_build2 (code, ctype, fold_convert (ctype, op0),
fold_convert (ctype,
const_binop (TRUNC_DIV_EXPR,
- c, op1, 0)));
+ c, op1)));
}
}
break;
possible. */
static tree
-fold_binary_op_with_conditional_arg (enum tree_code code,
+fold_binary_op_with_conditional_arg (location_t loc,
+ enum tree_code code,
tree type, tree op0, tree op1,
tree cond, tree arg, int cond_first_p)
{
tree lhs = NULL_TREE;
tree rhs = NULL_TREE;
- /* 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. */
- if (!TREE_CONSTANT (arg))
- return NULL_TREE;
-
if (TREE_CODE (cond) == COND_EXPR)
{
test = TREE_OPERAND (cond, 0);
false_value = constant_boolean_node (false, testtype);
}
- arg = fold_convert (arg_type, arg);
+ /* 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. */
+ if (!TREE_CONSTANT (arg)
+ && (TREE_SIDE_EFFECTS (arg)
+ || TREE_CONSTANT (true_value) || TREE_CONSTANT (false_value)))
+ return NULL_TREE;
+
+ arg = fold_convert_loc (loc, arg_type, arg);
if (lhs == 0)
{
- true_value = fold_convert (cond_type, true_value);
+ true_value = fold_convert_loc (loc, cond_type, true_value);
if (cond_first_p)
- lhs = fold_build2 (code, type, true_value, arg);
+ lhs = fold_build2_loc (loc, code, type, true_value, arg);
else
- lhs = fold_build2 (code, type, arg, true_value);
+ lhs = fold_build2_loc (loc, code, type, arg, true_value);
}
if (rhs == 0)
{
- false_value = fold_convert (cond_type, false_value);
+ false_value = fold_convert_loc (loc, cond_type, false_value);
if (cond_first_p)
- rhs = fold_build2 (code, type, false_value, arg);
+ rhs = fold_build2_loc (loc, code, type, false_value, arg);
else
- rhs = fold_build2 (code, type, arg, false_value);
+ rhs = fold_build2_loc (loc, code, type, arg, false_value);
}
- test = fold_build3 (COND_EXPR, type, test, lhs, rhs);
- return fold_convert (type, test);
+ /* Check that we have simplified at least one of the branches. */
+ if (!TREE_CONSTANT (arg) && !TREE_CONSTANT (lhs) && !TREE_CONSTANT (rhs))
+ return NULL_TREE;
+
+ return fold_build3_loc (loc, COND_EXPR, type, test, lhs, rhs);
}
\f
can be made, and NULL_TREE otherwise. */
static tree
-fold_mathfn_compare (enum built_in_function fcode, enum tree_code code,
+fold_mathfn_compare (location_t loc,
+ enum built_in_function fcode, enum tree_code code,
tree type, tree arg0, tree arg1)
{
REAL_VALUE_TYPE c;
{
/* sqrt(x) < y is always false, if y is negative. */
if (code == EQ_EXPR || code == LT_EXPR || code == LE_EXPR)
- return omit_one_operand (type, integer_zero_node, arg);
+ return omit_one_operand_loc (loc, type, integer_zero_node, arg);
/* sqrt(x) > y is always true, if y is negative and we
don't care about NaNs, i.e. negative values of x. */
if (code == NE_EXPR || !HONOR_NANS (mode))
- return omit_one_operand (type, integer_one_node, arg);
+ return omit_one_operand_loc (loc, type, integer_one_node, arg);
/* sqrt(x) > y is the same as x >= 0, if y is negative. */
- return fold_build2 (GE_EXPR, type, arg,
+ return fold_build2_loc (loc, GE_EXPR, type, arg,
build_real (TREE_TYPE (arg), dconst0));
}
else if (code == GT_EXPR || code == GE_EXPR)
{
/* sqrt(x) > y is x == +Inf, when y is very large. */
if (HONOR_INFINITIES (mode))
- return fold_build2 (EQ_EXPR, type, arg,
+ return fold_build2_loc (loc, EQ_EXPR, type, arg,
build_real (TREE_TYPE (arg), c2));
/* sqrt(x) > y is always false, when y is very large
and we don't care about infinities. */
- return omit_one_operand (type, integer_zero_node, arg);
+ return omit_one_operand_loc (loc, type, integer_zero_node, arg);
}
/* sqrt(x) > c is the same as x > c*c. */
- return fold_build2 (code, type, arg,
+ return fold_build2_loc (loc, code, type, arg,
build_real (TREE_TYPE (arg), c2));
}
else if (code == LT_EXPR || code == LE_EXPR)
/* sqrt(x) < y is always true, when y is a very large
value and we don't care about NaNs or Infinities. */
if (! HONOR_NANS (mode) && ! HONOR_INFINITIES (mode))
- return omit_one_operand (type, integer_one_node, arg);
+ return omit_one_operand_loc (loc, type, integer_one_node, arg);
/* sqrt(x) < y is x != +Inf when y is very large and we
don't care about NaNs. */
if (! HONOR_NANS (mode))
- return fold_build2 (NE_EXPR, type, arg,
+ return fold_build2_loc (loc, NE_EXPR, type, arg,
build_real (TREE_TYPE (arg), c2));
/* sqrt(x) < y is x >= 0 when y is very large and we
don't care about Infinities. */
if (! HONOR_INFINITIES (mode))
- return fold_build2 (GE_EXPR, type, arg,
+ return fold_build2_loc (loc, GE_EXPR, type, arg,
build_real (TREE_TYPE (arg), dconst0));
/* sqrt(x) < y is x >= 0 && x != +Inf, when y is large. */
return NULL_TREE;
arg = save_expr (arg);
- return fold_build2 (TRUTH_ANDIF_EXPR, type,
- fold_build2 (GE_EXPR, type, 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 (NE_EXPR, type, arg,
+ fold_build2_loc (loc, NE_EXPR, type, arg,
build_real (TREE_TYPE (arg),
c2)));
}
/* sqrt(x) < c is the same as x < c*c, if we ignore NaNs. */
if (! HONOR_NANS (mode))
- return fold_build2 (code, type, arg,
+ return fold_build2_loc (loc, code, type, arg,
build_real (TREE_TYPE (arg), c2));
/* sqrt(x) < c is the same as x >= 0 && x < c*c. */
&& ! CONTAINS_PLACEHOLDER_P (arg))
{
arg = save_expr (arg);
- return fold_build2 (TRUTH_ANDIF_EXPR, type,
- fold_build2 (GE_EXPR, type, 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 (code, type, arg,
+ fold_build2_loc (loc, code, type, arg,
build_real (TREE_TYPE (arg),
c2)));
}
can be made, and NULL_TREE otherwise. */
static tree
-fold_inf_compare (enum tree_code code, tree type, tree arg0, tree arg1)
+fold_inf_compare (location_t loc, enum tree_code code, tree type,
+ tree arg0, tree arg1)
{
enum machine_mode mode;
REAL_VALUE_TYPE max;
/* x > +Inf is always false, if with ignore sNANs. */
if (HONOR_SNANS (mode))
return NULL_TREE;
- return omit_one_operand (type, integer_zero_node, arg0);
+ return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
case LE_EXPR:
/* x <= +Inf is always true, if we don't case about NaNs. */
if (! HONOR_NANS (mode))
- return omit_one_operand (type, integer_one_node, arg0);
+ 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 (EQ_EXPR, type, arg0, arg0);
+ return fold_build2_loc (loc, EQ_EXPR, type, arg0, arg0);
}
break;
case GE_EXPR:
/* x == +Inf and x >= +Inf are always equal to x > DBL_MAX. */
real_maxval (&max, neg, mode);
- return fold_build2 (neg ? LT_EXPR : GT_EXPR, type,
+ return fold_build2_loc (loc, neg ? LT_EXPR : GT_EXPR, type,
arg0, build_real (TREE_TYPE (arg0), max));
case LT_EXPR:
/* x < +Inf is always equal to x <= DBL_MAX. */
real_maxval (&max, neg, mode);
- return fold_build2 (neg ? GE_EXPR : LE_EXPR, type,
+ return fold_build2_loc (loc, neg ? GE_EXPR : LE_EXPR, type,
arg0, build_real (TREE_TYPE (arg0), max));
case NE_EXPR:
/* x != +Inf is always equal to !(x > DBL_MAX). */
real_maxval (&max, neg, mode);
if (! HONOR_NANS (mode))
- return fold_build2 (neg ? GE_EXPR : LE_EXPR, type,
+ return fold_build2_loc (loc, neg ? GE_EXPR : LE_EXPR, type,
arg0, build_real (TREE_TYPE (arg0), max));
- temp = fold_build2 (neg ? LT_EXPR : GT_EXPR, type,
+ temp = fold_build2_loc (loc, neg ? LT_EXPR : GT_EXPR, type,
arg0, build_real (TREE_TYPE (arg0), max));
- return fold_build1 (TRUTH_NOT_EXPR, type, temp);
+ return fold_build1_loc (loc, TRUTH_NOT_EXPR, type, temp);
default:
break;
can be made, and NULL_TREE otherwise. */
static tree
-fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
+fold_div_compare (location_t loc,
+ enum tree_code code, tree type, tree arg0, tree arg1)
{
tree prod, tmp, hi, lo;
tree arg00 = TREE_OPERAND (arg0, 0);
tree arg01 = TREE_OPERAND (arg0, 1);
- unsigned HOST_WIDE_INT lpart;
- HOST_WIDE_INT hpart;
+ double_int val;
bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (arg0));
bool neg_overflow;
int overflow;
TREE_INT_CST_HIGH (arg01),
TREE_INT_CST_LOW (arg1),
TREE_INT_CST_HIGH (arg1),
- &lpart, &hpart, unsigned_p);
- prod = force_fit_type_double (TREE_TYPE (arg00), lpart, hpart,
- -1, overflow);
+ &val.low, &val.high, unsigned_p);
+ prod = force_fit_type_double (TREE_TYPE (arg00), val, -1, overflow);
neg_overflow = false;
if (unsigned_p)
TREE_INT_CST_HIGH (prod),
TREE_INT_CST_LOW (tmp),
TREE_INT_CST_HIGH (tmp),
- &lpart, &hpart, unsigned_p);
- hi = force_fit_type_double (TREE_TYPE (arg00), lpart, hpart,
+ &val.low, &val.high, unsigned_p);
+ hi = force_fit_type_double (TREE_TYPE (arg00), val,
-1, overflow | TREE_OVERFLOW (prod));
}
else if (tree_int_cst_sgn (arg01) >= 0)
{
case EQ_EXPR:
if (TREE_OVERFLOW (lo) && TREE_OVERFLOW (hi))
- return omit_one_operand (type, integer_zero_node, arg00);
+ return omit_one_operand_loc (loc, type, integer_zero_node, arg00);
if (TREE_OVERFLOW (hi))
- return fold_build2 (GE_EXPR, type, arg00, lo);
+ return fold_build2_loc (loc, GE_EXPR, type, arg00, lo);
if (TREE_OVERFLOW (lo))
- return fold_build2 (LE_EXPR, type, arg00, hi);
- return build_range_check (type, arg00, 1, lo, hi);
+ return fold_build2_loc (loc, LE_EXPR, type, arg00, hi);
+ return build_range_check (loc, type, arg00, 1, lo, hi);
case NE_EXPR:
if (TREE_OVERFLOW (lo) && TREE_OVERFLOW (hi))
- return omit_one_operand (type, integer_one_node, arg00);
+ return omit_one_operand_loc (loc, type, integer_one_node, arg00);
if (TREE_OVERFLOW (hi))
- return fold_build2 (LT_EXPR, type, arg00, lo);
+ return fold_build2_loc (loc, LT_EXPR, type, arg00, lo);
if (TREE_OVERFLOW (lo))
- return fold_build2 (GT_EXPR, type, arg00, hi);
- return build_range_check (type, arg00, 0, lo, hi);
+ return fold_build2_loc (loc, GT_EXPR, type, arg00, hi);
+ return build_range_check (loc, type, arg00, 0, lo, hi);
case LT_EXPR:
if (TREE_OVERFLOW (lo))
{
tmp = neg_overflow ? integer_zero_node : integer_one_node;
- return omit_one_operand (type, tmp, arg00);
+ return omit_one_operand_loc (loc, type, tmp, arg00);
}
- return fold_build2 (LT_EXPR, type, arg00, lo);
+ return fold_build2_loc (loc, LT_EXPR, type, arg00, lo);
case LE_EXPR:
if (TREE_OVERFLOW (hi))
{
tmp = neg_overflow ? integer_zero_node : integer_one_node;
- return omit_one_operand (type, tmp, arg00);
+ return omit_one_operand_loc (loc, type, tmp, arg00);
}
- return fold_build2 (LE_EXPR, type, arg00, hi);
+ return fold_build2_loc (loc, LE_EXPR, type, arg00, hi);
case GT_EXPR:
if (TREE_OVERFLOW (hi))
{
tmp = neg_overflow ? integer_one_node : integer_zero_node;
- return omit_one_operand (type, tmp, arg00);
+ return omit_one_operand_loc (loc, type, tmp, arg00);
}
- return fold_build2 (GT_EXPR, type, arg00, hi);
+ return fold_build2_loc (loc, GT_EXPR, type, arg00, hi);
case GE_EXPR:
if (TREE_OVERFLOW (lo))
{
tmp = neg_overflow ? integer_one_node : integer_zero_node;
- return omit_one_operand (type, tmp, arg00);
+ return omit_one_operand_loc (loc, type, tmp, arg00);
}
- return fold_build2 (GE_EXPR, type, arg00, lo);
+ return fold_build2_loc (loc, GE_EXPR, type, arg00, lo);
default:
break;
result type. */
static tree
-fold_single_bit_test_into_sign_test (enum tree_code code, tree arg0, tree arg1,
+fold_single_bit_test_into_sign_test (location_t loc,
+ enum tree_code code, tree arg0, tree arg1,
tree result_type)
{
/* If this is testing a single bit, we can optimize the test. */
== GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (arg00))))
{
tree stype = signed_type_for (TREE_TYPE (arg00));
- return fold_build2 (code == EQ_EXPR ? GE_EXPR : LT_EXPR,
- result_type, fold_convert (stype, arg00),
+ return fold_build2_loc (loc, code == EQ_EXPR ? GE_EXPR : LT_EXPR,
+ result_type,
+ fold_convert_loc (loc, stype, arg00),
build_int_cst (stype, 0));
}
}
NULL. TYPE is the desired result type. */
tree
-fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
- tree result_type)
+fold_single_bit_test (location_t loc, enum tree_code code,
+ tree arg0, tree arg1, tree result_type)
{
/* If this is testing a single bit, we can optimize the test. */
if ((code == NE_EXPR || code == EQ_EXPR)
/* First, see if we can fold the single bit test into a sign-bit
test. */
- tem = fold_single_bit_test_into_sign_test (code, arg0, arg1,
+ tem = fold_single_bit_test_into_sign_test (loc, code, arg0, arg1,
result_type);
if (tem)
return tem;
operations as unsigned. If we must use the AND, we have a choice.
Normally unsigned is faster, but for some machines signed is. */
#ifdef LOAD_EXTEND_OP
- ops_unsigned = (LOAD_EXTEND_OP (operand_mode) == SIGN_EXTEND
+ ops_unsigned = (LOAD_EXTEND_OP (operand_mode) == SIGN_EXTEND
&& !flag_syntax_only) ? 0 : 1;
#else
ops_unsigned = 1;
signed_type = lang_hooks.types.type_for_mode (operand_mode, 0);
unsigned_type = lang_hooks.types.type_for_mode (operand_mode, 1);
intermediate_type = ops_unsigned ? unsigned_type : signed_type;
- inner = fold_convert (intermediate_type, inner);
+ inner = fold_convert_loc (loc, intermediate_type, inner);
if (bitnum != 0)
inner = build2 (RSHIFT_EXPR, intermediate_type,
one = build_int_cst (intermediate_type, 1);
if (code == EQ_EXPR)
- inner = fold_build2 (BIT_XOR_EXPR, intermediate_type, inner, one);
+ inner = fold_build2_loc (loc, BIT_XOR_EXPR, intermediate_type, inner, one);
/* Put the AND last so it can combine with more things. */
inner = build2 (BIT_AND_EXPR, intermediate_type, inner, one);
/* Make sure to return the proper type. */
- inner = fold_convert (result_type, inner);
+ inner = fold_convert_loc (loc, result_type, inner);
return inner;
}
ARG0 is extended to a wider type. */
static tree
-fold_widened_comparison (enum tree_code code, tree type, tree arg0, tree arg1)
+fold_widened_comparison (location_t loc, enum tree_code code,
+ tree type, tree arg0, tree arg1)
{
tree arg0_unw = get_unwidened (arg0, NULL_TREE);
tree arg1_unw;
&& (TREE_CODE (shorter_type) == INTEGER_TYPE
|| TREE_CODE (shorter_type) == BOOLEAN_TYPE)
&& int_fits_type_p (arg1_unw, shorter_type))))
- return fold_build2 (code, type, arg0_unw,
- fold_convert (shorter_type, arg1_unw));
+ return fold_build2_loc (loc, code, type, arg0_unw,
+ fold_convert_loc (loc, shorter_type, arg1_unw));
if (TREE_CODE (arg1_unw) != INTEGER_CST
|| TREE_CODE (shorter_type) != INTEGER_TYPE
{
case EQ_EXPR:
if (above || below)
- return omit_one_operand (type, integer_zero_node, arg0);
+ return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
break;
case NE_EXPR:
if (above || below)
- return omit_one_operand (type, integer_one_node, arg0);
+ return omit_one_operand_loc (loc, type, integer_one_node, arg0);
break;
case LT_EXPR:
case LE_EXPR:
if (above)
- return omit_one_operand (type, integer_one_node, arg0);
+ return omit_one_operand_loc (loc, type, integer_one_node, arg0);
else if (below)
- return omit_one_operand (type, integer_zero_node, arg0);
+ return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
case GT_EXPR:
case GE_EXPR:
if (above)
- return omit_one_operand (type, integer_zero_node, arg0);
+ return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
else if (below)
- return omit_one_operand (type, integer_one_node, arg0);
+ return omit_one_operand_loc (loc, type, integer_one_node, arg0);
default:
break;
ARG0 just the signedness is changed. */
static tree
-fold_sign_changed_comparison (enum tree_code code, tree type,
+fold_sign_changed_comparison (location_t loc, enum tree_code code, tree type,
tree arg0, tree arg1)
{
tree arg0_inner;
return NULL_TREE;
if (TREE_CODE (arg1) == INTEGER_CST)
- arg1 = force_fit_type_double (inner_type, TREE_INT_CST_LOW (arg1),
- TREE_INT_CST_HIGH (arg1), 0,
- TREE_OVERFLOW (arg1));
+ arg1 = force_fit_type_double (inner_type, tree_to_double_int (arg1),
+ 0, TREE_OVERFLOW (arg1));
else
- arg1 = fold_convert (inner_type, arg1);
+ arg1 = fold_convert_loc (loc, inner_type, arg1);
- return fold_build2 (code, type, arg0_inner, arg1);
+ return fold_build2_loc (loc, code, type, arg0_inner, arg1);
}
/* Tries to replace &a[idx] p+ s * delta with &a[idx + delta], if s is
- step of the array. Reconstructs s and delta in the case of s * delta
- being an integer constant (and thus already folded).
- ADDR is the address. MULT is the multiplicative expression.
- If the function succeeds, the new address expression is returned. Otherwise
- NULL_TREE is returned. */
+ step of the array. Reconstructs s and delta in the case of s *
+ delta being an integer constant (and thus already folded). ADDR is
+ the address. MULT is the multiplicative expression. If the
+ function succeeds, the new address expression is returned.
+ Otherwise NULL_TREE is returned. LOC is the location of the
+ resulting expression. */
static tree
-try_move_mult_to_index (tree addr, tree op1)
+try_move_mult_to_index (location_t loc, tree addr, tree op1)
{
tree s, delta, step;
tree ref = TREE_OPERAND (addr, 0), pref;
STRIP_NOPS (arg0);
STRIP_NOPS (arg1);
-
+
if (TREE_CODE (arg0) == INTEGER_CST)
{
s = arg0;
{
if (TREE_CODE (ref) == ARRAY_REF)
{
+ tree domain;
+
/* Remember if this was a multi-dimensional array. */
if (TREE_CODE (TREE_OPERAND (ref, 0)) == ARRAY_REF)
mdim = true;
- itype = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (ref, 0)));
- if (! itype)
+ domain = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (ref, 0)));
+ if (! domain)
continue;
+ itype = TREE_TYPE (domain);
step = array_ref_element_size (ref);
if (TREE_CODE (step) != INTEGER_CST)
tree tmp;
if (TREE_CODE (TREE_OPERAND (ref, 1)) != INTEGER_CST
- || !INTEGRAL_TYPE_P (itype)
- || !TYPE_MAX_VALUE (itype)
- || TREE_CODE (TYPE_MAX_VALUE (itype)) != INTEGER_CST)
+ || !TYPE_MAX_VALUE (domain)
+ || TREE_CODE (TYPE_MAX_VALUE (domain)) != INTEGER_CST)
continue;
- tmp = fold_binary (PLUS_EXPR, itype,
- fold_convert (itype,
- TREE_OPERAND (ref, 1)),
- fold_convert (itype, delta));
+ tmp = fold_binary_loc (loc, PLUS_EXPR, itype,
+ fold_convert_loc (loc, itype,
+ TREE_OPERAND (ref, 1)),
+ fold_convert_loc (loc, itype, delta));
if (!tmp
|| TREE_CODE (tmp) != INTEGER_CST
- || tree_int_cst_lt (TYPE_MAX_VALUE (itype), tmp))
+ || tree_int_cst_lt (TYPE_MAX_VALUE (domain), tmp))
continue;
}
pref = TREE_OPERAND (addr, 0);
ret = copy_node (pref);
+ SET_EXPR_LOCATION (ret, loc);
pos = ret;
while (pref != ref)
pos = TREE_OPERAND (pos, 0);
}
- TREE_OPERAND (pos, 1) = fold_build2 (PLUS_EXPR, itype,
- fold_convert (itype,
- TREE_OPERAND (pos, 1)),
- fold_convert (itype, delta));
+ TREE_OPERAND (pos, 1) = fold_build2_loc (loc, PLUS_EXPR, itype,
+ fold_convert_loc (loc, itype,
+ TREE_OPERAND (pos, 1)),
+ fold_convert_loc (loc, itype, delta));
- return fold_build1 (ADDR_EXPR, TREE_TYPE (addr), ret);
+ return fold_build1_loc (loc, ADDR_EXPR, TREE_TYPE (addr), ret);
}
A < X <= MAX. INEQ is A + 1 > Y, BOUND is A < X. */
static tree
-fold_to_nonsharp_ineq_using_bound (tree ineq, tree bound)
+fold_to_nonsharp_ineq_using_bound (location_t loc, tree ineq, tree bound)
{
tree a, typea, type = TREE_TYPE (ineq), a1, diff, y;
if (POINTER_TYPE_P (typea))
{
/* Convert the pointer types into integer before taking the difference. */
- tree ta = fold_convert (ssizetype, a);
- tree ta1 = fold_convert (ssizetype, a1);
- diff = fold_binary (MINUS_EXPR, ssizetype, ta1, ta);
+ tree ta = fold_convert_loc (loc, ssizetype, a);
+ tree ta1 = fold_convert_loc (loc, ssizetype, a1);
+ diff = fold_binary_loc (loc, MINUS_EXPR, ssizetype, ta1, ta);
}
else
- diff = fold_binary (MINUS_EXPR, typea, a1, a);
+ diff = fold_binary_loc (loc, MINUS_EXPR, typea, a1, a);
if (!diff || !integer_onep (diff))
return NULL_TREE;
- return fold_build2 (GE_EXPR, type, a, y);
+ return fold_build2_loc (loc, GE_EXPR, type, a, y);
}
/* Fold a sum or difference of at least one multiplication.
Returns the folded tree or NULL if no simplification could be made. */
static tree
-fold_plusminus_mult_expr (enum tree_code code, tree type, tree arg0, tree arg1)
+fold_plusminus_mult_expr (location_t loc, enum tree_code code, tree type,
+ tree arg0, tree arg1)
{
tree arg00, arg01, arg10, arg11;
tree alt0 = NULL_TREE, alt1 = NULL_TREE, same;
increased the number of multiplications necessary. */
&& TREE_CODE (arg10) != INTEGER_CST)
{
- alt0 = fold_build2 (MULT_EXPR, TREE_TYPE (arg00), arg00,
+ alt0 = fold_build2_loc (loc, MULT_EXPR, TREE_TYPE (arg00), arg00,
build_int_cst (TREE_TYPE (arg00),
int01 / int11));
alt1 = arg10;
}
if (same)
- return fold_build2 (MULT_EXPR, type,
- fold_build2 (code, type,
- fold_convert (type, alt0),
- fold_convert (type, alt1)),
- fold_convert (type, same));
+ return fold_build2_loc (loc, MULT_EXPR, type,
+ fold_build2_loc (loc, code, type,
+ fold_convert_loc (loc, type, alt0),
+ fold_convert_loc (loc, type, alt1)),
+ fold_convert_loc (loc, type, same));
return NULL_TREE;
}
int total_bytes = GET_MODE_SIZE (TYPE_MODE (type));
int byte, offset, word, words;
unsigned char value;
- unsigned int HOST_WIDE_INT lo = 0;
- HOST_WIDE_INT hi = 0;
+ double_int result;
if (total_bytes > len)
return NULL_TREE;
if (total_bytes * BITS_PER_UNIT > 2 * HOST_BITS_PER_WIDE_INT)
return NULL_TREE;
+
+ result = double_int_zero;
words = total_bytes / UNITS_PER_WORD;
for (byte = 0; byte < total_bytes; byte++)
value = ptr[offset];
if (bitpos < HOST_BITS_PER_WIDE_INT)
- lo |= (unsigned HOST_WIDE_INT) value << bitpos;
+ result.low |= (unsigned HOST_WIDE_INT) value << bitpos;
else
- hi |= (unsigned HOST_WIDE_INT) value
- << (bitpos - HOST_BITS_PER_WIDE_INT);
+ result.high |= (unsigned HOST_WIDE_INT) value
+ << (bitpos - HOST_BITS_PER_WIDE_INT);
}
- return build_int_cst_wide_type (type, lo, hi);
+ return double_int_to_tree (type, result);
}
to avoid confusing the gimplify process. */
tree
-build_fold_addr_expr_with_type (tree t, tree ptrtype)
+build_fold_addr_expr_with_type_loc (location_t loc, tree t, tree ptrtype)
{
/* The size of the object is not relevant when talking about its address. */
if (TREE_CODE (t) == WITH_SIZE_EXPR)
t = TREE_OPERAND (t, 0);
- /* Note: doesn't apply to ALIGN_INDIRECT_REF */
- if (TREE_CODE (t) == INDIRECT_REF
- || TREE_CODE (t) == MISALIGNED_INDIRECT_REF)
+ if (TREE_CODE (t) == INDIRECT_REF)
{
t = TREE_OPERAND (t, 0);
if (TREE_TYPE (t) != ptrtype)
- t = build1 (NOP_EXPR, ptrtype, t);
+ t = build1_loc (loc, NOP_EXPR, ptrtype, t);
}
+ else if (TREE_CODE (t) == MEM_REF
+ && integer_zerop (TREE_OPERAND (t, 1)))
+ return TREE_OPERAND (t, 0);
else if (TREE_CODE (t) == VIEW_CONVERT_EXPR)
{
- t = build_fold_addr_expr (TREE_OPERAND (t, 0));
+ t = build_fold_addr_expr_loc (loc, TREE_OPERAND (t, 0));
if (TREE_TYPE (t) != ptrtype)
- t = fold_convert (ptrtype, t);
+ t = fold_convert_loc (loc, ptrtype, t);
}
else
- t = build1 (ADDR_EXPR, ptrtype, t);
+ t = build1_loc (loc, ADDR_EXPR, ptrtype, t);
return t;
}
/* Build an expression for the address of T. */
tree
-build_fold_addr_expr (tree t)
+build_fold_addr_expr_loc (location_t loc, tree t)
{
tree ptrtype = build_pointer_type (TREE_TYPE (t));
- return build_fold_addr_expr_with_type (t, ptrtype);
+ return build_fold_addr_expr_with_type_loc (loc, t, ptrtype);
}
/* Fold a unary expression of code CODE and type TYPE with operand
Otherwise, return NULL_TREE. */
tree
-fold_unary (enum tree_code code, tree type, tree op0)
+fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
{
tree tem;
tree arg0;
{
if (TREE_CODE (arg0) == COMPOUND_EXPR)
return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
- fold_build1 (code, type,
- fold_convert (TREE_TYPE (op0),
- TREE_OPERAND (arg0, 1))));
+ fold_build1_loc (loc, code, type,
+ fold_convert_loc (loc, TREE_TYPE (op0),
+ TREE_OPERAND (arg0, 1))));
else if (TREE_CODE (arg0) == COND_EXPR)
{
tree arg01 = TREE_OPERAND (arg0, 1);
tree arg02 = TREE_OPERAND (arg0, 2);
if (! VOID_TYPE_P (TREE_TYPE (arg01)))
- arg01 = fold_build1 (code, type,
- fold_convert (TREE_TYPE (op0), arg01));
+ arg01 = fold_build1_loc (loc, code, type,
+ fold_convert_loc (loc,
+ TREE_TYPE (op0), arg01));
if (! VOID_TYPE_P (TREE_TYPE (arg02)))
- arg02 = fold_build1 (code, type,
- fold_convert (TREE_TYPE (op0), arg02));
- tem = fold_build3 (COND_EXPR, type, TREE_OPERAND (arg0, 0),
+ arg02 = fold_build1_loc (loc, code, type,
+ fold_convert_loc (loc,
+ TREE_TYPE (op0), arg02));
+ tem = fold_build3_loc (loc, COND_EXPR, type, TREE_OPERAND (arg0, 0),
arg01, arg02);
/* If this was a conversion, and all we did was to move into
(TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 1), 0))))
&& TYPE_PRECISION (TREE_TYPE (tem)) <= BITS_PER_WORD)
|| flag_syntax_only))
- tem = build1 (code, type,
- build3 (COND_EXPR,
- TREE_TYPE (TREE_OPERAND
- (TREE_OPERAND (tem, 1), 0)),
- TREE_OPERAND (tem, 0),
- TREE_OPERAND (TREE_OPERAND (tem, 1), 0),
- TREE_OPERAND (TREE_OPERAND (tem, 2), 0)));
+ tem = build1_loc (loc, code, type,
+ build3 (COND_EXPR,
+ TREE_TYPE (TREE_OPERAND
+ (TREE_OPERAND (tem, 1), 0)),
+ TREE_OPERAND (tem, 0),
+ TREE_OPERAND (TREE_OPERAND (tem, 1), 0),
+ TREE_OPERAND (TREE_OPERAND (tem, 2),
+ 0)));
return tem;
}
else if (COMPARISON_CLASS_P (arg0))
return arg0;
}
else if (TREE_CODE (type) != INTEGER_TYPE)
- return fold_build3 (COND_EXPR, type, arg0,
- fold_build1 (code, type,
+ return fold_build3_loc (loc, COND_EXPR, type, arg0,
+ fold_build1_loc (loc, code, type,
integer_one_node),
- fold_build1 (code, type,
+ fold_build1_loc (loc, code, type,
integer_zero_node));
}
}
barriers can be removed. */
if (CONSTANT_CLASS_P (op0)
|| TREE_CODE (op0) == PAREN_EXPR)
- return fold_convert (type, op0);
+ return fold_convert_loc (loc, type, op0);
return NULL_TREE;
CASE_CONVERT:
case FIX_TRUNC_EXPR:
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 (TREE_CODE (op0), type, TREE_OPERAND (op0, 0),
+ return fold_build2_loc (loc, TREE_CODE (op0), type, TREE_OPERAND (op0, 0),
TREE_OPERAND (op0, 1));
/* Handle cases of two conversions in a row. */
&& (((inter_int || inter_ptr) && final_int)
|| (inter_float && final_float))
&& inter_prec >= final_prec)
- return fold_build1 (code, type, TREE_OPERAND (op0, 0));
+ return fold_build1_loc (loc, code, type, TREE_OPERAND (op0, 0));
/* Likewise, if the intermediate and initial types are either both
float or both integer, we don't need the middle conversion if the
&& TYPE_MODE (type) == TYPE_MODE (inter_type))
&& ! final_ptr
&& (! final_vec || inter_prec == inside_prec))
- return fold_build1 (code, type, TREE_OPERAND (op0, 0));
+ return fold_build1_loc (loc, code, type, TREE_OPERAND (op0, 0));
/* If we have a sign-extension of a zero-extended value, we can
replace that by a single zero-extension. */
if (inside_int && inter_int && final_int
&& inside_prec < inter_prec && inter_prec < final_prec
&& inside_unsignedp && !inter_unsignedp)
- return fold_build1 (code, type, TREE_OPERAND (op0, 0));
+ return fold_build1_loc (loc, code, type, TREE_OPERAND (op0, 0));
/* Two conversions in a row are not needed unless:
- some conversion is floating-point (overstrict for now), or
&& ! (final_ptr && inside_prec != inter_prec)
&& ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (type))
&& TYPE_MODE (type) == TYPE_MODE (inter_type)))
- return fold_build1 (code, type, TREE_OPERAND (op0, 0));
+ return fold_build1_loc (loc, code, type, TREE_OPERAND (op0, 0));
}
/* Handle (T *)&A.B.C for A being of type T and B and C
&mode, &unsignedp, &volatilep, false);
/* If the reference was to a (constant) zero offset, we can use
the address of the base if it has the same base type
- as the result type. */
+ as the result type and the pointer type is unqualified. */
if (! offset && bitpos == 0
- && TYPE_MAIN_VARIANT (TREE_TYPE (type))
+ && (TYPE_MAIN_VARIANT (TREE_TYPE (type))
== TYPE_MAIN_VARIANT (TREE_TYPE (base)))
- return fold_convert (type, build_fold_addr_expr (base));
+ && TYPE_QUALS (type) == TYPE_UNQUALIFIED)
+ return fold_convert_loc (loc, type,
+ build_fold_addr_expr_loc (loc, base));
}
if (TREE_CODE (op0) == MODIFY_EXPR
{
/* Don't leave an assignment inside a conversion
unless assigning a bitfield. */
- tem = fold_build1 (code, type, TREE_OPERAND (op0, 1));
+ tem = fold_build1_loc (loc, code, type, TREE_OPERAND (op0, 1));
/* First do the assignment, then return converted constant. */
- tem = build2 (COMPOUND_EXPR, TREE_TYPE (tem), op0, tem);
+ tem = build2_loc (loc, COMPOUND_EXPR, TREE_TYPE (tem), op0, tem);
TREE_NO_WARNING (tem) = 1;
TREE_USED (tem) = 1;
return tem;
&& TREE_CODE (op0) == BIT_AND_EXPR
&& TREE_CODE (TREE_OPERAND (op0, 1)) == INTEGER_CST)
{
- tree and = op0;
- tree and0 = TREE_OPERAND (and, 0), and1 = TREE_OPERAND (and, 1);
+ tree and_expr = op0;
+ tree and0 = TREE_OPERAND (and_expr, 0);
+ tree and1 = TREE_OPERAND (and_expr, 1);
int change = 0;
- if (TYPE_UNSIGNED (TREE_TYPE (and))
+ if (TYPE_UNSIGNED (TREE_TYPE (and_expr))
|| (TYPE_PRECISION (type)
- <= TYPE_PRECISION (TREE_TYPE (and))))
+ <= TYPE_PRECISION (TREE_TYPE (and_expr))))
change = 1;
else if (TYPE_PRECISION (TREE_TYPE (and1))
<= HOST_BITS_PER_WIDE_INT
== ZERO_EXTEND))
{
tree uns = unsigned_type_for (TREE_TYPE (and0));
- and0 = fold_convert (uns, and0);
- and1 = fold_convert (uns, and1);
+ and0 = fold_convert_loc (loc, uns, and0);
+ and1 = fold_convert_loc (loc, uns, and1);
}
#endif
}
if (change)
{
- tem = force_fit_type_double (type, TREE_INT_CST_LOW (and1),
- TREE_INT_CST_HIGH (and1), 0,
- TREE_OVERFLOW (and1));
- return fold_build2 (BIT_AND_EXPR, type,
- fold_convert (type, and0), tem);
+ tem = force_fit_type_double (type, tree_to_double_int (and1),
+ 0, TREE_OVERFLOW (and1));
+ return fold_build2_loc (loc, BIT_AND_EXPR, type,
+ fold_convert_loc (loc, type, and0), tem);
}
}
tree arg00 = TREE_OPERAND (arg0, 0);
tree arg01 = TREE_OPERAND (arg0, 1);
- return fold_build2 (TREE_CODE (arg0), type, fold_convert (type, arg00),
- fold_convert (sizetype, arg01));
+ return fold_build2_loc (loc,
+ TREE_CODE (arg0), type,
+ fold_convert_loc (loc, type, arg00),
+ fold_convert_loc (loc, sizetype, arg01));
}
/* Convert (T1)(~(T2)X) into ~(T1)X if T1 and T2 are integral types
tem = TREE_OPERAND (TREE_OPERAND (op0, 0), 0);
if (INTEGRAL_TYPE_P (TREE_TYPE (tem))
&& TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (tem)))
- return fold_build1 (BIT_NOT_EXPR, type, fold_convert (type, tem));
+ return fold_build1_loc (loc, BIT_NOT_EXPR, type,
+ fold_convert_loc (loc, type, tem));
}
/* Convert (T1)(X * Y) into (T1)X * (T1)Y if T1 is narrower than the
if (TYPE_PRECISION (mult_type) < TYPE_PRECISION (TREE_TYPE (op0)))
{
- tem = fold_build2 (MULT_EXPR, mult_type,
- fold_convert (mult_type,
- TREE_OPERAND (op0, 0)),
- fold_convert (mult_type,
- TREE_OPERAND (op0, 1)));
- return fold_convert (type, tem);
+ tem = fold_build2_loc (loc, MULT_EXPR, mult_type,
+ fold_convert_loc (loc, mult_type,
+ TREE_OPERAND (op0, 0)),
+ fold_convert_loc (loc, mult_type,
+ TREE_OPERAND (op0, 1)));
+ return fold_convert_loc (loc, type, tem);
}
}
tem = fold_convert_const (code, type, op0);
return tem ? tem : NULL_TREE;
+ case ADDR_SPACE_CONVERT_EXPR:
+ if (integer_zerop (arg0))
+ return fold_convert_const (code, type, arg0);
+ return NULL_TREE;
+
case FIXED_CONVERT_EXPR:
tem = fold_convert_const (code, type, arg0);
return tem ? tem : NULL_TREE;
if (TREE_TYPE (op0) == type)
return op0;
if (TREE_CODE (op0) == VIEW_CONVERT_EXPR)
- return fold_build1 (VIEW_CONVERT_EXPR, type, TREE_OPERAND (op0, 0));
+ return fold_build1_loc (loc, VIEW_CONVERT_EXPR,
+ type, TREE_OPERAND (op0, 0));
+ if (TREE_CODE (op0) == MEM_REF)
+ return fold_build2_loc (loc, MEM_REF, type,
+ TREE_OPERAND (op0, 0), TREE_OPERAND (op0, 1));
/* For integral conversions with the same precision or pointer
conversions use a NOP_EXPR instead. */
&& (INTEGRAL_TYPE_P (TREE_TYPE (op0))
|| POINTER_TYPE_P (TREE_TYPE (op0)))
&& TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (op0)))
- return fold_convert (type, op0);
+ return fold_convert_loc (loc, type, op0);
/* Strip inner integral conversions that do not change the precision. */
if (CONVERT_EXPR_P (op0)
|| POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (op0, 0))))
&& (TYPE_PRECISION (TREE_TYPE (op0))
== TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op0, 0)))))
- return fold_build1 (VIEW_CONVERT_EXPR, type, TREE_OPERAND (op0, 0));
+ return fold_build1_loc (loc, VIEW_CONVERT_EXPR,
+ type, TREE_OPERAND (op0, 0));
return fold_view_convert_expr (type, op0);
case NEGATE_EXPR:
- tem = fold_negate_expr (arg0);
+ tem = fold_negate_expr (loc, arg0);
if (tem)
- return fold_convert (type, tem);
+ return fold_convert_loc (loc, type, tem);
return NULL_TREE;
case ABS_EXPR:
if (TREE_CODE (arg0) == INTEGER_CST || TREE_CODE (arg0) == REAL_CST)
return fold_abs_const (arg0, type);
else if (TREE_CODE (arg0) == NEGATE_EXPR)
- return fold_build1 (ABS_EXPR, type, TREE_OPERAND (arg0, 0));
+ return fold_build1_loc (loc, ABS_EXPR, type, TREE_OPERAND (arg0, 0));
/* Convert fabs((double)float) into (double)fabsf(float). */
else if (TREE_CODE (arg0) == NOP_EXPR
&& TREE_CODE (type) == REAL_TYPE)
{
tree targ0 = strip_float_extensions (arg0);
if (targ0 != arg0)
- return fold_convert (type, fold_build1 (ABS_EXPR,
- TREE_TYPE (targ0),
- targ0));
+ return fold_convert_loc (loc, type,
+ fold_build1_loc (loc, ABS_EXPR,
+ TREE_TYPE (targ0),
+ targ0));
}
/* ABS_EXPR<ABS_EXPR<x>> = ABS_EXPR<x> even if flag_wrapv is on. */
else if (TREE_CODE (arg0) == ABS_EXPR)
{
tem = fold_strip_sign_ops (arg0);
if (tem)
- return fold_build1 (ABS_EXPR, type, fold_convert (type, tem));
+ return fold_build1_loc (loc, ABS_EXPR, type,
+ fold_convert_loc (loc, type, tem));
}
return NULL_TREE;
case CONJ_EXPR:
if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
- return fold_convert (type, arg0);
+ return fold_convert_loc (loc, type, arg0);
if (TREE_CODE (arg0) == COMPLEX_EXPR)
{
tree itype = TREE_TYPE (type);
- tree rpart = fold_convert (itype, TREE_OPERAND (arg0, 0));
- tree ipart = fold_convert (itype, TREE_OPERAND (arg0, 1));
- return fold_build2 (COMPLEX_EXPR, type, rpart, negate_expr (ipart));
+ tree rpart = fold_convert_loc (loc, itype, TREE_OPERAND (arg0, 0));
+ tree ipart = fold_convert_loc (loc, itype, TREE_OPERAND (arg0, 1));
+ return fold_build2_loc (loc, COMPLEX_EXPR, type, rpart,
+ negate_expr (ipart));
}
if (TREE_CODE (arg0) == COMPLEX_CST)
{
tree itype = TREE_TYPE (type);
- tree rpart = fold_convert (itype, TREE_REALPART (arg0));
- tree ipart = fold_convert (itype, TREE_IMAGPART (arg0));
+ tree rpart = fold_convert_loc (loc, itype, TREE_REALPART (arg0));
+ tree ipart = fold_convert_loc (loc, itype, TREE_IMAGPART (arg0));
return build_complex (type, rpart, negate_expr (ipart));
}
if (TREE_CODE (arg0) == CONJ_EXPR)
- return fold_convert (type, TREE_OPERAND (arg0, 0));
+ return fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
return NULL_TREE;
case BIT_NOT_EXPR:
if (TREE_CODE (arg0) == INTEGER_CST)
return fold_not_const (arg0, type);
else if (TREE_CODE (arg0) == BIT_NOT_EXPR)
- return fold_convert (type, TREE_OPERAND (arg0, 0));
+ return fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
/* Convert ~ (-A) to A - 1. */
else if (INTEGRAL_TYPE_P (type) && TREE_CODE (arg0) == NEGATE_EXPR)
- return fold_build2 (MINUS_EXPR, type,
- fold_convert (type, TREE_OPERAND (arg0, 0)),
+ return fold_build2_loc (loc, MINUS_EXPR, type,
+ fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0)),
build_int_cst (type, 1));
/* Convert ~ (A - 1) or ~ (A + -1) to -A. */
else if (INTEGRAL_TYPE_P (type)
&& integer_onep (TREE_OPERAND (arg0, 1)))
|| (TREE_CODE (arg0) == PLUS_EXPR
&& integer_all_onesp (TREE_OPERAND (arg0, 1)))))
- return fold_build1 (NEGATE_EXPR, type,
- fold_convert (type, TREE_OPERAND (arg0, 0)));
+ return fold_build1_loc (loc, NEGATE_EXPR, type,
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg0, 0)));
/* 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 (BIT_NOT_EXPR, type,
- fold_convert (type,
- TREE_OPERAND (arg0, 0)))))
- return fold_build2 (BIT_XOR_EXPR, type, tem,
- fold_convert (type, TREE_OPERAND (arg0, 1)));
+ && (tem = fold_unary_loc (loc, BIT_NOT_EXPR, type,
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg0, 0)))))
+ return fold_build2_loc (loc, BIT_XOR_EXPR, type, tem,
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg0, 1)));
else if (TREE_CODE (arg0) == BIT_XOR_EXPR
- && (tem = fold_unary (BIT_NOT_EXPR, type,
- fold_convert (type,
- TREE_OPERAND (arg0, 1)))))
- return fold_build2 (BIT_XOR_EXPR, type,
- fold_convert (type, TREE_OPERAND (arg0, 0)), tem);
+ && (tem = fold_unary_loc (loc, BIT_NOT_EXPR, type,
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg0, 1)))))
+ return fold_build2_loc (loc, BIT_XOR_EXPR, type,
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg0, 0)), tem);
/* Perform BIT_NOT_EXPR on each element individually. */
else if (TREE_CODE (arg0) == VECTOR_CST)
{
if (elements)
{
elem = TREE_VALUE (elements);
- elem = fold_unary (BIT_NOT_EXPR, TREE_TYPE (type), elem);
+ elem = fold_unary_loc (loc, BIT_NOT_EXPR, TREE_TYPE (type), elem);
if (elem == NULL_TREE)
break;
elements = TREE_CHAIN (elements);
case TRUTH_NOT_EXPR:
/* The argument to invert_truthvalue must have Boolean type. */
if (TREE_CODE (TREE_TYPE (arg0)) != BOOLEAN_TYPE)
- arg0 = fold_convert (boolean_type_node, arg0);
+ arg0 = fold_convert_loc (loc, boolean_type_node, arg0);
/* Note that the operand of this must be an int
and its values must be 0 or 1.
("true" is a fixed value perhaps depending on the language,
but we don't handle values other than 1 correctly yet.) */
- tem = fold_truth_not_expr (arg0);
+ tem = fold_truth_not_expr (loc, arg0);
if (!tem)
return NULL_TREE;
- return fold_convert (type, tem);
+ return fold_convert_loc (loc, type, tem);
case REALPART_EXPR:
if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
- return fold_convert (type, arg0);
+ return fold_convert_loc (loc, type, arg0);
if (TREE_CODE (arg0) == COMPLEX_EXPR)
- return omit_one_operand (type, TREE_OPERAND (arg0, 0),
+ return omit_one_operand_loc (loc, type, TREE_OPERAND (arg0, 0),
TREE_OPERAND (arg0, 1));
if (TREE_CODE (arg0) == COMPLEX_CST)
- return fold_convert (type, TREE_REALPART (arg0));
+ return fold_convert_loc (loc, type, TREE_REALPART (arg0));
if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
{
tree itype = TREE_TYPE (TREE_TYPE (arg0));
- tem = fold_build2 (TREE_CODE (arg0), itype,
- fold_build1 (REALPART_EXPR, itype,
+ tem = fold_build2_loc (loc, TREE_CODE (arg0), itype,
+ fold_build1_loc (loc, REALPART_EXPR, itype,
TREE_OPERAND (arg0, 0)),
- fold_build1 (REALPART_EXPR, itype,
+ fold_build1_loc (loc, REALPART_EXPR, itype,
TREE_OPERAND (arg0, 1)));
- return fold_convert (type, tem);
+ return fold_convert_loc (loc, type, tem);
}
if (TREE_CODE (arg0) == CONJ_EXPR)
{
tree itype = TREE_TYPE (TREE_TYPE (arg0));
- tem = fold_build1 (REALPART_EXPR, itype, TREE_OPERAND (arg0, 0));
- return fold_convert (type, tem);
+ tem = fold_build1_loc (loc, REALPART_EXPR, itype,
+ TREE_OPERAND (arg0, 0));
+ return fold_convert_loc (loc, type, tem);
}
if (TREE_CODE (arg0) == CALL_EXPR)
{
CASE_FLT_FN (BUILT_IN_CEXPI):
fn = mathfn_built_in (type, BUILT_IN_COS);
if (fn)
- return build_call_expr (fn, 1, CALL_EXPR_ARG (arg0, 0));
+ return build_call_expr_loc (loc, fn, 1, CALL_EXPR_ARG (arg0, 0));
break;
default:
case IMAGPART_EXPR:
if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
- return fold_convert (type, integer_zero_node);
+ return build_zero_cst (type);
if (TREE_CODE (arg0) == COMPLEX_EXPR)
- return omit_one_operand (type, TREE_OPERAND (arg0, 1),
+ return omit_one_operand_loc (loc, type, TREE_OPERAND (arg0, 1),
TREE_OPERAND (arg0, 0));
if (TREE_CODE (arg0) == COMPLEX_CST)
- return fold_convert (type, TREE_IMAGPART (arg0));
+ return fold_convert_loc (loc, type, TREE_IMAGPART (arg0));
if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
{
tree itype = TREE_TYPE (TREE_TYPE (arg0));
- tem = fold_build2 (TREE_CODE (arg0), itype,
- fold_build1 (IMAGPART_EXPR, itype,
+ tem = fold_build2_loc (loc, TREE_CODE (arg0), itype,
+ fold_build1_loc (loc, IMAGPART_EXPR, itype,
TREE_OPERAND (arg0, 0)),
- fold_build1 (IMAGPART_EXPR, itype,
+ fold_build1_loc (loc, IMAGPART_EXPR, itype,
TREE_OPERAND (arg0, 1)));
- return fold_convert (type, tem);
+ return fold_convert_loc (loc, type, tem);
}
if (TREE_CODE (arg0) == CONJ_EXPR)
{
tree itype = TREE_TYPE (TREE_TYPE (arg0));
- tem = fold_build1 (IMAGPART_EXPR, itype, TREE_OPERAND (arg0, 0));
- return fold_convert (type, negate_expr (tem));
+ tem = fold_build1_loc (loc, IMAGPART_EXPR, itype, TREE_OPERAND (arg0, 0));
+ return fold_convert_loc (loc, type, negate_expr (tem));
}
if (TREE_CODE (arg0) == CALL_EXPR)
{
CASE_FLT_FN (BUILT_IN_CEXPI):
fn = mathfn_built_in (type, BUILT_IN_SIN);
if (fn)
- return build_call_expr (fn, 1, CALL_EXPR_ARG (arg0, 0));
+ return build_call_expr_loc (loc, fn, 1, CALL_EXPR_ARG (arg0, 0));
break;
default:
}
return NULL_TREE;
+ case INDIRECT_REF:
+ /* Fold *&X to X if X is an lvalue. */
+ if (TREE_CODE (op0) == ADDR_EXPR)
+ {
+ tree op00 = TREE_OPERAND (op0, 0);
+ if ((TREE_CODE (op00) == VAR_DECL
+ || TREE_CODE (op00) == PARM_DECL
+ || TREE_CODE (op00) == RESULT_DECL)
+ && !TREE_READONLY (op00))
+ return op00;
+ }
+ return NULL_TREE;
+
default:
return NULL_TREE;
} /* switch (code) */
have implementation defined behavior and retaining the TREE_OVERFLOW
flag here would confuse later passes such as VRP. */
tree
-fold_unary_ignore_overflow (enum tree_code code, tree type, tree op0)
+fold_unary_ignore_overflow_loc (location_t loc, enum tree_code code,
+ tree type, tree op0)
{
- tree res = fold_unary (code, type, op0);
+ tree res = fold_unary_loc (loc, code, type, op0);
if (res
&& TREE_CODE (res) == INTEGER_CST
&& TREE_CODE (op0) == INTEGER_CST
return NULL_TREE. */
static tree
-fold_minmax (enum tree_code code, tree type, tree op0, tree op1)
+fold_minmax (location_t loc, enum tree_code code, tree type, tree op0, tree op1)
{
enum tree_code compl_code;
/* MIN (MAX (a, b), b) == b. */
if (TREE_CODE (op0) == compl_code
&& operand_equal_p (TREE_OPERAND (op0, 1), op1, 0))
- return omit_one_operand (type, op1, TREE_OPERAND (op0, 0));
+ return omit_one_operand_loc (loc, type, op1, TREE_OPERAND (op0, 0));
/* MIN (MAX (b, a), b) == b. */
if (TREE_CODE (op0) == compl_code
&& operand_equal_p (TREE_OPERAND (op0, 0), op1, 0)
&& reorder_operands_p (TREE_OPERAND (op0, 1), op1))
- return omit_one_operand (type, op1, TREE_OPERAND (op0, 1));
+ return omit_one_operand_loc (loc, type, op1, TREE_OPERAND (op0, 1));
/* MIN (a, MAX (a, b)) == a. */
if (TREE_CODE (op1) == compl_code
&& operand_equal_p (op0, TREE_OPERAND (op1, 0), 0)
&& reorder_operands_p (op0, TREE_OPERAND (op1, 1)))
- return omit_one_operand (type, op0, TREE_OPERAND (op1, 1));
+ return omit_one_operand_loc (loc, type, op0, TREE_OPERAND (op1, 1));
/* MIN (a, MAX (b, a)) == a. */
if (TREE_CODE (op1) == compl_code
&& operand_equal_p (op0, TREE_OPERAND (op1, 1), 0)
&& reorder_operands_p (op0, TREE_OPERAND (op1, 0)))
- return omit_one_operand (type, op0, TREE_OPERAND (op1, 0));
+ return omit_one_operand_loc (loc, type, op0, TREE_OPERAND (op1, 0));
return NULL_TREE;
}
valid if signed overflow is undefined. */
static tree
-maybe_canonicalize_comparison_1 (enum tree_code code, tree type,
+maybe_canonicalize_comparison_1 (location_t loc, enum tree_code code, tree type,
tree arg0, tree arg1,
bool *strict_overflow_p)
{
t = int_const_binop (sgn0 == -1 ? PLUS_EXPR : MINUS_EXPR,
cst0, build_int_cst (TREE_TYPE (cst0), 1), 0);
if (code0 != INTEGER_CST)
- t = fold_build2 (code0, TREE_TYPE (arg0), TREE_OPERAND (arg0, 0), t);
+ t = fold_build2_loc (loc, code0, TREE_TYPE (arg0), TREE_OPERAND (arg0, 0), t);
/* If swapping might yield to a more canonical form, do so. */
if (swap)
- return fold_build2 (swap_tree_comparison (code), type, arg1, t);
+ return fold_build2_loc (loc, swap_tree_comparison (code), type, arg1, t);
else
- return fold_build2 (code, type, t, arg1);
+ return fold_build2_loc (loc, code, type, t, arg1);
}
/* Canonicalize the comparison ARG0 CODE ARG1 with type TYPE with undefined
Returns the canonicalized tree if changed, otherwise NULL_TREE. */
static tree
-maybe_canonicalize_comparison (enum tree_code code, tree type,
+maybe_canonicalize_comparison (location_t loc, enum tree_code code, tree type,
tree arg0, tree arg1)
{
tree t;
/* Try canonicalization by simplifying arg0. */
strict_overflow_p = false;
- t = maybe_canonicalize_comparison_1 (code, type, arg0, arg1,
+ t = maybe_canonicalize_comparison_1 (loc, code, type, arg0, arg1,
&strict_overflow_p);
if (t)
{
comparison. */
code = swap_tree_comparison (code);
strict_overflow_p = false;
- t = maybe_canonicalize_comparison_1 (code, type, arg1, arg0,
+ t = maybe_canonicalize_comparison_1 (loc, code, type, arg1, arg0,
&strict_overflow_p);
if (t && strict_overflow_p)
fold_overflow_warning (warnmsg, WARN_STRICT_OVERFLOW_MAGNITUDE);
the folded comparison or NULL_TREE. */
static tree
-fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
+fold_comparison (location_t loc, enum tree_code code, tree type,
+ tree op0, tree op1)
{
tree arg0, arg1, tem;
/* If one arg is a real or integer constant, put it last. */
if (tree_swap_operands_p (arg0, arg1, true))
- return fold_build2 (swap_tree_comparison (code), type, op1, op0);
+ return fold_build2_loc (loc, swap_tree_comparison (code), type, op1, op0);
/* 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)
int lhs_add;
lhs_add = TREE_CODE (arg0) != PLUS_EXPR;
- lhs = fold_build2 (lhs_add ? PLUS_EXPR : MINUS_EXPR,
+ lhs = fold_build2_loc (loc, lhs_add ? PLUS_EXPR : MINUS_EXPR,
TREE_TYPE (arg1), const2, const1);
/* If the constant operation overflowed this can be
if (code2 == LT_EXPR
|| code2 == LE_EXPR
|| code2 == EQ_EXPR)
- return omit_one_operand (type, boolean_false_node, variable);
+ return omit_one_operand_loc (loc, type, boolean_false_node, variable);
else if (code2 == NE_EXPR
|| code2 == GE_EXPR
|| code2 == GT_EXPR)
- return omit_one_operand (type, boolean_true_node, variable);
+ return omit_one_operand_loc (loc, type, boolean_true_node, variable);
}
if (TREE_CODE (lhs) == TREE_CODE (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);
- return fold_build2 (code, type, variable, lhs);
+ 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);
}
}
else if (TREE_CODE (arg0) == POINTER_PLUS_EXPR)
{
base0 = TREE_OPERAND (arg0, 0);
+ STRIP_SIGN_NOPS (base0);
+ if (TREE_CODE (base0) == ADDR_EXPR)
+ {
+ base0 = TREE_OPERAND (base0, 0);
+ indirect_base0 = true;
+ }
offset0 = TREE_OPERAND (arg0, 1);
}
else if (TREE_CODE (arg1) == POINTER_PLUS_EXPR)
{
base1 = TREE_OPERAND (arg1, 0);
+ STRIP_SIGN_NOPS (base1);
+ if (TREE_CODE (base1) == ADDR_EXPR)
+ {
+ base1 = TREE_OPERAND (base1, 0);
+ indirect_base1 = true;
+ }
offset1 = TREE_OPERAND (arg1, 1);
}
+ /* A local variable can never be pointed to by
+ the default SSA name of an incoming parameter. */
+ if ((TREE_CODE (arg0) == ADDR_EXPR
+ && indirect_base0
+ && TREE_CODE (base0) == VAR_DECL
+ && auto_var_in_fn_p (base0, current_function_decl)
+ && !indirect_base1
+ && TREE_CODE (base1) == SSA_NAME
+ && TREE_CODE (SSA_NAME_VAR (base1)) == PARM_DECL
+ && SSA_NAME_IS_DEFAULT_DEF (base1))
+ || (TREE_CODE (arg1) == ADDR_EXPR
+ && indirect_base1
+ && TREE_CODE (base1) == VAR_DECL
+ && auto_var_in_fn_p (base1, current_function_decl)
+ && !indirect_base0
+ && TREE_CODE (base0) == SSA_NAME
+ && TREE_CODE (SSA_NAME_VAR (base0)) == PARM_DECL
+ && SSA_NAME_IS_DEFAULT_DEF (base0)))
+ {
+ if (code == NE_EXPR)
+ return constant_boolean_node (1, type);
+ else if (code == EQ_EXPR)
+ return constant_boolean_node (0, type);
+ }
/* If we have equivalent bases we might be able to simplify. */
- if (indirect_base0 == indirect_base1
- && operand_equal_p (base0, base1, 0))
+ else if (indirect_base0 == indirect_base1
+ && operand_equal_p (base0, base1, 0))
{
/* We can fold this expression to a constant if the non-constant
offset parts are equal. */
&& (code == EQ_EXPR
|| code == NE_EXPR
|| POINTER_TYPE_OVERFLOW_UNDEFINED))
-
+
{
if (code != EQ_EXPR
&& code != NE_EXPR
&& ((code == EQ_EXPR || code == NE_EXPR)
|| POINTER_TYPE_OVERFLOW_UNDEFINED))
{
- tree signed_size_type_node;
- signed_size_type_node = signed_type_for (size_type_node);
-
/* By converting to signed size type we cover middle-end pointer
arithmetic which operates on unsigned pointer types of size
type size and ARRAY_REF offsets which are properly sign or
zero extended from their type in case it is narrower than
size type. */
if (offset0 == NULL_TREE)
- offset0 = build_int_cst (signed_size_type_node, 0);
+ offset0 = build_int_cst (ssizetype, 0);
else
- offset0 = fold_convert (signed_size_type_node, offset0);
+ offset0 = fold_convert_loc (loc, ssizetype, offset0);
if (offset1 == NULL_TREE)
- offset1 = build_int_cst (signed_size_type_node, 0);
+ offset1 = build_int_cst (ssizetype, 0);
else
- offset1 = fold_convert (signed_size_type_node, offset1);
+ offset1 = fold_convert_loc (loc, ssizetype, offset1);
if (code != EQ_EXPR
&& code != NE_EXPR
"P +- C2"),
WARN_STRICT_OVERFLOW_COMPARISON);
- return fold_build2 (code, type, offset0, offset1);
+ return fold_build2_loc (loc, code, type, offset0, offset1);
}
}
/* For non-equal bases we can simplify if they are addresses
|| CONSTANT_CLASS_P (base1)))
{
if (code == EQ_EXPR)
- return omit_two_operands (type, boolean_false_node, arg0, arg1);
+ return omit_two_operands_loc (loc, type, boolean_false_node,
+ arg0, arg1);
else if (code == NE_EXPR)
- return omit_two_operands (type, boolean_true_node, arg0, arg1);
+ return omit_two_operands_loc (loc, type, boolean_true_node,
+ arg0, arg1);
}
/* For equal offsets we can simplify to a comparison of the
base addresses. */
&& operand_equal_p (offset0, offset1, 0))))
{
if (indirect_base0)
- base0 = build_fold_addr_expr (base0);
+ base0 = build_fold_addr_expr_loc (loc, base0);
if (indirect_base1)
- base1 = build_fold_addr_expr (base1);
- return fold_build2 (code, type, base0, base1);
+ base1 = build_fold_addr_expr_loc (loc, base1);
+ return fold_build2_loc (loc, code, type, base0, base1);
}
}
&& tree_int_cst_compare (const2, cst) == tree_int_cst_sgn (const2))
{
fold_overflow_warning (warnmsg, WARN_STRICT_OVERFLOW_COMPARISON);
- return fold_build2 (code, type,
+ return fold_build2_loc (loc, code, type,
variable1,
- fold_build2 (TREE_CODE (arg1), TREE_TYPE (arg1),
+ fold_build2_loc (loc,
+ TREE_CODE (arg1), TREE_TYPE (arg1),
variable2, cst));
}
&& tree_int_cst_compare (const1, cst) == tree_int_cst_sgn (const1))
{
fold_overflow_warning (warnmsg, WARN_STRICT_OVERFLOW_COMPARISON);
- return fold_build2 (code, type,
- fold_build2 (TREE_CODE (arg0), TREE_TYPE (arg0),
+ return fold_build2_loc (loc, code, type,
+ fold_build2_loc (loc, TREE_CODE (arg0), TREE_TYPE (arg0),
variable1, cst),
variable2);
}
tree variable1 = TREE_OPERAND (arg0, 0);
enum tree_code cmp_code = code;
- gcc_assert (!integer_zerop (const1));
+ /* Handle unfolded multiplication by zero. */
+ if (integer_zerop (const1))
+ return fold_build2_loc (loc, cmp_code, type, const1, const2);
fold_overflow_warning (("assuming signed overflow does not occur when "
"eliminating multiplication in comparison "
if (tree_int_cst_sgn (const1) < 0)
cmp_code = swap_tree_comparison (cmp_code);
- return fold_build2 (cmp_code, type, variable1, const2);
+ return fold_build2_loc (loc, cmp_code, type, variable1, const2);
}
- tem = maybe_canonicalize_comparison (code, type, op0, op1);
+ tem = maybe_canonicalize_comparison (loc, code, type, op0, op1);
if (tem)
return tem;
/* Fold (double)float1 CMP (double)float2 into float1 CMP float2. */
if (TYPE_PRECISION (newtype) < TYPE_PRECISION (TREE_TYPE (arg0)))
- return fold_build2 (code, type, fold_convert (newtype, targ0),
- fold_convert (newtype, targ1));
+ return fold_build2_loc (loc, code, type,
+ 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 (code, type, TREE_OPERAND (arg1, 0),
+ return fold_build2_loc (loc, code, type, TREE_OPERAND (arg1, 0),
TREE_OPERAND (arg0, 0));
if (TREE_CODE (arg1) == REAL_CST)
/* (-a) CMP CST -> a swap(CMP) (-CST) */
if (TREE_CODE (arg0) == NEGATE_EXPR)
- return fold_build2 (swap_tree_comparison (code), type,
+ return fold_build2_loc (loc, swap_tree_comparison (code), type,
TREE_OPERAND (arg0, 0),
build_real (TREE_TYPE (arg1),
- REAL_VALUE_NEGATE (cst)));
+ 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))
- return fold_build2 (code, type, arg0,
+ return fold_build2_loc (loc, code, type, arg0,
build_real (TREE_TYPE (arg1), dconst0));
/* x != NaN is always true, other ops are always false. */
&& ! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1))))
{
tem = (code == NE_EXPR) ? integer_one_node : integer_zero_node;
- return omit_one_operand (type, tem, arg0);
+ return omit_one_operand_loc (loc, type, tem, arg0);
}
/* Fold comparisons against infinity. */
if (REAL_VALUE_ISINF (cst)
&& MODE_HAS_INFINITIES (TYPE_MODE (TREE_TYPE (arg1))))
{
- tem = fold_inf_compare (code, type, arg0, arg1);
+ tem = fold_inf_compare (loc, code, type, arg0, arg1);
if (tem != NULL_TREE)
return tem;
}
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == REAL_CST
&& 0 != (tem = const_binop (TREE_CODE (arg0) == PLUS_EXPR
? MINUS_EXPR : PLUS_EXPR,
- arg1, TREE_OPERAND (arg0, 1), 0))
+ arg1, TREE_OPERAND (arg0, 1)))
&& !TREE_OVERFLOW (tem))
- return fold_build2 (code, type, TREE_OPERAND (arg0, 0), tem);
+ return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), tem);
/* Likewise, we can simplify a comparison of a real constant with
a MINUS_EXPR whose first operand is also a real constant, i.e.
- (c1 - x) < c2 becomes x > c1-c2. Reordering is allowed on
+ (c1 - x) < c2 becomes x > c1-c2. Reordering is allowed on
floating-point types only if -fassociative-math is set. */
if (flag_associative_math
&& TREE_CODE (arg1) == REAL_CST
&& TREE_CODE (arg0) == MINUS_EXPR
&& TREE_CODE (TREE_OPERAND (arg0, 0)) == REAL_CST
&& 0 != (tem = const_binop (MINUS_EXPR, TREE_OPERAND (arg0, 0),
- arg1, 0))
+ arg1))
&& !TREE_OVERFLOW (tem))
- return fold_build2 (swap_tree_comparison (code), type,
+ return fold_build2_loc (loc, swap_tree_comparison (code), type,
TREE_OPERAND (arg0, 1), tem);
/* Fold comparisons against built-in math functions. */
if (fcode != END_BUILTINS)
{
- tem = fold_mathfn_compare (fcode, code, type, arg0, arg1);
+ tem = fold_mathfn_compare (loc, fcode, code, type, arg0, arg1);
if (tem != NULL_TREE)
return tem;
}
/* If we are widening one operand of an integer comparison,
see if the other operand is similarly being widened. Perhaps we
can do the comparison in the narrower type. */
- tem = fold_widened_comparison (code, type, arg0, arg1);
+ tem = fold_widened_comparison (loc, code, type, arg0, arg1);
if (tem)
return tem;
/* Or if we are changing signedness. */
- tem = fold_sign_changed_comparison (code, type, arg0, arg1);
+ tem = fold_sign_changed_comparison (loc, code, type, arg0, arg1);
if (tem)
return tem;
}
|| TREE_CODE (arg0) == MAX_EXPR)
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
{
- tem = optimize_minmax_comparison (code, type, op0, op1);
+ tem = optimize_minmax_comparison (loc, code, type, op0, op1);
if (tem)
return tem;
}
if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
|| ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
return constant_boolean_node (1, type);
- return fold_build2 (EQ_EXPR, type, arg0, arg1);
+ return fold_build2_loc (loc, EQ_EXPR, type, arg0, arg1);
case NE_EXPR:
/* For NE, we can only do this simplification if integer
was the same as ARG1. */
tree high_result
- = fold_build2 (code, type,
- eval_subst (arg0, cval1, maxval,
+ = fold_build2_loc (loc, code, type,
+ eval_subst (loc, arg0, cval1, maxval,
cval2, minval),
arg1);
tree equal_result
- = fold_build2 (code, type,
- eval_subst (arg0, cval1, maxval,
+ = fold_build2_loc (loc, code, type,
+ eval_subst (loc, arg0, cval1, maxval,
cval2, maxval),
arg1);
tree low_result
- = fold_build2 (code, type,
- eval_subst (arg0, cval1, minval,
+ = fold_build2_loc (loc, code, type,
+ eval_subst (loc, arg0, cval1, minval,
cval2, maxval),
arg1);
{
case 0:
/* Always false. */
- return omit_one_operand (type, integer_zero_node, arg0);
+ return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
case 1:
code = LT_EXPR;
break;
break;
case 7:
/* Always true. */
- return omit_one_operand (type, integer_one_node, arg0);
+ return omit_one_operand_loc (loc, type, integer_one_node, arg0);
}
if (save_p)
- return save_expr (build2 (code, type, cval1, cval2));
- return fold_build2 (code, type, cval1, cval2);
+ {
+ tem = save_expr (build2 (code, type, cval1, cval2));
+ SET_EXPR_LOCATION (tem, loc);
+ return tem;
+ }
+ return fold_build2_loc (loc, code, type, cval1, cval2);
}
}
}
&& !TREE_OVERFLOW (TREE_OPERAND (arg0, 1))
&& !TREE_OVERFLOW (arg1))
{
- tem = fold_div_compare (code, type, arg0, arg1);
+ tem = fold_div_compare (loc, code, type, arg0, arg1);
if (tem != NULL_TREE)
return tem;
}
&& TREE_CODE (arg1) == BIT_NOT_EXPR)
{
tree cmp_type = TREE_TYPE (TREE_OPERAND (arg0, 0));
- return fold_build2 (code, type,
- fold_convert (cmp_type, TREE_OPERAND (arg1, 0)),
+ return fold_build2_loc (loc, code, type,
+ fold_convert_loc (loc, cmp_type,
+ TREE_OPERAND (arg1, 0)),
TREE_OPERAND (arg0, 0));
}
&& TREE_CODE (arg1) == INTEGER_CST)
{
tree cmp_type = TREE_TYPE (TREE_OPERAND (arg0, 0));
- return fold_build2 (swap_tree_comparison (code), type,
+ return fold_build2_loc (loc, swap_tree_comparison (code), type,
TREE_OPERAND (arg0, 0),
- fold_build1 (BIT_NOT_EXPR, cmp_type,
- fold_convert (cmp_type, arg1)));
+ fold_build1_loc (loc, BIT_NOT_EXPR, cmp_type,
+ fold_convert_loc (loc, cmp_type, arg1)));
}
return NULL_TREE;
argument EXPR represents the expression "z" of type TYPE. */
static tree
-fold_mult_zconjz (tree type, tree expr)
+fold_mult_zconjz (location_t loc, tree type, tree expr)
{
tree itype = TREE_TYPE (type);
tree rpart, ipart, tem;
else
{
expr = save_expr (expr);
- rpart = fold_build1 (REALPART_EXPR, itype, expr);
- ipart = fold_build1 (IMAGPART_EXPR, itype, expr);
+ rpart = fold_build1_loc (loc, REALPART_EXPR, itype, expr);
+ ipart = fold_build1_loc (loc, IMAGPART_EXPR, itype, expr);
}
rpart = save_expr (rpart);
ipart = save_expr (ipart);
- tem = fold_build2 (PLUS_EXPR, itype,
- fold_build2 (MULT_EXPR, itype, rpart, rpart),
- fold_build2 (MULT_EXPR, itype, ipart, ipart));
- return fold_build2 (COMPLEX_EXPR, type, tem,
- fold_convert (itype, integer_zero_node));
+ tem = fold_build2_loc (loc, PLUS_EXPR, itype,
+ fold_build2_loc (loc, MULT_EXPR, itype, rpart, rpart),
+ fold_build2_loc (loc, MULT_EXPR, itype, ipart, ipart));
+ return fold_build2_loc (loc, COMPLEX_EXPR, type, tem,
+ build_zero_cst (itype));
}
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)
{
tree op0, op1;
unsigned HOST_WIDE_INT modulus;
enum tree_code inner_code;
-
+
op0 = TREE_OPERAND (expr, 0);
STRIP_NOPS (op0);
modulus = get_pointer_modulus_and_residue (op0, residue,
if (TREE_CODE (op1) == INTEGER_CST)
{
unsigned HOST_WIDE_INT align;
-
+
/* Compute the greatest power-of-2 divisor of op1. */
align = TREE_INT_CST_LOW (op1);
align &= -align;
}
}
- /* 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;
}
/* Fold a binary expression of code CODE and type TYPE with operands
- OP0 and OP1. Return the folded expression if folding is
- successful. Otherwise, return NULL_TREE. */
+ OP0 and OP1. LOC is the location of the resulting expression.
+ Return the folded expression if folding is successful. Otherwise,
+ return NULL_TREE. */
tree
-fold_binary (enum tree_code code, tree type, tree op0, tree op1)
+fold_binary_loc (location_t loc,
+ enum tree_code code, tree type, tree op0, tree op1)
{
enum tree_code_class kind = TREE_CODE_CLASS (code);
tree arg0, arg1, tem;
/* Make sure type and arg0 have the same saturating flag. */
gcc_assert (TYPE_SATURATING (type)
== TYPE_SATURATING (TREE_TYPE (arg0)));
- tem = const_binop (code, arg0, arg1, 0);
+ tem = const_binop (code, arg0, arg1);
}
else if (kind == tcc_comparison)
tem = fold_relational_const (code, type, arg0, arg1);
if (tem != NULL_TREE)
{
if (TREE_TYPE (tem) != type)
- tem = fold_convert (type, tem);
+ tem = fold_convert_loc (loc, type, tem);
return tem;
}
}
to ARG1 to reduce the number of tests below. */
if (commutative_tree_code (code)
&& tree_swap_operands_p (arg0, arg1, true))
- return fold_build2 (code, type, op1, op0);
+ return fold_build2_loc (loc, code, type, op1, op0);
/* ARG0 is the first operand of EXPR, and ARG1 is the second operand.
|| (TREE_CODE (arg0) == BIT_AND_EXPR
&& integer_onep (TREE_OPERAND (arg0, 1)))))))
{
- tem = fold_build2 (code == BIT_AND_EXPR ? TRUTH_AND_EXPR
+ tem = fold_build2_loc (loc, code == BIT_AND_EXPR ? TRUTH_AND_EXPR
: code == BIT_IOR_EXPR ? TRUTH_OR_EXPR
: TRUTH_XOR_EXPR,
boolean_type_node,
- fold_convert (boolean_type_node, arg0),
- fold_convert (boolean_type_node, arg1));
+ fold_convert_loc (loc, boolean_type_node, arg0),
+ fold_convert_loc (loc, boolean_type_node, arg1));
if (code == EQ_EXPR)
- tem = invert_truthvalue (tem);
+ tem = invert_truthvalue_loc (loc, tem);
- return fold_convert (type, tem);
+ return fold_convert_loc (loc, type, tem);
}
if (TREE_CODE_CLASS (code) == tcc_binary
|| TREE_CODE_CLASS (code) == tcc_comparison)
{
if (TREE_CODE (arg0) == COMPOUND_EXPR)
- return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
- fold_build2 (code, type,
- fold_convert (TREE_TYPE (op0),
- TREE_OPERAND (arg0, 1)),
- op1));
+ {
+ tem = fold_build2_loc (loc, code, type,
+ fold_convert_loc (loc, TREE_TYPE (op0),
+ TREE_OPERAND (arg0, 1)), op1);
+ return build2_loc (loc, COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
+ tem);
+ }
if (TREE_CODE (arg1) == COMPOUND_EXPR
&& reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
- return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
- fold_build2 (code, type, op0,
- fold_convert (TREE_TYPE (op1),
- TREE_OPERAND (arg1, 1))));
+ {
+ tem = fold_build2_loc (loc, code, type, op0,
+ fold_convert_loc (loc, TREE_TYPE (op1),
+ TREE_OPERAND (arg1, 1)));
+ return build2_loc (loc, COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
+ tem);
+ }
if (TREE_CODE (arg0) == COND_EXPR || COMPARISON_CLASS_P (arg0))
{
- tem = fold_binary_op_with_conditional_arg (code, type, op0, op1,
- arg0, arg1,
+ tem = fold_binary_op_with_conditional_arg (loc, code, type, op0, op1,
+ arg0, arg1,
/*cond_first_p=*/1);
if (tem != NULL_TREE)
return tem;
if (TREE_CODE (arg1) == COND_EXPR || COMPARISON_CLASS_P (arg1))
{
- tem = fold_binary_op_with_conditional_arg (code, type, op0, op1,
- arg1, arg0,
+ tem = fold_binary_op_with_conditional_arg (loc, code, type, op0, op1,
+ arg1, arg0,
/*cond_first_p=*/0);
if (tem != NULL_TREE)
return tem;
switch (code)
{
+ case MEM_REF:
+ /* MEM[&MEM[p, CST1], CST2] -> MEM[p, CST1 + CST2]. */
+ if (TREE_CODE (arg0) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (arg0, 0)) == MEM_REF)
+ {
+ tree iref = TREE_OPERAND (arg0, 0);
+ return fold_build2 (MEM_REF, type,
+ TREE_OPERAND (iref, 0),
+ int_const_binop (PLUS_EXPR, arg1,
+ TREE_OPERAND (iref, 1), 0));
+ }
+
+ /* MEM[&a.b, CST2] -> MEM[&a, offsetof (a, b) + CST2]. */
+ if (TREE_CODE (arg0) == ADDR_EXPR
+ && handled_component_p (TREE_OPERAND (arg0, 0)))
+ {
+ tree base;
+ HOST_WIDE_INT coffset;
+ base = get_addr_base_and_unit_offset (TREE_OPERAND (arg0, 0),
+ &coffset);
+ if (!base)
+ return NULL_TREE;
+ return fold_build2 (MEM_REF, type,
+ build_fold_addr_expr (base),
+ int_const_binop (PLUS_EXPR, arg1,
+ size_int (coffset), 0));
+ }
+
+ return NULL_TREE;
+
case POINTER_PLUS_EXPR:
/* 0 +p index -> (type)index */
if (integer_zerop (arg0))
- return non_lvalue (fold_convert (type, arg1));
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1));
/* PTR +p 0 -> PTR */
if (integer_zerop (arg1))
- return non_lvalue (fold_convert (type, arg0));
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
/* INT +p INT -> (PTR)(INT + INT). Stripping types allows for this. */
if (INTEGRAL_TYPE_P (TREE_TYPE (arg1))
&& INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
- return fold_convert (type, fold_build2 (PLUS_EXPR, sizetype,
- fold_convert (sizetype, arg1),
- fold_convert (sizetype, arg0)));
+ return fold_convert_loc (loc, type,
+ fold_build2_loc (loc, PLUS_EXPR, sizetype,
+ fold_convert_loc (loc, sizetype,
+ arg1),
+ 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 (POINTER_PLUS_EXPR, type,
- fold_convert (type, arg1),
- fold_convert (sizetype, 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)
{
tree inner;
- tree arg01 = fold_convert (sizetype, TREE_OPERAND (arg0, 1));
+ tree arg01 = fold_convert_loc (loc, sizetype, TREE_OPERAND (arg0, 1));
tree arg00 = TREE_OPERAND (arg0, 0);
- inner = fold_build2 (PLUS_EXPR, sizetype,
- arg01, fold_convert (sizetype, arg1));
- return fold_convert (type,
- fold_build2 (POINTER_PLUS_EXPR,
- TREE_TYPE (arg00), arg00, inner));
+ 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));
}
/* PTR_CST +p CST -> CST1 */
if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
- return fold_build2 (PLUS_EXPR, type, arg0, fold_convert (type, arg1));
+ return fold_build2_loc (loc, PLUS_EXPR, type, arg0,
+ fold_convert_loc (loc, type, arg1));
/* Try replacing &a[i1] +p c * i2 with &a[i1 + i2], if c is step
of the array. Loop optimizer sometimes produce this type of
expressions. */
if (TREE_CODE (arg0) == ADDR_EXPR)
{
- tem = try_move_mult_to_index (arg0, fold_convert (sizetype, arg1));
+ tem = try_move_mult_to_index (loc, arg0,
+ fold_convert_loc (loc, sizetype, arg1));
if (tem)
- return fold_convert (type, tem);
+ return fold_convert_loc (loc, type, tem);
}
return NULL_TREE;
case PLUS_EXPR:
/* A + (-B) -> A - B */
if (TREE_CODE (arg1) == NEGATE_EXPR)
- return fold_build2 (MINUS_EXPR, type,
- fold_convert (type, arg0),
- fold_convert (type, TREE_OPERAND (arg1, 0)));
+ return fold_build2_loc (loc, MINUS_EXPR, type,
+ fold_convert_loc (loc, type, arg0),
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg1, 0)));
/* (-A) + B -> B - A */
if (TREE_CODE (arg0) == NEGATE_EXPR
&& reorder_operands_p (TREE_OPERAND (arg0, 0), arg1))
- return fold_build2 (MINUS_EXPR, type,
- fold_convert (type, arg1),
- fold_convert (type, TREE_OPERAND (arg0, 0)));
+ return fold_build2_loc (loc, MINUS_EXPR, type,
+ fold_convert_loc (loc, type, arg1),
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg0, 0)));
if (INTEGRAL_TYPE_P (type))
{
/* Convert ~A + 1 to -A. */
if (TREE_CODE (arg0) == BIT_NOT_EXPR
&& integer_onep (arg1))
- return fold_build1 (NEGATE_EXPR, type,
- fold_convert (type, TREE_OPERAND (arg0, 0)));
+ return fold_build1_loc (loc, NEGATE_EXPR, type,
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg0, 0)));
/* ~X + X is -1. */
if (TREE_CODE (arg0) == BIT_NOT_EXPR
if (operand_equal_p (tem, arg1, 0))
{
t1 = build_int_cst_type (type, -1);
- return omit_one_operand (type, t1, arg1);
+ return omit_one_operand_loc (loc, type, t1, arg1);
}
}
if (operand_equal_p (arg0, tem, 0))
{
t1 = build_int_cst_type (type, -1);
- return omit_one_operand (type, t1, arg0);
+ return omit_one_operand_loc (loc, type, t1, arg0);
}
}
{
tree cst0 = TREE_OPERAND (TREE_OPERAND (arg1, 0), 1);
tree cst1 = TREE_OPERAND (arg1, 1);
- tree sum = fold_binary (PLUS_EXPR, TREE_TYPE (cst1), cst1, cst0);
+ tree sum = fold_binary_loc (loc, PLUS_EXPR, TREE_TYPE (cst1),
+ cst1, cst0);
if (sum && integer_zerop (sum))
- return fold_convert (type,
- fold_build2 (TRUNC_MOD_EXPR,
- TREE_TYPE (arg0), arg0, cst0));
+ return fold_convert_loc (loc, type,
+ fold_build2_loc (loc, TRUNC_MOD_EXPR,
+ TREE_TYPE (arg0), arg0,
+ cst0));
}
}
&& !TYPE_SATURATING (type)
&& (!FLOAT_TYPE_P (type) || flag_associative_math))
{
- tree tem = fold_plusminus_mult_expr (code, type, arg0, arg1);
+ tree tem = fold_plusminus_mult_expr (loc, code, type, arg0, arg1);
if (tem)
return tem;
}
if (! FLOAT_TYPE_P (type))
{
if (integer_zerop (arg1))
- return non_lvalue (fold_convert (type, arg0));
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
/* If we are adding two BIT_AND_EXPR's, both of which are and'ing
with a constant, and the two constants have no bits in common,
&& TREE_CODE (TREE_OPERAND (arg1, 1)) == INTEGER_CST
&& integer_zerop (const_binop (BIT_AND_EXPR,
TREE_OPERAND (arg0, 1),
- TREE_OPERAND (arg1, 1), 0)))
+ TREE_OPERAND (arg1, 1))))
{
code = BIT_IOR_EXPR;
goto bit_ior;
if (TREE_CODE (parg0) == MULT_EXPR
&& TREE_CODE (parg1) != MULT_EXPR)
- return fold_build2 (pcode, type,
- fold_build2 (PLUS_EXPR, type,
- fold_convert (type, parg0),
- fold_convert (type, marg)),
- fold_convert (type, parg1));
+ return fold_build2_loc (loc, pcode, type,
+ fold_build2_loc (loc, PLUS_EXPR, type,
+ fold_convert_loc (loc, type,
+ parg0),
+ fold_convert_loc (loc, type,
+ marg)),
+ fold_convert_loc (loc, type, parg1));
if (TREE_CODE (parg0) != MULT_EXPR
&& TREE_CODE (parg1) == MULT_EXPR)
- return fold_build2 (PLUS_EXPR, type,
- fold_convert (type, parg0),
- fold_build2 (pcode, type,
- fold_convert (type, marg),
- fold_convert (type,
- parg1)));
+ return
+ fold_build2_loc (loc, PLUS_EXPR, type,
+ fold_convert_loc (loc, type, parg0),
+ fold_build2_loc (loc, pcode, type,
+ fold_convert_loc (loc, type, marg),
+ fold_convert_loc (loc, type,
+ parg1)));
}
}
else
{
/* See if ARG1 is zero and X + ARG1 reduces to X. */
if (fold_real_zero_addition_p (TREE_TYPE (arg0), arg1, 0))
- return non_lvalue (fold_convert (type, arg0));
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
/* Likewise if the operands are reversed. */
if (fold_real_zero_addition_p (TREE_TYPE (arg1), arg0, 0))
- return non_lvalue (fold_convert (type, arg1));
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1));
/* Convert X + -C into X - C. */
if (TREE_CODE (arg1) == REAL_CST
{
tem = fold_negate_const (arg1, type);
if (!TREE_OVERFLOW (arg1) || !flag_trapping_math)
- return fold_build2 (MINUS_EXPR, type,
- fold_convert (type, arg0),
- fold_convert (type, tem));
+ return fold_build2_loc (loc, MINUS_EXPR, type,
+ fold_convert_loc (loc, type, arg0),
+ fold_convert_loc (loc, type, tem));
}
/* Fold __complex__ ( x, 0 ) + __complex__ ( 0, y )
&& COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg0)))
{
tree rtype = TREE_TYPE (TREE_TYPE (arg0));
- tree arg0r = fold_unary (REALPART_EXPR, rtype, arg0);
- tree arg0i = fold_unary (IMAGPART_EXPR, rtype, arg0);
+ tree arg0r = fold_unary_loc (loc, REALPART_EXPR, rtype, arg0);
+ tree arg0i = fold_unary_loc (loc, IMAGPART_EXPR, rtype, arg0);
bool arg0rz = false, arg0iz = false;
if ((arg0r && (arg0rz = real_zerop (arg0r)))
|| (arg0i && (arg0iz = real_zerop (arg0i))))
{
- tree arg1r = fold_unary (REALPART_EXPR, rtype, arg1);
- tree arg1i = fold_unary (IMAGPART_EXPR, rtype, arg1);
+ tree arg1r = fold_unary_loc (loc, REALPART_EXPR, rtype, arg1);
+ tree arg1i = fold_unary_loc (loc, IMAGPART_EXPR, rtype, arg1);
if (arg0rz && arg1i && real_zerop (arg1i))
{
tree rp = arg1r ? arg1r
: build1 (REALPART_EXPR, rtype, arg1);
tree ip = arg0i ? arg0i
: build1 (IMAGPART_EXPR, rtype, arg0);
- return fold_build2 (COMPLEX_EXPR, type, rp, ip);
+ return fold_build2_loc (loc, COMPLEX_EXPR, type, rp, ip);
}
else if (arg0iz && arg1r && real_zerop (arg1r))
{
: build1 (REALPART_EXPR, rtype, arg0);
tree ip = arg1i ? arg1i
: build1 (IMAGPART_EXPR, rtype, arg1);
- return fold_build2 (COMPLEX_EXPR, type, rp, ip);
+ return fold_build2_loc (loc, COMPLEX_EXPR, type, rp, ip);
}
}
}
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)))
+ && (tem = distribute_real_division (loc, code, type, arg0, arg1)))
return tem;
/* Convert x+x into x*2.0. */
if (operand_equal_p (arg0, arg1, 0)
&& SCALAR_FLOAT_TYPE_P (type))
- return fold_build2 (MULT_EXPR, type, arg0,
+ return fold_build2_loc (loc, MULT_EXPR, type, arg0,
build_real (type, dconst2));
- /* Convert a + (b*c + d*e) into (a + b*c) + d*e.
+ /* Convert a + (b*c + d*e) into (a + b*c) + d*e.
We associate floats only if the user has specified
-fassociative-math. */
if (flag_associative_math
&& TREE_CODE (tree10) == MULT_EXPR)
{
tree tree0;
- tree0 = fold_build2 (PLUS_EXPR, type, arg0, tree10);
- return fold_build2 (PLUS_EXPR, type, tree0, tree11);
+ tree0 = fold_build2_loc (loc, PLUS_EXPR, type, arg0, tree10);
+ return fold_build2_loc (loc, PLUS_EXPR, type, tree0, tree11);
}
}
- /* Convert (b*c + d*e) + a into b*c + (d*e +a).
+ /* Convert (b*c + d*e) + a into b*c + (d*e +a).
We associate floats only if the user has specified
-fassociative-math. */
if (flag_associative_math
&& TREE_CODE (tree00) == MULT_EXPR)
{
tree tree0;
- tree0 = fold_build2 (PLUS_EXPR, type, tree01, arg1);
- return fold_build2 (PLUS_EXPR, type, tree00, tree0);
+ tree0 = fold_build2_loc (loc, PLUS_EXPR, type, tree01, arg1);
+ return fold_build2_loc (loc, PLUS_EXPR, type, tree00, tree0);
}
}
}
&& TREE_INT_CST_HIGH (tree11) == 0
&& ((TREE_INT_CST_LOW (tree01) + TREE_INT_CST_LOW (tree11))
== TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))))
- return build2 (LROTATE_EXPR, type, TREE_OPERAND (arg0, 0),
- code0 == LSHIFT_EXPR ? tree01 : tree11);
+ {
+ tem = build2_loc (loc, LROTATE_EXPR,
+ TREE_TYPE (TREE_OPERAND (arg0, 0)),
+ TREE_OPERAND (arg0, 0),
+ code0 == LSHIFT_EXPR ? tree01 : tree11);
+ return fold_convert_loc (loc, type, tem);
+ }
else if (code11 == MINUS_EXPR)
{
tree tree110, tree111;
(TREE_TYPE (TREE_OPERAND
(arg0, 0))))
&& operand_equal_p (tree01, tree111, 0))
- return build2 ((code0 == LSHIFT_EXPR
- ? LROTATE_EXPR
- : RROTATE_EXPR),
- type, TREE_OPERAND (arg0, 0), tree01);
+ return
+ fold_convert_loc (loc, type,
+ build2 ((code0 == LSHIFT_EXPR
+ ? LROTATE_EXPR
+ : RROTATE_EXPR),
+ TREE_TYPE (TREE_OPERAND (arg0, 0)),
+ TREE_OPERAND (arg0, 0), tree01));
}
else if (code01 == MINUS_EXPR)
{
(TREE_TYPE (TREE_OPERAND
(arg0, 0))))
&& operand_equal_p (tree11, tree011, 0))
- return build2 ((code0 != LSHIFT_EXPR
- ? LROTATE_EXPR
- : RROTATE_EXPR),
- type, TREE_OPERAND (arg0, 0), tree11);
+ return fold_convert_loc
+ (loc, type,
+ build2 ((code0 != LSHIFT_EXPR
+ ? LROTATE_EXPR
+ : RROTATE_EXPR),
+ TREE_TYPE (TREE_OPERAND (arg0, 0)),
+ TREE_OPERAND (arg0, 0), tree11));
}
}
}
var1 = split_tree (arg1, code, &con1, &lit1, &minus_lit1,
code == MINUS_EXPR);
- /* With undefined overflow we can only associate constants
- with one variable. */
- if (((POINTER_TYPE_P (type) && POINTER_TYPE_OVERFLOW_UNDEFINED)
- || (INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_WRAPS (type)))
- && var0 && var1)
+ /* Recombine MINUS_EXPR operands by using PLUS_EXPR. */
+ if (code == MINUS_EXPR)
+ code = PLUS_EXPR;
+
+ /* With undefined overflow we can only associate constants with one
+ variable, and constants whose association doesn't overflow. */
+ if ((POINTER_TYPE_P (type) && POINTER_TYPE_OVERFLOW_UNDEFINED)
+ || (INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_WRAPS (type)))
{
- tree tmp0 = var0;
- tree tmp1 = var1;
-
- if (TREE_CODE (tmp0) == NEGATE_EXPR)
- tmp0 = TREE_OPERAND (tmp0, 0);
- if (TREE_CODE (tmp1) == NEGATE_EXPR)
- tmp1 = TREE_OPERAND (tmp1, 0);
- /* The only case we can still associate with two variables
- is if they are the same, modulo negation. */
- if (!operand_equal_p (tmp0, tmp1, 0))
- ok = false;
+ if (var0 && var1)
+ {
+ tree tmp0 = var0;
+ tree tmp1 = var1;
+
+ if (TREE_CODE (tmp0) == NEGATE_EXPR)
+ tmp0 = TREE_OPERAND (tmp0, 0);
+ if (TREE_CODE (tmp1) == NEGATE_EXPR)
+ tmp1 = TREE_OPERAND (tmp1, 0);
+ /* The only case we can still associate with two variables
+ is if they are the same, modulo negation. */
+ if (!operand_equal_p (tmp0, tmp1, 0))
+ ok = false;
+ }
+
+ if (ok && lit0 && lit1)
+ {
+ tree tmp0 = fold_convert (type, lit0);
+ tree tmp1 = fold_convert (type, lit1);
+
+ if (!TREE_OVERFLOW (tmp0) && !TREE_OVERFLOW (tmp1)
+ && TREE_OVERFLOW (fold_build2 (code, type, tmp0, tmp1)))
+ ok = false;
+ }
}
/* Only do something if we found more than two objects. Otherwise,
+ (lit0 != 0) + (lit1 != 0)
+ (minus_lit0 != 0) + (minus_lit1 != 0))))
{
- /* Recombine MINUS_EXPR operands by using PLUS_EXPR. */
- if (code == MINUS_EXPR)
- code = PLUS_EXPR;
-
- var0 = associate_trees (var0, var1, code, type);
- con0 = associate_trees (con0, con1, code, type);
- lit0 = associate_trees (lit0, lit1, code, type);
- minus_lit0 = associate_trees (minus_lit0, minus_lit1, code, type);
+ var0 = associate_trees (loc, var0, var1, code, type);
+ con0 = associate_trees (loc, con0, con1, code, type);
+ lit0 = associate_trees (loc, lit0, lit1, code, type);
+ minus_lit0 = associate_trees (loc, minus_lit0, minus_lit1, code, type);
/* Preserve the MINUS_EXPR if the negative part of the literal is
greater than the positive part. Otherwise, the multiplicative
&& TREE_CODE (minus_lit0) == INTEGER_CST
&& tree_int_cst_lt (lit0, minus_lit0))
{
- minus_lit0 = associate_trees (minus_lit0, lit0,
+ minus_lit0 = associate_trees (loc, minus_lit0, lit0,
MINUS_EXPR, type);
lit0 = 0;
}
else
{
- lit0 = associate_trees (lit0, minus_lit0,
+ lit0 = associate_trees (loc, lit0, minus_lit0,
MINUS_EXPR, type);
minus_lit0 = 0;
}
if (minus_lit0)
{
if (con0 == 0)
- return fold_convert (type,
- associate_trees (var0, minus_lit0,
- MINUS_EXPR, type));
+ return
+ fold_convert_loc (loc, type,
+ associate_trees (loc, var0, minus_lit0,
+ MINUS_EXPR, type));
else
{
- con0 = associate_trees (con0, minus_lit0,
+ con0 = associate_trees (loc, con0, minus_lit0,
MINUS_EXPR, type);
- return fold_convert (type,
- associate_trees (var0, con0,
- PLUS_EXPR, type));
+ return
+ fold_convert_loc (loc, type,
+ associate_trees (loc, var0, con0,
+ PLUS_EXPR, type));
}
}
- con0 = associate_trees (con0, lit0, code, type);
- return fold_convert (type, associate_trees (var0, con0,
- code, type));
+ con0 = associate_trees (loc, con0, lit0, code, type);
+ return
+ fold_convert_loc (loc, type, associate_trees (loc, var0, con0,
+ code, type));
}
}
if (TREE_CODE (arg0) == POINTER_PLUS_EXPR
&& TREE_CODE (arg1) == POINTER_PLUS_EXPR)
{
- tree arg00 = fold_convert (type, TREE_OPERAND (arg0, 0));
- tree arg01 = fold_convert (type, TREE_OPERAND (arg0, 1));
- tree arg10 = fold_convert (type, TREE_OPERAND (arg1, 0));
- tree arg11 = fold_convert (type, TREE_OPERAND (arg1, 1));
- return fold_build2 (PLUS_EXPR, type,
- fold_build2 (MINUS_EXPR, type, arg00, arg10),
- fold_build2 (MINUS_EXPR, type, arg01, arg11));
+ tree arg00 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
+ tree arg01 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
+ tree arg10 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 0));
+ tree arg11 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 1));
+ return fold_build2_loc (loc, PLUS_EXPR, type,
+ fold_build2_loc (loc, MINUS_EXPR, type,
+ arg00, arg10),
+ fold_build2_loc (loc, MINUS_EXPR, type,
+ arg01, arg11));
}
/* (PTR0 p+ A) - PTR1 -> (PTR0 - PTR1) + A, assuming PTR0 - PTR1 simplifies. */
else if (TREE_CODE (arg0) == POINTER_PLUS_EXPR)
{
- tree arg00 = fold_convert (type, TREE_OPERAND (arg0, 0));
- tree arg01 = fold_convert (type, TREE_OPERAND (arg0, 1));
- tree tmp = fold_binary (MINUS_EXPR, type, arg00, fold_convert (type, arg1));
+ tree arg00 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
+ tree arg01 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
+ tree tmp = fold_binary_loc (loc, MINUS_EXPR, type, arg00,
+ fold_convert_loc (loc, type, arg1));
if (tmp)
- return fold_build2 (PLUS_EXPR, type, tmp, arg01);
+ return fold_build2_loc (loc, PLUS_EXPR, type, tmp, arg01);
}
}
/* A - (-B) -> A + B */
if (TREE_CODE (arg1) == NEGATE_EXPR)
- return fold_build2 (PLUS_EXPR, type, op0,
- fold_convert (type, TREE_OPERAND (arg1, 0)));
+ return fold_build2_loc (loc, PLUS_EXPR, type, op0,
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg1, 0)));
/* (-A) - B -> (-B) - A where B is easily negated and we can swap. */
if (TREE_CODE (arg0) == NEGATE_EXPR
&& (FLOAT_TYPE_P (type)
|| INTEGRAL_TYPE_P (type))
&& negate_expr_p (arg1)
&& reorder_operands_p (arg0, arg1))
- return fold_build2 (MINUS_EXPR, type,
- fold_convert (type, negate_expr (arg1)),
- fold_convert (type, TREE_OPERAND (arg0, 0)));
+ return fold_build2_loc (loc, MINUS_EXPR, type,
+ fold_convert_loc (loc, type,
+ negate_expr (arg1)),
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg0, 0)));
/* Convert -A - 1 to ~A. */
if (INTEGRAL_TYPE_P (type)
&& TREE_CODE (arg0) == NEGATE_EXPR
&& integer_onep (arg1)
&& !TYPE_OVERFLOW_TRAPS (type))
- return fold_build1 (BIT_NOT_EXPR, type,
- fold_convert (type, TREE_OPERAND (arg0, 0)));
+ return fold_build1_loc (loc, BIT_NOT_EXPR, type,
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg0, 0)));
/* Convert -1 - A to ~A. */
if (INTEGRAL_TYPE_P (type)
&& integer_all_onesp (arg0))
- return fold_build1 (BIT_NOT_EXPR, type, op1);
+ return fold_build1_loc (loc, BIT_NOT_EXPR, type, op1);
/* X - (X / CST) * CST is X % CST. */
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 (type,
- fold_build2 (TRUNC_MOD_EXPR, TREE_TYPE (arg0),
- arg0, TREE_OPERAND (arg1, 1)));
+ 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))
{
if (integer_zerop (arg0))
- return negate_expr (fold_convert (type, arg1));
+ return negate_expr (fold_convert_loc (loc, type, arg1));
if (integer_zerop (arg1))
- return non_lvalue (fold_convert (type, arg0));
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
/* Fold A - (A & B) into ~B & A. */
if (!TREE_SIDE_EFFECTS (arg0)
{
if (operand_equal_p (arg0, TREE_OPERAND (arg1, 1), 0))
{
- tree arg10 = fold_convert (type, TREE_OPERAND (arg1, 0));
- return fold_build2 (BIT_AND_EXPR, type,
- fold_build1 (BIT_NOT_EXPR, type, arg10),
- fold_convert (type, arg0));
+ tree arg10 = fold_convert_loc (loc, type,
+ TREE_OPERAND (arg1, 0));
+ return fold_build2_loc (loc, BIT_AND_EXPR, type,
+ fold_build1_loc (loc, BIT_NOT_EXPR,
+ type, arg10),
+ fold_convert_loc (loc, type, arg0));
}
if (operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
{
- tree arg11 = fold_convert (type, TREE_OPERAND (arg1, 1));
- return fold_build2 (BIT_AND_EXPR, type,
- fold_build1 (BIT_NOT_EXPR, type, arg11),
- fold_convert (type, arg0));
+ tree arg11 = fold_convert_loc (loc,
+ type, TREE_OPERAND (arg1, 1));
+ return fold_build2_loc (loc, BIT_AND_EXPR, type,
+ fold_build1_loc (loc, BIT_NOT_EXPR,
+ type, arg11),
+ fold_convert_loc (loc, type, arg0));
}
}
{
tree mask0 = TREE_OPERAND (arg0, 1);
tree mask1 = TREE_OPERAND (arg1, 1);
- tree tem = fold_build1 (BIT_NOT_EXPR, type, mask0);
+ tree tem = fold_build1_loc (loc, BIT_NOT_EXPR, type, mask0);
if (operand_equal_p (tem, mask1, 0))
{
- tem = fold_build2 (BIT_XOR_EXPR, type,
+ tem = fold_build2_loc (loc, BIT_XOR_EXPR, type,
TREE_OPERAND (arg0, 0), mask1);
- return fold_build2 (MINUS_EXPR, type, tem, mask1);
+ return fold_build2_loc (loc, MINUS_EXPR, type, tem, mask1);
}
}
}
/* See if ARG1 is zero and X - ARG1 reduces to X. */
else if (fold_real_zero_addition_p (TREE_TYPE (arg0), arg1, 1))
- return non_lvalue (fold_convert (type, arg0));
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
/* (ARG0 - ARG1) is the same as (-ARG1 + ARG0). So check whether
ARG0 is zero and X + ARG0 reduces to X, since that would mean
(-ARG1 + ARG0) reduces to -ARG1. */
else if (fold_real_zero_addition_p (TREE_TYPE (arg1), arg0, 0))
- return negate_expr (fold_convert (type, arg1));
+ return negate_expr (fold_convert_loc (loc, type, arg1));
/* Fold __complex__ ( x, 0 ) - __complex__ ( 0, y ) to
__complex__ ( x, -y ). This is not the same for SNaNs or if
&& COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg0)))
{
tree rtype = TREE_TYPE (TREE_TYPE (arg0));
- tree arg0r = fold_unary (REALPART_EXPR, rtype, arg0);
- tree arg0i = fold_unary (IMAGPART_EXPR, rtype, arg0);
+ tree arg0r = fold_unary_loc (loc, REALPART_EXPR, rtype, arg0);
+ tree arg0i = fold_unary_loc (loc, IMAGPART_EXPR, rtype, arg0);
bool arg0rz = false, arg0iz = false;
if ((arg0r && (arg0rz = real_zerop (arg0r)))
|| (arg0i && (arg0iz = real_zerop (arg0i))))
{
- tree arg1r = fold_unary (REALPART_EXPR, rtype, arg1);
- tree arg1i = fold_unary (IMAGPART_EXPR, rtype, arg1);
+ tree arg1r = fold_unary_loc (loc, REALPART_EXPR, rtype, arg1);
+ tree arg1i = fold_unary_loc (loc, IMAGPART_EXPR, rtype, arg1);
if (arg0rz && arg1i && real_zerop (arg1i))
{
- tree rp = fold_build1 (NEGATE_EXPR, rtype,
+ tree rp = fold_build1_loc (loc, NEGATE_EXPR, rtype,
arg1r ? arg1r
: build1 (REALPART_EXPR, rtype, arg1));
tree ip = arg0i ? arg0i
: build1 (IMAGPART_EXPR, rtype, arg0);
- return fold_build2 (COMPLEX_EXPR, type, rp, ip);
+ return fold_build2_loc (loc, COMPLEX_EXPR, type, rp, ip);
}
else if (arg0iz && arg1r && real_zerop (arg1r))
{
tree rp = arg0r ? arg0r
: build1 (REALPART_EXPR, rtype, arg0);
- tree ip = fold_build1 (NEGATE_EXPR, rtype,
+ tree ip = fold_build1_loc (loc, NEGATE_EXPR, rtype,
arg1i ? arg1i
: build1 (IMAGPART_EXPR, rtype, arg1));
- return fold_build2 (COMPLEX_EXPR, type, rp, ip);
+ return fold_build2_loc (loc, COMPLEX_EXPR, type, rp, ip);
}
}
}
if ((!FLOAT_TYPE_P (type) || !HONOR_NANS (TYPE_MODE (type)))
&& operand_equal_p (arg0, arg1, 0))
- return fold_convert (type, integer_zero_node);
+ return build_zero_cst (type);
/* A - B -> A + (-B) if B is easily negatable. */
if (negate_expr_p (arg1)
&& (TREE_CODE (arg1) != REAL_CST
|| REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg1))))
|| INTEGRAL_TYPE_P (type)))
- return fold_build2 (PLUS_EXPR, type,
- fold_convert (type, arg0),
- fold_convert (type, negate_expr (arg1)));
+ return fold_build2_loc (loc, PLUS_EXPR, type,
+ fold_convert_loc (loc, type, arg0),
+ fold_convert_loc (loc, type,
+ negate_expr (arg1)));
/* Try folding difference of addresses. */
{
if (operand_equal_p (TREE_OPERAND (aref0, 0),
TREE_OPERAND (aref1, 0), 0))
{
- tree op0 = fold_convert (type, TREE_OPERAND (aref0, 1));
- tree op1 = fold_convert (type, TREE_OPERAND (aref1, 1));
+ tree op0 = fold_convert_loc (loc, type, TREE_OPERAND (aref0, 1));
+ tree op1 = fold_convert_loc (loc, type, TREE_OPERAND (aref1, 1));
tree esz = array_ref_element_size (aref0);
tree diff = build2 (MINUS_EXPR, type, op0, op1);
- return fold_build2 (MULT_EXPR, type, diff,
- fold_convert (type, esz));
-
+ return fold_build2_loc (loc, MULT_EXPR, type, diff,
+ fold_convert_loc (loc, type, esz));
+
}
}
&& 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)))
+ && (tem = distribute_real_division (loc, code, type, arg0, arg1)))
return tem;
/* Handle (A1 * C1) - (A2 * C2) with A1, A2 or C1, C2 being the
&& !TYPE_SATURATING (type)
&& (!FLOAT_TYPE_P (type) || flag_associative_math))
{
- tree tem = fold_plusminus_mult_expr (code, type, arg0, arg1);
+ tree tem = fold_plusminus_mult_expr (loc, code, type, arg0, arg1);
if (tem)
return tem;
}
case MULT_EXPR:
/* (-A) * (-B) -> A * B */
if (TREE_CODE (arg0) == NEGATE_EXPR && negate_expr_p (arg1))
- return fold_build2 (MULT_EXPR, type,
- fold_convert (type, TREE_OPERAND (arg0, 0)),
- fold_convert (type, negate_expr (arg1)));
+ return fold_build2_loc (loc, MULT_EXPR, type,
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg0, 0)),
+ fold_convert_loc (loc, type,
+ negate_expr (arg1)));
if (TREE_CODE (arg1) == NEGATE_EXPR && negate_expr_p (arg0))
- return fold_build2 (MULT_EXPR, type,
- fold_convert (type, negate_expr (arg0)),
- fold_convert (type, TREE_OPERAND (arg1, 0)));
+ return fold_build2_loc (loc, MULT_EXPR, type,
+ fold_convert_loc (loc, type,
+ negate_expr (arg0)),
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg1, 0)));
if (! FLOAT_TYPE_P (type))
{
if (integer_zerop (arg1))
- return omit_one_operand (type, arg1, arg0);
+ return omit_one_operand_loc (loc, type, arg1, arg0);
if (integer_onep (arg1))
- return non_lvalue (fold_convert (type, arg0));
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
/* Transform x * -1 into -x. Make sure to do the negation
on the original operand with conversions not stripped
because we can only strip non-sign-changing conversions. */
if (integer_all_onesp (arg1))
- return fold_convert (type, negate_expr (op0));
+ return fold_convert_loc (loc, type, negate_expr (op0));
/* Transform x * -C into -x * C if x is easily negatable. */
if (TREE_CODE (arg1) == INTEGER_CST
&& tree_int_cst_sgn (arg1) == -1
&& negate_expr_p (arg0)
&& (tem = negate_expr (arg1)) != arg1
&& !TREE_OVERFLOW (tem))
- return fold_build2 (MULT_EXPR, type,
- fold_convert (type, negate_expr (arg0)), tem);
+ return fold_build2_loc (loc, MULT_EXPR, type,
+ fold_convert_loc (loc, type,
+ negate_expr (arg0)),
+ tem);
/* (a * (1 << b)) is (a << b) */
if (TREE_CODE (arg1) == LSHIFT_EXPR
&& integer_onep (TREE_OPERAND (arg1, 0)))
- return fold_build2 (LSHIFT_EXPR, type, op0,
+ return fold_build2_loc (loc, LSHIFT_EXPR, type, op0,
TREE_OPERAND (arg1, 1));
if (TREE_CODE (arg0) == LSHIFT_EXPR
&& integer_onep (TREE_OPERAND (arg0, 0)))
- return fold_build2 (LSHIFT_EXPR, type, op1,
+ return fold_build2_loc (loc, LSHIFT_EXPR, type, op1,
TREE_OPERAND (arg0, 1));
/* (A + A) * C -> A * 2 * C */
&& TREE_CODE (arg1) == INTEGER_CST
&& operand_equal_p (TREE_OPERAND (arg0, 0),
TREE_OPERAND (arg0, 1), 0))
- return fold_build2 (MULT_EXPR, type,
- omit_one_operand (type, TREE_OPERAND (arg0, 0),
+ return fold_build2_loc (loc, MULT_EXPR, type,
+ omit_one_operand_loc (loc, type,
+ TREE_OPERAND (arg0, 0),
TREE_OPERAND (arg0, 1)),
- fold_build2 (MULT_EXPR, type,
+ fold_build2_loc (loc, MULT_EXPR, type,
build_int_cst (type, 2) , arg1));
strict_overflow_p = false;
"occur when simplifying "
"multiplication"),
WARN_STRICT_OVERFLOW_MISC);
- return fold_convert (type, tem);
+ return fold_convert_loc (loc, type, tem);
}
/* Optimize z * conj(z) for integer complex numbers. */
if (TREE_CODE (arg0) == CONJ_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
- return fold_mult_zconjz (type, arg1);
+ return fold_mult_zconjz (loc, type, arg1);
if (TREE_CODE (arg1) == CONJ_EXPR
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
- return fold_mult_zconjz (type, arg0);
+ return fold_mult_zconjz (loc, type, arg0);
}
else
{
if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0)))
&& !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0)))
&& real_zerop (arg1))
- return omit_one_operand (type, arg1, arg0);
+ return omit_one_operand_loc (loc, type, arg1, arg0);
/* 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));
+ return non_lvalue_loc (loc, fold_convert_loc (loc, 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));
+ return fold_convert_loc (loc, type, negate_expr (arg0));
/* Convert (C1/X)*C2 into (C1*C2)/X. This transformation may change
the result for floating point types due to rounding so it is applied
&& TREE_CODE (TREE_OPERAND (arg0, 0)) == REAL_CST)
{
tree tem = const_binop (MULT_EXPR, TREE_OPERAND (arg0, 0),
- arg1, 0);
+ arg1);
if (tem)
- return fold_build2 (RDIV_EXPR, type, tem,
+ return fold_build2_loc (loc, RDIV_EXPR, type, tem,
TREE_OPERAND (arg0, 1));
}
tree tem = fold_strip_sign_ops (arg0);
if (tem != NULL_TREE)
{
- tem = fold_convert (type, tem);
- return fold_build2 (MULT_EXPR, type, tem, tem);
+ tem = fold_convert_loc (loc, type, tem);
+ return fold_build2_loc (loc, MULT_EXPR, type, tem, tem);
}
}
{
tree rtype = TREE_TYPE (TREE_TYPE (arg0));
if (real_onep (TREE_IMAGPART (arg1)))
- return fold_build2 (COMPLEX_EXPR, type,
- negate_expr (fold_build1 (IMAGPART_EXPR,
- rtype, arg0)),
- fold_build1 (REALPART_EXPR, rtype, arg0));
+ return
+ fold_build2_loc (loc, COMPLEX_EXPR, type,
+ negate_expr (fold_build1_loc (loc, IMAGPART_EXPR,
+ rtype, arg0)),
+ fold_build1_loc (loc, REALPART_EXPR, rtype, arg0));
else if (real_minus_onep (TREE_IMAGPART (arg1)))
- return fold_build2 (COMPLEX_EXPR, type,
- fold_build1 (IMAGPART_EXPR, rtype, arg0),
- negate_expr (fold_build1 (REALPART_EXPR,
- rtype, arg0)));
+ return
+ fold_build2_loc (loc, COMPLEX_EXPR, type,
+ fold_build1_loc (loc, IMAGPART_EXPR, rtype, arg0),
+ negate_expr (fold_build1_loc (loc, REALPART_EXPR,
+ rtype, arg0)));
}
/* Optimize z * conj(z) for floating point complex numbers.
if (flag_unsafe_math_optimizations
&& TREE_CODE (arg0) == CONJ_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
- return fold_mult_zconjz (type, arg1);
+ return fold_mult_zconjz (loc, type, arg1);
if (flag_unsafe_math_optimizations
&& TREE_CODE (arg1) == CONJ_EXPR
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
- return fold_mult_zconjz (type, arg0);
+ return fold_mult_zconjz (loc, type, arg0);
if (flag_unsafe_math_optimizations)
{
/* Optimize root(x)*root(y) as root(x*y). */
rootfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
- arg = fold_build2 (MULT_EXPR, type, arg00, arg10);
- return build_call_expr (rootfn, 1, arg);
+ arg = fold_build2_loc (loc, MULT_EXPR, type, arg00, arg10);
+ return build_call_expr_loc (loc, rootfn, 1, arg);
}
/* Optimize expN(x)*expN(y) as expN(x+y). */
if (fcode0 == fcode1 && BUILTIN_EXPONENT_P (fcode0))
{
tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
- tree arg = fold_build2 (PLUS_EXPR, type,
+ tree arg = fold_build2_loc (loc, PLUS_EXPR, type,
CALL_EXPR_ARG (arg0, 0),
CALL_EXPR_ARG (arg1, 0));
- return build_call_expr (expfn, 1, arg);
+ return build_call_expr_loc (loc, expfn, 1, arg);
}
/* Optimizations of pow(...)*pow(...). */
if (operand_equal_p (arg01, arg11, 0))
{
tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
- tree arg = fold_build2 (MULT_EXPR, type, arg00, arg10);
- return build_call_expr (powfn, 2, arg, arg01);
+ tree arg = fold_build2_loc (loc, MULT_EXPR, type,
+ arg00, arg10);
+ return build_call_expr_loc (loc, powfn, 2, arg, arg01);
}
/* Optimize pow(x,y)*pow(x,z) as pow(x,y+z). */
if (operand_equal_p (arg00, arg10, 0))
{
tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
- tree arg = fold_build2 (PLUS_EXPR, type, arg01, arg11);
- return build_call_expr (powfn, 2, arg00, arg);
+ tree arg = fold_build2_loc (loc, PLUS_EXPR, type,
+ arg01, arg11);
+ return build_call_expr_loc (loc, powfn, 2, arg00, arg);
}
}
tree sinfn = mathfn_built_in (type, BUILT_IN_SIN);
if (sinfn != NULL_TREE)
- return build_call_expr (sinfn, 1, CALL_EXPR_ARG (arg0, 0));
+ return build_call_expr_loc (loc, sinfn, 1,
+ CALL_EXPR_ARG (arg0, 0));
}
/* Optimize x*pow(x,c) as pow(x,c+1). */
c = TREE_REAL_CST (arg11);
real_arithmetic (&c, PLUS_EXPR, &c, &dconst1);
arg = build_real (type, c);
- return build_call_expr (powfn, 2, arg0, arg);
+ return build_call_expr_loc (loc, powfn, 2, arg0, arg);
}
}
c = TREE_REAL_CST (arg01);
real_arithmetic (&c, PLUS_EXPR, &c, &dconst1);
arg = build_real (type, c);
- return build_call_expr (powfn, 2, arg1, arg);
+ return build_call_expr_loc (loc, powfn, 2, arg1, arg);
}
}
if (powfn)
{
tree arg = build_real (type, dconst2);
- return build_call_expr (powfn, 2, arg0, arg);
+ return build_call_expr_loc (loc, powfn, 2, arg0, arg);
}
}
}
case BIT_IOR_EXPR:
bit_ior:
if (integer_all_onesp (arg1))
- return omit_one_operand (type, arg1, arg0);
+ return omit_one_operand_loc (loc, type, arg1, arg0);
if (integer_zerop (arg1))
- return non_lvalue (fold_convert (type, arg0));
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
if (operand_equal_p (arg0, arg1, 0))
- return non_lvalue (fold_convert (type, arg0));
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
/* ~X | X is -1. */
if (TREE_CODE (arg0) == BIT_NOT_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
{
- t1 = fold_convert (type, integer_zero_node);
- t1 = fold_unary (BIT_NOT_EXPR, type, t1);
- return omit_one_operand (type, t1, arg1);
+ t1 = build_zero_cst (type);
+ t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
+ return omit_one_operand_loc (loc, type, t1, arg1);
}
/* X | ~X is -1. */
if (TREE_CODE (arg1) == BIT_NOT_EXPR
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
{
- t1 = fold_convert (type, integer_zero_node);
- t1 = fold_unary (BIT_NOT_EXPR, type, t1);
- return omit_one_operand (type, t1, arg0);
+ t1 = build_zero_cst (type);
+ t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
+ return omit_one_operand_loc (loc, type, t1, arg0);
}
/* Canonicalize (X & C1) | C2. */
/* If (C1&C2) == C1, then (X&C1)|C2 becomes (X,C2). */
if ((hi1 & hi2) == hi1 && (lo1 & lo2) == lo1)
- return omit_one_operand (type, arg1, TREE_OPERAND (arg0, 0));
+ return omit_one_operand_loc (loc, type, arg1,
+ TREE_OPERAND (arg0, 0));
if (width > HOST_BITS_PER_WIDE_INT)
{
- mhi = (unsigned HOST_WIDE_INT) -1
+ mhi = (unsigned HOST_WIDE_INT) -1
>> (2 * HOST_BITS_PER_WIDE_INT - width);
mlo = -1;
}
/* If (C1|C2) == ~0 then (X&C1)|C2 becomes X|C2. */
if ((~(hi1 | hi2) & mhi) == 0 && (~(lo1 | lo2) & mlo) == 0)
- return fold_build2 (BIT_IOR_EXPR, type,
+ return fold_build2_loc (loc, BIT_IOR_EXPR, type,
TREE_OPERAND (arg0, 0), arg1);
/* Minimize the number of bits set in C1, i.e. C1 := C1 & ~C2,
}
}
if (hi3 != hi1 || lo3 != lo1)
- return fold_build2 (BIT_IOR_EXPR, type,
- fold_build2 (BIT_AND_EXPR, type,
+ 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)),
/* (X & Y) | Y is (X, Y). */
if (TREE_CODE (arg0) == BIT_AND_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
- return omit_one_operand (type, arg1, TREE_OPERAND (arg0, 0));
+ return omit_one_operand_loc (loc, type, arg1, TREE_OPERAND (arg0, 0));
/* (X & Y) | X is (Y, X). */
if (TREE_CODE (arg0) == BIT_AND_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
&& reorder_operands_p (TREE_OPERAND (arg0, 1), arg1))
- return omit_one_operand (type, arg1, TREE_OPERAND (arg0, 1));
+ return omit_one_operand_loc (loc, type, arg1, TREE_OPERAND (arg0, 1));
/* X | (X & Y) is (Y, X). */
if (TREE_CODE (arg1) == BIT_AND_EXPR
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0)
&& reorder_operands_p (arg0, TREE_OPERAND (arg1, 1)))
- return omit_one_operand (type, arg0, TREE_OPERAND (arg1, 1));
+ return omit_one_operand_loc (loc, type, arg0, TREE_OPERAND (arg1, 1));
/* X | (Y & X) is (Y, X). */
if (TREE_CODE (arg1) == BIT_AND_EXPR
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 1), 0)
&& reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
- return omit_one_operand (type, 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 (code, type, arg0, arg1);
+ t1 = distribute_bit_expr (loc, code, type, arg0, arg1);
if (t1 != NULL_TREE)
return t1;
if (TREE_CODE (arg0) == BIT_NOT_EXPR
&& TREE_CODE (arg1) == BIT_NOT_EXPR)
{
- return fold_build1 (BIT_NOT_EXPR, type,
- build2 (BIT_AND_EXPR, type,
- fold_convert (type,
- TREE_OPERAND (arg0, 0)),
- fold_convert (type,
- TREE_OPERAND (arg1, 0))));
+ return
+ fold_build1_loc (loc, BIT_NOT_EXPR, type,
+ build2 (BIT_AND_EXPR, type,
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg0, 0)),
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg1, 0))));
}
/* See if this can be simplified into a rotate first. If that
case BIT_XOR_EXPR:
if (integer_zerop (arg1))
- return non_lvalue (fold_convert (type, arg0));
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
if (integer_all_onesp (arg1))
- return fold_build1 (BIT_NOT_EXPR, type, op0);
+ return fold_build1_loc (loc, BIT_NOT_EXPR, type, op0);
if (operand_equal_p (arg0, arg1, 0))
- return omit_one_operand (type, integer_zero_node, arg0);
+ return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
/* ~X ^ X is -1. */
if (TREE_CODE (arg0) == BIT_NOT_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
{
- t1 = fold_convert (type, integer_zero_node);
- t1 = fold_unary (BIT_NOT_EXPR, type, t1);
- return omit_one_operand (type, t1, arg1);
+ t1 = build_zero_cst (type);
+ t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
+ return omit_one_operand_loc (loc, type, t1, arg1);
}
/* X ^ ~X is -1. */
if (TREE_CODE (arg1) == BIT_NOT_EXPR
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
{
- t1 = fold_convert (type, integer_zero_node);
- t1 = fold_unary (BIT_NOT_EXPR, type, t1);
- return omit_one_operand (type, t1, arg0);
+ t1 = build_zero_cst (type);
+ t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
+ return omit_one_operand_loc (loc, type, t1, arg0);
}
/* If we are XORing two BIT_AND_EXPR's, both of which are and'ing
&& TREE_CODE (TREE_OPERAND (arg1, 1)) == INTEGER_CST
&& integer_zerop (const_binop (BIT_AND_EXPR,
TREE_OPERAND (arg0, 1),
- TREE_OPERAND (arg1, 1), 0)))
+ TREE_OPERAND (arg1, 1))))
{
code = BIT_IOR_EXPR;
goto bit_ior;
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
{
tree t2 = TREE_OPERAND (arg0, 1);
- t1 = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (arg1),
+ t1 = fold_build1_loc (loc, BIT_NOT_EXPR, TREE_TYPE (arg1),
arg1);
- t1 = fold_build2 (BIT_AND_EXPR, type, fold_convert (type, t2),
- fold_convert (type, t1));
+ t1 = fold_build2_loc (loc, BIT_AND_EXPR, type,
+ fold_convert_loc (loc, type, t2),
+ fold_convert_loc (loc, type, t1));
return t1;
}
&& operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
{
tree t2 = TREE_OPERAND (arg0, 0);
- t1 = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (arg1),
+ t1 = fold_build1_loc (loc, BIT_NOT_EXPR, TREE_TYPE (arg1),
arg1);
- t1 = fold_build2 (BIT_AND_EXPR, type, fold_convert (type, t2),
- fold_convert (type, t1));
+ t1 = fold_build2_loc (loc, BIT_AND_EXPR, type,
+ fold_convert_loc (loc, type, t2),
+ fold_convert_loc (loc, type, t1));
return t1;
}
&& operand_equal_p (TREE_OPERAND (arg1, 0), arg0, 0))
{
tree t2 = TREE_OPERAND (arg1, 1);
- t1 = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (arg0),
+ t1 = fold_build1_loc (loc, BIT_NOT_EXPR, TREE_TYPE (arg0),
arg0);
- t1 = fold_build2 (BIT_AND_EXPR, type, fold_convert (type, t2),
- fold_convert (type, t1));
+ t1 = fold_build2_loc (loc, BIT_AND_EXPR, type,
+ fold_convert_loc (loc, type, t2),
+ fold_convert_loc (loc, type, t1));
return t1;
}
&& operand_equal_p (TREE_OPERAND (arg1, 1), arg0, 0))
{
tree t2 = TREE_OPERAND (arg1, 0);
- t1 = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (arg0),
+ t1 = fold_build1_loc (loc, BIT_NOT_EXPR, TREE_TYPE (arg0),
arg0);
- t1 = fold_build2 (BIT_AND_EXPR, type, fold_convert (type, t2),
- fold_convert (type, t1));
+ t1 = fold_build2_loc (loc, BIT_AND_EXPR, type,
+ fold_convert_loc (loc, type, t2),
+ fold_convert_loc (loc, type, t1));
return t1;
}
-
+
/* Convert ~X ^ ~Y to X ^ Y. */
if (TREE_CODE (arg0) == BIT_NOT_EXPR
&& TREE_CODE (arg1) == BIT_NOT_EXPR)
- return fold_build2 (code, type,
- fold_convert (type, TREE_OPERAND (arg0, 0)),
- fold_convert (type, TREE_OPERAND (arg1, 0)));
+ return fold_build2_loc (loc, code, type,
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg0, 0)),
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg1, 0)));
/* Convert ~X ^ C to X ^ ~C. */
if (TREE_CODE (arg0) == BIT_NOT_EXPR
&& TREE_CODE (arg1) == INTEGER_CST)
- return fold_build2 (code, type,
- fold_convert (type, TREE_OPERAND (arg0, 0)),
- fold_build1 (BIT_NOT_EXPR, type, arg1));
+ return fold_build2_loc (loc, code, type,
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg0, 0)),
+ fold_build1_loc (loc, BIT_NOT_EXPR, type, arg1));
/* Fold (X & 1) ^ 1 as (X & 1) == 0. */
if (TREE_CODE (arg0) == BIT_AND_EXPR
&& integer_onep (TREE_OPERAND (arg0, 1))
&& integer_onep (arg1))
- return fold_build2 (EQ_EXPR, type, arg0,
+ return fold_build2_loc (loc, EQ_EXPR, type, arg0,
build_int_cst (TREE_TYPE (arg0), 0));
/* Fold (X & Y) ^ Y as ~X & Y. */
if (TREE_CODE (arg0) == BIT_AND_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
{
- tem = fold_convert (type, TREE_OPERAND (arg0, 0));
- return fold_build2 (BIT_AND_EXPR, type,
- fold_build1 (BIT_NOT_EXPR, type, tem),
- fold_convert (type, arg1));
+ tem = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
+ return fold_build2_loc (loc, BIT_AND_EXPR, type,
+ fold_build1_loc (loc, BIT_NOT_EXPR, type, tem),
+ fold_convert_loc (loc, type, arg1));
}
/* Fold (X & Y) ^ X as ~Y & X. */
if (TREE_CODE (arg0) == BIT_AND_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
&& reorder_operands_p (TREE_OPERAND (arg0, 1), arg1))
{
- tem = fold_convert (type, TREE_OPERAND (arg0, 1));
- return fold_build2 (BIT_AND_EXPR, type,
- fold_build1 (BIT_NOT_EXPR, type, tem),
- fold_convert (type, arg1));
+ tem = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
+ return fold_build2_loc (loc, BIT_AND_EXPR, type,
+ fold_build1_loc (loc, BIT_NOT_EXPR, type, tem),
+ fold_convert_loc (loc, type, arg1));
}
/* Fold X ^ (X & Y) as X & ~Y. */
if (TREE_CODE (arg1) == BIT_AND_EXPR
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
{
- tem = fold_convert (type, TREE_OPERAND (arg1, 1));
- return fold_build2 (BIT_AND_EXPR, type,
- fold_convert (type, arg0),
- fold_build1 (BIT_NOT_EXPR, type, tem));
+ tem = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 1));
+ return fold_build2_loc (loc, BIT_AND_EXPR, type,
+ fold_convert_loc (loc, type, arg0),
+ fold_build1_loc (loc, BIT_NOT_EXPR, type, tem));
}
/* Fold X ^ (Y & X) as ~Y & X. */
if (TREE_CODE (arg1) == BIT_AND_EXPR
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 1), 0)
&& reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
{
- tem = fold_convert (type, TREE_OPERAND (arg1, 0));
- return fold_build2 (BIT_AND_EXPR, type,
- fold_build1 (BIT_NOT_EXPR, type, tem),
- fold_convert (type, arg0));
+ tem = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 0));
+ return fold_build2_loc (loc, BIT_AND_EXPR, type,
+ fold_build1_loc (loc, BIT_NOT_EXPR, type, tem),
+ fold_convert_loc (loc, type, arg0));
}
/* See if this can be simplified into a rotate first. If that
case BIT_AND_EXPR:
if (integer_all_onesp (arg1))
- return non_lvalue (fold_convert (type, arg0));
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
if (integer_zerop (arg1))
- return omit_one_operand (type, arg1, arg0);
+ return omit_one_operand_loc (loc, type, arg1, arg0);
if (operand_equal_p (arg0, arg1, 0))
- return non_lvalue (fold_convert (type, arg0));
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
/* ~X & X is always zero. */
if (TREE_CODE (arg0) == BIT_NOT_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
- return omit_one_operand (type, integer_zero_node, arg1);
+ return omit_one_operand_loc (loc, type, integer_zero_node, arg1);
/* X & ~X is always zero. */
if (TREE_CODE (arg1) == BIT_NOT_EXPR
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
- return omit_one_operand (type, integer_zero_node, arg0);
+ return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
/* Canonicalize (X | C1) & C2 as (X & C2) | (C1 & C2). */
if (TREE_CODE (arg0) == BIT_IOR_EXPR
&& TREE_CODE (arg1) == INTEGER_CST
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
{
- tree tmp1 = fold_convert (type, arg1);
- tree tmp2 = fold_convert (type, TREE_OPERAND (arg0, 0));
- tree tmp3 = fold_convert (type, TREE_OPERAND (arg0, 1));
- tmp2 = fold_build2 (BIT_AND_EXPR, type, tmp2, tmp1);
- tmp3 = fold_build2 (BIT_AND_EXPR, type, tmp3, tmp1);
- return fold_convert (type,
- fold_build2 (BIT_IOR_EXPR, type, tmp2, tmp3));
+ tree tmp1 = fold_convert_loc (loc, type, arg1);
+ tree tmp2 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
+ tree tmp3 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
+ tmp2 = fold_build2_loc (loc, BIT_AND_EXPR, type, tmp2, tmp1);
+ tmp3 = fold_build2_loc (loc, BIT_AND_EXPR, type, tmp3, tmp1);
+ return
+ fold_convert_loc (loc, type,
+ fold_build2_loc (loc, BIT_IOR_EXPR,
+ type, tmp2, tmp3));
}
/* (X | Y) & Y is (X, Y). */
if (TREE_CODE (arg0) == BIT_IOR_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
- return omit_one_operand (type, arg1, TREE_OPERAND (arg0, 0));
+ return omit_one_operand_loc (loc, type, arg1, TREE_OPERAND (arg0, 0));
/* (X | Y) & X is (Y, X). */
if (TREE_CODE (arg0) == BIT_IOR_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
&& reorder_operands_p (TREE_OPERAND (arg0, 1), arg1))
- return omit_one_operand (type, arg1, TREE_OPERAND (arg0, 1));
+ return omit_one_operand_loc (loc, type, arg1, TREE_OPERAND (arg0, 1));
/* X & (X | Y) is (Y, X). */
if (TREE_CODE (arg1) == BIT_IOR_EXPR
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0)
&& reorder_operands_p (arg0, TREE_OPERAND (arg1, 1)))
- return omit_one_operand (type, arg0, TREE_OPERAND (arg1, 1));
+ return omit_one_operand_loc (loc, type, arg0, TREE_OPERAND (arg1, 1));
/* X & (Y | X) is (Y, X). */
if (TREE_CODE (arg1) == BIT_IOR_EXPR
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 1), 0)
&& reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
- return omit_one_operand (type, arg0, TREE_OPERAND (arg1, 0));
+ return omit_one_operand_loc (loc, type, arg0, TREE_OPERAND (arg1, 0));
/* Fold (X ^ 1) & 1 as (X & 1) == 0. */
if (TREE_CODE (arg0) == BIT_XOR_EXPR
&& integer_onep (arg1))
{
tem = TREE_OPERAND (arg0, 0);
- return fold_build2 (EQ_EXPR, type,
- fold_build2 (BIT_AND_EXPR, TREE_TYPE (tem), tem,
+ return fold_build2_loc (loc, EQ_EXPR, type,
+ fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (tem), tem,
build_int_cst (TREE_TYPE (tem), 1)),
build_int_cst (TREE_TYPE (tem), 0));
}
&& integer_onep (arg1))
{
tem = TREE_OPERAND (arg0, 0);
- return fold_build2 (EQ_EXPR, type,
- fold_build2 (BIT_AND_EXPR, TREE_TYPE (tem), tem,
+ return fold_build2_loc (loc, EQ_EXPR, type,
+ fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (tem), tem,
build_int_cst (TREE_TYPE (tem), 1)),
build_int_cst (TREE_TYPE (tem), 0));
}
if (TREE_CODE (arg0) == BIT_XOR_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
{
- tem = fold_convert (type, TREE_OPERAND (arg0, 0));
- return fold_build2 (BIT_AND_EXPR, type,
- fold_build1 (BIT_NOT_EXPR, type, tem),
- fold_convert (type, arg1));
+ tem = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
+ return fold_build2_loc (loc, BIT_AND_EXPR, type,
+ fold_build1_loc (loc, BIT_NOT_EXPR, type, tem),
+ fold_convert_loc (loc, type, arg1));
}
/* Fold (X ^ Y) & X as ~Y & X. */
if (TREE_CODE (arg0) == BIT_XOR_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
&& reorder_operands_p (TREE_OPERAND (arg0, 1), arg1))
{
- tem = fold_convert (type, TREE_OPERAND (arg0, 1));
- return fold_build2 (BIT_AND_EXPR, type,
- fold_build1 (BIT_NOT_EXPR, type, tem),
- fold_convert (type, arg1));
+ tem = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
+ return fold_build2_loc (loc, BIT_AND_EXPR, type,
+ fold_build1_loc (loc, BIT_NOT_EXPR, type, tem),
+ fold_convert_loc (loc, type, arg1));
}
/* Fold X & (X ^ Y) as X & ~Y. */
if (TREE_CODE (arg1) == BIT_XOR_EXPR
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
{
- tem = fold_convert (type, TREE_OPERAND (arg1, 1));
- return fold_build2 (BIT_AND_EXPR, type,
- fold_convert (type, arg0),
- fold_build1 (BIT_NOT_EXPR, type, tem));
+ tem = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 1));
+ return fold_build2_loc (loc, BIT_AND_EXPR, type,
+ fold_convert_loc (loc, type, arg0),
+ fold_build1_loc (loc, BIT_NOT_EXPR, type, tem));
}
/* Fold X & (Y ^ X) as ~Y & X. */
if (TREE_CODE (arg1) == BIT_XOR_EXPR
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 1), 0)
&& reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
{
- tem = fold_convert (type, TREE_OPERAND (arg1, 0));
- return fold_build2 (BIT_AND_EXPR, type,
- fold_build1 (BIT_NOT_EXPR, type, tem),
- fold_convert (type, arg0));
+ tem = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 0));
+ return fold_build2_loc (loc, BIT_AND_EXPR, type,
+ fold_build1_loc (loc, BIT_NOT_EXPR, type, tem),
+ fold_convert_loc (loc, type, arg0));
+ }
+
+ /* For constants M and N, if M == (1LL << cst) - 1 && (N & M) == M,
+ ((A & N) + B) & M -> (A + B) & M
+ Similarly if (N & M) == 0,
+ ((A | N) + B) & M -> (A + B) & M
+ and for - instead of + (or unary - instead of +)
+ and/or ^ instead of |.
+ If B is constant and (B & M) == 0, fold into A & M. */
+ if (host_integerp (arg1, 1))
+ {
+ unsigned HOST_WIDE_INT cst1 = tree_low_cst (arg1, 1);
+ if (~cst1 && (cst1 & (cst1 + 1)) == 0
+ && INTEGRAL_TYPE_P (TREE_TYPE (arg0))
+ && (TREE_CODE (arg0) == PLUS_EXPR
+ || TREE_CODE (arg0) == MINUS_EXPR
+ || TREE_CODE (arg0) == NEGATE_EXPR)
+ && (TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg0))
+ || TREE_CODE (TREE_TYPE (arg0)) == INTEGER_TYPE))
+ {
+ tree pmop[2];
+ int which = 0;
+ unsigned HOST_WIDE_INT cst0;
+
+ /* Now we know that arg0 is (C + D) or (C - D) or
+ -C and arg1 (M) is == (1LL << cst) - 1.
+ Store C into PMOP[0] and D into PMOP[1]. */
+ pmop[0] = TREE_OPERAND (arg0, 0);
+ pmop[1] = NULL;
+ if (TREE_CODE (arg0) != NEGATE_EXPR)
+ {
+ pmop[1] = TREE_OPERAND (arg0, 1);
+ which = 1;
+ }
+
+ if (!host_integerp (TYPE_MAX_VALUE (TREE_TYPE (arg0)), 1)
+ || (tree_low_cst (TYPE_MAX_VALUE (TREE_TYPE (arg0)), 1)
+ & cst1) != cst1)
+ which = -1;
+
+ for (; which >= 0; which--)
+ switch (TREE_CODE (pmop[which]))
+ {
+ case BIT_AND_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ if (TREE_CODE (TREE_OPERAND (pmop[which], 1))
+ != INTEGER_CST)
+ break;
+ /* tree_low_cst not used, because we don't care about
+ the upper bits. */
+ cst0 = TREE_INT_CST_LOW (TREE_OPERAND (pmop[which], 1));
+ cst0 &= cst1;
+ if (TREE_CODE (pmop[which]) == BIT_AND_EXPR)
+ {
+ if (cst0 != cst1)
+ break;
+ }
+ else if (cst0 != 0)
+ break;
+ /* If C or D is of the form (A & N) where
+ (N & M) == M, or of the form (A | N) or
+ (A ^ N) where (N & M) == 0, replace it with A. */
+ pmop[which] = TREE_OPERAND (pmop[which], 0);
+ break;
+ case INTEGER_CST:
+ /* If C or D is a N where (N & M) == 0, it can be
+ omitted (assumed 0). */
+ if ((TREE_CODE (arg0) == PLUS_EXPR
+ || (TREE_CODE (arg0) == MINUS_EXPR && which == 0))
+ && (TREE_INT_CST_LOW (pmop[which]) & cst1) == 0)
+ pmop[which] = NULL;
+ break;
+ default:
+ break;
+ }
+
+ /* Only build anything new if we optimized one or both arguments
+ above. */
+ if (pmop[0] != TREE_OPERAND (arg0, 0)
+ || (TREE_CODE (arg0) != NEGATE_EXPR
+ && pmop[1] != TREE_OPERAND (arg0, 1)))
+ {
+ tree utype = TREE_TYPE (arg0);
+ if (! TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg0)))
+ {
+ /* Perform the operations in a type that has defined
+ overflow behavior. */
+ utype = unsigned_type_for (TREE_TYPE (arg0));
+ if (pmop[0] != NULL)
+ pmop[0] = fold_convert_loc (loc, utype, pmop[0]);
+ if (pmop[1] != NULL)
+ pmop[1] = fold_convert_loc (loc, utype, pmop[1]);
+ }
+
+ if (TREE_CODE (arg0) == NEGATE_EXPR)
+ tem = fold_build1_loc (loc, NEGATE_EXPR, utype, pmop[0]);
+ else if (TREE_CODE (arg0) == PLUS_EXPR)
+ {
+ if (pmop[0] != NULL && pmop[1] != NULL)
+ tem = fold_build2_loc (loc, PLUS_EXPR, utype,
+ pmop[0], pmop[1]);
+ else if (pmop[0] != NULL)
+ tem = pmop[0];
+ else if (pmop[1] != NULL)
+ tem = pmop[1];
+ else
+ return build_int_cst (type, 0);
+ }
+ else if (pmop[0] == NULL)
+ tem = fold_build1_loc (loc, NEGATE_EXPR, utype, pmop[1]);
+ else
+ tem = fold_build2_loc (loc, MINUS_EXPR, utype,
+ pmop[0], pmop[1]);
+ /* TEM is now the new binary +, - or unary - replacement. */
+ tem = fold_build2_loc (loc, BIT_AND_EXPR, utype, tem,
+ fold_convert_loc (loc, utype, arg1));
+ return fold_convert_loc (loc, type, tem);
+ }
+ }
}
- t1 = distribute_bit_expr (code, type, arg0, arg1);
+ t1 = distribute_bit_expr (loc, code, type, arg0, arg1);
if (t1 != NULL_TREE)
return t1;
/* Simplify ((int)c & 0377) into (int)c, if c is unsigned char. */
if (prec < BITS_PER_WORD && prec < HOST_BITS_PER_WIDE_INT
&& (~TREE_INT_CST_LOW (arg1)
& (((HOST_WIDE_INT) 1 << prec) - 1)) == 0)
- return fold_convert (type, TREE_OPERAND (arg0, 0));
+ return
+ fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
}
/* Convert (and (not arg0) (not arg1)) to (not (or (arg0) (arg1))).
if (TREE_CODE (arg0) == BIT_NOT_EXPR
&& TREE_CODE (arg1) == BIT_NOT_EXPR)
{
- return fold_build1 (BIT_NOT_EXPR, type,
+ return fold_build1_loc (loc, BIT_NOT_EXPR, type,
build2 (BIT_IOR_EXPR, type,
- fold_convert (type,
- TREE_OPERAND (arg0, 0)),
- fold_convert (type,
- TREE_OPERAND (arg1, 0))));
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg0, 0)),
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg1, 0))));
}
/* If arg0 is derived from the address of an object or function, we may
/* ((X << 16) & 0xff00) is (X, 0). */
if ((mask & zerobits) == mask)
- return omit_one_operand (type, build_int_cst (type, 0), arg0);
+ return omit_one_operand_loc (loc, type,
+ build_int_cst (type, 0), arg0);
newmask = mask | zerobits;
if (newmask != mask && (newmask & (newmask + 1)) == 0)
if (shift_type != TREE_TYPE (arg0))
{
- tem = fold_build2 (TREE_CODE (arg0), shift_type,
- fold_convert (shift_type,
- TREE_OPERAND (arg0, 0)),
+ 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 (type, tem);
+ 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 (BIT_AND_EXPR, type, tem, newmaskt);
+ return fold_build2_loc (loc, BIT_AND_EXPR, type, tem, newmaskt);
}
}
}
{
tree r = build_real (TREE_TYPE (arg0), dconst1);
- return omit_two_operands (type, r, arg0, arg1);
+ return omit_two_operands_loc (loc, type, r, arg0, arg1);
}
/* The complex version of the above A / A optimization. */
{
tree r = build_real (elem_type, dconst1);
/* omit_two_operands will call fold_convert for us. */
- return omit_two_operands (type, r, arg0, arg1);
+ return omit_two_operands_loc (loc, type, r, arg0, arg1);
}
}
/* (-A) / (-B) -> A / B */
if (TREE_CODE (arg0) == NEGATE_EXPR && negate_expr_p (arg1))
- return fold_build2 (RDIV_EXPR, type,
+ return fold_build2_loc (loc, RDIV_EXPR, type,
TREE_OPERAND (arg0, 0),
negate_expr (arg1));
if (TREE_CODE (arg1) == NEGATE_EXPR && negate_expr_p (arg0))
- return fold_build2 (RDIV_EXPR, type,
+ return fold_build2_loc (loc, RDIV_EXPR, type,
negate_expr (arg0),
TREE_OPERAND (arg1, 0));
/* In IEEE floating point, x/1 is not equivalent to x for snans. */
if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
&& real_onep (arg1))
- return non_lvalue (fold_convert (type, arg0));
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
/* In IEEE floating point, x/-1 is not equivalent to -x for snans. */
if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
&& real_minus_onep (arg1))
- return non_lvalue (fold_convert (type, negate_expr (arg0)));
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type,
+ negate_expr (arg0)));
/* If ARG1 is a constant, we can convert this to a multiply by the
reciprocal. This does not have the same rounding properties,
{
if (flag_reciprocal_math
&& 0 != (tem = const_binop (code, build_real (type, dconst1),
- arg1, 0)))
- return fold_build2 (MULT_EXPR, type, arg0, tem);
+ arg1)))
+ return fold_build2_loc (loc, MULT_EXPR, type, arg0, tem);
/* Find the reciprocal if optimizing and the result is exact. */
if (optimize)
{
if (exact_real_inverse (TYPE_MODE(TREE_TYPE(arg0)), &r))
{
tem = build_real (type, r);
- return fold_build2 (MULT_EXPR, type,
- fold_convert (type, arg0), tem);
+ return fold_build2_loc (loc, MULT_EXPR, type,
+ fold_convert_loc (loc, type, arg0), tem);
}
}
}
- /* Convert A/B/C to A/(B*C). */
+ /* Convert A/B/C to A/(B*C). */
if (flag_reciprocal_math
&& TREE_CODE (arg0) == RDIV_EXPR)
- return fold_build2 (RDIV_EXPR, type, TREE_OPERAND (arg0, 0),
- fold_build2 (MULT_EXPR, type,
+ return fold_build2_loc (loc, RDIV_EXPR, type, TREE_OPERAND (arg0, 0),
+ fold_build2_loc (loc, MULT_EXPR, type,
TREE_OPERAND (arg0, 1), arg1));
/* Convert A/(B/C) to (A/B)*C. */
if (flag_reciprocal_math
&& TREE_CODE (arg1) == RDIV_EXPR)
- return fold_build2 (MULT_EXPR, type,
- fold_build2 (RDIV_EXPR, type, arg0,
+ return fold_build2_loc (loc, MULT_EXPR, type,
+ fold_build2_loc (loc, RDIV_EXPR, type, arg0,
TREE_OPERAND (arg1, 0)),
TREE_OPERAND (arg1, 1));
&& TREE_CODE (TREE_OPERAND (arg1, 1)) == REAL_CST)
{
tree tem = const_binop (RDIV_EXPR, arg0,
- TREE_OPERAND (arg1, 1), 0);
+ TREE_OPERAND (arg1, 1));
if (tem)
- return fold_build2 (RDIV_EXPR, type, tem,
+ return fold_build2_loc (loc, RDIV_EXPR, type, tem,
TREE_OPERAND (arg1, 0));
}
tree tanfn = mathfn_built_in (type, BUILT_IN_TAN);
if (tanfn != NULL_TREE)
- return build_call_expr (tanfn, 1, CALL_EXPR_ARG (arg0, 0));
+ return build_call_expr_loc (loc, tanfn, 1, CALL_EXPR_ARG (arg0, 0));
}
/* Optimize cos(x)/sin(x) as 1.0/tan(x). */
if (tanfn != NULL_TREE)
{
- tree tmp = build_call_expr (tanfn, 1, CALL_EXPR_ARG (arg0, 0));
- return fold_build2 (RDIV_EXPR, type,
+ tree tmp = build_call_expr_loc (loc, tanfn, 1,
+ CALL_EXPR_ARG (arg0, 0));
+ return fold_build2_loc (loc, RDIV_EXPR, type,
build_real (type, dconst1), tmp);
}
}
tree cosfn = mathfn_built_in (type, BUILT_IN_COS);
if (cosfn != NULL_TREE)
- return build_call_expr (cosfn, 1, arg00);
+ return build_call_expr_loc (loc, cosfn, 1, arg00);
}
}
if (cosfn != NULL_TREE)
{
- tree tmp = build_call_expr (cosfn, 1, arg00);
- return fold_build2 (RDIV_EXPR, type,
+ tree tmp = build_call_expr_loc (loc, cosfn, 1, arg00);
+ return fold_build2_loc (loc, RDIV_EXPR, type,
build_real (type, dconst1),
tmp);
}
c = TREE_REAL_CST (arg01);
real_arithmetic (&c, MINUS_EXPR, &c, &dconst1);
arg = build_real (type, c);
- return build_call_expr (powfn, 2, arg1, arg);
+ return build_call_expr_loc (loc, powfn, 2, arg1, arg);
}
}
tree b = TREE_OPERAND (rootarg, 0);
tree c = TREE_OPERAND (rootarg, 1);
- tree tmp = fold_build2 (RDIV_EXPR, type, c, b);
+ tree tmp = fold_build2_loc (loc, RDIV_EXPR, type, c, b);
- tmp = build_call_expr (rootfn, 1, tmp);
- return fold_build2 (MULT_EXPR, type, arg0, tmp);
+ tmp = build_call_expr_loc (loc, rootfn, 1, tmp);
+ return fold_build2_loc (loc, MULT_EXPR, type, arg0, tmp);
}
}
{
tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg1), 0);
tree arg = negate_expr (CALL_EXPR_ARG (arg1, 0));
- arg1 = build_call_expr (expfn, 1, fold_convert (type, arg));
- return fold_build2 (MULT_EXPR, type, arg0, arg1);
+ arg1 = build_call_expr_loc (loc,
+ expfn, 1,
+ fold_convert_loc (loc, type, arg));
+ return fold_build2_loc (loc, MULT_EXPR, type, arg0, arg1);
}
/* Optimize x/pow(y,z) into x*pow(y,-z). */
tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg1), 0);
tree arg10 = CALL_EXPR_ARG (arg1, 0);
tree arg11 = CALL_EXPR_ARG (arg1, 1);
- tree neg11 = fold_convert (type, negate_expr (arg11));
- arg1 = build_call_expr (powfn, 2, arg10, neg11);
- return fold_build2 (MULT_EXPR, type, arg0, arg1);
+ tree neg11 = fold_convert_loc (loc, type,
+ negate_expr (arg11));
+ arg1 = build_call_expr_loc (loc, powfn, 2, arg10, neg11);
+ return fold_build2_loc (loc, MULT_EXPR, type, arg0, arg1);
}
}
return NULL_TREE;
case TRUNC_DIV_EXPR:
+ /* Optimize (X & (-A)) / A where A is a power of 2,
+ to X >> log2(A) */
+ if (TREE_CODE (arg0) == BIT_AND_EXPR
+ && !TYPE_UNSIGNED (type) && TREE_CODE (arg1) == INTEGER_CST
+ && integer_pow2p (arg1) && tree_int_cst_sgn (arg1) > 0)
+ {
+ tree sum = fold_binary_loc (loc, PLUS_EXPR, TREE_TYPE (arg1),
+ arg1, TREE_OPERAND (arg0, 1));
+ if (sum && integer_zerop (sum)) {
+ unsigned long pow2;
+
+ if (TREE_INT_CST_LOW (arg1))
+ pow2 = exact_log2 (TREE_INT_CST_LOW (arg1));
+ else
+ pow2 = exact_log2 (TREE_INT_CST_HIGH (arg1))
+ + HOST_BITS_PER_WIDE_INT;
+
+ return fold_build2_loc (loc, RSHIFT_EXPR, type,
+ TREE_OPERAND (arg0, 0),
+ build_int_cst (integer_type_node, pow2));
+ }
+ }
+
+ /* Fall thru */
+
case FLOOR_DIV_EXPR:
/* Simplify A / (B << N) where A and B are positive and B is
a power of 2, to A >> (N + log2(B)). */
if (integer_pow2p (sval) && tree_int_cst_sgn (sval) > 0)
{
tree sh_cnt = TREE_OPERAND (arg1, 1);
- unsigned long pow2 = exact_log2 (TREE_INT_CST_LOW (sval));
+ unsigned long pow2;
+
+ if (TREE_INT_CST_LOW (sval))
+ pow2 = exact_log2 (TREE_INT_CST_LOW (sval));
+ else
+ pow2 = exact_log2 (TREE_INT_CST_HIGH (sval))
+ + HOST_BITS_PER_WIDE_INT;
if (strict_overflow_p)
fold_overflow_warning (("assuming signed overflow does not "
"occur when simplifying A / (B << N)"),
WARN_STRICT_OVERFLOW_MISC);
- sh_cnt = fold_build2 (PLUS_EXPR, TREE_TYPE (sh_cnt),
- sh_cnt, build_int_cst (NULL_TREE, pow2));
- return fold_build2 (RSHIFT_EXPR, type,
- fold_convert (type, arg0), sh_cnt);
+ sh_cnt = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (sh_cnt),
+ 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);
}
}
if (INTEGRAL_TYPE_P (type)
&& TYPE_UNSIGNED (type)
&& code == FLOOR_DIV_EXPR)
- return fold_build2 (TRUNC_DIV_EXPR, type, op0, op1);
+ return fold_build2_loc (loc, TRUNC_DIV_EXPR, type, op0, op1);
/* Fall thru */
case CEIL_DIV_EXPR:
case EXACT_DIV_EXPR:
if (integer_onep (arg1))
- return non_lvalue (fold_convert (type, arg0));
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
if (integer_zerop (arg1))
return NULL_TREE;
/* X / -1 is -X. */
&& TREE_CODE (arg1) == INTEGER_CST
&& TREE_INT_CST_LOW (arg1) == (unsigned HOST_WIDE_INT) -1
&& TREE_INT_CST_HIGH (arg1) == -1)
- return fold_convert (type, negate_expr (arg0));
+ return fold_convert_loc (loc, type, negate_expr (arg0));
/* Convert -A / -B to A / B when the type is signed and overflow is
undefined. */
"when distributing negation across "
"division"),
WARN_STRICT_OVERFLOW_MISC);
- return fold_build2 (code, type,
- fold_convert (type, TREE_OPERAND (arg0, 0)),
- fold_convert (type, negate_expr (arg1)));
+ return fold_build2_loc (loc, code, type,
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg0, 0)),
+ fold_convert_loc (loc, type,
+ negate_expr (arg1)));
}
if ((!INTEGRAL_TYPE_P (type) || TYPE_OVERFLOW_UNDEFINED (type))
&& TREE_CODE (arg1) == NEGATE_EXPR
"when distributing negation across "
"division"),
WARN_STRICT_OVERFLOW_MISC);
- return fold_build2 (code, type,
- fold_convert (type, negate_expr (arg0)),
- fold_convert (type, TREE_OPERAND (arg1, 0)));
+ return fold_build2_loc (loc, code, type,
+ fold_convert_loc (loc, type,
+ negate_expr (arg0)),
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg1, 0)));
}
/* If arg0 is a multiple of arg1, then rewrite to the fastest div
after the last round to changes to the DIV code in expmed.c. */
if ((code == CEIL_DIV_EXPR || code == FLOOR_DIV_EXPR)
&& multiple_of_p (type, arg0, arg1))
- return fold_build2 (EXACT_DIV_EXPR, type, arg0, arg1);
+ return fold_build2_loc (loc, EXACT_DIV_EXPR, type, arg0, arg1);
strict_overflow_p = false;
if (TREE_CODE (arg1) == INTEGER_CST
fold_overflow_warning (("assuming signed overflow does not occur "
"when simplifying division"),
WARN_STRICT_OVERFLOW_MISC);
- return fold_convert (type, tem);
+ return fold_convert_loc (loc, type, tem);
}
return NULL_TREE;
/* X % 1 is always zero, but be sure to preserve any side
effects in X. */
if (integer_onep (arg1))
- return omit_one_operand (type, integer_zero_node, arg0);
+ return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
/* X % 0, return X % 0 unchanged so that we can get the
proper warnings and errors. */
/* 0 % X is always zero, but be sure to preserve any side
effects in X. Place this after checking for X == 0. */
if (integer_zerop (arg0))
- return omit_one_operand (type, integer_zero_node, arg1);
+ return omit_one_operand_loc (loc, type, integer_zero_node, arg1);
/* X % -1 is zero. */
if (!TYPE_UNSIGNED (type)
&& TREE_CODE (arg1) == INTEGER_CST
&& TREE_INT_CST_LOW (arg1) == (unsigned HOST_WIDE_INT) -1
&& TREE_INT_CST_HIGH (arg1) == -1)
- return omit_one_operand (type, integer_zero_node, arg0);
-
- /* 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. */
- strict_overflow_p = false;
- 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 (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 (BIT_AND_EXPR, type,
- fold_convert (type, arg0),
- fold_convert (type, mask));
- }
- }
+ return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
/* X % -C is the same as X % C. */
if (code == TRUNC_MOD_EXPR
&& !TYPE_OVERFLOW_TRAPS (type)
/* Avoid this transformation if C is INT_MIN, i.e. C == -C. */
&& !sign_bit_p (arg1, arg1))
- return fold_build2 (code, type, fold_convert (type, arg0),
- fold_convert (type, negate_expr (arg1)));
+ return fold_build2_loc (loc, code, type,
+ fold_convert_loc (loc, type, arg0),
+ fold_convert_loc (loc, type,
+ negate_expr (arg1)));
/* 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 (code, type, fold_convert (type, arg0),
- fold_convert (type, TREE_OPERAND (arg1, 0)));
+ 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,
&strict_overflow_p)))
fold_overflow_warning (("assuming signed overflow does not occur "
"when simplifying modulus"),
WARN_STRICT_OVERFLOW_MISC);
- return fold_convert (type, tem);
+ 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:
case RROTATE_EXPR:
if (integer_all_onesp (arg0))
- return omit_one_operand (type, arg0, arg1);
+ return omit_one_operand_loc (loc, type, arg0, arg1);
goto shift;
case RSHIFT_EXPR:
/* Optimize -1 >> x for arithmetic right shifts. */
if (integer_all_onesp (arg0) && !TYPE_UNSIGNED (type)
&& tree_expr_nonnegative_p (arg1))
- return omit_one_operand (type, arg0, arg1);
+ return omit_one_operand_loc (loc, type, arg0, arg1);
/* ... fall through ... */
case LSHIFT_EXPR:
shift:
if (integer_zerop (arg1))
- return non_lvalue (fold_convert (type, arg0));
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
if (integer_zerop (arg0))
- return omit_one_operand (type, arg0, arg1);
+ return omit_one_operand_loc (loc, type, arg0, arg1);
/* Since negative shift count is not well-defined,
don't try to compute it in the compiler. */
if (code == LROTATE_EXPR || code == RROTATE_EXPR)
low = low % TYPE_PRECISION (type);
else if (TYPE_UNSIGNED (type) || code == LSHIFT_EXPR)
- return omit_one_operand (type, build_int_cst (type, 0),
+ return omit_one_operand_loc (loc, type, build_int_cst (type, 0),
TREE_OPERAND (arg0, 0));
else
low = TYPE_PRECISION (type) - 1;
}
- return fold_build2 (code, type, TREE_OPERAND (arg0, 0),
+ return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0),
build_int_cst (type, low));
}
if (low0 == low1)
{
- arg00 = fold_convert (type, TREE_OPERAND (arg0, 0));
+ arg00 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
lshift = build_int_cst (type, -1);
lshift = int_const_binop (code, lshift, arg1, 0);
- return fold_build2 (BIT_AND_EXPR, type, arg00, lshift);
+ return fold_build2_loc (loc, BIT_AND_EXPR, type, arg00, lshift);
}
}
{
tree tem = build_int_cst (TREE_TYPE (arg1),
TYPE_PRECISION (type));
- tem = const_binop (MINUS_EXPR, tem, arg1, 0);
- return fold_build2 (RROTATE_EXPR, type, op0, tem);
+ tem = const_binop (MINUS_EXPR, tem, arg1);
+ return fold_build2_loc (loc, RROTATE_EXPR, type, op0, tem);
}
/* If we have a rotate of a bit operation with the rotate count and
|| TREE_CODE (arg0) == BIT_IOR_EXPR
|| TREE_CODE (arg0) == BIT_XOR_EXPR)
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
- return fold_build2 (TREE_CODE (arg0), type,
- fold_build2 (code, type,
+ return fold_build2_loc (loc, TREE_CODE (arg0), type,
+ fold_build2_loc (loc, code, type,
TREE_OPERAND (arg0, 0), arg1),
- fold_build2 (code, type,
+ fold_build2_loc (loc, code, type,
TREE_OPERAND (arg0, 1), arg1));
/* Two consecutive rotates adding up to the precision of the
&& TREE_CODE (arg1) == INTEGER_CST
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
{
- tree mask = fold_build2 (code, type,
- fold_convert (type, TREE_OPERAND (arg0, 1)),
+ tree mask = fold_build2_loc (loc, code, type,
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg0, 1)),
arg1);
- tree shift = fold_build2 (code, type,
- fold_convert (type, TREE_OPERAND (arg0, 0)),
+ tree shift = fold_build2_loc (loc, code, type,
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg0, 0)),
arg1);
- tem = fold_binary (BIT_AND_EXPR, type, shift, mask);
+ tem = fold_binary_loc (loc, BIT_AND_EXPR, type, shift, mask);
if (tem)
return tem;
}
case MIN_EXPR:
if (operand_equal_p (arg0, arg1, 0))
- return omit_one_operand (type, arg0, arg1);
+ return omit_one_operand_loc (loc, type, arg0, arg1);
if (INTEGRAL_TYPE_P (type)
&& operand_equal_p (arg1, TYPE_MIN_VALUE (type), OEP_ONLY_CONST))
- return omit_one_operand (type, arg1, arg0);
- tem = fold_minmax (MIN_EXPR, type, arg0, arg1);
+ return omit_one_operand_loc (loc, type, arg1, arg0);
+ tem = fold_minmax (loc, MIN_EXPR, type, arg0, arg1);
if (tem)
return tem;
goto associate;
case MAX_EXPR:
if (operand_equal_p (arg0, arg1, 0))
- return omit_one_operand (type, arg0, arg1);
+ return omit_one_operand_loc (loc, type, arg0, arg1);
if (INTEGRAL_TYPE_P (type)
&& TYPE_MAX_VALUE (type)
&& operand_equal_p (arg1, TYPE_MAX_VALUE (type), OEP_ONLY_CONST))
- return omit_one_operand (type, arg1, arg0);
- tem = fold_minmax (MAX_EXPR, type, arg0, arg1);
+ return omit_one_operand_loc (loc, type, arg1, arg0);
+ tem = fold_minmax (loc, MAX_EXPR, type, arg0, arg1);
if (tem)
return tem;
goto associate;
("true" is a fixed value perhaps depending on the language.) */
/* If first arg is constant zero, return it. */
if (integer_zerop (arg0))
- return fold_convert (type, arg0);
+ return fold_convert_loc (loc, type, arg0);
case TRUTH_AND_EXPR:
/* If either arg is constant true, drop it. */
if (TREE_CODE (arg0) == INTEGER_CST && ! integer_zerop (arg0))
- return non_lvalue (fold_convert (type, arg1));
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1));
if (TREE_CODE (arg1) == INTEGER_CST && ! integer_zerop (arg1)
/* Preserve sequence points. */
&& (code != TRUTH_ANDIF_EXPR || ! TREE_SIDE_EFFECTS (arg0)))
- return non_lvalue (fold_convert (type, arg0));
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
/* If second arg is constant zero, result is zero, but first arg
must be evaluated. */
if (integer_zerop (arg1))
- return omit_one_operand (type, arg1, arg0);
+ return omit_one_operand_loc (loc, type, arg1, arg0);
/* Likewise for first arg, but note that only the TRUTH_AND_EXPR
case will be handled here. */
if (integer_zerop (arg0))
- return omit_one_operand (type, arg0, arg1);
+ return omit_one_operand_loc (loc, type, arg0, arg1);
/* !X && X is always false. */
if (TREE_CODE (arg0) == TRUTH_NOT_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
- return omit_one_operand (type, integer_zero_node, arg1);
+ return omit_one_operand_loc (loc, type, integer_zero_node, arg1);
/* X && !X is always false. */
if (TREE_CODE (arg1) == TRUTH_NOT_EXPR
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
- return omit_one_operand (type, integer_zero_node, arg0);
+ return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
/* A < X && A + 1 > Y ==> A < X && A >= Y. Normally A + 1 > Y
means A >= Y && A != MAX, but in this case we know that
if (!TREE_SIDE_EFFECTS (arg0)
&& !TREE_SIDE_EFFECTS (arg1))
{
- tem = fold_to_nonsharp_ineq_using_bound (arg0, arg1);
+ tem = fold_to_nonsharp_ineq_using_bound (loc, arg0, arg1);
if (tem && !operand_equal_p (tem, arg0, 0))
- return fold_build2 (code, type, tem, arg1);
+ return fold_build2_loc (loc, code, type, tem, arg1);
- tem = fold_to_nonsharp_ineq_using_bound (arg1, arg0);
+ tem = fold_to_nonsharp_ineq_using_bound (loc, arg1, arg0);
if (tem && !operand_equal_p (tem, arg1, 0))
- return fold_build2 (code, type, arg0, tem);
+ return fold_build2_loc (loc, code, type, arg0, tem);
}
truth_andor:
|| code == TRUTH_OR_EXPR));
if (operand_equal_p (a00, a10, 0))
- return fold_build2 (TREE_CODE (arg0), type, a00,
- fold_build2 (code, type, a01, a11));
+ 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 (TREE_CODE (arg0), type, a00,
- fold_build2 (code, type, a01, a10));
+ 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 (TREE_CODE (arg0), type, a01,
- fold_build2 (code, type, a00, a11));
+ 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 (TREE_CODE (arg0), type,
- fold_build2 (code, type, a00, a10),
+ 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 (code, type, op0, op1)))
+ 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 (code, type,
+ && 0 != (tem = fold_truthop (loc, code, type,
TREE_OPERAND (arg0, 1), arg1)))
- return fold_build2 (code, type, TREE_OPERAND (arg0, 0), tem);
+ return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), tem);
- if ((tem = fold_truthop (code, type, arg0, arg1)) != 0)
+ if ((tem = fold_truthop (loc, code, type, arg0, arg1)) != 0)
return tem;
return NULL_TREE;
("true" is a fixed value perhaps depending on the language.) */
/* If first arg is constant true, return it. */
if (TREE_CODE (arg0) == INTEGER_CST && ! integer_zerop (arg0))
- return fold_convert (type, arg0);
+ return fold_convert_loc (loc, type, arg0);
case TRUTH_OR_EXPR:
/* If either arg is constant zero, drop it. */
if (TREE_CODE (arg0) == INTEGER_CST && integer_zerop (arg0))
- return non_lvalue (fold_convert (type, arg1));
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1));
if (TREE_CODE (arg1) == INTEGER_CST && integer_zerop (arg1)
/* Preserve sequence points. */
&& (code != TRUTH_ORIF_EXPR || ! TREE_SIDE_EFFECTS (arg0)))
- return non_lvalue (fold_convert (type, arg0));
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
/* If second arg is constant true, result is true, but we must
evaluate first arg. */
if (TREE_CODE (arg1) == INTEGER_CST && ! integer_zerop (arg1))
- return omit_one_operand (type, arg1, arg0);
+ return omit_one_operand_loc (loc, type, arg1, arg0);
/* Likewise for first arg, but note this only occurs here for
TRUTH_OR_EXPR. */
if (TREE_CODE (arg0) == INTEGER_CST && ! integer_zerop (arg0))
- return omit_one_operand (type, arg0, arg1);
+ return omit_one_operand_loc (loc, type, arg0, arg1);
/* !X || X is always true. */
if (TREE_CODE (arg0) == TRUTH_NOT_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
- return omit_one_operand (type, integer_one_node, arg1);
+ return omit_one_operand_loc (loc, type, integer_one_node, arg1);
/* X || !X is always true. */
if (TREE_CODE (arg1) == TRUTH_NOT_EXPR
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
- return omit_one_operand (type, integer_one_node, arg0);
+ return omit_one_operand_loc (loc, type, integer_one_node, arg0);
+
+ /* (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);
+ }
goto truth_andor;
case TRUTH_XOR_EXPR:
/* If the second arg is constant zero, drop it. */
if (integer_zerop (arg1))
- return non_lvalue (fold_convert (type, arg0));
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
/* If the second arg is constant true, this is a logical inversion. */
if (integer_onep (arg1))
{
/* Only call invert_truthvalue if operand is a truth value. */
if (TREE_CODE (TREE_TYPE (arg0)) != BOOLEAN_TYPE)
- tem = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (arg0), arg0);
+ tem = fold_build1_loc (loc, TRUTH_NOT_EXPR, TREE_TYPE (arg0), arg0);
else
- tem = invert_truthvalue (arg0);
- return non_lvalue (fold_convert (type, tem));
+ tem = invert_truthvalue_loc (loc, arg0);
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, tem));
}
/* Identical arguments cancel to zero. */
if (operand_equal_p (arg0, arg1, 0))
- return omit_one_operand (type, integer_zero_node, arg0);
+ return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
/* !X ^ X is always true. */
if (TREE_CODE (arg0) == TRUTH_NOT_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
- return omit_one_operand (type, integer_one_node, arg1);
+ return omit_one_operand_loc (loc, type, integer_one_node, arg1);
/* X ^ !X is always true. */
if (TREE_CODE (arg1) == TRUTH_NOT_EXPR
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
- return omit_one_operand (type, integer_one_node, arg0);
+ return omit_one_operand_loc (loc, type, integer_one_node, arg0);
return NULL_TREE;
case EQ_EXPR:
case NE_EXPR:
- tem = fold_comparison (code, type, op0, op1);
+ STRIP_NOPS (arg0);
+ STRIP_NOPS (arg1);
+
+ tem = fold_comparison (loc, code, type, op0, op1);
if (tem != NULL_TREE)
return tem;
/* bool_var != 0 becomes bool_var. */
if (TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE && integer_zerop (arg1)
&& code == NE_EXPR)
- return non_lvalue (fold_convert (type, arg0));
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
/* bool_var == 1 becomes bool_var. */
if (TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE && integer_onep (arg1)
&& code == EQ_EXPR)
- return non_lvalue (fold_convert (type, arg0));
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
/* bool_var != 1 becomes !bool_var. */
if (TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE && integer_onep (arg1)
&& code == NE_EXPR)
- return fold_build1 (TRUTH_NOT_EXPR, type, fold_convert (type, arg0));
+ return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
+ fold_convert_loc (loc, type, arg0));
/* bool_var == 0 becomes !bool_var. */
if (TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE && integer_zerop (arg1)
&& code == EQ_EXPR)
- return fold_build1 (TRUTH_NOT_EXPR, type, fold_convert (type, arg0));
+ return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
+ fold_convert_loc (loc, type, arg0));
+
+ /* !exp != 0 becomes !exp */
+ if (TREE_CODE (arg0) == TRUTH_NOT_EXPR && integer_zerop (arg1)
+ && code == NE_EXPR)
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
/* If this is an equality comparison of the address of two non-weak,
unaliased symbols neither of which are extern (since we do not
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
&& 0 != (tem = const_binop (TREE_CODE (arg0) == PLUS_EXPR
? MINUS_EXPR : PLUS_EXPR,
- fold_convert (TREE_TYPE (arg0), arg1),
- TREE_OPERAND (arg0, 1), 0))
+ fold_convert_loc (loc, TREE_TYPE (arg0),
+ arg1),
+ TREE_OPERAND (arg0, 1)))
&& !TREE_OVERFLOW (tem))
- return fold_build2 (code, type, TREE_OPERAND (arg0, 0), tem);
+ return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), tem);
/* 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 (code, type, TREE_OPERAND (arg0, 0), 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
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
- return fold_build2 (code, type, TREE_OPERAND (arg0, 0),
- fold_build2 (BIT_XOR_EXPR, TREE_TYPE (arg0),
- fold_convert (TREE_TYPE (arg0), arg1),
+ return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0),
+ fold_build2_loc (loc, BIT_XOR_EXPR, TREE_TYPE (arg0),
+ fold_convert_loc (loc,
+ TREE_TYPE (arg0),
+ arg1),
TREE_OPERAND (arg0, 1)));
/* 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)
+ && 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))))
{
tree val = TREE_OPERAND (arg0, 1);
- return omit_two_operands (type,
- fold_build2 (code, type,
+ return omit_two_operands_loc (loc, type,
+ fold_build2_loc (loc, code, type,
val,
build_int_cst (TREE_TYPE (val),
0)),
/* 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 (type,
+ return omit_two_operands_loc (loc, type,
code == NE_EXPR
? boolean_true_node : boolean_false_node,
TREE_OPERAND (arg0, 1), arg1);
for !=. Don't do this for ordered comparisons due to overflow. */
if (TREE_CODE (arg0) == MINUS_EXPR
&& integer_zerop (arg1))
- return fold_build2 (code, type,
+ return fold_build2_loc (loc, code, type,
TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1));
/* Convert ABS_EXPR<x> == 0 or ABS_EXPR<x> != 0 to x == 0 or x != 0. */
if (TREE_CODE (arg0) == ABS_EXPR
&& (integer_zerop (arg1) || real_zerop (arg1)))
- return fold_build2 (code, type, TREE_OPERAND (arg0, 0), arg1);
+ return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), arg1);
/* If this is an EQ or NE comparison with zero and ARG0 is
(1 << foo) & bar, convert it to (bar >> foo) & 1. Both require
if (TREE_CODE (arg00) == LSHIFT_EXPR
&& integer_onep (TREE_OPERAND (arg00, 0)))
{
- tree tem = fold_build2 (RSHIFT_EXPR, TREE_TYPE (arg00),
+ tree tem = fold_build2_loc (loc, RSHIFT_EXPR, TREE_TYPE (arg00),
arg01, TREE_OPERAND (arg00, 1));
- tem = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg0), tem,
+ tem = fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (arg0), tem,
build_int_cst (TREE_TYPE (arg0), 1));
- return fold_build2 (code, type,
- fold_convert (TREE_TYPE (arg1), tem), arg1);
+ return fold_build2_loc (loc, code, type,
+ fold_convert_loc (loc, TREE_TYPE (arg1), tem),
+ arg1);
}
else if (TREE_CODE (arg01) == LSHIFT_EXPR
&& integer_onep (TREE_OPERAND (arg01, 0)))
{
- tree tem = fold_build2 (RSHIFT_EXPR, TREE_TYPE (arg01),
+ tree tem = fold_build2_loc (loc, RSHIFT_EXPR, TREE_TYPE (arg01),
arg00, TREE_OPERAND (arg01, 1));
- tem = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg0), tem,
+ tem = fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (arg0), tem,
build_int_cst (TREE_TYPE (arg0), 1));
- return fold_build2 (code, type,
- fold_convert (TREE_TYPE (arg1), tem), arg1);
+ return fold_build2_loc (loc, code, type,
+ fold_convert_loc (loc, TREE_TYPE (arg1), tem),
+ arg1);
}
}
&& integer_pow2p (TREE_OPERAND (arg0, 1)))
{
tree newtype = unsigned_type_for (TREE_TYPE (arg0));
- tree newmod = fold_build2 (TREE_CODE (arg0), newtype,
- fold_convert (newtype,
- TREE_OPERAND (arg0, 0)),
- fold_convert (newtype,
- TREE_OPERAND (arg0, 1)));
+ tree newmod = fold_build2_loc (loc, TREE_CODE (arg0), newtype,
+ fold_convert_loc (loc, newtype,
+ TREE_OPERAND (arg0, 0)),
+ fold_convert_loc (loc, newtype,
+ TREE_OPERAND (arg0, 1)));
- return fold_build2 (code, type, newmod,
- fold_convert (newtype, arg1));
+ return fold_build2_loc (loc, code, type, newmod,
+ fold_convert_loc (loc, newtype, arg1));
}
/* Fold ((X >> C1) & C2) == 0 and ((X >> C1) & C2) != 0 where
can be rewritten as (X & (C2 << C1)) != 0. */
if ((log2 + TREE_INT_CST_LOW (arg001)) < prec)
{
- tem = fold_build2 (LSHIFT_EXPR, itype, arg01, arg001);
- tem = fold_build2 (BIT_AND_EXPR, itype, arg000, tem);
- return fold_build2 (code, type, tem, arg1);
+ 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,
+ fold_convert_loc (loc, itype, arg1));
}
/* Otherwise, for signed (arithmetic) shifts,
((X >> C1) & C2) != 0 is rewritten as X < 0, and
((X >> C1) & C2) == 0 is rewritten as X >= 0. */
else if (!TYPE_UNSIGNED (itype))
- return fold_build2 (code == EQ_EXPR ? GE_EXPR : LT_EXPR, type,
+ return fold_build2_loc (loc, code == EQ_EXPR ? GE_EXPR : LT_EXPR, type,
arg000, build_int_cst (itype, 0));
/* Otherwise, of unsigned (logical) shifts,
((X >> C1) & C2) != 0 is rewritten as (X,false), and
((X >> C1) & C2) == 0 is rewritten as (X,true). */
else
- return omit_one_operand (type,
+ return omit_one_operand_loc (loc, type,
code == EQ_EXPR ? integer_one_node
: integer_zero_node,
arg000);
&& integer_zerop (arg1)
&& TREE_CODE (arg0) == BIT_AND_EXPR
&& integer_onep (TREE_OPERAND (arg0, 1)))
- return fold_convert (type, arg0);
+ 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
&& integer_pow2p (TREE_OPERAND (arg0, 1))
&& operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
- return fold_build2 (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
- arg0, fold_convert (TREE_TYPE (arg0),
- integer_zero_node));
+ return fold_build2_loc (loc, code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
+ arg0, fold_convert_loc (loc, TREE_TYPE (arg0),
+ integer_zero_node));
/* If we have (A & C) != 0 or (A & C) == 0 and C is the sign
bit, then fold the expression into A < 0 or A >= 0. */
- tem = fold_single_bit_test_into_sign_test (code, arg0, arg1, type);
+ tem = fold_single_bit_test_into_sign_test (loc, code, arg0, arg1, type);
if (tem)
return tem;
&& TREE_CODE (arg1) == INTEGER_CST
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
{
- tree notc = fold_build1 (BIT_NOT_EXPR,
+ tree notc = fold_build1_loc (loc, BIT_NOT_EXPR,
TREE_TYPE (TREE_OPERAND (arg0, 1)),
TREE_OPERAND (arg0, 1));
- tree dandnotc = fold_build2 (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 (type, rslt, arg0);
+ return omit_one_operand_loc (loc, type, rslt, arg0);
}
/* If we have (A | C) == D where C & ~D != 0, convert this into 0.
&& TREE_CODE (arg1) == INTEGER_CST
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
{
- tree notd = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (arg1), arg1);
- tree candnotd = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
- TREE_OPERAND (arg0, 1), notd);
+ 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 (type, rslt, arg0);
+ return omit_one_operand_loc (loc, type, rslt, arg0);
}
/* If this is a comparison of a field, we may be able to simplify it. */
to make sure the warnings are given. */
&& (optimize || TREE_CODE (arg1) == INTEGER_CST))
{
- t1 = optimize_bit_field_compare (code, type, arg0, arg1);
+ t1 = optimize_bit_field_compare (loc, code, type, arg0, arg1);
if (t1)
return t1;
}
&& call_expr_nargs (arg0) == 1
&& TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (arg0, 0))) == POINTER_TYPE)
{
- tree iref = build_fold_indirect_ref (CALL_EXPR_ARG (arg0, 0));
- return fold_build2 (code, type, iref,
+ tree iref = build_fold_indirect_ref_loc (loc,
+ CALL_EXPR_ARG (arg0, 0));
+ return fold_build2_loc (loc, code, type, iref,
build_int_cst (TREE_TYPE (iref), 0));
}
}
if (TYPE_UNSIGNED (itype))
{
itype = signed_type_for (itype);
- arg00 = fold_convert (itype, arg00);
+ arg00 = fold_convert_loc (loc, itype, arg00);
}
- return fold_build2 (code == EQ_EXPR ? GE_EXPR : LT_EXPR,
+ return fold_build2_loc (loc, code == EQ_EXPR ? GE_EXPR : LT_EXPR,
type, arg00, build_int_cst (itype, 0));
}
}
/* (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 (code, type, TREE_OPERAND (arg0, 0),
+ 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 (code, type, TREE_OPERAND (arg0, 0),
- build_int_cst (TREE_TYPE (arg1), 0));
+ return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 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 (code, type, TREE_OPERAND (arg0, 1),
- build_int_cst (TREE_TYPE (arg1), 0));
+ return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 1),
+ 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
&& TREE_CODE (arg1) == INTEGER_CST
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
- return fold_build2 (code, type, TREE_OPERAND (arg0, 0),
- fold_build2 (BIT_XOR_EXPR, TREE_TYPE (arg1),
+ 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
&& integer_zerop (arg1)
&& integer_pow2p (TREE_OPERAND (arg0, 1)))
{
- tem = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
- TREE_OPERAND (TREE_OPERAND (arg0, 0), 0),
- TREE_OPERAND (arg0, 1));
- return fold_build2 (code == EQ_EXPR ? NE_EXPR : EQ_EXPR,
- type, tem, arg1);
+ tem = fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (arg0),
+ 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,
+ fold_convert_loc (loc, TREE_TYPE (arg0),
+ arg1));
}
/* Fold ((X & C) ^ C) eq/ne 0 into (X & C) ne/eq 0, when the
TREE_OPERAND (arg0, 1), OEP_ONLY_CONST))
{
tree arg00 = TREE_OPERAND (arg0, 0);
- return fold_build2 (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
+ return fold_build2_loc (loc, code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
arg00, build_int_cst (TREE_TYPE (arg00), 0));
}
TREE_OPERAND (arg0, 1), OEP_ONLY_CONST))
{
tree arg000 = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
- tem = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg000),
+ tem = fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (arg000),
arg000, TREE_OPERAND (arg0, 1));
- return fold_build2 (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
+ return fold_build2_loc (loc, code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
tem, build_int_cst (TREE_TYPE (tem), 0));
}
&& tree_expr_nonzero_p (arg0))
{
tree res = constant_boolean_node (code==NE_EXPR, type);
- return omit_one_operand (type, res, arg0);
+ 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 (code, type,
- TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg1, 0));
+ 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 itype = TREE_TYPE (arg0);
if (operand_equal_p (arg01, arg11, 0))
- return fold_build2 (code, type,
- fold_build2 (BIT_AND_EXPR, itype,
- fold_build2 (BIT_XOR_EXPR, itype,
+ return fold_build2_loc (loc, code, type,
+ fold_build2_loc (loc, BIT_AND_EXPR, itype,
+ fold_build2_loc (loc,
+ BIT_XOR_EXPR, itype,
arg00, arg10),
arg01),
build_int_cst (itype, 0));
if (operand_equal_p (arg01, arg10, 0))
- return fold_build2 (code, type,
- fold_build2 (BIT_AND_EXPR, itype,
- fold_build2 (BIT_XOR_EXPR, itype,
+ return fold_build2_loc (loc, code, type,
+ fold_build2_loc (loc, BIT_AND_EXPR, itype,
+ fold_build2_loc (loc,
+ BIT_XOR_EXPR, itype,
arg00, arg11),
arg01),
build_int_cst (itype, 0));
if (operand_equal_p (arg00, arg11, 0))
- return fold_build2 (code, type,
- fold_build2 (BIT_AND_EXPR, itype,
- fold_build2 (BIT_XOR_EXPR, itype,
+ return fold_build2_loc (loc, code, type,
+ fold_build2_loc (loc, BIT_AND_EXPR, itype,
+ fold_build2_loc (loc,
+ BIT_XOR_EXPR, itype,
arg01, arg10),
arg00),
build_int_cst (itype, 0));
if (operand_equal_p (arg00, arg10, 0))
- return fold_build2 (code, type,
- fold_build2 (BIT_AND_EXPR, itype,
- fold_build2 (BIT_XOR_EXPR, itype,
+ return fold_build2_loc (loc, code, type,
+ fold_build2_loc (loc, BIT_AND_EXPR, itype,
+ fold_build2_loc (loc,
+ BIT_XOR_EXPR, itype,
arg01, arg11),
arg00),
build_int_cst (itype, 0));
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 (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 (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 (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 (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 (code, type,
- fold_build2 (BIT_XOR_EXPR, itype, arg00,
- fold_build2 (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
imag1 = TREE_IMAGPART (arg1);
}
- rcond = fold_binary (code, type, real0, real1);
+ rcond = fold_binary_loc (loc, code, type, real0, real1);
if (rcond && TREE_CODE (rcond) == INTEGER_CST)
{
if (integer_zerop (rcond))
{
if (code == EQ_EXPR)
- return omit_two_operands (type, boolean_false_node,
+ return omit_two_operands_loc (loc, type, boolean_false_node,
imag0, imag1);
- return fold_build2 (NE_EXPR, type, imag0, imag1);
+ return fold_build2_loc (loc, NE_EXPR, type, imag0, imag1);
}
else
{
if (code == NE_EXPR)
- return omit_two_operands (type, boolean_true_node,
+ return omit_two_operands_loc (loc, type, boolean_true_node,
imag0, imag1);
- return fold_build2 (EQ_EXPR, type, imag0, imag1);
+ return fold_build2_loc (loc, EQ_EXPR, type, imag0, imag1);
}
}
- icond = fold_binary (code, type, imag0, imag1);
+ icond = fold_binary_loc (loc, code, type, imag0, imag1);
if (icond && TREE_CODE (icond) == INTEGER_CST)
{
if (integer_zerop (icond))
{
if (code == EQ_EXPR)
- return omit_two_operands (type, boolean_false_node,
+ return omit_two_operands_loc (loc, type, boolean_false_node,
real0, real1);
- return fold_build2 (NE_EXPR, type, real0, real1);
+ return fold_build2_loc (loc, NE_EXPR, type, real0, real1);
}
else
{
if (code == NE_EXPR)
- return omit_two_operands (type, boolean_true_node,
+ return omit_two_operands_loc (loc, type, boolean_true_node,
real0, real1);
- return fold_build2 (EQ_EXPR, type, real0, real1);
+ return fold_build2_loc (loc, EQ_EXPR, type, real0, real1);
}
}
}
case GT_EXPR:
case LE_EXPR:
case GE_EXPR:
- tem = fold_comparison (code, type, op0, op1);
+ tem = fold_comparison (loc, code, type, op0, op1);
if (tem != NULL_TREE)
return tem;
switch (code)
{
case GT_EXPR:
- return omit_one_operand (type, integer_zero_node, arg0);
+ return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
case GE_EXPR:
- return fold_build2 (EQ_EXPR, type, op0, op1);
+ return fold_build2_loc (loc, EQ_EXPR, type, op0, op1);
case LE_EXPR:
- return omit_one_operand (type, integer_one_node, arg0);
+ return omit_one_operand_loc (loc, type, integer_one_node, arg0);
case LT_EXPR:
- return fold_build2 (NE_EXPR, type, op0, op1);
+ return fold_build2_loc (loc, NE_EXPR, type, op0, op1);
/* The GE_EXPR and LT_EXPR cases above are not normally
reached because of previous transformations. */
{
case GT_EXPR:
arg1 = const_binop (PLUS_EXPR, arg1,
- build_int_cst (TREE_TYPE (arg1), 1), 0);
- return fold_build2 (EQ_EXPR, type,
- fold_convert (TREE_TYPE (arg1), arg0),
+ build_int_cst (TREE_TYPE (arg1), 1));
+ return fold_build2_loc (loc, EQ_EXPR, type,
+ fold_convert_loc (loc,
+ TREE_TYPE (arg1), arg0),
arg1);
case LE_EXPR:
arg1 = const_binop (PLUS_EXPR, arg1,
- build_int_cst (TREE_TYPE (arg1), 1), 0);
- return fold_build2 (NE_EXPR, type,
- fold_convert (TREE_TYPE (arg1), arg0),
+ build_int_cst (TREE_TYPE (arg1), 1));
+ return fold_build2_loc (loc, NE_EXPR, type,
+ fold_convert_loc (loc, TREE_TYPE (arg1),
+ arg0),
arg1);
default:
break;
switch (code)
{
case LT_EXPR:
- return omit_one_operand (type, integer_zero_node, arg0);
+ return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
case LE_EXPR:
- return fold_build2 (EQ_EXPR, type, op0, op1);
+ return fold_build2_loc (loc, EQ_EXPR, type, op0, op1);
case GE_EXPR:
- return omit_one_operand (type, integer_one_node, arg0);
+ return omit_one_operand_loc (loc, type, integer_one_node, arg0);
case GT_EXPR:
- return fold_build2 (NE_EXPR, type, op0, op1);
+ return fold_build2_loc (loc, NE_EXPR, type, op0, op1);
default:
break;
switch (code)
{
case GE_EXPR:
- arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
- return fold_build2 (NE_EXPR, type,
- fold_convert (TREE_TYPE (arg1), arg0),
+ arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node);
+ return fold_build2_loc (loc, NE_EXPR, type,
+ fold_convert_loc (loc,
+ TREE_TYPE (arg1), arg0),
arg1);
case LT_EXPR:
- arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
- return fold_build2 (EQ_EXPR, type,
- fold_convert (TREE_TYPE (arg1), arg0),
+ arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node);
+ return fold_build2_loc (loc, EQ_EXPR, type,
+ fold_convert_loc (loc, TREE_TYPE (arg1),
+ arg0),
arg1);
default:
break;
{
tree st;
st = signed_type_for (TREE_TYPE (arg1));
- return fold_build2 (code == LE_EXPR ? GE_EXPR : LT_EXPR,
- type, fold_convert (st, arg0),
+ return fold_build2_loc (loc,
+ code == LE_EXPR ? GE_EXPR : LT_EXPR,
+ type, fold_convert_loc (loc, st, arg0),
build_int_cst (st, 0));
}
}
&& (0 != (tem = negate_expr (arg1)))
&& TREE_CODE (tem) == INTEGER_CST
&& !TREE_OVERFLOW (tem))
- return fold_build2 (TRUTH_ANDIF_EXPR, type,
+ return fold_build2_loc (loc, TRUTH_ANDIF_EXPR, type,
build2 (GE_EXPR, type,
TREE_OPERAND (arg0, 0), tem),
build2 (LE_EXPR, type,
"when simplifying comparison of "
"absolute value and zero"),
WARN_STRICT_OVERFLOW_CONDITIONAL);
- return omit_one_operand (type, integer_one_node, arg0);
+ return omit_one_operand_loc (loc, type, integer_one_node, arg0);
}
/* Convert ABS_EXPR<x> < 0 to false. */
"when simplifying comparison of "
"absolute value and zero"),
WARN_STRICT_OVERFLOW_CONDITIONAL);
- return omit_one_operand (type, integer_zero_node, arg0);
+ return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
}
/* If X is unsigned, convert X < (1 << Y) into X >> Y == 0
&& TYPE_UNSIGNED (TREE_TYPE (arg0))
&& TREE_CODE (arg1) == LSHIFT_EXPR
&& integer_onep (TREE_OPERAND (arg1, 0)))
- return build2 (code == LT_EXPR ? EQ_EXPR : NE_EXPR, type,
- build2 (RSHIFT_EXPR, TREE_TYPE (arg0), arg0,
- TREE_OPERAND (arg1, 1)),
- build_int_cst (TREE_TYPE (arg0), 0));
+ return build2_loc (loc, code == LT_EXPR ? EQ_EXPR : NE_EXPR, type,
+ build2 (RSHIFT_EXPR, TREE_TYPE (arg0), arg0,
+ TREE_OPERAND (arg1, 1)),
+ build_int_cst (TREE_TYPE (arg0), 0));
if ((code == LT_EXPR || code == GE_EXPR)
&& TYPE_UNSIGNED (TREE_TYPE (arg0))
&& CONVERT_EXPR_P (arg1)
&& TREE_CODE (TREE_OPERAND (arg1, 0)) == LSHIFT_EXPR
&& integer_onep (TREE_OPERAND (TREE_OPERAND (arg1, 0), 0)))
- return
- build2 (code == LT_EXPR ? EQ_EXPR : NE_EXPR, type,
- fold_convert (TREE_TYPE (arg0),
- build2 (RSHIFT_EXPR, TREE_TYPE (arg0), arg0,
- TREE_OPERAND (TREE_OPERAND (arg1, 0),
- 1))),
- build_int_cst (TREE_TYPE (arg0), 0));
+ {
+ tem = build2 (RSHIFT_EXPR, TREE_TYPE (arg0), arg0,
+ TREE_OPERAND (TREE_OPERAND (arg1, 0), 1));
+ return build2_loc (loc, code == LT_EXPR ? EQ_EXPR : NE_EXPR, type,
+ fold_convert_loc (loc, TREE_TYPE (arg0), tem),
+ build_int_cst (TREE_TYPE (arg0), 0));
+ }
return NULL_TREE;
t1 = (code == ORDERED_EXPR || code == LTGT_EXPR)
? integer_zero_node
: integer_one_node;
- return omit_one_operand (type, t1, arg1);
+ return omit_one_operand_loc (loc, type, t1, arg1);
}
/* If the second operand is NaN, the result is constant. */
t1 = (code == ORDERED_EXPR || code == LTGT_EXPR)
? integer_zero_node
: integer_one_node;
- return omit_one_operand (type, t1, arg0);
+ return omit_one_operand_loc (loc, type, t1, arg0);
}
/* Simplify unordered comparison of something with itself. */
newtype = TREE_TYPE (targ1);
if (TYPE_PRECISION (newtype) < TYPE_PRECISION (TREE_TYPE (arg0)))
- return fold_build2 (code, type, fold_convert (newtype, targ0),
- fold_convert (newtype, targ1));
+ return fold_build2_loc (loc, code, type,
+ fold_convert_loc (loc, newtype, targ0),
+ fold_convert_loc (loc, newtype, targ1));
}
return NULL_TREE;
return NULL_TREE;
/* Don't let (0, 0) be null pointer constant. */
tem = integer_zerop (arg1) ? build1 (NOP_EXPR, type, arg1)
- : fold_convert (type, arg1);
- return pedantic_non_lvalue (tem);
+ : fold_convert_loc (loc, type, arg1);
+ return pedantic_non_lvalue_loc (loc, tem);
case COMPLEX_EXPR:
if ((TREE_CODE (arg0) == REAL_CST
|| (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
+ && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg0, 0)))
+ == TYPE_MAIN_VARIANT (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:
} /* switch (code) */
}
-/* Callback for walk_tree, looking for LABEL_EXPR.
- Returns tree TP if it is LABEL_EXPR. Otherwise it returns NULL_TREE.
- Do not check the sub-tree of GOTO_EXPR. */
+/* Callback for walk_tree, looking for LABEL_EXPR. Return *TP if it is
+ a LABEL_EXPR; otherwise return NULL_TREE. Do not check the subtrees
+ of GOTO_EXPR. */
static tree
-contains_label_1 (tree *tp,
- int *walk_subtrees,
- void *data ATTRIBUTE_UNUSED)
+contains_label_1 (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
{
switch (TREE_CODE (*tp))
{
case LABEL_EXPR:
return *tp;
+
case GOTO_EXPR:
*walk_subtrees = 0;
- /* no break */
+
+ /* ... fall through ... */
+
default:
return NULL_TREE;
}
}
-/* Checks whether the sub-tree ST contains a label LABEL_EXPR which is
- accessible from outside the sub-tree. Returns NULL_TREE if no
- addressable label is found. */
+/* Return whether the sub-tree ST contains a label which is accessible from
+ outside the sub-tree. */
static bool
contains_label_p (tree st)
{
- return (walk_tree (&st, contains_label_1 , NULL, NULL) != NULL_TREE);
+ return
+ (walk_tree_without_duplicates (&st, contains_label_1 , NULL) != NULL_TREE);
}
/* Fold a ternary expression of code CODE and type TYPE with operands
successful. Otherwise, return NULL_TREE. */
tree
-fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2)
+fold_ternary_loc (location_t loc, enum tree_code code, tree type,
+ tree op0, tree op1, tree op2)
{
tree tem;
- tree arg0 = NULL_TREE, arg1 = NULL_TREE;
+ tree arg0 = NULL_TREE, arg1 = NULL_TREE, arg2 = NULL_TREE;
enum tree_code_class kind = TREE_CODE_CLASS (code);
gcc_assert (IS_EXPR_CODE_CLASS (kind)
STRIP_NOPS (arg1);
}
+ if (op2)
+ {
+ arg2 = op2;
+ STRIP_NOPS (arg2);
+ }
+
switch (code)
{
case COMPONENT_REF:
|| !contains_label_p (unused_op))
&& (! VOID_TYPE_P (TREE_TYPE (tem))
|| VOID_TYPE_P (type)))
- return pedantic_non_lvalue (tem);
+ return pedantic_non_lvalue_loc (loc, tem);
return NULL_TREE;
}
if (operand_equal_p (arg1, op2, 0))
- return pedantic_omit_one_operand (type, arg1, arg0);
+ return pedantic_omit_one_operand_loc (loc, type, arg1, arg0);
/* If we have A op B ? A : C, we may be able to convert this to a
simpler expression, depending on the operation and the values
arg1, TREE_OPERAND (arg0, 1))
&& !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
{
- tem = fold_cond_expr_with_comparison (type, arg0, op1, op2);
+ tem = fold_cond_expr_with_comparison (loc, type, arg0, op1, op2);
if (tem)
return tem;
}
TREE_OPERAND (arg0, 1))
&& !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (op2))))
{
- tem = fold_truth_not_expr (arg0);
+ location_t loc0 = EXPR_LOCATION (arg0);
+ if (loc0 == UNKNOWN_LOCATION)
+ loc0 = loc;
+ tem = fold_truth_not_expr (loc0, arg0);
if (tem && COMPARISON_CLASS_P (tem))
{
- tem = fold_cond_expr_with_comparison (type, tem, op2, op1);
+ tem = fold_cond_expr_with_comparison (loc, type, tem, op2, op1);
if (tem)
return tem;
}
if (truth_value_p (TREE_CODE (arg0))
&& tree_swap_operands_p (op1, op2, false))
{
+ location_t loc0 = EXPR_LOCATION (arg0);
+ if (loc0 == UNKNOWN_LOCATION)
+ loc0 = 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 (arg0);
+ tem = fold_truth_not_expr (loc0, arg0);
if (tem)
- return fold_build3 (code, type, tem, op2, op1);
+ return fold_build3_loc (loc, code, type, tem, op2, op1);
}
/* Convert A ? 1 : 0 to simply A. */
a COND, which will recurse. In that case, the COND_EXPR
is probably the best choice, so leave it alone. */
&& type == TREE_TYPE (arg0))
- return pedantic_non_lvalue (arg0);
+ return pedantic_non_lvalue_loc (loc, arg0);
/* Convert A ? 0 : 1 to !A. This prefers the use of NOT_EXPR
over COND_EXPR in cases such as floating point comparisons. */
if (integer_zerop (op1)
&& integer_onep (op2)
&& truth_value_p (TREE_CODE (arg0)))
- return pedantic_non_lvalue (fold_convert (type,
- invert_truthvalue (arg0)));
+ return pedantic_non_lvalue_loc (loc,
+ fold_convert_loc (loc, type,
+ invert_truthvalue_loc (loc,
+ arg0)));
/* A < 0 ? <sign bit of A> : 0 is simply (A & <sign bit of A>). */
if (TREE_CODE (arg0) == LT_EXPR
&& (TREE_INT_CST_LOW (arg1) & mask_lo) == mask_lo)
{
tem_type = signed_type_for (TREE_TYPE (tem));
- tem = fold_convert (tem_type, tem);
+ tem = fold_convert_loc (loc, tem_type, tem);
}
else if ((TREE_INT_CST_HIGH (arg1) & mask_hi) == 0
&& (TREE_INT_CST_LOW (arg1) & mask_lo) == 0)
{
tem_type = unsigned_type_for (TREE_TYPE (tem));
- tem = fold_convert (tem_type, tem);
+ tem = fold_convert_loc (loc, tem_type, tem);
}
else
tem = NULL;
}
if (tem)
- return fold_convert (type,
- fold_build2 (BIT_AND_EXPR,
- TREE_TYPE (tem), tem,
- fold_convert (TREE_TYPE (tem),
- arg1)));
+ return
+ fold_convert_loc (loc, type,
+ fold_build2_loc (loc, BIT_AND_EXPR,
+ TREE_TYPE (tem), tem,
+ fold_convert_loc (loc,
+ TREE_TYPE (tem),
+ arg1)));
}
/* (A >> N) & 1 ? (1 << N) : 0 is simply A & (1 << N). A & 1 was
&& TREE_CODE (TREE_OPERAND (tem, 1)) == INTEGER_CST
&& (unsigned HOST_WIDE_INT) tree_log2 (arg1) ==
TREE_INT_CST_LOW (TREE_OPERAND (tem, 1)))
- return fold_build2 (BIT_AND_EXPR, type,
+ return fold_build2_loc (loc, BIT_AND_EXPR, type,
TREE_OPERAND (tem, 0), arg1);
}
&& TREE_CODE (TREE_OPERAND (arg0, 0)) == BIT_AND_EXPR
&& operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1),
arg1, OEP_ONLY_CONST))
- return pedantic_non_lvalue (fold_convert (type,
- TREE_OPERAND (arg0, 0)));
+ return pedantic_non_lvalue_loc (loc,
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg0, 0)));
/* Convert A ? B : 0 into A && B if A and B are truth values. */
if (integer_zerop (op2)
&& truth_value_p (TREE_CODE (arg0))
&& truth_value_p (TREE_CODE (arg1)))
- return fold_build2 (TRUTH_ANDIF_EXPR, type,
- fold_convert (type, arg0),
+ return fold_build2_loc (loc, TRUTH_ANDIF_EXPR, type,
+ fold_convert_loc (loc, type, arg0),
arg1);
/* Convert A ? B : 1 into !A || B if A and B are truth values. */
&& truth_value_p (TREE_CODE (arg0))
&& truth_value_p (TREE_CODE (arg1)))
{
+ location_t loc0 = EXPR_LOCATION (arg0);
+ if (loc0 == UNKNOWN_LOCATION)
+ loc0 = loc;
/* Only perform transformation if ARG0 is easily inverted. */
- tem = fold_truth_not_expr (arg0);
+ tem = fold_truth_not_expr (loc0, arg0);
if (tem)
- return fold_build2 (TRUTH_ORIF_EXPR, type,
- fold_convert (type, tem),
+ return fold_build2_loc (loc, TRUTH_ORIF_EXPR, type,
+ fold_convert_loc (loc, type, tem),
arg1);
}
&& truth_value_p (TREE_CODE (arg0))
&& truth_value_p (TREE_CODE (op2)))
{
+ location_t loc0 = EXPR_LOCATION (arg0);
+ if (loc0 == UNKNOWN_LOCATION)
+ loc0 = loc;
/* Only perform transformation if ARG0 is easily inverted. */
- tem = fold_truth_not_expr (arg0);
+ tem = fold_truth_not_expr (loc0, arg0);
if (tem)
- return fold_build2 (TRUTH_ANDIF_EXPR, type,
- fold_convert (type, tem),
+ return fold_build2_loc (loc, TRUTH_ANDIF_EXPR, type,
+ fold_convert_loc (loc, type, tem),
op2);
}
if (integer_onep (arg1)
&& truth_value_p (TREE_CODE (arg0))
&& truth_value_p (TREE_CODE (op2)))
- return fold_build2 (TRUTH_ORIF_EXPR, type,
- fold_convert (type, arg0),
+ return fold_build2_loc (loc, TRUTH_ORIF_EXPR, type,
+ fold_convert_loc (loc, type, arg0),
op2);
return NULL_TREE;
if (elements)
return TREE_VALUE (elements);
else
- return fold_convert (type, integer_zero_node);
+ return build_zero_cst (type);
}
}
if (INTEGRAL_TYPE_P (TREE_TYPE (arg0))
&& TYPE_PRECISION (TREE_TYPE (arg0)) == tree_low_cst (arg1, 1)
&& integer_zerop (op2))
- return fold_convert (type, arg0);
+ return fold_convert_loc (loc, type, arg0);
return NULL_TREE;
+ case FMA_EXPR:
+ /* For integers we can decompose the FMA if possible. */
+ if (TREE_CODE (arg0) == INTEGER_CST
+ && TREE_CODE (arg1) == INTEGER_CST)
+ return fold_build2_loc (loc, PLUS_EXPR, type,
+ const_binop (MULT_EXPR, arg0, arg1), arg2);
+ if (integer_zerop (arg2))
+ return fold_build2_loc (loc, MULT_EXPR, type, arg0, arg1);
+
+ return fold_fma (loc, type, arg0, arg1, arg2);
+
default:
return NULL_TREE;
} /* switch (code) */
enum tree_code code = TREE_CODE (t);
enum tree_code_class kind = TREE_CODE_CLASS (code);
tree tem;
+ location_t loc = EXPR_LOCATION (expr);
/* Return right away if a constant. */
if (kind == tcc_constant)
{
if (code == CALL_EXPR)
{
- tem = fold_call_expr (expr, false);
+ tem = fold_call_expr (loc, expr, false);
return tem ? tem : expr;
}
return expr;
{
case 1:
op0 = TREE_OPERAND (t, 0);
- tem = fold_unary (code, type, op0);
+ tem = fold_unary_loc (loc, code, type, op0);
return tem ? tem : expr;
case 2:
op0 = TREE_OPERAND (t, 0);
op1 = TREE_OPERAND (t, 1);
- tem = fold_binary (code, type, op0, op1);
+ tem = fold_binary_loc (loc, code, type, op0, op1);
return tem ? tem : expr;
case 3:
op0 = TREE_OPERAND (t, 0);
op1 = TREE_OPERAND (t, 1);
op2 = TREE_OPERAND (t, 2);
- tem = fold_ternary (code, type, op0, op1, op2);
+ tem = fold_ternary_loc (loc, code, type, op0, op1, op2);
return tem ? tem : expr;
default:
break;
static void
fold_checksum_tree (const_tree expr, struct md5_ctx *ctx, htab_t ht)
{
- const void **slot;
+ void **slot;
enum tree_code code;
union tree_node buf;
int i, len;
-
+
recursive_label:
gcc_assert ((sizeof (struct tree_exp) + 5 * sizeof (tree)
&& sizeof (struct tree_type) <= sizeof (struct tree_function_decl));
if (expr == NULL)
return;
- slot = (const void **) htab_find_slot (ht, expr, INSERT);
+ slot = (void **) htab_find_slot (ht, expr, INSERT);
if (*slot != NULL)
return;
- *slot = expr;
+ *slot = CONST_CAST_TREE (expr);
code = TREE_CODE (expr);
if (TREE_CODE_CLASS (code) == tcc_declaration
&& DECL_ASSEMBLER_NAME_SET_P (expr))
}
if (CODE_CONTAINS_STRUCT (TREE_CODE (expr), TS_DECL_WITH_VIS))
fold_checksum_tree (DECL_SECTION_NAME (expr), ctx, ht);
-
+
if (CODE_CONTAINS_STRUCT (TREE_CODE (expr), TS_DECL_NON_COMMON))
{
fold_checksum_tree (DECL_VINDEX (expr), ctx, ht);
by "call debug_fold_checksum (op0)", then just trace down till the
outputs differ. */
-void
+DEBUG_FUNCTION void
debug_fold_checksum (const_tree t)
{
int i;
unsigned char checksum[16];
struct md5_ctx ctx;
htab_t ht = htab_create (32, htab_hash_pointer, htab_eq_pointer, NULL);
-
+
md5_init_ctx (&ctx);
fold_checksum_tree (t, &ctx, ht);
md5_finish_ctx (&ctx, checksum);
#endif
/* Fold a unary tree expression with code CODE of type TYPE with an
- operand OP0. Return a folded expression if successful. Otherwise,
- return a tree expression with code CODE of type TYPE with an
- operand OP0. */
+ operand OP0. LOC is the location of the resulting expression.
+ Return a folded expression if successful. Otherwise, return a tree
+ expression with code CODE of type TYPE with an operand OP0. */
tree
-fold_build1_stat (enum tree_code code, tree type, tree op0 MEM_STAT_DECL)
+fold_build1_stat_loc (location_t loc,
+ enum tree_code code, tree type, tree op0 MEM_STAT_DECL)
{
tree tem;
#ifdef ENABLE_FOLD_CHECKING
md5_finish_ctx (&ctx, checksum_before);
htab_empty (ht);
#endif
-
- tem = fold_unary (code, type, op0);
+
+ tem = fold_unary_loc (loc, code, type, op0);
if (!tem)
- tem = build1_stat (code, type, op0 PASS_MEM_STAT);
-
+ tem = build1_stat_loc (loc, code, type, op0 PASS_MEM_STAT);
+
#ifdef ENABLE_FOLD_CHECKING
md5_init_ctx (&ctx);
fold_checksum_tree (op0, &ctx, ht);
}
/* Fold a binary tree expression with code CODE of type TYPE with
- operands OP0 and OP1. Return a folded expression if successful.
- Otherwise, return a tree expression with code CODE of type TYPE
- with operands OP0 and OP1. */
+ operands OP0 and OP1. LOC is the location of the resulting
+ expression. Return a folded expression if successful. Otherwise,
+ return a tree expression with code CODE of type TYPE with operands
+ OP0 and OP1. */
tree
-fold_build2_stat (enum tree_code code, tree type, tree op0, tree op1
- MEM_STAT_DECL)
+fold_build2_stat_loc (location_t loc,
+ enum tree_code code, tree type, tree op0, tree op1
+ MEM_STAT_DECL)
{
tree tem;
#ifdef ENABLE_FOLD_CHECKING
htab_empty (ht);
#endif
- tem = fold_binary (code, type, op0, op1);
+ tem = fold_binary_loc (loc, code, type, op0, op1);
if (!tem)
- tem = build2_stat (code, type, op0, op1 PASS_MEM_STAT);
-
+ tem = build2_stat_loc (loc, code, type, op0, op1 PASS_MEM_STAT);
+
#ifdef ENABLE_FOLD_CHECKING
md5_init_ctx (&ctx);
fold_checksum_tree (op0, &ctx, ht);
if (memcmp (checksum_before_op0, checksum_after_op0, 16))
fold_check_failed (op0, tem);
-
+
md5_init_ctx (&ctx);
fold_checksum_tree (op1, &ctx, ht);
md5_finish_ctx (&ctx, checksum_after_op1);
type TYPE with operands OP0, OP1, and OP2. */
tree
-fold_build3_stat (enum tree_code code, tree type, tree op0, tree op1, tree op2
- MEM_STAT_DECL)
+fold_build3_stat_loc (location_t loc, enum tree_code code, tree type,
+ tree op0, tree op1, tree op2 MEM_STAT_DECL)
{
tree tem;
#ifdef ENABLE_FOLD_CHECKING
#endif
gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp);
- tem = fold_ternary (code, type, op0, op1, op2);
+ tem = fold_ternary_loc (loc, code, type, op0, op1, op2);
if (!tem)
- tem = build3_stat (code, type, op0, op1, op2 PASS_MEM_STAT);
-
+ tem = build3_stat_loc (loc, code, type, op0, op1, op2 PASS_MEM_STAT);
+
#ifdef ENABLE_FOLD_CHECKING
md5_init_ctx (&ctx);
fold_checksum_tree (op0, &ctx, ht);
if (memcmp (checksum_before_op0, checksum_after_op0, 16))
fold_check_failed (op0, tem);
-
+
md5_init_ctx (&ctx);
fold_checksum_tree (op1, &ctx, ht);
md5_finish_ctx (&ctx, checksum_after_op1);
if (memcmp (checksum_before_op1, checksum_after_op1, 16))
fold_check_failed (op1, tem);
-
+
md5_init_ctx (&ctx);
fold_checksum_tree (op2, &ctx, ht);
md5_finish_ctx (&ctx, checksum_after_op2);
of type TYPE from the given operands as constructed by build_call_array. */
tree
-fold_build_call_array (tree type, tree fn, int nargs, tree *argarray)
+fold_build_call_array_loc (location_t loc, tree type, tree fn,
+ int nargs, tree *argarray)
{
tree tem;
#ifdef ENABLE_FOLD_CHECKING
htab_empty (ht);
#endif
- tem = fold_builtin_call_array (type, fn, nargs, argarray);
-
+ tem = fold_builtin_call_array (loc, type, fn, nargs, argarray);
+
#ifdef ENABLE_FOLD_CHECKING
md5_init_ctx (&ctx);
fold_checksum_tree (fn, &ctx, ht);
if (memcmp (checksum_before_fn, checksum_after_fn, 16))
fold_check_failed (fn, tem);
-
+
md5_init_ctx (&ctx);
for (i = 0; i < nargs; i++)
fold_checksum_tree (argarray[i], &ctx, ht);
folding_initializer = saved_folding_initializer;
tree
-fold_build1_initializer (enum tree_code code, tree type, tree op)
+fold_build1_initializer_loc (location_t loc, enum tree_code code,
+ tree type, tree op)
{
tree result;
START_FOLD_INIT;
- result = fold_build1 (code, type, op);
+ result = fold_build1_loc (loc, code, type, op);
END_FOLD_INIT;
return result;
}
tree
-fold_build2_initializer (enum tree_code code, tree type, tree op0, tree op1)
+fold_build2_initializer_loc (location_t loc, enum tree_code code,
+ tree type, tree op0, tree op1)
{
tree result;
START_FOLD_INIT;
- result = fold_build2 (code, type, op0, op1);
+ result = fold_build2_loc (loc, code, type, op0, op1);
END_FOLD_INIT;
return result;
}
tree
-fold_build3_initializer (enum tree_code code, tree type, tree op0, tree op1,
- tree op2)
+fold_build3_initializer_loc (location_t loc, enum tree_code code,
+ tree type, tree op0, tree op1, tree op2)
{
tree result;
START_FOLD_INIT;
- result = fold_build3 (code, type, op0, op1, op2);
+ result = fold_build3_loc (loc, code, type, op0, op1, op2);
END_FOLD_INIT;
return result;
}
tree
-fold_build_call_array_initializer (tree type, tree fn,
- int nargs, tree *argarray)
+fold_build_call_array_initializer_loc (location_t loc, tree type, tree fn,
+ int nargs, tree *argarray)
{
tree result;
START_FOLD_INIT;
- result = fold_build_call_array (type, fn, nargs, argarray);
+ result = fold_build_call_array_loc (loc, type, fn, nargs, argarray);
END_FOLD_INIT;
return result;
&& 0 != (t1 = fold_convert (type,
const_binop (LSHIFT_EXPR,
size_one_node,
- op1, 0)))
+ op1)))
&& !TREE_OVERFLOW (t1))
return multiple_of_p (type, t1, bottom);
}
case SAVE_EXPR:
return multiple_of_p (type, TREE_OPERAND (top, 0), bottom);
+ case COND_EXPR:
+ return (multiple_of_p (type, TREE_OPERAND (top, 1), bottom)
+ && multiple_of_p (type, TREE_OPERAND (top, 2), bottom));
+
case INTEGER_CST:
if (TREE_CODE (bottom) != INTEGER_CST
|| integer_zerop (bottom)
&& (TREE_CODE (op0) == NOP_EXPR || TREE_CODE (op0) == INTEGER_CST)
&& (TREE_CODE (op1) == NOP_EXPR || TREE_CODE (op1) == INTEGER_CST))
{
- tree inner0 = (TREE_CODE (op0) == NOP_EXPR)
+ tree inner0 = (TREE_CODE (op0) == NOP_EXPR)
? TREE_TYPE (TREE_OPERAND (op0, 0))
: TREE_TYPE (op0);
- tree inner1 = (TREE_CODE (op1) == NOP_EXPR)
+ tree inner1 = (TREE_CODE (op1) == NOP_EXPR)
? TREE_TYPE (TREE_OPERAND (op1, 0))
: TREE_TYPE (op1);
case ASSERT_EXPR:
case ADDR_EXPR:
case WITH_SIZE_EXPR:
- case EXC_PTR_EXPR:
case SSA_NAME:
- case FILTER_EXPR:
return tree_single_nonnegative_warnv_p (t, strict_overflow_p);
default:
case ADDR_EXPR:
{
- tree base = get_base_address (TREE_OPERAND (t, 0));
+ tree base = TREE_OPERAND (t, 0);
+ if (!DECL_P (base))
+ base = get_base_address (base);
if (!base)
return false;
allocated on the stack. */
if (DECL_P (base)
&& (flag_delete_null_pointer_checks
- || (TREE_CODE (base) == VAR_DECL && !TREE_STATIC (base))))
+ || (DECL_CONTEXT (base)
+ && TREE_CODE (DECL_CONTEXT (base)) == FUNCTION_DECL
+ && auto_var_in_fn_p (base, DECL_CONTEXT (base)))))
return !VAR_OR_FUNCTION_DECL_P (base) || !DECL_WEAK (base);
/* Constants are never weak. */
case ASSERT_EXPR:
case ADDR_EXPR:
case WITH_SIZE_EXPR:
- case EXC_PTR_EXPR:
case SSA_NAME:
- case FILTER_EXPR:
return tree_single_nonzero_warnv_p (t, strict_overflow_p);
case COMPOUND_EXPR:
tree exp1 = TREE_OPERAND (exp, 0);
tree index;
tree string;
+ location_t loc = EXPR_LOCATION (exp);
if (TREE_CODE (exp) == INDIRECT_REF)
string = string_constant (exp1, &index);
else
{
tree low_bound = array_ref_low_bound (exp);
- index = fold_convert (sizetype, TREE_OPERAND (exp, 1));
+ index = fold_convert_loc (loc, sizetype, TREE_OPERAND (exp, 1));
/* Optimize the special-case of a zero lower bound.
+(INDEX-(unsigned char)1)) becomes ((ARRAY+(-(unsigned char)1))
+INDEX), which becomes (ARRAY+255+INDEX). Oops!) */
if (! integer_zerop (low_bound))
- index = size_diffop (index, fold_convert (sizetype, low_bound));
+ index = size_diffop_loc (loc, index,
+ fold_convert_loc (loc, sizetype, low_bound));
string = exp1;
}
{
case INTEGER_CST:
{
- unsigned HOST_WIDE_INT low;
- HOST_WIDE_INT high;
- int overflow = neg_double (TREE_INT_CST_LOW (arg0),
- TREE_INT_CST_HIGH (arg0),
- &low, &high);
- t = force_fit_type_double (type, low, high, 1,
+ double_int val = tree_to_double_int (arg0);
+ int overflow = neg_double (val.low, val.high, &val.low, &val.high);
+
+ t = force_fit_type_double (type, val, 1,
(overflow | TREE_OVERFLOW (arg0))
&& !TYPE_UNSIGNED (type));
break;
}
case REAL_CST:
- t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
+ t = build_real (type, real_value_negate (&TREE_REAL_CST (arg0)));
break;
case FIXED_CST:
switch (TREE_CODE (arg0))
{
case INTEGER_CST:
- /* If the value is unsigned, then the absolute value is
- the same as the ordinary value. */
- if (TYPE_UNSIGNED (type))
- t = arg0;
- /* Similarly, if the value is non-negative. */
- else if (INT_CST_LT (integer_minus_one_node, arg0))
- t = arg0;
- /* If the value is negative, then the absolute value is
- its negation. */
- else
- {
- unsigned HOST_WIDE_INT low;
- HOST_WIDE_INT high;
- int overflow = neg_double (TREE_INT_CST_LOW (arg0),
- TREE_INT_CST_HIGH (arg0),
- &low, &high);
- t = force_fit_type_double (type, low, high, -1,
- overflow | TREE_OVERFLOW (arg0));
- }
+ {
+ double_int val = tree_to_double_int (arg0);
+
+ /* If the value is unsigned or non-negative, then the absolute value
+ is the same as the ordinary value. */
+ if (TYPE_UNSIGNED (type)
+ || !double_int_negative_p (val))
+ t = arg0;
+
+ /* If the value is negative, then the absolute value is
+ its negation. */
+ else
+ {
+ int overflow;
+
+ overflow = neg_double (val.low, val.high, &val.low, &val.high);
+ t = force_fit_type_double (type, val, -1,
+ overflow | TREE_OVERFLOW (arg0));
+ }
+ }
break;
case REAL_CST:
if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg0)))
- t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
+ t = build_real (type, real_value_negate (&TREE_REAL_CST (arg0)));
else
t = arg0;
break;
constant. TYPE is the type of the result. */
static tree
-fold_not_const (tree arg0, tree type)
+fold_not_const (const_tree arg0, tree type)
{
- tree t = NULL_TREE;
+ double_int val;
gcc_assert (TREE_CODE (arg0) == INTEGER_CST);
- t = force_fit_type_double (type, ~TREE_INT_CST_LOW (arg0),
- ~TREE_INT_CST_HIGH (arg0), 0,
- TREE_OVERFLOW (arg0));
-
- return t;
+ val = double_int_not (tree_to_double_int (arg0));
+ return force_fit_type_double (type, val, 0, TREE_OVERFLOW (arg0));
}
/* Given CODE, a relational operator, the target type, TYPE and two
if (!TREE_SIDE_EFFECTS (op))
return expr;
}
-
+
return build1 (CLEANUP_POINT_EXPR, type, expr);
}
possible. */
tree
-fold_indirect_ref_1 (tree type, tree op0)
+fold_indirect_ref_1 (location_t loc, tree type, tree op0)
{
tree sub = op0;
tree subtype;
}
/* *(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);
- return build4 (ARRAY_REF, type, op, min_val, NULL_TREE, NULL_TREE);
+ 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 *)&complexfoo => __real__ complexfoo */
else if (TREE_CODE (optype) == COMPLEX_TYPE
&& type == TREE_TYPE (optype))
- return fold_build1 (REALPART_EXPR, type, op);
+ return fold_build1_loc (loc, REALPART_EXPR, type, op);
/* *(foo *)&vectorfoo => BIT_FIELD_REF<vectorfoo,...> */
else if (TREE_CODE (optype) == VECTOR_TYPE
&& type == TREE_TYPE (optype))
{
tree part_width = TYPE_SIZE (type);
tree index = bitsize_int (0);
- return fold_build3 (BIT_FIELD_REF, type, op, part_width, index);
- }
- }
-
- /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */
- if (TREE_CODE (sub) == POINTER_PLUS_EXPR
- && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
- {
- tree op00 = TREE_OPERAND (sub, 0);
- tree op01 = TREE_OPERAND (sub, 1);
- tree op00type;
-
- STRIP_NOPS (op00);
- op00type = TREE_TYPE (op00);
- if (TREE_CODE (op00) == ADDR_EXPR
- && TREE_CODE (TREE_TYPE (op00type)) == VECTOR_TYPE
- && type == TREE_TYPE (TREE_TYPE (op00type)))
- {
- HOST_WIDE_INT offset = tree_low_cst (op01, 0);
- tree part_width = TYPE_SIZE (type);
- unsigned HOST_WIDE_INT part_widthi = tree_low_cst (part_width, 0)/BITS_PER_UNIT;
- unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
- tree index = bitsize_int (indexi);
-
- if (offset/part_widthi <= TYPE_VECTOR_SUBPARTS (TREE_TYPE (op00type)))
- return fold_build3 (BIT_FIELD_REF, type, TREE_OPERAND (op00, 0),
- part_width, index);
-
+ return fold_build3_loc (loc, BIT_FIELD_REF, type, op, part_width, index);
}
}
-
- /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
if (TREE_CODE (sub) == POINTER_PLUS_EXPR
&& TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
{
tree op00 = TREE_OPERAND (sub, 0);
tree op01 = TREE_OPERAND (sub, 1);
- tree op00type;
STRIP_NOPS (op00);
- op00type = TREE_TYPE (op00);
- if (TREE_CODE (op00) == ADDR_EXPR
- && TREE_CODE (TREE_TYPE (op00type)) == COMPLEX_TYPE
- && type == TREE_TYPE (TREE_TYPE (op00type)))
+ if (TREE_CODE (op00) == ADDR_EXPR)
{
- tree size = TYPE_SIZE_UNIT (type);
- if (tree_int_cst_equal (size, op01))
- return fold_build1 (IMAGPART_EXPR, type, TREE_OPERAND (op00, 0));
+ tree op00type;
+ op00 = TREE_OPERAND (op00, 0);
+ op00type = TREE_TYPE (op00);
+
+ /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */
+ if (TREE_CODE (op00type) == VECTOR_TYPE
+ && type == TREE_TYPE (op00type))
+ {
+ HOST_WIDE_INT offset = tree_low_cst (op01, 0);
+ tree part_width = TYPE_SIZE (type);
+ unsigned HOST_WIDE_INT part_widthi = tree_low_cst (part_width, 0)/BITS_PER_UNIT;
+ unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
+ tree index = bitsize_int (indexi);
+
+ if (offset/part_widthi <= TYPE_VECTOR_SUBPARTS (op00type))
+ return fold_build3_loc (loc,
+ BIT_FIELD_REF, type, op00,
+ part_width, index);
+
+ }
+ /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
+ else if (TREE_CODE (op00type) == COMPLEX_TYPE
+ && type == TREE_TYPE (op00type))
+ {
+ tree size = TYPE_SIZE_UNIT (type);
+ if (tree_int_cst_equal (size, op01))
+ return fold_build1_loc (loc, IMAGPART_EXPR, type, op00);
+ }
+ /* ((foo *)&fooarray)[1] => fooarray[1] */
+ else if (TREE_CODE (op00type) == ARRAY_TYPE
+ && type == TREE_TYPE (op00type))
+ {
+ tree type_domain = TYPE_DOMAIN (op00type);
+ tree min_val = size_zero_node;
+ if (type_domain && TYPE_MIN_VALUE (type_domain))
+ min_val = TYPE_MIN_VALUE (type_domain);
+ op01 = size_binop_loc (loc, EXACT_DIV_EXPR, op01,
+ TYPE_SIZE_UNIT (type));
+ op01 = size_binop_loc (loc, PLUS_EXPR, op01, min_val);
+ return build4_loc (loc, ARRAY_REF, type, op00, op01,
+ 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;
- sub = build_fold_indirect_ref (sub);
+ sub = build_fold_indirect_ref_loc (loc, sub);
type_domain = TYPE_DOMAIN (TREE_TYPE (sub));
if (type_domain && TYPE_MIN_VALUE (type_domain))
min_val = TYPE_MIN_VALUE (type_domain);
- return build4 (ARRAY_REF, type, sub, min_val, NULL_TREE, NULL_TREE);
+ 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);
}
return NULL_TREE;
cases. */
tree
-build_fold_indirect_ref (tree t)
+build_fold_indirect_ref_loc (location_t loc, tree t)
{
tree type = TREE_TYPE (TREE_TYPE (t));
- tree sub = fold_indirect_ref_1 (type, t);
+ tree sub = fold_indirect_ref_1 (loc, type, t);
if (sub)
return sub;
- else
- return build1 (INDIRECT_REF, type, t);
+
+ return build1_loc (loc, INDIRECT_REF, type, t);
}
/* Given an INDIRECT_REF T, return either T or a simplified version. */
tree
-fold_indirect_ref (tree t)
+fold_indirect_ref_loc (location_t loc, tree t)
{
- tree sub = fold_indirect_ref_1 (TREE_TYPE (t), TREE_OPERAND (t, 0));
+ tree sub = fold_indirect_ref_1 (loc, TREE_TYPE (t), TREE_OPERAND (t, 0));
if (sub)
return sub;
This can only be applied to objects of a sizetype. */
tree
-round_up (tree value, int divisor)
+round_up_loc (location_t loc, tree value, int divisor)
{
tree div = NULL_TREE;
{
if (TREE_CODE (value) == INTEGER_CST)
{
- unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (value);
- unsigned HOST_WIDE_INT high;
+ double_int val = tree_to_double_int (value);
bool overflow_p;
- if ((low & (divisor - 1)) == 0)
+ if ((val.low & (divisor - 1)) == 0)
return value;
overflow_p = TREE_OVERFLOW (value);
- high = TREE_INT_CST_HIGH (value);
- low &= ~(divisor - 1);
- low += divisor;
- if (low == 0)
+ val.low &= ~(divisor - 1);
+ val.low += divisor;
+ if (val.low == 0)
{
- high++;
- if (high == 0)
+ val.high++;
+ if (val.high == 0)
overflow_p = true;
}
- return force_fit_type_double (TREE_TYPE (value), low, high,
+ return force_fit_type_double (TREE_TYPE (value), val,
-1, overflow_p);
}
else
tree t;
t = build_int_cst (TREE_TYPE (value), divisor - 1);
- value = size_binop (PLUS_EXPR, value, t);
+ value = size_binop_loc (loc, PLUS_EXPR, value, t);
t = build_int_cst (TREE_TYPE (value), -divisor);
- value = size_binop (BIT_AND_EXPR, value, t);
+ value = size_binop_loc (loc, BIT_AND_EXPR, value, t);
}
}
else
{
if (!div)
div = build_int_cst (TREE_TYPE (value), divisor);
- value = size_binop (CEIL_DIV_EXPR, value, div);
- value = size_binop (MULT_EXPR, value, div);
+ value = size_binop_loc (loc, CEIL_DIV_EXPR, value, div);
+ value = size_binop_loc (loc, MULT_EXPR, value, div);
}
return value;
/* Likewise, but round down. */
tree
-round_down (tree value, int divisor)
+round_down_loc (location_t loc, tree value, int divisor)
{
tree div = NULL_TREE;
tree t;
t = build_int_cst (TREE_TYPE (value), -divisor);
- value = size_binop (BIT_AND_EXPR, value, t);
+ value = size_binop_loc (loc, BIT_AND_EXPR, value, t);
}
else
{
if (!div)
div = build_int_cst (TREE_TYPE (value), divisor);
- value = size_binop (FLOOR_DIV_EXPR, value, div);
- value = size_binop (MULT_EXPR, value, div);
+ value = size_binop_loc (loc, FLOOR_DIV_EXPR, value, div);
+ value = size_binop_loc (loc, MULT_EXPR, value, div);
}
return value;
enum machine_mode mode;
int unsignedp, volatilep;
HOST_WIDE_INT bitsize;
+ location_t loc = EXPR_LOCATION (exp);
if (TREE_CODE (exp) == ADDR_EXPR)
{
core = get_inner_reference (TREE_OPERAND (exp, 0), &bitsize, pbitpos,
poffset, &mode, &unsignedp, &volatilep,
false);
- core = build_fold_addr_expr (core);
+ core = build_fold_addr_expr_loc (loc, core);
}
else
{
fold_strip_sign_ops (tree exp)
{
tree arg0, arg1;
+ location_t loc = EXPR_LOCATION (exp);
switch (TREE_CODE (exp))
{
arg0 = fold_strip_sign_ops (TREE_OPERAND (exp, 0));
arg1 = fold_strip_sign_ops (TREE_OPERAND (exp, 1));
if (arg0 != NULL_TREE || arg1 != NULL_TREE)
- return fold_build2 (TREE_CODE (exp), TREE_TYPE (exp),
+ return fold_build2_loc (loc, TREE_CODE (exp), TREE_TYPE (exp),
arg0 ? arg0 : TREE_OPERAND (exp, 0),
arg1 ? arg1 : TREE_OPERAND (exp, 1));
break;
arg0 = TREE_OPERAND (exp, 0);
arg1 = fold_strip_sign_ops (TREE_OPERAND (exp, 1));
if (arg1)
- return fold_build2 (COMPOUND_EXPR, TREE_TYPE (exp), arg0, arg1);
+ return fold_build2_loc (loc, COMPOUND_EXPR, TREE_TYPE (exp), arg0, arg1);
break;
-
+
case COND_EXPR:
arg0 = fold_strip_sign_ops (TREE_OPERAND (exp, 1));
arg1 = fold_strip_sign_ops (TREE_OPERAND (exp, 2));
if (arg0 || arg1)
- return fold_build3 (COND_EXPR, TREE_TYPE (exp), TREE_OPERAND (exp, 0),
+ return fold_build3_loc (loc,
+ COND_EXPR, TREE_TYPE (exp), TREE_OPERAND (exp, 0),
arg0 ? arg0 : TREE_OPERAND (exp, 1),
arg1 ? arg1 : TREE_OPERAND (exp, 2));
break;
-
+
case CALL_EXPR:
{
const enum built_in_function fcode = builtin_mathfn_code (exp);
/* Strip copysign function call, return the 1st argument. */
arg0 = CALL_EXPR_ARG (exp, 0);
arg1 = CALL_EXPR_ARG (exp, 1);
- return omit_one_operand (TREE_TYPE (exp), arg0, arg1);
+ return omit_one_operand_loc (loc, TREE_TYPE (exp), arg0, arg1);
default:
/* Strip sign ops from the argument of "odd" math functions. */
{
arg0 = fold_strip_sign_ops (CALL_EXPR_ARG (exp, 0));
if (arg0)
- return build_call_expr (get_callee_fndecl (exp), 1, arg0);
+ return build_call_expr_loc (loc, get_callee_fndecl (exp), 1, arg0);
}
break;
}