OSDN Git Service

* config/mips/t-iris6 (CRTSTUFF_T_CFLAGS): Add -Wno-error.
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index 7ef2b22..3787915 100644 (file)
@@ -56,9 +56,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "ggc.h"
 #include "hashtab.h"
 #include "langhooks.h"
+#include "md5.h"
 
 static void encode (HOST_WIDE_INT *, unsigned HOST_WIDE_INT, HOST_WIDE_INT);
 static void decode (HOST_WIDE_INT *, unsigned HOST_WIDE_INT *, HOST_WIDE_INT *);
+static bool negate_mathfn_p (enum built_in_function);
 static bool negate_expr_p (tree);
 static tree negate_expr (tree);
 static tree split_tree (tree, enum tree_code, tree *, tree *, tree *, int);
@@ -107,6 +109,8 @@ static bool fold_real_zero_addition_p (tree, tree, int);
 static tree fold_mathfn_compare (enum built_in_function, enum tree_code,
                                 tree, tree, tree);
 static tree fold_inf_compare (enum tree_code, tree, tree, tree);
+static bool reorder_operands_p (tree, tree);
+static bool tree_swap_operands_p (tree, tree, bool);
 
 /* The following constants represent a bit based encoding of GCC's
    comparison operators.  This encoding simplifies transformations
@@ -193,7 +197,8 @@ force_fit_type (tree t, int overflow)
   low = TREE_INT_CST_LOW (t);
   high = TREE_INT_CST_HIGH (t);
 
-  if (POINTER_TYPE_P (TREE_TYPE (t)))
+  if (POINTER_TYPE_P (TREE_TYPE (t))
+      || TREE_CODE (TREE_TYPE (t)) == OFFSET_TYPE)
     prec = POINTER_SIZE;
   else
     prec = TYPE_PRECISION (TREE_TYPE (t));
@@ -313,7 +318,7 @@ mul_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
   encode (arg1, l1, h1);
   encode (arg2, l2, h2);
 
-  memset ((char *) prod, 0, sizeof prod);
+  memset (prod, 0, sizeof prod);
 
   for (i = 0; i < 4; i++)
     {
@@ -556,7 +561,7 @@ div_and_round_double (enum tree_code code, int uns,
   if (hden == 0 && lden == 0)
     overflow = 1, lden = 1;
 
-  /* calculate quotient sign and convert operands to unsigned.  */
+  /* Calculate quotient sign and convert operands to unsigned.  */
   if (!uns)
     {
       if (hnum < 0)
@@ -591,10 +596,10 @@ div_and_round_double (enum tree_code code, int uns,
       goto finish_up;
     }
 
-  memset ((char *) quo, 0, sizeof quo);
+  memset (quo, 0, sizeof quo);
 
-  memset ((char *) num, 0, sizeof num);        /* to zero 9th element */
-  memset ((char *) den, 0, sizeof den);
+  memset (num, 0, sizeof num); /* to zero 9th element */
+  memset (den, 0, sizeof den);
 
   encode (num, lnum, hnum);
   encode (den, lden, hden);
@@ -712,7 +717,7 @@ div_and_round_double (enum tree_code code, int uns,
   decode (quo, lquo, hquo);
 
  finish_up:
-  /* if result is negative, make it so.  */
+  /* If result is negative, make it so.  */
   if (quo_neg)
     neg_double (*lquo, *hquo, lquo, hquo);
 
@@ -800,6 +805,35 @@ div_and_round_double (enum tree_code code, int uns,
   return overflow;
 }
 \f
+/* Return true if built-in mathematical function specified by CODE
+   preserves the sign of it argument, i.e. -f(x) == f(-x).  */
+
+static bool
+negate_mathfn_p (enum built_in_function code)
+{
+  switch (code)
+    {
+    case BUILT_IN_ASIN:
+    case BUILT_IN_ASINF:
+    case BUILT_IN_ASINL:
+    case BUILT_IN_ATAN:
+    case BUILT_IN_ATANF:
+    case BUILT_IN_ATANL:
+    case BUILT_IN_SIN:
+    case BUILT_IN_SINF:
+    case BUILT_IN_SINL:
+    case BUILT_IN_TAN:
+    case BUILT_IN_TANF:
+    case BUILT_IN_TANL:
+      return true;
+
+    default:
+      break;
+    }
+  return false;
+}
+
+
 /* Determine whether an expression T can be cheaply negated using
    the function negate_expr.  */
 
@@ -819,8 +853,8 @@ negate_expr_p (tree t)
   switch (TREE_CODE (t))
     {
     case INTEGER_CST:
-      if (TREE_UNSIGNED (type))
-       return false;
+      if (TREE_UNSIGNED (type) || ! flag_trapv)
+       return true;
 
       /* Check that -CST will not overflow type.  */
       prec = TYPE_PRECISION (type);
@@ -839,9 +873,46 @@ negate_expr_p (tree t)
 
     case REAL_CST:
     case NEGATE_EXPR:
-    case MINUS_EXPR:
       return true;
 
+    case COMPLEX_CST:
+      return negate_expr_p (TREE_REALPART (t))
+            && negate_expr_p (TREE_IMAGPART (t));
+
+    case MINUS_EXPR:
+      /* We can't turn -(A-B) into B-A when we honor signed zeros.  */
+      return (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
+            && reorder_operands_p (TREE_OPERAND (t, 0),
+                                   TREE_OPERAND (t, 1));
+
+    case MULT_EXPR:
+      if (TREE_UNSIGNED (TREE_TYPE (t)))
+        break;
+
+      /* Fall through.  */
+
+    case RDIV_EXPR:
+      if (! HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (TREE_TYPE (t))))
+       return negate_expr_p (TREE_OPERAND (t, 1))
+              || negate_expr_p (TREE_OPERAND (t, 0));
+      break;
+
+    case NOP_EXPR:
+      /* Negate -((double)float) as (double)(-float).  */
+      if (TREE_CODE (type) == REAL_TYPE)
+       {
+         tree tem = strip_float_extensions (t);
+         if (tem != t)
+           return negate_expr_p (tem);
+       }
+      break;
+
+    case CALL_EXPR:
+      /* Negate -f(x) as f(-x).  */
+      if (negate_mathfn_p (builtin_mathfn_code (t)))
+       return negate_expr_p (TREE_VALUE (TREE_OPERAND (t, 1)));
+      break;
+
     default:
       break;
     }
@@ -866,25 +937,107 @@ negate_expr (tree t)
   switch (TREE_CODE (t))
     {
     case INTEGER_CST:
-    case REAL_CST:
-      if (! TREE_UNSIGNED (type)
-         && 0 != (tem = fold (build1 (NEGATE_EXPR, type, t)))
-         && ! TREE_OVERFLOW (tem))
+      {
+       unsigned HOST_WIDE_INT low;
+       HOST_WIDE_INT high;
+       int overflow = neg_double (TREE_INT_CST_LOW (t),
+                                  TREE_INT_CST_HIGH (t),
+                                  &low, &high);
+       tem = build_int_2 (low, high);
+       TREE_TYPE (tem) = type;
+       TREE_OVERFLOW (tem)
+         = (TREE_OVERFLOW (t)
+            | force_fit_type (tem, overflow && !TREE_UNSIGNED (type)));
+       TREE_CONSTANT_OVERFLOW (tem)
+         = TREE_OVERFLOW (tem) | TREE_CONSTANT_OVERFLOW (t);
+      }
+      if (! TREE_OVERFLOW (tem)
+         || TREE_UNSIGNED (type)
+         || ! flag_trapv)
        return tem;
       break;
 
+    case REAL_CST:
+      tem = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (t)));
+      /* Two's complement FP formats, such as c4x, may overflow.  */
+      if (! TREE_OVERFLOW (tem) || ! flag_trapping_math)
+       return convert (type, tem);
+      break;
+
+    case COMPLEX_CST:
+      {
+       tree rpart = negate_expr (TREE_REALPART (t));
+       tree ipart = negate_expr (TREE_IMAGPART (t));
+
+       if ((TREE_CODE (rpart) == REAL_CST
+            && TREE_CODE (ipart) == REAL_CST)
+           || (TREE_CODE (rpart) == INTEGER_CST
+               && TREE_CODE (ipart) == INTEGER_CST))
+         return build_complex (type, rpart, ipart);
+      }
+      break;
+
     case NEGATE_EXPR:
       return convert (type, TREE_OPERAND (t, 0));
 
     case MINUS_EXPR:
       /* - (A - B) -> B - A  */
-      if (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
+      if ((! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
+         && reorder_operands_p (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1)))
        return convert (type,
                        fold (build (MINUS_EXPR, TREE_TYPE (t),
                                     TREE_OPERAND (t, 1),
                                     TREE_OPERAND (t, 0))));
       break;
 
+    case MULT_EXPR:
+      if (TREE_UNSIGNED (TREE_TYPE (t)))
+        break;
+
+      /* Fall through.  */
+
+    case RDIV_EXPR:
+      if (! HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (TREE_TYPE (t))))
+       {
+         tem = TREE_OPERAND (t, 1);
+         if (negate_expr_p (tem))
+           return convert (type,
+                           fold (build (TREE_CODE (t), TREE_TYPE (t),
+                                        TREE_OPERAND (t, 0),
+                                        negate_expr (tem))));
+         tem = TREE_OPERAND (t, 0);
+         if (negate_expr_p (tem))
+           return convert (type,
+                           fold (build (TREE_CODE (t), TREE_TYPE (t),
+                                        negate_expr (tem),
+                                        TREE_OPERAND (t, 1))));
+       }
+      break;
+
+    case NOP_EXPR:
+      /* Convert -((double)float) into (double)(-float).  */
+      if (TREE_CODE (type) == REAL_TYPE)
+       {
+         tem = strip_float_extensions (t);
+         if (tem != t && negate_expr_p (tem))
+           return convert (type, negate_expr (tem));
+       }
+      break;
+
+    case CALL_EXPR:
+      /* Negate -f(x) as f(-x).  */
+      if (negate_mathfn_p (builtin_mathfn_code (t))
+         && negate_expr_p (TREE_VALUE (TREE_OPERAND (t, 1))))
+       {
+         tree fndecl, arg, arglist;
+
+         fndecl = get_callee_fndecl (t);
+         arg = negate_expr (TREE_VALUE (TREE_OPERAND (t, 1)));
+         arglist = build_tree_list (NULL_TREE, arg);
+         return build_function_call_expr (fndecl, arglist);
+       }
+      break;
+
     default:
       break;
     }
@@ -1061,10 +1214,6 @@ int_const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
       low = int1l & int2l, hi = int1h & int2h;
       break;
 
-    case BIT_ANDTC_EXPR:
-      low = int1l & ~int2l, hi = int1h & ~int2h;
-      break;
-
     case RSHIFT_EXPR:
       int2l = -int2l;
     case LSHIFT_EXPR:
@@ -1228,14 +1377,31 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
 
   if (TREE_CODE (arg1) == REAL_CST)
     {
+      enum machine_mode mode;
       REAL_VALUE_TYPE d1;
       REAL_VALUE_TYPE d2;
       REAL_VALUE_TYPE value;
-      tree t;
+      tree t, type;
 
       d1 = TREE_REAL_CST (arg1);
       d2 = TREE_REAL_CST (arg2);
 
+      type = TREE_TYPE (arg1);
+      mode = TYPE_MODE (type);
+
+      /* Don't perform operation if we honor signaling NaNs and
+        either operand is a NaN.  */
+      if (HONOR_SNANS (mode)
+         && (REAL_VALUE_ISNAN (d1) || REAL_VALUE_ISNAN (d2)))
+       return NULL_TREE;
+
+      /* Don't perform operation if it would raise a division
+        by zero exception.  */
+      if (code == RDIV_EXPR
+         && REAL_VALUES_EQUAL (d2, dconst0)
+         && (flag_trapping_math || ! MODE_HAS_INFINITIES (mode)))
+       return NULL_TREE;
+
       /* If either operand is a NaN, just return it.  Otherwise, set up
         for floating-point trap; we return an overflow.  */
       if (REAL_VALUE_ISNAN (d1))
@@ -1245,9 +1411,7 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
 
       REAL_ARITHMETIC (value, code, d1, d2);
 
-      t = build_real (TREE_TYPE (arg1),
-                     real_value_truncate (TYPE_MODE (TREE_TYPE (arg1)),
-                                          value));
+      t = build_real (type, real_value_truncate (mode, value));
 
       TREE_OVERFLOW (t)
        = (force_fit_type (t, 0)
@@ -1540,41 +1704,63 @@ fold_convert (tree t, tree arg1)
        }
       else if (TREE_CODE (arg1) == REAL_CST)
        {
-         /* Don't initialize these, use assignments.
-            Initialized local aggregates don't work on old compilers.  */
-         REAL_VALUE_TYPE x;
-         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));
-
-         no_upper_bound = (TYPE_MAX_VALUE (type) == NULL);
-         if (!no_upper_bound)
-           u = real_value_from_int_cst (type1, TYPE_MAX_VALUE (type));
+         /* The following code implements the floating point to integer
+            conversion rules required by the Java Language Specification,
+            that IEEE NaNs are mapped to zero and values that overflow
+            the target precision saturate, i.e. values greater than
+            INT_MAX are mapped to INT_MAX, and values less than INT_MIN
+            are mapped to INT_MIN.  These semantics are allowed by the
+            C and C++ standards that simply state that the behavior of
+            FP-to-integer conversion is unspecified upon overflow.  */
+
+         HOST_WIDE_INT high, low;
+
+         REAL_VALUE_TYPE x = TREE_REAL_CST (arg1);
+         /* If x is NaN, return zero and show we have an overflow.  */
+         if (REAL_VALUE_ISNAN (x))
+           {
+             overflow = 1;
+             high = 0;
+             low = 0;
+           }
 
          /* 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.  */
-         REAL_ARITHMETIC (l, MINUS_EXPR, l, dconst1);
-         if (!no_upper_bound)
-           REAL_ARITHMETIC (u, PLUS_EXPR, u, dconst1);
-         /* 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)
-                     && !no_upper_bound
-                     && REAL_VALUES_LESS (x, u)))
-           overflow = 1;
 
-         {
-           HOST_WIDE_INT low, high;
+         if (! overflow)
+           {
+             tree lt = TYPE_MIN_VALUE (type);
+             REAL_VALUE_TYPE l = real_value_from_int_cst (NULL_TREE, lt);
+             REAL_ARITHMETIC (l, MINUS_EXPR, l, dconst1);
+             if (! REAL_VALUES_LESS (l, x))
+               {
+                 overflow = 1;
+                 high = TREE_INT_CST_HIGH (lt);
+                 low = TREE_INT_CST_LOW (lt);
+               }
+           }
+
+         if (! overflow)
+           {
+             tree ut = TYPE_MAX_VALUE (type);
+             if (ut)
+               {
+                 REAL_VALUE_TYPE u = real_value_from_int_cst (NULL_TREE, ut);
+                 REAL_ARITHMETIC (u, PLUS_EXPR, u, dconst1);
+                 if (! REAL_VALUES_LESS (x, u))
+                   {
+                     overflow = 1;
+                     high = TREE_INT_CST_HIGH (ut);
+                     low = TREE_INT_CST_LOW (ut);
+                   }
+               }
+           }
+
+         if (! overflow)
            REAL_VALUE_TO_INT (&low, &high, x);
-           t = build_int_2 (low, high);
-         }
+
+         t = build_int_2 (low, high);
          TREE_TYPE (t) = type;
          TREE_OVERFLOW (t)
            = TREE_OVERFLOW (arg1) | force_fit_type (t, overflow);
@@ -1764,17 +1950,33 @@ truth_value_p (enum tree_code code)
          || code == TRUTH_XOR_EXPR || code == TRUTH_NOT_EXPR);
 }
 \f
-/* Return nonzero if two operands are necessarily equal.
+/* Return nonzero if two operands (typically of the same tree node)
+   are necessarily equal.  If either argument has side-effects this
+   function returns zero.
+
    If ONLY_CONST is nonzero, only return nonzero for constants.
    This function tests whether the operands are indistinguishable;
    it does not test whether they are equal using C's == operation.
    The distinction is important for IEEE floating point, because
    (1) -0.0 and 0.0 are distinguishable, but -0.0==0.0, and
-   (2) two NaNs may be indistinguishable, but NaN!=NaN.  */
+   (2) two NaNs may be indistinguishable, but NaN!=NaN.
+
+   If ONLY_CONST is zero, a VAR_DECL is considered equal to itself
+   even though it may hold multiple values during a function.
+   This is because a GCC tree node guarantees that nothing else is
+   executed between the evaluation of its "operands" (which may often
+   be evaluated in arbitrary order).  Hence if the operands themselves
+   don't side-effect, the VAR_DECLs, PARM_DECLs etc... must hold the
+   same value in each operand/subexpression.  Hence a zero value for
+   ONLY_CONST assumes isochronic (or instantaneous) tree equivalence.
+   If comparing arbitrary expression trees, such as from different
+   statements, ONLY_CONST must usually be nonzero.  */
 
 int
 operand_equal_p (tree arg0, tree arg1, int only_const)
 {
+  tree fndecl;
+
   /* If both types don't have the same signedness, then we can't consider
      them equal.  We must check this before the STRIP_NOPS calls
      because they may change the signedness of the arguments.  */
@@ -1945,13 +2147,9 @@ operand_equal_p (tree arg0, tree arg1, int only_const)
            return 0;
 
          /* Only consider const functions equivalent.  */
-         if (TREE_CODE (TREE_OPERAND (arg0, 0)) == ADDR_EXPR)
-           {
-             tree fndecl = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
-             if (! (flags_from_decl_or_type (fndecl) & ECF_CONST))
-               return 0;
-           }
-         else
+         fndecl = get_callee_fndecl (arg0);
+         if (fndecl == NULL_TREE
+             || ! (flags_from_decl_or_type (fndecl) & ECF_CONST))
            return 0;
 
          /* Now see if all the arguments are the same.  operand_equal_p
@@ -2194,7 +2392,7 @@ eval_subst (tree arg, tree old0, tree new0, tree old1, tree new1)
        default:
          break;
        }
-      /* fall through - ??? */
+      /* Fall through - ???  */
 
     case '<':
       {
@@ -2730,8 +2928,8 @@ all_ones_mask_p (tree mask, int size)
 static tree
 sign_bit_p (tree exp, tree val)
 {
-  unsigned HOST_WIDE_INT lo;
-  HOST_WIDE_INT hi;
+  unsigned HOST_WIDE_INT mask_lo, lo;
+  HOST_WIDE_INT mask_hi, hi;
   int width;
   tree t;
 
@@ -2750,14 +2948,25 @@ sign_bit_p (tree exp, tree val)
     {
       hi = (unsigned HOST_WIDE_INT) 1 << (width - HOST_BITS_PER_WIDE_INT - 1);
       lo = 0;
+
+      mask_hi = ((unsigned HOST_WIDE_INT) -1
+                >> (2 * HOST_BITS_PER_WIDE_INT - width));
+      mask_lo = -1;
     }
   else
     {
       hi = 0;
       lo = (unsigned HOST_WIDE_INT) 1 << (width - 1);
+
+      mask_hi = 0;
+      mask_lo = ((unsigned HOST_WIDE_INT) -1
+                >> (HOST_BITS_PER_WIDE_INT - width));
     }
 
-  if (TREE_INT_CST_HIGH (val) == hi && TREE_INT_CST_LOW (val) == lo)
+  /* We mask off those bits beyond TREE_TYPE (exp) so that we can
+     treat VAL as if it were unsigned.  */
+  if ((TREE_INT_CST_HIGH (val) & mask_hi) == hi
+      && (TREE_INT_CST_LOW (val) & mask_lo) == lo)
     return exp;
 
   /* Handle extension from a narrower type.  */
@@ -2994,10 +3203,10 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
 
              in_p = n_in_p, low = n_low, high = n_high;
 
-             /* If the high bound is missing, but we
-                have a low bound, reverse the range so
-                it goes from zero to the low bound minus 1.  */
-             if (high == 0 && low)
+             /* If the high bound is missing, but we have a nonzero low
+                bound, reverse the range so it goes from zero to the low bound
+                minus 1.  */
+             if (high == 0 && low && ! integer_zerop (low))
                {
                  in_p = ! in_p;
                  high = range_binop (MINUS_EXPR, NULL_TREE, low, 0,
@@ -4224,8 +4433,11 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type)
       if (code == MULT_EXPR
          || integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c, 0)))
        {
-         op1 = const_binop (code, convert (ctype, op1), convert (ctype, c), 0);
-         if (op1 == 0 || TREE_OVERFLOW (op1))
+         op1 = const_binop (code, convert (ctype, op1),
+                            convert (ctype, c), 0);
+         /* We allow the constant to overflow with wrapping semantics.  */
+         if (op1 == 0
+             || (TREE_OVERFLOW (op1) && ! flag_wrapv))
            break;
        }
       else
@@ -4827,7 +5039,7 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
       int bitnum = tree_log2 (TREE_OPERAND (arg0, 1));
       enum machine_mode operand_mode = TYPE_MODE (type);
       int ops_unsigned;
-      tree signed_type, unsigned_type;
+      tree signed_type, unsigned_type, intermediate_type;
       tree arg00;
   
       /* If we have (A & C) != 0 where C is the sign bit of A, convert
@@ -4840,6 +5052,10 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
                              convert (stype, arg00),
                              convert (stype, integer_zero_node)));
        }
+
+      /* At this point, we know that arg0 is not testing the sign bit.  */
+      if (TYPE_PRECISION (type) - 1 == bitnum)
+       abort ();
       
       /* Otherwise we have (A & C) != 0 where C is a single bit, 
         convert that into ((A >> C2) & 1).  Where C2 = log2(C).
@@ -4861,39 +5077,97 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
       /* If we are going to be able to omit the AND below, we must do our
         operations as unsigned.  If we must use the AND, we have a choice.
         Normally unsigned is faster, but for some machines signed is.  */
-      ops_unsigned = (bitnum == TYPE_PRECISION (type) - 1 ? 1
 #ifdef LOAD_EXTEND_OP
-                     : (LOAD_EXTEND_OP (operand_mode) == SIGN_EXTEND ? 0 : 1)
+      ops_unsigned = (LOAD_EXTEND_OP (operand_mode) == SIGN_EXTEND ? 0 : 1);
 #else
-                     : 1
+      ops_unsigned = 1;
 #endif
-                     );
 
       signed_type = (*lang_hooks.types.type_for_mode) (operand_mode, 0);
       unsigned_type = (*lang_hooks.types.type_for_mode) (operand_mode, 1);
+      intermediate_type = ops_unsigned ? unsigned_type : signed_type;
+      inner = convert (intermediate_type, inner);
 
       if (bitnum != 0)
-       inner = build (RSHIFT_EXPR, ops_unsigned ? unsigned_type : signed_type,
+       inner = build (RSHIFT_EXPR, intermediate_type,
                       inner, size_int (bitnum));
 
       if (code == EQ_EXPR)
-       inner = build (BIT_XOR_EXPR, ops_unsigned ? unsigned_type : signed_type,
+       inner = build (BIT_XOR_EXPR, intermediate_type,
                       inner, integer_one_node);
 
       /* Put the AND last so it can combine with more things.  */
-      if (bitnum != TYPE_PRECISION (type) - 1)
-       inner = build (BIT_AND_EXPR, ops_unsigned ? unsigned_type : signed_type,
-                      inner, integer_one_node);
+      inner = build (BIT_AND_EXPR, intermediate_type,
+                    inner, integer_one_node);
 
       /* Make sure to return the proper type.  */
-      if (TREE_TYPE (inner) != result_type)
-       inner = convert (result_type, inner);
+      inner = convert (result_type, inner);
 
       return inner;
     }
   return NULL_TREE;
 }
+
+/* Check whether we are allowed to reorder operands arg0 and arg1,
+   such that the evaluation of arg1 occurs before arg0.  */
+
+static bool
+reorder_operands_p (tree arg0, tree arg1)
+{
+  if (! flag_evaluation_order)
+    return true;
+  if (TREE_CONSTANT (arg0) || TREE_CONSTANT (arg1))
+    return true;
+  return ! TREE_SIDE_EFFECTS (arg0)
+        && ! TREE_SIDE_EFFECTS (arg1);
+}
+
+/* Test whether it is preferable two swap two operands, ARG0 and
+   ARG1, for example because ARG0 is an integer constant and ARG1
+   isn't.  If REORDER is true, only recommend swapping if we can
+   evaluate the operands in reverse order.  */
+
+static bool
+tree_swap_operands_p (tree arg0, tree arg1, bool reorder)
+{
+  STRIP_SIGN_NOPS (arg0);
+  STRIP_SIGN_NOPS (arg1);
+
+  if (TREE_CODE (arg1) == INTEGER_CST)
+    return 0;
+  if (TREE_CODE (arg0) == INTEGER_CST)
+    return 1;
+
+  if (TREE_CODE (arg1) == REAL_CST)
+    return 0;
+  if (TREE_CODE (arg0) == REAL_CST)
+    return 1;
+
+  if (TREE_CODE (arg1) == COMPLEX_CST)
+    return 0;
+  if (TREE_CODE (arg0) == COMPLEX_CST)
+    return 1;
+
+  if (TREE_CONSTANT (arg1))
+    return 0;
+  if (TREE_CONSTANT (arg0))
+    return 1;
+    
+  if (optimize_size)
+    return 0;
+
+  if (reorder && flag_evaluation_order
+      && (TREE_SIDE_EFFECTS (arg0) || TREE_SIDE_EFFECTS (arg1)))
+    return 0;
+
+  if (DECL_P (arg1))
+    return 0;
+  if (DECL_P (arg0))
+    return 1;
+
+  return 0;
+}
+
 /* 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.
@@ -4902,10 +5176,15 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
    We cannot simplify through a CONVERT_EXPR, FIX_EXPR or FLOAT_EXPR,
    but we can constant-fold them if they have constant operands.  */
 
+#ifdef ENABLE_FOLD_CHECKING
+# define fold(x) fold_1 (x)
+static tree fold_1 (tree);
+static
+#endif
 tree
 fold (tree expr)
 {
-  tree t = expr;
+  tree t = expr, orig_t;
   tree t1 = NULL_TREE;
   tree tem;
   tree type = TREE_TYPE (expr);
@@ -4929,6 +5208,7 @@ fold (tree expr)
 #ifdef MAX_INTEGER_COMPUTATION_MODE
   check_max_integer_computation_mode (expr);
 #endif
+  orig_t = t;
 
   if (code == NOP_EXPR || code == FLOAT_EXPR || code == CONVERT_EXPR)
     {
@@ -4947,14 +5227,13 @@ fold (tree expr)
        subop = arg0;
 
       if (subop != 0 && TREE_CODE (subop) != INTEGER_CST
-         && TREE_CODE (subop) != REAL_CST
-         )
+         && TREE_CODE (subop) != REAL_CST)
        /* Note that TREE_CONSTANT isn't enough:
           static var addresses are constant but we can't
           do arithmetic on them.  */
        wins = 0;
     }
-  else if (IS_EXPR_CODE_CLASS (kind) || kind == 'r')
+  else if (IS_EXPR_CODE_CLASS (kind))
     {
       int len = first_rtl_op (code);
       int i;
@@ -5000,13 +5279,8 @@ fold (tree expr)
   if ((code == PLUS_EXPR || code == MULT_EXPR || code == MIN_EXPR
        || code == MAX_EXPR || code == BIT_IOR_EXPR || code == BIT_XOR_EXPR
        || code == BIT_AND_EXPR)
-      && (TREE_CODE (arg0) == INTEGER_CST || TREE_CODE (arg0) == REAL_CST))
-    {
-      tem = arg0; arg0 = arg1; arg1 = tem;
-
-      tem = TREE_OPERAND (t, 0); TREE_OPERAND (t, 0) = TREE_OPERAND (t, 1);
-      TREE_OPERAND (t, 1) = tem;
-    }
+      && tree_swap_operands_p (arg0, arg1, true))
+    return fold (build (code, type, arg1, arg0));
 
   /* Now WINS is set as described above,
      ARG0 is the first operand of EXPR,
@@ -5254,6 +5528,8 @@ fold (tree expr)
          /* Don't leave an assignment inside a conversion
             unless assigning a bitfield.  */
          tree prev = TREE_OPERAND (t, 0);
+         if (t == orig_t)
+           t = copy_node (t);
          TREE_OPERAND (t, 0) = TREE_OPERAND (prev, 1);
          /* First do the assignment, then return converted constant.  */
          t = build (COMPOUND_EXPR, TREE_TYPE (t), prev, fold (t));
@@ -5306,7 +5582,12 @@ fold (tree expr)
 
       if (!wins)
        {
-         TREE_CONSTANT (t) = TREE_CONSTANT (arg0);
+         if (TREE_CONSTANT (t) != TREE_CONSTANT (arg0))
+           {
+             if (t == orig_t)
+               t = copy_node (t);
+             TREE_CONSTANT (t) = TREE_CONSTANT (arg0);
+           }
          return t;
        }
       return fold_convert (t, arg0);
@@ -5328,75 +5609,17 @@ fold (tree expr)
       return t;
 
     case RANGE_EXPR:
-      TREE_CONSTANT (t) = wins;
-      return t;
-
-    case NEGATE_EXPR:
-      if (wins)
-       {
-         if (TREE_CODE (arg0) == INTEGER_CST)
-           {
-             unsigned HOST_WIDE_INT low;
-             HOST_WIDE_INT high;
-             int overflow = neg_double (TREE_INT_CST_LOW (arg0),
-                                        TREE_INT_CST_HIGH (arg0),
-                                        &low, &high);
-             t = build_int_2 (low, high);
-             TREE_TYPE (t) = type;
-             TREE_OVERFLOW (t)
-               = (TREE_OVERFLOW (arg0)
-                  | force_fit_type (t, overflow && !TREE_UNSIGNED (type)));
-             TREE_CONSTANT_OVERFLOW (t)
-               = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg0);
-           }
-         else if (TREE_CODE (arg0) == REAL_CST)
-           t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
-       }
-      else if (TREE_CODE (arg0) == NEGATE_EXPR)
-       return TREE_OPERAND (arg0, 0);
-      /* Convert -((double)float) into (double)(-float).  */
-      else if (TREE_CODE (arg0) == NOP_EXPR
-              && TREE_CODE (type) == REAL_TYPE)
+      if (TREE_CONSTANT (t) != wins)
        {
-         tree targ0 = strip_float_extensions (arg0);
-         if (targ0 != arg0)
-           return convert (type, build1 (NEGATE_EXPR, TREE_TYPE (targ0), targ0));
-
+         if (t == orig_t)
+           t = copy_node (t);
+         TREE_CONSTANT (t) = wins;
        }
+      return t;
 
-      /* Convert - (a - b) to (b - a) for non-floating-point.  */
-      else if (TREE_CODE (arg0) == MINUS_EXPR
-              && (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations))
-       return build (MINUS_EXPR, type, TREE_OPERAND (arg0, 1),
-                     TREE_OPERAND (arg0, 0));
-
-      /* Convert -f(x) into f(-x) where f is sin, tan or atan.  */
-      switch (builtin_mathfn_code (arg0))
-       {
-       case BUILT_IN_SIN:
-       case BUILT_IN_SINF:
-       case BUILT_IN_SINL:
-       case BUILT_IN_TAN:
-       case BUILT_IN_TANF:
-       case BUILT_IN_TANL:
-       case BUILT_IN_ATAN:
-       case BUILT_IN_ATANF:
-       case BUILT_IN_ATANL:
-         if (negate_expr_p (TREE_VALUE (TREE_OPERAND (arg0, 1))))
-           {
-             tree fndecl, arg, arglist;
-
-             fndecl = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
-             arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
-             arg = fold (build1 (NEGATE_EXPR, type, arg));
-             arglist = build_tree_list (NULL_TREE, arg);
-             return build_function_call_expr (fndecl, arglist);
-           }
-         break;
-
-       default:
-         break;
-       }
+    case NEGATE_EXPR:
+      if (negate_expr_p (arg0))
+       return negate_expr (arg0);
       return t;
 
     case ABS_EXPR:
@@ -5609,14 +5832,73 @@ fold (tree expr)
                                    same));
            }
        }
+      else
+       {
+         /* See if ARG1 is zero and X + ARG1 reduces to X.  */
+         if (fold_real_zero_addition_p (TREE_TYPE (arg0), arg1, 0))
+           return non_lvalue (convert (type, arg0));
 
-      /* See if ARG1 is zero and X + ARG1 reduces to X.  */
-      else if (fold_real_zero_addition_p (TREE_TYPE (arg0), arg1, 0))
-       return non_lvalue (convert (type, arg0));
+         /* Likewise if the operands are reversed.  */
+         if (fold_real_zero_addition_p (TREE_TYPE (arg1), arg0, 0))
+           return non_lvalue (convert (type, arg1));
 
-      /* Likewise if the operands are reversed.  */
-      else if (fold_real_zero_addition_p (TREE_TYPE (arg1), arg0, 0))
-       return non_lvalue (convert (type, arg1));
+         /* Convert x+x into x*2.0.  */
+         if (operand_equal_p (arg0, arg1, 0)
+             && SCALAR_FLOAT_TYPE_P (type))
+           return fold (build (MULT_EXPR, type, arg0,
+                               build_real (type, dconst2)));
+
+         /* Convert x*c+x into x*(c+1).  */
+         if (flag_unsafe_math_optimizations
+             && TREE_CODE (arg0) == MULT_EXPR
+             && TREE_CODE (TREE_OPERAND (arg0, 1)) == REAL_CST
+             && ! TREE_CONSTANT_OVERFLOW (TREE_OPERAND (arg0, 1))
+             && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
+           {
+             REAL_VALUE_TYPE c;
+
+             c = TREE_REAL_CST (TREE_OPERAND (arg0, 1));
+             real_arithmetic (&c, PLUS_EXPR, &c, &dconst1);
+             return fold (build (MULT_EXPR, type, arg1,
+                                 build_real (type, c)));
+           }
+
+         /* Convert x+x*c into x*(c+1).  */
+         if (flag_unsafe_math_optimizations
+             && TREE_CODE (arg1) == MULT_EXPR
+             && TREE_CODE (TREE_OPERAND (arg1, 1)) == REAL_CST
+             && ! TREE_CONSTANT_OVERFLOW (TREE_OPERAND (arg1, 1))
+             && operand_equal_p (TREE_OPERAND (arg1, 0), arg0, 0))
+           {
+             REAL_VALUE_TYPE c;
+
+             c = TREE_REAL_CST (TREE_OPERAND (arg1, 1));
+             real_arithmetic (&c, PLUS_EXPR, &c, &dconst1);
+             return fold (build (MULT_EXPR, type, arg0,
+                                 build_real (type, c)));
+           }
+
+         /* Convert x*c1+x*c2 into x*(c1+c2).  */
+         if (flag_unsafe_math_optimizations
+             && TREE_CODE (arg0) == MULT_EXPR
+             && TREE_CODE (arg1) == MULT_EXPR
+             && TREE_CODE (TREE_OPERAND (arg0, 1)) == REAL_CST
+             && ! TREE_CONSTANT_OVERFLOW (TREE_OPERAND (arg0, 1))
+             && TREE_CODE (TREE_OPERAND (arg1, 1)) == REAL_CST
+             && ! TREE_CONSTANT_OVERFLOW (TREE_OPERAND (arg1, 1))
+             && operand_equal_p (TREE_OPERAND (arg0, 0),
+                                 TREE_OPERAND (arg1, 0), 0))
+           {
+             REAL_VALUE_TYPE c1, c2;
+
+             c1 = TREE_REAL_CST (TREE_OPERAND (arg0, 1));
+             c2 = TREE_REAL_CST (TREE_OPERAND (arg1, 1));
+             real_arithmetic (&c1, PLUS_EXPR, &c1, &c2);
+             return fold (build (MULT_EXPR, type,
+                                 TREE_OPERAND (arg0, 0),
+                                 build_real (type, c1)));
+           }
+       }
 
      bit_rotate:
       /* (A << C1) + (A >> C2) if A is unsigned and C1+C2 is the size of A
@@ -5692,13 +5974,11 @@ fold (tree expr)
     associate:
       /* In most languages, can't associate operations on floats through
         parentheses.  Rather than remember where the parentheses were, we
-        don't associate floats at all.  It shouldn't matter much.  However,
-        associating multiplications is only very slightly inaccurate, so do
-        that if -funsafe-math-optimizations is specified.  */
+        don't associate floats at all, unless the user has specified
+        -funsafe-math-optimizations.  */
 
       if (! wins
-         && (! FLOAT_TYPE_P (type)
-             || (flag_unsafe_math_optimizations && code == MULT_EXPR)))
+         && (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations))
        {
          tree var0, con0, lit0, minus_lit0;
          tree var1, con1, lit1, minus_lit1;
@@ -5735,7 +6015,9 @@ fold (tree expr)
                 example: ((X*2 + 4) - 8U)/2.  */
              if (minus_lit0 && lit0)
                {
-                 if (tree_int_cst_lt (lit0, minus_lit0))
+                 if (TREE_CODE (lit0) == INTEGER_CST
+                     && TREE_CODE (minus_lit0) == INTEGER_CST
+                     && tree_int_cst_lt (lit0, minus_lit0))
                    {
                      minus_lit0 = associate_trees (minus_lit0, lit0,
                                                    MINUS_EXPR, type);
@@ -5790,8 +6072,7 @@ fold (tree expr)
          && (FLOAT_TYPE_P (type)
              || (INTEGRAL_TYPE_P (type) && flag_wrapv && !flag_trapv))
          && negate_expr_p (arg1)
-         && (! TREE_SIDE_EFFECTS (arg0) || TREE_CONSTANT (arg1))
-         && (! TREE_SIDE_EFFECTS (arg1) || TREE_CONSTANT (arg0)))
+         && reorder_operands_p (arg0, arg1))
        return fold (build (MINUS_EXPR, type, negate_expr (arg1),
                            TREE_OPERAND (arg0, 0)));
 
@@ -5830,6 +6111,25 @@ fold (tree expr)
                                                  TREE_OPERAND (arg1, 1))),
                                    arg0));
            }
+
+         /* Fold (A & ~B) - (A & B) into (A ^ B) - B, where B is
+            any power of 2 minus 1.  */
+         if (TREE_CODE (arg0) == BIT_AND_EXPR
+             && TREE_CODE (arg1) == BIT_AND_EXPR
+             && operand_equal_p (TREE_OPERAND (arg0, 0),
+                                 TREE_OPERAND (arg1, 0), 0))
+           {
+             tree mask0 = TREE_OPERAND (arg0, 1);
+             tree mask1 = TREE_OPERAND (arg1, 1);
+             tree tem = fold (build1 (BIT_NOT_EXPR, type, mask0));
+             
+             if (operand_equal_p (tem, mask1, 0))
+               {
+                 tem = fold (build (BIT_XOR_EXPR, type,
+                                    TREE_OPERAND (arg0, 0), mask1));
+                 return fold (build (MINUS_EXPR, type, tem, mask1));
+               }
+           }
        }
 
       /* See if ARG1 is zero and X - ARG1 reduces to X.  */
@@ -5856,8 +6156,13 @@ fold (tree expr)
 
     case MULT_EXPR:
       /* (-A) * (-B) -> A * B  */
-      if (TREE_CODE (arg0) == NEGATE_EXPR && TREE_CODE (arg1) == NEGATE_EXPR)
-       return fold (build (MULT_EXPR, type, TREE_OPERAND (arg0, 0),
+      if (TREE_CODE (arg0) == NEGATE_EXPR && negate_expr_p (arg1))
+       return fold (build (MULT_EXPR, type,
+                           TREE_OPERAND (arg0, 0),
+                           negate_expr (arg1)));
+      if (TREE_CODE (arg1) == NEGATE_EXPR && negate_expr_p (arg0))
+       return fold (build (MULT_EXPR, type,
+                           negate_expr (arg0),
                            TREE_OPERAND (arg1, 0)));
 
       if (! FLOAT_TYPE_P (type))
@@ -5904,13 +6209,17 @@ fold (tree expr)
              && real_minus_onep (arg1))
            return fold (build1 (NEGATE_EXPR, type, arg0));
 
-         /* x*2 is x+x */
-         if (! wins && real_twop (arg1)
-             && (*lang_hooks.decls.global_bindings_p) () == 0
-             && ! CONTAINS_PLACEHOLDER_P (arg0))
+         /* Convert (C1/X)*C2 into (C1*C2)/X.  */
+         if (flag_unsafe_math_optimizations
+             && TREE_CODE (arg0) == RDIV_EXPR
+             && TREE_CODE (arg1) == REAL_CST
+             && TREE_CODE (TREE_OPERAND (arg0, 0)) == REAL_CST)
            {
-             tree arg = save_expr (arg0);
-             return fold (build (PLUS_EXPR, type, arg, arg));
+             tree tem = const_binop (MULT_EXPR, TREE_OPERAND (arg0, 0),
+                                     arg1, 0);
+             if (tem)
+               return fold (build (RDIV_EXPR, type, tem,
+                                   TREE_OPERAND (arg0, 1)));
            }
 
          if (flag_unsafe_math_optimizations)
@@ -5939,10 +6248,20 @@ fold (tree expr)
                  return build_function_call_expr (sqrtfn, arglist);
                }
 
-             /* Optimize exp(x)*exp(y) as exp(x+y).  */
-             if ((fcode0 == BUILT_IN_EXP && fcode1 == BUILT_IN_EXP)
-                 || (fcode0 == BUILT_IN_EXPF && fcode1 == BUILT_IN_EXPF)
-                 || (fcode0 == BUILT_IN_EXPL && fcode1 == BUILT_IN_EXPL))
+             /* Optimize expN(x)*expN(y) as expN(x+y).  */
+             if (fcode0 == fcode1
+                 && (fcode0 == BUILT_IN_EXP
+                     || fcode0 == BUILT_IN_EXPF
+                     || fcode0 == BUILT_IN_EXPL
+                     || fcode0 == BUILT_IN_EXP2
+                     || fcode0 == BUILT_IN_EXP2F
+                     || fcode0 == BUILT_IN_EXP2L
+                     || fcode0 == BUILT_IN_EXP10
+                     || fcode0 == BUILT_IN_EXP10F
+                     || fcode0 == BUILT_IN_EXP10L
+                     || fcode0 == BUILT_IN_POW10
+                     || fcode0 == BUILT_IN_POW10F
+                     || fcode0 == BUILT_IN_POW10L))
                {
                  tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
                  tree arg = build (PLUS_EXPR, type,
@@ -6021,6 +6340,80 @@ fold (tree expr)
                    return build_function_call_expr (sinfn,
                                                     TREE_OPERAND (arg0, 1));
                }
+
+             /* Optimize x*pow(x,c) as pow(x,c+1).  */
+             if (fcode1 == BUILT_IN_POW
+                 || fcode1 == BUILT_IN_POWF
+                 || fcode1 == BUILT_IN_POWL)
+               {
+                 tree arg10 = TREE_VALUE (TREE_OPERAND (arg1, 1));
+                 tree arg11 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg1,
+                                                                    1)));
+                 if (TREE_CODE (arg11) == REAL_CST
+                     && ! TREE_CONSTANT_OVERFLOW (arg11)
+                     && operand_equal_p (arg0, arg10, 0))
+                   {
+                     tree powfn = TREE_OPERAND (TREE_OPERAND (arg1, 0), 0);
+                     REAL_VALUE_TYPE c;
+                     tree arg, arglist;
+
+                     c = TREE_REAL_CST (arg11);
+                     real_arithmetic (&c, PLUS_EXPR, &c, &dconst1);
+                     arg = build_real (type, c);
+                     arglist = build_tree_list (NULL_TREE, arg);
+                     arglist = tree_cons (NULL_TREE, arg0, arglist);
+                     return build_function_call_expr (powfn, arglist);
+                   }
+               }
+
+             /* Optimize pow(x,c)*x as pow(x,c+1).  */
+             if (fcode0 == BUILT_IN_POW
+                 || fcode0 == BUILT_IN_POWF
+                 || fcode0 == BUILT_IN_POWL)
+               {
+                 tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
+                 tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0,
+                                                                    1)));
+                 if (TREE_CODE (arg01) == REAL_CST
+                     && ! TREE_CONSTANT_OVERFLOW (arg01)
+                     && operand_equal_p (arg1, arg00, 0))
+                   {
+                     tree powfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+                     REAL_VALUE_TYPE c;
+                     tree arg, arglist;
+
+                     c = TREE_REAL_CST (arg01);
+                     real_arithmetic (&c, PLUS_EXPR, &c, &dconst1);
+                     arg = build_real (type, c);
+                     arglist = build_tree_list (NULL_TREE, arg);
+                     arglist = tree_cons (NULL_TREE, arg1, arglist);
+                     return build_function_call_expr (powfn, arglist);
+                   }
+               }
+
+             /* Optimize x*x as pow(x,2.0), which is expanded as x*x.  */
+             if (! optimize_size
+                 && operand_equal_p (arg0, arg1, 0))
+               {
+                 tree powfn;
+
+                 if (type == double_type_node)
+                   powfn = implicit_built_in_decls[BUILT_IN_POW];
+                 else if (type == float_type_node)
+                   powfn = implicit_built_in_decls[BUILT_IN_POWF];
+                 else if (type == long_double_type_node)
+                   powfn = implicit_built_in_decls[BUILT_IN_POWL];
+                 else
+                   powfn = NULL_TREE;
+
+                 if (powfn)
+                   {
+                     tree arg = build_real (type, dconst2);
+                     tree arglist = build_tree_list (NULL_TREE, arg);
+                     arglist = tree_cons (NULL_TREE, arg0, arglist);
+                     return build_function_call_expr (powfn, arglist);
+                   }
+               }
            }
        }
       goto associate;
@@ -6081,7 +6474,6 @@ fold (tree expr)
       goto bit_rotate;
 
     case BIT_AND_EXPR:
-    bit_and:
       if (integer_all_onesp (arg1))
        return non_lvalue (convert (type, arg0));
       if (integer_zerop (arg1))
@@ -6119,19 +6511,6 @@ fold (tree expr)
 
       goto associate;
 
-    case BIT_ANDTC_EXPR:
-      if (integer_all_onesp (arg0))
-       return non_lvalue (convert (type, arg1));
-      if (integer_zerop (arg0))
-       return omit_one_operand (type, arg0, arg1);
-      if (TREE_CODE (arg1) == INTEGER_CST)
-       {
-         arg1 = fold (build1 (BIT_NOT_EXPR, type, arg1));
-         code = BIT_AND_EXPR;
-         goto bit_and;
-       }
-      goto binary;
-
     case RDIV_EXPR:
       /* Don't touch a floating-point divide by zero unless the mode
         of the constant can represent infinity.  */
@@ -6141,8 +6520,13 @@ fold (tree expr)
        return t;
 
       /* (-A) / (-B) -> A / B  */
-      if (TREE_CODE (arg0) == NEGATE_EXPR && TREE_CODE (arg1) == NEGATE_EXPR)
-       return fold (build (RDIV_EXPR, type, TREE_OPERAND (arg0, 0),
+      if (TREE_CODE (arg0) == NEGATE_EXPR && negate_expr_p (arg1))
+       return fold (build (RDIV_EXPR, type,
+                           TREE_OPERAND (arg0, 0),
+                           negate_expr (arg1)));
+      if (TREE_CODE (arg1) == NEGATE_EXPR && negate_expr_p (arg0))
+       return fold (build (RDIV_EXPR, type,
+                           negate_expr (arg0),
                            TREE_OPERAND (arg1, 0)));
 
       /* In IEEE floating point, x/1 is not equivalent to x for snans.  */
@@ -6150,6 +6534,11 @@ fold (tree expr)
          && real_onep (arg1))
        return non_lvalue (convert (type, arg0));
 
+      /* In IEEE floating point, x/-1 is not equivalent to -x for snans.  */
+      if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
+         && real_minus_onep (arg1))
+       return non_lvalue (convert (type, negate_expr (arg0)));
+
       /* 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 -funsafe-math-optimizations.  We can actually
@@ -6162,7 +6551,7 @@ fold (tree expr)
                                          arg1, 0)))
            return fold (build (MULT_EXPR, type, arg0, tem));
          /* Find the reciprocal if optimizing and the result is exact.  */
-         else if (optimize)
+         if (optimize)
            {
              REAL_VALUE_TYPE r;
              r = TREE_REAL_CST (arg1);
@@ -6176,28 +6565,47 @@ fold (tree 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)));
-       }
+       return fold (build (RDIV_EXPR, type, TREE_OPERAND (arg0, 0),
+                           fold (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,
+                           fold (build (RDIV_EXPR, type, arg0,
+                                        TREE_OPERAND (arg1, 0))),
+                           TREE_OPERAND (arg1, 1)));
+
+      /* Convert C1/(X*C2) into (C1/C2)/X.  */
+      if (flag_unsafe_math_optimizations
+         && TREE_CODE (arg1) == MULT_EXPR
+         && TREE_CODE (arg0) == REAL_CST
+         && TREE_CODE (TREE_OPERAND (arg1, 1)) == REAL_CST)
        {
-         return fold (build (MULT_EXPR, type,
-                             build (RDIV_EXPR, type, arg0,
-                                    TREE_OPERAND (arg1, 0)),
-                             TREE_OPERAND (arg1, 1)));
+         tree tem = const_binop (RDIV_EXPR, arg0,
+                                 TREE_OPERAND (arg1, 1), 0);
+         if (tem)
+           return fold (build (RDIV_EXPR, type, tem,
+                               TREE_OPERAND (arg1, 0)));
        }
 
       if (flag_unsafe_math_optimizations)
        {
          enum built_in_function fcode = builtin_mathfn_code (arg1);
-         /* Optimize x/exp(y) into x*exp(-y).  */
+         /* Optimize x/expN(y) into x*expN(-y).  */
          if (fcode == BUILT_IN_EXP
              || fcode == BUILT_IN_EXPF
-             || fcode == BUILT_IN_EXPL)
+             || fcode == BUILT_IN_EXPL
+             || fcode == BUILT_IN_EXP2
+             || fcode == BUILT_IN_EXP2F
+             || fcode == BUILT_IN_EXP2L
+             || fcode == BUILT_IN_EXP10
+             || fcode == BUILT_IN_EXP10F
+             || fcode == BUILT_IN_EXP10L
+             || fcode == BUILT_IN_POW10
+             || fcode == BUILT_IN_POW10F
+             || fcode == BUILT_IN_POW10L)
            {
              tree expfn = TREE_OPERAND (TREE_OPERAND (arg1, 0), 0);
              tree arg = build1 (NEGATE_EXPR, type,
@@ -6278,6 +6686,30 @@ fold (tree expr)
                                      tmp));
                }
            }
+
+         /* Optimize pow(x,c)/x as pow(x,c-1).  */
+         if (fcode0 == BUILT_IN_POW
+             || fcode0 == BUILT_IN_POWF
+             || fcode0 == BUILT_IN_POWL)
+           {
+             tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
+             tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0, 1)));
+             if (TREE_CODE (arg01) == REAL_CST
+                 && ! TREE_CONSTANT_OVERFLOW (arg01)
+                 && operand_equal_p (arg1, arg00, 0))
+               {
+                 tree powfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+                 REAL_VALUE_TYPE c;
+                 tree arg, arglist;
+
+                 c = TREE_REAL_CST (arg01);
+                 real_arithmetic (&c, MINUS_EXPR, &c, &dconst1);
+                 arg = build_real (type, c);
+                 arglist = build_tree_list (NULL_TREE, arg);
+                 arglist = tree_cons (NULL_TREE, arg1, arglist);
+                 return build_function_call_expr (powfn, arglist);
+               }
+           }
        }
       goto binary;
 
@@ -6351,16 +6783,10 @@ fold (tree expr)
         RROTATE_EXPR by a new constant.  */
       if (code == LROTATE_EXPR && TREE_CODE (arg1) == INTEGER_CST)
        {
-         TREE_SET_CODE (t, RROTATE_EXPR);
-         code = RROTATE_EXPR;
-         TREE_OPERAND (t, 1) = arg1
-           = const_binop
-             (MINUS_EXPR,
-              convert (TREE_TYPE (arg1),
-                       build_int_2 (GET_MODE_BITSIZE (TYPE_MODE (type)), 0)),
-              arg1, 0);
-         if (tree_int_cst_sgn (arg1) < 0)
-           return t;
+         tree tem = build_int_2 (GET_MODE_BITSIZE (TYPE_MODE (type)), 0);
+         tem = convert (TREE_TYPE (arg1), tem);
+         tem = const_binop (MINUS_EXPR, tem, arg1, 0);
+         return fold (build (RROTATE_EXPR, type, arg0, tem));
        }
 
       /* If we have a rotate of a bit operation with the rotate count and
@@ -6368,7 +6794,6 @@ fold (tree expr)
         permute the two operations.  */
       if (code == RROTATE_EXPR && TREE_CODE (arg1) == INTEGER_CST
          && (TREE_CODE (arg0) == BIT_AND_EXPR
-             || TREE_CODE (arg0) == BIT_ANDTC_EXPR
              || TREE_CODE (arg0) == BIT_IOR_EXPR
              || TREE_CODE (arg0) == BIT_XOR_EXPR)
          && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
@@ -6558,18 +6983,8 @@ fold (tree expr)
     case LE_EXPR:
     case GE_EXPR:
       /* If one arg is a real or integer constant, put it last.  */
-      if ((TREE_CODE (arg0) == INTEGER_CST
-          && TREE_CODE (arg1) != INTEGER_CST)
-         || (TREE_CODE (arg0) == REAL_CST
-             && TREE_CODE (arg0) != REAL_CST))
-       {
-         TREE_OPERAND (t, 0) = arg1;
-         TREE_OPERAND (t, 1) = arg0;
-         arg0 = TREE_OPERAND (t, 0);
-         arg1 = TREE_OPERAND (t, 1);
-         code = swap_tree_comparison (code);
-         TREE_SET_CODE (t, code);
-       }
+      if (tree_swap_operands_p (arg0, arg1, true))
+       return fold (build (swap_tree_comparison (code), type, arg1, arg0));
 
       if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
        {
@@ -6826,16 +7241,12 @@ fold (tree expr)
          switch (code)
            {
            case GE_EXPR:
-             code = GT_EXPR;
              arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
-             t = build (code, type, TREE_OPERAND (t, 0), arg1);
-             break;
+             return fold (build (GT_EXPR, type, arg0, arg1));
 
            case LT_EXPR:
-             code = LE_EXPR;
              arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
-             t = build (code, type, TREE_OPERAND (t, 0), arg1);
-             break;
+             return fold (build (LE_EXPR, type, arg0, arg1));
 
            default:
              break;
@@ -6878,20 +7289,17 @@ fold (tree expr)
                                           convert (type, integer_zero_node),
                                           arg0);
                case GE_EXPR:
-                 code = EQ_EXPR;
-                 TREE_SET_CODE (t, EQ_EXPR);
-                 break;
+                 return fold (build (EQ_EXPR, type, arg0, arg1));
+
                case LE_EXPR:
                  return omit_one_operand (type,
                                           convert (type, integer_one_node),
                                           arg0);
                case LT_EXPR:
-                 code = NE_EXPR;
-                 TREE_SET_CODE (t, NE_EXPR);
-                 break;
+                 return fold (build (NE_EXPR, type, arg0, arg1));
 
                /* The GE_EXPR and LT_EXPR cases above are not normally
-                  reached because of  previous transformations.  */
+                  reached because of previous transformations.  */
 
                default:
                  break;
@@ -6901,15 +7309,11 @@ fold (tree expr)
              switch (code)
                {
                case GT_EXPR:
-                 code = EQ_EXPR;
                  arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0);
-                 t = build (code, type, TREE_OPERAND (t, 0), arg1);
-                 break;
+                 return fold (build (EQ_EXPR, type, arg0, arg1));
                case LE_EXPR:
-                 code = NE_EXPR;
                  arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0);
-                 t = build (code, type, TREE_OPERAND (t, 0), arg1);
-                 break;
+                 return fold (build (NE_EXPR, type, arg0, arg1));
                default:
                  break;
                }
@@ -6922,18 +7326,14 @@ fold (tree expr)
                                           convert (type, integer_zero_node),
                                           arg0);
                case LE_EXPR:
-                 code = EQ_EXPR;
-                 TREE_SET_CODE (t, EQ_EXPR);
-                 break;
+                 return fold (build (EQ_EXPR, type, arg0, arg1));
 
                case GE_EXPR:
                  return omit_one_operand (type,
                                           convert (type, integer_one_node),
                                           arg0);
                case GT_EXPR:
-                 code = NE_EXPR;
-                 TREE_SET_CODE (t, NE_EXPR);
-                 break;
+                 return fold (build (NE_EXPR, type, arg0, arg1));
 
                default:
                  break;
@@ -6943,15 +7343,11 @@ fold (tree expr)
              switch (code)
                {
                case GE_EXPR:
-                 code = NE_EXPR;
                  arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
-                 t = build (code, type, TREE_OPERAND (t, 0), arg1);
-                 break;
+                 return fold (build (NE_EXPR, type, arg0, arg1));
                case LT_EXPR:
-                 code = EQ_EXPR;
                  arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
-                 t = build (code, type, TREE_OPERAND (t, 0), arg1);
-                 break;
+                 return fold (build (EQ_EXPR, type, arg0, arg1));
                default:
                  break;
                }
@@ -7120,6 +7516,39 @@ fold (tree expr)
       if (tem)
        return tem;
 
+      /* If we have (A & C) == D where D & ~C != 0, convert this into 0.
+        Similarly for NE_EXPR.  */
+      if ((code == EQ_EXPR || code == NE_EXPR)
+         && TREE_CODE (arg0) == BIT_AND_EXPR
+         && TREE_CODE (arg1) == INTEGER_CST
+         && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
+       {
+         tree dandnotc
+           = fold (build (BIT_AND_EXPR, TREE_TYPE (arg0),
+                          arg1, build1 (BIT_NOT_EXPR,
+                                        TREE_TYPE (TREE_OPERAND (arg0, 1)),
+                                        TREE_OPERAND (arg0, 1))));
+         tree rslt = code == EQ_EXPR ? integer_zero_node : integer_one_node;
+         if (integer_nonzerop (dandnotc))
+           return omit_one_operand (type, rslt, arg0);
+       }
+
+      /* If we have (A | C) == D where C & ~D != 0, convert this into 0.
+        Similarly for NE_EXPR.  */
+      if ((code == EQ_EXPR || code == NE_EXPR)
+         && TREE_CODE (arg0) == BIT_IOR_EXPR
+         && TREE_CODE (arg1) == INTEGER_CST
+         && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
+       {
+         tree candnotd
+           = fold (build (BIT_AND_EXPR, TREE_TYPE (arg0),
+                          TREE_OPERAND (arg0, 1),
+                          build1 (BIT_NOT_EXPR, TREE_TYPE (arg1), arg1)));
+         tree rslt = code == EQ_EXPR ? integer_zero_node : integer_one_node;
+         if (integer_nonzerop (candnotd))
+           return omit_one_operand (type, rslt, arg0);
+       }
+
       /* If X is unsigned, convert X < (1 << Y) into X >> Y == 0
         and similarly for >= into !=.  */
       if ((code == LT_EXPR || code == GE_EXPR)
@@ -7151,14 +7580,17 @@ fold (tree expr)
          switch (code)
            {
            case EQ_EXPR:
+             if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
+                 || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
+               return constant_boolean_node (1, type);
+             break;
+
            case GE_EXPR:
            case LE_EXPR:
              if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
                  || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
                return constant_boolean_node (1, type);
-             code = EQ_EXPR;
-             TREE_SET_CODE (t, code);
-             break;
+             return fold (build (EQ_EXPR, type, arg0, arg1));
 
            case NE_EXPR:
              /* For NE, we can only do this simplification if integer
@@ -7325,13 +7757,12 @@ fold (tree expr)
         due to the return value of strlen being unsigned.  */
       if ((code == EQ_EXPR || code == NE_EXPR)
          && integer_zerop (arg1)
-         && TREE_CODE (arg0) == CALL_EXPR
-         && TREE_CODE (TREE_OPERAND (arg0, 0)) == ADDR_EXPR)
+         && TREE_CODE (arg0) == CALL_EXPR)
        {
-         tree fndecl = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+         tree fndecl = get_callee_fndecl (arg0);
          tree arglist;
 
-         if (TREE_CODE (fndecl) == FUNCTION_DECL
+         if (fndecl
              && DECL_BUILT_IN (fndecl)
              && DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_MD
              && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STRLEN
@@ -7440,34 +7871,6 @@ fold (tree expr)
       else if (operand_equal_p (arg1, TREE_OPERAND (expr, 2), 0))
        return pedantic_omit_one_operand (type, arg1, arg0);
 
-      /* If the second operand is zero, invert the comparison and swap
-        the second and third operands.  Likewise if the second operand
-        is constant and the third is not or if the third operand is
-        equivalent to the first operand of the comparison.  */
-
-      if (integer_zerop (arg1)
-         || (TREE_CONSTANT (arg1) && ! TREE_CONSTANT (TREE_OPERAND (t, 2)))
-         || (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
-             && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
-                                                TREE_OPERAND (t, 2),
-                                                TREE_OPERAND (arg0, 1))))
-       {
-         /* See if this can be inverted.  If it can't, possibly because
-            it was a floating-point inequality comparison, don't do
-            anything.  */
-         tem = invert_truthvalue (arg0);
-
-         if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
-           {
-             t = build (code, type, tem,
-                        TREE_OPERAND (t, 2), TREE_OPERAND (t, 1));
-             arg0 = tem;
-             /* arg1 should be the first argument of the new T.  */
-             arg1 = TREE_OPERAND (t, 1);
-             STRIP_NOPS (arg1);
-           }
-       }
-
       /* If we have A op B ? A : C, we may be able to convert this to a
         simpler expression, depending on the operation and the values
         of B and C.  Signed zeros prevent all of these transformations,
@@ -7643,9 +8046,8 @@ fold (tree expr)
              case EQ_EXPR:
                /* We can replace A with C1 in this case.  */
                arg1 = convert (type, TREE_OPERAND (arg0, 1));
-               t = build (code, type, TREE_OPERAND (t, 0), arg1,
-                          TREE_OPERAND (t, 2));
-               break;
+               return fold (build (code, type, TREE_OPERAND (t, 0), arg1,
+                                   TREE_OPERAND (t, 2)));
 
              case LT_EXPR:
                /* If C1 is C2 + 1, this is min(A, C2).  */
@@ -7695,11 +8097,8 @@ fold (tree expr)
 
       /* If the second operand is simpler than the third, swap them
         since that produces better jump optimization results.  */
-      if ((TREE_CONSTANT (arg1) || DECL_P (arg1)
-          || TREE_CODE (arg1) == SAVE_EXPR)
-         && ! (TREE_CONSTANT (TREE_OPERAND (t, 2))
-               || DECL_P (TREE_OPERAND (t, 2))
-               || TREE_CODE (TREE_OPERAND (t, 2)) == SAVE_EXPR))
+      if (tree_swap_operands_p (TREE_OPERAND (t, 1),
+                               TREE_OPERAND (t, 2), false))
        {
          /* See if this can be inverted.  If it can't, possibly because
             it was a floating-point inequality comparison, don't do
@@ -7707,14 +8106,8 @@ fold (tree expr)
          tem = invert_truthvalue (arg0);
 
          if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
-           {
-             t = build (code, type, tem,
-                        TREE_OPERAND (t, 2), TREE_OPERAND (t, 1));
-             arg0 = tem;
-             /* arg1 should be the first argument of the new T.  */
-             arg1 = TREE_OPERAND (t, 1);
-             STRIP_NOPS (arg1);
-           }
+           return fold (build (code, type, tem,
+                        TREE_OPERAND (t, 2), TREE_OPERAND (t, 1)));
        }
 
       /* Convert A ? 1 : 0 to simply A.  */
@@ -7874,6 +8267,224 @@ fold (tree expr)
     } /* switch (code) */
 }
 
+#ifdef ENABLE_FOLD_CHECKING
+#undef fold
+
+static void fold_checksum_tree (tree, struct md5_ctx *, htab_t);
+static void fold_check_failed (tree, tree);
+void print_fold_checksum (tree);
+
+/* When --enable-checking=fold, compute a digest of expr before
+   and after actual fold call to see if fold did not accidentally
+   change original expr.  */
+
+tree
+fold (tree expr)
+{
+  tree ret;
+  struct md5_ctx ctx;
+  unsigned char checksum_before[16], checksum_after[16];
+  htab_t ht;
+
+  ht = htab_create (32, htab_hash_pointer, htab_eq_pointer, NULL);
+  md5_init_ctx (&ctx);
+  fold_checksum_tree (expr, &ctx, ht);
+  md5_finish_ctx (&ctx, checksum_before);
+  htab_empty (ht);
+
+  ret = fold_1 (expr);
+
+  md5_init_ctx (&ctx);
+  fold_checksum_tree (expr, &ctx, ht);
+  md5_finish_ctx (&ctx, checksum_after);
+  htab_delete (ht);
+
+  if (memcmp (checksum_before, checksum_after, 16))
+    fold_check_failed (expr, ret);
+
+  return ret;
+}
+
+void
+print_fold_checksum (tree expr)
+{
+  struct md5_ctx ctx;
+  unsigned char checksum[16], cnt;
+  htab_t ht;
+
+  ht = htab_create (32, htab_hash_pointer, htab_eq_pointer, NULL);
+  md5_init_ctx (&ctx);
+  fold_checksum_tree (expr, &ctx, ht);
+  md5_finish_ctx (&ctx, checksum);
+  htab_delete (ht);
+  for (cnt = 0; cnt < 16; ++cnt)
+    fprintf (stderr, "%02x", checksum[cnt]);
+  putc ('\n', stderr);
+}
+
+static void
+fold_check_failed (tree expr ATTRIBUTE_UNUSED, tree ret ATTRIBUTE_UNUSED)
+{
+  internal_error ("fold check: original tree changed by fold");
+}
+
+static void
+fold_checksum_tree (tree expr, struct md5_ctx *ctx, htab_t ht)
+{
+  void **slot;
+  enum tree_code code;
+  char buf[sizeof (struct tree_decl)];
+  int i, len;
+
+  if (sizeof (struct tree_exp) + 5 * sizeof (tree)
+      > sizeof (struct tree_decl)
+      || sizeof (struct tree_type) > sizeof (struct tree_decl))
+    abort ();
+  if (expr == NULL)
+    return;
+  slot = htab_find_slot (ht, expr, INSERT);
+  if (*slot != NULL)
+    return;
+  *slot = expr;
+  code = TREE_CODE (expr);
+  if (code == SAVE_EXPR && SAVE_EXPR_NOPLACEHOLDER (expr))
+    {
+      /* Allow SAVE_EXPR_NOPLACEHOLDER flag to be modified.  */
+      memcpy (buf, expr, tree_size (expr));
+      expr = (tree) buf;
+      SAVE_EXPR_NOPLACEHOLDER (expr) = 0;
+    }
+  else if (TREE_CODE_CLASS (code) == 'd' && DECL_ASSEMBLER_NAME_SET_P (expr))
+    {
+      /* Allow DECL_ASSEMBLER_NAME to be modified.  */
+      memcpy (buf, expr, tree_size (expr));
+      expr = (tree) buf;
+      SET_DECL_ASSEMBLER_NAME (expr, NULL);
+    }
+  else if (TREE_CODE_CLASS (code) == 't'
+          && (TYPE_POINTER_TO (expr) || TYPE_REFERENCE_TO (expr)))
+    {
+      /* Allow TYPE_POINTER_TO and TYPE_REFERENCE_TO to be modified.  */
+      memcpy (buf, expr, tree_size (expr));
+      expr = (tree) buf;
+      TYPE_POINTER_TO (expr) = NULL;
+      TYPE_REFERENCE_TO (expr) = NULL;
+    }
+  md5_process_bytes (expr, tree_size (expr), ctx);
+  fold_checksum_tree (TREE_TYPE (expr), ctx, ht);
+  if (TREE_CODE_CLASS (code) != 't' && TREE_CODE_CLASS (code) != 'd')
+    fold_checksum_tree (TREE_CHAIN (expr), ctx, ht);
+  len = TREE_CODE_LENGTH (code);
+  switch (TREE_CODE_CLASS (code))
+    {
+    case 'c':
+      switch (code)
+       {
+       case STRING_CST:
+         md5_process_bytes (TREE_STRING_POINTER (expr),
+                            TREE_STRING_LENGTH (expr), ctx);
+         break;
+       case COMPLEX_CST:
+         fold_checksum_tree (TREE_REALPART (expr), ctx, ht);
+         fold_checksum_tree (TREE_IMAGPART (expr), ctx, ht);
+         break;
+       case VECTOR_CST:
+         fold_checksum_tree (TREE_VECTOR_CST_ELTS (expr), ctx, ht);
+         break;
+       default:
+         break;
+       }
+      break;
+    case 'x':
+      switch (code)
+       {
+       case TREE_LIST:
+         fold_checksum_tree (TREE_PURPOSE (expr), ctx, ht);
+         fold_checksum_tree (TREE_VALUE (expr), ctx, ht);
+         break;
+       case TREE_VEC:
+         for (i = 0; i < TREE_VEC_LENGTH (expr); ++i)
+           fold_checksum_tree (TREE_VEC_ELT (expr, i), ctx, ht);
+         break;
+       default:
+         break;
+       }
+      break;
+    case 'e':
+      switch (code)
+       {
+       case SAVE_EXPR: len = 2; break;
+       case GOTO_SUBROUTINE_EXPR: len = 0; break;
+       case RTL_EXPR: len = 0; break;
+       case WITH_CLEANUP_EXPR: len = 2; break;
+       default: break;
+       }
+      /* FALLTHROUGH */
+    case 'r':
+    case '<':
+    case '1':
+    case '2':
+    case 's':
+      for (i = 0; i < len; ++i)
+       fold_checksum_tree (TREE_OPERAND (expr, i), ctx, ht);
+      break;
+    case 'd':
+      fold_checksum_tree (DECL_SIZE (expr), ctx, ht);
+      fold_checksum_tree (DECL_SIZE_UNIT (expr), ctx, ht);
+      fold_checksum_tree (DECL_NAME (expr), ctx, ht);
+      fold_checksum_tree (DECL_CONTEXT (expr), ctx, ht);
+      fold_checksum_tree (DECL_ARGUMENTS (expr), ctx, ht);
+      fold_checksum_tree (DECL_RESULT_FLD (expr), ctx, ht);
+      fold_checksum_tree (DECL_INITIAL (expr), ctx, ht);
+      fold_checksum_tree (DECL_ABSTRACT_ORIGIN (expr), ctx, ht);
+      fold_checksum_tree (DECL_SECTION_NAME (expr), ctx, ht);
+      fold_checksum_tree (DECL_ATTRIBUTES (expr), ctx, ht);
+      fold_checksum_tree (DECL_VINDEX (expr), ctx, ht);
+      break;
+    case 't':
+      fold_checksum_tree (TYPE_VALUES (expr), ctx, ht);
+      fold_checksum_tree (TYPE_SIZE (expr), ctx, ht);
+      fold_checksum_tree (TYPE_SIZE_UNIT (expr), ctx, ht);
+      fold_checksum_tree (TYPE_ATTRIBUTES (expr), ctx, ht);
+      fold_checksum_tree (TYPE_NAME (expr), ctx, ht);
+      fold_checksum_tree (TYPE_MIN_VALUE (expr), ctx, ht);
+      fold_checksum_tree (TYPE_MAX_VALUE (expr), ctx, ht);
+      fold_checksum_tree (TYPE_MAIN_VARIANT (expr), ctx, ht);
+      fold_checksum_tree (TYPE_BINFO (expr), ctx, ht);
+      fold_checksum_tree (TYPE_CONTEXT (expr), ctx, ht);
+      break;
+    default:
+      break;
+    }
+}
+
+#endif
+
+/* Perform constant folding and related simplification of initializer
+   expression EXPR.  This behaves identically to "fold" but ignores
+   potential run-time traps and exceptions that fold must preserve.  */
+
+tree
+fold_initializer (tree expr)
+{
+  int saved_signaling_nans = flag_signaling_nans;
+  int saved_trapping_math = flag_trapping_math;
+  int saved_trapv = flag_trapv;
+  tree result;
+
+  flag_signaling_nans = 0;
+  flag_trapping_math = 0;
+  flag_trapv = 0;
+
+  result = fold (expr);
+
+  flag_signaling_nans = saved_signaling_nans;
+  flag_trapping_math = saved_trapping_math;
+  flag_trapv = saved_trapv;
+
+  return result;
+}
+
 /* Determine if first argument is a multiple of second argument.  Return 0 if
    it is not, or we cannot easily determined it to be.
 
@@ -7987,18 +8598,8 @@ tree_expr_nonnegative_p (tree t)
   switch (TREE_CODE (t))
     {
     case ABS_EXPR:
-    case FFS_EXPR:
-    case POPCOUNT_EXPR:
-    case PARITY_EXPR:
       return 1;
 
-    case CLZ_EXPR:
-    case CTZ_EXPR:
-      /* These are undefined at zero.  This is true even if
-        C[LT]Z_DEFINED_VALUE_AT_ZERO is set, since what we're
-        computing here is a user-visible property.  */
-      return 0;
-
     case INTEGER_CST:
       return tree_int_cst_sgn (t) >= 0;
 
@@ -8122,58 +8723,75 @@ tree_expr_nonnegative_p (tree t)
       return rtl_expr_nonnegative_p (RTL_EXPR_RTL (t));
 
     case CALL_EXPR:
-      if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR)
-       {
-         tree fndecl = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
-         tree arglist = TREE_OPERAND (t, 1);
-         if (TREE_CODE (fndecl) == FUNCTION_DECL
-             && DECL_BUILT_IN (fndecl)
-             && DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_MD)
-           switch (DECL_FUNCTION_CODE (fndecl))
-             {
-             case BUILT_IN_CABS:
-             case BUILT_IN_CABSL:
-             case BUILT_IN_CABSF:
-             case BUILT_IN_EXP:
-             case BUILT_IN_EXPF:
-             case BUILT_IN_EXPL:
-             case BUILT_IN_FABS:
-             case BUILT_IN_FABSF:
-             case BUILT_IN_FABSL:
-             case BUILT_IN_SQRT:
-             case BUILT_IN_SQRTF:
-             case BUILT_IN_SQRTL:
-               return 1;
-
-             case BUILT_IN_ATAN:
-             case BUILT_IN_ATANF:
-             case BUILT_IN_ATANL:
-             case BUILT_IN_CEIL:
-             case BUILT_IN_CEILF:
-             case BUILT_IN_CEILL:
-             case BUILT_IN_FLOOR:
-             case BUILT_IN_FLOORF:
-             case BUILT_IN_FLOORL:
-             case BUILT_IN_NEARBYINT:
-             case BUILT_IN_NEARBYINTF:
-             case BUILT_IN_NEARBYINTL:
-             case BUILT_IN_ROUND:
-             case BUILT_IN_ROUNDF:
-             case BUILT_IN_ROUNDL:
-             case BUILT_IN_TRUNC:
-             case BUILT_IN_TRUNCF:
-             case BUILT_IN_TRUNCL:
-               return tree_expr_nonnegative_p (TREE_VALUE (arglist));
-
-             case BUILT_IN_POW:
-             case BUILT_IN_POWF:
-             case BUILT_IN_POWL:
-               return tree_expr_nonnegative_p (TREE_VALUE (arglist));
+      {
+       tree fndecl = get_callee_fndecl (t);
+       tree arglist = TREE_OPERAND (t, 1);
+       if (fndecl
+           && DECL_BUILT_IN (fndecl)
+           && DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_MD)
+         switch (DECL_FUNCTION_CODE (fndecl))
+           {
+           case BUILT_IN_CABS:
+           case BUILT_IN_CABSL:
+           case BUILT_IN_CABSF:
+           case BUILT_IN_EXP:
+           case BUILT_IN_EXPF:
+           case BUILT_IN_EXPL:
+           case BUILT_IN_EXP2:
+           case BUILT_IN_EXP2F:
+           case BUILT_IN_EXP2L:
+           case BUILT_IN_EXP10:
+           case BUILT_IN_EXP10F:
+           case BUILT_IN_EXP10L:
+           case BUILT_IN_FABS:
+           case BUILT_IN_FABSF:
+           case BUILT_IN_FABSL:
+           case BUILT_IN_FFS:
+           case BUILT_IN_FFSL:
+           case BUILT_IN_FFSLL:
+           case BUILT_IN_PARITY:
+           case BUILT_IN_PARITYL:
+           case BUILT_IN_PARITYLL:
+           case BUILT_IN_POPCOUNT:
+           case BUILT_IN_POPCOUNTL:
+           case BUILT_IN_POPCOUNTLL:
+           case BUILT_IN_POW10:
+           case BUILT_IN_POW10F:
+           case BUILT_IN_POW10L:
+           case BUILT_IN_SQRT:
+           case BUILT_IN_SQRTF:
+           case BUILT_IN_SQRTL:
+             return 1;
+
+           case BUILT_IN_ATAN:
+           case BUILT_IN_ATANF:
+           case BUILT_IN_ATANL:
+           case BUILT_IN_CEIL:
+           case BUILT_IN_CEILF:
+           case BUILT_IN_CEILL:
+           case BUILT_IN_FLOOR:
+           case BUILT_IN_FLOORF:
+           case BUILT_IN_FLOORL:
+           case BUILT_IN_NEARBYINT:
+           case BUILT_IN_NEARBYINTF:
+           case BUILT_IN_NEARBYINTL:
+           case BUILT_IN_ROUND:
+           case BUILT_IN_ROUNDF:
+           case BUILT_IN_ROUNDL:
+           case BUILT_IN_TRUNC:
+           case BUILT_IN_TRUNCF:
+           case BUILT_IN_TRUNCL:
+             return tree_expr_nonnegative_p (TREE_VALUE (arglist));
+
+           case BUILT_IN_POW:
+           case BUILT_IN_POWF:
+           case BUILT_IN_POWL:
+             return tree_expr_nonnegative_p (TREE_VALUE (arglist));
 
-             default:
-               break;
-             }
-       }
+           default:
+             break;
+           }
+      }
 
       /* ... fall through ...  */