OSDN Git Service

Fix bad regexp
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index ff925c9..084308e 100644 (file)
@@ -1,23 +1,23 @@
 /* Fold a constant sub-tree into a single node for C-compiler
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
 
 /*@@ This file should be rewritten to use an arbitrary precision
   @@ representation for "struct tree_int_cst" and "struct tree_real_cst".
@@ -27,7 +27,6 @@ Boston, MA 02111-1307, USA.  */
   @@ 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.
 
@@ -45,31 +44,30 @@ Boston, MA 02111-1307, USA.  */
 
 #include "config.h"
 #include "system.h"
-#include <setjmp.h>
 #include "flags.h"
 #include "tree.h"
 #include "rtl.h"
+#include "expr.h"
 #include "tm_p.h"
 #include "toplev.h"
 #include "ggc.h"
+#include "hashtab.h"
+#include "langhooks.h"
 
 static void encode             PARAMS ((HOST_WIDE_INT *,
-                                        HOST_WIDE_INT, HOST_WIDE_INT));
+                                        unsigned HOST_WIDE_INT,
+                                        HOST_WIDE_INT));
 static void decode             PARAMS ((HOST_WIDE_INT *,
-                                        HOST_WIDE_INT *, HOST_WIDE_INT *));
-int div_and_round_double       PARAMS ((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 *,
+                                        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));
+                                        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 int_const_binop    PARAMS ((enum tree_code, tree, tree, int));
 static tree const_binop                PARAMS ((enum tree_code, tree, tree, int));
-static void fold_convert_1     PARAMS ((PTR));
+static hashval_t size_htab_hash        PARAMS ((const void *));
+static int size_htab_eq                PARAMS ((const void *, const void *));
 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));
@@ -83,7 +81,8 @@ 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, int *, int *,
+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));
@@ -103,9 +102,15 @@ 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
+static tree fold_binary_op_with_conditional_arg 
+  PARAMS ((enum tree_code, tree, tree, tree, int));
+static bool fold_real_zero_addition_p  PARAMS ((tree, tree, int));
+                                                        
+#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
@@ -136,7 +141,8 @@ static int count_cond               PARAMS ((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);
@@ -151,7 +157,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;
@@ -172,8 +179,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)
     {
@@ -206,19 +214,24 @@ 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.  */
-  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.  */
   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.  */
@@ -229,7 +242,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);
        }
     }
 
@@ -246,13 +259,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 < (unsigned HOST_WIDE_INT) l1);
+  h = h1 + h2 + (l < l1);
 
   *lv = l;
   *hv = h;
@@ -266,8 +282,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)
     {
@@ -277,8 +295,8 @@ neg_double (l1, h1, lv, hv)
     }
   else
     {
-      *lv = - l1;
-      *hv = ~ h1;
+      *lv = -l1;
+      *hv = ~h1;
       return 0;
     }
 }
@@ -291,20 +309,23 @@ 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 carry;
+  int i, j, k;
+  unsigned HOST_WIDE_INT toplow, neglow;
+  HOST_WIDE_INT tophigh, neghigh;
 
   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++)
     {
@@ -326,7 +347,7 @@ mul_double (l1, h1, l2, h2, lv, hv)
 
   /* 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);
@@ -348,17 +369,21 @@ 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;
 {
+  unsigned HOST_WIDE_INT signmask;
+
   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;
@@ -373,14 +398,34 @@ lshift_double (l1, h1, count, prec, lv, hv, arith)
     }
   else if (count >= HOST_BITS_PER_WIDE_INT)
     {
-      *hv = (unsigned HOST_WIDE_INT) l1 << (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;
+    }
+
+  /* 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;
     }
 }
 
@@ -391,12 +436,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;
+     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);
@@ -410,21 +458,40 @@ rshift_double (l1, h1, count, prec, lv, hv, 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
     {
-      *lv = (((unsigned HOST_WIDE_INT) l1 >> count)
+      *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
@@ -435,11 +502,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)
@@ -457,11 +527,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)
@@ -478,7 +551,7 @@ rrotate_double (l1, h1, count, prec, lv, hv)
    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.  */
 
@@ -488,36 +561,40 @@ 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;
+  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.  */
-  if (!uns) 
+  if (!uns)
     {
       if (hnum < 0)
        {
          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) 
+      if (hden < 0)
        {
          quo_neg = ~ quo_neg;
          neg_double (lden, hden, &lden, &hden);
@@ -528,7 +605,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;
     }
 
@@ -541,115 +618,123 @@ div_and_round_double (code, uns,
       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.  */
-  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;
+      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;
-      }
-
-    /* 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);
 
@@ -678,7 +763,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:
@@ -688,28 +774,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;  */
@@ -720,7 +811,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;
 
@@ -735,498 +827,6 @@ div_and_round_double (code, uns,
   return overflow;
 }
 \f
-#ifndef REAL_ARITHMETIC
-/* Effectively truncate a real value to represent the nearest possible value
-   in a narrower mode.  The result is actually represented in the same data
-   type as the argument, but its value is usually different.
-
-   A trap may occur during the FP operations and it is the responsibility
-   of the calling function to have a handler established.  */
-
-REAL_VALUE_TYPE
-real_value_truncate (mode, arg)
-     enum machine_mode mode;
-     REAL_VALUE_TYPE arg;
-{
-  return REAL_VALUE_TRUNCATE (mode, arg);
-}
-
-#if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
-
-/* Check for infinity in an IEEE double precision number.  */
-
-int
-target_isinf (x)
-     REAL_VALUE_TYPE x;
-{
-  /* The IEEE 64-bit double format.  */
-  union {
-    REAL_VALUE_TYPE d;
-    struct {
-      unsigned sign      :  1;
-      unsigned exponent  : 11;
-      unsigned mantissa1 : 20;
-      unsigned mantissa2;
-    } little_endian;
-    struct {
-      unsigned mantissa2;
-      unsigned mantissa1 : 20;
-      unsigned exponent  : 11;
-      unsigned sign      :  1;
-    } big_endian;    
-  } u;
-
-  u.d = dconstm1;
-  if (u.big_endian.sign == 1)
-    {
-      u.d = x;
-      return (u.big_endian.exponent == 2047
-             && u.big_endian.mantissa1 == 0
-             && u.big_endian.mantissa2 == 0);
-    }
-  else
-    {
-      u.d = x;
-      return (u.little_endian.exponent == 2047
-             && u.little_endian.mantissa1 == 0
-             && u.little_endian.mantissa2 == 0);
-    }
-}
-
-/* Check whether an IEEE double precision number is a NaN.  */
-
-int
-target_isnan (x)
-     REAL_VALUE_TYPE x;
-{
-  /* The IEEE 64-bit double format.  */
-  union {
-    REAL_VALUE_TYPE d;
-    struct {
-      unsigned sign      :  1;
-      unsigned exponent  : 11;
-      unsigned mantissa1 : 20;
-      unsigned mantissa2;
-    } little_endian;
-    struct {
-      unsigned mantissa2;
-      unsigned mantissa1 : 20;
-      unsigned exponent  : 11;
-      unsigned sign      :  1;
-    } big_endian;    
-  } u;
-
-  u.d = dconstm1;
-  if (u.big_endian.sign == 1)
-    {
-      u.d = x;
-      return (u.big_endian.exponent == 2047
-             && (u.big_endian.mantissa1 != 0
-                 || u.big_endian.mantissa2 != 0));
-    }
-  else
-    {
-      u.d = x;
-      return (u.little_endian.exponent == 2047
-             && (u.little_endian.mantissa1 != 0
-                 || u.little_endian.mantissa2 != 0));
-    }
-}
-
-/* Check for a negative IEEE double precision number.  */
-
-int
-target_negative (x)
-     REAL_VALUE_TYPE x;
-{
-  /* The IEEE 64-bit double format.  */
-  union {
-    REAL_VALUE_TYPE d;
-    struct {
-      unsigned sign      :  1;
-      unsigned exponent  : 11;
-      unsigned mantissa1 : 20;
-      unsigned mantissa2;
-    } little_endian;
-    struct {
-      unsigned mantissa2;
-      unsigned mantissa1 : 20;
-      unsigned exponent  : 11;
-      unsigned sign      :  1;
-    } big_endian;    
-  } u;
-
-  u.d = dconstm1;
-  if (u.big_endian.sign == 1)
-    {
-      u.d = x;
-      return u.big_endian.sign;
-    }
-  else
-    {
-      u.d = x;
-      return u.little_endian.sign;
-    }
-}
-#else /* Target not IEEE */
-
-/* Let's assume other float formats don't have infinity.
-   (This can be overridden by redefining REAL_VALUE_ISINF.)  */
-
-int
-target_isinf (x)
-     REAL_VALUE_TYPE x ATTRIBUTE_UNUSED;
-{
-  return 0;
-}
-
-/* Let's assume other float formats don't have NaNs.
-   (This can be overridden by redefining REAL_VALUE_ISNAN.)  */
-
-int
-target_isnan (x)
-     REAL_VALUE_TYPE x ATTRIBUTE_UNUSED;
-{
-  return 0;
-}
-
-/* Let's assume other float formats don't have minus zero.
-   (This can be overridden by redefining REAL_VALUE_NEGATIVE.)  */
-
-int
-target_negative (x)
-     REAL_VALUE_TYPE x;
-{
-  return x < 0;
-}
-#endif /* Target not IEEE */
-
-/* Try to change R into its exact multiplicative inverse in machine mode
-   MODE.  Return nonzero function value if successful.  */
-
-int
-exact_real_inverse (mode, r)
-     enum machine_mode mode;
-     REAL_VALUE_TYPE *r;
-{
-  jmp_buf float_error;
-  union
-    {
-      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)
-    return 0;
-
-  /* Set array index to the less significant bits in the unions, depending
-     on the endian-ness of the host doubles.
-     Disable if insufficient information on the data structure.  */
-#if HOST_FLOAT_FORMAT == UNKNOWN_FLOAT_FORMAT
-  return 0;
-#else
-#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
-#define K 2
-#else
-#if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT
-#define K 2
-#else
-#define K (2 * HOST_FLOAT_WORDS_BIG_ENDIAN)
-#endif
-#endif
-#endif
-
-  if (setjmp (float_error))
-    {
-      /* Don't do the optimization if there was an arithmetic error.  */
-fail:
-      set_float_handler (NULL_PTR);
-      return 0;
-    }
-  set_float_handler (float_error);
-
-  /* Domain check the argument.  */
-  x.d = *r;
-  if (x.d == 0.0)
-    goto fail;
-
-#ifdef REAL_INFINITY
-  if (REAL_VALUE_ISINF (x.d) || REAL_VALUE_ISNAN (x.d))
-    goto fail;
-#endif
-
-  /* Compute the reciprocal and check for numerical exactness.
-     It is unnecessary to check all the significand bits to determine
-     whether X is a power of 2.  If X is not, then it is impossible for
-     the bottom half significand of both X and 1/X to be all zero bits.
-     Hence we ignore the data structure of the top half and examine only
-     the low order bits of the two significands.  */
-  t.d = 1.0 / x.d;
-  if (x.i[K] != 0 || x.i[K + 1] != 0 || t.i[K] != 0 || t.i[K + 1] != 0)
-    goto fail;
-
-  /* Truncate to the required mode and range-check the result.  */
-  y.d = REAL_VALUE_TRUNCATE (mode, t.d);
-#ifdef CHECK_FLOAT_VALUE
-  i = 0;
-  if (CHECK_FLOAT_VALUE (mode, y.d, i))
-    goto fail;
-#endif
-
-  /* Fail if truncation changed the value.  */
-  if (y.d != t.d || y.d == 0.0)
-    goto fail;
-
-#ifdef REAL_INFINITY
-  if (REAL_VALUE_ISINF (y.d) || REAL_VALUE_ISNAN (y.d))
-    goto fail;
-#endif
-
-  /* Output the reciprocal and return success flag.  */
-  set_float_handler (NULL_PTR);
-  *r = y.d;
-  return 1;
-}
-
-/* Convert C9X 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.  */
-
-REAL_VALUE_TYPE
-real_hex_to_f (s, mode)
-   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 & 0x7f;
-          if (k >= 'a')
-            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++ & 0x7f) - '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;
-#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;
-#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));
-
-   if (sign < 0)
-     ip = -ip;
-   return ip;
-}
-
-#endif /* no REAL_ARITHMETIC */
-\f
 /* Given T, an expression, return the negation of T.  Allow for T to be
    null, in which case return null.  */
 
@@ -1258,7 +858,7 @@ negate_expr (t)
 
     case MINUS_EXPR:
       /* - (A - B) -> B - A  */
-      if (! FLOAT_TYPE_P (type) || flag_fast_math)
+      if (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
        return convert (type,
                        fold (build (MINUS_EXPR, TREE_TYPE (t),
                                     TREE_OPERAND (t, 1),
@@ -1269,20 +869,23 @@ negate_expr (t)
       break;
     }
 
-  return convert (type, build1 (NEGATE_EXPR, TREE_TYPE (t), t));
+  return convert (type, fold (build1 (NEGATE_EXPR, TREE_TYPE (t), t)));
 }
 \f
 /* Split a tree IN into a constant, literal and variable parts that could be
    combined with CODE to make IN.  "constant" means an expression with
    TREE_CONSTANT but that isn't an actual constant.  CODE must be a
    commutative arithmetic operation.  Store the constant part into *CONP,
-   the literal in &LITP and return the variable part.  If a part isn't
+   the literal in *LITP and return the variable part.  If a part isn't
    present, set it to null.  If the tree does not decompose in this way,
    return the entire tree as the variable part and the other parts as null.
 
    If CODE is PLUS_EXPR we also split trees that use MINUS_EXPR.  In that
-   case, we negate an operand that was subtracted.  If NEGATE_P is true, we
-   are negating all of IN.
+   case, we negate an operand that was subtracted.  Except if it is a
+   literal for which we use *MINUS_LITP instead.
+
+   If NEGATE_P is true, we are negating all of IN, again except a literal
+   for which we use *MINUS_LITP instead.
 
    If IN is itself a literal or constant, return it as appropriate.
 
@@ -1290,25 +893,23 @@ negate_expr (t)
    same type as IN, but they will have the same signedness and mode.  */
 
 static tree
-split_tree (in, code, conp, litp, negate_p)
+split_tree (in, code, conp, litp, minus_litp, negate_p)
      tree in;
      enum tree_code code;
-     tree *conp, *litp;
+     tree *conp, *litp, *minus_litp;
      int negate_p;
 {
   tree var = 0;
 
   *conp = 0;
   *litp = 0;
+  *minus_litp = 0;
 
-  /* Strip any conversions that don't change the machine mode or signedness. */
+  /* Strip any conversions that don't change the machine mode or signedness.  */
   STRIP_SIGN_NOPS (in);
 
   if (TREE_CODE (in) == INTEGER_CST || TREE_CODE (in) == REAL_CST)
     *litp = in;
-  else if (TREE_CONSTANT (in))
-    *conp = in;
-
   else if (TREE_CODE (in) == code
           || (! FLOAT_TYPE_P (TREE_TYPE (in))
               /* We can associate addition and subtraction together (even
@@ -1335,7 +936,7 @@ split_tree (in, code, conp, litp, negate_p)
        *conp = op1, neg_conp_p = neg1_p, op1 = 0;
 
       /* If we haven't dealt with either operand, this is not a case we can
-        decompose.  Otherwise, VAR is either of the ones remaining, if any. */
+        decompose.  Otherwise, VAR is either of the ones remaining, if any.  */
       if (op0 != 0 && op1 != 0)
        var = in;
       else if (op0 != 0)
@@ -1344,18 +945,26 @@ split_tree (in, code, conp, litp, negate_p)
        var = op1, neg_var_p = neg1_p;
 
       /* Now do any needed negations.  */
-      if (neg_litp_p) *litp = negate_expr (*litp);
-      if (neg_conp_p) *conp = negate_expr (*conp);
-      if (neg_var_p) var = negate_expr (var);
+      if (neg_litp_p)
+       *minus_litp = *litp, *litp = 0;
+      if (neg_conp_p)
+       *conp = negate_expr (*conp);
+      if (neg_var_p)
+       var = negate_expr (var);
     }
+  else if (TREE_CONSTANT (in))
+    *conp = in;
   else
     var = in;
 
   if (negate_p)
     {
-      var = negate_expr (var);
+      if (*litp)
+       *minus_litp = *litp, *litp = 0;
+      else if (*minus_litp)
+       *litp = *minus_litp, *minus_litp = 0;
       *conp = negate_expr (*conp);
-      *litp = negate_expr (*litp);
+      var = negate_expr (var);
     }
 
   return var;
@@ -1363,9 +972,7 @@ split_tree (in, code, conp, litp, negate_p)
 
 /* Re-associate trees split by the above function.  T1 and T2 are either
    expressions to associate or null.  Return the new expression, if any.  If
-   we build an operation, do it in TYPE and with CODE, except if CODE is a
-   MINUS_EXPR, in which case we use PLUS_EXPR since split_tree will already
-   have taken care of the negations.  */
+   we build an operation, do it in TYPE and with CODE.  */
 
 static tree
 associate_trees (t1, t2, code, type)
@@ -1378,9 +985,6 @@ associate_trees (t1, t2, code, type)
   else if (t2 == 0)
     return t1;
 
-  if (code == MINUS_EXPR)
-    code = PLUS_EXPR;
-
   /* If either input is CODE, a PLUS_EXPR, or a MINUS_EXPR, don't
      try to fold this since we will have infinite recursion.  But do
      deal with any NEGATE_EXPRs.  */
@@ -1403,20 +1007,25 @@ associate_trees (t1, t2, code, type)
 /* Combine two integer constants ARG1 and ARG2 under operation CODE
    to produce a new constant.
 
-   If NOTRUNC is nonzero, do not truncate the result to fit the data type.
-   If FORSIZE is nonzero, compute overflow for unsigned types.  */
+   If NOTRUNC is nonzero, do not truncate the result to fit the data type.  */
 
 static tree
-int_const_binop (code, arg1, arg2, notrunc, forsize)
+int_const_binop (code, arg1, arg2, notrunc)
      enum tree_code code;
-     register tree arg1, arg2;
-     int notrunc, forsize;
+     tree arg1, arg2;
+     int notrunc;
 {
-  HOST_WIDE_INT int1l, int1h, int2l, int2h;
-  HOST_WIDE_INT low, hi;
-  HOST_WIDE_INT garbagel, garbageh;
-  register tree t;
-  int uns = TREE_UNSIGNED (TREE_TYPE (arg1));
+  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;
+  tree t;
+  tree type = TREE_TYPE (arg1);
+  int uns = TREE_UNSIGNED (type);
+  int is_sizetype
+    = (TREE_CODE (type) == INTEGER_TYPE && TYPE_IS_SIZETYPE (type));
   int overflow = 0;
   int no_overflow = 0;
 
@@ -1444,23 +1053,20 @@ int_const_binop (code, arg1, arg2, notrunc, forsize)
       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
         interpretation ruling is needed.  */
-      lshift_double (int1l, int1h, int2l,
-                    TYPE_PRECISION (TREE_TYPE (arg1)),
-                    &low, &hi,
-                    !uns);
+      lshift_double (int1l, int1h, int2l, TYPE_PRECISION (type),
+                    &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 (type),
                      &low, &hi);
       break;
 
@@ -1482,20 +1088,21 @@ 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;
        }
 
-      /* ... fall through ... */
+      /* ... fall through ...  */
 
-    case ROUND_DIV_EXPR: 
+    case ROUND_DIV_EXPR:
       if (int2h == 0 && int2l == 1)
        {
          low = int1l, hi = int1h;
@@ -1507,18 +1114,17 @@ int_const_binop (code, arg1, arg2, notrunc, forsize)
          low = 1, hi = 0;
          break;
        }
-      overflow = div_and_round_double (code, uns,
-                                      int1l, int1h, int2l, int2h,
+      overflow = div_and_round_double (code, uns, int1l, int1h, int2l, int2h,
                                       &low, &hi, &garbagel, &garbageh);
       break;
 
     case TRUNC_MOD_EXPR:
     case FLOOR_MOD_EXPR: case CEIL_MOD_EXPR:
       /* This is a shortcut for a common special case.  */
-      if (int2h == 0 && int2l > 0
+      if (int2h == 0 && (HOST_WIDE_INT) int2l > 0
          && ! TREE_CONSTANT_OVERFLOW (arg1)
          && ! TREE_CONSTANT_OVERFLOW (arg2)
-         && int1h == 0 && int1l >= 0)
+         && int1h == 0 && (HOST_WIDE_INT) int1l >= 0)
        {
          if (code == CEIL_MOD_EXPR)
            int1l += int2l - 1;
@@ -1526,9 +1132,9 @@ int_const_binop (code, arg1, arg2, notrunc, forsize)
          break;
        }
 
-      /* ... fall through ... */
+      /* ... 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);
@@ -1541,13 +1147,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;
@@ -1559,13 +1162,14 @@ 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 this is for a sizetype, can be represented as one (signed)
+     HOST_WIDE_INT word, and doesn't overflow, use size_int since it caches
+     constants.  */
+  if (is_sizetype
+      && ((hi == 0 && (HOST_WIDE_INT) low >= 0)
+         || (hi == -1 && (HOST_WIDE_INT) low < 0))
+      && overflow == 0 && ! TREE_OVERFLOW (arg1) && ! TREE_OVERFLOW (arg2))
+    return size_int_type_wide (low, type);
   else
     {
       t = build_int_2 (low, hi);
@@ -1573,14 +1177,16 @@ int_const_binop (code, arg1, arg2, notrunc, forsize)
     }
 
   TREE_OVERFLOW (t)
-    = ((notrunc ? (!uns || forsize) && overflow
-       : force_fit_type (t, (!uns || forsize) && overflow) && ! no_overflow)
+    = ((notrunc
+       ? (!uns || is_sizetype) && overflow
+       : (force_fit_type (t, (!uns || is_sizetype) && overflow)
+          && ! no_overflow))
        | TREE_OVERFLOW (arg1)
        | TREE_OVERFLOW (arg2));
 
   /* If we're doing a size calculation, unsigned arithmetic does overflow.
      So check if force_fit_type truncated the value.  */
-  if (forsize
+  if (is_sizetype
       && ! TREE_OVERFLOW (t)
       && (TREE_INT_CST_HIGH (t) != hi
          || TREE_INT_CST_LOW (t) != low))
@@ -1592,69 +1198,6 @@ int_const_binop (code, arg1, arg2, notrunc, forsize)
   return t;
 }
 
-/* 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. */
-};
-
-/* Do the real arithmetic for const_binop while protected by a
-   float overflow handler.  */
-
-static void
-const_binop_1 (data)
-  PTR data;
-{
-  struct cb_args *args = (struct cb_args *) data;
-  REAL_VALUE_TYPE value;
-
-#ifdef REAL_ARITHMETIC
-  REAL_ARITHMETIC (value, args->code, args->d1, args->d2);
-#else
-  switch (args->code)
-    {
-    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 ();
-    }
-#endif /* no REAL_ARITHMETIC */
-
-  args->t
-    = build_real (args->type,
-                 real_value_truncate (TYPE_MODE (args->type), value));
-}
-
 /* Combine two constants ARG1 and ARG2 under operation CODE to produce a new
    constant.  We assume ARG1 and ARG2 have the same data type, or at least
    are the same kind of constant and the same machine mode.
@@ -1664,22 +1207,21 @@ const_binop_1 (data)
 static tree
 const_binop (code, arg1, arg2, notrunc)
      enum tree_code code;
-     register tree arg1, arg2;
+     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);
+    return int_const_binop (code, arg1, arg2, notrunc);
 
-#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
   if (TREE_CODE (arg1) == REAL_CST)
     {
       REAL_VALUE_TYPE d1;
       REAL_VALUE_TYPE d2;
-      int overflow = 0;
+      REAL_VALUE_TYPE value;
       tree t;
-      struct cb_args args;
 
       d1 = TREE_REAL_CST (arg1);
       d2 = TREE_REAL_CST (arg2);
@@ -1691,24 +1233,14 @@ const_binop (code, arg1, arg2, notrunc)
       else if (REAL_VALUE_ISNAN (d2))
        return arg2;
 
-      /* Setup input for const_binop_1() */
-      args.type = TREE_TYPE (arg1);
-      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;
-      else
-       {
-         /* We got an exception from const_binop_1. */
-         t = copy_node (arg1);
-         overflow = 1;
-       }
+      REAL_ARITHMETIC (value, code, d1, d2);
+
+      t = build_real (TREE_TYPE (arg1),
+                     real_value_truncate (TYPE_MODE (TREE_TYPE (arg1)),
+                                          value));
 
       TREE_OVERFLOW (t)
-       = (force_fit_type (t, overflow)
+       = (force_fit_type (t, 0)
           | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2));
       TREE_CONSTANT_OVERFLOW (t)
        = TREE_OVERFLOW (t)
@@ -1716,15 +1248,14 @@ const_binop (code, arg1, arg2, notrunc)
          | TREE_CONSTANT_OVERFLOW (arg2);
       return t;
     }
-#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)
        {
@@ -1758,7 +1289,7 @@ const_binop (code, arg1, arg2, notrunc)
 
        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),
@@ -1795,65 +1326,95 @@ const_binop (code, arg1, arg2, notrunc)
     }
   return 0;
 }
+
+/* These are the hash table functions for the hash table of INTEGER_CST
+   nodes of a sizetype.  */
+
+/* Return the hash code code X, an INTEGER_CST.  */
+
+static hashval_t
+size_htab_hash (x)
+     const void *x;
+{
+  tree t = (tree) x;
+
+  return (TREE_INT_CST_HIGH (t) ^ TREE_INT_CST_LOW (t)
+         ^ (hashval_t) ((long) TREE_TYPE (t) >> 3)
+         ^ (TREE_OVERFLOW (t) << 20));
+}
+
+/* Return non-zero if the value represented by *X (an INTEGER_CST tree node)
+   is the same as that given by *Y, which is the same.  */
+
+static int
+size_htab_eq (x, y)
+     const void *x;
+     const void *y;
+{
+  tree xt = (tree) x;
+  tree yt = (tree) y;
+
+  return (TREE_INT_CST_HIGH (xt) == TREE_INT_CST_HIGH (yt)
+         && TREE_INT_CST_LOW (xt) == TREE_INT_CST_LOW (yt)
+         && TREE_TYPE (xt) == TREE_TYPE (yt)
+         && TREE_OVERFLOW (xt) == TREE_OVERFLOW (yt));
+}
 \f
 /* Return an INTEGER_CST with value whose low-order HOST_BITS_PER_WIDE_INT
-   bits are given by NUMBER.
+   bits are given by NUMBER and of the sizetype represented by KIND.  */
+
+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]);
+}
 
-   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.  */
+/* Likewise, but the desired type is specified explicitly.  */
 
 tree
-size_int_wide (number, bit_p)
+size_int_type_wide (number, type)
      HOST_WIDE_INT number;
-     int bit_p;
+     tree type;
 {
-  /* Type-size nodes already made for small sizes.  */
-  static tree size_table[2 * HOST_BITS_PER_WIDE_INT + 1][2];
-  static int init_p = 0;
-  tree t;
-  
-  if (ggc_p && ! init_p)
+  static htab_t size_htab = 0;
+  static tree new_const = 0;
+  PTR *slot;
+
+  if (size_htab == 0)
     {
-      ggc_add_tree_root ((tree *) size_table,
-                        sizeof size_table / sizeof (tree));
-      init_p = 1;
+      size_htab = htab_create (1024, size_htab_hash, size_htab_eq, NULL);
+      ggc_add_deletable_htab (size_htab, NULL, NULL);
+      new_const = make_node (INTEGER_CST);
+      ggc_add_tree_root (&new_const, 1);
     }
 
-  /* 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]) / 2)
+  /* Adjust NEW_CONST to be the constant we want.  If it's already in the
+     hash table, we return the value from the hash table.  Otherwise, we
+     place that in the hash table and make a new node for the next time.  */
+  TREE_INT_CST_LOW (new_const) = number;
+  TREE_INT_CST_HIGH (new_const) = number < 0 ? -1 : 0;
+  TREE_TYPE (new_const) = type;
+  TREE_OVERFLOW (new_const) = TREE_CONSTANT_OVERFLOW (new_const)
+    = force_fit_type (new_const, 0);
+
+  slot = htab_find_slot (size_htab, new_const, INSERT);
+  if (*slot == 0)
     {
-      if (size_table[number][bit_p] != 0)
-       return size_table[number][bit_p];
-
-      if (! ggc_p)
-       {
-         /* Make this a permanent node.  */
-         push_obstacks_nochange ();
-         end_temporary_allocation ();
-       }
-
-      t = build_int_2 (number, 0);
-      TREE_TYPE (t) = bit_p ? bitsizetype : sizetype;
-      size_table[number][bit_p] = t;
-
-      if (! ggc_p)
-       pop_obstacks ();
+      tree t = new_const;
 
+      *slot = (PTR) new_const;
+      new_const = make_node (INTEGER_CST);
       return t;
     }
-
-  t = build_int_2 (number, 0);
-  TREE_TYPE (t) = bit_p ? bitsizetype : sizetype;
-  TREE_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (t) = force_fit_type (t, 0);
-  return t;
+  else
+    return (tree) *slot;
 }
 
-/* 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
@@ -1861,6 +1422,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)
     {
@@ -1874,80 +1441,67 @@ size_binop (code, arg0, arg1)
        return arg1;
 
       /* Handle general case of two integer constants.  */
-      return int_const_binop (code, arg0, arg1, 0, 1);
+      return int_const_binop (code, arg0, arg1, 0);
     }
 
   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.  */
-struct fc_args
-{
-  tree arg1;                   /* Input: value to convert. */
-  tree type;                   /* Input: type to convert value to. */
-  tree t;                      /* Ouput: result of conversion. */
-};
-
-/* Function to convert floating-point constants, protected by floating
-   point exception handler.  */
-
-static void
-fold_convert_1 (data)
-  PTR data;
-{
-  struct fc_args * args = (struct fc_args *) data;
-
-  args->t = build_real (args->type,
-                       real_value_truncate (TYPE_MODE (args->type),
-                                            TREE_REAL_CST (args->arg1)));
-}
 
 /* Given T, a tree representing type conversion of ARG1, a constant,
    return a constant tree representing the result of conversion.  */
 
 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))
@@ -1959,6 +1513,13 @@ 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_TYPE && TYPE_IS_SIZETYPE (type)
+             && !TREE_CONSTANT_OVERFLOW (arg1)
+             && 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),
@@ -1979,7 +1540,6 @@ fold_convert (t, arg1)
          TREE_CONSTANT_OVERFLOW (t)
            = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
        }
-#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
       else if (TREE_CODE (arg1) == REAL_CST)
        {
          /* Don't initialize these, use assignments.
@@ -2000,15 +1560,9 @@ fold_convert (t, arg1)
          /* See if X will be in range after truncation towards 0.
             To compensate for truncation, move the bounds away from 0,
             but reject if X exactly equals the adjusted bounds.  */
-#ifdef REAL_ARITHMETIC
          REAL_ARITHMETIC (l, MINUS_EXPR, l, dconst1);
          if (!no_upper_bound)
            REAL_ARITHMETIC (u, PLUS_EXPR, u, dconst1);
-#else
-         l--;
-         if (!no_upper_bound)
-           u++;
-#endif
          /* If X is a NaN, use zero instead and show we have an overflow.
             Otherwise, range check.  */
          if (REAL_VALUE_ISNAN (x))
@@ -2018,54 +1572,25 @@ fold_convert (t, arg1)
                      && REAL_VALUES_LESS (x, u)))
            overflow = 1;
 
-#ifndef REAL_ARITHMETIC
-         {
-           HOST_WIDE_INT low, high;
-           HOST_WIDE_INT half_word
-             = (HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2);
-
-           if (x < 0)
-             x = -x;
-
-           high = (HOST_WIDE_INT) (x / half_word / half_word);
-           x -= (REAL_VALUE_TYPE) high * half_word * half_word;
-           if (x >= (REAL_VALUE_TYPE) half_word * half_word / 2)
-             {
-               low = x - (REAL_VALUE_TYPE) half_word * half_word / 2;
-               low |= (HOST_WIDE_INT) -1 << (HOST_BITS_PER_WIDE_INT - 1);
-             }
-           else
-             low = (HOST_WIDE_INT) x;
-           if (TREE_REAL_CST (arg1) < 0)
-             neg_double (low, high, &low, &high);
-           t = build_int_2 (low, high);
-         }
-#else
          {
            HOST_WIDE_INT low, high;
            REAL_VALUE_TO_INT (&low, &high, x);
            t = build_int_2 (low, high);
          }
-#endif
          TREE_TYPE (t) = type;
          TREE_OVERFLOW (t)
            = TREE_OVERFLOW (arg1) | force_fit_type (t, overflow);
          TREE_CONSTANT_OVERFLOW (t)
            = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
        }
-#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
       TREE_TYPE (t) = type;
     }
   else if (TREE_CODE (type) == REAL_TYPE)
     {
-#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
       if (TREE_CODE (arg1) == INTEGER_CST)
        return build_real_from_int_cst (type, arg1);
-#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
       if (TREE_CODE (arg1) == REAL_CST)
        {
-         struct fc_args args;
-         
          if (REAL_VALUE_ISNAN (TREE_REAL_CST (arg1)))
            {
              t = arg1;
@@ -2073,24 +1598,12 @@ fold_convert (t, arg1)
              return t;
            }
 
-         /* 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() */
-             t = args.t;
-           }
-         else
-           {
-             /* We got an exception from fold_convert_1() */
-             overflow = 1;
-             t = copy_node (arg1);
-           }
+         t = build_real (type,
+                         real_value_truncate (TYPE_MODE (type),
+                                              TREE_REAL_CST (arg1)));
 
          TREE_OVERFLOW (t)
-           = TREE_OVERFLOW (arg1) | force_fit_type (t, overflow);
+           = TREE_OVERFLOW (arg1) | force_fit_type (t, 0);
          TREE_CONSTANT_OVERFLOW (t)
            = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
          return t;
@@ -2253,8 +1766,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)
@@ -2262,6 +1774,27 @@ operand_equal_p (arg0, arg1, only_const)
                && REAL_VALUES_IDENTICAL (TREE_REAL_CST (arg0),
                                          TREE_REAL_CST (arg1)));
 
+      case VECTOR_CST:
+       {
+         tree v1, v2;
+
+         if (TREE_CONSTANT_OVERFLOW (arg0)
+             || TREE_CONSTANT_OVERFLOW (arg1))
+           return 0;
+
+         v1 = TREE_VECTOR_CST_ELTS (arg0);
+         v2 = TREE_VECTOR_CST_ELTS (arg1);
+         while (v1 && v2)
+           {
+             if (!operand_equal_p (v1, v2, only_const))
+               return 0;
+             v1 = TREE_CHAIN (v1);
+             v2 = TREE_CHAIN (v2);
+           }
+
+         return 1;
+       }
+
       case COMPLEX_CST:
        return (operand_equal_p (TREE_REALPART (arg0), TREE_REALPART (arg1),
                                 only_const)
@@ -2317,7 +1850,7 @@ operand_equal_p (arg0, arg1, only_const)
 
     case 'r':
       /* If either of the pointer (or reference) expressions we are dereferencing
-        contain a side effect, these cannot be equal. */
+        contain a side effect, these cannot be equal.  */
       if (TREE_SIDE_EFFECTS (arg0)
          || TREE_SIDE_EFFECTS (arg1))
        return 0;
@@ -2330,6 +1863,7 @@ operand_equal_p (arg0, arg1, only_const)
 
        case COMPONENT_REF:
        case ARRAY_REF:
+       case ARRAY_RANGE_REF:
          return (operand_equal_p (TREE_OPERAND (arg0, 0),
                                   TREE_OPERAND (arg1, 0), 0)
                  && operand_equal_p (TREE_OPERAND (arg0, 1),
@@ -2350,25 +1884,25 @@ operand_equal_p (arg0, arg1, only_const)
       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;
 {
   int unsignedp1, unsignedpo;
   tree primarg0, primarg1, primother;
-  unsigned correct_width;
+  unsigned int correct_width;
 
   if (operand_equal_p (arg0, arg1, 0))
     return 1;
@@ -2381,7 +1915,8 @@ operand_equal_for_comparison_p (arg0, arg1, 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;
 
@@ -2403,9 +1938,8 @@ operand_equal_for_comparison_p (arg0, arg1, other)
 
       /* 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);
+      primarg1 = convert ((*lang_hooks.types.signed_or_unsigned_type)
+                         (unsignedp1, TREE_TYPE (primarg1)), primarg1);
 
       if (operand_equal_p (arg0, convert (type, primarg1), 0))
        return 1;
@@ -2475,7 +2009,7 @@ twoval_comparison_p (arg, cval1, cval2, save_p)
                && 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
@@ -2630,8 +2164,6 @@ pedantic_omit_one_operand (type, result, omitted)
 
   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
@@ -2654,7 +2186,9 @@ invert_truthvalue (arg)
   if (TREE_CODE_CLASS (code) == '<')
     {
       if (FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
-         && !flag_fast_math && code != NE_EXPR && code != EQ_EXPR)
+         && !flag_unsafe_math_optimizations
+         && code != NE_EXPR 
+         && code != EQ_EXPR)
        return build1 (TRUTH_NOT_EXPR, type, arg);
       else
        return build (invert_tree_comparison (code), type,
@@ -2664,8 +2198,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,
@@ -2846,14 +2379,13 @@ 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;
   tree linner, rinner = NULL_TREE;
   tree mask;
   tree offset;
@@ -2864,7 +2396,7 @@ optimize_bit_field_compare (code, compare_type, lhs, rhs)
      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;
@@ -2872,9 +2404,9 @@ optimize_bit_field_compare (code, compare_type, lhs, rhs)
  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
@@ -2894,8 +2426,8 @@ optimize_bit_field_compare (code, compare_type, lhs, rhs)
 
   /* Set signed and unsigned types of the precision of this mode for the
      shifts below.  */
-  signed_type = type_for_mode (nmode, 0);
-  unsigned_type = type_for_mode (nmode, 1);
+  signed_type = (*lang_hooks.types.type_for_mode) (nmode, 0);
+  unsigned_type = (*lang_hooks.types.type_for_mode) (nmode, 1);
 
   /* Compute the bit position and size for the new reference and our offset
      within it. If the new reference is the same size as the original, we
@@ -2937,7 +2469,7 @@ optimize_bit_field_compare (code, compare_type, lhs, rhs)
      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)
@@ -2946,7 +2478,7 @@ optimize_bit_field_compare (code, compare_type, lhs, rhs)
                                        convert (unsigned_type, rhs),
                                        size_int (lbitsize), 0)))
        {
-         warning ("comparison is always %d due to width of bitfield",
+         warning ("comparison is always %d due to width of bit-field",
                   code == NE_EXPR);
          return convert (compare_type,
                          (code == NE_EXPR
@@ -2959,7 +2491,7 @@ optimize_bit_field_compare (code, compare_type, lhs, rhs)
                              size_int (lbitsize - 1), 0);
       if (! integer_zerop (tem) && ! integer_all_onesp (tem))
        {
-         warning ("comparison is always %d due to width of bitfield",
+         warning ("comparison is always %d due to width of bit-field",
                   code == NE_EXPR);
          return convert (compare_type,
                          (code == NE_EXPR
@@ -3022,7 +2554,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;
@@ -3031,10 +2563,9 @@ 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;
 
-  /* 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)))
@@ -3051,16 +2582,15 @@ decode_field_reference (exp, pbitsize, pbitpos, pmode, punsignedp,
        return 0;
     }
 
-
   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)
     return 0;
-  
+
   /* Compute the mask to access the bitfield.  */
-  unsigned_type = type_for_size (*pbitsize, 1);
+  unsigned_type = (*lang_hooks.types.type_for_size) (*pbitsize, 1);
   precision = TYPE_PRECISION (unsigned_type);
 
   mask = build_int_2 (~0, ~0);
@@ -3088,14 +2618,14 @@ 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);
-  TREE_TYPE (tmask) = signed_type (type);
+  TREE_TYPE (tmask) = (*lang_hooks.types.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),
@@ -3106,7 +2636,7 @@ all_ones_mask_p (mask, 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;
 {
@@ -3118,7 +2648,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)
@@ -3136,7 +2666,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
@@ -3199,7 +2729,7 @@ range_binop (code, type, arg0, upper0_p, arg1, upper1_p)
      the same. But, this is computer arithmetic, where numbers are finite.
      We can therefore make the transformation of any unbounded range with
      the value Z, Z being greater than any representable number. This permits
-     us to treat unbounded ranges as equal. */
+     us to treat unbounded ranges as equal.  */
   sgn0 = arg0 != 0 ? 0 : (upper0_p ? 1 : -1);
   sgn1 = arg1 != 0 ? 0 : (upper1_p ? 1 : -1);
   switch (code)
@@ -3228,10 +2758,10 @@ range_binop (code, type, arg0, upper0_p, arg1, upper1_p)
 
   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.  */
 
@@ -3262,14 +2792,14 @@ make_range (exp, pin_p, plow, phigh)
       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_length[(int) code] > 1))
+             || (TREE_CODE_CLASS (code) == 'e'
+                 && TREE_CODE_LENGTH (code) > 1))
            arg1 = TREE_OPERAND (exp, 1);
        }
 
@@ -3387,8 +2917,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;
@@ -3421,7 +2960,8 @@ make_range (exp, pin_p, plow, phigh)
             be interpreted as positive.  */
          if (TREE_UNSIGNED (type) && ! TREE_UNSIGNED (TREE_TYPE (exp)))
            {
-             tree equiv_type = type_for_mode (TYPE_MODE (type), 1);
+             tree equiv_type = (*lang_hooks.types.type_for_mode)
+               (TYPE_MODE (type), 1);
              tree high_positive;
 
              /* A range without an upper bound is, naturally, unbounded.
@@ -3434,7 +2974,7 @@ make_range (exp, pin_p, plow, phigh)
              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.  */
@@ -3523,7 +3063,7 @@ build_range_check (type, exp, in_p, low, high)
 
   else if (integer_zerop (low))
     {
-      utype = unsigned_type (etype);
+      utype = (*lang_hooks.types.unsigned_type) (etype);
       return build_range_check (type, convert (utype, exp), 1, 0,
                                convert (utype, high));
     }
@@ -3537,7 +3077,7 @@ build_range_check (type, exp, in_p, low, high)
     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
@@ -3562,7 +3102,7 @@ merge_ranges (pin_p, plow, phigh, in0_p, low0, high0, in1_p, low1, high1)
 
   /* 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,
@@ -3614,7 +3154,7 @@ merge_ranges (pin_p, plow, phigh, in0_p, low0, high0, in1_p, low1, high1)
        {
          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)
        {
@@ -3710,6 +3250,7 @@ fold_range_test (exp)
      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))
@@ -3723,7 +3264,7 @@ fold_range_test (exp)
                      TREE_TYPE (exp), TREE_OPERAND (exp, 0),
                      TREE_OPERAND (exp, 1));
 
-      else if (global_bindings_p () == 0
+      else if ((*lang_hooks.decls.global_bindings_p) () == 0
               && ! contains_placeholder_p (lhs))
        {
          tree common = save_expr (lhs);
@@ -3770,12 +3311,12 @@ unextend (c, p, unsignedp, mask)
 
   /* 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.  */
   if (TREE_UNSIGNED (type))
-    temp = convert (signed_type (type), temp);
+    temp = convert ((*lang_hooks.types.signed_type) (type), temp);
 
   temp = const_binop (LSHIFT_EXPR, temp, size_int (modesize - 1), 0);
   temp = const_binop (RSHIFT_EXPR, temp, size_int (modesize - p - 1), 0);
@@ -3817,9 +3358,9 @@ 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., 
+     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
@@ -3830,10 +3371,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;
@@ -3870,7 +3411,7 @@ fold_truthop (code, truth_type, lhs, rhs)
   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
@@ -3969,7 +3510,7 @@ fold_truthop (code, truth_type, lhs, rhs)
 
   lnbitsize = GET_MODE_BITSIZE (lnmode);
   lnbitpos = first_bit & ~ (lnbitsize - 1);
-  lntype = type_for_size (lnbitsize, 1);
+  lntype = (*lang_hooks.types.type_for_size) (lnbitsize, 1);
   xll_bitpos = ll_bitpos - lnbitpos, xrl_bitpos = rl_bitpos - lnbitpos;
 
   if (BYTES_BIG_ENDIAN)
@@ -3986,7 +3527,7 @@ fold_truthop (code, truth_type, lhs, rhs)
   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,
@@ -3994,7 +3535,7 @@ fold_truthop (code, truth_type, lhs, rhs)
                                        0)))
        {
          warning ("comparison is always %d", wanted_code == NE_EXPR);
-         
+
          return convert (truth_type,
                          wanted_code == NE_EXPR
                          ? integer_one_node : integer_zero_node);
@@ -4040,7 +3581,7 @@ fold_truthop (code, truth_type, lhs, rhs)
 
       rnbitsize = GET_MODE_BITSIZE (rnmode);
       rnbitpos = first_bit & ~ (rnbitsize - 1);
-      rntype = type_for_size (rnbitsize, 1);
+      rntype = (*lang_hooks.types.type_for_size) (rnbitsize, 1);
       xlr_bitpos = lr_bitpos - rnbitpos, xrr_bitpos = rr_bitpos - rnbitpos;
 
       if (BYTES_BIG_ENDIAN)
@@ -4081,7 +3622,7 @@ fold_truthop (code, truth_type, lhs, rhs)
         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)
@@ -4166,7 +3707,7 @@ fold_truthop (code, truth_type, lhs, rhs)
                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
@@ -4269,10 +3810,14 @@ optimize_minmax_comparison (t)
    other operations already in T.  WIDE_TYPE, if non-null, is a type that
    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.
+   For example, if we are dividing (X * 8) + (Y * 16) by 4, we can return
+   (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.  */
@@ -4286,7 +3831,7 @@ extract_muldiv (t, c, code, wide_type)
 {
   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;
@@ -4295,7 +3840,7 @@ extract_muldiv (t, c, code, wide_type)
 
   /* 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);
@@ -4316,6 +3861,18 @@ 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))
+         && ! (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
@@ -4331,6 +3888,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)
@@ -4358,7 +3920,14 @@ extract_muldiv (t, c, code, wide_type)
       if (SAVE_EXPR_RTL (t) == 0 && ! TREE_SIDE_EFFECTS (TREE_OPERAND (t, 0))
          && 0 != (t1 = extract_muldiv (TREE_OPERAND (t, 0), c, code,
                                        wide_type)))
-       return save_expr (t1);
+       {
+         t1 = save_expr (t1);
+         if (SAVE_EXPR_PERSISTENT_P (t) && TREE_CODE (t1) == SAVE_EXPR)
+           SAVE_EXPR_PERSISTENT_P (t1) = 1;
+         if (is_pending_size (t))
+           put_pending_size (t1);
+         return t1;
+       }
       break;
 
     case LSHIFT_EXPR:  case RSHIFT_EXPR:
@@ -4366,6 +3935,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)))
@@ -4383,7 +3956,12 @@ extract_muldiv (t, c, code, wide_type)
         constant.  */
       t1 = extract_muldiv (op0, c, code, wide_type);
       t2 = extract_muldiv (op1, c, code, wide_type);
-      if (t1 != 0 && t2 != 0)
+      if (t1 != 0 && t2 != 0
+         && (code == MULT_EXPR
+             /* If not multiplication, we can only do this if either operand
+                is divisible by c.  */
+             || multiple_of_p (ctype, op0, c)
+             || multiple_of_p (ctype, op1, c)))
        return fold (build (tcode, ctype, convert (ctype, t1),
                            convert (ctype, t2)));
 
@@ -4402,19 +3980,31 @@ extract_muldiv (t, c, code, wide_type)
        {
          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;
        }
 
-      /* 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)
+         && ! (TREE_CODE (ctype) == INTEGER_TYPE && TYPE_IS_SIZETYPE (ctype))
+         && ctype != type)
        break;
 
       /* If we were able to eliminate our operation from the first side,
@@ -4424,7 +4014,7 @@ extract_muldiv (t, c, code, wide_type)
 
       /* The last case is if we are a multiply.  In that case, we can
         apply the distributive law to commute the multiply and addition
-        if the multiplication of the constants doesn't overflow. */
+        if the multiplication of the constants doesn't overflow.  */
       if (code == MULT_EXPR)
        return fold (build (tcode, ctype, fold (build (code, ctype,
                                                       convert (ctype, op0),
@@ -4442,7 +4032,7 @@ extract_muldiv (t, c, code, wide_type)
          && integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c, 0)))
        return omit_one_operand (type, integer_zero_node, op0);
 
-      /* ... fall through ... */
+      /* ... fall through ...  */
 
     case TRUNC_DIV_EXPR:  case CEIL_DIV_EXPR:  case FLOOR_DIV_EXPR:
     case ROUND_DIV_EXPR:  case EXACT_DIV_EXPR:
@@ -4471,11 +4061,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 cannot 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)))
+         && ((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),
@@ -4544,9 +4140,9 @@ constant_boolean_node (value, type)
   if (type == integer_type_node)
     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 
+    return (*lang_hooks.truthvalue_conversion) (value ? integer_one_node :
+                                               integer_zero_node);
+  else
     {
       tree t = build_int_2 (value, 0);
 
@@ -4564,18 +4160,184 @@ count_cond (expr, lim)
      tree expr;
      int lim;
 {
-  int true, false;
+  int ctrue, cfalse;
 
   if (TREE_CODE (expr) != COND_EXPR)
     return 0;
   else if (lim <= 0)
     return 0;
 
-  true = count_cond (TREE_OPERAND (expr, 1), lim - 1);
-  false = count_cond (TREE_OPERAND (expr, 2), lim - 1 - true);
-  return MIN (lim, 1 + true + false);
+  ctrue = count_cond (TREE_OPERAND (expr, 1), lim - 1);
+  cfalse = count_cond (TREE_OPERAND (expr, 2), lim - 1 - ctrue);
+  return MIN (lim, 1 + ctrue + cfalse);
+}
+
+/* Transform `a + (b ? x : y)' into `x ? (a + b) : (a + y)'.
+   Transform, `a + (x < y)' into `(x < y) ? (a + 1) : (a + 0)'.  Here
+   CODE corresponds to the `+', COND to the `(b ? x : y)' or `(x < y)'
+   expression, and ARG to `a'.  If COND_FIRST_P is non-zero, then the
+   COND is the first argument to CODE; otherwise (as in the example
+   given here), it is the second argument.  TYPE is the type of the
+   original expression.  */
+
+static tree
+fold_binary_op_with_conditional_arg (code, type, cond, arg, cond_first_p)
+     enum tree_code code;
+     tree type;
+     tree cond;
+     tree arg;
+     int cond_first_p;
+{
+  tree test, true_value, false_value;
+  tree lhs = NULL_TREE;
+  tree rhs = NULL_TREE;
+  /* In the end, we'll produce a COND_EXPR.  Both arms of the
+     conditional expression will be binary operations.  The left-hand
+     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 analogous --
+     but apply to the expression to be executed if the conditional is
+     false.  */
+  tree *true_lhs;
+  tree *true_rhs;
+  tree *false_lhs;
+  tree *false_rhs;
+  /* These are the codes to use for the left-hand side and right-hand
+     side of the COND_EXPR.  Normally, they are the same as CODE.  */
+  enum tree_code lhs_code = code;
+  enum tree_code rhs_code = code;
+  /* And these are the types of the expressions.  */
+  tree lhs_type = type;
+  tree rhs_type = type;
+
+  if (cond_first_p)
+    {
+      true_rhs = false_rhs = &arg;
+      true_lhs = &true_value;
+      false_lhs = &false_value;
+    }
+  else
+    {
+      true_lhs = false_lhs = &arg;
+      true_rhs = &true_value;
+      false_rhs = &false_value;
+    }
+
+  if (TREE_CODE (cond) == COND_EXPR)
+    {
+      test = TREE_OPERAND (cond, 0);
+      true_value = TREE_OPERAND (cond, 1);
+      false_value = TREE_OPERAND (cond, 2);
+      /* If this operand throws an expression, then it does not make
+        sense to try to perform a logical or arithmetic operation
+        involving it.  Instead of building `a + throw 3' for example,
+        we simply build `a, throw 3'.  */
+      if (VOID_TYPE_P (TREE_TYPE (true_value)))
+       {
+         lhs_code = COMPOUND_EXPR;
+         if (!cond_first_p)
+           lhs_type = void_type_node;
+       }
+      if (VOID_TYPE_P (TREE_TYPE (false_value)))
+       {
+         rhs_code = COMPOUND_EXPR;
+         if (!cond_first_p)
+           rhs_type = void_type_node;
+       }
+    }
+  else
+    {
+      tree testtype = TREE_TYPE (cond);
+      test = cond;
+      true_value = convert (testtype, integer_one_node);
+      false_value = convert (testtype, integer_zero_node);
+    }
+  
+  /* If ARG is complex we want to make sure we only evaluate
+     it once.  Though this is only required if it is volatile, it
+     might be more efficient even if it is not.  However, if we
+     succeed in folding one part to a constant, we do not need
+     to make this SAVE_EXPR.  Since we do this optimization
+     primarily to see if we do end up with constant and this
+     SAVE_EXPR interferes with later optimizations, suppressing
+     it when we can is important.
+     
+     If we are not in a function, we can't make a SAVE_EXPR, so don't
+     try to do so.  Don't try to see if the result is a constant
+     if an arm is a COND_EXPR since we get exponential behavior
+     in that case.  */
+  
+  if (TREE_CODE (arg) != SAVE_EXPR && ! TREE_CONSTANT (arg)
+      && (*lang_hooks.decls.global_bindings_p) () == 0
+      && ((TREE_CODE (arg) != VAR_DECL
+          && TREE_CODE (arg) != PARM_DECL)
+         || TREE_SIDE_EFFECTS (arg)))
+    {
+      if (TREE_CODE (true_value) != COND_EXPR)
+       lhs = fold (build (lhs_code, lhs_type, *true_lhs, *true_rhs));
+      
+      if (TREE_CODE (false_value) != COND_EXPR)
+       rhs = fold (build (rhs_code, rhs_type, *false_lhs, *false_rhs));
+      
+      if ((lhs == 0 || ! TREE_CONSTANT (lhs))
+         && (rhs == 0 || !TREE_CONSTANT (rhs)))
+       arg = save_expr (arg), lhs = rhs = 0;
+    }
+  
+  if (lhs == 0)
+    lhs = fold (build (lhs_code, lhs_type, *true_lhs, *true_rhs));
+  if (rhs == 0)
+    rhs = fold (build (rhs_code, rhs_type, *false_lhs, *false_rhs));
+  
+  test = fold (build (COND_EXPR, type, test, lhs, rhs));
+  
+  if (TREE_CODE (arg) == SAVE_EXPR)
+    return build (COMPOUND_EXPR, type,
+                 convert (void_type_node, arg),
+                 strip_compound_expr (test, arg));
+  else
+    return convert (type, test);
 }
+
 \f
+/* Subroutine of fold() that checks for the addition of +/- 0.0.
+
+   If !NEGATE, return true if ADDEND is +/-0.0 and, for all X of type
+   TYPE, X + ADDEND is the same as X.  If NEGATE, return true if X -
+   ADDEND is the same as X.
+
+   X + 0 and X - 0 both give X when X is NaN, infinite, or non-zero
+   and finite.  The problematic cases are when X is zero, and its mode
+   has signed zeros.  In the case of rounding towards -infinity,
+   X - 0 is not the same as X because 0 - 0 is -0.  In other rounding
+   modes, X + 0 is not the same as X because -0 + 0 is 0.  */
+
+static bool
+fold_real_zero_addition_p (type, addend, negate)
+     tree type, addend;
+     int negate;
+{
+  if (!real_zerop (addend))
+    return false;
+
+  /* Allow the fold if zeros aren't signed, or their sign isn't important.  */
+  if (!HONOR_SIGNED_ZEROS (TYPE_MODE (type)))
+    return true;
+
+  /* Treat x + -0 as x - 0 and x - -0 as x + 0.  */
+  if (TREE_CODE (addend) == REAL_CST
+      && REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (addend)))
+    negate = !negate;
+
+  /* The mode has signed zeros, and we have to honor their sign.
+     In this situation, there is only one case we can return true for.
+     X - 0 is the same as X unless rounding towards -infinity is
+     supported.  */
+  return negate && !HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type));
+}
+
+
 /* Perform constant folding and related simplification of EXPR.
    The related simplifications include x*1 => x, x*0 => 0, etc.,
    and application of the associative law.
@@ -4585,39 +4347,34 @@ count_cond (expr, lim)
    but we can constant-fold them if they have constant operands.  */
 
 tree
-fold (expr) 
+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 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.  */
   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)
+  if (code == RTL_EXPR || (code == SAVE_EXPR && SAVE_EXPR_RTL (t) != 0))
+    return t;
+
+  /* Return right away if a constant.  */
+  if (kind == 'c')
     return t;
 
-  /* Return right away if already constant.  */
-  if (TREE_CONSTANT (t))
-    {
-      if (code == CONST_DECL)
-       return DECL_INITIAL (t);
-      return t;
-    }
-  
 #ifdef MAX_INTEGER_COMPUTATION_MODE
   check_max_integer_computation_mode (expr);
 #endif
 
-  kind = TREE_CODE_CLASS (code);
   if (code == NOP_EXPR || code == FLOAT_EXPR || code == CONVERT_EXPR)
     {
       tree subop;
@@ -4635,20 +4392,17 @@ fold (expr)
        subop = arg0;
 
       if (subop != 0 && TREE_CODE (subop) != INTEGER_CST
-#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
          && TREE_CODE (subop) != REAL_CST
-#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
          )
        /* Note that TREE_CONSTANT isn't enough:
           static var addresses are constant but we can't
           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 i;
+      int len = first_rtl_op (code);
+      int i;
       for (i = 0; i < len; i++)
        {
          tree op = TREE_OPERAND (t, i);
@@ -4664,21 +4418,16 @@ 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);
          else
            subop = op;
 
          if (TREE_CODE (subop) != INTEGER_CST
-#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
-             && TREE_CODE (subop) != REAL_CST
-#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
-             )
+             && TREE_CODE (subop) != REAL_CST)
            /* Note that TREE_CONSTANT isn't enough:
               static var addresses are constant but we can't
               do arithmetic on them.  */
@@ -4715,11 +4464,11 @@ 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
-     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
@@ -4784,7 +4533,7 @@ fold (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))));
@@ -4802,72 +4551,11 @@ fold (expr)
               && (TREE_CODE (arg0) != COND_EXPR
                   || count_cond (arg0, 25) + count_cond (arg1, 25) <= 25)
               && (! TREE_SIDE_EFFECTS (arg0)
-                  || (global_bindings_p () == 0
+                  || ((*lang_hooks.decls.global_bindings_p) () == 0
                       && ! contains_placeholder_p (arg0))))
-       {
-         tree test, true_value, false_value;
-         tree lhs = 0, rhs = 0;
-
-         if (TREE_CODE (arg1) == COND_EXPR)
-           {
-             test = TREE_OPERAND (arg1, 0);
-             true_value = TREE_OPERAND (arg1, 1);
-             false_value = TREE_OPERAND (arg1, 2);
-           }
-         else
-           {
-             tree testtype = TREE_TYPE (arg1);
-             test = arg1;
-             true_value = convert (testtype, integer_one_node);
-             false_value = convert (testtype, integer_zero_node);
-           }
-
-         /* If ARG0 is complex we want to make sure we only evaluate
-            it once.  Though this is only required if it is volatile, it
-            might be more efficient even if it is not.  However, if we
-            succeed in folding one part to a constant, we do not need
-            to make this SAVE_EXPR.  Since we do this optimization
-            primarily to see if we do end up with constant and this
-            SAVE_EXPR interferes with later optimizations, suppressing
-            it when we can is important.
-
-            If we are not in a function, we can't make a SAVE_EXPR, so don't
-            try to do so.  Don't try to see if the result is a constant
-            if an arm is a COND_EXPR since we get exponential behavior
-            in that case.  */
-
-         if (TREE_CODE (arg0) != SAVE_EXPR && ! TREE_CONSTANT (arg0)
-             && global_bindings_p () == 0
-             && ((TREE_CODE (arg0) != VAR_DECL
-                  && TREE_CODE (arg0) != PARM_DECL)
-                 || TREE_SIDE_EFFECTS (arg0)))
-           {
-             if (TREE_CODE (true_value) != COND_EXPR)
-               lhs = fold (build (code, type, arg0, true_value));
-
-             if (TREE_CODE (false_value) != COND_EXPR)
-               rhs = fold (build (code, type, arg0, false_value));
-
-             if ((lhs == 0 || ! TREE_CONSTANT (lhs))
-                 && (rhs == 0 || !TREE_CONSTANT (rhs)))
-               arg0 = save_expr (arg0), lhs = rhs = 0;
-           }
-
-         if (lhs == 0)
-           lhs = fold (build (code, type, arg0, true_value));
-         if (rhs == 0)
-           rhs = fold (build (code, type, arg0, false_value));
-
-         test = fold (build (COND_EXPR, type, test, lhs, rhs));
-
-         if (TREE_CODE (arg0) == SAVE_EXPR)
-           return build (COMPOUND_EXPR, type,
-                         convert (void_type_node, arg0),
-                         strip_compound_expr (test, arg0));
-         else
-           return convert (type, test);
-       }
-
+       return 
+         fold_binary_op_with_conditional_arg (code, type, arg1, arg0,
+                                              /*cond_first_p=*/0);
       else if (TREE_CODE (arg0) == COMPOUND_EXPR)
        return build (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
                      fold (build (code, type, TREE_OPERAND (arg0, 1), arg1)));
@@ -4877,57 +4565,11 @@ fold (expr)
               && (TREE_CODE (arg1) != COND_EXPR
                   || count_cond (arg0, 25) + count_cond (arg1, 25) <= 25)
               && (! TREE_SIDE_EFFECTS (arg1)
-                  || (global_bindings_p () == 0
+                  || ((*lang_hooks.decls.global_bindings_p) () == 0
                       && ! contains_placeholder_p (arg1))))
-       {
-         tree test, true_value, false_value;
-         tree lhs = 0, rhs = 0;
-
-         if (TREE_CODE (arg0) == COND_EXPR)
-           {
-             test = TREE_OPERAND (arg0, 0);
-             true_value = TREE_OPERAND (arg0, 1);
-             false_value = TREE_OPERAND (arg0, 2);
-           }
-         else
-           {
-             tree testtype = TREE_TYPE (arg0);
-             test = arg0;
-             true_value = convert (testtype, integer_one_node);
-             false_value = convert (testtype, integer_zero_node);
-           }
-
-         if (TREE_CODE (arg1) != SAVE_EXPR && ! TREE_CONSTANT (arg0)
-             && global_bindings_p () == 0
-             && ((TREE_CODE (arg1) != VAR_DECL
-                  && TREE_CODE (arg1) != PARM_DECL)
-                 || TREE_SIDE_EFFECTS (arg1)))
-           {
-             if (TREE_CODE (true_value) != COND_EXPR)
-               lhs = fold (build (code, type, true_value, arg1));
-
-             if (TREE_CODE (false_value) != COND_EXPR)
-               rhs = fold (build (code, type, false_value, arg1));
-
-             if ((lhs == 0 || ! TREE_CONSTANT (lhs))
-                 && (rhs == 0 || !TREE_CONSTANT (rhs)))
-               arg1 = save_expr (arg1), lhs = rhs = 0;
-           }
-
-         if (lhs == 0)
-           lhs = fold (build (code, type, true_value, arg1));
-
-         if (rhs == 0)
-           rhs = fold (build (code, type, false_value, arg1));
-
-         test = fold (build (COND_EXPR, type, test, lhs, rhs));
-         if (TREE_CODE (arg1) == SAVE_EXPR)
-           return build (COMPOUND_EXPR, type,
-                         convert (void_type_node, arg1),
-                         strip_compound_expr (test, arg1));
-         else
-           return convert (type, test);
-       }
+       return 
+         fold_binary_op_with_conditional_arg (code, type, arg0, arg1,
+                                              /*cond_first_p=*/1);
     }
   else if (TREE_CODE_CLASS (code) == '<'
           && TREE_CODE (arg0) == COMPOUND_EXPR)
@@ -4937,11 +4579,12 @@ fold (expr)
           && 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:
     case REAL_CST:
+    case VECTOR_CST:
     case STRING_CST:
     case COMPLEX_CST:
     case CONSTRUCTOR:
@@ -4969,27 +4612,27 @@ 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 
+         /* 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
@@ -5021,7 +4664,7 @@ fold (expr)
               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)
@@ -5053,6 +4696,49 @@ fold (expr)
          TREE_USED (t) = 1;
          return t;
        }
+
+      /* Convert (T)(x & c) into (T)x & (T)c, if c is an integer
+        constants (if x has signed type, the sign bit cannot be set
+        in c).  This folds extension into the BIT_AND_EXPR.  */
+      if (INTEGRAL_TYPE_P (TREE_TYPE (t))
+         && TREE_CODE (TREE_OPERAND (t, 0)) == BIT_AND_EXPR
+         && TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 1)) == INTEGER_CST)
+       {
+         tree and = TREE_OPERAND (t, 0);
+         tree and0 = TREE_OPERAND (and, 0), and1 = TREE_OPERAND (and, 1);
+         int change = 0;
+
+         if (TREE_UNSIGNED (TREE_TYPE (and))
+             || (TYPE_PRECISION (TREE_TYPE (t))
+                 <= TYPE_PRECISION (TREE_TYPE (and))))
+           change = 1;
+         else if (TYPE_PRECISION (TREE_TYPE (and1))
+                  <= HOST_BITS_PER_WIDE_INT
+                  && host_integerp (and1, 1))
+           {
+             unsigned HOST_WIDE_INT cst;
+
+             cst = tree_low_cst (and1, 1);
+             cst &= (HOST_WIDE_INT) -1
+                    << (TYPE_PRECISION (TREE_TYPE (and1)) - 1);
+             change = (cst == 0);
+#ifdef LOAD_EXTEND_OP
+             if (change
+                 && (LOAD_EXTEND_OP (TYPE_MODE (TREE_TYPE (and0)))
+                     == ZERO_EXTEND))
+               {
+                 tree uns = (*lang_hooks.types.unsigned_type) (TREE_TYPE (and0));
+                 and0 = convert (uns, and0);
+                 and1 = convert (uns, and1);
+               }
+#endif
+           }
+         if (change)
+           return fold (build (BIT_AND_EXPR, TREE_TYPE (t),
+                               convert (TREE_TYPE (t), and0),
+                               convert (TREE_TYPE (t), and1)));
+       }
+
       if (!wins)
        {
          TREE_CONSTANT (t) = TREE_CONSTANT (arg0);
@@ -5060,24 +4746,11 @@ fold (expr)
        }
       return fold_convert (t, arg0);
 
-#if 0  /* This loses on &"foo"[0].  */
-    case ARRAY_REF:
-       {
-         int i;
-
-         /* 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))
-           {
-             t = build_int_2 (TREE_STRING_POINTER (arg0)[i], 0);
-             TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (arg0));
-             force_fit_type (t, 0);
-           }
-       }
+    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;
-#endif /* 0 */
 
     case COMPONENT_REF:
       if (TREE_CODE (arg0) == CONSTRUCTOR)
@@ -5097,7 +4770,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);
@@ -5117,7 +4791,7 @@ fold (expr)
 
       /* Convert - (a - b) to (b - a) for non-floating-point.  */
       else if (TREE_CODE (arg0) == MINUS_EXPR
-              && (! FLOAT_TYPE_P (type) || flag_fast_math))
+              && (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations))
        return build (MINUS_EXPR, type, TREE_OPERAND (arg0, 1),
                      TREE_OPERAND (arg0, 0));
 
@@ -5128,10 +4802,19 @@ fold (expr)
        {
          if (TREE_CODE (arg0) == INTEGER_CST)
            {
-             if (! TREE_UNSIGNED (type)
-                 && TREE_INT_CST_HIGH (arg0) < 0)
+             /* If the value is unsigned, then the absolute value is
+                the same as the ordinary value.  */
+             if (TREE_UNSIGNED (type))
+               return arg0;
+             /* Similarly, if the value is non-negative.  */
+             else if (INT_CST_LT (integer_minus_one_node, arg0))
+               return arg0;
+             /* If the value is negative, then the absolute value is
+                its negation.  */
+             else
                {
-                 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);
@@ -5157,14 +4840,14 @@ 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)
-       return build_complex (type, TREE_OPERAND (arg0, 0),
-                             negate_expr (TREE_OPERAND (arg0, 1)));
+       return build_complex (type, TREE_REALPART (arg0),
+                             negate_expr (TREE_IMAGPART (arg0)));
       else if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
        return fold (build (TREE_CODE (arg0), type,
                            fold (build1 (CONJ_EXPR, type,
@@ -5218,12 +4901,12 @@ fold (expr)
            }
 
          /* 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;
 
@@ -5304,38 +4987,37 @@ fold (expr)
                }
 
              if (same)
-               return fold (build (MULT_EXPR, type,
+               return fold (build (MULT_EXPR, type,
                                    fold (build (PLUS_EXPR, type, alt0, alt1)),
                                    same));
            }
        }
-      /* In IEEE floating point, x+0 may not equal x.  */
-      else if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
-               || flag_fast_math)
-              && real_zerop (arg1))
-       return non_lvalue (convert (type, arg0));
-      /* x+(-0) equals x, even for IEEE.  */
-      else if (TREE_CODE (arg1) == REAL_CST
-              && REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (arg1)))
+
+      /* See if ARG1 is zero and X + ARG1 reduces to X.  */
+      else if (fold_real_zero_addition_p (TREE_TYPE (arg0), arg1, 0))
        return non_lvalue (convert (type, arg0));
 
+      /* Likewise if the operands are reversed.  */
+      else if (fold_real_zero_addition_p (TREE_TYPE (arg1), arg0, 0))
+       return non_lvalue (convert (type, arg1));
+
      bit_rotate:
       /* (A << C1) + (A >> C2) if A is unsigned and C1+C2 is the size of A
         is a rotate of A by C1 bits.  */
       /* (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))
+       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;
-           register enum tree_code code01, code11;
+           tree tree01, tree11;
+           enum tree_code code01, code11;
 
            tree01 = TREE_OPERAND (arg0, 1);
            tree11 = TREE_OPERAND (arg1, 1);
@@ -5344,90 +5026,131 @@ fold (expr)
            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_INT_CST_HIGH (tree110) == 0
-                   && (TREE_INT_CST_LOW (tree110)
-                       == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0))))
+               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_INT_CST_HIGH (tree010) == 0
-                   && (TREE_INT_CST_LOW (tree010)
-                       == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0))))
+               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
         don't associate floats at all.  It shouldn't matter much.  However,
         associating multiplications is only very slightly inaccurate, so do
-        that if -ffast-math is specified.  */
+        that if -funsafe-math-optimizations is specified.  */
 
       if (! wins
          && (! FLOAT_TYPE_P (type)
-             || (flag_fast_math && code != MULT_EXPR)))
+             || (flag_unsafe_math_optimizations && code == MULT_EXPR)))
        {
-         tree var0, con0, lit0, var1, con1, lit1;
+         tree var0, con0, lit0, minus_lit0;
+         tree var1, con1, lit1, minus_lit1;
 
          /* Split both trees into variables, constants, and literals.  Then
             associate each group together, the constants with literals,
             then the result with variables.  This increases the chances of
             literals being recombined later and of generating relocatable
-            expressions for the sum of a constant and literal. */
-         var0 = split_tree (arg0, code, &con0, &lit0, 0);
-         var1 = split_tree (arg1, code, &con1, &lit1, code == MINUS_EXPR);
+            expressions for the sum of a constant and literal.  */
+         var0 = split_tree (arg0, code, &con0, &lit0, &minus_lit0, 0);
+         var1 = split_tree (arg1, code, &con1, &lit1, &minus_lit1,
+                            code == MINUS_EXPR);
 
          /* Only do something if we found more than two objects.  Otherwise,
             nothing has changed and we risk infinite recursion.  */
-         if (2 < ((var0 != 0) + (var1 != 0) + (con0 != 0) + (con1 != 0)
-                  + (lit0 != 0) + (lit1 != 0)))
+         if (2 < ((var0 != 0) + (var1 != 0)
+                  + (con0 != 0) + (con1 != 0)
+                  + (lit0 != 0) + (lit1 != 0)
+                  + (minus_lit0 != 0) + (minus_lit1 != 0)))
            {
+             /* Recombine MINUS_EXPR operands by using PLUS_EXPR.  */
+             if (code == MINUS_EXPR)
+               code = PLUS_EXPR;
+
              var0 = associate_trees (var0, var1, code, type);
              con0 = associate_trees (con0, con1, code, type);
              lit0 = associate_trees (lit0, lit1, code, type);
+             minus_lit0 = associate_trees (minus_lit0, minus_lit1, code, type);
+
+             /* Preserve the MINUS_EXPR if the negative part of the literal is
+                greater than the positive part.  Otherwise, the multiplicative
+                folding code (i.e extract_muldiv) may be fooled in case
+                unsigned constants are substracted, like in the following
+                example: ((X*2 + 4) - 8U)/2.  */
+             if (minus_lit0 && lit0)
+               {
+                 if (tree_int_cst_lt (lit0, minus_lit0))
+                   {
+                     minus_lit0 = associate_trees (minus_lit0, lit0,
+                                                   MINUS_EXPR, type);
+                     lit0 = 0;
+                   }
+                 else
+                   {
+                     lit0 = associate_trees (lit0, minus_lit0,
+                                             MINUS_EXPR, type);
+                     minus_lit0 = 0;
+                   }
+               }
+             if (minus_lit0)
+               {
+                 if (con0 == 0)
+                   return convert (type, associate_trees (var0, minus_lit0,
+                                                          MINUS_EXPR, type));
+                 else
+                   {
+                     con0 = associate_trees (con0, minus_lit0,
+                                             MINUS_EXPR, type);
+                     return convert (type, associate_trees (var0, con0,
+                                                            PLUS_EXPR, type));
+                   }
+               }
+
              con0 = associate_trees (con0, lit0, code, type);
              return convert (type, associate_trees (var0, con0, code, type));
            }
        }
 
     binary:
-#if defined (REAL_IS_NOT_DOUBLE) && ! defined (REAL_ARITHMETIC)
-      if (TREE_CODE (arg1) == REAL_CST)
-       return t;
-#endif /* REAL_IS_NOT_DOUBLE, and no REAL_ARITHMETIC */
       if (wins)
        t1 = const_binop (code, arg0, arg1, 0);
       if (t1 != NULL_TREE)
@@ -5448,7 +5171,7 @@ fold (expr)
       /* (-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)));
@@ -5456,7 +5179,7 @@ fold (expr)
       if (! FLOAT_TYPE_P (type))
        {
          if (! wins && integer_zerop (arg0))
-           return negate_expr (arg1);
+           return negate_expr (convert (type, arg1));
          if (integer_zerop (arg1))
            return non_lvalue (convert (type, arg0));
 
@@ -5474,24 +5197,23 @@ fold (expr)
                                TREE_OPERAND (arg0, 1)));
        }
 
-      else if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
-              || flag_fast_math)
-       {
-         /* Except with IEEE floating point, 0-x equals -x.  */
-         if (! wins && real_zerop (arg0))
-           return negate_expr (arg1);
-         /* Except with IEEE floating point, x-0 equals x.  */
-         if (real_zerop (arg1))
-           return non_lvalue (convert (type, arg0));
-       }
+      /* See if ARG1 is zero and X - ARG1 reduces to X.  */
+      else if (fold_real_zero_addition_p (TREE_TYPE (arg0), arg1, 1))
+       return non_lvalue (convert (type, arg0));
+
+      /* (ARG0 - ARG1) is the same as (-ARG1 + ARG0).  So check whether
+        ARG0 is zero and X + ARG0 reduces to X, since that would mean
+        (-ARG1 + ARG0) reduces to -ARG1.  */
+      else if (!wins && fold_real_zero_addition_p (TREE_TYPE (arg1), arg0, 0))
+       return negate_expr (convert (type, arg1));
 
-      /* 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
         is volatile.  */
 
-      if ((! FLOAT_TYPE_P (type) || flag_fast_math)
+      if ((! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
          && operand_equal_p (arg0, arg1, 0))
        return convert (type, integer_zero_node);
 
@@ -5501,7 +5223,7 @@ fold (expr)
       /* (-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))
        {
@@ -5528,9 +5250,12 @@ fold (expr)
        }
       else
        {
-         /* x*0 is 0, except for IEEE floating point.  */
-         if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
-              || flag_fast_math)
+         /* Maybe fold x * 0 to 0.  The expressions aren't the same
+            when x is NaN, since x * 0 is also NaN.  Nor are they the
+            same in modes with signed zeros, since multiplying a
+            negative value by 0 gives -0, not +0.  */
+         if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0)))
+             && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0)))
              && real_zerop (arg1))
            return omit_one_operand (type, arg1, arg0);
          /* In IEEE floating point, x*1 is not equivalent to x for snans.
@@ -5539,7 +5264,8 @@ fold (expr)
          if (real_onep (arg1))
            return non_lvalue (convert (type, arg0));
          /* x*2 is x+x */
-         if (! wins && real_twop (arg1) && global_bindings_p () == 0
+         if (! wins && real_twop (arg1)
+             && (*lang_hooks.decls.global_bindings_p) () == 0
              && ! contains_placeholder_p (arg0))
            {
              tree arg = save_expr (arg0);
@@ -5560,7 +5286,7 @@ fold (expr)
 
       /* 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.  */
@@ -5594,10 +5320,10 @@ fold (expr)
          && 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.  */
@@ -5616,7 +5342,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)
@@ -5625,7 +5353,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)
@@ -5634,7 +5364,7 @@ fold (expr)
 
       /* 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.  */
@@ -5663,13 +5393,12 @@ fold (expr)
       goto binary;
 
     case RDIV_EXPR:
-      /* In most cases, do nothing with a divide by zero.  */
-#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
-#ifndef REAL_INFINITY
-      if (TREE_CODE (arg1) == REAL_CST && real_zerop (arg1))
+      /* Don't touch a floating-point divide by zero unless the mode
+        of the constant can represent infinity.  */
+      if (TREE_CODE (arg1) == REAL_CST
+         && !MODE_HAS_INFINITIES (TYPE_MODE (TREE_TYPE (arg1)))
+         && real_zerop (arg1))
        return t;
-#endif
-#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
 
       /* (-A) / (-B) -> A / B  */
       if (TREE_CODE (arg0) == NEGATE_EXPR && TREE_CODE (arg1) == NEGATE_EXPR)
@@ -5683,27 +5412,44 @@ fold (expr)
 
       /* If ARG1 is a constant, we can convert this to a multiply by the
         reciprocal.  This does not have the same rounding properties,
-        so only do this if -ffast-math.  We can actually always safely
-        do it if ARG1 is a power of two, but it's hard to tell if it is
-        or not in a portable manner.  */
+        so only do this if -funsafe-math-optimizations.  We can actually
+        always safely do it if ARG1 is a power of two, but it's hard to
+        tell if it is or not in a portable manner.  */
       if (TREE_CODE (arg1) == REAL_CST)
        {
-         if (flag_fast_math
+         if (flag_unsafe_math_optimizations
              && 0 != (tem = const_binop (code, build_real (type, dconst1),
                                          arg1, 0)))
            return fold (build (MULT_EXPR, type, arg0, tem));
-         /* Find the reciprocal if optimizing and the result is exact. */
+         /* Find the reciprocal if optimizing and the result is exact.  */
          else if (optimize)
            {
              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));
+               }
            }
        }
+      /* Convert A/B/C to A/(B*C).  */
+      if (flag_unsafe_math_optimizations
+         && TREE_CODE (arg0) == RDIV_EXPR)
+       {
+         return fold (build (RDIV_EXPR, type, TREE_OPERAND (arg0, 0),
+                             build (MULT_EXPR, type, TREE_OPERAND (arg0, 1),
+                                    arg1)));
+       }
+      /* Convert A/(B/C) to (A/B)*C.  */
+      if (flag_unsafe_math_optimizations
+         && TREE_CODE (arg1) == RDIV_EXPR)
+       {
+         return fold (build (MULT_EXPR, type,
+                             build (RDIV_EXPR, type, arg0,
+                                    TREE_OPERAND (arg1, 0)),
+                             TREE_OPERAND (arg1, 1)));
+       }
       goto binary;
 
     case TRUNC_DIV_EXPR:
@@ -5726,7 +5472,7 @@ fold (expr)
          && 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);
@@ -5799,14 +5545,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);
@@ -5814,7 +5560,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))
@@ -5838,13 +5584,15 @@ 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);
-      if (TREE_CODE (arg1) == INTEGER_CST && ! integer_zerop (arg1))
-       return non_lvalue (arg0);
+       return non_lvalue (convert (type, arg1));
+      if (TREE_CODE (arg1) == INTEGER_CST && ! integer_zerop (arg1)
+         /* Preserve sequence points.  */
+         && (code != TRUTH_ANDIF_EXPR || ! TREE_SIDE_EFFECTS (arg0)))
+       return non_lvalue (convert (type, arg0));
       /* If second arg is constant zero, result is zero, but first arg
         must be evaluated.  */
       if (integer_zerop (arg1))
@@ -5864,7 +5612,7 @@ fold (expr)
         truth and/or operations and the transformation will still be
         valid.   Also note that we only care about order for the
         ANDIF and ORIF operators.  If B contains side effects, this
-        might change the truth-value of A. */
+        might change the truth-value of A.  */
       if (TREE_CODE (arg0) == TREE_CODE (arg1)
          && (TREE_CODE (arg0) == TRUTH_ANDIF_EXPR
              || TREE_CODE (arg0) == TRUTH_ORIF_EXPR
@@ -5924,13 +5672,15 @@ 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);
-      if (TREE_CODE (arg1) == INTEGER_CST && integer_zerop (arg1))
-       return non_lvalue (arg0);
+       return non_lvalue (convert (type, arg1));
+      if (TREE_CODE (arg1) == INTEGER_CST && integer_zerop (arg1)
+         /* Preserve sequence points.  */
+         && (code != TRUTH_ORIF_EXPR || ! TREE_SIDE_EFFECTS (arg0)))
+       return non_lvalue (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))
@@ -5944,14 +5694,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:
@@ -5971,10 +5721,10 @@ fold (expr)
          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
@@ -5983,7 +5733,6 @@ fold (expr)
                                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)
@@ -6021,7 +5770,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.  */
@@ -6034,7 +5791,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
@@ -6051,7 +5808,7 @@ fold (expr)
                        || integer_onep (folded_compare))
                      return omit_one_operand (type, folded_compare, varop);
 
-                   unsigned_type = type_for_size (size, 1);
+                   unsigned_type = (*lang_hooks.types.type_for_size)(size, 1);
                    precision = TYPE_PRECISION (unsigned_type);
                    mask = build_int_2 (~0, ~0);
                    TREE_TYPE (mask) = unsigned_type;
@@ -6063,11 +5820,10 @@ fold (expr)
                                            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;
              }
          }
@@ -6080,7 +5836,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
@@ -6091,7 +5855,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)
@@ -6105,7 +5869,7 @@ fold (expr)
                        || integer_onep (folded_compare))
                      return omit_one_operand (type, folded_compare, varop);
 
-                   unsigned_type = type_for_size (size, 1);
+                   unsigned_type = (*lang_hooks.types.type_for_size)(size, 1);
                    precision = TYPE_PRECISION (unsigned_type);
                    mask = build_int_2 (~0, ~0);
                    TREE_TYPE (mask) = TREE_TYPE (varop);
@@ -6117,11 +5881,10 @@ fold (expr)
                                            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;
              }
          }
@@ -6192,7 +5955,7 @@ fold (expr)
                   || (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
@@ -6216,7 +5979,7 @@ fold (expr)
                            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
@@ -6263,7 +6026,7 @@ fold (expr)
              || TREE_CODE (arg0) == ROUND_MOD_EXPR)
          && integer_pow2p (TREE_OPERAND (arg0, 1)))
        {
-         tree newtype = unsigned_type (TREE_TYPE (arg0));
+         tree newtype = (*lang_hooks.types.unsigned_type) (TREE_TYPE (arg0));
          tree newmod = build (TREE_CODE (arg0), newtype,
                               convert (newtype, TREE_OPERAND (arg0, 0)),
                               convert (newtype, TREE_OPERAND (arg0, 1)));
@@ -6293,7 +6056,7 @@ fold (expr)
          && 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));
@@ -6320,7 +6083,7 @@ fold (expr)
            case EQ_EXPR:
            case GE_EXPR:
            case LE_EXPR:
-             if (INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
+             if (! FLOAT_TYPE_P (TREE_TYPE (arg0)))
                return constant_boolean_node (1, type);
              code = EQ_EXPR;
              TREE_SET_CODE (t, code);
@@ -6328,7 +6091,7 @@ fold (expr)
 
            case NE_EXPR:
              /* For NE, we can only do this simplification if integer.  */
-             if (! INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
+             if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
                break;
              /* ... fall through ...  */
            case GT_EXPR:
@@ -6382,7 +6145,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))
                {
@@ -6407,8 +6170,8 @@ fold (expr)
                }
 
            else if (TREE_INT_CST_HIGH (arg1) == -1
-                    && (TREE_INT_CST_LOW (arg1)
-                        == ((HOST_WIDE_INT) 1 << (width - 1)))
+                    && (TREE_INT_CST_LOW (arg1)
+                        == ((unsigned HOST_WIDE_INT) 1 << (width - 1)))
                     && ! TREE_UNSIGNED (TREE_TYPE (arg1)))
              switch (TREE_CODE (t))
                {
@@ -6433,28 +6196,48 @@ fold (expr)
                }
 
            else if (TREE_INT_CST_HIGH (arg1) == 0
-                     && (TREE_INT_CST_LOW (arg1)
-                         == ((HOST_WIDE_INT) 1 << (width - 1)) - 1)
-                     && TREE_UNSIGNED (TREE_TYPE (arg1)))
-             
-             switch (TREE_CODE (t))
-               {
-               case LE_EXPR:
-                 return fold (build (GE_EXPR, type,
-                                     convert (signed_type (TREE_TYPE (arg0)),
-                                              arg0),
-                                     convert (signed_type (TREE_TYPE (arg1)),
-                                              integer_zero_node)));
-               case GT_EXPR:
-                 return fold (build (LT_EXPR, type,
-                                     convert (signed_type (TREE_TYPE (arg0)),
-                                              arg0),
-                                     convert (signed_type (TREE_TYPE (arg1)),
-                                              integer_zero_node)));
-
-               default:
-                 break;
-               }
+                    && (TREE_INT_CST_LOW (arg1)
+                        == ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1)
+                    && TREE_UNSIGNED (TREE_TYPE (arg1))
+                    /* signed_type does not work on pointer types.  */
+                    && INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
+             {
+               if (TREE_CODE (t) == LE_EXPR || TREE_CODE (t) == GT_EXPR)
+                 {
+                   tree st0, st1;
+                   st0 = (*lang_hooks.types.signed_type) (TREE_TYPE (arg0));
+                   st1 = (*lang_hooks.types.signed_type) (TREE_TYPE (arg1));
+                   return fold
+                     (build (TREE_CODE (t) == LE_EXPR ? GE_EXPR: LT_EXPR,
+                             type, convert (st0, arg0),
+                             convert (st1, integer_zero_node)));
+                 }
+             }
+            else if (TREE_INT_CST_HIGH (arg1) == 0
+                    && (TREE_INT_CST_LOW (arg1)
+                        == ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1)
+                    && TREE_UNSIGNED (TREE_TYPE (arg1)))
+              switch (TREE_CODE (t))
+                {
+                case GT_EXPR:
+                  return omit_one_operand (type,
+                                           convert (type, integer_zero_node),
+                                           arg0);
+                case GE_EXPR:
+                  TREE_SET_CODE (t, EQ_EXPR);
+                  break;
+
+                case LE_EXPR:
+                  return omit_one_operand (type,
+                                           convert (type, integer_one_node),
+                                           arg0);
+                case LT_EXPR:
+                  TREE_SET_CODE (t, NE_EXPR);
+                  break;
+
+                default:
+                  break;
+                }
          }
       }
 
@@ -6599,6 +6382,33 @@ fold (expr)
                              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.
 
@@ -6631,11 +6441,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)
@@ -6687,7 +6493,7 @@ fold (expr)
 
       TREE_TYPE (t1) = type;
       if (TREE_CODE (type) == BOOLEAN_TYPE)
-       return truthvalue_conversion (t1);
+       return (*lang_hooks.truthvalue_conversion) (t1);
       return t1;
 
     case COND_EXPR:
@@ -6729,23 +6535,38 @@ fold (expr)
 
       /* If we have A op B ? A : C, we may be able to convert this to a
         simpler expression, depending on the operation and the values
-        of B and C.  IEEE floating point prevents this though,
-        because A or B might be -0.0 or a NaN.  */
+        of B and C.  Signed zeros prevent all of these transformations,
+        for reasons given above each one.  */
 
       if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
-         && (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
-             || ! FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (arg0, 0)))
-             || flag_fast_math)
          && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
-                                            arg1, TREE_OPERAND (arg0, 1)))
+                                            arg1, TREE_OPERAND (arg0, 1))
+         && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
        {
          tree arg2 = TREE_OPERAND (t, 2);
          enum tree_code comp_code = TREE_CODE (arg0);
 
          STRIP_NOPS (arg2);
 
-         /* If we have A op 0 ? A : -A, this is A, -A, abs (A), or abs (-A),
-            depending on the comparison operation.  */
+         /* If we have A op 0 ? A : -A, consider applying the following
+            transformations:
+
+            A == 0? A : -A    same as -A
+            A != 0? A : -A    same as A
+            A >= 0? A : -A    same as abs (A)
+            A > 0?  A : -A    same as abs (A)
+            A <= 0? A : -A    same as -abs (A)
+            A < 0?  A : -A    same as -abs (A)
+
+            None of these transformations work for modes with signed
+            zeros.  If A is +/-0, the first two transformations will
+            change the sign of the result (from +0 to -0, or vice
+            versa).  The last four will fix the sign of the result,
+            even though the original expressions could be positive or
+            negative, depending on the sign of A.
+
+            Note that all these transformations are correct if A is
+            NaN, since the two alternatives (A and -A) are also NaNs.  */
          if ((FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (arg0, 1)))
               ? real_zerop (TREE_OPERAND (arg0, 1))
               : integer_zerop (TREE_OPERAND (arg0, 1)))
@@ -6754,20 +6575,27 @@ fold (expr)
            switch (comp_code)
              {
              case EQ_EXPR:
-               return pedantic_non_lvalue (negate_expr (arg1));
+               return
+                 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 GT_EXPR:
                if (TREE_UNSIGNED (TREE_TYPE (arg1)))
-                 arg1 = convert (signed_type (TREE_TYPE (arg1)), arg1);
+                 arg1 = convert ((*lang_hooks.types.signed_type)
+                                 (TREE_TYPE (arg1)), arg1);
                return pedantic_non_lvalue
                  (convert (type, fold (build1 (ABS_EXPR,
                                                TREE_TYPE (arg1), arg1))));
              case LE_EXPR:
              case LT_EXPR:
                if (TREE_UNSIGNED (TREE_TYPE (arg1)))
-                 arg1 = convert (signed_type (TREE_TYPE (arg1)), arg1);
+                 arg1 = convert ((lang_hooks.types.signed_type)
+                                 (TREE_TYPE (arg1)), arg1);
                return pedantic_non_lvalue
                  (negate_expr (convert (type,
                                         fold (build1 (ABS_EXPR,
@@ -6777,8 +6605,10 @@ fold (expr)
                abort ();
              }
 
-         /* If this is A != 0 ? A : 0, this is simply A.  For ==, it is
-            always zero.  */
+         /* A != 0 ? A : 0 is simply A, unless A is -0.  Likewise
+            A == 0 ? A : 0 is always 0 unless A is -0.  Note that
+            both transformations are correct when A is NaN: A != 0
+            is then true, and A == 0 is false.  */
 
          if (integer_zerop (TREE_OPERAND (arg0, 1)) && integer_zerop (arg2))
            {
@@ -6788,9 +6618,32 @@ fold (expr)
                return pedantic_non_lvalue (convert (type, integer_zero_node));
            }
 
-         /* If this is A op B ? A : B, this is either A, B, min (A, B),
-            or max (A, B), depending on the operation.  */
-
+         /* Try some transformations of A op B ? A : B.
+
+            A == B? A : B    same as B
+            A != B? A : B    same as A
+            A >= B? A : B    same as max (A, B)
+            A > B?  A : B    same as max (B, A)
+            A <= B? A : B    same as min (A, B)
+            A < B?  A : B    same as min (B, A)
+
+            As above, these transformations don't work in the presence
+            of signed zeros.  For example, if A and B are zeros of
+            opposite sign, the first two transformations will change
+            the sign of the result.  In the last four, the original
+            expressions give different results for (A=+0, B=-0) and
+            (A=-0, B=+0), but the transformed expressions do not.
+
+            The first two transformations are correct if either A or B
+            is a NaN.  In the first transformation, the condition will
+            be false, and B will indeed be chosen.  In the case of the
+            second transformation, the condition A != B will be true,
+            and A will be chosen.
+
+            The conversions to max() and min() are not correct if B is
+            a number and A is not.  The conditions in the original
+            expressions will be false, so all four give B.  The min()
+            and max() versions would give a NaN instead.  */
          if (operand_equal_for_comparison_p (TREE_OPERAND (arg0, 1),
                                              arg2, TREE_OPERAND (arg0, 0)))
            {
@@ -6798,6 +6651,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:
@@ -6808,23 +6665,25 @@ fold (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,
-                                                 (comp_code == LE_EXPR
-                                                  ? comp_op0 : comp_op1),
-                                                 (comp_code == LE_EXPR
-                                                  ? comp_op1 : comp_op0))))));
+                 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
+                   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)))));
                  break;
                case GE_EXPR:
                case GT_EXPR:
-                 return pedantic_non_lvalue
-                   (convert (type, fold (build (MAX_EXPR, comp_type,
-                                                (comp_code == GE_EXPR
-                                                 ? comp_op0 : comp_op1),
-                                                (comp_code == GE_EXPR
-                                                 ? comp_op1 : comp_op0)))));
+                 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
+                   return pedantic_non_lvalue
+                     (convert (type, fold (build (MAX_EXPR, comp_type,
+                                                  (comp_code == GE_EXPR
+                                                   ? comp_op0 : comp_op1),
+                                                  (comp_code == GE_EXPR
+                                                   ? comp_op1 : comp_op0)))));
                  break;
                default:
                  abort ();
@@ -6897,10 +6756,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
@@ -6923,7 +6782,7 @@ fold (expr)
       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))
@@ -6950,8 +6809,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)
@@ -7003,7 +6862,7 @@ fold (expr)
        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))));
 
@@ -7031,6 +6890,19 @@ fold (expr)
        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) */
@@ -7099,6 +6971,25 @@ multiple_of_p (type, top, bottom)
       return (multiple_of_p (type, TREE_OPERAND (top, 0), bottom)
              && multiple_of_p (type, TREE_OPERAND (top, 1), bottom));
 
+    case LSHIFT_EXPR:
+      if (TREE_CODE (TREE_OPERAND (top, 1)) == INTEGER_CST)
+       {
+         tree op1, t1;
+
+         op1 = TREE_OPERAND (top, 1);
+         /* const_binop may not detect overflow correctly,
+            so check for it explicitly here.  */
+         if (TYPE_PRECISION (TREE_TYPE (size_one_node))
+             > TREE_INT_CST_LOW (op1)
+             && TREE_INT_CST_HIGH (op1) == 0
+             && 0 != (t1 = convert (type,
+                                    const_binop (LSHIFT_EXPR, size_one_node,
+                                                 op1, 0)))
+             && ! TREE_OVERFLOW (t1))
+           return multiple_of_p (type, t1, bottom);
+       }
+      return 0;
+
     case NOP_EXPR:
       /* Can't handle conversions from non-integral or wider integral type.  */
       if ((TREE_CODE (TREE_TYPE (TREE_OPERAND (top, 0))) != INTEGER_TYPE)
@@ -7106,15 +6997,16 @@ multiple_of_p (type, top, bottom)
              < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (top, 0)))))
        return 0;
 
-      /* .. fall through ... */
+      /* .. fall through ...  */
 
     case SAVE_EXPR:
       return multiple_of_p (type, TREE_OPERAND (top, 0), bottom);
 
     case INTEGER_CST:
-      if ((TREE_CODE (bottom) != INTEGER_CST)
-         || (tree_int_cst_sgn (top) < 0)
-         || (tree_int_cst_sgn (bottom) < 0))
+      if (TREE_CODE (bottom) != INTEGER_CST
+         || (TREE_UNSIGNED (type)
+             && (tree_int_cst_sgn (top) < 0
+                 || tree_int_cst_sgn (bottom) < 0)))
        return 0;
       return integer_zerop (const_binop (TRUNC_MOD_EXPR,
                                         top, bottom, 0));
@@ -7123,3 +7015,103 @@ multiple_of_p (type, top, bottom)
       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 ABS_EXPR:
+    case FFS_EXPR:
+      return 1;
+    case INTEGER_CST:
+      return tree_int_cst_sgn (t) >= 0;
+    case TRUNC_DIV_EXPR:
+    case CEIL_DIV_EXPR:
+    case FLOOR_DIV_EXPR:
+    case ROUND_DIV_EXPR:
+      return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
+        && tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+    case TRUNC_MOD_EXPR:
+    case CEIL_MOD_EXPR:
+    case FLOOR_MOD_EXPR:
+    case ROUND_MOD_EXPR:
+      return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
+    case COND_EXPR:
+      return tree_expr_nonnegative_p (TREE_OPERAND (t, 1))
+       && tree_expr_nonnegative_p (TREE_OPERAND (t, 2));
+    case COMPOUND_EXPR:
+      return tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+    case MIN_EXPR:
+      return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
+        && tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+    case MAX_EXPR:
+      return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
+        || tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+    case MODIFY_EXPR:
+      return tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+    case BIND_EXPR:
+      return tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+    case SAVE_EXPR:
+      return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
+    case NON_LVALUE_EXPR:
+      return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
+    case RTL_EXPR:
+      return rtl_expr_nonnegative_p (RTL_EXPR_RTL (t));
+      
+    default:
+      if (truth_value_p (TREE_CODE (t)))
+       /* Truth values evaluate to 0 or 1, which is nonnegative.  */
+       return 1;
+      else
+       /* We don't know sign of `t', so be conservative 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 CONST_VECTOR:
+      {
+       int units, i;
+       rtx elt;
+
+       units = CONST_VECTOR_NUNITS (r);
+
+       for (i = 0; i < units; ++i)
+         {
+           elt = CONST_VECTOR_ELT (r, i);
+           if (!rtl_expr_nonnegative_p (elt))
+             return 0;
+         }
+
+       return 1;
+      }
+
+    case SYMBOL_REF:
+    case LABEL_REF:
+      /* These are always nonnegative.  */
+      return 1;
+
+    default:
+      return 0;
+    }
+}