OSDN Git Service

* typeck.c (build_x_unary_op): Take note of the fact that
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index 726e845..e268055 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, 2002,
-   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -57,60 +57,56 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "hashtab.h"
 #include "langhooks.h"
 
-static void encode             PARAMS ((HOST_WIDE_INT *,
-                                        unsigned HOST_WIDE_INT,
-                                        HOST_WIDE_INT));
-static void decode             PARAMS ((HOST_WIDE_INT *,
-                                        unsigned HOST_WIDE_INT *,
-                                        HOST_WIDE_INT *));
-static tree negate_expr                PARAMS ((tree));
-static tree split_tree         PARAMS ((tree, enum tree_code, tree *, tree *,
-                                        tree *, int));
-static tree associate_trees    PARAMS ((tree, tree, enum tree_code, tree));
-static tree int_const_binop    PARAMS ((enum tree_code, tree, tree, int));
-static tree const_binop                PARAMS ((enum tree_code, tree, tree, int));
-static hashval_t size_htab_hash        PARAMS ((const void *));
-static int size_htab_eq                PARAMS ((const void *, const void *));
-static tree fold_convert       PARAMS ((tree, tree));
-static enum tree_code invert_tree_comparison PARAMS ((enum tree_code));
-static enum tree_code swap_tree_comparison PARAMS ((enum tree_code));
-static int comparison_to_compcode PARAMS ((enum tree_code));
-static enum tree_code compcode_to_comparison PARAMS ((int));
-static int truth_value_p       PARAMS ((enum tree_code));
-static int operand_equal_for_comparison_p PARAMS ((tree, tree, tree));
-static int twoval_comparison_p PARAMS ((tree, tree *, tree *, int *));
-static tree eval_subst         PARAMS ((tree, tree, tree, tree, tree));
-static tree omit_one_operand   PARAMS ((tree, tree, tree));
-static tree pedantic_omit_one_operand PARAMS ((tree, tree, tree));
-static tree distribute_bit_expr PARAMS ((enum tree_code, tree, tree, tree));
-static tree make_bit_field_ref PARAMS ((tree, tree, int, int, int));
-static tree optimize_bit_field_compare PARAMS ((enum tree_code, tree,
-                                               tree, tree));
-static tree decode_field_reference PARAMS ((tree, HOST_WIDE_INT *,
-                                           HOST_WIDE_INT *,
-                                           enum machine_mode *, int *,
-                                           int *, tree *, tree *));
-static int all_ones_mask_p     PARAMS ((tree, int));
-static tree sign_bit_p         PARAMS ((tree, tree));
-static int simple_operand_p    PARAMS ((tree));
-static tree range_binop                PARAMS ((enum tree_code, tree, tree, int,
-                                        tree, int));
-static tree make_range         PARAMS ((tree, int *, tree *, tree *));
-static tree build_range_check  PARAMS ((tree, tree, int, tree, tree));
-static int merge_ranges                PARAMS ((int *, tree *, tree *, int, tree, tree,
-                                      int, tree, tree));
-static tree fold_range_test    PARAMS ((tree));
-static tree unextend           PARAMS ((tree, int, int, tree));
-static tree fold_truthop       PARAMS ((enum tree_code, tree, tree, tree));
-static tree optimize_minmax_comparison PARAMS ((tree));
-static tree extract_muldiv     PARAMS ((tree, tree, enum tree_code, tree));
-static tree strip_compound_expr PARAMS ((tree, tree));
-static int multiple_of_p       PARAMS ((tree, tree, tree));
-static tree constant_boolean_node PARAMS ((int, tree));
-static int count_cond          PARAMS ((tree, int));
-static tree fold_binary_op_with_conditional_arg
-  PARAMS ((enum tree_code, tree, tree, tree, int));
-static bool fold_real_zero_addition_p  PARAMS ((tree, tree, int));
+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_expr_p (tree);
+static tree negate_expr (tree);
+static tree split_tree (tree, enum tree_code, tree *, tree *, tree *, int);
+static tree associate_trees (tree, tree, enum tree_code, tree);
+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 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);
+static enum tree_code compcode_to_comparison (int);
+static int truth_value_p (enum tree_code);
+static int operand_equal_for_comparison_p (tree, tree, tree);
+static int twoval_comparison_p (tree, tree *, tree *, int *);
+static tree eval_subst (tree, tree, tree, tree, tree);
+static tree pedantic_omit_one_operand (tree, tree, tree);
+static tree distribute_bit_expr (enum tree_code, tree, tree, tree);
+static tree make_bit_field_ref (tree, tree, int, int, int);
+static tree optimize_bit_field_compare (enum tree_code, tree, tree, tree);
+static tree decode_field_reference (tree, HOST_WIDE_INT *, HOST_WIDE_INT *,
+                                   enum machine_mode *, int *, int *,
+                                   tree *, tree *);
+static int all_ones_mask_p (tree, int);
+static tree sign_bit_p (tree, tree);
+static int simple_operand_p (tree);
+static tree range_binop (enum tree_code, tree, tree, int, tree, int);
+static tree make_range (tree, int *, tree *, tree *);
+static tree build_range_check (tree, tree, int, tree, tree);
+static int merge_ranges (int *, tree *, tree *, int, tree, tree, int, tree,
+                        tree);
+static tree fold_range_test (tree);
+static tree unextend (tree, int, int, tree);
+static tree fold_truthop (enum tree_code, tree, tree, tree);
+static tree optimize_minmax_comparison (tree);
+static tree extract_muldiv (tree, tree, enum tree_code, tree);
+static tree extract_muldiv_1 (tree, tree, enum tree_code, tree);
+static tree strip_compound_expr (tree, tree);
+static int multiple_of_p (tree, tree, tree);
+static tree constant_boolean_node (int, tree);
+static int count_cond (tree, int);
+static tree fold_binary_op_with_conditional_arg (enum tree_code, tree, tree,
+                                                tree, int);
+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);
 
 /* The following constants represent a bit based encoding of GCC's
    comparison operators.  This encoding simplifies transformations
@@ -150,10 +146,7 @@ static bool fold_real_zero_addition_p      PARAMS ((tree, tree, int));
    WORDS points to the array of HOST_WIDE_INTs.  */
 
 static void
-encode (words, low, hi)
-     HOST_WIDE_INT *words;
-     unsigned HOST_WIDE_INT low;
-     HOST_WIDE_INT hi;
+encode (HOST_WIDE_INT *words, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi)
 {
   words[0] = LOWPART (low);
   words[1] = HIGHPART (low);
@@ -166,10 +159,7 @@ encode (words, low, hi)
    The integer is stored into *LOW and *HI as two `HOST_WIDE_INT' pieces.  */
 
 static void
-decode (words, low, hi)
-     HOST_WIDE_INT *words;
-     unsigned HOST_WIDE_INT *low;
-     HOST_WIDE_INT *hi;
+decode (HOST_WIDE_INT *words, unsigned HOST_WIDE_INT *low, HOST_WIDE_INT *hi)
 {
   *low = words[0] + words[1] * BASE;
   *hi = words[2] + words[3] * BASE;
@@ -183,9 +173,7 @@ decode (words, low, hi)
    propagate it.  */
 
 int
-force_fit_type (t, overflow)
-     tree t;
-     int overflow;
+force_fit_type (tree t, int overflow)
 {
   unsigned HOST_WIDE_INT low;
   HOST_WIDE_INT high;
@@ -264,11 +252,8 @@ force_fit_type (t, overflow)
    The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV.  */
 
 int
-add_double (l1, h1, l2, h2, lv, hv)
-     unsigned HOST_WIDE_INT l1, l2;
-     HOST_WIDE_INT h1, h2;
-     unsigned HOST_WIDE_INT *lv;
-     HOST_WIDE_INT *hv;
+add_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, unsigned HOST_WIDE_INT l2,
+           HOST_WIDE_INT h2, unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv)
 {
   unsigned HOST_WIDE_INT l;
   HOST_WIDE_INT h;
@@ -287,11 +272,8 @@ add_double (l1, h1, l2, h2, lv, hv)
    The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV.  */
 
 int
-neg_double (l1, h1, lv, hv)
-     unsigned HOST_WIDE_INT l1;
-     HOST_WIDE_INT h1;
-     unsigned HOST_WIDE_INT *lv;
-     HOST_WIDE_INT *hv;
+neg_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, unsigned HOST_WIDE_INT *lv,
+           HOST_WIDE_INT *hv)
 {
   if (l1 == 0)
     {
@@ -314,11 +296,8 @@ neg_double (l1, h1, lv, hv)
    The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV.  */
 
 int
-mul_double (l1, h1, l2, h2, lv, hv)
-     unsigned HOST_WIDE_INT l1, l2;
-     HOST_WIDE_INT h1, h2;
-     unsigned HOST_WIDE_INT *lv;
-     HOST_WIDE_INT *hv;
+mul_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, unsigned HOST_WIDE_INT l2,
+           HOST_WIDE_INT h2, unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv)
 {
   HOST_WIDE_INT arg1[4];
   HOST_WIDE_INT arg2[4];
@@ -374,13 +353,9 @@ mul_double (l1, h1, l2, h2, lv, hv)
    Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV.  */
 
 void
-lshift_double (l1, h1, count, prec, lv, hv, arith)
-     unsigned HOST_WIDE_INT l1;
-     HOST_WIDE_INT h1, count;
-     unsigned int prec;
-     unsigned HOST_WIDE_INT *lv;
-     HOST_WIDE_INT *hv;
-     int arith;
+lshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, HOST_WIDE_INT count,
+              unsigned int prec, unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv,
+              int arith)
 {
   unsigned HOST_WIDE_INT signmask;
 
@@ -442,13 +417,9 @@ lshift_double (l1, h1, count, prec, lv, hv, arith)
    Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV.  */
 
 void
-rshift_double (l1, h1, count, prec, lv, hv, arith)
-     unsigned HOST_WIDE_INT l1;
-     HOST_WIDE_INT h1, count;
-     unsigned int prec;
-     unsigned HOST_WIDE_INT *lv;
-     HOST_WIDE_INT *hv;
-     int arith;
+rshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, HOST_WIDE_INT count,
+              unsigned int prec, unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv,
+              int arith)
 {
   unsigned HOST_WIDE_INT signmask;
 
@@ -508,12 +479,8 @@ rshift_double (l1, h1, count, prec, lv, hv, arith)
    Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV.  */
 
 void
-lrotate_double (l1, h1, count, prec, lv, hv)
-     unsigned HOST_WIDE_INT l1;
-     HOST_WIDE_INT h1, count;
-     unsigned int prec;
-     unsigned HOST_WIDE_INT *lv;
-     HOST_WIDE_INT *hv;
+lrotate_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, HOST_WIDE_INT count,
+               unsigned int prec, unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv)
 {
   unsigned HOST_WIDE_INT s1l, s2l;
   HOST_WIDE_INT s1h, s2h;
@@ -533,12 +500,8 @@ lrotate_double (l1, h1, count, prec, lv, hv)
    Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV.  */
 
 void
-rrotate_double (l1, h1, count, prec, lv, hv)
-     unsigned HOST_WIDE_INT l1;
-     HOST_WIDE_INT h1, count;
-     unsigned int prec;
-     unsigned HOST_WIDE_INT *lv;
-     HOST_WIDE_INT *hv;
+rrotate_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, HOST_WIDE_INT count,
+               unsigned int prec, unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv)
 {
   unsigned HOST_WIDE_INT s1l, s2l;
   HOST_WIDE_INT s1h, s2h;
@@ -563,17 +526,13 @@ rrotate_double (l1, h1, count, prec, lv, hv)
    UNS nonzero says do unsigned division.  */
 
 int
-div_and_round_double (code, uns,
-                     lnum_orig, hnum_orig, lden_orig, hden_orig,
-                     lquo, hquo, lrem, hrem)
-     enum tree_code code;
-     int uns;
-     unsigned HOST_WIDE_INT lnum_orig; /* num == numerator == dividend */
-     HOST_WIDE_INT hnum_orig;
-     unsigned HOST_WIDE_INT lden_orig; /* den == denominator == divisor */
-     HOST_WIDE_INT hden_orig;
-     unsigned HOST_WIDE_INT *lquo, *lrem;
-     HOST_WIDE_INT *hquo, *hrem;
+div_and_round_double (enum tree_code code, int uns,
+                     unsigned HOST_WIDE_INT lnum_orig, /* num == numerator == dividend */
+                     HOST_WIDE_INT hnum_orig,
+                     unsigned HOST_WIDE_INT lden_orig, /* den == denominator == divisor */
+                     HOST_WIDE_INT hden_orig, unsigned HOST_WIDE_INT *lquo,
+                     HOST_WIDE_INT *hquo, unsigned HOST_WIDE_INT *lrem,
+                     HOST_WIDE_INT *hrem)
 {
   int quo_neg = 0;
   HOST_WIDE_INT num[4 + 1];    /* extra element for scaling.  */
@@ -793,7 +752,7 @@ div_and_round_double (code, uns,
        unsigned HOST_WIDE_INT labs_den = lden, ltwice;
        HOST_WIDE_INT habs_den = hden, htwice;
 
-       /* Get absolute values */
+       /* Get absolute values */
        if (*hrem < 0)
          neg_double (*lrem, *hrem, &labs_rem, &habs_rem);
        if (hden < 0)
@@ -834,12 +793,59 @@ div_and_round_double (code, uns,
   return overflow;
 }
 \f
+/* Determine whether an expression T can be cheaply negated using
+   the function negate_expr.  */
+
+static bool
+negate_expr_p (tree t)
+{
+  unsigned HOST_WIDE_INT val;
+  unsigned int prec;
+  tree type;
+
+  if (t == 0)
+    return false;
+
+  type = TREE_TYPE (t);
+
+  STRIP_SIGN_NOPS (t);
+  switch (TREE_CODE (t))
+    {
+    case INTEGER_CST:
+      if (TREE_UNSIGNED (type))
+       return false;
+
+      /* Check that -CST will not overflow type.  */
+      prec = TYPE_PRECISION (type);
+      if (prec > HOST_BITS_PER_WIDE_INT)
+       {
+         if (TREE_INT_CST_LOW (t) != 0)
+           return true;
+         prec -= HOST_BITS_PER_WIDE_INT;
+         val = TREE_INT_CST_HIGH (t);
+       }
+      else
+       val = TREE_INT_CST_LOW (t);
+      if (prec < HOST_BITS_PER_WIDE_INT)
+       val &= ((unsigned HOST_WIDE_INT) 1 << prec) - 1;
+      return val != ((unsigned HOST_WIDE_INT) 1 << (prec - 1));
+
+    case REAL_CST:
+    case NEGATE_EXPR:
+    case MINUS_EXPR:
+      return true;
+
+    default:
+      break;
+    }
+  return false;
+}
+
 /* Given T, an expression, return the negation of T.  Allow for T to be
    null, in which case return null.  */
 
 static tree
-negate_expr (t)
-     tree t;
+negate_expr (tree t)
 {
   tree type;
   tree tem;
@@ -900,11 +906,7 @@ negate_expr (t)
    same type as IN, but they will have the same signedness and mode.  */
 
 static tree
-split_tree (in, code, conp, litp, minus_litp, negate_p)
-     tree in;
-     enum tree_code code;
-     tree *conp, *litp, *minus_litp;
-     int negate_p;
+split_tree (tree in, enum tree_code code, tree *conp, tree *litp, tree *minus_litp, int negate_p)
 {
   tree var = 0;
 
@@ -982,10 +984,7 @@ split_tree (in, code, conp, litp, minus_litp, negate_p)
    we build an operation, do it in TYPE and with CODE.  */
 
 static tree
-associate_trees (t1, t2, code, type)
-     tree t1, t2;
-     enum tree_code code;
-     tree type;
+associate_trees (tree t1, tree t2, enum tree_code code, tree type)
 {
   if (t1 == 0)
     return t2;
@@ -1019,10 +1018,7 @@ associate_trees (t1, t2, code, type)
    If NOTRUNC is nonzero, do not truncate the result to fit the data type.  */
 
 static tree
-int_const_binop (code, arg1, arg2, notrunc)
-     enum tree_code code;
-     tree arg1, arg2;
-     int notrunc;
+int_const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
 {
   unsigned HOST_WIDE_INT int1l, int2l;
   HOST_WIDE_INT int1h, int2h;
@@ -1214,10 +1210,7 @@ int_const_binop (code, arg1, arg2, notrunc)
    If NOTRUNC is nonzero, do not truncate the result to fit the data type.  */
 
 static tree
-const_binop (code, arg1, arg2, notrunc)
-     enum tree_code code;
-     tree arg1, arg2;
-     int notrunc;
+const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
 {
   STRIP_NOPS (arg1);
   STRIP_NOPS (arg2);
@@ -1342,8 +1335,7 @@ const_binop (code, arg1, arg2, notrunc)
 /* Return the hash code code X, an INTEGER_CST.  */
 
 static hashval_t
-size_htab_hash (x)
-     const void *x;
+size_htab_hash (const void *x)
 {
   tree t = (tree) x;
 
@@ -1356,9 +1348,7 @@ size_htab_hash (x)
    is the same as that given by *Y, which is the same.  */
 
 static int
-size_htab_eq (x, y)
-     const void *x;
-     const void *y;
+size_htab_eq (const void *x, const void *y)
 {
   tree xt = (tree) x;
   tree yt = (tree) y;
@@ -1373,9 +1363,7 @@ size_htab_eq (x, y)
    bits are given by NUMBER and of the sizetype represented by KIND.  */
 
 tree
-size_int_wide (number, kind)
-     HOST_WIDE_INT number;
-     enum size_type_kind kind;
+size_int_wide (HOST_WIDE_INT number, enum size_type_kind kind)
 {
   return size_int_type_wide (number, sizetype_tab[(int) kind]);
 }
@@ -1387,11 +1375,9 @@ static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
      htab_t size_htab;
 
 tree
-size_int_type_wide (number, type)
-     HOST_WIDE_INT number;
-     tree type;
+size_int_type_wide (HOST_WIDE_INT number, tree type)
 {
-  PTR *slot;
+  void **slot;
 
   if (size_htab == 0)
     {
@@ -1413,7 +1399,7 @@ size_int_type_wide (number, type)
     {
       tree t = new_const;
 
-      *slot = (PTR) new_const;
+      *slot = new_const;
       new_const = make_node (INTEGER_CST);
       return t;
     }
@@ -1427,9 +1413,7 @@ size_int_type_wide (number, type)
    If the operands are constant, so is the result.  */
 
 tree
-size_binop (code, arg0, arg1)
-     enum tree_code code;
-     tree arg0, arg1;
+size_binop (enum tree_code code, tree arg0, tree arg1)
 {
   tree type = TREE_TYPE (arg0);
 
@@ -1464,8 +1448,7 @@ size_binop (code, arg0, arg1)
    in signed type corresponding to the type of the operands.  */
 
 tree
-size_diffop (arg0, arg1)
-     tree arg0, arg1;
+size_diffop (tree arg0, tree arg1)
 {
   tree type = TREE_TYPE (arg0);
   tree ctype;
@@ -1506,9 +1489,7 @@ size_diffop (arg0, arg1)
    return a constant tree representing the result of conversion.  */
 
 static tree
-fold_convert (t, arg1)
-     tree t;
-     tree arg1;
+fold_convert (tree t, tree arg1)
 {
   tree type = TREE_TYPE (t);
   int overflow = 0;
@@ -1627,8 +1608,7 @@ fold_convert (t, arg1)
 /* Return an expr equal to X but certainly not valid as an lvalue.  */
 
 tree
-non_lvalue (x)
-     tree x;
+non_lvalue (tree x)
 {
   tree result;
 
@@ -1654,8 +1634,7 @@ int pedantic_lvalues;
    pedantic lvalue.  Otherwise, return X.  */
 
 tree
-pedantic_non_lvalue (x)
-     tree x;
+pedantic_non_lvalue (tree x)
 {
   if (pedantic_lvalues)
     return non_lvalue (x);
@@ -1668,8 +1647,7 @@ pedantic_non_lvalue (x)
    comparisons, except for NE_EXPR and EQ_EXPR.  */
 
 static enum tree_code
-invert_tree_comparison (code)
-     enum tree_code code;
+invert_tree_comparison (enum tree_code code)
 {
   switch (code)
     {
@@ -1694,8 +1672,7 @@ invert_tree_comparison (code)
    swapped.  This is safe for floating-point.  */
 
 static enum tree_code
-swap_tree_comparison (code)
-     enum tree_code code;
+swap_tree_comparison (enum tree_code code)
 {
   switch (code)
     {
@@ -1721,8 +1698,7 @@ swap_tree_comparison (code)
    compcode_to_comparison.  */
 
 static int
-comparison_to_compcode (code)
-     enum tree_code code;
+comparison_to_compcode (enum tree_code code)
 {
   switch (code)
     {
@@ -1748,8 +1724,7 @@ comparison_to_compcode (code)
    inverse of comparison_to_compcode.  */
 
 static enum tree_code
-compcode_to_comparison (code)
-     int code;
+compcode_to_comparison (int code)
 {
   switch (code)
     {
@@ -1773,8 +1748,7 @@ compcode_to_comparison (code)
 /* Return nonzero if CODE is a tree code that represents a truth value.  */
 
 static int
-truth_value_p (code)
-     enum tree_code code;
+truth_value_p (enum tree_code code)
 {
   return (TREE_CODE_CLASS (code) == '<'
          || code == TRUTH_AND_EXPR || code == TRUTH_ANDIF_EXPR
@@ -1791,9 +1765,7 @@ truth_value_p (code)
    (2) two NaNs may be indistinguishable, but NaN!=NaN.  */
 
 int
-operand_equal_p (arg0, arg1, only_const)
-     tree arg0, arg1;
-     int only_const;
+operand_equal_p (tree arg0, tree arg1, int only_const)
 {
   /* 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
@@ -1915,8 +1887,8 @@ operand_equal_p (arg0, arg1, only_const)
                                  TREE_OPERAND (arg1, 0), 0));
 
     case 'r':
-      /* If either of the pointer (or reference) expressions we are dereferencing
-        contain a side effect, these cannot be equal.  */
+      /* If either of the pointer (or reference) expressions we are
+        dereferencing contain a side effect, these cannot be equal.  */
       if (TREE_SIDE_EFFECTS (arg0)
          || TREE_SIDE_EFFECTS (arg1))
        return 0;
@@ -1947,9 +1919,61 @@ operand_equal_p (arg0, arg1, only_const)
        }
 
     case 'e':
-      if (TREE_CODE (arg0) == RTL_EXPR)
-       return rtx_equal_p (RTL_EXPR_RTL (arg0), RTL_EXPR_RTL (arg1));
-      return 0;
+      switch (TREE_CODE (arg0))
+       {
+       case ADDR_EXPR:
+       case TRUTH_NOT_EXPR:
+         return operand_equal_p (TREE_OPERAND (arg0, 0),
+                                 TREE_OPERAND (arg1, 0), 0);
+
+       case RTL_EXPR:
+         return rtx_equal_p (RTL_EXPR_RTL (arg0), RTL_EXPR_RTL (arg1));
+
+       case CALL_EXPR:
+         /* If the CALL_EXPRs call different functions, then they
+            clearly can not be equal.  */
+         if (! operand_equal_p (TREE_OPERAND (arg0, 0),
+                                TREE_OPERAND (arg1, 0), 0))
+           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
+           return 0;
+
+         /* Now see if all the arguments are the same.  operand_equal_p
+            does not handle TREE_LIST, so we walk the operands here
+            feeding them to operand_equal_p.  */
+         arg0 = TREE_OPERAND (arg0, 1);
+         arg1 = TREE_OPERAND (arg1, 1);
+         while (arg0 && arg1)
+           {
+             if (! operand_equal_p (TREE_VALUE (arg0), TREE_VALUE (arg1), 0))
+               return 0;
+
+             arg0 = TREE_CHAIN (arg0);
+             arg1 = TREE_CHAIN (arg1);
+           }
+
+         /* If we get here and both argument lists are exhausted
+            then the CALL_EXPRs are equal.  */
+         return ! (arg0 || arg1);
+
+       default:
+         return 0;
+       }
+
+    case 'd':
+       /* Consider __builtin_sqrt equal to sqrt.  */
+       return TREE_CODE (arg0) == FUNCTION_DECL
+              && DECL_BUILT_IN (arg0) && DECL_BUILT_IN (arg1)
+              && DECL_BUILT_IN_CLASS (arg0) == DECL_BUILT_IN_CLASS (arg1)
+              && DECL_FUNCTION_CODE (arg0) == DECL_FUNCTION_CODE (arg1);
 
     default:
       return 0;
@@ -1962,9 +1986,7 @@ operand_equal_p (arg0, arg1, only_const)
    When in doubt, return 0.  */
 
 static int
-operand_equal_for_comparison_p (arg0, arg1, other)
-     tree arg0, arg1;
-     tree other;
+operand_equal_for_comparison_p (tree arg0, tree arg1, tree other)
 {
   int unsignedp1, unsignedpo;
   tree primarg0, primarg1, primother;
@@ -2025,10 +2047,7 @@ operand_equal_for_comparison_p (arg0, arg1, other)
    If this is true, return 1.  Otherwise, return zero.  */
 
 static int
-twoval_comparison_p (arg, cval1, cval2, save_p)
-     tree arg;
-     tree *cval1, *cval2;
-     int *save_p;
+twoval_comparison_p (tree arg, tree *cval1, tree *cval2, int *save_p)
 {
   enum tree_code code = TREE_CODE (arg);
   char class = TREE_CODE_CLASS (code);
@@ -2120,9 +2139,7 @@ twoval_comparison_p (arg, cval1, cval2, save_p)
    NEW1 and OLD1.  */
 
 static tree
-eval_subst (arg, old0, new0, old1, new1)
-     tree arg;
-     tree old0, new0, old1, new1;
+eval_subst (tree arg, tree old0, tree new0, tree old1, tree new1)
 {
   tree type = TREE_TYPE (arg);
   enum tree_code code = TREE_CODE (arg);
@@ -2205,9 +2222,8 @@ eval_subst (arg, old0, new0, old1, new1)
    If OMITTED has side effects, we must evaluate it.  Otherwise, just do
    the conversion of RESULT to TYPE.  */
 
-static tree
-omit_one_operand (type, result, omitted)
-     tree type, result, omitted;
+tree
+omit_one_operand (tree type, tree result, tree omitted)
 {
   tree t = convert (type, result);
 
@@ -2220,8 +2236,7 @@ omit_one_operand (type, result, omitted)
 /* Similar, but call pedantic_non_lvalue instead of non_lvalue.  */
 
 static tree
-pedantic_omit_one_operand (type, result, omitted)
-     tree type, result, omitted;
+pedantic_omit_one_operand (tree type, tree result, tree omitted)
 {
   tree t = convert (type, result);
 
@@ -2236,8 +2251,7 @@ pedantic_omit_one_operand (type, result, omitted)
    returns a truth value (0 or 1).  */
 
 tree
-invert_truthvalue (arg)
-     tree arg;
+invert_truthvalue (tree arg)
 {
   tree type = TREE_TYPE (arg);
   enum tree_code code = TREE_CODE (arg);
@@ -2350,16 +2364,13 @@ invert_truthvalue (arg)
    operands are another bit-wise operation with a common input.  If so,
    distribute the bit operations to save an operation and possibly two if
    constants are involved.  For example, convert
-       (A | B) & (A | C) into A | (B & C)
+       (A | B) & (A | C) into A | (B & C)
    Further simplification will occur if B and C are constants.
 
    If this optimization cannot be done, 0 will be returned.  */
 
 static tree
-distribute_bit_expr (code, type, arg0, arg1)
-     enum tree_code code;
-     tree type;
-     tree arg0, arg1;
+distribute_bit_expr (enum tree_code code, tree type, tree arg0, tree arg1)
 {
   tree common;
   tree left, right;
@@ -2405,11 +2416,7 @@ distribute_bit_expr (code, type, arg0, arg1)
    starting at BITPOS.  The field is unsigned if UNSIGNEDP is nonzero.  */
 
 static tree
-make_bit_field_ref (inner, type, bitsize, bitpos, unsignedp)
-     tree inner;
-     tree type;
-     int bitsize, bitpos;
-     int unsignedp;
+make_bit_field_ref (tree inner, tree type, int bitsize, int bitpos, int unsignedp)
 {
   tree result = build (BIT_FIELD_REF, type, inner,
                       size_int (bitsize), bitsize_int (bitpos));
@@ -2440,10 +2447,7 @@ make_bit_field_ref (inner, type, bitsize, bitpos, unsignedp)
    tree.  Otherwise we return zero.  */
 
 static tree
-optimize_bit_field_compare (code, compare_type, lhs, rhs)
-     enum tree_code code;
-     tree compare_type;
-     tree lhs, rhs;
+optimize_bit_field_compare (enum tree_code code, tree compare_type, tree lhs, tree rhs)
 {
   HOST_WIDE_INT lbitpos, lbitsize, rbitpos, rbitsize, nbitpos, nbitsize;
   tree type = TREE_TYPE (lhs);
@@ -2617,15 +2621,11 @@ optimize_bit_field_compare (code, compare_type, lhs, rhs)
    do anything with.  */
 
 static tree
-decode_field_reference (exp, pbitsize, pbitpos, pmode, punsignedp,
-                       pvolatilep, pmask, pand_mask)
-     tree exp;
-     HOST_WIDE_INT *pbitsize, *pbitpos;
-     enum machine_mode *pmode;
-     int *punsignedp, *pvolatilep;
-     tree *pmask;
-     tree *pand_mask;
+decode_field_reference (tree exp, HOST_WIDE_INT *pbitsize, HOST_WIDE_INT *pbitpos,
+                       enum machine_mode *pmode, int *punsignedp, int *pvolatilep,
+                       tree *pmask, tree *pand_mask)
 {
+  tree outer_type = 0;
   tree and_mask = 0;
   tree mask, inner, offset;
   tree unsigned_type;
@@ -2637,6 +2637,13 @@ decode_field_reference (exp, pbitsize, pbitpos, pmode, punsignedp,
   if (! INTEGRAL_TYPE_P (TREE_TYPE (exp)))
     return 0;
 
+  /* We are interested in the bare arrangement of bits, so strip everything
+     that doesn't affect the machine mode.  However, record the type of the
+     outermost expression if it may matter below.  */
+  if (TREE_CODE (exp) == NOP_EXPR
+      || TREE_CODE (exp) == CONVERT_EXPR
+      || TREE_CODE (exp) == NON_LVALUE_EXPR)
+    outer_type = TREE_TYPE (exp);
   STRIP_NOPS (exp);
 
   if (TREE_CODE (exp) == BIT_AND_EXPR)
@@ -2655,6 +2662,12 @@ decode_field_reference (exp, pbitsize, pbitpos, pmode, punsignedp,
       || TREE_CODE (inner) == PLACEHOLDER_EXPR)
     return 0;
 
+  /* If the number of bits in the reference is the same as the bitsize of
+     the outer type, then the outer type gives the signedness. Otherwise
+     (in case of a small bitfield) the signedness is unchanged.  */
+  if (outer_type && *pbitsize == tree_low_cst (TYPE_SIZE (outer_type), 1))
+    *punsignedp = TREE_UNSIGNED (outer_type);
+
   /* Compute the mask to access the bitfield.  */
   unsigned_type = (*lang_hooks.types.type_for_size) (*pbitsize, 1);
   precision = TYPE_PRECISION (unsigned_type);
@@ -2679,9 +2692,7 @@ decode_field_reference (exp, pbitsize, pbitpos, pmode, punsignedp,
    bit positions.  */
 
 static int
-all_ones_mask_p (mask, size)
-     tree mask;
-     int size;
+all_ones_mask_p (tree mask, int size)
 {
   tree type = TREE_TYPE (mask);
   unsigned int precision = TYPE_PRECISION (type);
@@ -2706,9 +2717,7 @@ all_ones_mask_p (mask, size)
    or NULL_TREE otherwise.  */
 
 static tree
-sign_bit_p (exp, val)
-     tree exp;
-     tree val;
+sign_bit_p (tree exp, tree val)
 {
   unsigned HOST_WIDE_INT lo;
   HOST_WIDE_INT hi;
@@ -2752,8 +2761,7 @@ sign_bit_p (exp, val)
    to be evaluated unconditionally.  */
 
 static int
-simple_operand_p (exp)
-     tree exp;
+simple_operand_p (tree exp)
 {
   /* Strip any conversions that don't change the machine mode.  */
   while ((TREE_CODE (exp) == NOP_EXPR
@@ -2781,9 +2789,9 @@ simple_operand_p (exp)
    try to change a logical combination of comparisons into a range test.
 
    For example, both
-       X == 2 || X == 3 || X == 4 || X == 5
+       X == 2 || X == 3 || X == 4 || X == 5
    and
-       X >= 2 && X <= 5
+       X >= 2 && X <= 5
    are converted to
        (unsigned) (X - 2) <= 3
 
@@ -2813,11 +2821,8 @@ simple_operand_p (exp)
    type if both are specified.  */
 
 static tree
-range_binop (code, type, arg0, upper0_p, arg1, upper1_p)
-     enum tree_code code;
-     tree type;
-     tree arg0, arg1;
-     int upper0_p, upper1_p;
+range_binop (enum tree_code code, tree type, tree arg0, int upper0_p, tree arg1,
+            int upper1_p)
 {
   tree tem;
   int result;
@@ -2881,10 +2886,7 @@ range_binop (code, type, arg0, upper0_p, arg1, upper1_p)
    likely not be returning a useful value and range.  */
 
 static tree
-make_range (exp, pin_p, plow, phigh)
-     tree exp;
-     int *pin_p;
-     tree *plow, *phigh;
+make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
 {
   enum tree_code code;
   tree arg0 = NULL_TREE, arg1 = NULL_TREE, type = NULL_TREE;
@@ -2906,7 +2908,8 @@ make_range (exp, pin_p, plow, phigh)
 
       if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
        {
-         arg0 = TREE_OPERAND (exp, 0);
+         if (first_rtl_op (code) > 0)
+           arg0 = TREE_OPERAND (exp, 0);
          if (TREE_CODE_CLASS (code) == '<'
              || TREE_CODE_CLASS (code) == '1'
              || TREE_CODE_CLASS (code) == '2')
@@ -3149,11 +3152,7 @@ make_range (exp, pin_p, plow, phigh)
    on IN_P) the range.  */
 
 static tree
-build_range_check (type, exp, in_p, low, high)
-     tree type;
-     tree exp;
-     int in_p;
-     tree low, high;
+build_range_check (tree type, tree exp, int in_p, tree low, tree high)
 {
   tree etype = TREE_TYPE (exp);
   tree value;
@@ -3229,11 +3228,8 @@ build_range_check (type, exp, in_p, low, high)
    can, 0 if we can't.  Set the output range into the specified parameters.  */
 
 static int
-merge_ranges (pin_p, plow, phigh, in0_p, low0, high0, in1_p, low1, high1)
-     int *pin_p;
-     tree *plow, *phigh;
-     int in0_p, in1_p;
-     tree low0, high0, low1, high1;
+merge_ranges (int *pin_p, tree *plow, tree *phigh, int in0_p, tree low0, tree high0,
+             int in1_p, tree low1, tree high1)
 {
   int no_overlap;
   int subset;
@@ -3361,12 +3357,15 @@ merge_ranges (pin_p, plow, phigh, in0_p, low0, high0, in1_p, low1, high1)
   return 1;
 }
 \f
+#ifndef RANGE_TEST_NON_SHORT_CIRCUIT
+#define RANGE_TEST_NON_SHORT_CIRCUIT (BRANCH_COST >= 2)
+#endif
+
 /* EXP is some logical combination of boolean tests.  See if we can
    merge it into some range test.  Return the new tree if so.  */
 
 static tree
-fold_range_test (exp)
-     tree exp;
+fold_range_test (tree exp)
 {
   int or_op = (TREE_CODE (exp) == TRUTH_ORIF_EXPR
               || TREE_CODE (exp) == TRUTH_OR_EXPR);
@@ -3397,7 +3396,7 @@ fold_range_test (exp)
   /* On machines where the branch cost is expensive, if this is a
      short-circuited branch and the underlying object on both sides
      is the same, make a non-short-circuit operation.  */
-  else if (BRANCH_COST >= 2
+  else if (RANGE_TEST_NON_SHORT_CIRCUIT
           && lhs != 0 && rhs != 0
           && (TREE_CODE (exp) == TRUTH_ANDIF_EXPR
               || TREE_CODE (exp) == TRUTH_ORIF_EXPR)
@@ -3413,7 +3412,7 @@ fold_range_test (exp)
                      TREE_OPERAND (exp, 1));
 
       else if ((*lang_hooks.decls.global_bindings_p) () == 0
-              && ! contains_placeholder_p (lhs))
+              && ! CONTAINS_PLACEHOLDER_P (lhs))
        {
          tree common = save_expr (lhs);
 
@@ -3438,11 +3437,7 @@ fold_range_test (exp)
    it is an INTEGER_CST that should be AND'ed with the extra bits.  */
 
 static tree
-unextend (c, p, unsignedp, mask)
-     tree c;
-     int p;
-     int unsignedp;
-     tree mask;
+unextend (tree c, int p, int unsignedp, tree mask)
 {
   tree type = TREE_TYPE (c);
   int modesize = GET_MODE_BITSIZE (TYPE_MODE (type));
@@ -3502,14 +3497,12 @@ unextend (c, p, unsignedp, mask)
    We return the simplified tree or 0 if no optimization is possible.  */
 
 static tree
-fold_truthop (code, truth_type, lhs, rhs)
-     enum tree_code code;
-     tree truth_type, lhs, rhs;
+fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs)
 {
   /* If this is the "or" of two comparisons, we can do something if
      the comparisons are NE_EXPR.  If this is the "and", we can do something
      if the comparisons are EQ_EXPR.  I.e.,
-       (a->b == 2 && a->c == 4) can become (a->new == NEW).
+       (a->b == 2 && a->c == 4) can become (a->new == NEW).
 
      WANTED_CODE is this operation code.  For single bit fields, we can
      convert EQ_EXPR to NE_EXPR so we need not reject the "wrong"
@@ -3928,8 +3921,7 @@ fold_truthop (code, truth_type, lhs, rhs)
    constant.  */
 
 static tree
-optimize_minmax_comparison (t)
-     tree t;
+optimize_minmax_comparison (tree t)
 {
   tree type = TREE_TYPE (t);
   tree arg0 = TREE_OPERAND (t, 0);
@@ -4040,11 +4032,28 @@ optimize_minmax_comparison (t)
    original computation, but need not be in the original type.  */
 
 static tree
-extract_muldiv (t, c, code, wide_type)
-     tree t;
-     tree c;
-     enum tree_code code;
-     tree wide_type;
+extract_muldiv (tree t, tree c, enum tree_code code, tree wide_type)
+{
+  /* To avoid exponential search depth, refuse to allow recursion past
+     three levels.  Beyond that (1) it's highly unlikely that we'll find
+     something interesting and (2) we've probably processed it before
+     when we built the inner expression.  */
+
+  static int depth;
+  tree ret;
+
+  if (depth > 3)
+    return NULL;
+
+  depth++;
+  ret = extract_muldiv_1 (t, c, code, wide_type);
+  depth--;
+
+  return ret;
+}
+
+static tree
+extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type)
 {
   tree type = TREE_TYPE (t);
   enum tree_code tcode = TREE_CODE (t);
@@ -4093,14 +4102,23 @@ extract_muldiv (t, c, code, wide_type)
              /* ... or its type is larger than ctype,
                 then we cannot pass through this truncation.  */
              || (GET_MODE_SIZE (TYPE_MODE (ctype))
-                 < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0))))))
+                 < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0))))
+             /* ... or signedness changes for division or modulus,
+                then we cannot pass through this conversion.  */
+             || (code != MULT_EXPR
+                 && (TREE_UNSIGNED (ctype)
+                     != TREE_UNSIGNED (TREE_TYPE (op0))))))
        break;
 
       /* Pass the constant down and see if we can make a simplification.  If
         we can, replace this expression with the inner simplification for
         possible later conversion to our or some other type.  */
-      if (0 != (t1 = extract_muldiv (op0, convert (TREE_TYPE (op0), c), code,
-                                    code == MULT_EXPR ? ctype : NULL_TREE)))
+      if ((t2 = convert (TREE_TYPE (op0), c)) != 0
+         && TREE_CODE (t2) == INTEGER_CST
+         && ! TREE_CONSTANT_OVERFLOW (t2)
+         && (0 != (t1 = extract_muldiv (op0, t2, code,
+                                        code == MULT_EXPR
+                                        ? ctype : NULL_TREE))))
        return t1;
       break;
 
@@ -4133,25 +4151,6 @@ extract_muldiv (t, c, code, wide_type)
                      TREE_OPERAND (t, 1));
       break;
 
-    case SAVE_EXPR:
-      /* If this has not been evaluated and the operand has no side effects,
-        we can see if we can do something inside it and make a new one.
-        Note that this test is overly conservative since we can do this
-        if the only reason it had side effects is that it was another
-        similar SAVE_EXPR, but that isn't worth bothering with.  */
-      if (SAVE_EXPR_RTL (t) == 0 && ! TREE_SIDE_EFFECTS (TREE_OPERAND (t, 0))
-         && 0 != (t1 = extract_muldiv (TREE_OPERAND (t, 0), c, code,
-                                       wide_type)))
-       {
-         t1 = save_expr (t1);
-         if (SAVE_EXPR_PERSISTENT_P (t) && TREE_CODE (t1) == SAVE_EXPR)
-           SAVE_EXPR_PERSISTENT_P (t1) = 1;
-         if (is_pending_size (t))
-           put_pending_size (t1);
-         return t1;
-       }
-      break;
-
     case LSHIFT_EXPR:  case RSHIFT_EXPR:
       /* If the second operand is constant, this is a multiplication
         or floor division, by a power of two, so we can treat it that
@@ -4290,6 +4289,7 @@ extract_muldiv (t, c, code, wide_type)
         overflowed.  */
       if ((! TREE_UNSIGNED (ctype)
           || (TREE_CODE (ctype) == INTEGER_TYPE && TYPE_IS_SIZETYPE (ctype)))
+         && ! flag_wrapv
          && ((code == MULT_EXPR && tcode == EXACT_DIV_EXPR)
              || (tcode == MULT_EXPR
                  && code != TRUNC_MOD_EXPR && code != CEIL_MOD_EXPR
@@ -4320,9 +4320,7 @@ extract_muldiv (t, c, code, wide_type)
    that we may sometimes modify the tree.  */
 
 static tree
-strip_compound_expr (t, s)
-     tree t;
-     tree s;
+strip_compound_expr (tree t, tree s)
 {
   enum tree_code code = TREE_CODE (t);
 
@@ -4355,9 +4353,7 @@ strip_compound_expr (t, s)
    1), and is of the indicated TYPE.  */
 
 static tree
-constant_boolean_node (value, type)
-     int value;
-     tree type;
+constant_boolean_node (int value, tree type)
 {
   if (type == integer_type_node)
     return value ? integer_one_node : integer_zero_node;
@@ -4378,9 +4374,7 @@ constant_boolean_node (value, type)
    we don't care (to avoid spending too much time on complex expressions.).  */
 
 static int
-count_cond (expr, lim)
-     tree expr;
-     int lim;
+count_cond (tree expr, int lim)
 {
   int ctrue, cfalse;
 
@@ -4403,12 +4397,7 @@ count_cond (expr, lim)
    original expression.  */
 
 static tree
-fold_binary_op_with_conditional_arg (code, type, cond, arg, cond_first_p)
-     enum tree_code code;
-     tree type;
-     tree cond;
-     tree arg;
-     int cond_first_p;
+fold_binary_op_with_conditional_arg (enum tree_code code, tree type, tree cond, tree arg, int cond_first_p)
 {
   tree test, true_value, false_value;
   tree lhs = NULL_TREE;
@@ -4485,21 +4474,19 @@ fold_binary_op_with_conditional_arg (code, type, cond, arg, cond_first_p)
       false_value = convert (testtype, integer_zero_node);
     }
 
-  /* If ARG is complex we want to make sure we only evaluate
-     it once.  Though this is only required if it is volatile, it
-     might be more efficient even if it is not.  However, if we
-     succeed in folding one part to a constant, we do not need
-     to make this SAVE_EXPR.  Since we do this optimization
-     primarily to see if we do end up with constant and this
-     SAVE_EXPR interferes with later optimizations, suppressing
-     it when we can is important.
-
-     If we are not in a function, we can't make a SAVE_EXPR, so don't
-     try to do so.  Don't try to see if the result is a constant
-     if an arm is a COND_EXPR since we get exponential behavior
-     in that case.  */
-
-  if (TREE_CODE (arg) == SAVE_EXPR)
+  /* If ARG is complex we want to make sure we only evaluate it once.  Though
+     this is only required if it is volatile, it might be more efficient even
+     if it is not.  However, if we succeed in folding one part to a constant,
+     we do not need to make this SAVE_EXPR.  Since we do this optimization
+     primarily to see if we do end up with constant and this SAVE_EXPR
+     interferes with later optimizations, suppressing it when we can is
+     important.
+
+     If we are not in a function, we can't make a SAVE_EXPR, so don't try to
+     do so.  Don't try to see if the result is a constant if an arm is a
+     COND_EXPR since we get exponential behavior in that case.  */
+
+  if (saved_expr_p (arg))
     save = 1;
   else if (lhs == 0 && rhs == 0
           && !TREE_CONSTANT (arg)
@@ -4551,13 +4538,15 @@ fold_binary_op_with_conditional_arg (code, type, cond, arg, cond_first_p)
    modes, X + 0 is not the same as X because -0 + 0 is 0.  */
 
 static bool
-fold_real_zero_addition_p (type, addend, negate)
-     tree type, addend;
-     int negate;
+fold_real_zero_addition_p (tree type, tree addend, int negate)
 {
   if (!real_zerop (addend))
     return false;
 
+  /* Don't allow the fold with -fsignaling-nans.  */
+  if (HONOR_SNANS (TYPE_MODE (type)))
+    return false;
+
   /* Allow the fold if zeros aren't signed, or their sign isn't important.  */
   if (!HONOR_SIGNED_ZEROS (TYPE_MODE (type)))
     return true;
@@ -4574,7 +4563,324 @@ fold_real_zero_addition_p (type, addend, negate)
   return negate && !HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type));
 }
 
+/* Subroutine of fold() that checks comparisons of built-in math
+   functions against real constants.
+
+   FCODE is the DECL_FUNCTION_CODE of the built-in, CODE is the comparison
+   operator: EQ_EXPR, NE_EXPR, GT_EXPR, LT_EXPR, GE_EXPR or LE_EXPR.  TYPE
+   is the type of the result and ARG0 and ARG1 are the operands of the
+   comparison.  ARG1 must be a TREE_REAL_CST.
+
+   The function returns the constant folded tree if a simplification
+   can be made, and NULL_TREE otherwise.  */
+
+static tree
+fold_mathfn_compare (enum built_in_function fcode, enum tree_code code, tree type, tree arg0, tree arg1)
+{
+  REAL_VALUE_TYPE c;
+
+  if (fcode == BUILT_IN_SQRT
+      || fcode == BUILT_IN_SQRTF
+      || fcode == BUILT_IN_SQRTL)
+    {
+      tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
+      enum machine_mode mode = TYPE_MODE (TREE_TYPE (arg0));
+
+      c = TREE_REAL_CST (arg1);
+      if (REAL_VALUE_NEGATIVE (c))
+       {
+         /* sqrt(x) < y is always false, if y is negative.  */
+         if (code == EQ_EXPR || code == LT_EXPR || code == LE_EXPR)
+           return omit_one_operand (type,
+                                    convert (type, integer_zero_node),
+                                    arg);
+
+         /* sqrt(x) > y is always true, if y is negative and we
+            don't care about NaNs, i.e. negative values of x.  */
+         if (code == NE_EXPR || !HONOR_NANS (mode))
+           return omit_one_operand (type,
+                                    convert (type, integer_one_node),
+                                    arg);
+
+         /* sqrt(x) > y is the same as x >= 0, if y is negative.  */
+         return fold (build (GE_EXPR, type, arg,
+                             build_real (TREE_TYPE (arg), dconst0)));
+       }
+      else if (code == GT_EXPR || code == GE_EXPR)
+       {
+         REAL_VALUE_TYPE c2;
+
+         REAL_ARITHMETIC (c2, MULT_EXPR, c, c);
+         real_convert (&c2, mode, &c2);
+
+         if (REAL_VALUE_ISINF (c2))
+           {
+             /* sqrt(x) > y is x == +Inf, when y is very large.  */
+             if (HONOR_INFINITIES (mode))
+               return fold (build (EQ_EXPR, type, arg,
+                                   build_real (TREE_TYPE (arg), c2)));
+
+             /* sqrt(x) > y is always false, when y is very large
+                and we don't care about infinities.  */
+             return omit_one_operand (type,
+                                      convert (type, integer_zero_node),
+                                      arg);
+           }
+
+         /* sqrt(x) > c is the same as x > c*c.  */
+         return fold (build (code, type, arg,
+                             build_real (TREE_TYPE (arg), c2)));
+       }
+      else if (code == LT_EXPR || code == LE_EXPR)
+       {
+         REAL_VALUE_TYPE c2;
+
+         REAL_ARITHMETIC (c2, MULT_EXPR, c, c);
+         real_convert (&c2, mode, &c2);
+
+         if (REAL_VALUE_ISINF (c2))
+           {
+             /* sqrt(x) < y is always true, when y is a very large
+                value and we don't care about NaNs or Infinities.  */
+             if (! HONOR_NANS (mode) && ! HONOR_INFINITIES (mode))
+               return omit_one_operand (type,
+                                        convert (type, integer_one_node),
+                                        arg);
+
+             /* sqrt(x) < y is x != +Inf when y is very large and we
+                don't care about NaNs.  */
+             if (! HONOR_NANS (mode))
+               return fold (build (NE_EXPR, type, arg,
+                                   build_real (TREE_TYPE (arg), c2)));
+
+             /* sqrt(x) < y is x >= 0 when y is very large and we
+                don't care about Infinities.  */
+             if (! HONOR_INFINITIES (mode))
+               return fold (build (GE_EXPR, type, arg,
+                                   build_real (TREE_TYPE (arg), dconst0)));
+
+             /* sqrt(x) < y is x >= 0 && x != +Inf, when y is large.  */
+             if ((*lang_hooks.decls.global_bindings_p) () != 0
+                 || CONTAINS_PLACEHOLDER_P (arg))
+               return NULL_TREE;
+
+             arg = save_expr (arg);
+             return fold (build (TRUTH_ANDIF_EXPR, type,
+                                 fold (build (GE_EXPR, type, arg,
+                                              build_real (TREE_TYPE (arg),
+                                                          dconst0))),
+                                 fold (build (NE_EXPR, type, arg,
+                                              build_real (TREE_TYPE (arg),
+                                                          c2)))));
+           }
+
+         /* sqrt(x) < c is the same as x < c*c, if we ignore NaNs.  */
+         if (! HONOR_NANS (mode))
+           return fold (build (code, type, arg,
+                               build_real (TREE_TYPE (arg), c2)));
+
+         /* sqrt(x) < c is the same as x >= 0 && x < c*c.  */
+         if ((*lang_hooks.decls.global_bindings_p) () == 0
+             && ! CONTAINS_PLACEHOLDER_P (arg))
+           {
+             arg = save_expr (arg);
+             return fold (build (TRUTH_ANDIF_EXPR, type,
+                                 fold (build (GE_EXPR, type, arg,
+                                              build_real (TREE_TYPE (arg),
+                                                          dconst0))),
+                                 fold (build (code, type, arg,
+                                              build_real (TREE_TYPE (arg),
+                                                          c2)))));
+           }
+       }
+    }
+
+  return NULL_TREE;
+}
+
+/* Subroutine of fold() that optimizes comparisons against Infinities,
+   either +Inf or -Inf.
+
+   CODE is the comparison operator: EQ_EXPR, NE_EXPR, GT_EXPR, LT_EXPR,
+   GE_EXPR or LE_EXPR.  TYPE is the type of the result and ARG0 and ARG1
+   are the operands of the comparison.  ARG1 must be a TREE_REAL_CST.
+
+   The function returns the constant folded tree if a simplification
+   can be made, and NULL_TREE otherwise.  */
+
+static tree
+fold_inf_compare (enum tree_code code, tree type, tree arg0, tree arg1)
+{
+  enum machine_mode mode;
+  REAL_VALUE_TYPE max;
+  tree temp;
+  bool neg;
+
+  mode = TYPE_MODE (TREE_TYPE (arg0));
+
+  /* For negative infinity swap the sense of the comparison.  */
+  neg = REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg1));
+  if (neg)
+    code = swap_tree_comparison (code);
+
+  switch (code)
+    {
+    case GT_EXPR:
+      /* x > +Inf is always false, if with ignore sNANs.  */
+      if (HONOR_SNANS (mode))
+        return NULL_TREE;
+      return omit_one_operand (type,
+                              convert (type, integer_zero_node),
+                              arg0);
+
+    case LE_EXPR:
+      /* x <= +Inf is always true, if we don't case about NaNs.  */
+      if (! HONOR_NANS (mode))
+       return omit_one_operand (type,
+                                convert (type, integer_one_node),
+                                arg0);
+
+      /* x <= +Inf is the same as x == x, i.e. isfinite(x).  */
+      if ((*lang_hooks.decls.global_bindings_p) () == 0
+         && ! CONTAINS_PLACEHOLDER_P (arg0))
+       {
+         arg0 = save_expr (arg0);
+         return fold (build (EQ_EXPR, type, arg0, arg0));
+       }
+      break;
+
+    case EQ_EXPR:
+    case GE_EXPR:
+      /* x == +Inf and x >= +Inf are always equal to x > DBL_MAX.  */
+      real_maxval (&max, neg, mode);
+      return fold (build (neg ? LT_EXPR : GT_EXPR, type,
+                         arg0, build_real (TREE_TYPE (arg0), max)));
+
+    case LT_EXPR:
+      /* x < +Inf is always equal to x <= DBL_MAX.  */
+      real_maxval (&max, neg, mode);
+      return fold (build (neg ? GE_EXPR : LE_EXPR, type,
+                         arg0, build_real (TREE_TYPE (arg0), max)));
+
+    case NE_EXPR:
+      /* x != +Inf is always equal to !(x > DBL_MAX).  */
+      real_maxval (&max, neg, mode);
+      if (! HONOR_NANS (mode))
+       return fold (build (neg ? GE_EXPR : LE_EXPR, type,
+                           arg0, build_real (TREE_TYPE (arg0), max)));
+      temp = fold (build (neg ? LT_EXPR : GT_EXPR, type,
+                         arg0, build_real (TREE_TYPE (arg0), max)));
+      return fold (build1 (TRUTH_NOT_EXPR, type, temp));
+
+    default:
+      break;
+    }
+
+  return NULL_TREE;
+}
+
+/* If CODE with arguments ARG0 and ARG1 represents a single bit
+   equality/inequality test, then return a simplified form of
+   the test using shifts and logical operations.  Otherwise return
+   NULL.  TYPE is the desired result type.  */
+tree
+fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
+                     tree result_type)
+{
+  /* If this is a TRUTH_NOT_EXPR, it may have a single bit test inside
+     operand 0.  */
+  if (code == TRUTH_NOT_EXPR)
+    {
+      code = TREE_CODE (arg0);
+      if (code != NE_EXPR && code != EQ_EXPR)
+       return NULL_TREE;
 
+      /* Extract the arguments of the EQ/NE.  */
+      arg1 = TREE_OPERAND (arg0, 1);
+      arg0 = TREE_OPERAND (arg0, 0);
+
+      /* This requires us to invert the code.  */ 
+      code = (code == EQ_EXPR ? NE_EXPR : EQ_EXPR);
+    }
+
+  /* If this is testing a single bit, we can optimize the test.  */
+  if ((code == NE_EXPR || code == EQ_EXPR)
+      && TREE_CODE (arg0) == BIT_AND_EXPR && integer_zerop (arg1)
+      && integer_pow2p (TREE_OPERAND (arg0, 1)))
+    {
+      tree inner = TREE_OPERAND (arg0, 0);
+      tree type = TREE_TYPE (arg0);
+      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 arg00;
+  
+      /* If we have (A & C) != 0 where C is the sign bit of A, convert
+        this into A < 0.  Similarly for (A & C) == 0 into A >= 0.  */
+      arg00 = sign_bit_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1));
+      if (arg00 != NULL_TREE)
+       {
+         tree stype = (*lang_hooks.types.signed_type) (TREE_TYPE (arg00));
+         return fold (build (code == EQ_EXPR ? GE_EXPR : LT_EXPR, result_type,
+                             convert (stype, arg00),
+                             convert (stype, integer_zero_node)));
+       }
+      
+      /* Otherwise we have (A & C) != 0 where C is a single bit, 
+        convert that into ((A >> C2) & 1).  Where C2 = log2(C).
+        Similarly for (A & C) == 0.  */
+
+      /* If INNER is a right shift of a constant and it plus BITNUM does
+        not overflow, adjust BITNUM and INNER.  */
+      if (TREE_CODE (inner) == RSHIFT_EXPR
+         && TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST
+         && TREE_INT_CST_HIGH (TREE_OPERAND (inner, 1)) == 0
+         && bitnum < TYPE_PRECISION (type)
+         && 0 > compare_tree_int (TREE_OPERAND (inner, 1),
+                                  bitnum - TYPE_PRECISION (type)))
+       {
+         bitnum += TREE_INT_CST_LOW (TREE_OPERAND (inner, 1));
+         inner = TREE_OPERAND (inner, 0);
+       }
+
+      /* 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)
+#else
+                     : 1
+#endif
+                     );
+
+      signed_type = (*lang_hooks.types.type_for_mode) (operand_mode, 0);
+      unsigned_type = (*lang_hooks.types.type_for_mode) (operand_mode, 1);
+
+      if (bitnum != 0)
+       inner = build (RSHIFT_EXPR, ops_unsigned ? unsigned_type : signed_type,
+                      inner, size_int (bitnum));
+
+      if (code == EQ_EXPR)
+       inner = build (BIT_XOR_EXPR, ops_unsigned ? unsigned_type : signed_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);
+
+      /* Make sure to return the proper type.  */
+      if (TREE_TYPE (inner) != result_type)
+       inner = convert (result_type, inner);
+
+      return inner;
+    }
+  return NULL_TREE;
+}
 /* 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.
@@ -4584,8 +4890,7 @@ fold_real_zero_addition_p (type, addend, negate)
    but we can constant-fold them if they have constant operands.  */
 
 tree
-fold (expr)
-     tree expr;
+fold (tree expr)
 {
   tree t = expr;
   tree t1 = NULL_TREE;
@@ -4782,6 +5087,14 @@ fold (expr)
                            fold (build1 (code, type, integer_one_node)),
                            fold (build1 (code, type, integer_zero_node))));
    }
+  else if (TREE_CODE_CLASS (code) == '<'
+          && TREE_CODE (arg0) == COMPOUND_EXPR)
+    return build (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
+                 fold (build (code, type, TREE_OPERAND (arg0, 1), arg1)));
+  else if (TREE_CODE_CLASS (code) == '<'
+          && TREE_CODE (arg1) == COMPOUND_EXPR)
+    return build (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
+                 fold (build (code, type, arg0, TREE_OPERAND (arg1, 1))));
   else if (TREE_CODE_CLASS (code) == '2'
           || TREE_CODE_CLASS (code) == '<')
     {
@@ -4798,7 +5111,7 @@ fold (expr)
                   || count_cond (arg0, 25) + count_cond (arg1, 25) <= 25)
               && (! TREE_SIDE_EFFECTS (arg0)
                   || ((*lang_hooks.decls.global_bindings_p) () == 0
-                      && ! contains_placeholder_p (arg0))))
+                      && ! CONTAINS_PLACEHOLDER_P (arg0))))
        return
          fold_binary_op_with_conditional_arg (code, type, arg1, arg0,
                                               /*cond_first_p=*/0);
@@ -4812,19 +5125,11 @@ fold (expr)
                   || count_cond (arg0, 25) + count_cond (arg1, 25) <= 25)
               && (! TREE_SIDE_EFFECTS (arg1)
                   || ((*lang_hooks.decls.global_bindings_p) () == 0
-                      && ! contains_placeholder_p (arg1))))
+                      && ! CONTAINS_PLACEHOLDER_P (arg1))))
        return
          fold_binary_op_with_conditional_arg (code, type, arg0, arg1,
                                               /*cond_first_p=*/1);
     }
-  else if (TREE_CODE_CLASS (code) == '<'
-          && TREE_CODE (arg0) == COMPOUND_EXPR)
-    return build (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
-                 fold (build (code, type, TREE_OPERAND (arg0, 1), arg1)));
-  else if (TREE_CODE_CLASS (code) == '<'
-          && TREE_CODE (arg1) == COMPOUND_EXPR)
-    return build (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
-                 fold (build (code, type, arg0, TREE_OPERAND (arg1, 1))));
 
   switch (code)
     {
@@ -4976,7 +5281,7 @@ fold (expr)
                {
                  tree uns = (*lang_hooks.types.unsigned_type) (TREE_TYPE (and0));
                  and0 = convert (uns, and0);
-                 and1 = convert (uns, and1);
+                 and1 = convert (uns, and1);
                }
 #endif
            }
@@ -5000,7 +5305,8 @@ fold (expr)
       return t;
 
     case COMPONENT_REF:
-      if (TREE_CODE (arg0) == CONSTRUCTOR)
+      if (TREE_CODE (arg0) == CONSTRUCTOR
+         && ! type_contains_placeholder_p (TREE_TYPE (arg0)))
        {
          tree m = purpose_member (arg1, CONSTRUCTOR_ELTS (arg0));
          if (m)
@@ -5035,6 +5341,15 @@ fold (expr)
        }
       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
@@ -5042,6 +5357,33 @@ fold (expr)
        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;
+       }
       return t;
 
     case ABS_EXPR:
@@ -5081,20 +5423,19 @@ fold (expr)
                                REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
            }
        }
-      else if (TREE_CODE (arg0) == ABS_EXPR || TREE_CODE (arg0) == NEGATE_EXPR)
-       return build1 (ABS_EXPR, type, TREE_OPERAND (arg0, 0));
-      else
+      else if (TREE_CODE (arg0) == NEGATE_EXPR)
+       return fold (build1 (ABS_EXPR, type, TREE_OPERAND (arg0, 0)));
+      /* Convert fabs((double)float) into (double)fabsf(float).  */
+      else if (TREE_CODE (arg0) == NOP_EXPR
+              && TREE_CODE (type) == REAL_TYPE)
        {
-         /* fabs(sqrt(x)) = sqrt(x) and fabs(exp(x)) = exp(x).  */
-         enum built_in_function fcode = builtin_mathfn_code (arg0);
-         if (fcode == BUILT_IN_SQRT
-             || fcode == BUILT_IN_SQRTF
-             || fcode == BUILT_IN_SQRTL
-             || fcode == BUILT_IN_EXP
-             || fcode == BUILT_IN_EXPF
-             || fcode == BUILT_IN_EXPL)
-           t = arg0;
+         tree targ0 = strip_float_extensions (arg0);
+         if (targ0 != arg0)
+           return convert (type, fold (build1 (ABS_EXPR, TREE_TYPE (targ0),
+                                               targ0)));
        }
+      else if (tree_expr_nonnegative_p (arg0))
+       return arg0;
       return t;
 
     case CONJ_EXPR:
@@ -5181,13 +5522,17 @@ fold (expr)
              if (TREE_CODE (parg0) == MULT_EXPR
                  && TREE_CODE (parg1) != MULT_EXPR)
                return fold (build (PLUS_EXPR, type,
-                                   fold (build (PLUS_EXPR, type, parg0, marg)),
-                                   parg1));
+                                   fold (build (PLUS_EXPR, type,
+                                                convert (type, parg0),
+                                                convert (type, marg))),
+                                   convert (type, parg1)));
              if (TREE_CODE (parg0) != MULT_EXPR
                  && TREE_CODE (parg1) == MULT_EXPR)
                return fold (build (PLUS_EXPR, type,
-                                   fold (build (PLUS_EXPR, type, parg1, marg)),
-                                   parg0));
+                                   fold (build (PLUS_EXPR, type,
+                                                convert (type, parg1),
+                                                convert (type, marg))),
+                                   convert (type, parg0)));
            }
 
          if (TREE_CODE (arg0) == MULT_EXPR && TREE_CODE (arg1) == MULT_EXPR)
@@ -5373,7 +5718,7 @@ fold (expr)
              /* Preserve the MINUS_EXPR if the negative part of the literal is
                 greater than the positive part.  Otherwise, the multiplicative
                 folding code (i.e extract_muldiv) may be fooled in case
-                unsigned constants are substracted, like in the following
+                unsigned constants are subtracted, like in the following
                 example: ((X*2 + 4) - 8U)/2.  */
              if (minus_lit0 && lit0)
                {
@@ -5427,13 +5772,15 @@ fold (expr)
       /* A - (-B) -> A + B */
       if (TREE_CODE (arg1) == NEGATE_EXPR)
        return fold (build (PLUS_EXPR, type, arg0, TREE_OPERAND (arg1, 0)));
-      /* (-A) - CST -> (-CST) - A   for floating point (what about ints ?)  */
-      if (TREE_CODE (arg0) == NEGATE_EXPR && TREE_CODE (arg1) == REAL_CST)
-       return
-         fold (build (MINUS_EXPR, type,
-                      build_real (TREE_TYPE (arg1),
-                                  REAL_VALUE_NEGATE (TREE_REAL_CST (arg1))),
-                      TREE_OPERAND (arg0, 0)));
+      /* (-A) - B -> (-B) - A  where B is easily negated and we can swap.  */
+      if (TREE_CODE (arg0) == NEGATE_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)))
+       return fold (build (MINUS_EXPR, type, negate_expr (arg1),
+                           TREE_OPERAND (arg0, 0)));
 
       if (! FLOAT_TYPE_P (type))
        {
@@ -5454,6 +5801,22 @@ fold (expr)
                                             TREE_OPERAND (arg0, 0),
                                             TREE_OPERAND (arg1, 0))),
                                TREE_OPERAND (arg0, 1)));
+
+         /* Fold A - (A & B) into ~B & A.  */
+         if (!TREE_SIDE_EFFECTS (arg0)
+             && TREE_CODE (arg1) == BIT_AND_EXPR)
+           {
+             if (operand_equal_p (arg0, TREE_OPERAND (arg1, 1), 0))
+               return fold (build (BIT_AND_EXPR, type,
+                                   fold (build1 (BIT_NOT_EXPR, type,
+                                                 TREE_OPERAND (arg1, 0))),
+                                   arg0));
+             if (operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
+               return fold (build (BIT_AND_EXPR, type,
+                                   fold (build1 (BIT_NOT_EXPR, type,
+                                                 TREE_OPERAND (arg1, 1))),
+                                   arg0));
+           }
        }
 
       /* See if ARG1 is zero and X - ARG1 reduces to X.  */
@@ -5502,7 +5865,8 @@ fold (expr)
                                TREE_OPERAND (arg0, 1)));
 
          if (TREE_CODE (arg1) == INTEGER_CST
-             && 0 != (tem = extract_muldiv (TREE_OPERAND (t, 0), arg1,
+             && 0 != (tem = extract_muldiv (TREE_OPERAND (t, 0),
+                                            convert (type, arg1),
                                             code, NULL_TREE)))
            return convert (type, tem);
 
@@ -5530,10 +5894,10 @@ fold (expr)
          /* x*2 is x+x */
          if (! wins && real_twop (arg1)
              && (*lang_hooks.decls.global_bindings_p) () == 0
-             && ! contains_placeholder_p (arg0))
+             && ! CONTAINS_PLACEHOLDER_P (arg0))
            {
              tree arg = save_expr (arg0);
-             return build (PLUS_EXPR, type, arg, arg);
+             return fold (build (PLUS_EXPR, type, arg, arg));
            }
 
          if (flag_unsafe_math_optimizations)
@@ -5541,17 +5905,25 @@ fold (expr)
              enum built_in_function fcode0 = builtin_mathfn_code (arg0);
              enum built_in_function fcode1 = builtin_mathfn_code (arg1);
 
-             /* Optimize sqrt(x)*sqrt(y) as sqrt(x*y).  */
+             /* Optimizations of sqrt(...)*sqrt(...).  */
              if ((fcode0 == BUILT_IN_SQRT && fcode1 == BUILT_IN_SQRT)
                  || (fcode0 == BUILT_IN_SQRTF && fcode1 == BUILT_IN_SQRTF)
                  || (fcode0 == BUILT_IN_SQRTL && fcode1 == BUILT_IN_SQRTL))
                {
-                 tree sqrtfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
-                 tree arg = build (MULT_EXPR, type,
-                                   TREE_VALUE (TREE_OPERAND (arg0, 1)),
-                                   TREE_VALUE (TREE_OPERAND (arg1, 1)));
-                 tree arglist = build_tree_list (NULL_TREE, arg);
-                 return fold (build_function_call_expr (sqrtfn, arglist));
+                 tree sqrtfn, arg, arglist;
+                 tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
+                 tree arg10 = TREE_VALUE (TREE_OPERAND (arg1, 1));
+
+                 /* Optimize sqrt(x)*sqrt(x) as x.  */
+                 if (operand_equal_p (arg00, arg10, 0)
+                     && ! HONOR_SNANS (TYPE_MODE (type)))
+                   return arg00;
+
+                 /* Optimize sqrt(x)*sqrt(y) as sqrt(x*y).  */
+                 sqrtfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+                 arg = fold (build (MULT_EXPR, type, arg00, arg10));
+                 arglist = build_tree_list (NULL_TREE, arg);
+                 return build_function_call_expr (sqrtfn, arglist);
                }
 
              /* Optimize exp(x)*exp(y) as exp(x+y).  */
@@ -5563,8 +5935,78 @@ fold (expr)
                  tree arg = build (PLUS_EXPR, type,
                                    TREE_VALUE (TREE_OPERAND (arg0, 1)),
                                    TREE_VALUE (TREE_OPERAND (arg1, 1)));
-                 tree arglist = build_tree_list (NULL_TREE, arg);
-                 return fold (build_function_call_expr (expfn, arglist));
+                 tree arglist = build_tree_list (NULL_TREE, fold (arg));
+                 return build_function_call_expr (expfn, arglist);
+               }
+
+             /* Optimizations of pow(...)*pow(...).  */
+             if ((fcode0 == BUILT_IN_POW && fcode1 == BUILT_IN_POW)
+                 || (fcode0 == BUILT_IN_POWF && fcode1 == BUILT_IN_POWF)
+                 || (fcode0 == BUILT_IN_POWL && fcode1 == BUILT_IN_POWL))
+               {
+                 tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
+                 tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0,
+                                                                    1)));
+                 tree arg10 = TREE_VALUE (TREE_OPERAND (arg1, 1));
+                 tree arg11 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg1,
+                                                                    1)));
+
+                 /* Optimize pow(x,y)*pow(z,y) as pow(x*z,y).  */
+                 if (operand_equal_p (arg01, arg11, 0))
+                   {
+                     tree powfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+                     tree arg = build (MULT_EXPR, type, arg00, arg10);
+                     tree arglist = tree_cons (NULL_TREE, fold (arg),
+                                               build_tree_list (NULL_TREE,
+                                                                arg01));
+                     return build_function_call_expr (powfn, arglist);
+                   }
+
+                 /* Optimize pow(x,y)*pow(x,z) as pow(x,y+z).  */
+                 if (operand_equal_p (arg00, arg10, 0))
+                   {
+                     tree powfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+                     tree arg = fold (build (PLUS_EXPR, type, arg01, arg11));
+                     tree arglist = tree_cons (NULL_TREE, arg00,
+                                               build_tree_list (NULL_TREE,
+                                                                arg));
+                     return build_function_call_expr (powfn, arglist);
+                   }
+               }
+
+             /* Optimize tan(x)*cos(x) as sin(x).  */
+             if (((fcode0 == BUILT_IN_TAN && fcode1 == BUILT_IN_COS)
+                  || (fcode0 == BUILT_IN_TANF && fcode1 == BUILT_IN_COSF)
+                  || (fcode0 == BUILT_IN_TANL && fcode1 == BUILT_IN_COSL)
+                  || (fcode0 == BUILT_IN_COS && fcode1 == BUILT_IN_TAN)
+                  || (fcode0 == BUILT_IN_COSF && fcode1 == BUILT_IN_TANF)
+                  || (fcode0 == BUILT_IN_COSL && fcode1 == BUILT_IN_TANL))
+                 && operand_equal_p (TREE_VALUE (TREE_OPERAND (arg0, 1)),
+                                     TREE_VALUE (TREE_OPERAND (arg1, 1)), 0))
+               {
+                 tree sinfn;
+
+                 switch (fcode0)
+                   {
+                   case BUILT_IN_TAN:
+                   case BUILT_IN_COS:
+                     sinfn = implicit_built_in_decls[BUILT_IN_SIN];
+                     break;
+                   case BUILT_IN_TANF:
+                   case BUILT_IN_COSF:
+                     sinfn = implicit_built_in_decls[BUILT_IN_SINF];
+                     break;
+                   case BUILT_IN_TANL:
+                   case BUILT_IN_COSL:
+                     sinfn = implicit_built_in_decls[BUILT_IN_SINL];
+                     break;
+                   default:
+                     sinfn = NULL_TREE;
+                   }
+
+                 if (sinfn != NULL_TREE)
+                   return build_function_call_expr (sinfn,
+                                                    TREE_OPERAND (arg0, 1));
                }
            }
        }
@@ -5634,7 +6076,7 @@ fold (expr)
       t1 = distribute_bit_expr (code, type, arg0, arg1);
       if (t1 != NULL_TREE)
        return t1;
-      /* Simplify ((int)c & 0x377) into (int)c, if c is unsigned char.  */
+      /* Simplify ((int)c & 0377) into (int)c, if c is unsigned char.  */
       if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg0) == NOP_EXPR
          && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
        {
@@ -5732,14 +6174,14 @@ fold (expr)
        {
          return fold (build (MULT_EXPR, type,
                              build (RDIV_EXPR, type, arg0,
-                                    TREE_OPERAND (arg1, 0)),
-                             TREE_OPERAND (arg1, 1)));
+                                    TREE_OPERAND (arg1, 0)),
+                             TREE_OPERAND (arg1, 1)));
        }
 
-      /* Optimize x/exp(y) into x*exp(-y).  */
       if (flag_unsafe_math_optimizations)
        {
          enum built_in_function fcode = builtin_mathfn_code (arg1);
+         /* Optimize x/exp(y) into x*exp(-y).  */
          if (fcode == BUILT_IN_EXP
              || fcode == BUILT_IN_EXPF
              || fcode == BUILT_IN_EXPL)
@@ -5747,10 +6189,82 @@ fold (expr)
              tree expfn = TREE_OPERAND (TREE_OPERAND (arg1, 0), 0);
              tree arg = build1 (NEGATE_EXPR, type,
                                 TREE_VALUE (TREE_OPERAND (arg1, 1)));
-             tree arglist = build_tree_list (NULL_TREE, arg);
+             tree arglist = build_tree_list (NULL_TREE, fold (arg));
              arg1 = build_function_call_expr (expfn, arglist);
              return fold (build (MULT_EXPR, type, arg0, arg1));
            }
+
+         /* Optimize x/pow(y,z) into x*pow(y,-z).  */
+         if (fcode == BUILT_IN_POW
+             || fcode == BUILT_IN_POWF
+             || fcode == BUILT_IN_POWL)
+           {
+             tree powfn = TREE_OPERAND (TREE_OPERAND (arg1, 0), 0);
+             tree arg10 = TREE_VALUE (TREE_OPERAND (arg1, 1));
+             tree arg11 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg1, 1)));
+             tree neg11 = fold (build1 (NEGATE_EXPR, type, arg11));
+             tree arglist = tree_cons(NULL_TREE, arg10,
+                                      build_tree_list (NULL_TREE, neg11));
+             arg1 = build_function_call_expr (powfn, arglist);
+             return fold (build (MULT_EXPR, type, arg0, arg1));
+           }
+       }
+
+      if (flag_unsafe_math_optimizations)
+       {
+         enum built_in_function fcode0 = builtin_mathfn_code (arg0);
+         enum built_in_function fcode1 = builtin_mathfn_code (arg1);
+
+         /* Optimize sin(x)/cos(x) as tan(x).  */
+         if (((fcode0 == BUILT_IN_SIN && fcode1 == BUILT_IN_COS)
+              || (fcode0 == BUILT_IN_SINF && fcode1 == BUILT_IN_COSF)
+              || (fcode0 == BUILT_IN_SINL && fcode1 == BUILT_IN_COSL))
+             && operand_equal_p (TREE_VALUE (TREE_OPERAND (arg0, 1)),
+                                 TREE_VALUE (TREE_OPERAND (arg1, 1)), 0))
+           {
+             tree tanfn;
+
+             if (fcode0 == BUILT_IN_SIN)
+               tanfn = implicit_built_in_decls[BUILT_IN_TAN];
+             else if (fcode0 == BUILT_IN_SINF)
+               tanfn = implicit_built_in_decls[BUILT_IN_TANF];
+             else if (fcode0 == BUILT_IN_SINL)
+               tanfn = implicit_built_in_decls[BUILT_IN_TANL];
+             else
+               tanfn = NULL_TREE;
+
+             if (tanfn != NULL_TREE)
+               return build_function_call_expr (tanfn,
+                                                TREE_OPERAND (arg0, 1));
+           }
+
+         /* Optimize cos(x)/sin(x) as 1.0/tan(x).  */
+         if (((fcode0 == BUILT_IN_COS && fcode1 == BUILT_IN_SIN)
+              || (fcode0 == BUILT_IN_COSF && fcode1 == BUILT_IN_SINF)
+              || (fcode0 == BUILT_IN_COSL && fcode1 == BUILT_IN_SINL))
+             && operand_equal_p (TREE_VALUE (TREE_OPERAND (arg0, 1)),
+                                 TREE_VALUE (TREE_OPERAND (arg1, 1)), 0))
+           {
+             tree tanfn;
+
+             if (fcode0 == BUILT_IN_COS)
+               tanfn = implicit_built_in_decls[BUILT_IN_TAN];
+             else if (fcode0 == BUILT_IN_COSF)
+               tanfn = implicit_built_in_decls[BUILT_IN_TANF];
+             else if (fcode0 == BUILT_IN_COSL)
+               tanfn = implicit_built_in_decls[BUILT_IN_TANL];
+             else
+               tanfn = NULL_TREE;
+
+             if (tanfn != NULL_TREE)
+               {
+                 tree tmp = TREE_OPERAND (arg0, 1);
+                 tmp = build_function_call_expr (tanfn, tmp);
+                 return fold (build (RDIV_EXPR, type,
+                                     build_real (type, dconst1),
+                                     tmp));
+               }
+           }
        }
       goto binary;
 
@@ -5890,7 +6404,12 @@ fold (expr)
       tem = invert_truthvalue (arg0);
       /* Avoid infinite recursion.  */
       if (TREE_CODE (tem) == TRUTH_NOT_EXPR)
-       return t;
+       {
+         tem = fold_single_bit_test (code, arg0, arg1, type);
+         if (tem)
+           return tem;
+         return t;
+       }
       return convert (type, tem);
 
     case TRUTH_ANDIF_EXPR:
@@ -6058,20 +6577,42 @@ fold (expr)
              && TREE_CODE (arg1) == NEGATE_EXPR)
            return fold (build (code, type, TREE_OPERAND (arg1, 0),
                                TREE_OPERAND (arg0, 0)));
-         /* (-a) CMP CST -> a swap(CMP) (-CST)  */
-         if (TREE_CODE (arg0) == NEGATE_EXPR && TREE_CODE (arg1) == REAL_CST)
-           return
-             fold (build
-                   (swap_tree_comparison (code), type,
-                    TREE_OPERAND (arg0, 0),
-                    build_real (TREE_TYPE (arg1),
-                                REAL_VALUE_NEGATE (TREE_REAL_CST (arg1)))));
-         /* IEEE doesn't distinguish +0 and -0 in comparisons.  */
-         /* a CMP (-0) -> a CMP 0  */
-         if (TREE_CODE (arg1) == REAL_CST
-             && REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (arg1)))
-           return fold (build (code, type, arg0,
-                               build_real (TREE_TYPE (arg1), dconst0)));
+
+         if (TREE_CODE (arg1) == REAL_CST)
+         {
+           REAL_VALUE_TYPE cst;
+           cst = TREE_REAL_CST (arg1);
+
+           /* (-a) CMP CST -> a swap(CMP) (-CST)  */
+           if (TREE_CODE (arg0) == NEGATE_EXPR)
+             return
+               fold (build (swap_tree_comparison (code), type,
+                            TREE_OPERAND (arg0, 0),
+                            build_real (TREE_TYPE (arg1),
+                                        REAL_VALUE_NEGATE (cst))));
+
+           /* IEEE doesn't distinguish +0 and -0 in comparisons.  */
+           /* a CMP (-0) -> a CMP 0  */
+           if (REAL_VALUE_MINUS_ZERO (cst))
+             return fold (build (code, type, arg0,
+                                 build_real (TREE_TYPE (arg1), dconst0)));
+
+           /* x != NaN is always true, other ops are always false.  */
+           if (REAL_VALUE_ISNAN (cst)
+               && ! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1))))
+             {
+               t = (code == NE_EXPR) ? integer_one_node : integer_zero_node;
+               return omit_one_operand (type, convert (type, t), arg0);
+             }
+
+           /* Fold comparisons against infinity.  */
+           if (REAL_VALUE_ISINF (cst))
+             {
+               tem = fold_inf_compare (code, type, arg0, arg1);
+               if (tem != NULL_TREE)
+                 return tem;
+             }
+         }
 
          /* If this is a comparison of a real constant with a PLUS_EXPR
             or a MINUS_EXPR of a real constant, we can convert it into a
@@ -6087,6 +6628,34 @@ fold (expr)
                                          arg1, TREE_OPERAND (arg0, 1), 0))
              && ! TREE_CONSTANT_OVERFLOW (tem))
            return fold (build (code, type, TREE_OPERAND (arg0, 0), tem));
+
+         /* Likewise, we can simplify a comparison of a real constant with
+            a MINUS_EXPR whose first operand is also a real constant, i.e.
+            (c1 - x) < c2 becomes x > c1-c2.  */
+         if (flag_unsafe_math_optimizations
+             && TREE_CODE (arg1) == REAL_CST
+             && TREE_CODE (arg0) == MINUS_EXPR
+             && TREE_CODE (TREE_OPERAND (arg0, 0)) == REAL_CST
+             && 0 != (tem = const_binop (MINUS_EXPR, TREE_OPERAND (arg0, 0),
+                                         arg1, 0))
+             && ! TREE_CONSTANT_OVERFLOW (tem))
+           return fold (build (swap_tree_comparison (code), type,
+                               TREE_OPERAND (arg0, 1), tem));
+
+         /* Fold comparisons against built-in math functions.  */
+         if (TREE_CODE (arg1) == REAL_CST
+             && flag_unsafe_math_optimizations
+             && ! flag_errno_math)
+           {
+             enum built_in_function fcode = builtin_mathfn_code (arg0);
+
+             if (fcode != END_BUILTINS)
+               {
+                 tem = fold_mathfn_compare (fcode, code, type, arg0, arg1);
+                 if (tem != NULL_TREE)
+                   return tem;
+               }
+           }
        }
 
       /* Convert foo++ == CONST into ++foo == CONST + INCR.
@@ -6532,22 +7101,11 @@ fold (expr)
        return fold (build (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
                            arg0, integer_zero_node));
 
-      /* If we have (A & C) != 0 where C is the sign bit of A, convert
-        this into A < 0.  Similarly for (A & C) == 0 into A >= 0.  */
-      if ((code == EQ_EXPR || code == NE_EXPR)
-         && TREE_CODE (arg0) == BIT_AND_EXPR
-         && integer_zerop (arg1))
-       {
-         tree arg00 = sign_bit_p (TREE_OPERAND (arg0, 0),
-                                  TREE_OPERAND (arg0, 1));
-         if (arg00 != NULL_TREE)
-         {
-           tree stype = (*lang_hooks.types.signed_type) (TREE_TYPE (arg00));
-           return fold (build (code == EQ_EXPR ? GE_EXPR : LT_EXPR, type,
-                               convert (stype, arg00),
-                               convert (stype, integer_zero_node)));
-         }
-       }
+      /* If we have (A & C) != 0 or (A & C) == 0 and C is a power of
+        2, then fold the expression into shifts and logical operations.  */
+      tem = fold_single_bit_test (code, arg0, arg1, type);
+      if (tem)
+       return tem;
 
       /* If X is unsigned, convert X < (1 << Y) into X >> Y == 0
         and similarly for >= into !=.  */
@@ -6582,15 +7140,18 @@ fold (expr)
            case EQ_EXPR:
            case GE_EXPR:
            case LE_EXPR:
-             if (! FLOAT_TYPE_P (TREE_TYPE (arg0)))
+             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;
 
            case NE_EXPR:
-             /* For NE, we can only do this simplification if integer.  */
-             if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
+             /* For NE, we can only do this simplification if integer
+                or we don't honor IEEE floating point NaNs.  */
+             if (FLOAT_TYPE_P (TREE_TYPE (arg0))
+                 && HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
                break;
              /* ... fall through ...  */
            case GT_EXPR:
@@ -6745,7 +7306,7 @@ fold (expr)
 
       /* Optimize comparisons of strlen vs zero to a compare of the
         first character of the string vs zero.  To wit,
-               strlen(ptr) == 0   =>  *ptr == 0
+               strlen(ptr) == 0   =>  *ptr == 0
                strlen(ptr) != 0   =>  *ptr != 0
         Other cases should reduce to one of these two (or a constant)
         due to the return value of strlen being unsigned.  */
@@ -7341,10 +7902,7 @@ fold (expr)
    transformed version).  */
 
 static int
-multiple_of_p (type, top, bottom)
-     tree type;
-     tree top;
-     tree bottom;
+multiple_of_p (tree type, tree top, tree bottom)
 {
   if (operand_equal_p (top, bottom, 0))
     return 1;
@@ -7411,27 +7969,121 @@ multiple_of_p (type, top, bottom)
 /* Return true if `t' is known to be non-negative.  */
 
 int
-tree_expr_nonnegative_p (t)
-     tree t;
+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;
+
+    case REAL_CST:
+      return ! REAL_VALUE_NEGATIVE (TREE_REAL_CST (t));
+
+    case PLUS_EXPR:
+      if (FLOAT_TYPE_P (TREE_TYPE (t)))
+       return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
+              && tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+
+      /* zero_extend(x) + zero_extend(y) is non-negative if x and y are
+        both unsigned and at least 2 bits shorter than the result.  */
+      if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
+         && TREE_CODE (TREE_OPERAND (t, 0)) == NOP_EXPR
+         && TREE_CODE (TREE_OPERAND (t, 1)) == NOP_EXPR)
+       {
+         tree inner1 = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 0), 0));
+         tree inner2 = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 1), 0));
+         if (TREE_CODE (inner1) == INTEGER_TYPE && TREE_UNSIGNED (inner1)
+             && TREE_CODE (inner2) == INTEGER_TYPE && TREE_UNSIGNED (inner2))
+           {
+             unsigned int prec = MAX (TYPE_PRECISION (inner1),
+                                      TYPE_PRECISION (inner2)) + 1;
+             return prec < TYPE_PRECISION (TREE_TYPE (t));
+           }
+       }
+      break;
+
+    case MULT_EXPR:
+      if (FLOAT_TYPE_P (TREE_TYPE (t)))
+       {
+         /* x * x for floating point x is always non-negative.  */
+         if (operand_equal_p (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1), 0))
+           return 1;
+         return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
+                && tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+       }
+
+      /* zero_extend(x) * zero_extend(y) is non-negative if x and y are
+        both unsigned and their total bits is shorter than the result.  */
+      if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
+         && TREE_CODE (TREE_OPERAND (t, 0)) == NOP_EXPR
+         && TREE_CODE (TREE_OPERAND (t, 1)) == NOP_EXPR)
+       {
+         tree inner1 = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 0), 0));
+         tree inner2 = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 1), 0));
+         if (TREE_CODE (inner1) == INTEGER_TYPE && TREE_UNSIGNED (inner1)
+             && TREE_CODE (inner2) == INTEGER_TYPE && TREE_UNSIGNED (inner2))
+           return TYPE_PRECISION (inner1) + TYPE_PRECISION (inner2)
+                  < TYPE_PRECISION (TREE_TYPE (t));
+       }
+      return 0;
+
     case TRUNC_DIV_EXPR:
     case CEIL_DIV_EXPR:
     case FLOOR_DIV_EXPR:
     case ROUND_DIV_EXPR:
       return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
-       && tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+            && tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+
     case TRUNC_MOD_EXPR:
     case CEIL_MOD_EXPR:
     case FLOOR_MOD_EXPR:
     case ROUND_MOD_EXPR:
       return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
+
+    case RDIV_EXPR:
+      return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
+            && tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+
+    case NOP_EXPR:
+      {
+       tree inner_type = TREE_TYPE (TREE_OPERAND (t, 0));
+       tree outer_type = TREE_TYPE (t);
+
+       if (TREE_CODE (outer_type) == REAL_TYPE)
+         {
+           if (TREE_CODE (inner_type) == REAL_TYPE)
+             return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
+           if (TREE_CODE (inner_type) == INTEGER_TYPE)
+             {
+               if (TREE_UNSIGNED (inner_type))
+                 return 1;
+               return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
+             }
+         }
+       else if (TREE_CODE (outer_type) == INTEGER_TYPE)
+         {
+           if (TREE_CODE (inner_type) == REAL_TYPE)
+             return tree_expr_nonnegative_p (TREE_OPERAND (t,0));
+           if (TREE_CODE (inner_type) == INTEGER_TYPE)
+             return TYPE_PRECISION (inner_type) < TYPE_PRECISION (outer_type)
+                     && TREE_UNSIGNED (inner_type);
+         }
+      }
+      break;
+
     case COND_EXPR:
       return tree_expr_nonnegative_p (TREE_OPERAND (t, 1))
        && tree_expr_nonnegative_p (TREE_OPERAND (t, 2));
@@ -7451,25 +8103,82 @@ tree_expr_nonnegative_p (t)
       return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
     case NON_LVALUE_EXPR:
       return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
+    case FLOAT_EXPR:
+      return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
     case RTL_EXPR:
       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));
+
+             default:
+               break;
+             }
+       }
+
+      /* ... fall through ...  */
+
     default:
       if (truth_value_p (TREE_CODE (t)))
        /* Truth values evaluate to 0 or 1, which is nonnegative.  */
        return 1;
-      else
-       /* We don't know sign of `t', so be conservative and return false.  */
-       return 0;
     }
+
+  /* We don't know sign of `t', so be conservative and return false.  */
+  return 0;
 }
 
 /* Return true if `r' is known to be non-negative.
    Only handles constants at the moment.  */
 
 int
-rtl_expr_nonnegative_p (r)
-     rtx r;
+rtl_expr_nonnegative_p (rtx r)
 {
   switch (GET_CODE (r))
     {