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;
+ unsigned HOST_WIDE_INT carry;
+ int i, j, k;
unsigned HOST_WIDE_INT toplow, neglow;
HOST_WIDE_INT tophigh, neghigh;
HOST_WIDE_INT *hv;
int arith;
{
+ unsigned HOST_WIDE_INT signmask;
+
if (count < 0)
{
rshift_double (l1, h1, -count, prec, lv, hv, arith);
| (l1 >> (HOST_BITS_PER_WIDE_INT - count - 1) >> 1));
*lv = l1 << count;
}
+
+ /* Sign extend all bits that are beyond the precision. */
+
+ signmask = -((prec > HOST_BITS_PER_WIDE_INT
+ ? (*hv >> (prec - HOST_BITS_PER_WIDE_INT - 1))
+ : (*lv >> (prec - 1))) & 1);
+
+ if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
+ ;
+ else if (prec >= HOST_BITS_PER_WIDE_INT)
+ {
+ *hv &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
+ *hv |= signmask << (prec - HOST_BITS_PER_WIDE_INT);
+ }
+ else
+ {
+ *hv = signmask;
+ *lv &= ~((unsigned HOST_WIDE_INT) (-1) << prec);
+ *lv |= signmask << prec;
+ }
}
/* Shift the doubleword integer in L1, H1 right by COUNT places
rshift_double (l1, h1, count, prec, lv, hv, arith)
unsigned HOST_WIDE_INT l1;
HOST_WIDE_INT h1, count;
- unsigned int prec ATTRIBUTE_UNUSED;
+ unsigned int prec;
unsigned HOST_WIDE_INT *lv;
HOST_WIDE_INT *hv;
int arith;
{
/* 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;
+ *hv = 0;
+ *lv = 0;
}
else if (count >= HOST_BITS_PER_WIDE_INT)
{
- *hv = signmask;
- *lv = ((signmask << (2 * HOST_BITS_PER_WIDE_INT - count - 1) << 1)
- | ((unsigned HOST_WIDE_INT) h1 >> (count - HOST_BITS_PER_WIDE_INT)));
+ *hv = 0;
+ *lv = (unsigned HOST_WIDE_INT) h1 >> (count - HOST_BITS_PER_WIDE_INT);
}
else
{
+ *hv = (unsigned HOST_WIDE_INT) h1 >> count;
*lv = ((l1 >> count)
| ((unsigned HOST_WIDE_INT) h1 << (HOST_BITS_PER_WIDE_INT - count - 1) << 1));
- *hv = ((signmask << (HOST_BITS_PER_WIDE_INT - count))
- | ((unsigned HOST_WIDE_INT) h1 >> count));
+ }
+
+ /* Zero / sign extend all bits that are beyond the precision. */
+
+ if (count >= (HOST_WIDE_INT)prec)
+ {
+ *hv = signmask;
+ *lv = signmask;
+ }
+ else if ((prec - count) >= 2 * HOST_BITS_PER_WIDE_INT)
+ ;
+ else if ((prec - count) >= HOST_BITS_PER_WIDE_INT)
+ {
+ *hv &= ~((HOST_WIDE_INT) (-1) << (prec - count - HOST_BITS_PER_WIDE_INT));
+ *hv |= signmask << (prec - count - HOST_BITS_PER_WIDE_INT);
+ }
+ else
+ {
+ *hv = signmask;
+ *lv &= ~((unsigned HOST_WIDE_INT) (-1) << (prec - count));
+ *lv |= signmask << (prec - count);
}
}
\f
CODE is a tree code for a kind of division, one of
TRUNC_DIV_EXPR, FLOOR_DIV_EXPR, CEIL_DIV_EXPR, ROUND_DIV_EXPR
or EXACT_DIV_EXPR
- It controls how the quotient is rounded to a integer.
+ It controls how the quotient is rounded to an integer.
Return nonzero if the operation overflows.
UNS nonzero says do unsigned division. */
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;
+ int i, j;
unsigned HOST_WIDE_INT work;
unsigned HOST_WIDE_INT carry = 0;
unsigned HOST_WIDE_INT lnum = lnum_orig;
else
quo_est = BASE - 1;
- /* Refine quo_est so it's usually correct, and at most one high. */
+ /* 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
shcount = 0;
while ((c = *p) != '\0')
{
- if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')
- || (c >= 'a' && c <= 'f'))
+ if (ISXDIGIT (c))
{
k = c & CHARMASK;
if (k >= 'a' && k <= 'f')
static tree
int_const_binop (code, arg1, arg2, notrunc)
enum tree_code code;
- register tree arg1, arg2;
+ tree arg1, arg2;
int notrunc;
{
unsigned HOST_WIDE_INT int1l, int2l;
HOST_WIDE_INT hi;
unsigned HOST_WIDE_INT garbagel;
HOST_WIDE_INT garbageh;
- register tree t;
+ tree t;
tree type = TREE_TYPE (arg1);
int uns = TREE_UNSIGNED (type);
int is_sizetype
static tree
const_binop (code, arg1, arg2, notrunc)
enum tree_code code;
- register tree arg1, arg2;
+ tree arg1, arg2;
int notrunc;
{
STRIP_NOPS (arg1);
#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
if (TREE_CODE (arg1) == COMPLEX_CST)
{
- register tree type = TREE_TYPE (arg1);
- register tree r1 = TREE_REALPART (arg1);
- register tree i1 = TREE_IMAGPART (arg1);
- register tree r2 = TREE_REALPART (arg2);
- register tree i2 = TREE_IMAGPART (arg2);
- register tree t;
+ tree type = TREE_TYPE (arg1);
+ tree r1 = TREE_REALPART (arg1);
+ tree i1 = TREE_IMAGPART (arg1);
+ tree r2 = TREE_REALPART (arg2);
+ tree i2 = TREE_IMAGPART (arg2);
+ tree t;
switch (code)
{
case RDIV_EXPR:
{
- register tree magsquared
+ tree magsquared
= const_binop (PLUS_EXPR,
const_binop (MULT_EXPR, r2, r2, notrunc),
const_binop (MULT_EXPR, i2, i2, notrunc),
{
tree arg1; /* Input: value to convert. */
tree type; /* Input: type to convert value to. */
- tree t; /* Ouput: result of conversion. */
+ tree t; /* Output: result of conversion. */
};
/* Function to convert floating-point constants, protected by floating
static tree
fold_convert (t, arg1)
- register tree t;
- register tree arg1;
+ tree t;
+ tree arg1;
{
- register tree type = TREE_TYPE (t);
+ tree type = TREE_TYPE (t);
int overflow = 0;
if (POINTER_TYPE_P (type) || INTEGRAL_TYPE_P (type))
enum machine_mode lmode, rmode, nmode;
int lunsignedp, runsignedp;
int lvolatilep = 0, rvolatilep = 0;
- unsigned int alignment;
tree linner, rinner = NULL_TREE;
tree mask;
tree offset;
do anything if the inner expression is a PLACEHOLDER_EXPR since we
then will no longer be able to replace it. */
linner = get_inner_reference (lhs, &lbitsize, &lbitpos, &offset, &lmode,
- &lunsignedp, &lvolatilep, &alignment);
+ &lunsignedp, &lvolatilep);
if (linner == lhs || lbitsize == GET_MODE_BITSIZE (lmode) || lbitsize < 0
|| offset != 0 || TREE_CODE (linner) == PLACEHOLDER_EXPR)
return 0;
if (!const_p)
{
/* If this is not a constant, we can only do something if bit positions,
- sizes, and signedness are the same. */
+ sizes, and signedness are the same. */
rinner = get_inner_reference (rhs, &rbitsize, &rbitpos, &offset, &rmode,
- &runsignedp, &rvolatilep, &alignment);
+ &runsignedp, &rvolatilep);
if (rinner == rhs || lbitpos != rbitpos || lbitsize != rbitsize
|| lunsignedp != runsignedp || offset != 0
tree mask, inner, offset;
tree unsigned_type;
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
}
inner = get_inner_reference (exp, pbitsize, pbitpos, &offset, pmode,
- punsignedp, pvolatilep, &alignment);
+ punsignedp, pvolatilep);
if ((inner == exp && and_mask == 0)
|| *pbitsize < 0 || offset != 0
|| TREE_CODE (inner) == PLACEHOLDER_EXPR)
{
if (code == CEIL_DIV_EXPR)
code = FLOOR_DIV_EXPR;
- else if (code == CEIL_MOD_EXPR)
- code = FLOOR_MOD_EXPR;
else if (code == FLOOR_DIV_EXPR)
code = CEIL_DIV_EXPR;
- else if (code == FLOOR_MOD_EXPR)
- code = CEIL_MOD_EXPR;
- else if (code != MULT_EXPR)
+ else if (code != MULT_EXPR
+ && code != CEIL_MOD_EXPR && code != FLOOR_MOD_EXPR)
break;
}
multiple of the other, in which case we replace this with either an
operation or CODE or TCODE.
- If we have an unsigned type that is not a sizetype, we canot do
+ If we have an unsigned type that is not a sizetype, we cannot do
this since it will change the result if the original computation
overflowed. */
if ((! TREE_UNSIGNED (ctype)
side of the expression to be executed if the condition is true
will be pointed to by TRUE_LHS. Similarly, the right-hand side
of the expression to be executed if the condition is true will be
- pointed to by TRUE_RHS. FALSE_LHS and FALSE_RHS are analagous --
+ pointed to by TRUE_RHS. FALSE_LHS and FALSE_RHS are analogous --
but apply to the expression to be executed if the conditional is
false. */
tree *true_lhs;
fold (expr)
tree expr;
{
- register tree t = expr;
+ tree t = expr;
tree t1 = NULL_TREE;
tree tem;
tree type = TREE_TYPE (expr);
- register tree arg0 = NULL_TREE, arg1 = NULL_TREE;
- register enum tree_code code = TREE_CODE (t);
- register int kind = TREE_CODE_CLASS (code);
+ tree arg0 = NULL_TREE, arg1 = NULL_TREE;
+ enum tree_code code = TREE_CODE (t);
+ int kind = TREE_CODE_CLASS (code);
int invert;
/* WINS will be nonzero when the switch is done
if all operands are constant. */
}
else if (IS_EXPR_CODE_CLASS (kind) || kind == 'r')
{
- register int len = first_rtl_op (code);
- register int i;
+ int len = first_rtl_op (code);
+ int i;
for (i = 0; i < len; i++)
{
tree op = TREE_OPERAND (t, i);
}
return fold_convert (t, arg0);
+ case VIEW_CONVERT_EXPR:
+ if (TREE_CODE (TREE_OPERAND (t, 0)) == VIEW_CONVERT_EXPR)
+ return build1 (VIEW_CONVERT_EXPR, type,
+ TREE_OPERAND (TREE_OPERAND (t, 0), 0));
+ return t;
+
#if 0 /* This loses on &"foo"[0]. */
case ARRAY_REF:
{
/* (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;
+ enum tree_code code0, code1;
code0 = TREE_CODE (arg0);
code1 = TREE_CODE (arg1);
if (((code0 == RSHIFT_EXPR && code1 == LSHIFT_EXPR)
TREE_OPERAND (arg1, 0), 0)
&& TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
{
- register tree tree01, tree11;
- register enum tree_code code01, code11;
+ tree tree01, tree11;
+ enum tree_code code01, code11;
tree01 = TREE_OPERAND (arg0, 1);
tree11 = TREE_OPERAND (arg1, 1);
fold (build (code, type, imag0, imag1))));
}
+ /* Optimize comparisons of strlen vs zero to a compare of the
+ first character of the string vs zero. To wit,
+ strlen(ptr) == 0 => *ptr == 0
+ strlen(ptr) != 0 => *ptr != 0
+ Other cases should reduce to one of these two (or a constant)
+ due to the return value of strlen being unsigned. */
+ if ((code == EQ_EXPR || code == NE_EXPR)
+ && integer_zerop (arg1)
+ && TREE_CODE (arg0) == CALL_EXPR
+ && TREE_CODE (TREE_OPERAND (arg0, 0)) == ADDR_EXPR)
+ {
+ tree fndecl = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+ tree arglist;
+
+ if (TREE_CODE (fndecl) == FUNCTION_DECL
+ && DECL_BUILT_IN (fndecl)
+ && DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_MD
+ && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STRLEN
+ && (arglist = TREE_OPERAND (arg0, 1))
+ && TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) == POINTER_TYPE
+ && ! TREE_CHAIN (arglist))
+ return fold (build (code, type,
+ build1 (INDIRECT_REF, char_type_node,
+ TREE_VALUE(arglist)),
+ integer_zero_node));
+ }
+
/* From here on, the only cases we handle are when the result is
known to be a constant.