@@ 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.
#include "flags.h"
#include "tree.h"
#include "rtl.h"
+#include "expr.h"
#include "tm_p.h"
#include "toplev.h"
#include "ggc.h"
#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
TREE_INT_CST_LOW (t) &= ~((unsigned HOST_WIDE_INT) (-1) << prec);
}
- /* Unsigned types do not suffer sign extension or overflow. */
- if (TREE_UNSIGNED (TREE_TYPE (t)))
+ /* Unsigned types do not suffer sign extension or overflow unless they
+ are a sizetype. */
+ if (TREE_UNSIGNED (TREE_TYPE (t))
+ && ! (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
+ && TYPE_IS_SIZETYPE (TREE_TYPE (t))))
return overflow;
/* If the value's sign bit is set, extend the sign. */
}
else
{
- *lv = - l1;
- *hv = ~ h1;
+ *lv = -l1;
+ *hv = ~h1;
return 0;
}
}
encode (arg1, l1, h1);
encode (arg2, l2, h2);
- bzero ((char *) prod, sizeof prod);
+ memset ((char *) prod, 0, sizeof prod);
for (i = 0; i < 4; i++)
{
/* Check for overflow by calculating the top half of the answer in full;
it should agree with the low half's sign bit. */
- decode (prod+4, &toplow, &tophigh);
+ decode (prod + 4, &toplow, &tophigh);
if (h1 < 0)
{
neg_double (l2, h2, &neglow, &neghigh);
{
if (count < 0)
{
- rshift_double (l1, h1, - count, prec, lv, hv, arith);
+ rshift_double (l1, h1, -count, prec, lv, hv, arith);
return;
}
-
+
#ifdef SHIFT_COUNT_TRUNCATED
if (SHIFT_COUNT_TRUNCATED)
count %= prec;
overflow = 1, lden = 1;
/* calculate quotient sign and convert operands to unsigned. */
- if (!uns)
+ if (!uns)
{
if (hnum < 0)
{
&& ((HOST_WIDE_INT) lden & hden) == -1)
overflow = 1;
}
- if (hden < 0)
+ if (hden < 0)
{
quo_neg = ~ quo_neg;
neg_double (lden, hden, &lden, &hden);
goto finish_up;
}
- bzero ((char *) quo, sizeof quo);
+ memset ((char *) quo, 0, sizeof quo);
- bzero ((char *) num, sizeof num); /* to zero 9th element */
- bzero ((char *) den, sizeof den);
+ memset ((char *) num, 0, sizeof num); /* to zero 9th element */
+ memset ((char *) den, 0, sizeof den);
- encode (num, lnum, hnum);
+ encode (num, lnum, hnum);
encode (den, lden, hden);
/* Special code for when the divisor < BASE. */
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;
- }
+ 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. */
else
return overflow;
break;
-
+
case ROUND_DIV_EXPR:
case ROUND_MOD_EXPR: /* round to closest integer */
{
unsigned mantissa1 : 20;
unsigned exponent : 11;
unsigned sign : 1;
- } big_endian;
+ } big_endian;
} u;
u.d = dconstm1;
unsigned mantissa1 : 20;
unsigned exponent : 11;
unsigned sign : 1;
- } big_endian;
+ } big_endian;
} u;
u.d = dconstm1;
unsigned mantissa1 : 20;
unsigned exponent : 11;
unsigned sign : 1;
- } big_endian;
+ } big_endian;
} u;
u.d = dconstm1;
return 1;
}
-/* Convert C9X hexadecimal floating point string constant S. Return
+/* Convert C99 hexadecimal floating point string constant S. Return
real value type in mode MODE. This function uses the host computer's
floating point arithmetic when there is no REAL_ARITHMETIC. */
char *s;
enum machine_mode mode;
{
- REAL_VALUE_TYPE ip;
- char *p = s;
- unsigned HOST_WIDE_INT low, high;
- 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. */
- int expon = 0; /* Value of exponent. */
- int decpt = 0; /* How many decimal points. */
- int gotp = 0; /* How many P's. */
- char c;
-
- isfloat = 0;
- expsign = 1;
- ip = 0.0;
-
- while (*p == ' ' || *p == '\t')
- ++p;
-
- /* Sign, if any, comes first. */
- sign = 1;
- if (*p == '-')
- {
- sign = -1;
- ++p;
- }
-
- /* The string is supposed to start with 0x or 0X . */
- if (*p == '0')
- {
- ++p;
- if (*p == 'x' || *p == 'X')
- ++p;
- else
- abort ();
- }
- else
- abort ();
-
- while (*p == '0')
- ++p;
-
- high = 0;
- low = 0;
- shcount = 0;
- while ((c = *p) != '\0')
- {
- if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')
- || (c >= 'a' && c <= 'f'))
- {
- k = c & CHARMASK;
- if (k >= 'a' && k <= 'f')
- k = k - 'a' + 10;
- else if (k >= 'A')
- k = k - 'A' + 10;
- else
- k = k - '0';
-
- if ((high & 0xf0000000) == 0)
- {
- high = (high << 4) + ((low >> 28) & 15);
- low = (low << 4) + k;
- shcount += 4;
- if (decpt)
- frexpon += 4;
- }
- else
- {
- /* Record nonzero lost bits. */
- lost |= k;
- if (! decpt)
- frexpon -= 4;
- }
- ++p;
- }
- else if ( c == '.')
- {
- ++decpt;
- ++p;
- }
-
- else if (c == 'p' || c == 'P')
- {
- ++gotp;
- ++p;
- /* Sign of exponent. */
- if (*p == '-')
- {
- expsign = -1;
- ++p;
- }
-
- /* Value of exponent.
- The exponent field is a decimal integer. */
- while (ISDIGIT(*p))
- {
- k = (*p++ & CHARMASK) - '0';
- expon = 10 * expon + k;
- }
-
- expon *= expsign;
- /* F suffix is ambiguous in the significand part
- so it must appear after the decimal exponent field. */
- if (*p == 'f' || *p == 'F')
- {
- isfloat = 1;
- ++p;
- break;
- }
- }
-
- else if (c == 'l' || c == 'L')
- {
- ++p;
- break;
- }
- else
- break;
- }
-
- /* Abort if last character read was not legitimate. */
- c = *p;
- if ((c != '\0' && c != ' ' && c != '\n' && c != '\r') || (decpt > 1))
- abort ();
-
- /* There must be either one decimal point or one p. */
- if (decpt == 0 && gotp == 0)
- abort ();
-
- shcount -= 4;
- if (high == 0 && low == 0)
- return dconst0;
-
- /* Normalize. */
- nrmcount = 0;
- if (high == 0)
- {
- high = low;
- low = 0;
- nrmcount += 32;
- }
-
- /* Leave a high guard bit for carry-out. */
- if ((high & 0x80000000) != 0)
- {
- lost |= low & 1;
- low = (low >> 1) | (high << 31);
- high = high >> 1;
- nrmcount -= 1;
- }
-
- if ((high & 0xffff8000) == 0)
- {
- high = (high << 16) + ((low >> 16) & 0xffff);
- low = low << 16;
- nrmcount += 16;
- }
-
- while ((high & 0xc0000000) == 0)
- {
- high = (high << 1) + ((low >> 31) & 1);
- low = low << 1;
- nrmcount += 1;
- }
-
- if (isfloat || GET_MODE_SIZE(mode) == UNITS_PER_WORD)
- {
- /* Keep 24 bits precision, bits 0x7fffff80.
- Rounding bit is 0x40. */
- lost = lost | low | (high & 0x3f);
- low = 0;
- if (high & 0x40)
- {
- if ((high & 0x80) || lost)
- high += 0x40;
- }
- high &= 0xffffff80;
- }
- else
- {
- /* We need real.c to do long double formats, so here default
- to double precision. */
+ REAL_VALUE_TYPE ip;
+ char *p = s;
+ unsigned HOST_WIDE_INT low, high;
+ 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. */
+ int expon = 0; /* Value of exponent. */
+ int decpt = 0; /* How many decimal points. */
+ int gotp = 0; /* How many P's. */
+ char c;
+
+ isfloat = 0;
+ expsign = 1;
+ ip = 0.0;
+
+ while (*p == ' ' || *p == '\t')
+ ++p;
+
+ /* Sign, if any, comes first. */
+ sign = 1;
+ if (*p == '-')
+ {
+ sign = -1;
+ ++p;
+ }
+
+ /* The string is supposed to start with 0x or 0X . */
+ if (*p == '0')
+ {
+ ++p;
+ if (*p == 'x' || *p == 'X')
+ ++p;
+ else
+ abort ();
+ }
+ else
+ abort ();
+
+ while (*p == '0')
+ ++p;
+
+ high = 0;
+ low = 0;
+ shcount = 0;
+ while ((c = *p) != '\0')
+ {
+ if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')
+ || (c >= 'a' && c <= 'f'))
+ {
+ k = c & CHARMASK;
+ if (k >= 'a' && k <= 'f')
+ k = k - 'a' + 10;
+ else if (k >= 'A')
+ k = k - 'A' + 10;
+ else
+ k = k - '0';
+
+ if ((high & 0xf0000000) == 0)
+ {
+ high = (high << 4) + ((low >> 28) & 15);
+ low = (low << 4) + k;
+ shcount += 4;
+ if (decpt)
+ frexpon += 4;
+ }
+ else
+ {
+ /* Record nonzero lost bits. */
+ lost |= k;
+ if (! decpt)
+ frexpon -= 4;
+ }
+ ++p;
+ }
+ else if (c == '.')
+ {
+ ++decpt;
+ ++p;
+ }
+
+ else if (c == 'p' || c == 'P')
+ {
+ ++gotp;
+ ++p;
+ /* Sign of exponent. */
+ if (*p == '-')
+ {
+ expsign = -1;
+ ++p;
+ }
+
+ /* Value of exponent.
+ The exponent field is a decimal integer. */
+ while (ISDIGIT (*p))
+ {
+ k = (*p++ & CHARMASK) - '0';
+ expon = 10 * expon + k;
+ }
+
+ expon *= expsign;
+ /* F suffix is ambiguous in the significand part
+ so it must appear after the decimal exponent field. */
+ if (*p == 'f' || *p == 'F')
+ {
+ isfloat = 1;
+ ++p;
+ break;
+ }
+ }
+
+ else if (c == 'l' || c == 'L')
+ {
+ ++p;
+ break;
+ }
+ else
+ break;
+ }
+
+ /* Abort if last character read was not legitimate. */
+ c = *p;
+ if ((c != '\0' && c != ' ' && c != '\n' && c != '\r') || (decpt > 1))
+ abort ();
+
+ /* There must be either one decimal point or one p. */
+ if (decpt == 0 && gotp == 0)
+ abort ();
+
+ shcount -= 4;
+ if (high == 0 && low == 0)
+ return dconst0;
+
+ /* Normalize. */
+ nrmcount = 0;
+ if (high == 0)
+ {
+ high = low;
+ low = 0;
+ nrmcount += 32;
+ }
+
+ /* Leave a high guard bit for carry-out. */
+ if ((high & 0x80000000) != 0)
+ {
+ lost |= low & 1;
+ low = (low >> 1) | (high << 31);
+ high = high >> 1;
+ nrmcount -= 1;
+ }
+
+ if ((high & 0xffff8000) == 0)
+ {
+ high = (high << 16) + ((low >> 16) & 0xffff);
+ low = low << 16;
+ nrmcount += 16;
+ }
+
+ while ((high & 0xc0000000) == 0)
+ {
+ high = (high << 1) + ((low >> 31) & 1);
+ low = low << 1;
+ nrmcount += 1;
+ }
+
+ if (isfloat || GET_MODE_SIZE (mode) == UNITS_PER_WORD)
+ {
+ /* Keep 24 bits precision, bits 0x7fffff80.
+ Rounding bit is 0x40. */
+ lost = lost | low | (high & 0x3f);
+ low = 0;
+ if (high & 0x40)
+ {
+ if ((high & 0x80) || lost)
+ high += 0x40;
+ }
+ high &= 0xffffff80;
+ }
+ else
+ {
+ /* We need real.c to do long double formats, so here default
+ to double precision. */
#if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
- /* IEEE double.
- Keep 53 bits precision, bits 0x7fffffff fffffc00.
- Rounding bit is low word 0x200. */
- lost = lost | (low & 0x1ff);
- if (low & 0x200)
- {
- if ((low & 0x400) || lost)
- {
- low = (low + 0x200) & 0xfffffc00;
- if (low == 0)
- high += 1;
- }
- }
- low &= 0xfffffc00;
+ /* IEEE double.
+ Keep 53 bits precision, bits 0x7fffffff fffffc00.
+ Rounding bit is low word 0x200. */
+ lost = lost | (low & 0x1ff);
+ if (low & 0x200)
+ {
+ if ((low & 0x400) || lost)
+ {
+ low = (low + 0x200) & 0xfffffc00;
+ if (low == 0)
+ high += 1;
+ }
+ }
+ low &= 0xfffffc00;
#else
- /* Assume it's a VAX with 56-bit significand,
- bits 0x7fffffff ffffff80. */
- lost = lost | (low & 0x7f);
- if (low & 0x40)
- {
- if ((low & 0x80) || lost)
- {
- low = (low + 0x40) & 0xffffff80;
- if (low == 0)
- high += 1;
- }
- }
- low &= 0xffffff80;
+ /* Assume it's a VAX with 56-bit significand,
+ bits 0x7fffffff ffffff80. */
+ lost = lost | (low & 0x7f);
+ if (low & 0x40)
+ {
+ if ((low & 0x80) || lost)
+ {
+ low = (low + 0x40) & 0xffffff80;
+ if (low == 0)
+ high += 1;
+ }
+ }
+ low &= 0xffffff80;
#endif
- }
+ }
- ip = (double) high;
- ip = REAL_VALUE_LDEXP (ip, 32) + (double) low;
- /* Apply shifts and exponent value as power of 2. */
- ip = REAL_VALUE_LDEXP (ip, expon - (nrmcount + frexpon));
+ ip = (double) high;
+ ip = REAL_VALUE_LDEXP (ip, 32) + (double) low;
+ /* Apply shifts and exponent value as power of 2. */
+ ip = REAL_VALUE_LDEXP (ip, expon - (nrmcount + frexpon));
- if (sign < 0)
- ip = -ip;
- return ip;
+ if (sign < 0)
+ ip = -ip;
+ return ip;
}
#endif /* no REAL_ARITHMETIC */
break;
case RSHIFT_EXPR:
- int2l = - int2l;
+ int2l = -int2l;
case LSHIFT_EXPR:
/* It's unclear from the C standard whether shifts can overflow.
The following code ignores overflow; perhaps a C standard
/* ... fall through ... */
- case ROUND_DIV_EXPR:
+ case ROUND_DIV_EXPR:
if (int2h == 0 && int2l == 1)
{
low = int1l, hi = int1h;
/* ... fall through ... */
- case ROUND_MOD_EXPR:
+ case ROUND_MOD_EXPR:
overflow = div_and_round_double (code, uns,
int1l, int1h, int2l, int2h,
&garbagel, &garbageh, &low, &hi);
abort ();
}
- if (forsize && hi == 0 && low < 10000)
+ if (forsize && hi == 0 && low < 10000
+ && overflow == 0 && ! TREE_OVERFLOW (arg1) && ! TREE_OVERFLOW (arg2))
return size_int_type_wide (low, TREE_TYPE (arg1));
else
{
/* Define input and output argument for const_binop_1. */
struct cb_args
{
- enum tree_code code; /* Input: tree code for operation*/
- tree type; /* Input: tree type for operation. */
- REAL_VALUE_TYPE d1, d2; /* Input: floating point operands. */
- tree t; /* Output: constant for result. */
+ enum tree_code code; /* Input: tree code for operation. */
+ tree type; /* Input: tree type for operation. */
+ REAL_VALUE_TYPE d1, d2; /* Input: floating point operands. */
+ tree t; /* Output: constant for result. */
};
/* Do the real arithmetic for const_binop while protected by a
static void
const_binop_1 (data)
- PTR data;
+ PTR data;
{
struct cb_args *args = (struct cb_args *) data;
REAL_VALUE_TYPE value;
case PLUS_EXPR:
value = args->d1 + args->d2;
break;
-
+
case MINUS_EXPR:
value = args->d1 - args->d2;
break;
-
+
case MULT_EXPR:
value = args->d1 * args->d2;
break;
-
+
case RDIV_EXPR:
#ifndef REAL_INFINITY
if (args->d2 == 0)
abort ();
#endif
-
+
value = args->d1 / args->d2;
break;
-
+
case MIN_EXPR:
value = MIN (args->d1, args->d2);
break;
-
+
case MAX_EXPR:
value = MAX (args->d1, args->d2);
break;
-
+
default:
abort ();
}
register tree arg1, arg2;
int notrunc;
{
- STRIP_NOPS (arg1); STRIP_NOPS (arg2);
+ STRIP_NOPS (arg1);
+ STRIP_NOPS (arg2);
if (TREE_CODE (arg1) == INTEGER_CST)
return int_const_binop (code, arg1, arg2, notrunc, 0);
args.d1 = d1;
args.d2 = d2;
args.code = code;
-
+
if (do_float_handler (const_binop_1, (PTR) &args))
/* Receive output from const_binop_1. */
t = args.t;
static tree size_table[2048 + 1];
static int init_p = 0;
tree t;
-
- if (ggc_p && ! init_p)
+
+ if (! init_p)
{
ggc_add_tree_root ((tree *) size_table,
sizeof size_table / sizeof (tree));
/* 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 (number >= 0 && number < (int) ARRAY_SIZE (size_table))
{
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. */
- push_obstacks_nochange ();
- end_temporary_allocation ();
- }
-
t = build_int_2 (number, 0);
TREE_TYPE (t) = type;
TREE_CHAIN (t) = size_table[number];
size_table[number] = t;
- if (! ggc_p)
- pop_obstacks ();
-
return t;
}
static void
fold_convert_1 (data)
- PTR data;
+ PTR data;
{
- struct fc_args * args = (struct fc_args *) data;
+ struct fc_args *args = (struct fc_args *) data;
args->t = build_real (args->type,
real_value_truncate (TYPE_MODE (args->type),
if (TREE_CODE (arg1) == REAL_CST)
{
struct fc_args args;
-
+
if (REAL_VALUE_ISNAN (TREE_REAL_CST (arg1)))
{
t = arg1;
/* Setup input for fold_convert_1() */
args.arg1 = arg1;
args.type = type;
-
+
if (do_float_handler (fold_convert_1, (PTR) &args))
{
/* Receive output from fold_convert_1() */
if (TREE_CODE (arg0) == RTL_EXPR)
return rtx_equal_p (RTL_EXPR_RTL (arg0), RTL_EXPR_RTL (arg1));
return 0;
-
+
default:
return 0;
}
}
\f
/* Similar to operand_equal_p, but see if ARG0 might have been made by
- shorten_compare from ARG1 when ARG1 was being compared with OTHER.
+ shorten_compare from ARG1 when ARG1 was being compared with OTHER.
When in doubt, return 0. */
-static int
+static int
operand_equal_for_comparison_p (arg0, arg1, other)
tree arg0, arg1;
tree other;
and see if the inner values are the same. This removes any
signedness comparison, which doesn't matter here. */
primarg0 = arg0, primarg1 = arg1;
- STRIP_NOPS (primarg0); STRIP_NOPS (primarg1);
+ STRIP_NOPS (primarg0);
+ STRIP_NOPS (primarg1);
if (operand_equal_p (primarg0, primarg1, 0))
return 1;
/* Make sure shorter operand is extended the right way
to match the longer operand. */
primarg1 = convert (signed_or_unsigned_type (unsignedp1,
- TREE_TYPE (primarg1)),
- primarg1);
+ TREE_TYPE (primarg1)),
+ primarg1);
if (operand_equal_p (arg0, convert (type, primarg1), 0))
return 1;
&& twoval_comparison_p (TREE_OPERAND (arg, 2),
cval1, cval2, save_p));
return 0;
-
+
case '<':
/* First see if we can handle the first operand, then the second. For
the second operand, we know *CVAL1 can't be zero. It must be that
return pedantic_non_lvalue (t);
}
-
-
\f
/* Return a simplified tree node for the truth-negation of ARG. This
never alters ARG itself. We assume that ARG is an operation that
error case below. If we didn't, we might generate wrong code.
For unsigned fields, the constant shifted right by the field length should
- be all zero. For signed fields, the high-order bits should agree with
+ be all zero. For signed fields, the high-order bits should agree with
the sign bit. */
if (lunsignedp)
unsigned int precision;
unsigned int alignment;
- /* All the optimizations using this function assume integer fields.
+ /* All the optimizations using this function assume integer fields.
There are problems with FP fields since the type_for_size call
below can fail for, e.g., XFmode. */
if (! INTEGRAL_TYPE_P (TREE_TYPE (exp)))
return 0;
}
-
inner = get_inner_reference (exp, pbitsize, pbitpos, &offset, pmode,
punsignedp, pvolatilep, &alignment);
if ((inner == exp && and_mask == 0)
|| *pbitsize < 0 || offset != 0
|| TREE_CODE (inner) == PLACEHOLDER_EXPR)
return 0;
-
+
/* Compute the mask to access the bitfield. */
unsigned_type = type_for_size (*pbitsize, 1);
precision = TYPE_PRECISION (unsigned_type);
TREE_TYPE (tmask) = signed_type (type);
force_fit_type (tmask, 0);
return
- tree_int_cst_equal (mask,
+ tree_int_cst_equal (mask,
const_binop (RSHIFT_EXPR,
const_binop (LSHIFT_EXPR, tmask,
size_int (precision - size),
/* Subroutine for fold_truthop: determine if an operand is simple enough
to be evaluated unconditionally. */
-static int
+static int
simple_operand_p (exp)
tree 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
return convert (type, result ? integer_one_node : integer_zero_node);
}
-\f
+\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 (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
{
arg0 = TREE_OPERAND (exp, 0);
- if (TREE_CODE_CLASS (code) == '<'
+ if (TREE_CODE_CLASS (code) == '<'
|| TREE_CODE_CLASS (code) == '1'
|| TREE_CODE_CLASS (code) == '2')
type = TREE_TYPE (arg0);
- if (TREE_CODE_CLASS (code) == '2'
+ if (TREE_CODE_CLASS (code) == '2'
|| TREE_CODE_CLASS (code) == '<'
- || (TREE_CODE_CLASS (code) == 'e'
+ || (TREE_CODE_CLASS (code) == 'e'
&& TREE_CODE_LENGTH (code) > 1))
arg1 = TREE_OPERAND (exp, 1);
}
high_positive = fold (build (RSHIFT_EXPR, type,
convert (type, high_positive),
convert (type, integer_one_node)));
-
+
/* If the low bound is specified, "and" the range with the
range for which the original unsigned value will be
positive. */
return 0;
}
\f
-/* Given two ranges, see if we can merge them into one. Return 1 if we
+/* 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
/* Make range 0 be the range that starts first, or ends last if they
start at the same value. Swap them if it isn't. */
- if (integer_onep (range_binop (GT_EXPR, integer_type_node,
+ if (integer_onep (range_binop (GT_EXPR, integer_type_node,
low0, 0, low1, 0))
|| (lowequal
&& integer_onep (range_binop (GT_EXPR, integer_type_node,
{
in_p = 1, high = high0;
low = range_binop (PLUS_EXPR, NULL_TREE, high1, 0,
- integer_one_node, 0);
+ integer_one_node, 0);
}
else if (! subset || highequal)
{
short-circuited branch and the underlying object on both sides
is the same, make a non-short-circuit operation. */
else if (BRANCH_COST >= 2
+ && lhs != 0 && rhs != 0
&& (TREE_CODE (exp) == TRUTH_ANDIF_EXPR
|| TREE_CODE (exp) == TRUTH_ORIF_EXPR)
&& operand_equal_p (lhs, rhs, 0))
/* We must use a signed type in order to get an arithmetic right shift.
However, we must also avoid introducing accidental overflows, so that
- a subsequent call to integer_zerop will work. Hence we must
+ a subsequent call to integer_zerop will work. Hence we must
do the type conversion here. At this point, the constant is either
zero or one, and the conversion to a signed type can never overflow.
We could get an overflow if this conversion is done anywhere else. */
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.,
+ if the comparisons are EQ_EXPR. I.e.,
(a->b == 2 && a->c == 4) can become (a->new == NEW).
WANTED_CODE is this operation code. For single bit fields, we can
lr_arg = TREE_OPERAND (lhs, 1);
rl_arg = TREE_OPERAND (rhs, 0);
rr_arg = TREE_OPERAND (rhs, 1);
-
+
/* If the RHS can be evaluated unconditionally and its operands are
simple, it wins to evaluate the RHS unconditionally on machines
with expensive branches. In this case, this isn't a comparison
if (l_const)
{
l_const = convert (lntype, l_const);
- l_const = unextend (l_const, ll_bitsize, ll_unsignedp, ll_and_mask);
+ 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);
if (! integer_zerop (const_binop (BIT_AND_EXPR, l_const,
fold (build1 (BIT_NOT_EXPR,
0)))
{
warning ("comparison is always %d", wanted_code == NE_EXPR);
-
+
return convert (truth_type,
wanted_code == NE_EXPR
? integer_one_node : integer_zero_node);
field containing them both.
Note that we still must mask the lhs/rhs expressions. Furthermore,
- the mask must be shifted to account for the shift done by
+ the mask must be shifted to account for the shift done by
make_bit_field_ref. */
if ((ll_bitsize + ll_bitpos == rl_bitpos
&& lr_bitsize + lr_bitpos == rr_bitpos)
const_binop (BIT_IOR_EXPR, l_const, r_const, 0));
}
\f
-/* Optimize T, which is a comparison of a MIN_EXPR or MAX_EXPR with a
+/* Optimize T, which is a comparison of a MIN_EXPR or MAX_EXPR with a
constant. */
static tree
{
tree type = TREE_TYPE (t);
enum tree_code tcode = TREE_CODE (t);
- tree ctype = (wide_type != 0 && (GET_MODE_SIZE (TYPE_MODE (wide_type))
+ tree ctype = (wide_type != 0 && (GET_MODE_SIZE (TYPE_MODE (wide_type))
> GET_MODE_SIZE (TYPE_MODE (type)))
? wide_type : type);
tree t1, t2;
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))
+ && ! (TREE_CODE (TREE_TYPE (op0)) == INTEGER_TYPE
+ && 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
possible later conversion to our or some other type. */
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 (ctype != type && TREE_UNSIGNED (ctype) != TREE_UNSIGNED (type))
+ if (TREE_UNSIGNED (ctype) != TREE_UNSIGNED (type))
break;
/* MIN (a, b) / 5 -> MIN (a / 5, b / 5) */
the operation since it will change the result if the original
computation overflowed. */
if (TREE_UNSIGNED (ctype)
- && ! TYPE_IS_SIZETYPE (ctype)
+ && ! (TREE_CODE (ctype) == INTEGER_TYPE && TYPE_IS_SIZETYPE (ctype))
&& ctype != type)
break;
/* 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.
+ 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)
- || (TREE_CODE (ctype) == INTEGER_TYPE
- && TYPE_IS_SIZETYPE (ctype)))
+ || (TREE_CODE (ctype) == INTEGER_TYPE && TYPE_IS_SIZETYPE (ctype)))
&& ((code == MULT_EXPR && tcode == EXACT_DIV_EXPR)
|| (tcode == MULT_EXPR
&& code != TRUNC_MOD_EXPR && code != CEIL_MOD_EXPR
return value ? integer_one_node : integer_zero_node;
else if (TREE_CODE (type) == BOOLEAN_TYPE)
return truthvalue_conversion (value ? integer_one_node :
- integer_zero_node);
- else
+ integer_zero_node);
+ else
{
tree t = build_int_2 (value, 0);
but we can constant-fold them if they have constant operands. */
tree
-fold (expr)
+fold (expr)
tree expr;
{
register tree t = expr;
if all operands are constant. */
int wins = 1;
- /* Don't try to process an RTL_EXPR since its operands aren't trees.
+ /* Don't try to process an RTL_EXPR since its operands aren't trees.
Likewise for a SAVE_EXPR that's already been evaluated. */
if (code == RTL_EXPR || (code == SAVE_EXPR && SAVE_EXPR_RTL (t)) != 0)
return t;
return DECL_INITIAL (t);
return t;
}
-
+
#ifdef MAX_INTEGER_COMPUTATION_MODE
check_max_integer_computation_mode (expr);
#endif
else
/* Strip any conversions that don't change the mode. */
STRIP_NOPS (op);
-
+
if (TREE_CODE (op) == COMPLEX_CST)
subop = TREE_REALPART (op);
else
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
- TRUTH_{AND,OR}_EXPR. Likewise, convert a similar NE_EXPR to
+ TRUTH_{AND,OR}_EXPR. Likewise, convert a similar NE_EXPR to
TRUTH_XOR_EXPR and an EQ_EXPR to the inversion of a TRUTH_XOR_EXPR. */
if ((code == BIT_AND_EXPR || code == BIT_IOR_EXPR
TREE_OPERAND (TREE_OPERAND (t, 2), 0)));
return t;
}
- else if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<')
+ else if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<')
return fold (build (COND_EXPR, type, arg0,
fold (build1 (code, type, integer_one_node)),
fold (build1 (code, type, integer_zero_node))));
&& TREE_CODE (arg1) == COMPOUND_EXPR)
return build (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
fold (build (code, type, arg0, TREE_OPERAND (arg1, 1))));
-
+
switch (code)
{
case INTEGER_CST:
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
+ /* In addition to the cases of two conversions in a row
handled below, if we are converting something to its own
type via an object of identical or wider precision, neither
conversion is needed. */
- if (inside_type == final_type
+ if (TYPE_MAIN_VARIANT (inside_type) == TYPE_MAIN_VARIANT (final_type)
&& ((inter_int && final_int) || (inter_float && final_float))
&& inter_prec >= final_prec)
- return TREE_OPERAND (TREE_OPERAND (t, 0), 0);
+ return convert (final_type, TREE_OPERAND (TREE_OPERAND (t, 0), 0));
/* Likewise, if the intermediate and final types are either both
float or both integer, we don't need the middle conversion if
and the outermost type is wider than the intermediate, or
- the initial type is a pointer type and the precisions of the
intermediate and final types differ, or
- - the final type is a pointer type and the precisions of the
+ - the final type is a pointer type and the precisions of the
initial and intermediate types differ. */
if (! inside_float && ! inter_float && ! final_float
&& (inter_prec > inside_prec || inter_prec > final_prec)
}
/* Reassociate (plus (plus (mult) (foo)) (mult)) as
- (plus (plus (mult) (mult)) (foo)) so that we can
+ (plus (plus (mult) (mult)) (foo)) so that we can
take advantage of the factoring cases below. */
if ((TREE_CODE (arg0) == PLUS_EXPR
&& TREE_CODE (arg1) == MULT_EXPR)
|| (TREE_CODE (arg1) == PLUS_EXPR
- && TREE_CODE (arg0) == MULT_EXPR))
+ && TREE_CODE (arg0) == MULT_EXPR))
{
tree parg0, parg1, parg, marg;
}
if (same)
- return fold (build (MULT_EXPR, type,
+ return fold (build (MULT_EXPR, type,
fold (build (PLUS_EXPR, type, alt0, alt1)),
same));
}
/* (A << B) + (A >> (Z - B)) if A is unsigned and Z is the size of A
is a rotate of A by B bits. */
{
- register enum tree_code code0, code1;
- code0 = TREE_CODE (arg0);
- code1 = TREE_CODE (arg1);
- if (((code0 == RSHIFT_EXPR && code1 == LSHIFT_EXPR)
- || (code1 == RSHIFT_EXPR && code0 == LSHIFT_EXPR))
+ register enum tree_code code0, code1;
+ code0 = TREE_CODE (arg0);
+ code1 = TREE_CODE (arg1);
+ if (((code0 == RSHIFT_EXPR && code1 == LSHIFT_EXPR)
+ || (code1 == RSHIFT_EXPR && code0 == LSHIFT_EXPR))
&& operand_equal_p (TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg1,0), 0)
+ TREE_OPERAND (arg1, 0), 0)
&& TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
{
register tree tree01, tree11;
code01 = TREE_CODE (tree01);
code11 = TREE_CODE (tree11);
if (code01 == INTEGER_CST
- && code11 == INTEGER_CST
- && TREE_INT_CST_HIGH (tree01) == 0
- && TREE_INT_CST_HIGH (tree11) == 0
- && ((TREE_INT_CST_LOW (tree01) + TREE_INT_CST_LOW (tree11))
- == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))))
+ && code11 == INTEGER_CST
+ && TREE_INT_CST_HIGH (tree01) == 0
+ && 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 build (LROTATE_EXPR, type, TREE_OPERAND (arg0, 0),
- code0 == LSHIFT_EXPR ? tree01 : tree11);
+ code0 == LSHIFT_EXPR ? tree01 : tree11);
else if (code11 == MINUS_EXPR)
{
- tree tree110, tree111;
- tree110 = TREE_OPERAND (tree11, 0);
- tree111 = TREE_OPERAND (tree11, 1);
- STRIP_NOPS (tree110);
- STRIP_NOPS (tree111);
- if (TREE_CODE (tree110) == INTEGER_CST
+ tree tree110, tree111;
+ tree110 = TREE_OPERAND (tree11, 0);
+ tree111 = TREE_OPERAND (tree11, 1);
+ STRIP_NOPS (tree110);
+ STRIP_NOPS (tree111);
+ if (TREE_CODE (tree110) == INTEGER_CST
&& 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
- : RROTATE_EXPR),
- type, TREE_OPERAND (arg0, 0), tree01);
+ return build ((code0 == LSHIFT_EXPR
+ ? LROTATE_EXPR
+ : RROTATE_EXPR),
+ type, TREE_OPERAND (arg0, 0), tree01);
}
else if (code01 == MINUS_EXPR)
{
- tree tree010, tree011;
- tree010 = TREE_OPERAND (tree01, 0);
- tree011 = TREE_OPERAND (tree01, 1);
- STRIP_NOPS (tree010);
- STRIP_NOPS (tree011);
- if (TREE_CODE (tree010) == INTEGER_CST
+ tree tree010, tree011;
+ tree010 = TREE_OPERAND (tree01, 0);
+ tree011 = TREE_OPERAND (tree01, 1);
+ STRIP_NOPS (tree010);
+ STRIP_NOPS (tree011);
+ if (TREE_CODE (tree010) == INTEGER_CST
&& 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
- : RROTATE_EXPR),
- type, TREE_OPERAND (arg0, 0), tree11);
+ return build ((code0 != LSHIFT_EXPR
+ ? LROTATE_EXPR
+ : RROTATE_EXPR),
+ type, TREE_OPERAND (arg0, 0), tree11);
}
}
}
-
associate:
/* In most languages, can't associate operations on floats through
parentheses. Rather than remember where the parentheses were, we
/* (-A) - CST -> (-CST) - A for floating point (what about ints ?) */
if (TREE_CODE (arg0) == NEGATE_EXPR && TREE_CODE (arg1) == REAL_CST)
return
- fold (build (MINUS_EXPR, type,
+ fold (build (MINUS_EXPR, type,
build_real (TREE_TYPE (arg1),
REAL_VALUE_NEGATE (TREE_REAL_CST (arg1))),
TREE_OPERAND (arg0, 0)));
if (! FLOAT_TYPE_P (type))
{
if (! wins && integer_zerop (arg0))
- return convert (type, negate_expr (arg1));
+ return negate_expr (convert (type, 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 convert (type, negate_expr (arg1));
+ return negate_expr (convert (type, arg1));
/* Except with IEEE floating point, x-0 equals x. */
if (real_zerop (arg1))
return non_lvalue (convert (type, arg0));
}
- /* Fold &x - &x. This can happen from &x.foo - &x.
+ /* Fold &x - &x. This can happen from &x.foo - &x.
This is unsafe for certain floats even in non-IEEE formats.
In IEEE, it is unsafe because it does wrong for NaNs.
Also note that operand_equal_p is always false if an operand
/* (-A) * (-B) -> A * B */
if (TREE_CODE (arg0) == NEGATE_EXPR && TREE_CODE (arg1) == NEGATE_EXPR)
return fold (build (MULT_EXPR, type, TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg1, 0)));
+ TREE_OPERAND (arg1, 0)));
if (! FLOAT_TYPE_P (type))
{
/* Convert (or (not arg0) (not arg1)) to (not (and (arg0) (arg1))).
- This results in more efficient code for machines without a NAND
+ This results in more efficient code for machines without a NAND
instruction. Combine will canonicalize to the first form
which will allow use of NAND instructions provided by the
backend if they exist. */
&& integer_zerop (const_binop (BIT_AND_EXPR,
TREE_OPERAND (arg0, 1),
TREE_OPERAND (arg1, 1), 0)))
- {
- code = BIT_IOR_EXPR;
- goto bit_ior;
- }
+ {
+ code = BIT_IOR_EXPR;
+ goto bit_ior;
+ }
/* See if this can be simplified into a rotate first. If that
is unsuccessful continue in the association code. */
/* Convert (and (not arg0) (not arg1)) to (not (or (arg0) (arg1))).
- This results in more efficient code for machines without a NOR
+ This results in more efficient code for machines without a NOR
instruction. Combine will canonicalize to the first form
which will allow use of NOR instructions provided by the
backend if they exist. */
REAL_VALUE_TYPE r;
r = TREE_REAL_CST (arg1);
if (exact_real_inverse (TYPE_MODE(TREE_TYPE(arg0)), &r))
- {
- tem = build_real (type, r);
- return fold (build (MULT_EXPR, type, arg0, tem));
- }
+ {
+ tem = build_real (type, r);
+ return fold (build (MULT_EXPR, type, arg0, tem));
+ }
}
}
goto binary;
&& multiple_of_p (type, arg0, arg1))
return fold (build (EXACT_DIV_EXPR, type, arg0, arg1));
- if (TREE_CODE (arg1) == INTEGER_CST
+ if (TREE_CODE (arg1) == INTEGER_CST
&& 0 != (tem = extract_muldiv (TREE_OPERAND (t, 0), arg1,
code, NULL_TREE)))
return convert (type, tem);
/* If either arg is constant true, drop it. */
if (TREE_CODE (arg0) == INTEGER_CST && ! integer_zerop (arg0))
return non_lvalue (convert (type, arg1));
- if (TREE_CODE (arg1) == INTEGER_CST && ! integer_zerop (arg1))
+ if (TREE_CODE (arg1) == INTEGER_CST && ! integer_zerop (arg1)
+ /* Preserve sequence points. */
+ && (code != TRUTH_ANDIF_EXPR || ! TREE_SIDE_EFFECTS (arg0)))
return non_lvalue (convert (type, arg0));
/* If second arg is constant zero, result is zero, but first arg
must be evaluated. */
/* If either arg is constant zero, drop it. */
if (TREE_CODE (arg0) == INTEGER_CST && integer_zerop (arg0))
return non_lvalue (convert (type, arg1));
- if (TREE_CODE (arg1) == INTEGER_CST && integer_zerop (arg1))
+ if (TREE_CODE (arg1) == INTEGER_CST && integer_zerop (arg1)
+ /* Preserve sequence points. */
+ && (code != TRUTH_ORIF_EXPR || ! TREE_SIDE_EFFECTS (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 (arg0) == NEGATE_EXPR && TREE_CODE (arg1) == REAL_CST)
return
fold (build
- (swap_tree_comparison (code), type,
- TREE_OPERAND (arg0, 0),
- build_real (TREE_TYPE (arg1),
- REAL_VALUE_NEGATE (TREE_REAL_CST (arg1)))));
+ (swap_tree_comparison (code), type,
+ TREE_OPERAND (arg0, 0),
+ build_real (TREE_TYPE (arg1),
+ REAL_VALUE_NEGATE (TREE_REAL_CST (arg1)))));
/* IEEE doesn't distinguish +0 and -0 in comparisons. */
/* a CMP (-0) -> a CMP 0 */
if (TREE_CODE (arg1) == REAL_CST
build_real (TREE_TYPE (arg1), dconst0)));
}
-
/* If one arg is a constant integer, put it last. */
if (TREE_CODE (arg0) == INTEGER_CST
&& TREE_CODE (arg1) != INTEGER_CST)
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. */
convert (TREE_TYPE (varop),
mask)));
}
-
- 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
convert (TREE_TYPE (varop),
mask)));
}
-
- 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_CODE (t1) == INTEGER_CST
&& int_fits_type_p (t1, TREE_TYPE (tem)))))
return fold (build (code, type, tem, convert (TREE_TYPE (tem), t1)));
-
+
/* If this is comparing a constant with a MIN_EXPR or a MAX_EXPR of a
constant, we can simplify it. */
else if (TREE_CODE (arg1) == INTEGER_CST
build (GE_EXPR, type, TREE_OPERAND (arg0, 0), tem),
build (LE_EXPR, 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
two operations, but the latter can be done in one less insn
&& TREE_UNSIGNED (TREE_TYPE (arg0))
&& TREE_CODE (arg1) == LSHIFT_EXPR
&& integer_onep (TREE_OPERAND (arg1, 0)))
- return build (code == LT_EXPR ? EQ_EXPR : NE_EXPR, type,
+ return build (code == LT_EXPR ? EQ_EXPR : NE_EXPR, type,
build (RSHIFT_EXPR, TREE_TYPE (arg0), arg0,
TREE_OPERAND (arg1, 1)),
convert (TREE_TYPE (arg0), integer_zero_node));
&& (TREE_INT_CST_LOW (arg1)
== ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1)
&& TREE_UNSIGNED (TREE_TYPE (arg1)))
-
+
switch (TREE_CODE (t))
{
case LE_EXPR:
{
case EQ_EXPR:
return
- pedantic_non_lvalue (convert (type, negate_expr (arg1)));
+ pedantic_non_lvalue
+ (convert (type,
+ negate_expr
+ (convert (TREE_TYPE (TREE_OPERAND (t, 1)),
+ arg1))));
+
case NE_EXPR:
return pedantic_non_lvalue (convert (type, arg1));
case GE_EXPR:
case LT_EXPR:
/* In C++ a ?: expression can be an lvalue, so put the
operand which will be used if they are equal first
- so that we can convert this back to the
+ so that we can convert this back to the
corresponding COND_EXPR. */
return pedantic_non_lvalue
(convert (type, fold (build (MIN_EXPR, comp_type,
if (integer_onep (TREE_OPERAND (t, 1))
&& integer_zerop (TREE_OPERAND (t, 2))
/* If we try to convert TREE_OPERAND (t, 0) to our type, the
- call to fold will try to move the conversion inside
+ call to fold will try to move the conversion inside
a COND, which will recurse. In that case, the COND_EXPR
is probably the best choice, so leave it alone. */
&& type == TREE_TYPE (arg0))
tree arg01;
if (kind0 == '1' || code0 == TRUTH_NOT_EXPR)
- return fold (build1 (code0, type,
+ return fold (build1 (code0, type,
fold (build1 (CLEANUP_POINT_EXPR,
TREE_TYPE (arg00), arg00))));
return t;
}
+ case CALL_EXPR:
+ /* Check for a built-in function. */
+ if (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR
+ && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (expr, 0), 0))
+ == FUNCTION_DECL)
+ && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (expr, 0), 0)))
+ {
+ tree tmp = fold_builtin (expr);
+ if (tmp)
+ return tmp;
+ }
+ return t;
+
default:
return t;
} /* switch (code) */
return 0;
}
}
+
+/* Return true if `t' is known to be non-negative. */
+
+int
+tree_expr_nonnegative_p (t)
+ tree t;
+{
+ switch (TREE_CODE (t))
+ {
+ case INTEGER_CST:
+ return tree_int_cst_sgn (t) >= 0;
+ case COND_EXPR:
+ return tree_expr_nonnegative_p (TREE_OPERAND (t, 1))
+ && tree_expr_nonnegative_p (TREE_OPERAND (t, 2));
+ case BIND_EXPR:
+ return tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+ case RTL_EXPR:
+ return rtl_expr_nonnegative_p (RTL_EXPR_RTL (t));
+
+ default:
+ /* We don't know sign of `t', so be safe and return false. */
+ return 0;
+ }
+}
+
+/* Return true if `r' is known to be non-negative.
+ Only handles constants at the moment. */
+
+int
+rtl_expr_nonnegative_p (r)
+ rtx r;
+{
+ switch (GET_CODE (r))
+ {
+ case CONST_INT:
+ return INTVAL (r) >= 0;
+
+ case CONST_DOUBLE:
+ if (GET_MODE (r) == VOIDmode)
+ return CONST_DOUBLE_HIGH (r) >= 0;
+ return 0;
+
+ case SYMBOL_REF:
+ case LABEL_REF:
+ /* These are always nonnegative. */
+ return 1;
+
+ default:
+ return 0;
+ }
+}