OSDN Git Service

* config/arm/arm.c, config/arm/arm.h, config/arm/arm.md,
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index aea392f..de72a76 100644 (file)
@@ -1,6 +1,6 @@
 /* Fold a constant sub-tree into a single node for C-compiler
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -60,6 +60,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 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);
@@ -68,7 +69,7 @@ static tree int_const_binop (enum tree_code, tree, tree, int);
 static tree const_binop (enum tree_code, tree, tree, int);
 static hashval_t size_htab_hash (const void *);
 static int size_htab_eq (const void *, const void *);
-static tree fold_convert (tree, tree);
+static tree fold_convert_const (enum tree_code, tree, tree);
 static enum tree_code invert_tree_comparison (enum tree_code);
 static enum tree_code swap_tree_comparison (enum tree_code);
 static int comparison_to_compcode (enum tree_code);
@@ -108,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
@@ -558,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)
@@ -795,13 +798,42 @@ div_and_round_double (enum tree_code code, int uns,
       abort ();
     }
 
-  /* compute true remainder:  rem = num - (quo * den)  */
+  /* Compute true remainder:  rem = num - (quo * den)  */
   mul_double (*lquo, *hquo, lden_orig, hden_orig, lrem, hrem);
   neg_double (*lrem, *hrem, lrem, hrem);
   add_double (lnum_orig, hnum_orig, *lrem, *hrem, lrem, hrem);
   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.  */
 
@@ -821,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);
@@ -841,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;
     }
@@ -868,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;
     }
@@ -1063,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:
@@ -1510,14 +1657,17 @@ size_diffop (tree arg0, tree arg1)
 }
 \f
 
-/* Given T, a tree representing type conversion of ARG1, a constant,
-   return a constant tree representing the result of conversion.  */
+/* Attempt to fold type conversion operation CODE of expression ARG1 to
+   type TYPE.  If no simplification can be done return NULL_TREE.  */
 
 static tree
-fold_convert (tree t, tree arg1)
+fold_convert_const (enum tree_code code, tree type, tree arg1)
 {
-  tree type = TREE_TYPE (t);
   int overflow = 0;
+  tree t;
+
+  if (TREE_TYPE (arg1) == type)
+    return arg1;
 
   if (POINTER_TYPE_P (type) || INTEGRAL_TYPE_P (type))
     {
@@ -1526,7 +1676,7 @@ fold_convert (tree t, tree arg1)
          /* If we would build a constant wider than GCC supports,
             leave the conversion unfolded.  */
          if (TYPE_PRECISION (type) > 2 * HOST_BITS_PER_WIDE_INT)
-           return t;
+           return NULL_TREE;
 
          /* If we are trying to make a sizetype for a small integer, use
             size_int to pick up cached types to reduce duplicate nodes.  */
@@ -1554,51 +1704,91 @@ fold_convert (tree t, tree arg1)
               || TREE_OVERFLOW (arg1));
          TREE_CONSTANT_OVERFLOW (t)
            = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
+         return t;
        }
       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));
-
-         /* 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;
+         /* 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 low, high;
-           REAL_VALUE_TO_INT (&low, &high, x);
-           t = build_int_2 (low, high);
-         }
+         HOST_WIDE_INT high, low;
+
+         REAL_VALUE_TYPE r;
+         REAL_VALUE_TYPE x = TREE_REAL_CST (arg1);
+
+         switch (code)
+           {
+           case FIX_TRUNC_EXPR:
+             real_trunc (&r, VOIDmode, &x);
+             break;
+
+           case FIX_CEIL_EXPR:
+             real_ceil (&r, VOIDmode, &x);
+             break;
+
+           case FIX_FLOOR_EXPR:
+             real_floor (&r, VOIDmode, &x);
+             break;
+
+           default:
+             abort ();
+           }
+
+         /* If R is NaN, return zero and show we have an overflow.  */
+         if (REAL_VALUE_ISNAN (r))
+           {
+             overflow = 1;
+             high = 0;
+             low = 0;
+           }
+
+         /* See if R is less than the lower bound or greater than the
+            upper bound.  */
+
+         if (! overflow)
+           {
+             tree lt = TYPE_MIN_VALUE (type);
+             REAL_VALUE_TYPE l = real_value_from_int_cst (NULL_TREE, lt);
+             if (REAL_VALUES_LESS (r, l))
+               {
+                 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);
+                 if (REAL_VALUES_LESS (u, r))
+                   {
+                     overflow = 1;
+                     high = TREE_INT_CST_HIGH (ut);
+                     low = TREE_INT_CST_LOW (ut);
+                   }
+               }
+           }
+
+         if (! overflow)
+           REAL_VALUE_TO_INT (&low, &high, r);
+
+         t = build_int_2 (low, high);
          TREE_TYPE (t) = type;
          TREE_OVERFLOW (t)
            = TREE_OVERFLOW (arg1) | force_fit_type (t, overflow);
          TREE_CONSTANT_OVERFLOW (t)
            = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
+         return t;
        }
-      TREE_TYPE (t) = type;
     }
   else if (TREE_CODE (type) == REAL_TYPE)
     {
@@ -1626,8 +1816,7 @@ fold_convert (tree t, tree arg1)
          return t;
        }
     }
-  TREE_CONSTANT (t) = 1;
-  return t;
+  return NULL_TREE;
 }
 \f
 /* Return an expr equal to X but certainly not valid as an lvalue.  */
@@ -1781,17 +1970,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.  */
@@ -1962,13 +2167,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
@@ -3022,10 +3223,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,
@@ -4252,8 +4453,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
@@ -4545,7 +4749,7 @@ fold_binary_op_with_conditional_arg (enum tree_code code, tree type,
        {
          arg = save_expr (arg);
          lhs = rhs = 0;
-         save = 1;
+         save = saved_expr_p (arg);
        }
     }
 
@@ -4556,6 +4760,12 @@ fold_binary_op_with_conditional_arg (enum tree_code code, tree type,
 
   test = fold (build (COND_EXPR, type, test, lhs, rhs));
 
+  /* If ARG involves a SAVE_EXPR, we need to ensure it is evaluated
+     ahead of the COND_EXPR we made.  Otherwise we would have it only
+     evaluated in one branch, with the other branch using the result
+     but missing the evaluation code.  Beware that the save_expr call
+     above might not return a SAVE_EXPR, so testing the TREE_CODE
+     of ARG is not enough to decide here. Â */
   if (save)
     return build (COMPOUND_EXPR, type,
                  convert (void_type_node, arg),
@@ -4855,7 +5065,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
@@ -4901,28 +5111,89 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
 
       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.  */
-      inner = build (BIT_AND_EXPR, ops_unsigned ? unsigned_type : signed_type,
+      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.
@@ -4960,9 +5231,6 @@ fold (tree expr)
   if (kind == 'c')
     return t;
 
-#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)
@@ -4982,14 +5250,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;
@@ -5035,16 +5302,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 (arg1) != INTEGER_CST)
-         || (TREE_CODE (arg0) == REAL_CST && TREE_CODE (arg1) != REAL_CST)))
-    {
-      tem = arg0; arg0 = arg1; arg1 = tem;
-
-      if (t == orig_t)
-       t = copy_node (t);
-      TREE_OPERAND (t, 0) = arg0;
-      TREE_OPERAND (t, 1) = arg1;
-    }
+      && 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,
@@ -5199,8 +5458,8 @@ fold (tree expr)
     case FLOAT_EXPR:
     case CONVERT_EXPR:
     case FIX_TRUNC_EXPR:
-      /* Other kinds of FIX are not handled properly by fold_convert.  */
-
+    case FIX_CEIL_EXPR:
+    case FIX_FLOOR_EXPR:
       if (TREE_TYPE (TREE_OPERAND (t, 0)) == TREE_TYPE (t))
        return TREE_OPERAND (t, 0);
 
@@ -5344,17 +5603,8 @@ fold (tree expr)
                                convert (TREE_TYPE (t), and1)));
        }
 
-      if (!wins)
-       {
-         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);
+      tem = fold_convert_const (code, TREE_TYPE (t), arg0);
+      return tem ? tem : t;
 
     case VIEW_CONVERT_EXPR:
       if (TREE_CODE (TREE_OPERAND (t, 0)) == VIEW_CONVERT_EXPR)
@@ -5382,71 +5632,8 @@ fold (tree expr)
       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)
-       {
-         tree targ0 = strip_float_extensions (arg0);
-         if (targ0 != arg0)
-           return convert (type, build1 (NEGATE_EXPR, TREE_TYPE (targ0), targ0));
-
-       }
-
-      /* 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;
-       }
+      if (negate_expr_p (arg0))
+       return negate_expr (arg0);
       return t;
 
     case ABS_EXPR:
@@ -5659,14 +5846,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
@@ -5742,13 +5988,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;
@@ -5785,7 +6029,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);
@@ -5840,8 +6086,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)));
 
@@ -5880,6 +6125,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.  */
@@ -5906,8 +6170,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))
@@ -5954,13 +6223,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)
@@ -5989,10 +6262,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,
@@ -6071,6 +6354,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;
@@ -6131,7 +6488,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))
@@ -6169,19 +6525,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.  */
@@ -6191,8 +6534,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.  */
@@ -6200,6 +6548,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
@@ -6212,7 +6565,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);
@@ -6226,28 +6579,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,
@@ -6328,6 +6700,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;
 
@@ -6401,18 +6797,10 @@ fold (tree expr)
         RROTATE_EXPR by a new constant.  */
       if (code == LROTATE_EXPR && TREE_CODE (arg1) == INTEGER_CST)
        {
-         if (t == orig_t)
-           t = copy_node (t);
-         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
@@ -6420,7 +6808,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)
@@ -6610,20 +6997,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))
-       {
-         if (t == orig_t)
-           t = copy_node (t);
-         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)))
        {
@@ -6880,16 +7255,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;
@@ -6932,24 +7303,17 @@ fold (tree expr)
                                           convert (type, integer_zero_node),
                                           arg0);
                case GE_EXPR:
-                 code = EQ_EXPR;
-                 if (t == orig_t)
-                   t = copy_node (t);
-                 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;
-                 if (t == orig_t)
-                   t = copy_node (t);
-                 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;
@@ -6959,15 +7323,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;
                }
@@ -6980,22 +7340,14 @@ fold (tree expr)
                                           convert (type, integer_zero_node),
                                           arg0);
                case LE_EXPR:
-                 code = EQ_EXPR;
-                 if (t == orig_t)
-                   t = copy_node (t);
-                 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;
-                 if (t == orig_t)
-                   t = copy_node (t);
-                 TREE_SET_CODE (t, NE_EXPR);
-                 break;
+                 return fold (build (NE_EXPR, type, arg0, arg1));
 
                default:
                  break;
@@ -7005,15 +7357,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;
                }
@@ -7189,10 +7537,13 @@ fold (tree expr)
          && TREE_CODE (arg1) == INTEGER_CST
          && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
        {
-         tree dandnotc = fold (build (BIT_ANDTC_EXPR, TREE_TYPE (arg0),
-                                      arg1, TREE_OPERAND (arg0, 1)));
+         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_zerop (dandnotc))
+         if (integer_nonzerop (dandnotc))
            return omit_one_operand (type, rslt, arg0);
        }
 
@@ -7203,10 +7554,12 @@ fold (tree expr)
          && TREE_CODE (arg1) == INTEGER_CST
          && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
        {
-         tree candnotd = fold (build (BIT_ANDTC_EXPR, TREE_TYPE (arg0),
-                                      TREE_OPERAND (arg0, 1), arg1));
+         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_zerop (candnotd))
+         if (integer_nonzerop (candnotd))
            return omit_one_operand (type, rslt, arg0);
        }
 
@@ -7241,16 +7594,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;
-             if (t == orig_t)
-               t = copy_node (t);
-             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
@@ -7378,7 +7732,8 @@ fold (tree expr)
          && (optimize || TREE_CODE (arg1) == INTEGER_CST))
        {
          t1 = optimize_bit_field_compare (code, type, arg0, arg1);
-         return t1 ? t1 : t;
+         if (t1)
+           return t1;
        }
 
       /* If this is a comparison of complex values and either or both sides
@@ -7417,13 +7772,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
@@ -7527,38 +7881,18 @@ fold (tree expr)
       /* Pedantic ANSI C says that a conditional expression is never an lvalue,
         so all simple results must be passed through pedantic_non_lvalue.  */
       if (TREE_CODE (arg0) == INTEGER_CST)
-       return pedantic_non_lvalue
-         (TREE_OPERAND (t, (integer_zerop (arg0) ? 2 : 1)));
-      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);
-           }
+         tem = TREE_OPERAND (t, (integer_zerop (arg0) ? 2 : 1));
+         /* Only optimize constant conditions when the selected branch
+            has the same type as the COND_EXPR.  This avoids optimizing
+            away "c ? x : throw", where the throw has a void type.  */
+         if (! VOID_TYPE_P (TREE_TYPE (tem))
+             || VOID_TYPE_P (TREE_TYPE (t)))
+           return pedantic_non_lvalue (tem);
+         return t;
        }
+      if (operand_equal_p (arg1, TREE_OPERAND (expr, 2), 0))
+       return pedantic_omit_one_operand (type, arg1, arg0);
 
       /* 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
@@ -7735,9 +8069,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).  */
@@ -7787,11 +8120,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
@@ -7799,14 +8129,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.  */
@@ -7863,12 +8187,12 @@ fold (tree expr)
     case COMPOUND_EXPR:
       /* When pedantic, a compound expression can be neither an lvalue
         nor an integer constant expression.  */
-      if (TREE_SIDE_EFFECTS (arg0) || pedantic)
+      if (TREE_SIDE_EFFECTS (arg0) || TREE_CONSTANT (arg1))
        return t;
       /* Don't let (0, 0) be null pointer constant.  */
       if (integer_zerop (arg1))
-       return build1 (NOP_EXPR, type, arg1);
-      return convert (type, arg1);
+       return pedantic_non_lvalue (build1 (NOP_EXPR, type, arg1));
+      return pedantic_non_lvalue (convert (type, arg1));
 
     case COMPLEX_EXPR:
       if (wins)
@@ -8118,7 +8442,7 @@ fold_checksum_tree (tree expr, struct md5_ctx *ctx, htab_t ht)
        case WITH_CLEANUP_EXPR: len = 2; break;
        default: break;
        }
-      /* FALLTHROUGH */
+      /* Fall through.  */
     case 'r':
     case '<':
     case '1':
@@ -8159,7 +8483,7 @@ fold_checksum_tree (tree expr, struct md5_ctx *ctx, htab_t ht)
 
 #endif
 
-/* Perform constant folding and related simplification of intializer
+/* 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.  */
 
@@ -8297,18 +8621,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;
 
@@ -8432,58 +8746,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 ...  */