OSDN Git Service

* collect2.c (find_a_file): Use HAVE_DOS_BASED_FILE_SYSTEM in place
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index 65a6d85..9b003c2 100644 (file)
@@ -1,5 +1,5 @@
 /* Fold a constant sub-tree into a single node for C-compiler
-   Copyright (C) 1987, 88, 92-96, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 92-98, 1999 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -27,7 +27,7 @@ Boston, MA 02111-1307, USA.  */
   @@ for cross-compilers.  */
 
 
-/* The entry points in this file are fold, size_int, size_binop
+/* The entry points in this file are fold, size_int_wide, size_binop
    and force_fit_type.
 
    fold takes a tree as argument and returns a simplified tree.
@@ -43,13 +43,12 @@ Boston, MA 02111-1307, USA.  */
    forces the value to fit the type.  It returns an overflow indicator.  */
 
 #include "config.h"
-#include <stdio.h>
+#include "system.h"
 #include <setjmp.h>
 #include "flags.h"
 #include "tree.h"
-
-/* Handle floating overflow for `const_binop'.  */
-static jmp_buf float_error;
+#include "rtl.h"
+#include "toplev.h"
 
 static void encode             PROTO((HOST_WIDE_INT *,
                                       HOST_WIDE_INT, HOST_WIDE_INT));
@@ -93,6 +92,10 @@ static tree unextend         PROTO((tree, int, int, tree));
 static tree fold_truthop       PROTO((enum tree_code, tree, tree, tree));
 static tree strip_compound_expr PROTO((tree, tree));
 static int multiple_of_p       PROTO((tree, tree, tree));
+static tree constant_boolean_node PROTO((int, tree));
+static int count_cond          PROTO((tree, int));
+static void const_binop_1      PROTO((PTR));
+static void fold_convert_1     PROTO((PTR));
 
 #ifndef BRANCH_COST
 #define BRANCH_COST 1
@@ -176,7 +179,7 @@ force_fit_type (t, overflow)
   low = TREE_INT_CST_LOW (t);
   high = TREE_INT_CST_HIGH (t);
 
-  if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE)
+  if (POINTER_TYPE_P (TREE_TYPE (t)))
     prec = POINTER_SIZE;
   else
     prec = TYPE_PRECISION (TREE_TYPE (t));
@@ -356,13 +359,13 @@ lshift_double (l1, h1, count, prec, lv, hv, arith)
 
   if (count >= HOST_BITS_PER_WIDE_INT)
     {
-      *hv = (unsigned HOST_WIDE_INT) l1 << count - HOST_BITS_PER_WIDE_INT;
+      *hv = (unsigned HOST_WIDE_INT) 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));
+            | ((unsigned HOST_WIDE_INT) l1 >> (HOST_BITS_PER_WIDE_INT - count - 1) >> 1));
       *lv = (unsigned HOST_WIDE_INT) l1 << count;
     }
 }
@@ -375,7 +378,7 @@ 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;
+     int prec ATTRIBUTE_UNUSED;
      HOST_WIDE_INT *lv, *hv;
      int arith;
 {
@@ -392,14 +395,14 @@ rshift_double (l1, h1, count, prec, lv, hv, arith)
   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));
+      *lv = ((signmask << (2 * HOST_BITS_PER_WIDE_INT - count - 1) << 1)
+            | ((unsigned HOST_WIDE_INT) h1 >> (count - HOST_BITS_PER_WIDE_INT)));
     }
   else
     {
       *lv = (((unsigned HOST_WIDE_INT) 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 << (HOST_BITS_PER_WIDE_INT - count - 1) << 1));
+      *hv = ((signmask << (HOST_BITS_PER_WIDE_INT - count))
             | ((unsigned HOST_WIDE_INT) h1 >> count));
     }
 }
@@ -526,7 +529,7 @@ div_and_round_double (code, uns,
   encode (den, lden, hden);
 
   /* Special code for when the divisor < BASE.  */
-  if (hden == 0 && lden < BASE)
+  if (hden == 0 && lden < (HOST_WIDE_INT) BASE)
     {
       /* hnum != 0 already checked.  */
       for (i = 4 - 1; i >= 0; i--)
@@ -882,6 +885,7 @@ exact_real_inverse (mode, r)
      enum machine_mode mode;
      REAL_VALUE_TYPE *r;
 {
+  jmp_buf float_error;
   union
     {
       double d;
@@ -961,6 +965,235 @@ fail:
   *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
+   fp 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 frexpon, expon, shcount, nrmcount, k;
+   int sign, expsign, decpt, isfloat, isldouble, gotp, lost;
+   char c;
+
+   isldouble = 0;
+   isfloat = 0;
+   frexpon = 0;
+   expon = 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;
+   lost = 0; /* Nonzero low order bits shifted out and discarded.  */
+   frexpon = 0;  /* Bits after the decimal point.  */
+   expon = 0;  /* Value of exponent.  */
+   decpt = 0;  /* How many decimal points.  */
+   gotp = 0;  /* How many P's.  */
+   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')
+        {
+          isldouble = 1;
+          ++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
 /* Split a tree IN into a constant and a variable part
@@ -1215,7 +1448,9 @@ int_const_binop (code, arg1, arg2, notrunc, forsize)
     }
 
   if (TREE_TYPE (arg1) == sizetype && hi == 0
-      && low >= 0 && low <= TREE_INT_CST_LOW (TYPE_MAX_VALUE (sizetype))
+      && 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);
@@ -1243,6 +1478,67 @@ int_const_binop (code, arg1, arg2, notrunc, forsize)
   return t;
 }
 
+struct cb_args
+{
+  /* Input */
+  tree arg1;
+  REAL_VALUE_TYPE d1, d2;
+  enum tree_code code;
+  /* Output */
+  tree t;
+};
+
+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 (TREE_TYPE (args->arg1),
+               real_value_truncate (TYPE_MODE (TREE_TYPE (args->arg1)),
+                                    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,
@@ -1267,8 +1563,8 @@ const_binop (code, arg1, arg2, notrunc)
       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);
@@ -1279,57 +1575,24 @@ const_binop (code, arg1, arg2, notrunc)
        return arg1;
       else if (REAL_VALUE_ISNAN (d2))
        return arg2;
-      else if (setjmp (float_error))
+
+      /* Setup input for const_binop_1() */
+      args.arg1 = arg1;
+      args.d1 = d1;
+      args.d2 = d2;
+      args.code = code;
+      
+      if (do_float_handler (const_binop_1, (PTR) &args))
        {
-         t = copy_node (arg1);
-         overflow = 1;
-         goto got_float;
+         /* Receive output from const_binop_1() */
+         t = args.t;
        }
-
-      set_float_handler (float_error);
-
-#ifdef REAL_ARITHMETIC
-      REAL_ARITHMETIC (value, code, d1, d2);
-#else
-      switch (code)
+      else
        {
-       case PLUS_EXPR:
-         value = d1 + d2;
-         break;
-
-       case MINUS_EXPR:
-         value = d1 - d2;
-         break;
-
-       case MULT_EXPR:
-         value = d1 * d2;
-         break;
-
-       case RDIV_EXPR:
-#ifndef REAL_INFINITY
-         if (d2 == 0)
-           abort ();
-#endif
-
-         value = d1 / d2;
-         break;
-
-       case MIN_EXPR:
-         value = MIN (d1, d2);
-         break;
-
-       case MAX_EXPR:
-         value = MAX (d1, d2);
-         break;
-
-       default:
-         abort ();
+         /* We got an exception from const_binop_1() */
+         t = copy_node (arg1);
+         overflow = 1;
        }
-#endif /* no REAL_ARITHMETIC */
-      t = build_real (TREE_TYPE (arg1),
-                     real_value_truncate (TYPE_MODE (TREE_TYPE (arg1)), value));
-    got_float:
-      set_float_handler (NULL_PTR);
 
       TREE_OVERFLOW (t)
        = (force_fit_type (t, overflow)
@@ -1420,33 +1683,36 @@ const_binop (code, arg1, arg2, notrunc)
   return 0;
 }
 \f
-/* Return an INTEGER_CST with value V and type from `sizetype'.  */
+/* Return an INTEGER_CST with value V .  The type is determined by bit_p:
+   if it is zero, the type is taken from sizetype; if it is one, the type
+   is taken from bitsizetype.  */
 
 tree
-size_int (number)
-     unsigned HOST_WIDE_INT number;
+size_int_wide (number, high, bit_p)
+     unsigned HOST_WIDE_INT number, high;
+     int bit_p;
 {
   register tree t;
   /* Type-size nodes already made for small sizes.  */
-  static tree size_table[2*HOST_BITS_PER_WIDE_INT + 1];
+  static tree size_table[2*HOST_BITS_PER_WIDE_INT + 1][2];
 
-  if (number < 2*HOST_BITS_PER_WIDE_INT + 1
-      && size_table[number] != 0)
-    return size_table[number];
-  if (number < 2*HOST_BITS_PER_WIDE_INT + 1)
+  if (number < 2*HOST_BITS_PER_WIDE_INT + 1 && ! high
+      && size_table[number][bit_p] != 0)
+    return size_table[number][bit_p];
+  if (number < 2*HOST_BITS_PER_WIDE_INT + 1 && ! high)
     {
       push_obstacks_nochange ();
       /* Make this a permanent node.  */
       end_temporary_allocation ();
       t = build_int_2 (number, 0);
-      TREE_TYPE (t) = sizetype;
-      size_table[number] = t;
+      TREE_TYPE (t) = bit_p ? bitsizetype : sizetype;
+      size_table[number][bit_p] = t;
       pop_obstacks ();
     }
   else
     {
-      t = build_int_2 (number, 0);
-      TREE_TYPE (t) = sizetype;
+      t = build_int_2 (number, high);
+      TREE_TYPE (t) = bit_p ? bitsizetype : sizetype;
       TREE_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (t) = force_fit_type (t, 0);
     }
   return t;
@@ -1482,7 +1748,60 @@ size_binop (code, arg0, arg1)
 
   return fold (build (code, sizetype, 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.  */
+
+tree
+ssize_binop (code, arg0, arg1)
+     enum tree_code code;
+     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);
+    }
+
+  if (arg0 == error_mark_node || arg1 == error_mark_node)
+    return error_mark_node;
+
+  return fold (build (code, ssizetype, arg0, arg1));
+}
 \f
+struct fc_args
+{
+  /* Input */
+  tree arg1, type;
+  /* Output */
+  tree t;
+};
+
+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.  */
 
@@ -1494,7 +1813,7 @@ fold_convert (t, arg1)
   register tree type = TREE_TYPE (t);
   int overflow = 0;
 
-  if (TREE_CODE (type) == POINTER_TYPE || INTEGRAL_TYPE_P (type))
+  if (POINTER_TYPE_P (type) || INTEGRAL_TYPE_P (type))
     {
       if (TREE_CODE (arg1) == INTEGER_CST)
        {
@@ -1514,12 +1833,12 @@ fold_convert (t, arg1)
             if ARG1 is a too-large unsigned value and T is signed.
             But don't indicate an overflow if converting a pointer.  */
          TREE_OVERFLOW (t)
-           = (TREE_OVERFLOW (arg1)
-              || (force_fit_type (t,
-                                 (TREE_INT_CST_HIGH (arg1) < 0
-                                  & (TREE_UNSIGNED (type)
-                                    < TREE_UNSIGNED (TREE_TYPE (arg1)))))
-                  && TREE_CODE (TREE_TYPE (arg1)) != POINTER_TYPE));
+           = ((force_fit_type (t,
+                               (TREE_INT_CST_HIGH (arg1) < 0
+                                && (TREE_UNSIGNED (type)
+                                   < TREE_UNSIGNED (TREE_TYPE (arg1)))))
+               && ! POINTER_TYPE_P (TREE_TYPE (arg1)))
+              || TREE_OVERFLOW (arg1));
          TREE_CONSTANT_OVERFLOW (t)
            = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
        }
@@ -1532,25 +1851,34 @@ fold_convert (t, arg1)
          REAL_VALUE_TYPE l;
          REAL_VALUE_TYPE u;
          tree type1 = TREE_TYPE (arg1);
+         int no_upper_bound;
 
          x = TREE_REAL_CST (arg1);
          l = real_value_from_int_cst (type1, TYPE_MIN_VALUE (type));
-         u = real_value_from_int_cst (type1, TYPE_MAX_VALUE (type));
+
+         no_upper_bound = (TYPE_MAX_VALUE (type) == NULL);
+         if (!no_upper_bound)
+           u = real_value_from_int_cst (type1, TYPE_MAX_VALUE (type));
+
          /* 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);
-         REAL_ARITHMETIC (u, PLUS_EXPR, u, dconst1);
+         if (!no_upper_bound)
+           REAL_ARITHMETIC (u, PLUS_EXPR, u, dconst1);
 #else
          l--;
-         u++;
+         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))
            overflow = 1, x = dconst0;
-         else if (! (REAL_VALUES_LESS (l, x) && REAL_VALUES_LESS (x, u)))
+         else if (! (REAL_VALUES_LESS (l, x)
+                     && !no_upper_bound
+                     && REAL_VALUES_LESS (x, u)))
            overflow = 1;
 
 #ifndef REAL_ARITHMETIC
@@ -1599,25 +1927,31 @@ fold_convert (t, 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;
              TREE_TYPE (arg1) = type;
              return t;
            }
-         else if (setjmp (float_error))
+
+         /* 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);
-             goto got_it;
            }
-         set_float_handler (float_error);
 
-         t = build_real (type, real_value_truncate (TYPE_MODE (type),
-                                                    TREE_REAL_CST (arg1)));
-         set_float_handler (NULL_PTR);
-
-       got_it:
          TREE_OVERFLOW (t)
            = TREE_OVERFLOW (arg1) | force_fit_type (t, overflow);
          TREE_CONSTANT_OVERFLOW (t)
@@ -1629,8 +1963,7 @@ fold_convert (t, arg1)
   return t;
 }
 \f
-/* Return an expr equal to X but certainly not valid as an lvalue.
-   Also make sure it is not valid as an null pointer constant.  */
+/* Return an expr equal to X but certainly not valid as an lvalue.  */
 
 tree
 non_lvalue (x)
@@ -1644,18 +1977,7 @@ non_lvalue (x)
       || TREE_CODE (x) == REAL_CST
       || TREE_CODE (x) == STRING_CST
       || TREE_CODE (x) == ADDR_EXPR)
-    {
-      if (TREE_CODE (x) == INTEGER_CST && integer_zerop (x))
-       {
-         /* Use NOP_EXPR instead of NON_LVALUE_EXPR
-            so convert_for_assignment won't strip it.
-            This is so this 0 won't be treated as a null pointer constant.  */
-         result = build1 (NOP_EXPR, TREE_TYPE (x), x);
-         TREE_CONSTANT (result) = TREE_CONSTANT (x);
-         return result;
-       }
-      return x;
-    }
+    return x;
 
   result = build1 (NON_LVALUE_EXPR, TREE_TYPE (x), x);
   TREE_CONSTANT (result) = TREE_CONSTANT (x);
@@ -1878,6 +2200,11 @@ operand_equal_p (arg0, arg1, only_const)
        default:
          return 0;
        }
+
+    case 'e':
+      if (TREE_CODE (arg0) == RTL_EXPR)
+       return rtx_equal_p (RTL_EXPR_RTL (arg0), RTL_EXPR_RTL (arg1));
+      return 0;
       
     default:
       return 0;
@@ -1895,7 +2222,7 @@ operand_equal_for_comparison_p (arg0, arg1, other)
      tree other;
 {
   int unsignedp1, unsignedpo;
-  tree primarg1, primother;
+  tree primarg0, primarg1, primother;
   unsigned correct_width;
 
   if (operand_equal_p (arg0, arg1, 0))
@@ -1905,6 +2232,14 @@ operand_equal_for_comparison_p (arg0, arg1, other)
       || ! INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
     return 0;
 
+  /* Discard any conversions that don't change the modes of ARG0 and ARG1
+     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);
+  if (operand_equal_p (primarg0, primarg1, 0))
+    return 1;
+
   /* Duplicate what shorten_compare does to ARG1 and see if that gives the
      actual comparison operand, ARG0.
 
@@ -2093,7 +2428,7 @@ eval_subst (arg, old0, new0, old1, new1)
        default:
          break;
        }
-      /* fall through (???) */
+      /* fall through - ??? */
 
     case '<':
       {
@@ -2178,7 +2513,7 @@ invert_truthvalue (arg)
   if (TREE_CODE_CLASS (code) == '<')
     {
       if (FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
-         && code != NE_EXPR && code != EQ_EXPR)
+         && !flag_fast_math && code != NE_EXPR && code != EQ_EXPR)
        return build1 (TRUTH_NOT_EXPR, type, arg);
       else
        return build (invert_tree_comparison (code), type,
@@ -2332,7 +2667,7 @@ make_bit_field_ref (inner, type, bitsize, bitpos, unsignedp)
      int unsignedp;
 {
   tree result = build (BIT_FIELD_REF, type, inner,
-                      size_int (bitsize), size_int (bitpos));
+                      size_int (bitsize), bitsize_int (bitpos, 0L));
 
   TREE_UNSIGNED (result) = unsignedp;
 
@@ -2366,15 +2701,15 @@ optimize_bit_field_compare (code, compare_type, lhs, rhs)
      tree lhs, rhs;
 {
   int lbitpos, lbitsize, rbitpos, rbitsize;
-  int lnbitpos, lnbitsize, rnbitpos, rnbitsize;
+  int lnbitpos, lnbitsize, rnbitpos = 0, rnbitsize = 0;
   tree type = TREE_TYPE (lhs);
   tree signed_type, unsigned_type;
   int const_p = TREE_CODE (rhs) == INTEGER_CST;
-  enum machine_mode lmode, rmode, lnmode, rnmode;
+  enum machine_mode lmode, rmode, lnmode, rnmode = VOIDmode;
   int lunsignedp, runsignedp;
   int lvolatilep = 0, rvolatilep = 0;
   int alignment;
-  tree linner, rinner;
+  tree linner, rinner = NULL_TREE;
   tree mask;
   tree offset;
 
@@ -2479,8 +2814,8 @@ optimize_bit_field_compare (code, compare_type, lhs, rhs)
                                        convert (unsigned_type, rhs),
                                        size_int (lbitsize), 0)))
        {
-         warning ("comparison is always %s due to width of bitfield",
-                  code == NE_EXPR ? "one" : "zero");
+         warning ("comparison is always %d due to width of bitfield",
+                  code == NE_EXPR);
          return convert (compare_type,
                          (code == NE_EXPR
                           ? integer_one_node : integer_zero_node));
@@ -2492,8 +2827,8 @@ 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 %s due to width of bitfield",
-                  code == NE_EXPR ? "one" : "zero");
+         warning ("comparison is always %d due to width of bitfield",
+                  code == NE_EXPR);
          return convert (compare_type,
                          (code == NE_EXPR
                           ? integer_one_node : integer_zero_node));
@@ -2546,7 +2881,7 @@ optimize_bit_field_compare (code, compare_type, lhs, rhs)
    *PMASK is set to the mask used.  This is either contained in a
    BIT_AND_EXPR or derived from the width of the field.
 
-   *PAND_MASK is set the the mask found in a BIT_AND_EXPR, if any.
+   *PAND_MASK is set to the mask found in a BIT_AND_EXPR, if any.
 
    Return 0 if this is not a component reference or is one that we can't
    do anything with.  */
@@ -2727,21 +3062,33 @@ range_binop (code, type, arg0, upper0_p, arg1, upper1_p)
     return 0;
 
   /* Set SGN[01] to -1 if ARG[01] is a lower bound, 1 for upper, and 0
-     for neither.  Then compute our result treating them as never equal
-     and comparing bounds to non-bounds as above.  */
+     for neither.  In real maths, we cannot assume open ended ranges are
+     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. */
   sgn0 = arg0 != 0 ? 0 : (upper0_p ? 1 : -1);
   sgn1 = arg1 != 0 ? 0 : (upper1_p ? 1 : -1);
   switch (code)
     {
-    case EQ_EXPR:  case NE_EXPR:
-      result = (code == NE_EXPR);
+    case EQ_EXPR:
+      result = sgn0 == sgn1;
+      break;
+    case NE_EXPR:
+      result = sgn0 != sgn1;
       break;
-    case LT_EXPR:  case LE_EXPR:
+    case LT_EXPR:
       result = sgn0 < sgn1;
       break;
-    case GT_EXPR:  case GE_EXPR:
+    case LE_EXPR:
+      result = sgn0 <= sgn1;
+      break;
+    case GT_EXPR:
       result = sgn0 > sgn1;
       break;
+    case GE_EXPR:
+      result = sgn0 >= sgn1;
+      break;
     default:
       abort ();
     }
@@ -2762,7 +3109,8 @@ make_range (exp, pin_p, plow, phigh)
      tree *plow, *phigh;
 {
   enum tree_code code;
-  tree arg0, arg1, type;
+  tree arg0, arg1, type = NULL_TREE;
+  tree orig_type = NULL_TREE;
   int in_p, n_in_p;
   tree low, high, n_low, n_high;
 
@@ -2777,10 +3125,25 @@ make_range (exp, pin_p, plow, phigh)
   while (1)
     {
       code = TREE_CODE (exp);
-      arg0 = TREE_OPERAND (exp, 0), arg1 = TREE_OPERAND (exp, 1);
-      if (TREE_CODE_CLASS (code) == '<' || TREE_CODE_CLASS (code) == '1'
-         || TREE_CODE_CLASS (code) == '2')
-       type = TREE_TYPE (arg0);
+
+      if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
+       {
+         arg0 = TREE_OPERAND (exp, 0);
+         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' 
+             || TREE_CODE_CLASS (code) == '<'
+             || (TREE_CODE_CLASS (code) == 'e' 
+                 && tree_code_length[(int) code] > 1))
+           arg1 = TREE_OPERAND (exp, 1);
+       }
+
+      /* Set ORIG_TYPE as soon as TYPE is non-null so that we do not
+        lose a cast by accident.  */
+      if (type != NULL_TREE && orig_type == NULL_TREE)
+       orig_type = type;
 
       switch (code)
        {
@@ -2900,6 +3263,9 @@ make_range (exp, pin_p, plow, phigh)
          continue;
 
        case NOP_EXPR:  case NON_LVALUE_EXPR:  case CONVERT_EXPR:
+         if (TYPE_PRECISION (type) > TYPE_PRECISION (orig_type))
+           break;
+
          if (! INTEGRAL_TYPE_P (type)
              || (low != 0 && ! int_fits_type_p (low, type))
              || (high != 0 && ! int_fits_type_p (high, type)))
@@ -2922,11 +3288,22 @@ make_range (exp, pin_p, plow, phigh)
          if (TREE_UNSIGNED (type) && ! TREE_UNSIGNED (TREE_TYPE (exp)))
            {
              tree equiv_type = type_for_mode (TYPE_MODE (type), 1);
-             tree high_positive
-               = fold (build (RSHIFT_EXPR, type,
-                              convert (type,
-                                       TYPE_MAX_VALUE (equiv_type)),
-                              convert (type, integer_one_node)));
+             tree high_positive;
+
+             /* A range without an upper bound is, naturally, unbounded.
+                Since convert would have cropped a very large value, use
+                 the max value for the destination type.  */
+
+             high_positive = TYPE_MAX_VALUE (equiv_type);
+             if (!high_positive)
+               {
+                 high_positive = TYPE_MAX_VALUE (type);
+                 if (!high_positive)
+                   abort();
+               }
+             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
@@ -3208,14 +3585,16 @@ fold_range_test (exp)
           && operand_equal_p (lhs, rhs, 0))
     {
       /* If simple enough, just rewrite.  Otherwise, make a SAVE_EXPR
-        unless we are at top level, in which case we can't do this.  */
+        unless we are at top level or LHS contains a PLACEHOLDER_EXPR, in
+        which cases we can't do this.  */
       if (simple_operand_p (lhs))
        return build (TREE_CODE (exp) == TRUTH_ANDIF_EXPR
                      ? TRUTH_AND_EXPR : TRUTH_OR_EXPR,
                      TREE_TYPE (exp), TREE_OPERAND (exp, 0),
                      TREE_OPERAND (exp, 1));
 
-      else if (current_function_decl != 0)
+      else if (current_function_decl != 0
+              && ! contains_placeholder_p (lhs))
        {
          tree common = save_expr (lhs);
 
@@ -3230,8 +3609,8 @@ fold_range_test (exp)
                          TREE_TYPE (exp), lhs, rhs);
        }
     }
-  else
-    return 0;
+
+  return 0;
 }
 \f
 /* Subroutine for fold_truthop: C is an INTEGER_CST interpreted as a P
@@ -3331,7 +3710,7 @@ fold_truthop (code, truth_type, lhs, rhs)
   tree ll_mask, lr_mask, rl_mask, rr_mask;
   tree ll_and_mask, lr_and_mask, rl_and_mask, rr_and_mask;
   tree l_const, r_const;
-  tree type, result;
+  tree lntype, rntype, result;
   int first_bit, end_bit;
   int volatilep;
 
@@ -3469,7 +3848,7 @@ fold_truthop (code, truth_type, lhs, rhs)
 
   lnbitsize = GET_MODE_BITSIZE (lnmode);
   lnbitpos = first_bit & ~ (lnbitsize - 1);
-  type = type_for_size (lnbitsize, 1);
+  lntype = type_for_size (lnbitsize, 1);
   xll_bitpos = ll_bitpos - lnbitpos, xrl_bitpos = rl_bitpos - lnbitpos;
 
   if (BYTES_BIG_ENDIAN)
@@ -3478,23 +3857,22 @@ fold_truthop (code, truth_type, lhs, rhs)
       xrl_bitpos = lnbitsize - xrl_bitpos - rl_bitsize;
     }
 
-  ll_mask = const_binop (LSHIFT_EXPR, convert (type, ll_mask),
+  ll_mask = const_binop (LSHIFT_EXPR, convert (lntype, ll_mask),
                         size_int (xll_bitpos), 0);
-  rl_mask = const_binop (LSHIFT_EXPR, convert (type, rl_mask),
+  rl_mask = const_binop (LSHIFT_EXPR, convert (lntype, rl_mask),
                         size_int (xrl_bitpos), 0);
 
   if (l_const)
     {
-      l_const = convert (type, l_const);
+      l_const = convert (lntype, l_const);
       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,
-                                                     type, ll_mask)),
+                                                     lntype, ll_mask)),
                                        0)))
        {
-         warning ("comparison is always %s",
-                  wanted_code == NE_EXPR ? "one" : "zero");
+         warning ("comparison is always %d", wanted_code == NE_EXPR);
          
          return convert (truth_type,
                          wanted_code == NE_EXPR
@@ -3503,17 +3881,16 @@ fold_truthop (code, truth_type, lhs, rhs)
     }
   if (r_const)
     {
-      r_const = convert (type, r_const);
+      r_const = convert (lntype, r_const);
       r_const = unextend (r_const, rl_bitsize, rl_unsignedp, rl_and_mask);
       r_const = const_binop (LSHIFT_EXPR, r_const, size_int (xrl_bitpos), 0);
       if (! integer_zerop (const_binop (BIT_AND_EXPR, r_const,
                                        fold (build1 (BIT_NOT_EXPR,
-                                                     type, rl_mask)),
+                                                     lntype, rl_mask)),
                                        0)))
        {
-         warning ("comparison is always %s",
-                  wanted_code == NE_EXPR ? "one" : "zero");
-         
+         warning ("comparison is always %d", wanted_code == NE_EXPR);
+
          return convert (truth_type,
                          wanted_code == NE_EXPR
                          ? integer_one_node : integer_zero_node);
@@ -3542,6 +3919,7 @@ fold_truthop (code, truth_type, lhs, rhs)
 
       rnbitsize = GET_MODE_BITSIZE (rnmode);
       rnbitpos = first_bit & ~ (rnbitsize - 1);
+      rntype = type_for_size (rnbitsize, 1);
       xlr_bitpos = lr_bitpos - rnbitpos, xrr_bitpos = rr_bitpos - rnbitpos;
 
       if (BYTES_BIG_ENDIAN)
@@ -3550,47 +3928,83 @@ fold_truthop (code, truth_type, lhs, rhs)
          xrr_bitpos = rnbitsize - xrr_bitpos - rr_bitsize;
        }
 
-      lr_mask = const_binop (LSHIFT_EXPR, convert (type, lr_mask),
+      lr_mask = const_binop (LSHIFT_EXPR, convert (rntype, lr_mask),
                             size_int (xlr_bitpos), 0);
-      rr_mask = const_binop (LSHIFT_EXPR, convert (type, rr_mask),
+      rr_mask = const_binop (LSHIFT_EXPR, convert (rntype, rr_mask),
                             size_int (xrr_bitpos), 0);
 
       /* Make a mask that corresponds to both fields being compared.
-        Do this for both items being compared.  If the masks agree,
-        we can do this by masking both and comparing the masked
+        Do this for both items being compared.  If the operands are the
+        same size and the bits being compared are in the same position
+        then we can do this by masking both and comparing the masked
         results.  */
       ll_mask = const_binop (BIT_IOR_EXPR, ll_mask, rl_mask, 0);
       lr_mask = const_binop (BIT_IOR_EXPR, lr_mask, rr_mask, 0);
-      if (operand_equal_p (ll_mask, lr_mask, 0) && lnbitsize == rnbitsize)
+      if (lnbitsize == rnbitsize && xll_bitpos == xlr_bitpos)
        {
-         lhs = make_bit_field_ref (ll_inner, type, lnbitsize, lnbitpos,
+         lhs = make_bit_field_ref (ll_inner, lntype, lnbitsize, lnbitpos,
                                    ll_unsignedp || rl_unsignedp);
-         rhs = make_bit_field_ref (lr_inner, type, rnbitsize, rnbitpos,
-                                   lr_unsignedp || rr_unsignedp);
          if (! all_ones_mask_p (ll_mask, lnbitsize))
-           {
-             lhs = build (BIT_AND_EXPR, type, lhs, ll_mask);
-             rhs = build (BIT_AND_EXPR, type, rhs, ll_mask);
-           }
+           lhs = build (BIT_AND_EXPR, lntype, lhs, ll_mask);
+
+         rhs = make_bit_field_ref (lr_inner, rntype, rnbitsize, rnbitpos,
+                                   lr_unsignedp || rr_unsignedp);
+         if (! all_ones_mask_p (lr_mask, rnbitsize))
+           rhs = build (BIT_AND_EXPR, rntype, rhs, lr_mask);
+
          return build (wanted_code, truth_type, lhs, rhs);
        }
 
       /* There is still another way we can do something:  If both pairs of
         fields being compared are adjacent, we may be able to make a wider
-        field containing them both.  */
+        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 
+        make_bit_field_ref.  */
       if ((ll_bitsize + ll_bitpos == rl_bitpos
           && lr_bitsize + lr_bitpos == rr_bitpos)
          || (ll_bitpos == rl_bitpos + rl_bitsize
              && lr_bitpos == rr_bitpos + rr_bitsize))
-       return build (wanted_code, truth_type,
-                     make_bit_field_ref (ll_inner, type,
-                                         ll_bitsize + rl_bitsize,
-                                         MIN (ll_bitpos, rl_bitpos),
-                                         ll_unsignedp),
-                     make_bit_field_ref (lr_inner, type,
-                                         lr_bitsize + rr_bitsize,
-                                         MIN (lr_bitpos, rr_bitpos),
-                                         lr_unsignedp));
+       {
+         tree type;
+
+         lhs = make_bit_field_ref (ll_inner, lntype, ll_bitsize + rl_bitsize,
+                                   MIN (ll_bitpos, rl_bitpos), ll_unsignedp);
+         rhs = make_bit_field_ref (lr_inner, rntype, lr_bitsize + rr_bitsize,
+                                   MIN (lr_bitpos, rr_bitpos), lr_unsignedp);
+
+         ll_mask = const_binop (RSHIFT_EXPR, ll_mask,
+                                size_int (MIN (xll_bitpos, xrl_bitpos)), 0);
+         lr_mask = const_binop (RSHIFT_EXPR, lr_mask,
+                                size_int (MIN (xlr_bitpos, xrr_bitpos)), 0);
+
+         /* Convert to the smaller type before masking out unwanted bits.  */
+         type = lntype;
+         if (lntype != rntype)
+           {
+             if (lnbitsize > rnbitsize)
+               {
+                 lhs = convert (rntype, lhs);
+                 ll_mask = convert (rntype, ll_mask);
+                 type = rntype;
+               }
+             else if (lnbitsize < rnbitsize)
+               {
+                 rhs = convert (lntype, rhs);
+                 lr_mask = convert (lntype, lr_mask);
+                 type = lntype;
+               }
+           }
+
+         if (! all_ones_mask_p (ll_mask, ll_bitsize + rl_bitsize))
+           lhs = build (BIT_AND_EXPR, type, lhs, ll_mask);
+
+         if (! all_ones_mask_p (lr_mask, lr_bitsize + rr_bitsize))
+           rhs = build (BIT_AND_EXPR, type, rhs, lr_mask);
+
+         return build (wanted_code, truth_type, lhs, rhs);
+       }
 
       return 0;
     }
@@ -3611,7 +4025,7 @@ fold_truthop (code, truth_type, lhs, rhs)
        }
       else
        {
-         warning ("`and' of mutually exclusive equal-tests is always zero");
+         warning ("`and' of mutually exclusive equal-tests is always 0");
          return convert (truth_type, integer_zero_node);
        }
     }
@@ -3620,12 +4034,12 @@ fold_truthop (code, truth_type, lhs, rhs)
      reference we will make.  Unless the mask is all ones the width of
      that field, perform the mask operation.  Then compare with the
      merged constant.  */
-  result = make_bit_field_ref (ll_inner, type, lnbitsize, lnbitpos,
+  result = make_bit_field_ref (ll_inner, lntype, lnbitsize, lnbitpos,
                               ll_unsignedp || rl_unsignedp);
 
   ll_mask = const_binop (BIT_IOR_EXPR, ll_mask, rl_mask, 0);
   if (! all_ones_mask_p (ll_mask, lnbitsize))
-    result = build (BIT_AND_EXPR, type, result, ll_mask);
+    result = build (BIT_AND_EXPR, lntype, result, ll_mask);
 
   return build (wanted_code, truth_type, result,
                const_binop (BIT_IOR_EXPR, l_const, r_const, 0));
@@ -3640,7 +4054,6 @@ strip_compound_expr (t, s)
      tree t;
      tree s;
 {
-  tree type = TREE_TYPE (t);
   enum tree_code code = TREE_CODE (t);
 
   /* See if this is the COMPOUND_EXPR we want to eliminate.  */
@@ -3668,6 +4081,48 @@ strip_compound_expr (t, s)
   return t;
 }
 \f
+/* Return a node which has the indicated constant VALUE (either 0 or
+   1), and is of the indicated TYPE.  */
+
+static tree
+constant_boolean_node (value, type)
+     int value;
+     tree 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 
+    {
+      tree t = build_int_2 (value, 0);
+      TREE_TYPE (t) = type;
+      return t;
+    }
+}
+
+/* Utility function for the following routine, to see how complex a nesting of
+   COND_EXPRs can be.  EXPR is the expression and LIMIT is a count beyond which
+   we don't care (to avoid spending too much time on complex expressions.).  */
+
+static int
+count_cond (expr, lim)
+     tree expr;
+     int lim;
+{
+  int true, false;
+
+  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);
+}
+\f
 /* 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.
@@ -3684,7 +4139,7 @@ fold (expr)
   tree t1 = NULL_TREE;
   tree tem;
   tree type = TREE_TYPE (expr);
-  register tree arg0, arg1;
+  register tree arg0 = NULL_TREE, arg1 = NULL_TREE;
   register enum tree_code code = TREE_CODE (t);
   register int kind;
   int invert;
@@ -3707,6 +4162,10 @@ fold (expr)
       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)
     {
@@ -3887,9 +4346,14 @@ fold (expr)
       else if ((TREE_CODE (arg1) == COND_EXPR
                || (TREE_CODE_CLASS (TREE_CODE (arg1)) == '<'
                    && TREE_CODE_CLASS (code) != '<'))
-              && (! TREE_SIDE_EFFECTS (arg0) || current_function_decl != 0))
+              && (TREE_CODE (arg0) != COND_EXPR
+                  || count_cond (arg0, 25) + count_cond (arg1, 25) <= 25)
+              && (! TREE_SIDE_EFFECTS (arg0)
+                  || (current_function_decl != 0
+                      && ! contains_placeholder_p (arg0))))
        {
          tree test, true_value, false_value;
+         tree lhs = 0, rhs = 0;
 
          if (TREE_CODE (arg1) == COND_EXPR)
            {
@@ -3912,26 +4376,37 @@ fold (expr)
             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.  */
+            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
+         if (TREE_CODE (arg0) != SAVE_EXPR && ! TREE_CONSTANT (arg0)
+             && current_function_decl != 0
              && ((TREE_CODE (arg0) != VAR_DECL
                   && TREE_CODE (arg0) != PARM_DECL)
                  || TREE_SIDE_EFFECTS (arg0)))
            {
-             tree lhs = fold (build (code, type, arg0, true_value));
-             tree rhs = fold (build (code, type, arg0, false_value));
+             if (TREE_CODE (true_value) != COND_EXPR)
+               lhs = fold (build (code, type, arg0, true_value));
 
-             if (TREE_CONSTANT (lhs) || TREE_CONSTANT (rhs))
-               return fold (build (COND_EXPR, type, test, lhs, rhs));
+             if (TREE_CODE (false_value) != COND_EXPR)
+               rhs = fold (build (code, type, arg0, false_value));
 
-             if (current_function_decl != 0)
-               arg0 = save_expr (arg0);
+             if ((lhs == 0 || ! TREE_CONSTANT (lhs))
+                 && (rhs == 0 || !TREE_CONSTANT (rhs)))
+               arg0 = save_expr (arg0), lhs = rhs = 0;
            }
 
-         test = fold (build (COND_EXPR, type, test,
-                             fold (build (code, type, arg0, true_value)),
-                             fold (build (code, type, arg0, false_value))));
+         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),
@@ -3946,9 +4421,14 @@ fold (expr)
       else if ((TREE_CODE (arg0) == COND_EXPR
                || (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
                    && TREE_CODE_CLASS (code) != '<'))
-              && (! TREE_SIDE_EFFECTS (arg1) || current_function_decl != 0))
+              && (TREE_CODE (arg1) != COND_EXPR
+                  || count_cond (arg0, 25) + count_cond (arg1, 25) <= 25)
+              && (! TREE_SIDE_EFFECTS (arg1)
+                  || (current_function_decl != 0
+                      && ! contains_placeholder_p (arg1))))
        {
          tree test, true_value, false_value;
+         tree lhs = 0, rhs = 0;
 
          if (TREE_CODE (arg0) == COND_EXPR)
            {
@@ -3964,25 +4444,30 @@ fold (expr)
              false_value = convert (testtype, integer_zero_node);
            }
 
-         if (TREE_CODE (arg1) != SAVE_EXPR
+         if (TREE_CODE (arg1) != SAVE_EXPR && ! TREE_CONSTANT (arg0)
+             && current_function_decl != 0
              && ((TREE_CODE (arg1) != VAR_DECL
                   && TREE_CODE (arg1) != PARM_DECL)
                  || TREE_SIDE_EFFECTS (arg1)))
            {
-             tree lhs = fold (build (code, type, true_value, arg1));
-             tree rhs = fold (build (code, type, false_value, arg1));
+             if (TREE_CODE (true_value) != COND_EXPR)
+               lhs = fold (build (code, type, true_value, arg1));
 
-             if (TREE_CONSTANT (lhs) || TREE_CONSTANT (rhs)
-                 || TREE_CONSTANT (arg1))
-               return fold (build (COND_EXPR, type, test, lhs, rhs));
+             if (TREE_CODE (false_value) != COND_EXPR)
+               rhs = fold (build (code, type, false_value, arg1));
 
-             if (current_function_decl != 0)
-               arg1 = save_expr (arg1);
+             if ((lhs == 0 || ! TREE_CONSTANT (lhs))
+                 && (rhs == 0 || !TREE_CONSTANT (rhs)))
+               arg1 = save_expr (arg1), lhs = rhs = 0;
            }
 
-         test = fold (build (COND_EXPR, type, test,
-                             fold (build (code, type, true_value, arg1)),
-                             fold (build (code, type, false_value, arg1))));
+         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),
@@ -4068,6 +4553,13 @@ fold (expr)
              && ! final_ptr)
            return convert (final_type, TREE_OPERAND (TREE_OPERAND (t, 0), 0));
 
+         /* If we have a sign-extension of a zero-extended value, we can
+            replace that by a single zero-extension.  */
+         if (inside_int && inter_int && final_int
+             && inside_prec < inter_prec && inter_prec < final_prec
+             && inside_unsignedp && !inter_unsignedp)
+           return convert (final_type, TREE_OPERAND (TREE_OPERAND (t, 0), 0));
+
          /* Two conversions in a row are not needed unless:
             - some conversion is floating-point (overstrict for now), or
             - the intermediate type is narrower than both initial and
@@ -4272,18 +4764,36 @@ fold (expr)
              goto bit_ior;
            }
 
-         /* (A * C) + (B * C) -> (A+B) * C.  Since we are most concerned
-            about the case where C is a constant, just try one of the
-            four possibilities.  */
-
-         if (TREE_CODE (arg0) == MULT_EXPR && TREE_CODE (arg1) == MULT_EXPR
-             && operand_equal_p (TREE_OPERAND (arg0, 1),
-                                 TREE_OPERAND (arg1, 1), 0))
-           return fold (build (MULT_EXPR, type,
-                               fold (build (PLUS_EXPR, type,
-                                            TREE_OPERAND (arg0, 0),
-                                            TREE_OPERAND (arg1, 0))),
-                               TREE_OPERAND (arg0, 1)));
+         if (TREE_CODE (arg0) == MULT_EXPR && TREE_CODE (arg1) == MULT_EXPR)
+           {
+             tree arg00, arg01, arg10, arg11;
+             tree alt0, alt1, same;
+
+             /* (A * C) + (B * C) -> (A+B) * C.
+                We are most concerned about the case where C is a constant,
+                but other combinations show up during loop reduction.  Since
+                it is not difficult, try all four possibilities.  */
+
+             arg00 = TREE_OPERAND (arg0, 0);
+             arg01 = TREE_OPERAND (arg0, 1);
+             arg10 = TREE_OPERAND (arg1, 0);
+             arg11 = TREE_OPERAND (arg1, 1);
+             same = NULL_TREE;
+
+             if (operand_equal_p (arg01, arg11, 0))
+               same = arg01, alt0 = arg00, alt1 = arg10;
+             else if (operand_equal_p (arg00, arg10, 0))
+               same = arg00, alt0 = arg01, alt1 = arg11;
+             else if (operand_equal_p (arg00, arg11, 0))
+               same = arg00, alt0 = arg01, alt1 = arg10;
+             else if (operand_equal_p (arg01, arg10, 0))
+               same = arg01, alt0 = arg00, alt1 = arg11;
+
+             if (same)
+               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
@@ -4498,7 +5008,8 @@ fold (expr)
          if (real_onep (arg1))
            return non_lvalue (convert (type, arg0));
          /* x*2 is x+x */
-         if (! wins && real_twop (arg1) && current_function_decl != 0)
+         if (! wins && real_twop (arg1) && current_function_decl != 0
+             && ! contains_placeholder_p (arg0))
            {
              tree arg = save_expr (arg0);
              return build (PLUS_EXPR, type, arg, arg);
@@ -4536,6 +5047,8 @@ fold (expr)
 
          tree01 = TREE_OPERAND (arg0, 1);
          tree11 = TREE_OPERAND (arg1, 1);
+         STRIP_NOPS (tree01);
+         STRIP_NOPS (tree11);
          code01 = TREE_CODE (tree01);
          code11 = TREE_CODE (tree11);
          if (code01 == INTEGER_CST
@@ -4546,22 +5059,40 @@ fold (expr)
              == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))))
            return build (LROTATE_EXPR, type, TREE_OPERAND (arg0, 0),
                      code0 == LSHIFT_EXPR ? tree01 : tree11);
-         else if (code11 == MINUS_EXPR
-               && TREE_CODE (TREE_OPERAND (tree11, 0)) == INTEGER_CST
-               && TREE_INT_CST_HIGH (TREE_OPERAND (tree11, 0)) == 0
-               && TREE_INT_CST_LOW (TREE_OPERAND (tree11, 0))
-                 == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))
-               && operand_equal_p (tree01, TREE_OPERAND (tree11, 1), 0))
-           return build (code0 == LSHIFT_EXPR ? LROTATE_EXPR : RROTATE_EXPR,
-                       type, TREE_OPERAND (arg0, 0), tree01);
-         else if (code01 == MINUS_EXPR
-               && TREE_CODE (TREE_OPERAND (tree01, 0)) == INTEGER_CST
-               && TREE_INT_CST_HIGH (TREE_OPERAND (tree01, 0)) == 0
-               && TREE_INT_CST_LOW (TREE_OPERAND (tree01, 0))
-                 == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))
-               && operand_equal_p (tree11, TREE_OPERAND (tree01, 1), 0))
-           return build (code0 != LSHIFT_EXPR ? LROTATE_EXPR : RROTATE_EXPR,
-                       type, TREE_OPERAND (arg0, 0), 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))))
+                 && operand_equal_p (tree01, tree111, 0))
+               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))))
+                 && operand_equal_p (tree11, tree011, 0))
+               return build ((code0 != LSHIFT_EXPR 
+                              ? LROTATE_EXPR 
+                              : RROTATE_EXPR),
+                              type, TREE_OPERAND (arg0, 0), tree11);
+           }
        }
 
       goto associate;
@@ -4914,6 +5445,7 @@ fold (expr)
       if (operand_equal_p (arg0, arg1, 0))
        return arg0;
       if (INTEGRAL_TYPE_P (type)
+         && TYPE_MAX_VALUE (type)
          && operand_equal_p (arg1, TYPE_MAX_VALUE (type), 1))
        return omit_one_operand (type, arg1, arg0);
       goto associate;
@@ -5073,7 +5605,7 @@ fold (expr)
         First, see if one arg is constant; find the constant arg
         and the other one.  */
       {
-       tree constop = 0, varop;
+       tree constop = 0, varop = NULL_TREE;
        int constopnum = -1;
 
        if (TREE_CONSTANT (arg1))
@@ -5087,7 +5619,7 @@ fold (expr)
               if CONST+INCR overflows or if foo+incr might overflow.
               This optimization is invalid for floating point due to rounding.
               For pointer types we assume overflow doesn't happen.  */
-           if (TREE_CODE (TREE_TYPE (varop)) == POINTER_TYPE
+           if (POINTER_TYPE_P (TREE_TYPE (varop))
                || (! FLOAT_TYPE_P (TREE_TYPE (varop))
                    && (code == EQ_EXPR || code == NE_EXPR)))
              {
@@ -5106,11 +5638,35 @@ fold (expr)
                      = TREE_INT_CST_LOW (DECL_SIZE
                                          (TREE_OPERAND
                                           (TREE_OPERAND (varop, 0), 1)));
-
+                   tree mask, unsigned_type;
+                   int precision;
+                   tree folded_compare;
+
+                   /* First check whether the comparison would come out
+                      always the same.  If we don't do that we would
+                      change the meaning with the masking.  */
+                   if (constopnum == 0)
+                     folded_compare = fold (build (code, type, constop,
+                                                   TREE_OPERAND (varop, 0)));
+                   else
+                     folded_compare = fold (build (code, type,
+                                                   TREE_OPERAND (varop, 0),
+                                                   constop));
+                   if (integer_zerop (folded_compare)
+                       || integer_onep (folded_compare))
+                     return omit_one_operand (type, folded_compare, varop);
+
+                   unsigned_type = type_for_size (size, 1);
+                   precision = TYPE_PRECISION (unsigned_type);
+                   mask = build_int_2 (~0, ~0);
+                   TREE_TYPE (mask) = unsigned_type;
+                   force_fit_type (mask, 0);
+                   mask = const_binop (RSHIFT_EXPR, mask,
+                                       size_int (precision - size), 0);
                    newconst = fold (build (BIT_AND_EXPR,
                                            TREE_TYPE (varop), newconst,
                                            convert (TREE_TYPE (varop),
-                                                    build_int_2 (size, 0))));
+                                                    mask)));
                  }
                                                         
 
@@ -5122,7 +5678,7 @@ fold (expr)
          }
        else if (constop && TREE_CODE (varop) == POSTDECREMENT_EXPR)
          {
-           if (TREE_CODE (TREE_TYPE (varop)) == POINTER_TYPE
+           if (POINTER_TYPE_P (TREE_TYPE (varop))
                || (! FLOAT_TYPE_P (TREE_TYPE (varop))
                    && (code == EQ_EXPR || code == NE_EXPR)))
              {
@@ -5139,11 +5695,32 @@ fold (expr)
                      = TREE_INT_CST_LOW (DECL_SIZE
                                          (TREE_OPERAND
                                           (TREE_OPERAND (varop, 0), 1)));
-
+                   tree mask, unsigned_type;
+                   int precision;
+                   tree folded_compare;
+
+                   if (constopnum == 0)
+                     folded_compare = fold (build (code, type, constop,
+                                                   TREE_OPERAND (varop, 0)));
+                   else
+                     folded_compare = fold (build (code, type,
+                                                   TREE_OPERAND (varop, 0),
+                                                   constop));
+                   if (integer_zerop (folded_compare)
+                       || integer_onep (folded_compare))
+                     return omit_one_operand (type, folded_compare, varop);
+
+                   unsigned_type = type_for_size (size, 1);
+                   precision = TYPE_PRECISION (unsigned_type);
+                   mask = build_int_2 (~0, ~0);
+                   TREE_TYPE (mask) = TREE_TYPE (varop);
+                   force_fit_type (mask, 0);
+                   mask = const_binop (RSHIFT_EXPR, mask,
+                                       size_int (precision - size), 0);
                    newconst = fold (build (BIT_AND_EXPR,
                                            TREE_TYPE (varop), newconst,
                                            convert (TREE_TYPE (varop),
-                                                    build_int_2 (size, 0))));
+                                                    mask)));
                  }
                                                         
 
@@ -5283,14 +5860,7 @@ fold (expr)
            case GE_EXPR:
            case LE_EXPR:
              if (INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
-               {
-                 if (type == integer_type_node)
-                   return integer_one_node;
-
-                 t = build_int_2 (1, 0);
-                 TREE_TYPE (t) = type;
-                 return t;
-               }
+               return constant_boolean_node (1, type);
              code = EQ_EXPR;
              TREE_SET_CODE (t, code);
              break;
@@ -5302,12 +5872,7 @@ fold (expr)
              /* ... fall through ...  */
            case GT_EXPR:
            case LT_EXPR:
-             if (type == integer_type_node)
-               return integer_zero_node;
-
-             t = build_int_2 (0, 0);
-             TREE_TYPE (t) = type;
-             return t;
+             return constant_boolean_node (0, type);
            default:
              abort ();
            }
@@ -5316,7 +5881,7 @@ fold (expr)
       /* An unsigned comparison against 0 can be simplified.  */
       if (integer_zerop (arg1)
          && (INTEGRAL_TYPE_P (TREE_TYPE (arg1))
-             || TREE_CODE (TREE_TYPE (arg1)) == POINTER_TYPE)
+             || POINTER_TYPE_P (TREE_TYPE (arg1)))
          && TREE_UNSIGNED (TREE_TYPE (arg1)))
        {
          switch (TREE_CODE (t))
@@ -5351,7 +5916,7 @@ fold (expr)
            && TREE_INT_CST_LOW (arg1) == ((HOST_WIDE_INT) 1 << (width - 1)) - 1
            && TREE_INT_CST_HIGH (arg1) == 0
            && (INTEGRAL_TYPE_P (TREE_TYPE (arg1))
-               || TREE_CODE (TREE_TYPE (arg1)) == POINTER_TYPE)
+               || POINTER_TYPE_P (TREE_TYPE (arg1)))
            && TREE_UNSIGNED (TREE_TYPE (arg1)))
          {
            switch (TREE_CODE (t))
@@ -5368,6 +5933,8 @@ fold (expr)
                                             arg0),
                                    convert (signed_type (TREE_TYPE (arg1)),
                                             integer_zero_node)));
+             default:
+               break;
              }
          }
       }
@@ -5397,6 +5964,8 @@ fold (expr)
              && ! (TREE_CONSTANT (cval1) && TREE_CONSTANT (cval2))
              && TREE_TYPE (cval1) == TREE_TYPE (cval2)
              && INTEGRAL_TYPE_P (TREE_TYPE (cval1))
+             && TYPE_MAX_VALUE (TREE_TYPE (cval1))
+             && TYPE_MAX_VALUE (TREE_TYPE (cval2))
              && ! operand_equal_p (TYPE_MIN_VALUE (TREE_TYPE (cval1)),
                                    TYPE_MAX_VALUE (TREE_TYPE (cval2)), 0))
            {
@@ -5483,20 +6052,26 @@ fold (expr)
          return t1 ? t1 : t;
        }
 
-      /* If this is a comparison of complex values and either or both
-        sizes are a COMPLEX_EXPR, it is best to split up the comparisons
-        and join them with a TRUTH_ANDIF_EXPR or TRUTH_ORIF_EXPR.  This
-        may prevent needless evaluations.  */
+      /* If this is a comparison of complex values and either or both sides
+        are a COMPLEX_EXPR or COMPLEX_CST, it is best to split up the
+        comparisons and join them with a TRUTH_ANDIF_EXPR or TRUTH_ORIF_EXPR.
+        This may prevent needless evaluations.  */
       if ((code == EQ_EXPR || code == NE_EXPR)
          && TREE_CODE (TREE_TYPE (arg0)) == COMPLEX_TYPE
          && (TREE_CODE (arg0) == COMPLEX_EXPR
-             || TREE_CODE (arg1) == COMPLEX_EXPR))
+             || TREE_CODE (arg1) == COMPLEX_EXPR
+             || TREE_CODE (arg0) == COMPLEX_CST
+             || TREE_CODE (arg1) == COMPLEX_CST))
        {
          tree subtype = TREE_TYPE (TREE_TYPE (arg0));
-         tree real0 = fold (build1 (REALPART_EXPR, subtype, arg0));
-         tree imag0 = fold (build1 (IMAGPART_EXPR, subtype, arg0));
-         tree real1 = fold (build1 (REALPART_EXPR, subtype, arg1));
-         tree imag1 = fold (build1 (IMAGPART_EXPR, subtype, arg1));
+         tree real0, imag0, real1, imag1;
+
+         arg0 = save_expr (arg0);
+         arg1 = save_expr (arg1);
+         real0 = fold (build1 (REALPART_EXPR, subtype, arg0));
+         imag0 = fold (build1 (IMAGPART_EXPR, subtype, arg0));
+         real1 = fold (build1 (REALPART_EXPR, subtype, arg1));
+         imag1 = fold (build1 (IMAGPART_EXPR, subtype, arg1));
 
          return fold (build ((code == EQ_EXPR ? TRUTH_ANDIF_EXPR
                               : TRUTH_ORIF_EXPR),
@@ -5591,6 +6166,8 @@ fold (expr)
        TREE_INT_CST_LOW (t1) ^= 1;
 
       TREE_TYPE (t1) = type;
+      if (TREE_CODE (type) == BOOLEAN_TYPE)
+       return truthvalue_conversion (t1);
       return t1;
 
     case COND_EXPR:
@@ -5624,7 +6201,8 @@ fold (expr)
              t = build (code, type, tem,
                         TREE_OPERAND (t, 2), TREE_OPERAND (t, 1));
              arg0 = tem;
-             arg1 = TREE_OPERAND (t, 2);
+             /* arg1 should be the first argument of the new T.  */
+             arg1 = TREE_OPERAND (t, 1);
              STRIP_NOPS (arg1);
            }
        }
@@ -5662,11 +6240,15 @@ fold (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);
                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);
                return pedantic_non_lvalue
                  (fold (build1 (NEGATE_EXPR, type,
                                 convert (type,
@@ -5813,7 +6395,8 @@ fold (expr)
              t = build (code, type, tem,
                         TREE_OPERAND (t, 2), TREE_OPERAND (t, 1));
              arg0 = tem;
-             arg1 = TREE_OPERAND (t, 2);
+             /* arg1 should be the first argument of the new T.  */
+             arg1 = TREE_OPERAND (t, 1);
              STRIP_NOPS (arg1);
            }
        }
@@ -5849,7 +6432,7 @@ fold (expr)
        return t;
       /* Don't let (0, 0) be null pointer constant.  */
       if (integer_zerop (arg1))
-       return non_lvalue (arg1);
+       return build1 (NOP_EXPR, TREE_TYPE (arg1), arg1);
       return arg1;
 
     case COMPLEX_EXPR:
@@ -5892,7 +6475,7 @@ fold (expr)
       /* Pull arithmetic ops out of the CLEANUP_POINT_EXPR where
          appropriate.  */
     case CLEANUP_POINT_EXPR:
-      if (! TREE_SIDE_EFFECTS (arg0))
+      if (! has_cleanups (arg0))
        return TREE_OPERAND (t, 0);
 
       {
@@ -5913,12 +6496,14 @@ fold (expr)
          {
            arg01 = TREE_OPERAND (arg0, 1);
 
-           if (! TREE_SIDE_EFFECTS (arg00))
+           if (TREE_CONSTANT (arg00)
+               || ((code0 == TRUTH_ANDIF_EXPR || code0 == TRUTH_ORIF_EXPR)
+                   && ! has_cleanups (arg00)))
              return fold (build (code0, type, arg00,
                                  fold (build1 (CLEANUP_POINT_EXPR,
                                                TREE_TYPE (arg01), arg01))));
 
-           if (! TREE_SIDE_EFFECTS (arg01))
+           if (TREE_CONSTANT (arg01))
              return fold (build (code0, type,
                                  fold (build1 (CLEANUP_POINT_EXPR,
                                                TREE_TYPE (arg00), arg00)),