OSDN Git Service

2000-07-21 Alexandre Petit-Bianco <apbianco@cygnus.com>
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index 4eaf4ce..991ad2e 100644 (file)
@@ -1,5 +1,6 @@
 /* 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.
 
@@ -52,61 +53,67 @@ Boston, MA 02111-1307, USA.  */
 #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
@@ -135,7 +142,8 @@ static int count_cond               PROTO((tree, int));
 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);
@@ -150,7 +158,8 @@ encode (words, low, hi)
 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;
@@ -171,8 +180,9 @@ force_fit_type (t, overflow)
      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)
     {
@@ -205,7 +215,7 @@ force_fit_type (t, overflow)
     {
       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.  */
@@ -215,9 +225,11 @@ force_fit_type (t, 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.  */
@@ -228,7 +240,7 @@ force_fit_type (t, overflow)
        {
          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);
        }
     }
 
@@ -245,13 +257,16 @@ force_fit_type (t, overflow)
 
 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;
@@ -265,8 +280,10 @@ add_double (l1, h1, l2, h2, lv, hv)
 
 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)
     {
@@ -290,15 +307,18 @@ neg_double (l1, h1, lv, hv)
 
 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);
@@ -347,9 +367,11 @@ mul_double (l1, h1, l2, h2, lv, hv)
 
 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)
@@ -363,16 +385,23 @@ lshift_double (l1, h1, count, prec, lv, hv, arith)
     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;
     }
 }
 
@@ -383,12 +412,15 @@ lshift_double (l1, h1, count, prec, lv, hv, arith)
 
 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);
@@ -398,7 +430,14 @@ rshift_double (l1, h1, count, prec, lv, hv, arith)
     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)
@@ -406,7 +445,7 @@ rshift_double (l1, h1, count, prec, lv, hv, arith)
     }
   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));
@@ -420,11 +459,14 @@ rshift_double (l1, h1, count, prec, lv, hv, arith)
 
 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)
@@ -442,11 +484,14 @@ lrotate_double (l1, h1, count, prec, lv, hv)
 
 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)
@@ -473,23 +518,26 @@ div_and_round_double (code, uns,
                      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.  */
@@ -499,7 +547,8 @@ div_and_round_double (code, uns,
        {
          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) 
@@ -513,7 +562,7 @@ div_and_round_double (code, uns,
     {                          /* single precision */
       *hquo = *hrem = 0;
       /* This unsigned division rounds toward zero.  */
-      *lquo = lnum / (unsigned HOST_WIDE_INT) lden;
+      *lquo = lnum / lden;
       goto finish_up;
     }
 
@@ -535,106 +584,113 @@ div_and_round_double (code, uns,
   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);
 
@@ -663,7 +719,8 @@ div_and_round_double (code, uns,
          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:
@@ -673,28 +730,33 @@ div_and_round_double (code, uns,
          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, &ltwice, &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;  */
@@ -705,7 +767,8 @@ div_and_round_double (code, uns,
              add_double (*lquo, *hquo, (HOST_WIDE_INT) 1, (HOST_WIDE_INT) 0,
                          lquo, hquo);
          }
-       else return overflow;
+       else
+         return overflow;
       }
       break;
 
@@ -860,7 +923,7 @@ target_negative (x)
 
 int
 target_isinf (x)
-     REAL_VALUE_TYPE x;
+     REAL_VALUE_TYPE x ATTRIBUTE_UNUSED;
 {
   return 0;
 }
@@ -870,7 +933,7 @@ target_isinf (x)
 
 int
 target_isnan (x)
-     REAL_VALUE_TYPE x;
+     REAL_VALUE_TYPE x ATTRIBUTE_UNUSED;
 {
   return 0;
 }
@@ -900,7 +963,9 @@ exact_real_inverse (mode, r)
       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)
@@ -987,7 +1052,7 @@ real_hex_to_f (s, mode)
    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.  */
@@ -1034,8 +1099,8 @@ real_hex_to_f (s, mode)
        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;
@@ -1080,7 +1145,7 @@ real_hex_to_f (s, mode)
              The exponent field is a decimal integer.  */
           while (ISDIGIT(*p))
             {
-              k = (*p++ & 0x7f) - '0';
+              k = (*p++ & CHARMASK) - '0';
               expon = 10 * expon + k;
             }
 
@@ -1395,9 +1460,12 @@ int_const_binop (code, arg1, arg2, notrunc, forsize)
      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;
@@ -1432,18 +1500,15 @@ int_const_binop (code, arg1, arg2, notrunc, forsize)
       /* 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;
 
@@ -1465,13 +1530,14 @@ int_const_binop (code, arg1, arg2, notrunc, forsize)
     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;
        }
@@ -1498,10 +1564,10 @@ int_const_binop (code, arg1, arg2, notrunc, forsize)
     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;
@@ -1524,13 +1590,10 @@ int_const_binop (code, arg1, arg2, notrunc, forsize)
                < (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;
@@ -1542,13 +1605,8 @@ int_const_binop (code, arg1, arg2, notrunc, forsize)
       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);
@@ -1779,20 +1837,26 @@ const_binop (code, arg1, arg2, notrunc)
   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;
   
@@ -1803,12 +1867,16 @@ size_int_wide (number, high, bit_p)
       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.  */
@@ -1817,8 +1885,9 @@ size_int_wide (number, high, bit_p)
        }
 
       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 ();
@@ -1826,14 +1895,15 @@ size_int_wide (number, high, bit_p)
       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
@@ -1841,6 +1911,12 @@ size_binop (code, arg0, arg1)
      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)
     {
@@ -1860,41 +1936,49 @@ size_binop (code, arg0, arg1)
   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.  */
@@ -1939,6 +2023,12 @@ fold_convert (t, arg1)
          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),
@@ -2233,8 +2323,7 @@ operand_equal_p (arg0, arg1, only_const)
       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)
@@ -2250,7 +2339,7 @@ operand_equal_p (arg0, arg1, only_const)
 
       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)));
 
@@ -2348,7 +2437,7 @@ operand_equal_for_comparison_p (arg0, arg1, other)
 {
   int unsignedp1, unsignedpo;
   tree primarg0, primarg1, primother;
-  unsigned correct_width;
+  unsigned int correct_width;
 
   if (operand_equal_p (arg0, arg1, 0))
     return 1;
@@ -2644,8 +2733,7 @@ invert_truthvalue (arg)
   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,
@@ -2793,7 +2881,7 @@ make_bit_field_ref (inner, type, bitsize, bitpos, unsignedp)
      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;
 
@@ -2826,14 +2914,14 @@ optimize_bit_field_compare (code, compare_type, lhs, rhs)
      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;
@@ -3002,7 +3090,7 @@ static tree
 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;
@@ -3011,8 +3099,8 @@ decode_field_reference (exp, pbitsize, pbitpos, pmode, punsignedp,
   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
@@ -3068,7 +3156,7 @@ all_ones_mask_p (mask, size)
      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);
@@ -3098,7 +3186,7 @@ simple_operand_p (exp)
     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)
@@ -3116,7 +3204,7 @@ simple_operand_p (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
@@ -3211,7 +3299,7 @@ range_binop (code, type, arg0, upper0_p, arg1, upper1_p)
 \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.  */
 
@@ -3249,7 +3337,7 @@ make_range (exp, pin_p, plow, phigh)
          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);
        }
 
@@ -3315,9 +3403,10 @@ make_range (exp, pin_p, plow, phigh)
 
              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,
@@ -3366,8 +3455,17 @@ make_range (exp, pin_p, plow, phigh)
              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;
@@ -3796,7 +3894,7 @@ fold_truthop (code, truth_type, lhs, rhs)
      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).
@@ -3809,10 +3907,10 @@ fold_truthop (code, truth_type, lhs, rhs)
   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;
@@ -4249,9 +4347,13 @@ optimize_minmax_comparison (t)
    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.  */
@@ -4270,11 +4372,11 @@ extract_muldiv (t, c, code, wide_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);
@@ -4295,6 +4397,17 @@ extract_muldiv (t, c, code, wide_type)
       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
@@ -4310,6 +4423,11 @@ extract_muldiv (t, c, code, wide_type)
       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)
@@ -4345,6 +4463,10 @@ extract_muldiv (t, c, code, wide_type)
         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)))
@@ -4391,9 +4513,24 @@ extract_muldiv (t, c, code, wide_type)
            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,
@@ -4450,11 +4587,17 @@ extract_muldiv (t, c, code, wide_type)
       /* 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),
@@ -4623,10 +4766,9 @@ fold (expr)
           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++)
        {
@@ -4643,10 +4785,8 @@ fold (expr)
              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);
@@ -4694,7 +4834,7 @@ fold (expr)
      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
@@ -4948,17 +5088,17 @@ fold (expr)
          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 
@@ -5047,10 +5187,9 @@ fold (expr)
          /* 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);
            }
@@ -5076,7 +5215,8 @@ fold (expr)
        {
          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);
@@ -5110,7 +5250,8 @@ fold (expr)
              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);
@@ -5136,9 +5277,9 @@ fold (expr)
 
     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)
@@ -5338,9 +5479,10 @@ fold (expr)
                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 
@@ -5355,9 +5497,10 @@ fold (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 
@@ -5435,7 +5578,7 @@ fold (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));
 
@@ -5458,7 +5601,7 @@ fold (expr)
        {
          /* 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));
@@ -5595,7 +5738,9 @@ fold (expr)
       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)
@@ -5604,7 +5749,9 @@ fold (expr)
       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)
@@ -5778,14 +5925,14 @@ fold (expr)
          && 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);
@@ -5793,7 +5940,7 @@ fold (expr)
 
     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))
@@ -5817,13 +5964,13 @@ fold (expr)
         ("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))
@@ -5903,13 +6050,13 @@ fold (expr)
         ("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))
@@ -5923,14 +6070,14 @@ fold (expr)
     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:
@@ -6000,7 +6147,15 @@ fold (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.  */
@@ -6013,7 +6168,7 @@ fold (expr)
                                          (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
@@ -6044,9 +6199,9 @@ fold (expr)
                  }
                                                         
 
-               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;
              }
          }
@@ -6059,7 +6214,15 @@ fold (expr)
                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
@@ -6070,7 +6233,7 @@ fold (expr)
                                          (TREE_OPERAND
                                           (TREE_OPERAND (varop, 0), 1)));
                    tree mask, unsigned_type;
-                   int precision;
+                   unsigned int precision;
                    tree folded_compare;
 
                    if (constopnum == 0)
@@ -6098,9 +6261,9 @@ fold (expr)
                  }
                                                         
 
-               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;
              }
          }
@@ -6361,7 +6524,7 @@ fold (expr)
          {
            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))
                {
@@ -6387,7 +6550,7 @@ fold (expr)
 
            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))
                {
@@ -6413,7 +6576,7 @@ fold (expr)
 
            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))
@@ -6610,11 +6773,7 @@ fold (expr)
       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)
@@ -6733,7 +6892,8 @@ fold (expr)
            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:
@@ -6777,6 +6937,10 @@ fold (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:
@@ -6790,11 +6954,11 @@ fold (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:
@@ -6876,10 +7040,10 @@ fold (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
@@ -6929,8 +7093,8 @@ fold (expr)
        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)