/* 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
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 "diagnostic-core.h"
#include "toplev.h"
#include "intl.h"
#include "ggc.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_binop (enum tree_code, tree, tree, int, tree, int);
static tree range_predecessor (tree);
static tree range_successor (tree);
-static tree make_range (tree, int *, tree *, tree *, bool *);
-static tree build_range_check (tree, tree, int, tree, tree);
-static int 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);
+extern tree make_range (tree, int *, tree *, tree *, bool *);
+extern bool merge_ranges (int *, tree *, tree *, int, tree, tree, int,
+ 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);
/* We know that A1 + B1 = SUM1, using 2's complement arithmetic and ignoring
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)
-{
- 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);
-}
-
-/* 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. */
-
-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)
-{
- 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)
- {
- neg_double (l1, h1, &neglow, &neghigh);
- add_double (neglow, neghigh, toplow, tophigh, &toplow, &tophigh);
- }
- return (*hv < 0 ? ~(toplow & tophigh) : toplow | tophigh) != 0;
-}
-\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;
-
- 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;
-}
-\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. */
-static 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
if (fold_deferred_overflow_warning != NULL
&& code != 0
&& code < (int) fold_deferred_overflow_code)
- fold_deferred_overflow_code = code;
+ fold_deferred_overflow_code = (enum warn_strict_overflow_code) code;
return;
}
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 (NEGATE_EXPR, TREE_TYPE (t), t);
+ SET_EXPR_LOCATION (tem, loc);
+ }
+ 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)
{
+ tree tem;
+
if (t1 == 0)
return t2;
else if (t2 == 0)
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)));
+ tem = build2 (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)));
+ tem = build2 (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));
+ tem = build2 (code, type, fold_convert_loc (loc, type, t1),
+ fold_convert_loc (loc, type, t2));
+ goto associate_trees_exit;
}
- 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));
+ associate_trees_exit:
+ protected_set_expr_location (tem, loc);
+ return tem;
}
\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)
{
t = build_fixed (type, result);
/* Propagate overflow flags. */
if (overflow_p | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2))
- {
- TREE_OVERFLOW (t) = 1;
- TREE_CONSTANT_OVERFLOW (t) = 1;
- }
- else if (TREE_CONSTANT_OVERFLOW (arg1) | TREE_CONSTANT_OVERFLOW (arg2))
- TREE_CONSTANT_OVERFLOW (t) = 1;
+ TREE_OVERFLOW (t) = 1;
return t;
}
{
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));
+
+ 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().
- if (INTEGRAL_TYPE_P (TREE_TYPE (r1)))
- code = TRUNC_DIV_EXPR;
+ 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)));
- real = const_binop (code, t1, magsquared, notrunc);
- imag = const_binop (code, t2, magsquared, notrunc);
+ 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;
return build_complex (type, real, imag);
}
+ if (TREE_CODE (arg1) == VECTOR_CST)
+ {
+ tree type = TREE_TYPE(arg1);
+ int count = TYPE_VECTOR_SUBPARTS (type), i;
+ tree elements1, elements2, list = NULL_TREE;
+
+ if(TREE_CODE(arg2) != VECTOR_CST)
+ return NULL_TREE;
+
+ elements1 = TREE_VECTOR_CST_ELTS (arg1);
+ elements2 = TREE_VECTOR_CST_ELTS (arg2);
+
+ for (i = 0; i < count; i++)
+ {
+ tree elem1, elem2, elem;
+
+ /* The trailing elements can be empty and should be treated as 0 */
+ if(!elements1)
+ elem1 = fold_convert_const (NOP_EXPR, TREE_TYPE (type), integer_zero_node);
+ else
+ {
+ elem1 = TREE_VALUE(elements1);
+ elements1 = TREE_CHAIN (elements1);
+ }
+
+ if(!elements2)
+ elem2 = fold_convert_const (NOP_EXPR, TREE_TYPE (type), integer_zero_node);
+ else
+ {
+ elem2 = TREE_VALUE(elements2);
+ elements2 = TREE_CHAIN (elements2);
+ }
+
+ elem = const_binop (code, elem1, elem2);
+
+ /* It is possible that const_binop cannot handle the given
+ code and return NULL_TREE */
+ if(elem == NULL_TREE)
+ return NULL_TREE;
+
+ list = tree_cons (NULL_TREE, elem, list);
+ }
+ return build_vector(type, nreverse(list));
+ }
return NULL_TREE;
}
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));
real_convert (&value, TYPE_MODE (type), &TREE_REAL_CST (arg1));
t = build_real (type, value);
- TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1);
+ /* If converting an infinity or NAN to a representation that doesn't
+ have one, set the overflow bit so that we can produce some kind of
+ error message at the appropriate point if necessary. It's not the
+ most user-friendly message, but it's better than nothing. */
+ if (REAL_VALUE_ISINF (TREE_REAL_CST (arg1))
+ && !MODE_HAS_INFINITIES (TYPE_MODE (type)))
+ TREE_OVERFLOW (t) = 1;
+ else if (REAL_VALUE_ISNAN (TREE_REAL_CST (arg1))
+ && !MODE_HAS_NANS (TYPE_MODE (type)))
+ TREE_OVERFLOW (t) = 1;
+ /* Regular overflow, conversion produced an infinity in a mode that
+ can't represent them. */
+ else if (!MODE_HAS_INFINITIES (TYPE_MODE (type))
+ && REAL_VALUE_ISINF (value)
+ && !REAL_VALUE_ISINF (TREE_REAL_CST (arg1)))
+ TREE_OVERFLOW (t) = 1;
+ else
+ TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1);
return t;
}
t = build_real (type, value);
TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1);
- TREE_CONSTANT_OVERFLOW (t)
- = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
return t;
}
/* Propagate overflow flags. */
if (overflow_p | TREE_OVERFLOW (arg1))
- {
- TREE_OVERFLOW (t) = 1;
- TREE_CONSTANT_OVERFLOW (t) = 1;
- }
- else if (TREE_CONSTANT_OVERFLOW (arg1))
- TREE_CONSTANT_OVERFLOW (t) = 1;
+ TREE_OVERFLOW (t) = 1;
return t;
}
/* Propagate overflow flags. */
if (overflow_p | TREE_OVERFLOW (arg1))
- {
- TREE_OVERFLOW (t) = 1;
- TREE_CONSTANT_OVERFLOW (t) = 1;
- }
- else if (TREE_CONSTANT_OVERFLOW (arg1))
- TREE_CONSTANT_OVERFLOW (t) = 1;
+ TREE_OVERFLOW (t) = 1;
return t;
}
/* Propagate overflow flags. */
if (overflow_p | TREE_OVERFLOW (arg1))
- {
- TREE_OVERFLOW (t) = 1;
- TREE_CONSTANT_OVERFLOW (t) = 1;
- }
- else if (TREE_CONSTANT_OVERFLOW (arg1))
- TREE_CONSTANT_OVERFLOW (t) = 1;
+ TREE_OVERFLOW (t) = 1;
return 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);
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);
+ goto fold_convert_exit;
+ return fold_build1_loc (loc, NOP_EXPR, type, tem);
default:
gcc_unreachable ();
}
+ fold_convert_exit:
+ protected_set_expr_location (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);
+ x = build1 (NON_LVALUE_EXPR, TREE_TYPE (x), x);
+ SET_EXPR_LOCATION (x, loc);
+ return 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);
+ protected_set_expr_location (x, loc);
+ return x;
}
\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)
{
bool honor_nans = HONOR_NANS (TYPE_MODE (TREE_TYPE (ll_arg)));
enum comparison_code lcompcode = comparison_to_compcode (lcode);
enum comparison_code rcompcode = comparison_to_compcode (rcode);
- enum comparison_code compcode;
+ int compcode;
switch (code)
{
else if (compcode == COMPCODE_FALSE)
return constant_boolean_node (false, truth_type);
else
- return fold_build2 (compcode_to_comparison (compcode),
- truth_type, ll_arg, lr_arg);
+ {
+ enum tree_code tcode;
+
+ tcode = compcode_to_comparison ((enum comparison_code) compcode);
+ return fold_build2_loc (loc, tcode, truth_type, ll_arg, lr_arg);
+ }
}
\f
/* Return nonzero if two operands (typically of the same tree node)
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)))
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,
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 COND_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));
+ {
+ t = build1 (NOP_EXPR, void_type_node, fold_ignored_result (omitted));
+ goto omit_one_operand_exit;
+ }
if (TREE_SIDE_EFFECTS (omitted))
- return build2 (COMPOUND_EXPR, type, fold_ignored_result (omitted), t);
+ {
+ t = build2 (COMPOUND_EXPR, type, fold_ignored_result (omitted), t);
+ goto omit_one_operand_exit;
+ }
+
+ return non_lvalue_loc (loc, t);
- return non_lvalue (t);
+ omit_one_operand_exit:
+ protected_set_expr_location (t, loc);
+ return 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));
+ {
+ t = build1 (NOP_EXPR, void_type_node, fold_ignored_result (omitted));
+ goto pedantic_omit_one_operand_exit;
+ }
if (TREE_SIDE_EFFECTS (omitted))
- return build2 (COMPOUND_EXPR, type, fold_ignored_result (omitted), t);
+ {
+ t = build2 (COMPOUND_EXPR, type, fold_ignored_result (omitted), t);
+ goto pedantic_omit_one_operand_exit;
+ }
+
+ return pedantic_non_lvalue_loc (loc, t);
- return pedantic_non_lvalue (t);
+ pedantic_omit_one_operand_exit:
+ protected_set_expr_location (t, loc);
+ return 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 (COMPOUND_EXPR, type, omitted2, t);
+ SET_EXPR_LOCATION (t, loc);
+ }
if (TREE_SIDE_EFFECTS (omitted1))
- t = build2 (COMPOUND_EXPR, type, omitted1, t);
+ {
+ t = build2 (COMPOUND_EXPR, type, omitted1, t);
+ SET_EXPR_LOCATION (t, loc);
+ }
- 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 type = TREE_TYPE (arg);
+ tree t, 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
&& code != ORDERED_EXPR && code != UNORDERED_EXPR
&& code != NE_EXPR && code != EQ_EXPR)
return NULL_TREE;
- else
- {
- code = invert_tree_comparison (code,
- HONOR_NANS (TYPE_MODE (op_type)));
- if (code == ERROR_MARK)
- return NULL_TREE;
- else
- return build2 (code, type,
- TREE_OPERAND (arg, 0), TREE_OPERAND (arg, 1));
- }
+
+ code = invert_tree_comparison (code, HONOR_NANS (TYPE_MODE (op_type)));
+ if (code == ERROR_MARK)
+ return NULL_TREE;
+
+ t = build2 (code, type, TREE_OPERAND (arg, 0), TREE_OPERAND (arg, 1));
+ SET_EXPR_LOCATION (t, loc);
+ return t;
}
switch (code)
return constant_boolean_node (integer_zerop (arg), type);
case TRUTH_AND_EXPR:
- return build2 (TRUTH_OR_EXPR, type,
- invert_truthvalue (TREE_OPERAND (arg, 0)),
- invert_truthvalue (TREE_OPERAND (arg, 1)));
+ loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 0));
+ loc2 = EXPR_LOCATION (TREE_OPERAND (arg, 1));
+ if (loc1 == UNKNOWN_LOCATION)
+ loc1 = loc;
+ if (loc2 == UNKNOWN_LOCATION)
+ loc2 = loc;
+ t = build2 (TRUTH_OR_EXPR, type,
+ invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
+ invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
+ break;
case TRUTH_OR_EXPR:
- return build2 (TRUTH_AND_EXPR, type,
- invert_truthvalue (TREE_OPERAND (arg, 0)),
- invert_truthvalue (TREE_OPERAND (arg, 1)));
+ loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 0));
+ loc2 = EXPR_LOCATION (TREE_OPERAND (arg, 1));
+ if (loc1 == UNKNOWN_LOCATION)
+ loc1 = loc;
+ if (loc2 == UNKNOWN_LOCATION)
+ loc2 = loc;
+ t = build2 (TRUTH_AND_EXPR, type,
+ invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
+ invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
+ break;
case TRUTH_XOR_EXPR:
/* Here we can invert either operand. We invert the first operand
negation of the second operand. */
if (TREE_CODE (TREE_OPERAND (arg, 1)) == TRUTH_NOT_EXPR)
- return build2 (TRUTH_XOR_EXPR, type, TREE_OPERAND (arg, 0),
- TREE_OPERAND (TREE_OPERAND (arg, 1), 0));
+ t = build2 (TRUTH_XOR_EXPR, type, TREE_OPERAND (arg, 0),
+ TREE_OPERAND (TREE_OPERAND (arg, 1), 0));
else
- return build2 (TRUTH_XOR_EXPR, type,
- invert_truthvalue (TREE_OPERAND (arg, 0)),
- TREE_OPERAND (arg, 1));
+ t = build2 (TRUTH_XOR_EXPR, type,
+ invert_truthvalue_loc (loc, TREE_OPERAND (arg, 0)),
+ TREE_OPERAND (arg, 1));
+ break;
case TRUTH_ANDIF_EXPR:
- return build2 (TRUTH_ORIF_EXPR, type,
- invert_truthvalue (TREE_OPERAND (arg, 0)),
- invert_truthvalue (TREE_OPERAND (arg, 1)));
+ loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 0));
+ loc2 = EXPR_LOCATION (TREE_OPERAND (arg, 1));
+ if (loc1 == UNKNOWN_LOCATION)
+ loc1 = loc;
+ if (loc2 == UNKNOWN_LOCATION)
+ loc2 = loc;
+ t = build2 (TRUTH_ORIF_EXPR, type,
+ invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
+ invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
+ break;
case TRUTH_ORIF_EXPR:
- return build2 (TRUTH_ANDIF_EXPR, type,
- invert_truthvalue (TREE_OPERAND (arg, 0)),
- invert_truthvalue (TREE_OPERAND (arg, 1)));
+ loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 0));
+ loc2 = EXPR_LOCATION (TREE_OPERAND (arg, 1));
+ if (loc1 == UNKNOWN_LOCATION)
+ loc1 = loc;
+ if (loc2 == UNKNOWN_LOCATION)
+ loc2 = loc;
+ t = build2 (TRUTH_ANDIF_EXPR, type,
+ invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
+ invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
+ break;
case TRUTH_NOT_EXPR:
return TREE_OPERAND (arg, 0);
{
tree arg1 = TREE_OPERAND (arg, 1);
tree arg2 = TREE_OPERAND (arg, 2);
+
+ loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 1));
+ loc2 = EXPR_LOCATION (TREE_OPERAND (arg, 2));
+ if (loc1 == UNKNOWN_LOCATION)
+ loc1 = loc;
+ if (loc2 == UNKNOWN_LOCATION)
+ loc2 = loc;
+
/* A COND_EXPR may have a throw as one operand, which
then has void type. Just leave void operands
as they are. */
- return build3 (COND_EXPR, type, TREE_OPERAND (arg, 0),
- VOID_TYPE_P (TREE_TYPE (arg1))
- ? arg1 : invert_truthvalue (arg1),
- VOID_TYPE_P (TREE_TYPE (arg2))
- ? arg2 : invert_truthvalue (arg2));
+ t = build3 (COND_EXPR, type, TREE_OPERAND (arg, 0),
+ VOID_TYPE_P (TREE_TYPE (arg1))
+ ? arg1 : invert_truthvalue_loc (loc1, arg1),
+ VOID_TYPE_P (TREE_TYPE (arg2))
+ ? arg2 : invert_truthvalue_loc (loc2, arg2));
+ break;
}
case COMPOUND_EXPR:
- return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg, 0),
- invert_truthvalue (TREE_OPERAND (arg, 1)));
+ loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 1));
+ if (loc1 == UNKNOWN_LOCATION)
+ loc1 = loc;
+ t = build2 (COMPOUND_EXPR, type,
+ TREE_OPERAND (arg, 0),
+ invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 1)));
+ break;
case NON_LVALUE_EXPR:
- return invert_truthvalue (TREE_OPERAND (arg, 0));
+ loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 0));
+ if (loc1 == UNKNOWN_LOCATION)
+ loc1 = loc;
+ return invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0));
- case NOP_EXPR:
+ CASE_CONVERT:
if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
- return build1 (TRUTH_NOT_EXPR, type, arg);
+ {
+ t = build1 (TRUTH_NOT_EXPR, type, arg);
+ break;
+ }
+
+ /* ... fall through ... */
- case CONVERT_EXPR:
case FLOAT_EXPR:
- return build1 (TREE_CODE (arg), type,
- invert_truthvalue (TREE_OPERAND (arg, 0)));
+ loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 0));
+ if (loc1 == UNKNOWN_LOCATION)
+ loc1 = loc;
+ t = build1 (TREE_CODE (arg), type,
+ invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)));
+ break;
case BIT_AND_EXPR:
if (!integer_onep (TREE_OPERAND (arg, 1)))
- break;
- return build2 (EQ_EXPR, type, arg,
- build_int_cst (type, 0));
+ return NULL_TREE;
+ t = build2 (EQ_EXPR, type, arg, build_int_cst (type, 0));
+ break;
case SAVE_EXPR:
- return build1 (TRUTH_NOT_EXPR, type, arg);
+ t = build1 (TRUTH_NOT_EXPR, type, arg);
+ break;
case CLEANUP_POINT_EXPR:
- return build1 (CLEANUP_POINT_EXPR, type,
- invert_truthvalue (TREE_OPERAND (arg, 0)));
+ loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 0));
+ if (loc1 == UNKNOWN_LOCATION)
+ loc1 = loc;
+ t = build1 (CLEANUP_POINT_EXPR, type,
+ invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)));
+ break;
default:
+ t = NULL_TREE;
break;
}
- return NULL_TREE;
+ if (t)
+ SET_EXPR_LOCATION (t, loc);
+
+ 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 (TRUTH_NOT_EXPR, TREE_TYPE (arg), arg);
+ SET_EXPR_LOCATION (tem, loc);
+ }
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;
result = build3 (BIT_FIELD_REF, bftype, inner,
size_int (bitsize), bitsize_int (bitpos));
+ SET_EXPR_LOCATION (result, loc);
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 (code, compare_type,
+ build2 (BIT_AND_EXPR, unsigned_type, lhs, mask),
+ rhs);
+ SET_EXPR_LOCATION (lhs, loc);
+ 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
because signed overflow is undefined; otherwise, do not change
*STRICT_OVERFLOW_P. */
-static tree
+tree
make_range (tree exp, int *pin_p, tree *plow, tree *phigh,
bool *strict_overflow_p)
{
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));
+ SET_EXPR_LOCATION (exp, loc);
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;
type, TYPE, return an expression to test if EXP is in (or out of, depending
on IN_P) the range. Return 0 if the test couldn't be created. */
-static tree
-build_range_check (tree type, tree exp, int in_p, tree low, tree high)
+tree
+build_range_check (location_t loc, tree type, tree exp, int in_p,
+ tree low, tree high)
{
- tree etype = TREE_TYPE (exp);
- tree value;
+ tree etype = TREE_TYPE (exp), value;
#ifdef HAVE_canonicalize_funcptr_for_compare
/* Disable this optimization for function pointer expressions
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));
}
}
/* Optimize (c>=low) && (c<=high) into (c-low>=0) && (c-low<=high-low).
- This requires wrap-around arithmetics for the type of the expression. */
- switch (TREE_CODE (etype))
- {
- case INTEGER_TYPE:
- /* There is no requirement that LOW be within the range of ETYPE
- if the latter is a subtype. It must, however, be within the base
- type of ETYPE. So be sure we do the subtraction in that type. */
- if (TREE_TYPE (etype))
- etype = TREE_TYPE (etype);
- break;
+ This requires wrap-around arithmetics for the type of the expression.
+ First make sure that arithmetics in this type is valid, then make sure
+ that it wraps around. */
+ if (TREE_CODE (etype) == ENUMERAL_TYPE || TREE_CODE (etype) == BOOLEAN_TYPE)
+ etype = lang_hooks.types.type_for_size (TYPE_PRECISION (etype),
+ TYPE_UNSIGNED (etype));
- case ENUMERAL_TYPE:
- case BOOLEAN_TYPE:
- etype = lang_hooks.types.type_for_size (TYPE_PRECISION (etype),
- TYPE_UNSIGNED (etype));
- break;
-
- default:
- break;
- }
-
- /* If we don't have wrap-around arithmetics upfront, try to force it. */
- if (TREE_CODE (etype) == INTEGER_TYPE
- && !TYPE_OVERFLOW_WRAPS (etype))
+ if (TREE_CODE (etype) == INTEGER_TYPE && !TYPE_OVERFLOW_WRAPS (etype))
{
tree utype, minv, maxv;
/* 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;
/* Given two ranges, see if we can merge them into one. Return 1 if we
can, 0 if we can't. Set the output range into the specified parameters. */
-static int
+bool
merge_ranges (int *pin_p, tree *plow, tree *phigh, int in0_p, tree low0,
tree high0, int in1_p, tree low1, tree high1)
{
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:
- /* If C1 is C2 - 1, this is max(A, C2). */
+ /* If C1 is C2 - 1, this is max(A, C2), but use ARG00's type for
+ MAX_EXPR, to preserve the signedness of the comparison. */
if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type),
OEP_ONLY_CONST)
&& operand_equal_p (arg01,
const_binop (MINUS_EXPR, arg2,
- build_int_cst (type, 1), 0),
+ build_int_cst (type, 1)),
OEP_ONLY_CONST))
- return pedantic_non_lvalue (fold_build2 (MAX_EXPR,
- type,
- fold_convert (type, arg1),
- 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:
- /* If C1 is C2 + 1, this is max(A, C2). */
+ /* If C1 is C2 + 1, this is max(A, C2), with the same care as above. */
if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type),
OEP_ONLY_CONST)
&& operand_equal_p (arg01,
const_binop (PLUS_EXPR, arg2,
- build_int_cst (type, 1), 0),
+ build_int_cst (type, 1)),
OEP_ONLY_CONST))
- return pedantic_non_lvalue (fold_build2 (MAX_EXPR,
- type,
- fold_convert (type, arg1),
- 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);
+ {
+ tem = build2 (code == TRUTH_ANDIF_EXPR
+ ? TRUTH_AND_EXPR : TRUTH_OR_EXPR,
+ type, op0, op1);
+ SET_EXPR_LOCATION (tem, loc);
+ return tem;
+ }
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);
+ tem = build2 (code == TRUTH_ANDIF_EXPR
+ ? TRUTH_AND_EXPR : TRUTH_OR_EXPR,
+ type, lhs, rhs);
+ SET_EXPR_LOCATION (tem, loc);
+ return tem;
}
}
}
/* 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 (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));
+ {
+ result = 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));
+ goto fold_truthop_exit;
+ }
/* 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));
+ {
+ result = 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));
+ goto fold_truthop_exit;
+ }
if (LOGICAL_OP_NON_SHORT_CIRCUIT)
{
if (code != orig_code || lhs != orig_lhs || rhs != orig_rhs)
- return build2 (code, truth_type, lhs, rhs);
+ {
+ result = build2 (code, truth_type, lhs, rhs);
+ goto fold_truthop_exit;
+ }
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);
+ result = build2 (wanted_code, truth_type, lhs, rhs);
+ goto fold_truthop_exit;
}
/* 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);
+ result = build2 (wanted_code, truth_type, lhs, rhs);
+ goto fold_truthop_exit;
}
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 (BIT_AND_EXPR, lntype, result, ll_mask);
+ SET_EXPR_LOCATION (result, loc);
+ }
- return build2 (wanted_code, truth_type, result,
- const_binop (BIT_IOR_EXPR, l_const, r_const, 0));
+ result = build2 (wanted_code, truth_type, result,
+ const_binop (BIT_IOR_EXPR, l_const, r_const));
+
+ fold_truthop_exit:
+ SET_EXPR_LOCATION (result, loc);
+ return result;
}
\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;
if (TYPE_PRECISION (inner_type) != TYPE_PRECISION (outer_type))
return NULL_TREE;
- /* If the conversion is from an integral subtype to its basetype
- leave it alone. */
- if (TREE_TYPE (inner_type) == outer_type)
- return NULL_TREE;
-
if (TREE_CODE (arg1) != INTEGER_CST
&& !(CONVERT_EXPR_P (arg1)
&& TREE_TYPE (TREE_OPERAND (arg1, 0)) == inner_type))
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;
else
maybe_same = arg11;
- if (exact_log2 (abs (int11)) > 0 && int01 % int11 == 0)
+ if (exact_log2 (abs (int11)) > 0 && int01 % int11 == 0
+ /* The remainder should not be a constant, otherwise we
+ end up folding i * 4 + 2 to (i * 2 + 1) * 2 which has
+ increased the number of multiplications necessary. */
+ && TREE_CODE (arg10) != INTEGER_CST)
{
- alt0 = fold_build2 (MULT_EXPR, TREE_TYPE (arg00), arg00,
+ 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 (NOP_EXPR, ptrtype, t);
+ SET_EXPR_LOCATION (t, loc);
+ }
+ }
+ 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_loc (loc, TREE_OPERAND (t, 0));
+
+ if (TREE_TYPE (t) != ptrtype)
+ t = fold_convert_loc (loc, ptrtype, t);
}
else
- t = build1 (ADDR_EXPR, ptrtype, t);
+ {
+ t = build1 (ADDR_EXPR, ptrtype, t);
+ SET_EXPR_LOCATION (t, loc);
+ }
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 (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)));
+ SET_EXPR_LOCATION (tem, loc);
+ }
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);
TREE_NO_WARNING (tem) = 1;
TREE_USED (tem) = 1;
+ SET_EXPR_LOCATION (tem, loc);
return tem;
}
transformation effectively doesn't preserve non-maximal ranges. */
if (TREE_CODE (type) == INTEGER_TYPE
&& TREE_CODE (op0) == BIT_AND_EXPR
- && TREE_CODE (TREE_OPERAND (op0, 1)) == INTEGER_CST
- /* Not if the conversion is to the sub-type. */
- && TREE_TYPE (type) != TREE_TYPE (op0))
+ && 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. */
|| POINTER_TYPE_P (type))
&& (INTEGRAL_TYPE_P (TREE_TYPE (op0))
|| POINTER_TYPE_P (TREE_TYPE (op0)))
- && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (op0))
- /* Do not muck with VIEW_CONVERT_EXPRs that convert from
- a sub-type to its base type as generated by the Ada FE. */
- && !(INTEGRAL_TYPE_P (TREE_TYPE (op0))
- && TREE_TYPE (TREE_TYPE (op0))))
- return fold_convert (type, op0);
+ && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_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 fold_convert_loc (loc, type, integer_zero_node);
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 "
+ fold_overflow_warning ("assuming signed overflow does not occur "
"when changing X +- C1 cmp C2 to "
- "X cmp C1 +- C2"),
+ "X cmp C1 +- C2",
WARN_STRICT_OVERFLOW_COMPARISON);
- return fold_build2 (code, type, variable, lhs);
+ 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,
+ fold_convert_loc (loc, itype, integer_zero_node));
}
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;
/* 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);
+ tem = build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0), tem);
+ goto fold_binary_exit;
+ }
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)));
+ tem = build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0), tem);
+ goto fold_binary_exit;
+ }
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
+ 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 (LROTATE_EXPR,
+ TREE_TYPE (TREE_OPERAND (arg0, 0)),
+ TREE_OPERAND (arg0, 0),
+ code0 == LSHIFT_EXPR
+ ? tree01 : tree11);
+ SET_EXPR_LOCATION (tem, loc);
+ 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 fold_convert_loc (loc, type, integer_zero_node);
/* 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));
+
}
}
- if (flag_unsafe_math_optimizations
+ if (FLOAT_TYPE_P (type)
+ && flag_unsafe_math_optimizations
&& (TREE_CODE (arg0) == RDIV_EXPR || TREE_CODE (arg0) == MULT_EXPR)
&& (TREE_CODE (arg1) == RDIV_EXPR || TREE_CODE (arg1) == MULT_EXPR)
- && (tem = distribute_real_division (code, type, arg0, arg1)))
+ && (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);
- /* In IEEE floating point, x*1 is not equivalent to x for snans. */
+ 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 = fold_convert_loc (loc, type, integer_zero_node);
+ 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 = fold_convert_loc (loc, type, integer_zero_node);
+ 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));
- 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 = fold_convert_loc (loc, type, integer_zero_node);
+ 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 = fold_convert_loc (loc, type, integer_zero_node);
+ 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));
}
- 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 (prec < HOST_BITS_PER_WIDE_INT
|| newmask == ~(unsigned HOST_WIDE_INT) 0)
{
+ tree newmaskt;
+
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;
- return fold_build2 (BIT_AND_EXPR, type, tem,
- build_int_cst_type (TREE_TYPE (op1),
- newmask));
+ newmaskt = build_int_cst_type (TREE_TYPE (op1), newmask);
+ if (!tree_int_cst_equal (newmaskt, arg1))
+ return fold_build2_loc (loc, BIT_AND_EXPR, type, tem, newmaskt);
}
}
}
{
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;
"occur when simplifying A / (B << N)"),
WARN_STRICT_OVERFLOW_MISC);
- sh_cnt = fold_build2 (PLUS_EXPR, TREE_TYPE (sh_cnt),
+ sh_cnt = fold_build2_loc (loc, 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);
+ 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 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);
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);
+ 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
&& 0 != (tem = negate_expr (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 +- C CMP X. */
- if ((TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
+ /* Transform comparisons of the form X +- Y CMP X to Y CMP 0. */
+ if ((TREE_CODE (arg0) == PLUS_EXPR
+ || TREE_CODE (arg0) == POINTER_PLUS_EXPR
+ || TREE_CODE (arg0) == MINUS_EXPR)
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
&& (INTEGRAL_TYPE_P (TREE_TYPE (arg0))
|| POINTER_TYPE_P (TREE_TYPE (arg0))))
{
- tree cst = TREE_OPERAND (arg0, 1);
+ tree val = TREE_OPERAND (arg0, 1);
+ return omit_two_operands_loc (loc, type,
+ fold_build2_loc (loc, code, type,
+ val,
+ build_int_cst (TREE_TYPE (val),
+ 0)),
+ TREE_OPERAND (arg0, 0), arg1);
+ }
- if (code == EQ_EXPR
- && !integer_zerop (cst))
- return omit_two_operands (type, boolean_false_node,
- TREE_OPERAND (arg0, 0), arg1);
- else
- return omit_two_operands (type, boolean_true_node,
- TREE_OPERAND (arg0, 0), arg1);
+ /* Transform comparisons of the form C - X CMP X if C % 2 == 1. */
+ if (TREE_CODE (arg0) == MINUS_EXPR
+ && TREE_CODE (TREE_OPERAND (arg0, 0)) == INTEGER_CST
+ && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0)
+ && (TREE_INT_CST_LOW (TREE_OPERAND (arg0, 0)) & 1) == 1)
+ {
+ return omit_two_operands_loc (loc, type,
+ code == NE_EXPR
+ ? boolean_true_node : boolean_false_node,
+ TREE_OPERAND (arg0, 1), arg1);
}
/* If we have X - Y == 0, we can convert that to X == Y and similarly
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, 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),
+ tree dandnotc = fold_build2_loc (loc, BIT_AND_EXPR, 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 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), 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),
+ return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0),
build_int_cst (TREE_TYPE (arg1), 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),
+ return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 1),
build_int_cst (TREE_TYPE (arg1), 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),
+ 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 (code == EQ_EXPR ? NE_EXPR : EQ_EXPR,
+ return fold_build2_loc (loc, code == EQ_EXPR ? NE_EXPR : EQ_EXPR,
type, tem, arg1);
}
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,
+ return fold_build2_loc (loc, code, type,
TREE_OPERAND (arg0, 0),
TREE_OPERAND (arg1, 0));
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, arg10);
if (operand_equal_p (arg01, arg10, 0))
- return fold_build2 (code, type, arg00, arg11);
+ return fold_build2_loc (loc, code, 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, arg10);
if (operand_equal_p (arg00, arg10, 0))
- return fold_build2 (code, type, arg01, arg11);
+ return fold_build2_loc (loc, code, 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,
+ return fold_build2_loc (loc, code, type,
+ fold_build2_loc (loc, BIT_XOR_EXPR, itype, arg00,
+ fold_build2_loc (loc,
+ BIT_XOR_EXPR, itype,
arg01, arg11)),
arg10);
}
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));
+ {
+ tem = 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));
+ goto fold_binary_exit;
+ }
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 (code == LT_EXPR ? EQ_EXPR : NE_EXPR, type,
+ fold_convert_loc (loc, TREE_TYPE (arg0),
+ build2 (RSHIFT_EXPR,
+ TREE_TYPE (arg0), arg0,
+ TREE_OPERAND (TREE_OPERAND (arg1, 0),
+ 1))),
+ build_int_cst (TREE_TYPE (arg0), 0));
+ goto fold_binary_exit;
+ }
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
default:
return NULL_TREE;
} /* switch (code) */
+ fold_binary_exit:
+ protected_set_expr_location (tem, loc);
+ return tem;
}
-/* 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;
|| !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);
+ tem = fold_truth_not_expr (loc, 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;
}
/* 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 (loc, 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 (arg1)))
{
/* Only perform transformation if ARG0 is easily inverted. */
- tem = fold_truth_not_expr (arg0);
+ tem = fold_truth_not_expr (loc, 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 (op2)))
{
/* Only perform transformation if ARG0 is easily inverted. */
- tem = fold_truth_not_expr (arg0);
+ tem = fold_truth_not_expr (loc, 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 fold_convert_loc (loc, type, integer_zero_node);
}
}
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;
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 (code, type, op0 PASS_MEM_STAT);
+ SET_EXPR_LOCATION (tem, loc);
+ }
+
#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 (code, type, op0, op1 PASS_MEM_STAT);
+ SET_EXPR_LOCATION (tem, loc);
+ }
+
#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 (code, type, op0, op1, op2 PASS_MEM_STAT);
+ SET_EXPR_LOCATION (tem, loc);
+ }
+
#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;
- /* Weak declarations may link to NULL. */
- if (VAR_OR_FUNCTION_DECL_P (base))
- return !DECL_WEAK (base);
+ /* Weak declarations may link to NULL. Other things may also be NULL
+ so protect with -fdelete-null-pointer-checks; but not variables
+ allocated on the stack. */
+ if (DECL_P (base)
+ && (flag_delete_null_pointer_checks
+ || (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. */
if (CONSTANT_CLASS_P (base))
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:
t = build_fixed (type, f);
/* Propagate overflow flags. */
if (overflow_p | TREE_OVERFLOW (arg0))
- {
- TREE_OVERFLOW (t) = 1;
- TREE_CONSTANT_OVERFLOW (t) = 1;
- }
- else if (TREE_CONSTANT_OVERFLOW (arg0))
- TREE_CONSTANT_OVERFLOW (t) = 1;
+ TREE_OVERFLOW (t) = 1;
break;
}
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;
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);
+ op0 = build4 (ARRAY_REF, type, op, min_val, NULL_TREE, NULL_TREE);
+ SET_EXPR_LOCATION (op0, loc);
+ return op0;
}
/* *(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);
+ return fold_build3_loc (loc, 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;
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),
+ return fold_build3_loc (loc,
+ BIT_FIELD_REF, type, TREE_OPERAND (op00, 0),
part_width, index);
-
+
}
}
{
tree size = TYPE_SIZE_UNIT (type);
if (tree_int_cst_equal (size, op01))
- return fold_build1 (IMAGPART_EXPR, type, TREE_OPERAND (op00, 0));
+ return fold_build1_loc (loc, IMAGPART_EXPR, type,
+ TREE_OPERAND (op00, 0));
}
}
-
+
/* *(foo *)fooarrptr => (*fooarrptr)[0] */
if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
&& type == TREE_TYPE (TREE_TYPE (subtype)))
{
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);
+ op0 = build4 (ARRAY_REF, type, sub, min_val, NULL_TREE, NULL_TREE);
+ SET_EXPR_LOCATION (op0, loc);
+ return op0;
}
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);
+
+ t = build1 (INDIRECT_REF, type, t);
+ SET_EXPR_LOCATION (t, loc);
+ return 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;
}