OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index 3975ae4..07184b9 100644 (file)
@@ -2,22 +2,22 @@
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
    1999, 2000, 2001 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".
@@ -44,7 +44,6 @@ Boston, MA 02111-1307, USA.  */
 
 #include "config.h"
 #include "system.h"
-#include <setjmp.h>
 #include "flags.h"
 #include "tree.h"
 #include "rtl.h"
@@ -52,6 +51,7 @@ Boston, MA 02111-1307, USA.  */
 #include "tm_p.h"
 #include "toplev.h"
 #include "ggc.h"
+#include "hashtab.h"
 
 static void encode             PARAMS ((HOST_WIDE_INT *,
                                         unsigned HOST_WIDE_INT,
@@ -59,13 +59,18 @@ static void encode          PARAMS ((HOST_WIDE_INT *,
 static void decode             PARAMS ((HOST_WIDE_INT *,
                                         unsigned HOST_WIDE_INT *,
                                         HOST_WIDE_INT *));
+#ifndef REAL_ARITHMETIC
+static void exact_real_inverse_1 PARAMS ((PTR));
+#endif
 static tree negate_expr                PARAMS ((tree));
 static tree split_tree         PARAMS ((tree, enum tree_code, tree *, tree *,
                                         int));
 static tree associate_trees    PARAMS ((tree, tree, enum tree_code, tree));
-static tree int_const_binop    PARAMS ((enum tree_code, tree, tree, int, int));
+static tree int_const_binop    PARAMS ((enum tree_code, tree, tree, int));
 static void const_binop_1      PARAMS ((PTR));
 static tree const_binop                PARAMS ((enum tree_code, tree, tree, int));
+static hashval_t size_htab_hash        PARAMS ((const void *));
+static int size_htab_eq                PARAMS ((const void *, const void *));
 static void fold_convert_1     PARAMS ((PTR));
 static tree fold_convert       PARAMS ((tree, tree));
 static enum tree_code invert_tree_comparison PARAMS ((enum tree_code));
@@ -101,7 +106,9 @@ 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));
-
+static tree fold_binary_op_with_conditional_arg 
+  PARAMS ((enum tree_code, tree, tree, tree, int));
+                                                        
 #ifndef BRANCH_COST
 #define BRANCH_COST 1
 #endif
@@ -317,8 +324,8 @@ mul_double (l1, h1, l2, h2, lv, 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;
+  unsigned HOST_WIDE_INT carry;
+  int i, j, k;
   unsigned HOST_WIDE_INT toplow, neglow;
   HOST_WIDE_INT tophigh, neghigh;
 
@@ -510,7 +517,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.  */
 
@@ -530,7 +537,7 @@ div_and_round_double (code, uns,
   int quo_neg = 0;
   HOST_WIDE_INT num[4 + 1];    /* extra element for scaling.  */
   HOST_WIDE_INT den[4], quo[4];
-  register int i, j;
+  int i, j;
   unsigned HOST_WIDE_INT work;
   unsigned HOST_WIDE_INT carry = 0;
   unsigned HOST_WIDE_INT lnum = lnum_orig;
@@ -653,7 +660,7 @@ div_and_round_double (code, uns,
          else
            quo_est = BASE - 1;
 
-         /* Refine quo_est so it's usually correct, and at most one high.   */
+         /* Refine quo_est so it's usually correct, and at most one high.  */
          tmp = work - quo_est * den[den_hi_sig];
          if (tmp < BASE
              && (den[den_hi_sig - 1] * quo_est
@@ -817,10 +824,10 @@ target_isinf (x)
       unsigned sign      :  1;
       unsigned exponent  : 11;
       unsigned mantissa1 : 20;
-      unsigned mantissa2;
+      unsigned mantissa2 : 32;
     } little_endian;
     struct {
-      unsigned mantissa2;
+      unsigned mantissa2 : 32;
       unsigned mantissa1 : 20;
       unsigned exponent  : 11;
       unsigned sign      :  1;
@@ -857,10 +864,10 @@ target_isnan (x)
       unsigned sign      :  1;
       unsigned exponent  : 11;
       unsigned mantissa1 : 20;
-      unsigned mantissa2;
+      unsigned mantissa2 : 32;
     } little_endian;
     struct {
-      unsigned mantissa2;
+      unsigned mantissa2 : 32;
       unsigned mantissa1 : 20;
       unsigned exponent  : 11;
       unsigned sign      :  1;
@@ -897,10 +904,10 @@ target_negative (x)
       unsigned sign      :  1;
       unsigned exponent  : 11;
       unsigned mantissa1 : 20;
-      unsigned mantissa2;
+      unsigned mantissa2 : 32;
     } little_endian;
     struct {
-      unsigned mantissa2;
+      unsigned mantissa2 : 32;
       unsigned mantissa1 : 20;
       unsigned exponent  : 11;
       unsigned sign      :  1;
@@ -954,51 +961,41 @@ target_negative (x)
 
 /* Try to change R into its exact multiplicative inverse in machine mode
    MODE.  Return nonzero function value if successful.  */
+struct exact_real_inverse_args
+{
+  REAL_VALUE_TYPE *r;
+  enum machine_mode mode;
+  int success;
+};
 
-int
-exact_real_inverse (mode, r)
-     enum machine_mode mode;
-     REAL_VALUE_TYPE *r;
+static void
+exact_real_inverse_1 (p)
+     PTR p;
 {
-  jmp_buf float_error;
+  struct exact_real_inverse_args *args =
+    (struct exact_real_inverse_args *) p;
+
+  enum machine_mode mode = args->mode;
+  REAL_VALUE_TYPE *r = args->r;
+
   union
-    {
-      double d;
-      unsigned short i[4];
-    }x, t, y;
+  {
+    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
+     on the endian-ness of the host doubles.  */
+#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT \
+ || HOST_FLOAT_FORMAT == IBM_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
+# define K (2 * HOST_FLOAT_WORDS_BIG_ENDIAN)
 #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;
@@ -1038,9 +1035,40 @@ fail:
 #endif
 
   /* Output the reciprocal and return success flag.  */
-  set_float_handler (NULL_PTR);
   *r = y.d;
-  return 1;
+  args->success = 1;
+  return;
+
+ fail:
+  args->success = 0;
+  return;
+
+#undef K
+}
+
+
+int
+exact_real_inverse (mode, r)
+     enum machine_mode mode;
+     REAL_VALUE_TYPE *r;
+{
+  struct exact_real_inverse_args args;
+
+  /* Disable if insufficient information on the data structure.  */
+#if HOST_FLOAT_FORMAT == UNKNOWN_FLOAT_FORMAT
+  return 0;
+#endif
+
+  /* Usually disable if bounds checks are not reliable.  */
+  if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT) && !flag_pretend_float)
+    return 0;
+
+  args.mode = mode;
+  args.r = r;
+
+  if (do_float_handler (exact_real_inverse_1, (PTR) &args))
+    return args.success;
+  return 0;
 }
 
 /* Convert C99 hexadecimal floating point string constant S.  Return
@@ -1049,11 +1077,11 @@ fail:
 
 REAL_VALUE_TYPE
 real_hex_to_f (s, mode)
-   char *s;
+   const char *s;
    enum machine_mode mode;
 {
   REAL_VALUE_TYPE ip;
-  char *p = s;
+  const char *p = s;
   unsigned HOST_WIDE_INT low, high;
   int shcount, nrmcount, k;
   int sign, expsign, isfloat;
@@ -1099,8 +1127,7 @@ real_hex_to_f (s, mode)
   shcount = 0;
   while ((c = *p) != '\0')
     {
-      if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')
-         || (c >= 'a' && c <= 'f'))
+      if (ISXDIGIT (c))
        {
          k = c & CHARMASK;
          if (k >= 'a' && k <= 'f')
@@ -1309,7 +1336,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),
@@ -1352,7 +1379,7 @@ split_tree (in, code, conp, litp, negate_p)
   *conp = 0;
   *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)
@@ -1383,7 +1410,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)
@@ -1453,14 +1480,13 @@ 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;
 {
   unsigned HOST_WIDE_INT int1l, int2l;
   HOST_WIDE_INT int1h, int2h;
@@ -1468,8 +1494,11 @@ int_const_binop (code, arg1, arg2, notrunc, forsize)
   HOST_WIDE_INT hi;
   unsigned HOST_WIDE_INT garbagel;
   HOST_WIDE_INT garbageh;
-  register tree t;
-  int uns = TREE_UNSIGNED (TREE_TYPE (arg1));
+  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;
 
@@ -1502,7 +1531,7 @@ int_const_binop (code, arg1, arg2, notrunc, forsize)
       /* It's unclear from the C standard whether shifts can overflow.
         The following code ignores overflow; perhaps a C standard
         interpretation ruling is needed.  */
-      lshift_double (int1l, int1h, int2l, TYPE_PRECISION (TREE_TYPE (arg1)),
+      lshift_double (int1l, int1h, int2l, TYPE_PRECISION (type),
                     &low, &hi, !uns);
       no_overflow = 1;
       break;
@@ -1510,7 +1539,7 @@ int_const_binop (code, arg1, arg2, notrunc, forsize)
     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;
 
@@ -1544,7 +1573,7 @@ int_const_binop (code, arg1, arg2, notrunc, forsize)
          break;
        }
 
-      /* ... fall through ... */
+      /* ... fall through ...  */
 
     case ROUND_DIV_EXPR:
       if (int2h == 0 && int2l == 1)
@@ -1558,8 +1587,7 @@ 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;
 
@@ -1577,7 +1605,7 @@ int_const_binop (code, arg1, arg2, notrunc, forsize)
          break;
        }
 
-      /* ... fall through ... */
+      /* ... fall through ...  */
 
     case ROUND_MOD_EXPR:
       overflow = div_and_round_double (code, uns,
@@ -1607,9 +1635,14 @@ int_const_binop (code, arg1, arg2, notrunc, forsize)
       abort ();
     }
 
-  if (forsize && hi == 0 && low < 10000
+  /* 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, TREE_TYPE (arg1));
+    return size_int_type_wide (low, type);
   else
     {
       t = build_int_2 (low, hi);
@@ -1617,14 +1650,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))
@@ -1708,14 +1743,14 @@ 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);
 
   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)
@@ -1743,11 +1778,11 @@ const_binop (code, arg1, arg2, notrunc)
       args.code = code;
 
       if (do_float_handler (const_binop_1, (PTR) &args))
-       /* Receive output from const_binop_1. */
+       /* Receive output from const_binop_1.  */
        t = args.t;
       else
        {
-         /* We got an exception from const_binop_1. */
+         /* We got an exception from const_binop_1.  */
          t = copy_node (arg1);
          overflow = 1;
        }
@@ -1764,12 +1799,12 @@ const_binop (code, arg1, arg2, notrunc)
 #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)
        {
@@ -1803,7 +1838,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),
@@ -1840,6 +1875,39 @@ 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 and of the sizetype represented by KIND.  */
@@ -1859,40 +1927,38 @@ size_int_type_wide (number, type)
      HOST_WIDE_INT number;
      tree type;
 {
-  /* Type-size nodes already made for small sizes.  */
-  static tree size_table[2048 + 1];
-  static int init_p = 0;
-  tree t;
+  static htab_t size_htab = 0;
+  static tree new_const = 0;
+  PTR *slot;
 
-  if (! init_p)
+  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) ARRAY_SIZE (size_table))
+  /* 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] != 0)
-       for (t = size_table[number]; t != 0; t = TREE_CHAIN (t))
-         if (TREE_TYPE (t) == type)
-           return t;
-
-      t = build_int_2 (number, 0);
-      TREE_TYPE (t) = type;
-      TREE_CHAIN (t) = size_table[number];
-      size_table[number] = t;
+      tree t = new_const;
 
+      *slot = (PTR) new_const;
+      new_const = make_node (INTEGER_CST);
       return t;
     }
-
-  t = build_int_2 (number, number < 0 ? -1 : 0);
-  TREE_TYPE (t) = type;
-  TREE_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (t) = force_fit_type (t, 0);
-  return t;
+  else
+    return (tree) *slot;
 }
 
 /* Combine operands OP1 and OP2 with arithmetic operation CODE.  CODE
@@ -1924,7 +1990,7 @@ 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)
@@ -1978,9 +2044,9 @@ size_diffop (arg0, arg1)
 /* 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. */
+  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
@@ -2002,10 +2068,10 @@ fold_convert_1 (data)
 
 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))
@@ -2020,6 +2086,7 @@ fold_convert (t, arg1)
          /* 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);
 
@@ -2380,7 +2447,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;
@@ -2393,6 +2460,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),
@@ -2716,7 +2784,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,
@@ -2933,7 +3003,7 @@ 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);
 
@@ -3259,7 +3329,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)
@@ -4485,7 +4555,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)));
 
@@ -4504,13 +4579,10 @@ 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;
        }
 
@@ -4541,7 +4613,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),
@@ -4559,7 +4631,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:
@@ -4687,17 +4759,146 @@ 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 analagous --
+     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)
+      && 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
 /* Perform constant folding and related simplification of EXPR.
    The related simplifications include x*1 => x, x*0 => 0, etc.,
@@ -4711,13 +4912,13 @@ tree
 fold (expr)
      tree expr;
 {
-  register tree t = expr;
+  tree t = expr;
   tree t1 = NULL_TREE;
   tree tem;
   tree type = TREE_TYPE (expr);
-  register tree arg0 = NULL_TREE, arg1 = NULL_TREE;
-  register enum tree_code code = TREE_CODE (t);
-  register int kind = TREE_CODE_CLASS (code);
+  tree arg0 = NULL_TREE, arg1 = NULL_TREE;
+  enum tree_code code = TREE_CODE (t);
+  int kind = TREE_CODE_CLASS (code);
   int invert;
   /* WINS will be nonzero when the switch is done
      if all operands are constant.  */
@@ -4725,7 +4926,7 @@ fold (expr)
 
   /* 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.  */
@@ -4764,8 +4965,8 @@ fold (expr)
     }
   else if (IS_EXPR_CODE_CLASS (kind) || kind == 'r')
     {
-      register int len = TREE_CODE_LENGTH (code);
-      register int i;
+      int len = first_rtl_op (code);
+      int i;
       for (i = 0; i < len; i++)
        {
          tree op = TREE_OPERAND (t, i);
@@ -4919,70 +5120,9 @@ fold (expr)
               && (! TREE_SIDE_EFFECTS (arg0)
                   || (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)));
@@ -4994,55 +5134,9 @@ fold (expr)
               && (! TREE_SIDE_EFFECTS (arg1)
                   || (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)
@@ -5232,7 +5326,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));
 
@@ -5243,8 +5337,16 @@ 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
                {
                  unsigned HOST_WIDE_INT low;
                  HOST_WIDE_INT high;
@@ -5427,7 +5529,7 @@ fold (expr)
        }
       /* In IEEE floating point, x+0 may not equal x.  */
       else if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
-               || flag_fast_math)
+               || flag_unsafe_math_optimizations)
               && real_zerop (arg1))
        return non_lvalue (convert (type, arg0));
       /* x+(-0) equals x, even for IEEE.  */
@@ -5441,7 +5543,7 @@ fold (expr)
       /* (A << B) + (A >> (Z - B)) if A is unsigned and Z is the size of A
         is a rotate of A by B bits.  */
       {
-       register enum tree_code code0, code1;
+       enum tree_code code0, code1;
        code0 = TREE_CODE (arg0);
        code1 = TREE_CODE (arg1);
        if (((code0 == RSHIFT_EXPR && code1 == LSHIFT_EXPR)
@@ -5450,8 +5552,8 @@ fold (expr)
                                TREE_OPERAND (arg1, 0), 0)
            && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
          {
-           register tree tree01, tree11;
-           register enum tree_code code01, code11;
+           tree tree01, tree11;
+           enum tree_code code01, code11;
 
            tree01 = TREE_OPERAND (arg0, 1);
            tree11 = TREE_OPERAND (arg1, 1);
@@ -5511,11 +5613,11 @@ fold (expr)
         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;
 
@@ -5523,7 +5625,7 @@ fold (expr)
             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. */
+            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);
 
@@ -5592,7 +5694,7 @@ fold (expr)
        }
 
       else if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
-              || flag_fast_math)
+              || flag_unsafe_math_optimizations)
        {
          /* Except with IEEE floating point, 0-x equals -x.  */
          if (! wins && real_zerop (arg0))
@@ -5608,7 +5710,7 @@ fold (expr)
         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);
 
@@ -5647,7 +5749,7 @@ fold (expr)
        {
          /* x*0 is 0, except for IEEE floating point.  */
          if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
-              || flag_fast_math)
+              || flag_unsafe_math_optimizations)
              && real_zerop (arg1))
            return omit_one_operand (type, arg1, arg0);
          /* In IEEE floating point, x*1 is not equivalent to x for snans.
@@ -5804,16 +5906,16 @@ 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;
@@ -5825,6 +5927,23 @@ fold (expr)
                }
            }
        }
+      /* 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:
@@ -5987,7 +6106,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
@@ -6458,7 +6577,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);
@@ -6466,7 +6585,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:
@@ -6573,7 +6692,9 @@ fold (expr)
            else if (TREE_INT_CST_HIGH (arg1) == 0
                      && (TREE_INT_CST_LOW (arg1)
                          == ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1)
-                     && TREE_UNSIGNED (TREE_TYPE (arg1)))
+                     && TREE_UNSIGNED (TREE_TYPE (arg1))
+                        /* signed_type does not work on pointer types.  */
+                     && INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
 
              switch (TREE_CODE (t))
                {
@@ -6869,7 +6990,7 @@ fold (expr)
       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)
+             || flag_unsafe_math_optimizations)
          && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
                                             arg1, TREE_OPERAND (arg0, 1)))
        {
@@ -7256,6 +7377,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)
@@ -7263,15 +7403,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));
@@ -7289,13 +7430,41 @@ tree_expr_nonnegative_p (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));