/* Fold a constant sub-tree into a single node for C-compiler
- Copyright (C) 1987, 88, 92-98, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2000 Free Software Foundation, Inc.
This file is part of GNU CC.
#include "toplev.h"
#include "ggc.h"
-static void encode PROTO((HOST_WIDE_INT *,
- HOST_WIDE_INT, HOST_WIDE_INT));
-static void decode PROTO((HOST_WIDE_INT *,
- HOST_WIDE_INT *, HOST_WIDE_INT *));
-int div_and_round_double PROTO((enum tree_code, int, HOST_WIDE_INT,
- HOST_WIDE_INT, HOST_WIDE_INT,
- HOST_WIDE_INT, HOST_WIDE_INT *,
- HOST_WIDE_INT *, HOST_WIDE_INT *,
- HOST_WIDE_INT *));
-static tree negate_expr PROTO((tree));
-static tree split_tree PROTO((tree, enum tree_code, tree *, tree *,
- int));
-static tree associate_trees PROTO((tree, tree, enum tree_code, tree));
-static tree int_const_binop PROTO((enum tree_code, tree, tree, int, int));
-static void const_binop_1 PROTO((PTR));
-static tree const_binop PROTO((enum tree_code, tree, tree, int));
-static void fold_convert_1 PROTO((PTR));
-static tree fold_convert PROTO((tree, tree));
-static enum tree_code invert_tree_comparison PROTO((enum tree_code));
-static enum tree_code swap_tree_comparison PROTO((enum tree_code));
-static int truth_value_p PROTO((enum tree_code));
-static int operand_equal_for_comparison_p PROTO((tree, tree, tree));
-static int twoval_comparison_p PROTO((tree, tree *, tree *, int *));
-static tree eval_subst PROTO((tree, tree, tree, tree, tree));
-static tree omit_one_operand PROTO((tree, tree, tree));
-static tree pedantic_omit_one_operand PROTO((tree, tree, tree));
-static tree distribute_bit_expr PROTO((enum tree_code, tree, tree, tree));
-static tree make_bit_field_ref PROTO((tree, tree, int, int, int));
-static tree optimize_bit_field_compare PROTO((enum tree_code, tree,
- tree, tree));
-static tree decode_field_reference PROTO((tree, int *, int *,
- enum machine_mode *, int *,
- int *, tree *, tree *));
-static int all_ones_mask_p PROTO((tree, int));
-static int simple_operand_p PROTO((tree));
-static tree range_binop PROTO((enum tree_code, tree, tree, int,
- tree, int));
-static tree make_range PROTO((tree, int *, tree *, tree *));
-static tree build_range_check PROTO((tree, tree, int, tree, tree));
-static int merge_ranges PROTO((int *, tree *, tree *, int, tree, tree,
+static void encode PARAMS ((HOST_WIDE_INT *,
+ unsigned HOST_WIDE_INT,
+ HOST_WIDE_INT));
+static void decode PARAMS ((HOST_WIDE_INT *,
+ unsigned HOST_WIDE_INT *,
+ HOST_WIDE_INT *));
+static tree negate_expr PARAMS ((tree));
+static tree split_tree PARAMS ((tree, enum tree_code, tree *, tree *,
+ int));
+static tree associate_trees PARAMS ((tree, tree, enum tree_code, tree));
+static tree int_const_binop PARAMS ((enum tree_code, tree, tree, int, int));
+static void const_binop_1 PARAMS ((PTR));
+static tree const_binop PARAMS ((enum tree_code, tree, tree, int));
+static void fold_convert_1 PARAMS ((PTR));
+static tree fold_convert PARAMS ((tree, tree));
+static enum tree_code invert_tree_comparison PARAMS ((enum tree_code));
+static enum tree_code swap_tree_comparison PARAMS ((enum tree_code));
+static int truth_value_p PARAMS ((enum tree_code));
+static int operand_equal_for_comparison_p PARAMS ((tree, tree, tree));
+static int twoval_comparison_p PARAMS ((tree, tree *, tree *, int *));
+static tree eval_subst PARAMS ((tree, tree, tree, tree, tree));
+static tree omit_one_operand PARAMS ((tree, tree, tree));
+static tree pedantic_omit_one_operand PARAMS ((tree, tree, tree));
+static tree distribute_bit_expr PARAMS ((enum tree_code, tree, tree, tree));
+static tree make_bit_field_ref PARAMS ((tree, tree, int, int, int));
+static tree optimize_bit_field_compare PARAMS ((enum tree_code, tree,
+ tree, tree));
+static tree decode_field_reference PARAMS ((tree, HOST_WIDE_INT *,
+ HOST_WIDE_INT *,
+ enum machine_mode *, int *,
+ int *, tree *, tree *));
+static int all_ones_mask_p PARAMS ((tree, int));
+static int simple_operand_p PARAMS ((tree));
+static tree range_binop PARAMS ((enum tree_code, tree, tree, int,
+ tree, int));
+static tree make_range PARAMS ((tree, int *, tree *, tree *));
+static tree build_range_check PARAMS ((tree, tree, int, tree, tree));
+static int merge_ranges PARAMS ((int *, tree *, tree *, int, tree, tree,
int, tree, tree));
-static tree fold_range_test PROTO((tree));
-static tree unextend PROTO((tree, int, int, tree));
-static tree fold_truthop PROTO((enum tree_code, tree, tree, tree));
-static tree optimize_minmax_comparison PROTO((tree));
-static tree extract_muldiv PROTO((tree, tree, enum tree_code, tree));
-static tree strip_compound_expr PROTO((tree, tree));
-static int multiple_of_p PROTO((tree, tree, tree));
-static tree constant_boolean_node PROTO((int, tree));
-static int count_cond PROTO((tree, int));
+static tree fold_range_test PARAMS ((tree));
+static tree unextend PARAMS ((tree, int, int, tree));
+static tree fold_truthop PARAMS ((enum tree_code, tree, tree, tree));
+static tree optimize_minmax_comparison PARAMS ((tree));
+static tree extract_muldiv PARAMS ((tree, tree, enum tree_code, tree));
+static tree strip_compound_expr PARAMS ((tree, tree));
+static int multiple_of_p PARAMS ((tree, tree, tree));
+static tree constant_boolean_node PARAMS ((int, tree));
+static int count_cond PARAMS ((tree, int));
#ifndef BRANCH_COST
#define BRANCH_COST 1
#endif
+#if defined(HOST_EBCDIC)
+/* bit 8 is significant in EBCDIC */
+#define CHARMASK 0xff
+#else
+#define CHARMASK 0x7f
+#endif
+
+
/* We know that A1 + B1 = SUM1, using 2's complement arithmetic and ignoring
overflow. Suppose A, B and SUM have the same respective signs as A1, B1,
and SUM1. Then this yields nonzero if overflow occurred during the
static void
encode (words, low, hi)
HOST_WIDE_INT *words;
- HOST_WIDE_INT low, hi;
+ unsigned HOST_WIDE_INT low;
+ HOST_WIDE_INT hi;
{
words[0] = LOWPART (low);
words[1] = HIGHPART (low);
static void
decode (words, low, hi)
HOST_WIDE_INT *words;
- HOST_WIDE_INT *low, *hi;
+ unsigned HOST_WIDE_INT *low;
+ HOST_WIDE_INT *hi;
{
*low = words[0] + words[1] * BASE;
*hi = words[2] + words[3] * BASE;
tree t;
int overflow;
{
- HOST_WIDE_INT low, high;
- register int prec;
+ unsigned HOST_WIDE_INT low;
+ HOST_WIDE_INT high;
+ unsigned int prec;
if (TREE_CODE (t) == REAL_CST)
{
{
TREE_INT_CST_HIGH (t) = 0;
if (prec < HOST_BITS_PER_WIDE_INT)
- TREE_INT_CST_LOW (t) &= ~((HOST_WIDE_INT) (-1) << prec);
+ TREE_INT_CST_LOW (t) &= ~((unsigned HOST_WIDE_INT) (-1) << prec);
}
/* Unsigned types do not suffer sign extension or overflow. */
/* If the value's sign bit is set, extend the sign. */
if (prec != 2 * HOST_BITS_PER_WIDE_INT
&& (prec > HOST_BITS_PER_WIDE_INT
- ? (TREE_INT_CST_HIGH (t)
- & ((HOST_WIDE_INT) 1 << (prec - HOST_BITS_PER_WIDE_INT - 1)))
- : TREE_INT_CST_LOW (t) & ((HOST_WIDE_INT) 1 << (prec - 1))))
+ ? 0 != (TREE_INT_CST_HIGH (t)
+ & ((HOST_WIDE_INT) 1
+ << (prec - HOST_BITS_PER_WIDE_INT - 1)))
+ : 0 != (TREE_INT_CST_LOW (t)
+ & ((unsigned HOST_WIDE_INT) 1 << (prec - 1)))))
{
/* Value is negative:
set to 1 all the bits that are outside this type's precision. */
{
TREE_INT_CST_HIGH (t) = -1;
if (prec < HOST_BITS_PER_WIDE_INT)
- TREE_INT_CST_LOW (t) |= ((HOST_WIDE_INT) (-1) << prec);
+ TREE_INT_CST_LOW (t) |= ((unsigned HOST_WIDE_INT) (-1) << prec);
}
}
int
add_double (l1, h1, l2, h2, lv, hv)
- HOST_WIDE_INT l1, h1, l2, h2;
- HOST_WIDE_INT *lv, *hv;
+ unsigned HOST_WIDE_INT l1, l2;
+ HOST_WIDE_INT h1, h2;
+ unsigned HOST_WIDE_INT *lv;
+ HOST_WIDE_INT *hv;
{
- HOST_WIDE_INT l, h;
+ unsigned HOST_WIDE_INT l;
+ HOST_WIDE_INT h;
l = l1 + l2;
- h = h1 + h2 + ((unsigned HOST_WIDE_INT) l < l1);
+ h = h1 + h2 + (l < l1);
*lv = l;
*hv = h;
int
neg_double (l1, h1, lv, hv)
- HOST_WIDE_INT l1, h1;
- HOST_WIDE_INT *lv, *hv;
+ unsigned HOST_WIDE_INT l1;
+ HOST_WIDE_INT h1;
+ unsigned HOST_WIDE_INT *lv;
+ HOST_WIDE_INT *hv;
{
if (l1 == 0)
{
int
mul_double (l1, h1, l2, h2, lv, hv)
- HOST_WIDE_INT l1, h1, l2, h2;
- HOST_WIDE_INT *lv, *hv;
+ unsigned HOST_WIDE_INT l1, l2;
+ HOST_WIDE_INT h1, h2;
+ unsigned HOST_WIDE_INT *lv;
+ HOST_WIDE_INT *hv;
{
HOST_WIDE_INT arg1[4];
HOST_WIDE_INT arg2[4];
HOST_WIDE_INT prod[4 * 2];
register unsigned HOST_WIDE_INT carry;
register int i, j, k;
- HOST_WIDE_INT toplow, tophigh, neglow, neghigh;
+ unsigned HOST_WIDE_INT toplow, neglow;
+ HOST_WIDE_INT tophigh, neghigh;
encode (arg1, l1, h1);
encode (arg2, l2, h2);
void
lshift_double (l1, h1, count, prec, lv, hv, arith)
- HOST_WIDE_INT l1, h1, count;
- int prec;
- HOST_WIDE_INT *lv, *hv;
+ unsigned HOST_WIDE_INT l1;
+ HOST_WIDE_INT h1, count;
+ unsigned int prec;
+ unsigned HOST_WIDE_INT *lv;
+ HOST_WIDE_INT *hv;
int arith;
{
if (count < 0)
count %= prec;
#endif
- if (count >= HOST_BITS_PER_WIDE_INT)
+ if (count >= 2 * HOST_BITS_PER_WIDE_INT)
{
- *hv = (unsigned HOST_WIDE_INT) l1 << (count - 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)
- | ((unsigned HOST_WIDE_INT) l1 >> (HOST_BITS_PER_WIDE_INT - count - 1) >> 1));
- *lv = (unsigned HOST_WIDE_INT) l1 << count;
+ | (l1 >> (HOST_BITS_PER_WIDE_INT - count - 1) >> 1));
+ *lv = l1 << count;
}
}
void
rshift_double (l1, h1, count, prec, lv, hv, arith)
- HOST_WIDE_INT l1, h1, count;
- int prec ATTRIBUTE_UNUSED;
- HOST_WIDE_INT *lv, *hv;
+ unsigned HOST_WIDE_INT l1;
+ HOST_WIDE_INT h1, count;
+ unsigned int prec ATTRIBUTE_UNUSED;
+ 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);
count %= prec;
#endif
- if (count >= HOST_BITS_PER_WIDE_INT)
+ 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 = signmask;
+ *lv = signmask;
+ }
+ else if (count >= HOST_BITS_PER_WIDE_INT)
{
*hv = signmask;
*lv = ((signmask << (2 * HOST_BITS_PER_WIDE_INT - count - 1) << 1)
}
else
{
- *lv = (((unsigned HOST_WIDE_INT) l1 >> count)
+ *lv = ((l1 >> count)
| ((unsigned HOST_WIDE_INT) h1 << (HOST_BITS_PER_WIDE_INT - count - 1) << 1));
*hv = ((signmask << (HOST_BITS_PER_WIDE_INT - count))
| ((unsigned HOST_WIDE_INT) h1 >> count));
void
lrotate_double (l1, h1, count, prec, lv, hv)
- HOST_WIDE_INT l1, h1, count;
- int prec;
- HOST_WIDE_INT *lv, *hv;
+ unsigned HOST_WIDE_INT l1;
+ HOST_WIDE_INT h1, count;
+ unsigned int prec;
+ unsigned HOST_WIDE_INT *lv;
+ HOST_WIDE_INT *hv;
{
- HOST_WIDE_INT s1l, s1h, s2l, s2h;
+ unsigned HOST_WIDE_INT s1l, s2l;
+ HOST_WIDE_INT s1h, s2h;
count %= prec;
if (count < 0)
void
rrotate_double (l1, h1, count, prec, lv, hv)
- HOST_WIDE_INT l1, h1, count;
- int prec;
- HOST_WIDE_INT *lv, *hv;
+ unsigned HOST_WIDE_INT l1;
+ HOST_WIDE_INT h1, count;
+ unsigned int prec;
+ unsigned HOST_WIDE_INT *lv;
+ HOST_WIDE_INT *hv;
{
- HOST_WIDE_INT s1l, s1h, s2l, s2h;
+ unsigned HOST_WIDE_INT s1l, s2l;
+ HOST_WIDE_INT s1h, s2h;
count %= prec;
if (count < 0)
lquo, hquo, lrem, hrem)
enum tree_code code;
int uns;
- HOST_WIDE_INT lnum_orig, hnum_orig; /* num == numerator == dividend */
- HOST_WIDE_INT lden_orig, hden_orig; /* den == denominator == divisor */
- HOST_WIDE_INT *lquo, *hquo, *lrem, *hrem;
+ 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, *lrem;
+ HOST_WIDE_INT *hquo, *hrem;
{
int quo_neg = 0;
HOST_WIDE_INT num[4 + 1]; /* extra element for scaling. */
HOST_WIDE_INT den[4], quo[4];
register int i, j;
unsigned HOST_WIDE_INT work;
- register unsigned HOST_WIDE_INT carry = 0;
- HOST_WIDE_INT lnum = lnum_orig;
+ unsigned HOST_WIDE_INT carry = 0;
+ unsigned HOST_WIDE_INT lnum = lnum_orig;
HOST_WIDE_INT hnum = hnum_orig;
- HOST_WIDE_INT lden = lden_orig;
+ unsigned HOST_WIDE_INT lden = lden_orig;
HOST_WIDE_INT hden = hden_orig;
int overflow = 0;
- if ((hden == 0) && (lden == 0))
+ if (hden == 0 && lden == 0)
overflow = 1, lden = 1;
/* calculate quotient sign and convert operands to unsigned. */
{
quo_neg = ~ quo_neg;
/* (minimum integer) / (-1) is the only overflow case. */
- if (neg_double (lnum, hnum, &lnum, &hnum) && (lden & hden) == -1)
+ if (neg_double (lnum, hnum, &lnum, &hnum)
+ && ((HOST_WIDE_INT) lden & hden) == -1)
overflow = 1;
}
if (hden < 0)
{ /* single precision */
*hquo = *hrem = 0;
/* This unsigned division rounds toward zero. */
- *lquo = lnum / (unsigned HOST_WIDE_INT) lden;
+ *lquo = lnum / lden;
goto finish_up;
}
encode (den, lden, hden);
/* Special code for when the divisor < BASE. */
- if (hden == 0 && lden < (HOST_WIDE_INT) 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 / (unsigned HOST_WIDE_INT) lden;
- carry = work % (unsigned HOST_WIDE_INT) lden;
+ 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 non-zero divisor digit. */
- for (i = 4 - 1; ; i--)
- if (den[i] != 0) {
- den_hi_sig = i;
- break;
- }
+ int num_hi_sig, den_hi_sig;
+ unsigned HOST_WIDE_INT quo_est, scale;
- /* 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;
+ /* Find the highest non-zero divisor digit. */
+ for (i = 4 - 1; ; i--)
+ if (den[i] != 0) {
+ den_hi_sig = i;
+ break;
+ }
- /* 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;
+ /* Insure that the first digit of the divisor is at least BASE/2.
+ This is required by the quotient digit estimation algorithm. */
- 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;
+ 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);
+ }
- /* 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--;
+ 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;
+ }
+ }
- /* 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. */
+ num_hi_sig = 4;
- carry = 0;
- for (j = 0; j <= den_hi_sig; j++)
+ /* Main loop */
+ for (i = num_hi_sig - den_hi_sig - 1; i >= 0; i--)
{
- work = quo_est * den[j] + carry;
- carry = HIGHPART (work);
- work = num[i + j] - LOWPART (work);
- num[i + j] = LOWPART (work);
- carry += HIGHPART (work) != 0;
- }
+ /* 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;
- /* if quo_est was high by one, then num[i] went negative and
- we need to correct things. */
+ /* 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--;
- if (num[num_hi_sig] < carry)
- {
- quo_est--;
- carry = 0; /* add divisor back in */
+ /* 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 = num[i + j] + den[j] + carry;
+ work = quo_est * den[j] + carry;
carry = HIGHPART (work);
+ work = num[i + j] - LOWPART (work);
num[i + j] = LOWPART (work);
+ carry += HIGHPART (work) != 0;
}
- num [num_hi_sig] += carry;
- }
- /* store the quotient digit. */
- quo[i] = quo_est;
+ /* If quo_est was high by one, then num[i] went negative and
+ we need to correct things. */
+ if (num[num_hi_sig] < 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);
add_double (*lquo, *hquo, (HOST_WIDE_INT) -1, (HOST_WIDE_INT) -1,
lquo, hquo);
}
- else return overflow;
+ else
+ return overflow;
break;
case CEIL_DIV_EXPR:
add_double (*lquo, *hquo, (HOST_WIDE_INT) 1, (HOST_WIDE_INT) 0,
lquo, hquo);
}
- else return overflow;
+ else
+ return overflow;
break;
case ROUND_DIV_EXPR:
case ROUND_MOD_EXPR: /* round to closest integer */
{
- HOST_WIDE_INT labs_rem = *lrem, habs_rem = *hrem;
- HOST_WIDE_INT labs_den = lden, habs_den = hden, ltwice, 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)) */
+ 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)) */
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)
- && ((HOST_WIDE_INT unsigned) labs_den
- < (unsigned HOST_WIDE_INT) ltwice)))
+ && (labs_den < ltwice)))
{
if (*hquo < 0)
/* quo = quo - 1; */
add_double (*lquo, *hquo, (HOST_WIDE_INT) 1, (HOST_WIDE_INT) 0,
lquo, hquo);
}
- else return overflow;
+ else
+ return overflow;
}
break;
int
target_isinf (x)
- REAL_VALUE_TYPE x;
+ REAL_VALUE_TYPE x ATTRIBUTE_UNUSED;
{
return 0;
}
int
target_isnan (x)
- REAL_VALUE_TYPE x;
+ REAL_VALUE_TYPE x ATTRIBUTE_UNUSED;
{
return 0;
}
double d;
unsigned short i[4];
}x, t, y;
+#ifdef CHECK_FLOAT_VALUE
int i;
+#endif
/* Usually disable if bounds checks are not reliable. */
if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT) && !flag_pretend_float)
REAL_VALUE_TYPE ip;
char *p = s;
unsigned HOST_WIDE_INT low, high;
- int expon, shcount, nrmcount, k;
+ int shcount, nrmcount, k;
int sign, expsign, isfloat;
int lost = 0;/* Nonzero low order bits shifted out and discarded. */
int frexpon = 0; /* Bits after the decimal point. */
if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')
|| (c >= 'a' && c <= 'f'))
{
- k = c & 0x7f;
- if (k >= 'a')
+ k = c & CHARMASK;
+ if (k >= 'a' && k <= 'f')
k = k - 'a' + 10;
else if (k >= 'A')
k = k - 'A' + 10;
The exponent field is a decimal integer. */
while (ISDIGIT(*p))
{
- k = (*p++ & 0x7f) - '0';
+ k = (*p++ & CHARMASK) - '0';
expon = 10 * expon + k;
}
register tree arg1, arg2;
int notrunc, forsize;
{
- HOST_WIDE_INT int1l, int1h, int2l, int2h;
- HOST_WIDE_INT low, hi;
- HOST_WIDE_INT garbagel, garbageh;
+ 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;
register tree t;
int uns = TREE_UNSIGNED (TREE_TYPE (arg1));
int overflow = 0;
/* 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 (TREE_TYPE (arg1)),
- &low, &hi,
- !uns);
+ lshift_double (int1l, int1h, int2l, TYPE_PRECISION (TREE_TYPE (arg1)),
+ &low, &hi, !uns);
no_overflow = 1;
break;
case RROTATE_EXPR:
int2l = - int2l;
case LROTATE_EXPR:
- lrotate_double (int1l, int1h, int2l,
- TYPE_PRECISION (TREE_TYPE (arg1)),
+ lrotate_double (int1l, int1h, int2l, TYPE_PRECISION (TREE_TYPE (arg1)),
&low, &hi);
break;
case FLOOR_DIV_EXPR: case CEIL_DIV_EXPR:
case EXACT_DIV_EXPR:
/* This is a shortcut for a common special case. */
- if (int2h == 0 && int2l > 0
+ if (int2h == 0 && (HOST_WIDE_INT) int2l > 0
&& ! TREE_CONSTANT_OVERFLOW (arg1)
&& ! TREE_CONSTANT_OVERFLOW (arg2)
- && int1h == 0 && int1l >= 0)
+ && int1h == 0 && (HOST_WIDE_INT) int1l >= 0)
{
if (code == CEIL_DIV_EXPR)
int1l += int2l - 1;
+
low = int1l / int2l, hi = 0;
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 && int2l > 0
+ if (int2h == 0 && (HOST_WIDE_INT) int2l > 0
&& ! TREE_CONSTANT_OVERFLOW (arg1)
&& ! TREE_CONSTANT_OVERFLOW (arg2)
- && int1h == 0 && int1l >= 0)
+ && int1h == 0 && (HOST_WIDE_INT) int1l >= 0)
{
if (code == CEIL_MOD_EXPR)
int1l += int2l - 1;
< (unsigned HOST_WIDE_INT) int2h)
|| (((unsigned HOST_WIDE_INT) int1h
== (unsigned HOST_WIDE_INT) int2h)
- && ((unsigned HOST_WIDE_INT) int1l
- < (unsigned HOST_WIDE_INT) int2l)));
+ && int1l < int2l));
else
- low = ((int1h < int2h)
- || ((int1h == int2h)
- && ((unsigned HOST_WIDE_INT) int1l
- < (unsigned HOST_WIDE_INT) int2l)));
+ low = (int1h < int2h
+ || (int1h == int2h && int1l < int2l));
if (low == (code == MIN_EXPR))
low = int1l, hi = int1h;
abort ();
}
- if (TREE_TYPE (arg1) == sizetype && hi == 0
- && low >= 0
- && (TYPE_MAX_VALUE (sizetype) == NULL
- || low <= TREE_INT_CST_LOW (TYPE_MAX_VALUE (sizetype)))
- && ! overflow
- && ! TREE_OVERFLOW (arg1) && ! TREE_OVERFLOW (arg2))
- t = size_int (low);
+ if (forsize && hi == 0 && low < 10000)
+ return size_int_type_wide (low, TREE_TYPE (arg1));
else
{
t = build_int_2 (low, hi);
return 0;
}
\f
-/* Return an INTEGER_CST with value whose HOST_BITS_PER_WIDE_INT bits are
- given by HIGH and whose HOST_BITS_PER_WIDE_INT bits are given by NUMBER.
+/* Return an INTEGER_CST with value whose low-order HOST_BITS_PER_WIDE_INT
+ bits are given by NUMBER and of the sizetype represented by KIND. */
- If BIT_P is nonzero, this represents a size in bit and the type of the
- result will be bitsizetype, othewise it represents a size in bytes and
- the type of the result will be sizetype. */
+tree
+size_int_wide (number, kind)
+ HOST_WIDE_INT number;
+ enum size_type_kind kind;
+{
+ return size_int_type_wide (number, sizetype_tab[(int) kind]);
+}
+
+/* Likewise, but the desired type is specified explicitly. */
tree
-size_int_wide (number, high, bit_p)
- unsigned HOST_WIDE_INT number, high;
- int bit_p;
+size_int_type_wide (number, type)
+ HOST_WIDE_INT number;
+ tree type;
{
/* Type-size nodes already made for small sizes. */
- static tree size_table[2 * HOST_BITS_PER_WIDE_INT + 1][2];
+ static tree size_table[2048 + 1];
static int init_p = 0;
tree t;
init_p = 1;
}
- if (number < 2*HOST_BITS_PER_WIDE_INT + 1 && high == 0
- && size_table[number][bit_p] != 0)
- return size_table[number][bit_p];
-
- if (number < 2*HOST_BITS_PER_WIDE_INT + 1 && high == 0)
+ /* If this is a positive number that fits in the table we use to hold
+ cached entries, see if it is already in the table and put it there
+ if not. */
+ if (number >= 0 && number < (int) (sizeof size_table / sizeof size_table[0]))
{
+ if (size_table[number] != 0)
+ for (t = size_table[number]; t != 0; t = TREE_CHAIN (t))
+ if (TREE_TYPE (t) == type)
+ return t;
+
if (! ggc_p)
{
/* Make this a permanent node. */
}
t = build_int_2 (number, 0);
- TREE_TYPE (t) = bit_p ? bitsizetype : sizetype;
- size_table[number][bit_p] = t;
+ TREE_TYPE (t) = type;
+ TREE_CHAIN (t) = size_table[number];
+ size_table[number] = t;
if (! ggc_p)
pop_obstacks ();
return t;
}
- t = build_int_2 (number, high);
- TREE_TYPE (t) = bit_p ? bitsizetype : sizetype;
+ t = build_int_2 (number, number < 0 ? -1 : 0);
+ TREE_TYPE (t) = type;
TREE_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (t) = force_fit_type (t, 0);
return t;
}
-/* Combine operands OP1 and OP2 with arithmetic operation CODE.
- CODE is a tree code. Data type is taken from `sizetype',
+/* Combine operands OP1 and OP2 with arithmetic operation CODE. CODE
+ is a tree code. The type of the result is taken from the operands.
+ Both must be the same type integer type and it must be a size type.
If the operands are constant, so is the result. */
tree
enum tree_code code;
tree arg0, arg1;
{
+ tree type = TREE_TYPE (arg0);
+
+ if (TREE_CODE (type) != INTEGER_TYPE || ! TYPE_IS_SIZETYPE (type)
+ || type != TREE_TYPE (arg1))
+ abort ();
+
/* Handle the special case of two integer constants faster. */
if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
{
if (arg0 == error_mark_node || arg1 == error_mark_node)
return error_mark_node;
- return fold (build (code, sizetype, arg0, arg1));
+ return fold (build (code, type, arg0, arg1));
}
-/* Combine operands OP1 and OP2 with arithmetic operation CODE.
- CODE is a tree code. Data type is taken from `ssizetype',
- If the operands are constant, so is the result. */
+/* Given two values, either both of sizetype or both of bitsizetype,
+ compute the difference between the two values. Return the value
+ in signed type corresponding to the type of the operands. */
tree
-ssize_binop (code, arg0, arg1)
- enum tree_code code;
+size_diffop (arg0, arg1)
tree arg0, arg1;
{
- /* Handle the special case of two integer constants faster. */
- if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
- {
- /* And some specific cases even faster than that. */
- if (code == PLUS_EXPR && integer_zerop (arg0))
- return arg1;
- else if ((code == MINUS_EXPR || code == PLUS_EXPR)
- && integer_zerop (arg1))
- return arg0;
- else if (code == MULT_EXPR && integer_onep (arg0))
- return arg1;
-
- /* Handle general case of two integer constants. We convert
- arg0 to ssizetype because int_const_binop uses its type for the
- return value. */
- arg0 = convert (ssizetype, arg0);
- return int_const_binop (code, arg0, arg1, 0, 0);
- }
+ tree type = TREE_TYPE (arg0);
+ tree ctype;
- if (arg0 == error_mark_node || arg1 == error_mark_node)
- return error_mark_node;
+ if (TREE_CODE (type) != INTEGER_TYPE || ! TYPE_IS_SIZETYPE (type)
+ || type != TREE_TYPE (arg1))
+ abort ();
- return fold (build (code, ssizetype, arg0, arg1));
+ /* If the type is already signed, just do the simple thing. */
+ if (! TREE_UNSIGNED (type))
+ return size_binop (MINUS_EXPR, arg0, arg1);
+
+ ctype = (type == bitsizetype || type == ubitsizetype
+ ? sbitsizetype : ssizetype);
+
+ /* If either operand is not a constant, do the conversions to the signed
+ 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, convert (ctype, arg0),
+ convert (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
+ overflow) and negate (which can't either). Special-case a result
+ of zero while we're here. */
+ if (tree_int_cst_equal (arg0, arg1))
+ return convert (ctype, integer_zero_node);
+ else if (tree_int_cst_lt (arg1, arg0))
+ return convert (ctype, size_binop (MINUS_EXPR, arg0, arg1));
+ else
+ return size_binop (MINUS_EXPR, convert (ctype, integer_zero_node),
+ convert (ctype, size_binop (MINUS_EXPR, arg1, arg0)));
}
\f
/* This structure is used to communicate arguments to fold_convert_1. */
if (TYPE_PRECISION (type) > 2 * HOST_BITS_PER_WIDE_INT)
return t;
+ /* If we are trying to make a sizetype for a small integer, use
+ size_int to pick up cached types to reduce duplicate nodes. */
+ if (TREE_CODE (type) == INTEGER_CST && TYPE_IS_SIZETYPE (type)
+ && compare_tree_int (arg1, 10000) < 0)
+ return size_int_type_wide (TREE_INT_CST_LOW (arg1), type);
+
/* Given an integer constant, make new constant with new type,
appropriately sign-extended or truncated. */
t = build_int_2 (TREE_INT_CST_LOW (arg1),
case INTEGER_CST:
return (! TREE_CONSTANT_OVERFLOW (arg0)
&& ! TREE_CONSTANT_OVERFLOW (arg1)
- && TREE_INT_CST_LOW (arg0) == TREE_INT_CST_LOW (arg1)
- && TREE_INT_CST_HIGH (arg0) == TREE_INT_CST_HIGH (arg1));
+ && tree_int_cst_equal (arg0, arg1));
case REAL_CST:
return (! TREE_CONSTANT_OVERFLOW (arg0)
case STRING_CST:
return (TREE_STRING_LENGTH (arg0) == TREE_STRING_LENGTH (arg1)
- && ! strncmp (TREE_STRING_POINTER (arg0),
+ && ! memcmp (TREE_STRING_POINTER (arg0),
TREE_STRING_POINTER (arg1),
TREE_STRING_LENGTH (arg0)));
{
int unsignedp1, unsignedpo;
tree primarg0, primarg1, primother;
- unsigned correct_width;
+ unsigned int correct_width;
if (operand_equal_p (arg0, arg1, 0))
return 1;
switch (code)
{
case INTEGER_CST:
- return convert (type, build_int_2 (TREE_INT_CST_LOW (arg) == 0
- && TREE_INT_CST_HIGH (arg) == 0, 0));
+ return convert (type, build_int_2 (integer_zerop (arg), 0));
case TRUTH_AND_EXPR:
return build (TRUTH_OR_EXPR, type,
int unsignedp;
{
tree result = build (BIT_FIELD_REF, type, inner,
- size_int (bitsize), bitsize_int (bitpos, 0L));
+ size_int (bitsize), bitsize_int (bitpos));
TREE_UNSIGNED (result) = unsignedp;
tree compare_type;
tree lhs, rhs;
{
- int lbitpos, lbitsize, rbitpos, rbitsize, nbitpos, nbitsize;
+ HOST_WIDE_INT lbitpos, lbitsize, rbitpos, rbitsize, nbitpos, nbitsize;
tree type = TREE_TYPE (lhs);
tree signed_type, unsigned_type;
int const_p = TREE_CODE (rhs) == INTEGER_CST;
enum machine_mode lmode, rmode, nmode;
int lunsignedp, runsignedp;
int lvolatilep = 0, rvolatilep = 0;
- int alignment;
+ unsigned int alignment;
tree linner, rinner = NULL_TREE;
tree mask;
tree offset;
decode_field_reference (exp, pbitsize, pbitpos, pmode, punsignedp,
pvolatilep, pmask, pand_mask)
tree exp;
- int *pbitsize, *pbitpos;
+ HOST_WIDE_INT *pbitsize, *pbitpos;
enum machine_mode *pmode;
int *punsignedp, *pvolatilep;
tree *pmask;
tree and_mask = 0;
tree mask, inner, offset;
tree unsigned_type;
- int precision;
- int alignment;
+ unsigned int precision;
+ unsigned int alignment;
/* All the optimizations using this function assume integer fields.
There are problems with FP fields since the type_for_size call
int size;
{
tree type = TREE_TYPE (mask);
- int precision = TYPE_PRECISION (type);
+ unsigned int precision = TYPE_PRECISION (type);
tree tmask;
tmask = build_int_2 (~0, ~0);
exp = TREE_OPERAND (exp, 0);
return (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c'
- || (TREE_CODE_CLASS (TREE_CODE (exp)) == 'd'
+ || (DECL_P (exp)
&& ! TREE_ADDRESSABLE (exp)
&& ! TREE_THIS_VOLATILE (exp)
&& ! DECL_NONLOCAL (exp)
try to change a logical combination of comparisons into a range test.
For example, both
- X == 2 && X == 3 && X == 4 && X == 5
+ X == 2 || X == 3 || X == 4 || X == 5
and
X >= 2 && X <= 5
are converted to
\f
/* Given EXP, a logical expression, set the range it is testing into
variables denoted by PIN_P, PLOW, and PHIGH. Return the expression
- actually being tested. *PLOW and *PHIGH will have be made the same type
+ actually being tested. *PLOW and *PHIGH will be made of the same type
as the returned expression. If EXP is not a comparison, we will most
likely not be returning a useful value and range. */
if (TREE_CODE_CLASS (code) == '2'
|| TREE_CODE_CLASS (code) == '<'
|| (TREE_CODE_CLASS (code) == 'e'
- && tree_code_length[(int) code] > 1))
+ && TREE_CODE_LENGTH (code) > 1))
arg1 = TREE_OPERAND (exp, 1);
}
in_p = n_in_p, low = n_low, high = n_high;
- /* If the high bound is missing, reverse the range so it
- goes from zero to the low bound minus 1. */
- if (high == 0)
+ /* If the high bound is missing, but we
+ have a low bound, reverse the range so
+ it goes from zero to the low bound minus 1. */
+ if (high == 0 && low)
{
in_p = ! in_p;
high = range_binop (MINUS_EXPR, NULL_TREE, low, 0,
low = range_binop (PLUS_EXPR, type, n_high, 0,
integer_one_node, 0);
high = range_binop (MINUS_EXPR, type, n_low, 0,
- integer_one_node, 0);
- in_p = ! in_p;
+ integer_one_node, 0);
+
+ /* If the range is of the form +/- [ x+1, x ], we won't
+ be able to normalize it. But then, it represents the
+ whole range or the empty set, so make it
+ +/- [ -, - ]. */
+ if (tree_int_cst_equal (n_low, low)
+ && tree_int_cst_equal (n_high, high))
+ low = high = 0;
+ else
+ in_p = ! in_p;
}
else
low = n_low, high = n_high;
enum tree_code code;
tree truth_type, lhs, rhs;
{
- /* If this is the "or" of two comparisons, we can do something if we
+ /* 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 the comparisons are EQ_EXPR. I.e.,
(a->b == 2 && a->c == 4) can become (a->new == NEW).
enum tree_code lcode, rcode;
tree ll_arg, lr_arg, rl_arg, rr_arg;
tree ll_inner, lr_inner, rl_inner, rr_inner;
- int ll_bitsize, ll_bitpos, lr_bitsize, lr_bitpos;
- int rl_bitsize, rl_bitpos, rr_bitsize, rr_bitpos;
- int xll_bitpos, xlr_bitpos, xrl_bitpos, xrr_bitpos;
- int lnbitsize, lnbitpos, rnbitsize, rnbitpos;
+ HOST_WIDE_INT ll_bitsize, ll_bitpos, lr_bitsize, lr_bitpos;
+ HOST_WIDE_INT rl_bitsize, rl_bitpos, rr_bitsize, rr_bitpos;
+ HOST_WIDE_INT xll_bitpos, xlr_bitpos, xrl_bitpos, xrr_bitpos;
+ HOST_WIDE_INT lnbitsize, lnbitpos, rnbitsize, rnbitpos;
int ll_unsignedp, lr_unsignedp, rl_unsignedp, rr_unsignedp;
enum machine_mode ll_mode, lr_mode, rl_mode, rr_mode;
enum machine_mode lnmode, rnmode;
should be used for the computation if wider than our type.
For example, if we are dividing (X * 8) + (Y + 16) by 4, we can return
- (X * 2) + (Y + 4). We also canonicalize (X + 7) * 4 into X * 4 + 28
- in the hope that either the machine has a multiply-accumulate insn
- or that this is part of an addressing calculation.
+ (X * 2) + (Y + 4). We must, however, be assured that either the original
+ expression would not overflow or that overflow is undefined for the type
+ in the language in question.
+
+ We also canonicalize (X + 7) * 4 into X * 4 + 28 in the hope that either
+ the machine has a multiply-accumulate insn or that this is part of an
+ addressing calculation.
If we return a non-null expression, it is an equivalent form of the
original computation, but need not be in the original type. */
? wide_type : type);
tree t1, t2;
int same_p = tcode == code;
- tree op0, op1;
+ tree op0 = NULL_TREE, op1 = NULL_TREE;
/* Don't deal with constants of zero here; they confuse the code below. */
if (integer_zerop (c))
- return 0;
+ return NULL_TREE;
if (TREE_CODE_CLASS (tcode) == '1')
op0 = TREE_OPERAND (t, 0);
break;
case CONVERT_EXPR: case NON_LVALUE_EXPR: case NOP_EXPR:
+ /* If op0 is an expression, and is unsigned, and the type is
+ smaller than ctype, then we cannot widen the expression. */
+ if ((TREE_CODE_CLASS (TREE_CODE (op0)) == '<'
+ || TREE_CODE_CLASS (TREE_CODE (op0)) == '1'
+ || TREE_CODE_CLASS (TREE_CODE (op0)) == '2'
+ || TREE_CODE_CLASS (TREE_CODE (op0)) == 'e')
+ && TREE_UNSIGNED (TREE_TYPE (op0))
+ && ! TYPE_IS_SIZETYPE (TREE_TYPE (op0))
+ && (GET_MODE_SIZE (TYPE_MODE (ctype))
+ > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0)))))
+ break;
/* Pass the constant down and see if we can make a simplification. If
we can, replace this expression with the inner simplification for
break;
case MIN_EXPR: case MAX_EXPR:
+ /* If widening the type changes the signedness, then we can't perform
+ this optimization as that changes the result. */
+ if (TREE_UNSIGNED (ctype) != TREE_UNSIGNED (type))
+ break;
+
/* MIN (a, b) / 5 -> MIN (a / 5, b / 5) */
if ((t1 = extract_muldiv (op0, c, code, wide_type)) != 0
&& (t2 = extract_muldiv (op1, c, code, wide_type)) != 0)
or floor division, by a power of two, so we can treat it that
way unless the multiplier or divisor overflows. */
if (TREE_CODE (op1) == INTEGER_CST
+ /* const_binop may not detect overflow correctly,
+ so check for it explicitly here. */
+ && TYPE_PRECISION (TREE_TYPE (size_one_node)) > TREE_INT_CST_LOW (op1)
+ && TREE_INT_CST_HIGH (op1) == 0
&& 0 != (t1 = convert (ctype,
const_binop (LSHIFT_EXPR, size_one_node,
op1, 0)))
break;
}
- /* Now do the operation and verify it doesn't overflow. */
- op1 = const_binop (code, convert (ctype, op1), convert (ctype, c), 0);
- if (op1 == 0 || TREE_OVERFLOW (op1))
+ /* 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)))
+ {
+ op1 = const_binop (code, convert (ctype, op1), convert (ctype, c), 0);
+ if (op1 == 0 || TREE_OVERFLOW (op1))
+ break;
+ }
+ else
+ break;
+
+ /* If we have an unsigned type is not a sizetype, we cannot widen
+ the operation since it will change the result if the original
+ computation overflowed. */
+ if (TREE_UNSIGNED (ctype)
+ && ! TYPE_IS_SIZETYPE (ctype)
+ && ctype != type)
break;
/* If we were able to eliminate our operation from the first side,
/* If these operations "cancel" each other, we have the main
optimizations of this pass, which occur when either constant is a
multiple of the other, in which case we replace this with either an
- operation or CODE or TCODE. */
- if ((code == MULT_EXPR && tcode == EXACT_DIV_EXPR)
- || (tcode == MULT_EXPR
- && code != TRUNC_MOD_EXPR && code != CEIL_MOD_EXPR
- && code != FLOOR_MOD_EXPR && code != ROUND_MOD_EXPR))
+ operation or CODE or TCODE.
+
+ If we have an unsigned type that is not a sizetype, we canot do
+ this since it will change the result if the original computation
+ overflowed. */
+ if ((! TREE_UNSIGNED (ctype)
+ || TYPE_IS_SIZETYPE (ctype))
+ && ((code == MULT_EXPR && tcode == EXACT_DIV_EXPR)
+ || (tcode == MULT_EXPR
+ && code != TRUNC_MOD_EXPR && code != CEIL_MOD_EXPR
+ && code != FLOOR_MOD_EXPR && code != ROUND_MOD_EXPR)))
{
if (integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c, 0)))
return fold (build (tcode, ctype, convert (ctype, op0),
do arithmetic on them. */
wins = 0;
}
- else if (kind == 'e' || kind == '<'
- || kind == '1' || kind == '2' || kind == 'r')
+ else if (IS_EXPR_CODE_CLASS (kind) || kind == 'r')
{
- register int len = tree_code_length[(int) code];
+ register int len = TREE_CODE_LENGTH (code);
register int i;
for (i = 0; i < len; i++)
{
STRIP_SIGN_NOPS (op);
}
else
- {
- /* Strip any conversions that don't change the mode. */
- STRIP_NOPS (op);
- }
+ /* Strip any conversions that don't change the mode. */
+ STRIP_NOPS (op);
if (TREE_CODE (op) == COMPLEX_CST)
subop = TREE_REALPART (op);
The also optimizes non-constant cases that used to be done in
expand_expr.
- Before we do that, see if this is a BIT_AND_EXPR or a BIT_OR_EXPR,
+ Before we do that, see if this is a BIT_AND_EXPR or a BIT_IOR_EXPR,
one of the operands is a comparison and the other is a comparison, a
BIT_AND_EXPR with the constant 1, or a truth value. In that case, the
code below would make the expression more complex. Change it to a
int inside_int = INTEGRAL_TYPE_P (inside_type);
int inside_ptr = POINTER_TYPE_P (inside_type);
int inside_float = FLOAT_TYPE_P (inside_type);
- int inside_prec = TYPE_PRECISION (inside_type);
+ unsigned int inside_prec = TYPE_PRECISION (inside_type);
int inside_unsignedp = TREE_UNSIGNED (inside_type);
int inter_int = INTEGRAL_TYPE_P (inter_type);
int inter_ptr = POINTER_TYPE_P (inter_type);
int inter_float = FLOAT_TYPE_P (inter_type);
- int inter_prec = TYPE_PRECISION (inter_type);
+ unsigned int inter_prec = TYPE_PRECISION (inter_type);
int inter_unsignedp = TREE_UNSIGNED (inter_type);
int final_int = INTEGRAL_TYPE_P (final_type);
int final_ptr = POINTER_TYPE_P (final_type);
int final_float = FLOAT_TYPE_P (final_type);
- int final_prec = TYPE_PRECISION (final_type);
+ unsigned int final_prec = TYPE_PRECISION (final_type);
int final_unsignedp = TREE_UNSIGNED (final_type);
/* In addition to the cases of two conversions in a row
/* Fold an expression like: "foo"[2] */
if (TREE_CODE (arg0) == STRING_CST
&& TREE_CODE (arg1) == INTEGER_CST
- && !TREE_INT_CST_HIGH (arg1)
- && (i = TREE_INT_CST_LOW (arg1)) < TREE_STRING_LENGTH (arg0))
+ && compare_tree_int (arg1, TREE_STRING_LENGTH (arg0)) < 0)
{
- t = build_int_2 (TREE_STRING_POINTER (arg0)[i], 0);
+ t = build_int_2 (TREE_STRING_POINTER (arg0)[TREE_INT_CST_LOW (arg))], 0);
TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (arg0));
force_fit_type (t, 0);
}
{
if (TREE_CODE (arg0) == INTEGER_CST)
{
- HOST_WIDE_INT low, high;
+ 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);
if (! TREE_UNSIGNED (type)
&& TREE_INT_CST_HIGH (arg0) < 0)
{
- HOST_WIDE_INT low, high;
+ 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);
case CONJ_EXPR:
if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
- return arg0;
+ return convert (type, arg0);
else if (TREE_CODE (arg0) == COMPLEX_EXPR)
- return build (COMPLEX_EXPR, TREE_TYPE (arg0),
+ return build (COMPLEX_EXPR, type,
TREE_OPERAND (arg0, 0),
negate_expr (TREE_OPERAND (arg0, 1)));
else if (TREE_CODE (arg0) == COMPLEX_CST)
STRIP_NOPS (tree110);
STRIP_NOPS (tree111);
if (TREE_CODE (tree110) == INTEGER_CST
- && TREE_INT_CST_HIGH (tree110) == 0
- && (TREE_INT_CST_LOW (tree110)
- == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0))))
+ && 0 == compare_tree_int (tree110,
+ TYPE_PRECISION
+ (TREE_TYPE (TREE_OPERAND
+ (arg0, 0))))
&& operand_equal_p (tree01, tree111, 0))
return build ((code0 == LSHIFT_EXPR
? LROTATE_EXPR
STRIP_NOPS (tree010);
STRIP_NOPS (tree011);
if (TREE_CODE (tree010) == INTEGER_CST
- && TREE_INT_CST_HIGH (tree010) == 0
- && (TREE_INT_CST_LOW (tree010)
- == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0))))
+ && 0 == compare_tree_int (tree010,
+ TYPE_PRECISION
+ (TREE_TYPE (TREE_OPERAND
+ (arg0, 0))))
&& operand_equal_p (tree11, tree011, 0))
return build ((code0 != LSHIFT_EXPR
? LROTATE_EXPR
if (! FLOAT_TYPE_P (type))
{
if (! wins && integer_zerop (arg0))
- return negate_expr (arg1);
+ return convert (type, negate_expr (arg1));
if (integer_zerop (arg1))
return non_lvalue (convert (type, arg0));
{
/* Except with IEEE floating point, 0-x equals -x. */
if (! wins && real_zerop (arg0))
- return negate_expr (arg1);
+ return convert (type, negate_expr (arg1));
/* Except with IEEE floating point, x-0 equals x. */
if (real_zerop (arg1))
return non_lvalue (convert (type, arg0));
if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == NOP_EXPR
&& TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg1, 0))))
{
- int prec = TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg1, 0)));
+ unsigned int prec
+ = TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg1, 0)));
+
if (prec < BITS_PER_WORD && prec < HOST_BITS_PER_WIDE_INT
&& (~TREE_INT_CST_LOW (arg0)
& (((HOST_WIDE_INT) 1 << prec) - 1)) == 0)
if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg0) == NOP_EXPR
&& TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
{
- int prec = TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)));
+ unsigned int prec
+ = TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)));
+
if (prec < BITS_PER_WORD && prec < HOST_BITS_PER_WIDE_INT
&& (~TREE_INT_CST_LOW (arg1)
& (((HOST_WIDE_INT) 1 << prec) - 1)) == 0)
&& TREE_INT_CST_HIGH (TREE_OPERAND (arg0, 1)) == 0
&& ((TREE_INT_CST_LOW (arg1)
+ TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1)))
- == GET_MODE_BITSIZE (TYPE_MODE (type))))
+ == (unsigned int) GET_MODE_BITSIZE (TYPE_MODE (type))))
return TREE_OPERAND (arg0, 0);
goto binary;
case MIN_EXPR:
if (operand_equal_p (arg0, arg1, 0))
- return arg0;
+ return omit_one_operand (type, arg0, arg1);
if (INTEGRAL_TYPE_P (type)
&& operand_equal_p (arg1, TYPE_MIN_VALUE (type), 1))
return omit_one_operand (type, arg1, arg0);
case MAX_EXPR:
if (operand_equal_p (arg0, arg1, 0))
- return arg0;
+ return omit_one_operand (type, arg0, arg1);
if (INTEGRAL_TYPE_P (type)
&& TYPE_MAX_VALUE (type)
&& operand_equal_p (arg1, TYPE_MAX_VALUE (type), 1))
("true" is a fixed value perhaps depending on the language.) */
/* If first arg is constant zero, return it. */
if (integer_zerop (arg0))
- return arg0;
+ return convert (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 (arg1);
+ return non_lvalue (convert (type, arg1));
if (TREE_CODE (arg1) == INTEGER_CST && ! integer_zerop (arg1))
- return non_lvalue (arg0);
+ return non_lvalue (convert (type, arg0));
/* If second arg is constant zero, result is zero, but first arg
must be evaluated. */
if (integer_zerop (arg1))
("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 arg0;
+ return convert (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 (arg1);
+ return non_lvalue (convert (type, arg1));
if (TREE_CODE (arg1) == INTEGER_CST && integer_zerop (arg1))
- return non_lvalue (arg0);
+ return non_lvalue (convert (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))
case TRUTH_XOR_EXPR:
/* If either arg is constant zero, drop it. */
if (integer_zerop (arg0))
- return non_lvalue (arg1);
+ return non_lvalue (convert (type, arg1));
if (integer_zerop (arg1))
- return non_lvalue (arg0);
+ return non_lvalue (convert (type, arg0));
/* If either arg is constant true, this is a logical inversion. */
if (integer_onep (arg0))
- return non_lvalue (invert_truthvalue (arg1));
+ return non_lvalue (convert (type, invert_truthvalue (arg1)));
if (integer_onep (arg1))
- return non_lvalue (invert_truthvalue (arg0));
+ return non_lvalue (convert (type, invert_truthvalue (arg0)));
return t;
case EQ_EXPR:
tree newconst
= fold (build (PLUS_EXPR, TREE_TYPE (varop),
constop, TREE_OPERAND (varop, 1)));
- TREE_SET_CODE (varop, PREINCREMENT_EXPR);
+
+ /* Do not overwrite the current varop to be a preincrement,
+ create a new node so that we won't confuse our caller who
+ might create trees and throw them away, reusing the
+ arguments that they passed to build. This shows up in
+ the THEN or ELSE parts of ?: being postincrements. */
+ varop = build (PREINCREMENT_EXPR, TREE_TYPE (varop),
+ TREE_OPERAND (varop, 0),
+ TREE_OPERAND (varop, 1));
/* If VAROP is a reference to a bitfield, we must mask
the constant by the width of the field. */
(TREE_OPERAND
(TREE_OPERAND (varop, 0), 1)));
tree mask, unsigned_type;
- int precision;
+ unsigned int precision;
tree folded_compare;
/* First check whether the comparison would come out
}
- t = build (code, type, TREE_OPERAND (t, 0),
- TREE_OPERAND (t, 1));
- TREE_OPERAND (t, constopnum) = newconst;
+ t = build (code, type,
+ (constopnum == 0) ? newconst : varop,
+ (constopnum == 1) ? newconst : varop);
return t;
}
}
tree newconst
= fold (build (MINUS_EXPR, TREE_TYPE (varop),
constop, TREE_OPERAND (varop, 1)));
- TREE_SET_CODE (varop, PREDECREMENT_EXPR);
+
+ /* Do not overwrite the current varop to be a predecrement,
+ create a new node so that we won't confuse our caller who
+ might create trees and throw them away, reusing the
+ arguments that they passed to build. This shows up in
+ the THEN or ELSE parts of ?: being postdecrements. */
+ varop = build (PREDECREMENT_EXPR, TREE_TYPE (varop),
+ TREE_OPERAND (varop, 0),
+ TREE_OPERAND (varop, 1));
if (TREE_CODE (TREE_OPERAND (varop, 0)) == COMPONENT_REF
&& DECL_BIT_FIELD(TREE_OPERAND
(TREE_OPERAND
(TREE_OPERAND (varop, 0), 1)));
tree mask, unsigned_type;
- int precision;
+ unsigned int precision;
tree folded_compare;
if (constopnum == 0)
}
- t = build (code, type, TREE_OPERAND (t, 0),
- TREE_OPERAND (t, 1));
- TREE_OPERAND (t, constopnum) = newconst;
+ t = build (code, type,
+ (constopnum == 0) ? newconst : varop,
+ (constopnum == 1) ? newconst : varop);
return t;
}
}
{
if (TREE_INT_CST_HIGH (arg1) == 0
&& (TREE_INT_CST_LOW (arg1)
- == ((HOST_WIDE_INT) 1 << (width - 1)) - 1)
+ == ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1)
&& ! TREE_UNSIGNED (TREE_TYPE (arg1)))
switch (TREE_CODE (t))
{
else if (TREE_INT_CST_HIGH (arg1) == -1
&& (- TREE_INT_CST_LOW (arg1)
- == ((HOST_WIDE_INT) 1 << (width - 1)))
+ == ((unsigned HOST_WIDE_INT) 1 << (width - 1)))
&& ! TREE_UNSIGNED (TREE_TYPE (arg1)))
switch (TREE_CODE (t))
{
else if (TREE_INT_CST_HIGH (arg1) == 0
&& (TREE_INT_CST_LOW (arg1)
- == ((HOST_WIDE_INT) 1 << (width - 1)) - 1)
+ == ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1)
&& TREE_UNSIGNED (TREE_TYPE (arg1)))
switch (TREE_CODE (t))
if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
{
if (code == EQ_EXPR)
- t1 = build_int_2 ((TREE_INT_CST_LOW (arg0)
- == TREE_INT_CST_LOW (arg1))
- && (TREE_INT_CST_HIGH (arg0)
- == TREE_INT_CST_HIGH (arg1)),
- 0);
+ t1 = build_int_2 (tree_int_cst_equal (arg0, arg1), 0);
else
t1 = build_int_2 ((TREE_UNSIGNED (TREE_TYPE (arg0))
? INT_CST_LT_UNSIGNED (arg0, arg1)
switch (comp_code)
{
case EQ_EXPR:
- return pedantic_non_lvalue (negate_expr (arg1));
+ return
+ pedantic_non_lvalue (convert (type, negate_expr (arg1)));
case NE_EXPR:
return pedantic_non_lvalue (convert (type, arg1));
case GE_EXPR:
tree comp_op1 = TREE_OPERAND (arg0, 1);
tree comp_type = TREE_TYPE (comp_op0);
+ /* Avoid adding NOP_EXPRs in case this is an lvalue. */
+ if (TYPE_MAIN_VARIANT (comp_type) == TYPE_MAIN_VARIANT (type))
+ comp_type = type;
+
switch (comp_code)
{
case EQ_EXPR:
so that we can convert this back to the
corresponding COND_EXPR. */
return pedantic_non_lvalue
- (convert (type, (fold (build (MIN_EXPR, comp_type,
- (comp_code == LE_EXPR
- ? comp_op0 : comp_op1),
- (comp_code == LE_EXPR
- ? comp_op1 : comp_op0))))));
+ (convert (type, fold (build (MIN_EXPR, comp_type,
+ (comp_code == LE_EXPR
+ ? comp_op0 : comp_op1),
+ (comp_code == LE_EXPR
+ ? comp_op1 : comp_op0)))));
break;
case GE_EXPR:
case GT_EXPR:
/* If the second operand is simpler than the third, swap them
since that produces better jump optimization results. */
- if ((TREE_CONSTANT (arg1) || TREE_CODE_CLASS (TREE_CODE (arg1)) == 'd'
+ if ((TREE_CONSTANT (arg1) || DECL_P (arg1)
|| TREE_CODE (arg1) == SAVE_EXPR)
&& ! (TREE_CONSTANT (TREE_OPERAND (t, 2))
- || TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (t, 2))) == 'd'
+ || DECL_P (TREE_OPERAND (t, 2))
|| TREE_CODE (TREE_OPERAND (t, 2)) == SAVE_EXPR))
{
/* See if this can be inverted. If it can't, possibly because
return t;
/* Don't let (0, 0) be null pointer constant. */
if (integer_zerop (arg1))
- return build1 (NOP_EXPR, TREE_TYPE (arg1), arg1);
- return arg1;
+ return build1 (NOP_EXPR, type, arg1);
+ return convert (type, arg1);
case COMPLEX_EXPR:
if (wins)