OSDN Git Service

2005-03-04 Andrew Pinski <pinskia@physics.uc.edu>
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index eca8c96..517c45d 100644 (file)
@@ -1,6 +1,6 @@
 /* Fold a constant sub-tree into a single node for C-compiler
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -89,8 +89,6 @@ 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 const_binop (enum tree_code, tree, tree, int);
-static tree build_zero_vector (tree);
-static tree fold_convert_const (enum tree_code, tree, tree);
 static enum tree_code invert_tree_comparison (enum tree_code, bool);
 static enum comparison_code comparison_to_compcode (enum tree_code);
 static enum tree_code compcode_to_comparison (enum comparison_code);
@@ -123,8 +121,8 @@ 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 int multiple_of_p (tree, tree, tree);
-static tree fold_binary_op_with_conditional_arg (enum tree_code, tree, tree,
-                                                tree, int);
+static tree fold_binary_op_with_conditional_arg (tree, enum tree_code, 
+                                                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);
@@ -225,7 +223,7 @@ force_fit_type (tree t, int overflowable,
 
   /* First clear all bits that are beyond the type's precision.  */
 
-  if (prec == 2 * HOST_BITS_PER_WIDE_INT)
+  if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
     ;
   else if (prec > HOST_BITS_PER_WIDE_INT)
     high &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
@@ -238,7 +236,7 @@ force_fit_type (tree t, int overflowable,
 
   if (!sign_extended_type)
     /* No sign extension */;
-  else if (prec == 2 * HOST_BITS_PER_WIDE_INT)
+  else if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
     /* Correct width already.  */;
   else if (prec > HOST_BITS_PER_WIDE_INT)
     {
@@ -1484,6 +1482,8 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
       REAL_VALUE_TYPE d1;
       REAL_VALUE_TYPE d2;
       REAL_VALUE_TYPE value;
+      REAL_VALUE_TYPE result;
+      bool inexact;
       tree t, type;
 
       d1 = TREE_REAL_CST (arg1);
@@ -1512,9 +1512,21 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
       else if (REAL_VALUE_ISNAN (d2))
        return arg2;
 
-      REAL_ARITHMETIC (value, code, d1, d2);
+      inexact = real_arithmetic (&value, code, &d1, &d2);
+      real_convert (&result, mode, &value);
+
+      /* Don't constant fold this floating point operation if the
+        result may dependent upon the run-time rounding mode and
+        flag_rounding_math is set, or if GCC's software emulation
+        is unable to accurately represent the result.  */
+      
+      if ((flag_rounding_math
+          || (REAL_MODE_FORMAT_COMPOSITE_P (mode)
+              && !flag_unsafe_math_optimizations))
+         && (inexact || !real_identical (&result, &value)))
+       return NULL_TREE;
 
-      t = build_real (type, real_value_truncate (mode, value));
+      t = build_real (type, result);
 
       TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2);
       TREE_CONSTANT_OVERFLOW (t)
@@ -1686,174 +1698,185 @@ size_diffop (tree arg0, tree arg1)
                                                        arg1, arg0)));
 }
 \f
-/* Construct a vector of zero elements of vector type TYPE.  */
+/* A subroutine of fold_convert_const handling conversions of an
+   INTEGER_CST to another integer type.  */
 
 static tree
-build_zero_vector (tree type)
+fold_convert_const_int_from_int (tree type, tree arg1)
 {
-  tree elem, list;
-  int i, units;
+  tree t;
 
-  elem = fold_convert_const (NOP_EXPR, TREE_TYPE (type), integer_zero_node);
-  units = TYPE_VECTOR_SUBPARTS (type);
+  /* Given an integer constant, make new constant with new type,
+     appropriately sign-extended or truncated.  */
+  t = build_int_cst_wide (type, TREE_INT_CST_LOW (arg1),
+                         TREE_INT_CST_HIGH (arg1));
+
+  t = force_fit_type (t,
+                     /* Don't set the overflow when
+                        converting a pointer  */
+                     !POINTER_TYPE_P (TREE_TYPE (arg1)),
+                     (TREE_INT_CST_HIGH (arg1) < 0
+                      && (TYPE_UNSIGNED (type)
+                          < TYPE_UNSIGNED (TREE_TYPE (arg1))))
+                     | TREE_OVERFLOW (arg1),
+                     TREE_CONSTANT_OVERFLOW (arg1));
 
-  list = NULL_TREE;
-  for (i = 0; i < units; i++)
-    list = tree_cons (NULL_TREE, elem, list);
-  return build_vector (type, list);
+  return t;
 }
 
-
-/* Attempt to fold type conversion operation CODE of expression ARG1 to
-   type TYPE.  If no simplification can be done return NULL_TREE.  */
+/* A subroutine of fold_convert_const handling conversions a REAL_CST
+   to an integer type.  */
 
 static tree
-fold_convert_const (enum tree_code code, tree type, tree arg1)
+fold_convert_const_int_from_real (enum tree_code code, tree type, tree arg1)
 {
   int overflow = 0;
   tree t;
 
-  if (TREE_TYPE (arg1) == type)
-    return arg1;
+  /* The following code implements the floating point to integer
+     conversion rules required by the Java Language Specification,
+     that IEEE NaNs are mapped to zero and values that overflow
+     the target precision saturate, i.e. values greater than
+     INT_MAX are mapped to INT_MAX, and values less than INT_MIN
+     are mapped to INT_MIN.  These semantics are allowed by the
+     C and C++ standards that simply state that the behavior of
+     FP-to-integer conversion is unspecified upon overflow.  */
 
-  if (POINTER_TYPE_P (type) || INTEGRAL_TYPE_P (type))
+  HOST_WIDE_INT high, low;
+  REAL_VALUE_TYPE r;
+  REAL_VALUE_TYPE x = TREE_REAL_CST (arg1);
+
+  switch (code)
     {
-      if (TREE_CODE (arg1) == INTEGER_CST)
-       {
-         /* If we would build a constant wider than GCC supports,
-            leave the conversion unfolded.  */
-         if (TYPE_PRECISION (type) > 2 * HOST_BITS_PER_WIDE_INT)
-           return NULL_TREE;
-
-         /* Given an integer constant, make new constant with new type,
-            appropriately sign-extended or truncated.  */
-         t = build_int_cst_wide (type, TREE_INT_CST_LOW (arg1),
-                                 TREE_INT_CST_HIGH (arg1));
-
-         t = force_fit_type (t,
-                             /* Don't set the overflow when
-                                converting a pointer  */
-                             !POINTER_TYPE_P (TREE_TYPE (arg1)),
-                             (TREE_INT_CST_HIGH (arg1) < 0
-                              && (TYPE_UNSIGNED (type)
-                                  < TYPE_UNSIGNED (TREE_TYPE (arg1))))
-                             | TREE_OVERFLOW (arg1),
-                             TREE_CONSTANT_OVERFLOW (arg1));
-         return t;
-       }
-      else if (TREE_CODE (arg1) == REAL_CST)
-       {
-         /* The following code implements the floating point to integer
-            conversion rules required by the Java Language Specification,
-            that IEEE NaNs are mapped to zero and values that overflow
-            the target precision saturate, i.e. values greater than
-            INT_MAX are mapped to INT_MAX, and values less than INT_MIN
-            are mapped to INT_MIN.  These semantics are allowed by the
-            C and C++ standards that simply state that the behavior of
-            FP-to-integer conversion is unspecified upon overflow.  */
+    case FIX_TRUNC_EXPR:
+      real_trunc (&r, VOIDmode, &x);
+      break;
+
+    case FIX_CEIL_EXPR:
+      real_ceil (&r, VOIDmode, &x);
+      break;
 
-         HOST_WIDE_INT high, low;
-         REAL_VALUE_TYPE r;
-         REAL_VALUE_TYPE x = TREE_REAL_CST (arg1);
+    case FIX_FLOOR_EXPR:
+      real_floor (&r, VOIDmode, &x);
+      break;
 
-         switch (code)
-           {
-           case FIX_TRUNC_EXPR:
-             real_trunc (&r, VOIDmode, &x);
-             break;
+    case FIX_ROUND_EXPR:
+      real_round (&r, VOIDmode, &x);
+      break;
 
-           case FIX_CEIL_EXPR:
-             real_ceil (&r, VOIDmode, &x);
-             break;
+    default:
+      gcc_unreachable ();
+    }
 
-           case FIX_FLOOR_EXPR:
-             real_floor (&r, VOIDmode, &x);
-             break;
+  /* If R is NaN, return zero and show we have an overflow.  */
+  if (REAL_VALUE_ISNAN (r))
+    {
+      overflow = 1;
+      high = 0;
+      low = 0;
+    }
 
-           case FIX_ROUND_EXPR:
-             real_round (&r, VOIDmode, &x);
-             break;
+  /* See if R is less than the lower bound or greater than the
+     upper bound.  */
 
-           default:
-             gcc_unreachable ();
-           }
+  if (! overflow)
+    {
+      tree lt = TYPE_MIN_VALUE (type);
+      REAL_VALUE_TYPE l = real_value_from_int_cst (NULL_TREE, lt);
+      if (REAL_VALUES_LESS (r, l))
+       {
+         overflow = 1;
+         high = TREE_INT_CST_HIGH (lt);
+         low = TREE_INT_CST_LOW (lt);
+       }
+    }
 
-         /* If R is NaN, return zero and show we have an overflow.  */
-         if (REAL_VALUE_ISNAN (r))
+  if (! overflow)
+    {
+      tree ut = TYPE_MAX_VALUE (type);
+      if (ut)
+       {
+         REAL_VALUE_TYPE u = real_value_from_int_cst (NULL_TREE, ut);
+         if (REAL_VALUES_LESS (u, r))
            {
              overflow = 1;
-             high = 0;
-             low = 0;
+             high = TREE_INT_CST_HIGH (ut);
+             low = TREE_INT_CST_LOW (ut);
            }
+       }
+    }
 
-         /* See if R is less than the lower bound or greater than the
-            upper bound.  */
+  if (! overflow)
+    REAL_VALUE_TO_INT (&low, &high, r);
 
-         if (! overflow)
-           {
-             tree lt = TYPE_MIN_VALUE (type);
-             REAL_VALUE_TYPE l = real_value_from_int_cst (NULL_TREE, lt);
-             if (REAL_VALUES_LESS (r, l))
-               {
-                 overflow = 1;
-                 high = TREE_INT_CST_HIGH (lt);
-                 low = TREE_INT_CST_LOW (lt);
-               }
-           }
+  t = build_int_cst_wide (type, low, high);
 
-         if (! overflow)
-           {
-             tree ut = TYPE_MAX_VALUE (type);
-             if (ut)
-               {
-                 REAL_VALUE_TYPE u = real_value_from_int_cst (NULL_TREE, ut);
-                 if (REAL_VALUES_LESS (u, r))
-                   {
-                     overflow = 1;
-                     high = TREE_INT_CST_HIGH (ut);
-                     low = TREE_INT_CST_LOW (ut);
-                   }
-               }
-           }
+  t = force_fit_type (t, -1, overflow | TREE_OVERFLOW (arg1),
+                     TREE_CONSTANT_OVERFLOW (arg1));
+  return t;
+}
 
-         if (! overflow)
-           REAL_VALUE_TO_INT (&low, &high, r);
+/* A subroutine of fold_convert_const handling conversions a REAL_CST
+   to another floating point type.  */
 
-         t = build_int_cst_wide (type, low, high);
+static tree
+fold_convert_const_real_from_real (tree type, tree arg1)
+{
+  REAL_VALUE_TYPE value;
+  tree t;
 
-         t = force_fit_type (t, -1, overflow | TREE_OVERFLOW (arg1),
-                             TREE_CONSTANT_OVERFLOW (arg1));
-         return t;
-       }
+  real_convert (&value, TYPE_MODE (type), &TREE_REAL_CST (arg1));
+  t = build_real (type, value);
+
+  TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1);
+  TREE_CONSTANT_OVERFLOW (t)
+    = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
+  return t;
+}
+
+/* Attempt to fold type conversion operation CODE of expression ARG1 to
+   type TYPE.  If no simplification can be done return NULL_TREE.  */
+
+static tree
+fold_convert_const (enum tree_code code, tree type, tree arg1)
+{
+  if (TREE_TYPE (arg1) == type)
+    return arg1;
+
+  if (POINTER_TYPE_P (type) || INTEGRAL_TYPE_P (type))
+    {
+      if (TREE_CODE (arg1) == INTEGER_CST)
+       return fold_convert_const_int_from_int (type, arg1);
+      else if (TREE_CODE (arg1) == REAL_CST)
+       return fold_convert_const_int_from_real (code, type, arg1);
     }
   else if (TREE_CODE (type) == REAL_TYPE)
     {
       if (TREE_CODE (arg1) == INTEGER_CST)
        return build_real_from_int_cst (type, arg1);
       if (TREE_CODE (arg1) == REAL_CST)
-       {
-         if (REAL_VALUE_ISNAN (TREE_REAL_CST (arg1)))
-           {
-             /* We make a copy of ARG1 so that we don't modify an
-                existing constant tree.  */
-             t = copy_node (arg1);
-             TREE_TYPE (t) = type;
-             return t;
-           }
-
-         t = build_real (type,
-                         real_value_truncate (TYPE_MODE (type),
-                                              TREE_REAL_CST (arg1)));
-
-         TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1);
-         TREE_CONSTANT_OVERFLOW (t)
-           = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
-         return t;
-       }
+       return fold_convert_const_real_from_real (type, arg1);
     }
   return NULL_TREE;
 }
 
+/* Construct a vector of zero elements of vector type TYPE.  */
+
+static tree
+build_zero_vector (tree type)
+{
+  tree elem, list;
+  int i, units;
+
+  elem = fold_convert_const (NOP_EXPR, TREE_TYPE (type), integer_zero_node);
+  units = TYPE_VECTOR_SUBPARTS (type);
+  
+  list = NULL_TREE;
+  for (i = 0; i < units; i++)
+    list = tree_cons (NULL_TREE, elem, list);
+  return build_vector (type, list);
+}
+
 /* Convert expression ARG to type TYPE.  Used by the middle-end for
    simple conversions in preference to calling the front-end's convert.  */
 
@@ -2424,7 +2447,7 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
   if (flags & OEP_ONLY_CONST)
     return 0;
 
-/* Define macros to test an operan from arg0 and arg1 for equality and a
+/* Define macros to test an operand from arg0 and arg1 for equality and a
    variant that allows null and views null as being different from any
    non-null value.  In the latter case, if either is null, the both
    must be; otherwise, do the normal comparison.  */
@@ -2913,8 +2936,7 @@ invert_truthvalue (tree arg)
   switch (code)
     {
     case INTEGER_CST:
-      return fold_convert (type,
-                          build_int_cst (NULL_TREE, integer_zerop (arg)));
+      return constant_boolean_node (integer_zerop (arg), type);
 
     case TRUTH_AND_EXPR:
       return build2 (TRUTH_OR_EXPR, type,
@@ -3053,8 +3075,20 @@ static tree
 make_bit_field_ref (tree inner, tree type, int bitsize, int bitpos,
                    int unsignedp)
 {
-  tree result = build3 (BIT_FIELD_REF, type, inner,
-                       size_int (bitsize), bitsize_int (bitpos));
+  tree result;
+
+  if (bitpos == 0)
+    {
+      tree size = TYPE_SIZE (TREE_TYPE (inner));
+      if ((INTEGRAL_TYPE_P (TREE_TYPE (inner))
+          || POINTER_TYPE_P (TREE_TYPE (inner)))
+         && host_integerp (size, 0) 
+         && tree_low_cst (size, 0) == bitsize)
+       return fold_convert (type, inner);
+    }
+
+  result = build3 (BIT_FIELD_REF, type, inner,
+                  size_int (bitsize), bitsize_int (bitpos));
 
   BIT_FIELD_REF_UNSIGNED (result) = unsignedp;
 
@@ -3102,7 +3136,7 @@ optimize_bit_field_compare (enum tree_code code, tree compare_type,
      do anything if the inner expression is a PLACEHOLDER_EXPR since we
      then will no longer be able to replace it.  */
   linner = get_inner_reference (lhs, &lbitsize, &lbitpos, &offset, &lmode,
-                               &lunsignedp, &lvolatilep);
+                               &lunsignedp, &lvolatilep, false);
   if (linner == lhs || lbitsize == GET_MODE_BITSIZE (lmode) || lbitsize < 0
       || offset != 0 || TREE_CODE (linner) == PLACEHOLDER_EXPR)
     return 0;
@@ -3112,7 +3146,7 @@ optimize_bit_field_compare (enum tree_code code, tree compare_type,
      /* If this is not a constant, we can only do something if bit positions,
        sizes, and signedness are the same.  */
      rinner = get_inner_reference (rhs, &rbitsize, &rbitpos, &offset, &rmode,
-                                  &runsignedp, &rvolatilep);
+                                  &runsignedp, &rvolatilep, false);
 
      if (rinner == rhs || lbitpos != rbitpos || lbitsize != rbitsize
         || lunsignedp != runsignedp || offset != 0
@@ -3288,7 +3322,7 @@ decode_field_reference (tree exp, HOST_WIDE_INT *pbitsize,
     }
 
   inner = get_inner_reference (exp, pbitsize, pbitpos, &offset, pmode,
-                              punsignedp, pvolatilep);
+                              punsignedp, pvolatilep, false);
   if ((inner == exp && and_mask == 0)
       || *pbitsize < 0 || offset != 0
       || TREE_CODE (inner) == PLACEHOLDER_EXPR)
@@ -3550,7 +3584,7 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
 
       if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
        {
-         if (first_rtl_op (code) > 0)
+         if (TREE_CODE_LENGTH (code) > 0)
            arg0 = TREE_OPERAND (exp, 0);
          if (TREE_CODE_CLASS (code) == tcc_comparison
              || TREE_CODE_CLASS (code) == tcc_unary
@@ -5347,13 +5381,61 @@ constant_boolean_node (int value, tree type)
     return value ? integer_one_node : integer_zero_node;
   else if (type == boolean_type_node)
     return value ? boolean_true_node : boolean_false_node;
-  else if (TREE_CODE (type) == BOOLEAN_TYPE)
-    return lang_hooks.truthvalue_conversion (value ? integer_one_node
-                                                  : integer_zero_node);
   else
     return build_int_cst (type, value);
 }
 
+
+/* Return true if expr looks like an ARRAY_REF and set base and
+   offset to the appropriate trees.  If there is no offset,
+   offset is set to NULL_TREE.  */
+
+static bool
+extract_array_ref (tree expr, tree *base, tree *offset)
+{
+  /* We have to be careful with stripping nops as with the
+     base type the meaning of the offset can change.  */
+  tree inner_expr = expr;
+  STRIP_NOPS (inner_expr);
+  /* One canonical form is a PLUS_EXPR with the first
+     argument being an ADDR_EXPR with a possible NOP_EXPR
+     attached.  */
+  if (TREE_CODE (expr) == PLUS_EXPR)
+    {
+      tree op0 = TREE_OPERAND (expr, 0);
+      STRIP_NOPS (op0);
+      if (TREE_CODE (op0) == ADDR_EXPR)
+       {
+         *base = TREE_OPERAND (expr, 0);
+         *offset = TREE_OPERAND (expr, 1);
+         return true;
+       }
+    }
+  /* Other canonical form is an ADDR_EXPR of an ARRAY_REF,
+     which we transform into an ADDR_EXPR with appropriate
+     offset.  For other arguments to the ADDR_EXPR we assume
+     zero offset and as such do not care about the ADDR_EXPR
+     type and strip possible nops from it.  */
+  else if (TREE_CODE (inner_expr) == ADDR_EXPR)
+    {
+      tree op0 = TREE_OPERAND (inner_expr, 0);
+      if (TREE_CODE (op0) == ARRAY_REF)
+       {
+         *base = build_fold_addr_expr (TREE_OPERAND (op0, 0));
+         *offset = TREE_OPERAND (op0, 1);
+       }
+      else
+       {
+         *base = inner_expr;
+         *offset = NULL_TREE;
+       }
+      return true;
+    }
+
+  return false;
+}
+
+
 /* Transform `a + (b ? x : y)' into `b ? (a + x) : (a + y)'.
    Transform, `a + (x < y)' into `(x < y) ? (a + 1) : (a + 0)'.  Here
    CODE corresponds to the `+', COND to the `(b ? x : y)' or `(x < y)'
@@ -5364,15 +5446,20 @@ constant_boolean_node (int value, tree type)
    possible.  */
 
 static tree
-fold_binary_op_with_conditional_arg (enum tree_code code, tree type,
-                                    tree cond, tree arg, int cond_first_p)
+fold_binary_op_with_conditional_arg (tree t, enum tree_code code, tree cond,
+                                    tree arg, int cond_first_p)
 {
+  const tree type = TREE_TYPE (t);
+  tree cond_type = cond_first_p ? TREE_TYPE (TREE_OPERAND (t, 0)) 
+                               : TREE_TYPE (TREE_OPERAND (t, 1));
+  tree arg_type = cond_first_p ? TREE_TYPE (TREE_OPERAND (t, 1)) 
+                              : TREE_TYPE (TREE_OPERAND (t, 0));
   tree test, true_value, false_value;
   tree lhs = NULL_TREE;
   tree rhs = NULL_TREE;
 
   /* This transformation is only worthwhile if we don't have to wrap
-     arg in a SAVE_EXPR, and the operation can be simplified on atleast
+     arg in a SAVE_EXPR, and the operation can be simplified on at least
      one of the branches once its pushed inside the COND_EXPR.  */
   if (!TREE_CONSTANT (arg))
     return NULL_TREE;
@@ -5398,12 +5485,19 @@ fold_binary_op_with_conditional_arg (enum tree_code code, tree type,
       false_value = constant_boolean_node (false, testtype);
     }
 
+  arg = fold_convert (arg_type, arg);
   if (lhs == 0)
-    lhs = fold (cond_first_p ? build2 (code, type, true_value, arg)
+    {
+      true_value = fold_convert (cond_type, true_value);
+      lhs = fold (cond_first_p ? build2 (code, type, true_value, arg)
                             : build2 (code, type, arg, true_value));
+    }
   if (rhs == 0)
-    rhs = fold (cond_first_p ? build2 (code, type, false_value, arg)
+    {
+      false_value = fold_convert (cond_type, false_value);
+      rhs = fold (cond_first_p ? build2 (code, type, false_value, arg)
                             : build2 (code, type, arg, false_value));
+    }
 
   test = fold (build3 (COND_EXPR, type, test, lhs, rhs));
   return fold_convert (type, test);
@@ -5811,22 +5905,6 @@ 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)
@@ -5876,7 +5954,8 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
         operations as unsigned.  If we must use the AND, we have a choice.
         Normally unsigned is faster, but for some machines signed is.  */
 #ifdef LOAD_EXTEND_OP
-      ops_unsigned = (LOAD_EXTEND_OP (operand_mode) == SIGN_EXTEND ? 0 : 1);
+      ops_unsigned = (LOAD_EXTEND_OP (operand_mode) == SIGN_EXTEND 
+                     && !flag_syntax_only) ? 0 : 1;
 #else
       ops_unsigned = 1;
 #endif
@@ -5990,7 +6069,10 @@ fold_widened_comparison (enum tree_code code, tree type, tree arg0, tree arg1)
   if (arg0_unw == arg0)
     return NULL_TREE;
   shorter_type = TREE_TYPE (arg0_unw);
-  
+
+  if (TYPE_PRECISION (TREE_TYPE (arg0)) <= TYPE_PRECISION (shorter_type))
+    return NULL_TREE;
+
   arg1_unw = get_unwidened (arg1, shorter_type);
   if (!arg1_unw)
     return NULL_TREE;
@@ -6000,6 +6082,7 @@ fold_widened_comparison (enum tree_code code, tree type, tree arg0, tree arg1)
        || TYPE_UNSIGNED (TREE_TYPE (arg0)) == TYPE_UNSIGNED (shorter_type))
       && (TREE_TYPE (arg1_unw) == shorter_type
          || (TREE_CODE (arg1_unw) == INTEGER_CST
+             && TREE_CODE (shorter_type) == INTEGER_TYPE
              && int_fits_type_p (arg1_unw, shorter_type))))
     return fold (build (code, type, arg0_unw,
                        fold_convert (shorter_type, arg1_unw)));
@@ -6022,27 +6105,27 @@ fold_widened_comparison (enum tree_code code, tree type, tree arg0, tree arg1)
     {
     case EQ_EXPR:
       if (above || below)
-       return constant_boolean_node (false, type);
+       return omit_one_operand (type, integer_zero_node, arg0);
       break;
 
     case NE_EXPR:
       if (above || below)
-       return constant_boolean_node (true, type);
+       return omit_one_operand (type, integer_one_node, arg0);
       break;
 
     case LT_EXPR:
     case LE_EXPR:
       if (above)
-       return constant_boolean_node (true, type);
+       return omit_one_operand (type, integer_one_node, arg0);
       else if (below)
-       return constant_boolean_node (false, type);;
+       return omit_one_operand (type, integer_zero_node, arg0);
 
     case GT_EXPR:
     case GE_EXPR:
       if (above)
-       return constant_boolean_node (false, type);
+       return omit_one_operand (type, integer_zero_node, arg0);
       else if (below)
-       return constant_boolean_node (true, type);;
+       return omit_one_operand (type, integer_one_node, arg0);
 
     default:
       break;
@@ -6097,12 +6180,12 @@ fold_sign_changed_comparison (enum tree_code code, tree type,
 }
 
 /* Tries to replace &a[idx] CODE s * delta with &a[idx CODE delta], if s is
-   step of the array.  TYPE is the type of the expression.  ADDR is the address.
-   MULT is the multiplicative expression.  If the function succeeds, the new
-   address expression is returned.  Otherwise NULL_TREE is returned.  */
+   step of the array.  ADDR is the address. MULT is the multiplicative expression.
+   If the function succeeds, the new address expression is returned.  Otherwise
+   NULL_TREE is returned.  */
 
 static tree
-try_move_mult_to_index (tree type, enum tree_code code, tree addr, tree mult)
+try_move_mult_to_index (enum tree_code code, tree addr, tree mult)
 {
   tree s, delta, step;
   tree arg0 = TREE_OPERAND (mult, 0), arg1 = TREE_OPERAND (mult, 1);
@@ -6139,7 +6222,7 @@ try_move_mult_to_index (tree type, enum tree_code code, tree addr, tree mult)
 
          /* If the type sizes do not match, we might run into problems
             when one of them would overflow.  */
-         if (TYPE_PRECISION (itype) != TYPE_PRECISION (type))
+         if (TYPE_PRECISION (itype) != TYPE_PRECISION (TREE_TYPE (s)))
            continue;
 
          if (!operand_equal_p (step, fold_convert (itype, s), 0))
@@ -6171,7 +6254,7 @@ try_move_mult_to_index (tree type, enum tree_code code, tree addr, tree mult)
                                        TREE_OPERAND (pos, 1),
                                        delta));
 
-  return build1 (ADDR_EXPR, type, ret);
+  return build1 (ADDR_EXPR, TREE_TYPE (addr), ret);
 }
 
 
@@ -6219,154 +6302,341 @@ fold_to_nonsharp_ineq_using_bound (tree ineq, tree bound)
   return fold (build2 (GE_EXPR, type, a, y));
 }
 
-/* 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.
-   NOP_EXPR conversions may be removed freely (as long as we
-   are careful not to change the type of the overall expression).
-   We cannot simplify through a CONVERT_EXPR, FIX_EXPR or FLOAT_EXPR,
-   but we can constant-fold them if they have constant operands.  */
+/* Fold complex addition when both components are accessible by parts.
+   Return non-null if successful.  CODE should be PLUS_EXPR for addition,
+   or MINUS_EXPR for subtraction.  */
 
-#ifdef ENABLE_FOLD_CHECKING
-# define fold(x) fold_1 (x)
-static tree fold_1 (tree);
-static
-#endif
-tree
-fold (tree expr)
+static tree
+fold_complex_add (tree type, tree ac, tree bc, enum tree_code code)
 {
-  const tree t = expr;
-  const tree type = TREE_TYPE (expr);
-  tree t1 = NULL_TREE;
-  tree tem;
-  tree arg0 = NULL_TREE, arg1 = NULL_TREE;
-  enum tree_code code = TREE_CODE (t);
-  enum tree_code_class kind = TREE_CODE_CLASS (code);
+  tree ar, ai, br, bi, rr, ri, inner_type;
 
-  /* WINS will be nonzero when the switch is done
-     if all operands are constant.  */
-  int wins = 1;
+  if (TREE_CODE (ac) == COMPLEX_EXPR)
+    ar = TREE_OPERAND (ac, 0), ai = TREE_OPERAND (ac, 1);
+  else if (TREE_CODE (ac) == COMPLEX_CST)
+    ar = TREE_REALPART (ac), ai = TREE_IMAGPART (ac);
+  else
+    return NULL;
 
-  /* Return right away if a constant.  */
-  if (kind == tcc_constant)
-    return t;
+  if (TREE_CODE (bc) == COMPLEX_EXPR)
+    br = TREE_OPERAND (bc, 0), bi = TREE_OPERAND (bc, 1);
+  else if (TREE_CODE (bc) == COMPLEX_CST)
+    br = TREE_REALPART (bc), bi = TREE_IMAGPART (bc);
+  else
+    return NULL;
 
-  if (code == NOP_EXPR || code == FLOAT_EXPR || code == CONVERT_EXPR)
-    {
-      tree subop;
+  inner_type = TREE_TYPE (type);
 
-      /* Special case for conversion ops that can have fixed point args.  */
-      arg0 = TREE_OPERAND (t, 0);
+  rr = fold (build2 (code, inner_type, ar, br));  
+  ri = fold (build2 (code, inner_type, ai, bi));  
 
-      /* Don't use STRIP_NOPS, because signedness of argument type matters.  */
-      if (arg0 != 0)
-       STRIP_SIGN_NOPS (arg0);
+  return fold (build2 (COMPLEX_EXPR, type, rr, ri));
+}
 
-      if (arg0 != 0 && TREE_CODE (arg0) == COMPLEX_CST)
-       subop = TREE_REALPART (arg0);
-      else
-       subop = arg0;
+/* Perform some simplifications of complex multiplication when one or more
+   of the components are constants or zeros.  Return non-null if successful.  */
 
-      if (subop != 0 && TREE_CODE (subop) != INTEGER_CST
-         && TREE_CODE (subop) != REAL_CST)
-       /* Note that TREE_CONSTANT isn't enough:
-          static var addresses are constant but we can't
-          do arithmetic on them.  */
-       wins = 0;
-    }
-  else if (IS_EXPR_CODE_CLASS (kind))
-    {
-      int len = first_rtl_op (code);
-      int i;
-      for (i = 0; i < len; i++)
-       {
-         tree op = TREE_OPERAND (t, i);
-         tree subop;
+tree
+fold_complex_mult_parts (tree type, tree ar, tree ai, tree br, tree bi)
+{
+  tree rr, ri, inner_type, zero;
+  bool ar0, ai0, br0, bi0, bi1;
 
-         if (op == 0)
-           continue;           /* Valid for CALL_EXPR, at least.  */
+  inner_type = TREE_TYPE (type);
+  zero = NULL;
 
-         /* Strip any conversions that don't change the mode.  This is
-            safe for every expression, except for a comparison expression
-            because its signedness is derived from its operands.  So, in
-            the latter case, only strip conversions that don't change the
-            signedness.
+  if (SCALAR_FLOAT_TYPE_P (inner_type))
+    {
+      ar0 = ai0 = br0 = bi0 = bi1 = false;
 
-            Note that this is done as an internal manipulation within the
-            constant folder, in order to find the simplest representation
-            of the arguments so that their form can be studied.  In any
-            cases, the appropriate type conversions should be put back in
-            the tree that will get out of the constant folder.  */
-         if (kind == tcc_comparison)
-           STRIP_SIGN_NOPS (op);
-         else
-           STRIP_NOPS (op);
+      /* We're only interested in +0.0 here, thus we don't use real_zerop.  */
 
-         if (TREE_CODE (op) == COMPLEX_CST)
-           subop = TREE_REALPART (op);
-         else
-           subop = op;
+      if (TREE_CODE (ar) == REAL_CST
+         && REAL_VALUES_IDENTICAL (TREE_REAL_CST (ar), dconst0))
+       ar0 = true, zero = ar;
 
-         if (TREE_CODE (subop) != INTEGER_CST
-             && TREE_CODE (subop) != REAL_CST)
-           /* Note that TREE_CONSTANT isn't enough:
-              static var addresses are constant but we can't
-              do arithmetic on them.  */
-           wins = 0;
+      if (TREE_CODE (ai) == REAL_CST
+         && REAL_VALUES_IDENTICAL (TREE_REAL_CST (ai), dconst0))
+       ai0 = true, zero = ai;
 
-         if (i == 0)
-           arg0 = op;
-         else if (i == 1)
-           arg1 = op;
+      if (TREE_CODE (br) == REAL_CST
+         && REAL_VALUES_IDENTICAL (TREE_REAL_CST (br), dconst0))
+       br0 = true, zero = br;
+
+      if (TREE_CODE (bi) == REAL_CST)
+       {
+         if (REAL_VALUES_IDENTICAL (TREE_REAL_CST (bi), dconst0))
+           bi0 = true, zero = bi;
+         else if (REAL_VALUES_IDENTICAL (TREE_REAL_CST (bi), dconst1))
+           bi1 = true;
+       }
+    }
+  else
+    {
+      ar0 = integer_zerop (ar);
+      if (ar0)
+       zero = ar;
+      ai0 = integer_zerop (ai);
+      if (ai0)
+       zero = ai;
+      br0 = integer_zerop (br);
+      if (br0)
+       zero = br;
+      bi0 = integer_zerop (bi);
+      if (bi0)
+       {
+         zero = bi;
+         bi1 = false;
        }
+      else
+       bi1 = integer_onep (bi);
     }
 
-  /* If this is a commutative operation, and ARG0 is a constant, move it
-     to ARG1 to reduce the number of tests below.  */
-  if (commutative_tree_code (code)
-      && tree_swap_operands_p (arg0, arg1, true))
-    return fold (build2 (code, type, TREE_OPERAND (t, 1),
-                        TREE_OPERAND (t, 0)));
+  /* We won't optimize anything below unless something is zero.  */
+  if (zero == NULL)
+    return NULL;
 
-  /* Now WINS is set as described above,
-     ARG0 is the first operand of EXPR,
-     and ARG1 is the second operand (if it has more than one operand).
+  if (ai0 && br0 && bi1)
+    {
+      rr = zero;
+      ri = ar;
+    }
+  else if (ai0 && bi0)
+    {
+      rr = fold (build2 (MULT_EXPR, inner_type, ar, br));
+      ri = zero;
+    }
+  else if (ai0 && br0)
+    {
+      rr = zero;
+      ri = fold (build2 (MULT_EXPR, inner_type, ar, bi));
+    }
+  else if (ar0 && bi0)
+    {
+      rr = zero;
+      ri = fold (build2 (MULT_EXPR, inner_type, ai, br));
+    }
+  else if (ar0 && br0)
+    {
+      rr = fold (build2 (MULT_EXPR, inner_type, ai, bi));
+      rr = fold (build1 (NEGATE_EXPR, inner_type, rr));
+      ri = zero;
+    }
+  else if (bi0)
+    {
+      rr = fold (build2 (MULT_EXPR, inner_type, ar, br));
+      ri = fold (build2 (MULT_EXPR, inner_type, ai, br));
+    }
+  else if (ai0)
+    {
+      rr = fold (build2 (MULT_EXPR, inner_type, ar, br));
+      ri = fold (build2 (MULT_EXPR, inner_type, ar, bi));
+    }
+  else if (br0)
+    {
+      rr = fold (build2 (MULT_EXPR, inner_type, ai, bi));
+      rr = fold (build1 (NEGATE_EXPR, inner_type, rr));
+      ri = fold (build2 (MULT_EXPR, inner_type, ar, bi));
+    }
+  else if (ar0)
+    {
+      rr = fold (build2 (MULT_EXPR, inner_type, ai, bi));
+      rr = fold (build1 (NEGATE_EXPR, inner_type, rr));
+      ri = fold (build2 (MULT_EXPR, inner_type, ai, br));
+    }
+  else
+    return NULL;
 
-     First check for cases where an arithmetic operation is applied to a
-     compound, conditional, or comparison operation.  Push the arithmetic
-     operation inside the compound or conditional to see if any folding
-     can then be done.  Convert comparison to conditional for this purpose.
-     The also optimizes non-constant cases that used to be done in
-     expand_expr.
+  return fold (build2 (COMPLEX_EXPR, type, rr, ri));
+}
 
-     Before we do that, see if this is a BIT_AND_EXPR or a BIT_IOR_EXPR,
-     one of the operands is a comparison and the other is a comparison, a
-     BIT_AND_EXPR with the constant 1, or a truth value.  In that case, the
-     code below would make the expression more complex.  Change it to a
-     TRUTH_{AND,OR}_EXPR.  Likewise, convert a similar NE_EXPR to
-     TRUTH_XOR_EXPR and an EQ_EXPR to the inversion of a TRUTH_XOR_EXPR.  */
+static tree
+fold_complex_mult (tree type, tree ac, tree bc)
+{
+  tree ar, ai, br, bi;
 
-  if ((code == BIT_AND_EXPR || code == BIT_IOR_EXPR
-       || code == EQ_EXPR || code == NE_EXPR)
-      && ((truth_value_p (TREE_CODE (arg0))
-          && (truth_value_p (TREE_CODE (arg1))
-              || (TREE_CODE (arg1) == BIT_AND_EXPR
-                  && integer_onep (TREE_OPERAND (arg1, 1)))))
-         || (truth_value_p (TREE_CODE (arg1))
-             && (truth_value_p (TREE_CODE (arg0))
-                 || (TREE_CODE (arg0) == BIT_AND_EXPR
-                     && integer_onep (TREE_OPERAND (arg0, 1)))))))
+  if (TREE_CODE (ac) == COMPLEX_EXPR)
+    ar = TREE_OPERAND (ac, 0), ai = TREE_OPERAND (ac, 1);
+  else if (TREE_CODE (ac) == COMPLEX_CST)
+    ar = TREE_REALPART (ac), ai = TREE_IMAGPART (ac);
+  else
+    return NULL;
+
+  if (TREE_CODE (bc) == COMPLEX_EXPR)
+    br = TREE_OPERAND (bc, 0), bi = TREE_OPERAND (bc, 1);
+  else if (TREE_CODE (bc) == COMPLEX_CST)
+    br = TREE_REALPART (bc), bi = TREE_IMAGPART (bc);
+  else
+    return NULL;
+
+  return fold_complex_mult_parts (type, ar, ai, br, bi);
+}
+
+/* Perform some simplifications of complex division when one or more of
+   the components are constants or zeros.  Return non-null if successful.  */
+
+tree
+fold_complex_div_parts (tree type, tree ar, tree ai, tree br, tree bi,
+                       enum tree_code code)
+{
+  tree rr, ri, inner_type, zero;
+  bool ar0, ai0, br0, bi0, bi1;
+
+  inner_type = TREE_TYPE (type);
+  zero = NULL;
+
+  if (SCALAR_FLOAT_TYPE_P (inner_type))
     {
-      tem = fold (build2 (code == BIT_AND_EXPR ? TRUTH_AND_EXPR
-                         : code == BIT_IOR_EXPR ? TRUTH_OR_EXPR
-                         : TRUTH_XOR_EXPR,
-                         type, fold_convert (boolean_type_node, arg0),
-                         fold_convert (boolean_type_node, arg1)));
+      ar0 = ai0 = br0 = bi0 = bi1 = false;
 
-      if (code == EQ_EXPR)
-       tem = invert_truthvalue (tem);
+      /* We're only interested in +0.0 here, thus we don't use real_zerop.  */
 
-      return tem;
+      if (TREE_CODE (ar) == REAL_CST
+         && REAL_VALUES_IDENTICAL (TREE_REAL_CST (ar), dconst0))
+       ar0 = true, zero = ar;
+
+      if (TREE_CODE (ai) == REAL_CST
+         && REAL_VALUES_IDENTICAL (TREE_REAL_CST (ai), dconst0))
+       ai0 = true, zero = ai;
+
+      if (TREE_CODE (br) == REAL_CST
+         && REAL_VALUES_IDENTICAL (TREE_REAL_CST (br), dconst0))
+       br0 = true, zero = br;
+
+      if (TREE_CODE (bi) == REAL_CST)
+       {
+         if (REAL_VALUES_IDENTICAL (TREE_REAL_CST (bi), dconst0))
+           bi0 = true, zero = bi;
+         else if (REAL_VALUES_IDENTICAL (TREE_REAL_CST (bi), dconst1))
+           bi1 = true;
+       }
+    }
+  else
+    {
+      ar0 = integer_zerop (ar);
+      if (ar0)
+       zero = ar;
+      ai0 = integer_zerop (ai);
+      if (ai0)
+       zero = ai;
+      br0 = integer_zerop (br);
+      if (br0)
+       zero = br;
+      bi0 = integer_zerop (bi);
+      if (bi0)
+       {
+         zero = bi;
+         bi1 = false;
+       }
+      else
+       bi1 = integer_onep (bi);
+    }
+
+  /* We won't optimize anything below unless something is zero.  */
+  if (zero == NULL)
+    return NULL;
+
+  if (ai0 && bi0)
+    {
+      rr = fold (build2 (code, inner_type, ar, br));
+      ri = zero;
+    }
+  else if (ai0 && br0)
+    {
+      rr = zero;
+      ri = fold (build2 (code, inner_type, ar, bi));
+      ri = fold (build1 (NEGATE_EXPR, inner_type, ri));
+    }
+  else if (ar0 && bi0)
+    {
+      rr = zero;
+      ri = fold (build2 (code, inner_type, ai, br));
+    }
+  else if (ar0 && br0)
+    {
+      rr = fold (build2 (code, inner_type, ai, bi));
+      ri = zero;
+    }
+  else if (bi0)
+    {
+      rr = fold (build2 (code, inner_type, ar, br));
+      ri = fold (build2 (code, inner_type, ai, br));
+    }
+  else if (br0)
+    {
+      rr = fold (build2 (code, inner_type, ai, bi));
+      ri = fold (build2 (code, inner_type, ar, bi));
+      ri = fold (build1 (NEGATE_EXPR, inner_type, ri));
+    }
+  else
+    return NULL;
+
+  return fold (build2 (COMPLEX_EXPR, type, rr, ri));
+}
+
+static tree
+fold_complex_div (tree type, tree ac, tree bc, enum tree_code code)
+{
+  tree ar, ai, br, bi;
+
+  if (TREE_CODE (ac) == COMPLEX_EXPR)
+    ar = TREE_OPERAND (ac, 0), ai = TREE_OPERAND (ac, 1);
+  else if (TREE_CODE (ac) == COMPLEX_CST)
+    ar = TREE_REALPART (ac), ai = TREE_IMAGPART (ac);
+  else
+    return NULL;
+
+  if (TREE_CODE (bc) == COMPLEX_EXPR)
+    br = TREE_OPERAND (bc, 0), bi = TREE_OPERAND (bc, 1);
+  else if (TREE_CODE (bc) == COMPLEX_CST)
+    br = TREE_REALPART (bc), bi = TREE_IMAGPART (bc);
+  else
+    return NULL;
+
+  return fold_complex_div_parts (type, ar, ai, br, bi, code);
+}
+
+/* Fold a unary expression EXPR.  Return the folded expression if
+   folding is successful.  Otherwise, return the original
+   expression.  */
+
+static tree
+fold_unary (tree expr)
+{
+  const tree t = expr;
+  const tree type = TREE_TYPE (expr);
+  tree tem;
+  tree op0, arg0;
+  enum tree_code code = TREE_CODE (t);
+  enum tree_code_class kind = TREE_CODE_CLASS (code);
+
+  gcc_assert (IS_EXPR_CODE_CLASS (kind)
+             && TREE_CODE_LENGTH (code) == 1);
+
+
+  arg0 = op0 = TREE_OPERAND (t, 0);
+  if (arg0)
+    {
+      if (code == NOP_EXPR || code == FLOAT_EXPR || code == CONVERT_EXPR)
+       {
+         /* Don't use STRIP_NOPS, because signedness of argument type matters.  */
+         STRIP_SIGN_NOPS (arg0);
+       }
+      else
+       {
+         /* Strip any conversions that don't change the mode.  This
+            is safe for every expression, except for a comparison
+            expression because its signedness is derived from its
+            operands.
+
+            Note that this is done as an internal manipulation within
+            the constant folder, in order to find the simplest
+            representation of the arguments so that their form can be
+            studied.  In any cases, the appropriate type conversions
+            should be put back in the tree that will get out of the
+            constant folder.  */
+         STRIP_NOPS (arg0);
+       }
     }
 
   if (TREE_CODE_CLASS (code) == tcc_unary)
@@ -6403,10 +6673,11 @@ fold (tree expr)
              && ! VOID_TYPE_P (TREE_OPERAND (tem, 2))
              && (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 1), 0))
                  == TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 2), 0)))
-             && ! (INTEGRAL_TYPE_P (TREE_TYPE (tem))
-                   && (INTEGRAL_TYPE_P
-                       (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 1), 0))))
-                   && TYPE_PRECISION (TREE_TYPE (tem)) <= BITS_PER_WORD))
+             && (! (INTEGRAL_TYPE_P (TREE_TYPE (tem))
+                    && (INTEGRAL_TYPE_P
+                        (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 1), 0))))
+                    && TYPE_PRECISION (TREE_TYPE (tem)) <= BITS_PER_WORD)
+                 || flag_syntax_only))
            tem = build1 (code, type,
                          build3 (COND_EXPR,
                                  TREE_TYPE (TREE_OPERAND
@@ -6432,49 +6703,9 @@ fold (tree expr)
                                               integer_zero_node))));
        }
    }
-  else if (TREE_CODE_CLASS (code) == tcc_comparison
-          && TREE_CODE (arg0) == COMPOUND_EXPR)
-    return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
-                  fold (build2 (code, type, TREE_OPERAND (arg0, 1), arg1)));
-  else if (TREE_CODE_CLASS (code) == tcc_comparison
-          && TREE_CODE (arg1) == COMPOUND_EXPR)
-    return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
-                  fold (build2 (code, type, arg0, TREE_OPERAND (arg1, 1))));
-  else if (TREE_CODE_CLASS (code) == tcc_binary
-          || TREE_CODE_CLASS (code) == tcc_comparison)
-    {
-      if (TREE_CODE (arg0) == COMPOUND_EXPR)
-       return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
-                      fold (build2 (code, type, TREE_OPERAND (arg0, 1),
-                                    arg1)));
-      if (TREE_CODE (arg1) == COMPOUND_EXPR
-         && reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
-       return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
-                      fold (build2 (code, type,
-                                    arg0, TREE_OPERAND (arg1, 1))));
-
-      if (TREE_CODE (arg0) == COND_EXPR || COMPARISON_CLASS_P (arg0))
-       {
-         tem = fold_binary_op_with_conditional_arg (code, type, arg0, arg1,
-                                                    /*cond_first_p=*/1);
-         if (tem != NULL_TREE)
-           return tem;
-       }
-
-      if (TREE_CODE (arg1) == COND_EXPR || COMPARISON_CLASS_P (arg1))
-       {
-         tem = fold_binary_op_with_conditional_arg (code, type, arg1, arg0,
-                                                    /*cond_first_p=*/0);
-         if (tem != NULL_TREE)
-           return tem;
-       }
-    }
 
   switch (code)
     {
-    case CONST_DECL:
-      return fold (DECL_INITIAL (t));
-
     case NOP_EXPR:
     case FLOAT_EXPR:
     case CONVERT_EXPR:
@@ -6482,15 +6713,15 @@ fold (tree expr)
     case FIX_CEIL_EXPR:
     case FIX_FLOOR_EXPR:
     case FIX_ROUND_EXPR:
-      if (TREE_TYPE (TREE_OPERAND (t, 0)) == type)
-       return TREE_OPERAND (t, 0);
+      if (TREE_TYPE (op0) == type)
+       return op0;
 
       /* Handle cases of two conversions in a row.  */
-      if (TREE_CODE (TREE_OPERAND (t, 0)) == NOP_EXPR
-         || TREE_CODE (TREE_OPERAND (t, 0)) == CONVERT_EXPR)
+      if (TREE_CODE (op0) == NOP_EXPR
+         || TREE_CODE (op0) == CONVERT_EXPR)
        {
-         tree inside_type = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 0), 0));
-         tree inter_type = TREE_TYPE (TREE_OPERAND (t, 0));
+         tree inside_type = TREE_TYPE (TREE_OPERAND (op0, 0));
+         tree inter_type = TREE_TYPE (op0);
          int inside_int = INTEGRAL_TYPE_P (inside_type);
          int inside_ptr = POINTER_TYPE_P (inside_type);
          int inside_float = FLOAT_TYPE_P (inside_type);
@@ -6514,8 +6745,7 @@ fold (tree expr)
          if (TYPE_MAIN_VARIANT (inside_type) == TYPE_MAIN_VARIANT (type)
              && ((inter_int && final_int) || (inter_float && final_float))
              && inter_prec >= final_prec)
-           return fold (build1 (code, type,
-                                TREE_OPERAND (TREE_OPERAND (t, 0), 0)));
+           return fold (build1 (code, type, TREE_OPERAND (op0, 0)));
 
          /* Likewise, if the intermediate and final types are either both
             float or both integer, we don't need the middle conversion if
@@ -6530,16 +6760,14 @@ fold (tree expr)
              && ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (type))
                    && TYPE_MODE (type) == TYPE_MODE (inter_type))
              && ! final_ptr)
-           return fold (build1 (code, type,
-                                TREE_OPERAND (TREE_OPERAND (t, 0), 0)));
+           return fold (build1 (code, type, TREE_OPERAND (op0, 0)));
 
          /* If we have a sign-extension of a zero-extended value, we can
             replace that by a single zero-extension.  */
          if (inside_int && inter_int && final_int
              && inside_prec < inter_prec && inter_prec < final_prec
              && inside_unsignedp && !inter_unsignedp)
-           return fold (build1 (code, type,
-                                TREE_OPERAND (TREE_OPERAND (t, 0), 0)));
+           return fold (build1 (code, type, TREE_OPERAND (op0, 0)));
 
          /* Two conversions in a row are not needed unless:
             - some conversion is floating-point (overstrict for now), or
@@ -6563,23 +6791,21 @@ fold (tree expr)
              && ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (type))
                    && TYPE_MODE (type) == TYPE_MODE (inter_type))
              && ! final_ptr)
-           return fold (build1 (code, type,
-                                TREE_OPERAND (TREE_OPERAND (t, 0), 0)));
+           return fold (build1 (code, type, TREE_OPERAND (op0, 0)));
        }
 
-      if (TREE_CODE (TREE_OPERAND (t, 0)) == MODIFY_EXPR
-         && TREE_CONSTANT (TREE_OPERAND (TREE_OPERAND (t, 0), 1))
+      if (TREE_CODE (op0) == MODIFY_EXPR
+         && TREE_CONSTANT (TREE_OPERAND (op0, 1))
          /* Detect assigning a bitfield.  */
-         && !(TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 0)) == COMPONENT_REF
-              && DECL_BIT_FIELD (TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (t, 0), 0), 1))))
+         && !(TREE_CODE (TREE_OPERAND (op0, 0)) == COMPONENT_REF
+              && DECL_BIT_FIELD (TREE_OPERAND (TREE_OPERAND (op0, 0), 1))))
        {
          /* Don't leave an assignment inside a conversion
             unless assigning a bitfield.  */
-         tree prev = TREE_OPERAND (t, 0);
          tem = copy_node (t);
-         TREE_OPERAND (tem, 0) = TREE_OPERAND (prev, 1);
+         TREE_OPERAND (tem, 0) = TREE_OPERAND (op0, 1);
          /* First do the assignment, then return converted constant.  */
-         tem = build2 (COMPOUND_EXPR, TREE_TYPE (tem), prev, fold (tem));
+         tem = build2 (COMPOUND_EXPR, TREE_TYPE (tem), op0, fold (tem));
          TREE_NO_WARNING (tem) = 1;
          TREE_USED (tem) = 1;
          return tem;
@@ -6590,10 +6816,10 @@ fold (tree expr)
         in c).  This folds extension into the BIT_AND_EXPR.  */
       if (INTEGRAL_TYPE_P (type)
          && TREE_CODE (type) != BOOLEAN_TYPE
-         && TREE_CODE (TREE_OPERAND (t, 0)) == BIT_AND_EXPR
-         && TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 1)) == INTEGER_CST)
+         && TREE_CODE (op0) == BIT_AND_EXPR
+         && TREE_CODE (TREE_OPERAND (op0, 1)) == INTEGER_CST)
        {
-         tree and = TREE_OPERAND (t, 0);
+         tree and = op0;
          tree and0 = TREE_OPERAND (and, 0), and1 = TREE_OPERAND (and, 1);
          int change = 0;
 
@@ -6613,6 +6839,7 @@ fold (tree expr)
              change = (cst == 0);
 #ifdef LOAD_EXTEND_OP
              if (change
+                 && !flag_syntax_only
                  && (LOAD_EXTEND_OP (TYPE_MODE (TREE_TYPE (and0)))
                      == ZERO_EXTEND))
                {
@@ -6623,20 +6850,25 @@ fold (tree expr)
 #endif
            }
          if (change)
-           return fold (build2 (BIT_AND_EXPR, type,
-                                fold_convert (type, and0),
-                                fold_convert (type, and1)));
+           {
+             tem = build_int_cst_wide (type, TREE_INT_CST_LOW (and1),
+                                       TREE_INT_CST_HIGH (and1));
+             tem = force_fit_type (tem, 0, TREE_OVERFLOW (and1),
+                                   TREE_CONSTANT_OVERFLOW (and1));
+             return fold (build2 (BIT_AND_EXPR, type,
+                                  fold_convert (type, and0), tem));
+           }
        }
 
       /* Convert (T1)((T2)X op Y) into (T1)X op Y, for pointer types T1 and
         T2 being pointers to types of the same size.  */
-      if (POINTER_TYPE_P (TREE_TYPE (t))
+      if (POINTER_TYPE_P (type)
          && BINARY_CLASS_P (arg0)
          && TREE_CODE (TREE_OPERAND (arg0, 0)) == NOP_EXPR
          && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (arg0, 0))))
        {
          tree arg00 = TREE_OPERAND (arg0, 0);
-         tree t0 = TREE_TYPE (t);
+         tree t0 = type;
          tree t1 = TREE_TYPE (arg00);
          tree tt0 = TREE_TYPE (t0);
          tree tt1 = TREE_TYPE (t1);
@@ -6652,34 +6884,17 @@ fold (tree expr)
       return tem ? tem : t;
 
     case VIEW_CONVERT_EXPR:
-      if (TREE_CODE (TREE_OPERAND (t, 0)) == VIEW_CONVERT_EXPR)
-       return build1 (VIEW_CONVERT_EXPR, type,
-                      TREE_OPERAND (TREE_OPERAND (t, 0), 0));
-      return t;
-
-    case COMPONENT_REF:
-      if (TREE_CODE (arg0) == CONSTRUCTOR
-         && ! type_contains_placeholder_p (TREE_TYPE (arg0)))
-       {
-         tree m = purpose_member (arg1, CONSTRUCTOR_ELTS (arg0));
-         if (m)
-           return TREE_VALUE (m);
-       }
-      return t;
-
-    case RANGE_EXPR:
-      if (TREE_CONSTANT (t) != wins)
-       {
-         tem = copy_node (t);
-         TREE_CONSTANT (tem) = wins;
-         TREE_INVARIANT (tem) = wins;
-         return tem;
-       }
+      if (TREE_CODE (op0) == VIEW_CONVERT_EXPR)
+       return build1 (VIEW_CONVERT_EXPR, type, TREE_OPERAND (op0, 0));
       return t;
 
     case NEGATE_EXPR:
       if (negate_expr_p (arg0))
        return fold_convert (type, negate_expr (arg0));
+      /* Convert - (~A) to A + 1.  */
+      if (INTEGRAL_TYPE_P (type) && TREE_CODE (arg0) == BIT_NOT_EXPR)
+       return fold (build2 (PLUS_EXPR, type, TREE_OPERAND (arg0, 0),
+                            build_int_cst (type, 1)));
       return t;
 
     case ABS_EXPR:
@@ -6699,6 +6914,14 @@ fold (tree expr)
        }
       else if (tree_expr_nonnegative_p (arg0))
        return arg0;
+
+      /* Strip sign ops from argument.  */
+      if (TREE_CODE (type) == REAL_TYPE)
+       {
+         tem = fold_strip_sign_ops (arg0);
+         if (tem)
+           return fold (build1 (ABS_EXPR, type, fold_convert (type, tem)));
+       }
       return t;
 
     case CONJ_EXPR:
@@ -6721,11 +6944,506 @@ fold (tree expr)
        return TREE_OPERAND (arg0, 0);
       return t;
 
-    case BIT_NOT_EXPR:
-      if (TREE_CODE (arg0) == INTEGER_CST)
-        return fold_not_const (arg0, type);
-      else if (TREE_CODE (arg0) == BIT_NOT_EXPR)
-       return TREE_OPERAND (arg0, 0);
+    case BIT_NOT_EXPR:
+      if (TREE_CODE (arg0) == INTEGER_CST)
+        return fold_not_const (arg0, type);
+      else if (TREE_CODE (arg0) == BIT_NOT_EXPR)
+       return TREE_OPERAND (arg0, 0);
+      /* Convert ~ (-A) to A - 1.  */
+      else if (INTEGRAL_TYPE_P (type) && TREE_CODE (arg0) == NEGATE_EXPR)
+       return fold (build2 (MINUS_EXPR, type, TREE_OPERAND (arg0, 0),
+                            build_int_cst (type, 1)));
+      /* Convert ~ (A - 1) or ~ (A + -1) to -A.  */
+      else if (INTEGRAL_TYPE_P (type)
+              && ((TREE_CODE (arg0) == MINUS_EXPR
+                   && integer_onep (TREE_OPERAND (arg0, 1)))
+                  || (TREE_CODE (arg0) == PLUS_EXPR
+                      && integer_all_onesp (TREE_OPERAND (arg0, 1)))))
+       return fold (build1 (NEGATE_EXPR, type, TREE_OPERAND (arg0, 0)));
+      return t;
+
+    case TRUTH_NOT_EXPR:
+      /* The argument to invert_truthvalue must have Boolean type.  */
+      if (TREE_CODE (TREE_TYPE (arg0)) != BOOLEAN_TYPE)
+          arg0 = fold_convert (boolean_type_node, arg0);
+
+      /* Note that the operand of this must be an int
+        and its values must be 0 or 1.
+        ("true" is a fixed value perhaps depending on the language,
+        but we don't handle values other than 1 correctly yet.)  */
+      tem = invert_truthvalue (arg0);
+      /* Avoid infinite recursion.  */
+      if (TREE_CODE (tem) == TRUTH_NOT_EXPR)
+       return t;
+      return fold_convert (type, tem);
+
+    case REALPART_EXPR:
+      if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
+       return t;
+      else if (TREE_CODE (arg0) == COMPLEX_EXPR)
+       return omit_one_operand (type, TREE_OPERAND (arg0, 0),
+                                TREE_OPERAND (arg0, 1));
+      else if (TREE_CODE (arg0) == COMPLEX_CST)
+       return TREE_REALPART (arg0);
+      else if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
+       return fold (build2 (TREE_CODE (arg0), type,
+                            fold (build1 (REALPART_EXPR, type,
+                                          TREE_OPERAND (arg0, 0))),
+                            fold (build1 (REALPART_EXPR, type,
+                                          TREE_OPERAND (arg0, 1)))));
+      return t;
+
+    case IMAGPART_EXPR:
+      if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
+       return fold_convert (type, integer_zero_node);
+      else if (TREE_CODE (arg0) == COMPLEX_EXPR)
+       return omit_one_operand (type, TREE_OPERAND (arg0, 1),
+                                TREE_OPERAND (arg0, 0));
+      else if (TREE_CODE (arg0) == COMPLEX_CST)
+       return TREE_IMAGPART (arg0);
+      else if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
+       return fold (build2 (TREE_CODE (arg0), type,
+                            fold (build1 (IMAGPART_EXPR, type,
+                                          TREE_OPERAND (arg0, 0))),
+                            fold (build1 (IMAGPART_EXPR, type,
+                                          TREE_OPERAND (arg0, 1)))));
+      return t;
+
+    default:
+      return t;
+    } /* switch (code) */
+}
+
+/* Fold a ternary expression EXPR.  Return the folded expression if
+   folding is successful.  Otherwise, return the original
+   expression.  */
+
+static tree
+fold_ternary (tree expr)
+{
+  const tree t = expr;
+  const tree type = TREE_TYPE (expr);
+  tree tem;
+  tree arg0 = NULL_TREE, arg1 = NULL_TREE;
+  enum tree_code code = TREE_CODE (t);
+  enum tree_code_class kind = TREE_CODE_CLASS (code);
+  int i;
+
+  gcc_assert (IS_EXPR_CODE_CLASS (kind)
+             && TREE_CODE_LENGTH (code) == 3);
+
+  /* For now, we iterate only twice even though we are handling
+     ternary expressions.  This is because we haven't defined arg2
+     yet.  */
+  for (i = 0; i < 2; i++)
+    {
+      tree op = TREE_OPERAND (t, i);
+
+      if (op == 0)
+       continue;               /* Valid for CALL_EXPR, at least.  */
+
+      /* Strip any conversions that don't change the mode.  This is
+        safe for every expression, except for a comparison expression
+        because its signedness is derived from its operands.  So, in
+        the latter case, only strip conversions that don't change the
+        signedness.
+
+        Note that this is done as an internal manipulation within the
+        constant folder, in order to find the simplest representation
+        of the arguments so that their form can be studied.  In any
+        cases, the appropriate type conversions should be put back in
+        the tree that will get out of the constant folder.  */
+      STRIP_NOPS (op);
+
+      if (i == 0)
+       arg0 = op;
+      else if (i == 1)
+       arg1 = op;
+    }
+
+  switch (code)
+    {
+    case COMPONENT_REF:
+      if (TREE_CODE (arg0) == CONSTRUCTOR
+         && ! type_contains_placeholder_p (TREE_TYPE (arg0)))
+       {
+         tree m = purpose_member (arg1, CONSTRUCTOR_ELTS (arg0));
+         if (m)
+           return TREE_VALUE (m);
+       }
+      return t;
+
+    case COND_EXPR:
+      /* Pedantic ANSI C says that a conditional expression is never an lvalue,
+        so all simple results must be passed through pedantic_non_lvalue.  */
+      if (TREE_CODE (arg0) == INTEGER_CST)
+       {
+         tem = TREE_OPERAND (t, (integer_zerop (arg0) ? 2 : 1));
+         /* Only optimize constant conditions when the selected branch
+            has the same type as the COND_EXPR.  This avoids optimizing
+            away "c ? x : throw", where the throw has a void type.  */
+         if (! VOID_TYPE_P (TREE_TYPE (tem))
+             || VOID_TYPE_P (type))
+           return pedantic_non_lvalue (tem);
+         return t;
+       }
+      if (operand_equal_p (arg1, TREE_OPERAND (t, 2), 0))
+       return pedantic_omit_one_operand (type, arg1, arg0);
+
+      /* If we have A op B ? A : C, we may be able to convert this to a
+        simpler expression, depending on the operation and the values
+        of B and C.  Signed zeros prevent all of these transformations,
+        for reasons given above each one.
+
+         Also try swapping the arguments and inverting the conditional.  */
+      if (COMPARISON_CLASS_P (arg0)
+         && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
+                                            arg1, TREE_OPERAND (arg0, 1))
+         && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
+       {
+         tem = fold_cond_expr_with_comparison (type, arg0,
+                                               TREE_OPERAND (t, 1),
+                                               TREE_OPERAND (t, 2));
+         if (tem)
+           return tem;
+       }
+
+      if (COMPARISON_CLASS_P (arg0)
+         && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
+                                            TREE_OPERAND (t, 2),
+                                            TREE_OPERAND (arg0, 1))
+         && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 2)))))
+       {
+         tem = invert_truthvalue (arg0);
+         if (COMPARISON_CLASS_P (tem))
+           {
+             tem = fold_cond_expr_with_comparison (type, tem,
+                                                   TREE_OPERAND (t, 2),
+                                                   TREE_OPERAND (t, 1));
+             if (tem)
+               return tem;
+           }
+       }
+
+      /* If the second operand is simpler than the third, swap them
+        since that produces better jump optimization results.  */
+      if (tree_swap_operands_p (TREE_OPERAND (t, 1),
+                               TREE_OPERAND (t, 2), false))
+       {
+         /* See if this can be inverted.  If it can't, possibly because
+            it was a floating-point inequality comparison, don't do
+            anything.  */
+         tem = invert_truthvalue (arg0);
+
+         if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
+           return fold (build3 (code, type, tem,
+                                TREE_OPERAND (t, 2), TREE_OPERAND (t, 1)));
+       }
+
+      /* Convert A ? 1 : 0 to simply A.  */
+      if (integer_onep (TREE_OPERAND (t, 1))
+         && integer_zerop (TREE_OPERAND (t, 2))
+         /* If we try to convert TREE_OPERAND (t, 0) to our type, the
+            call to fold will try to move the conversion inside
+            a COND, which will recurse.  In that case, the COND_EXPR
+            is probably the best choice, so leave it alone.  */
+         && type == TREE_TYPE (arg0))
+       return pedantic_non_lvalue (arg0);
+
+      /* Convert A ? 0 : 1 to !A.  This prefers the use of NOT_EXPR
+        over COND_EXPR in cases such as floating point comparisons.  */
+      if (integer_zerop (TREE_OPERAND (t, 1))
+         && integer_onep (TREE_OPERAND (t, 2))
+         && truth_value_p (TREE_CODE (arg0)))
+       return pedantic_non_lvalue (fold_convert (type,
+                                                 invert_truthvalue (arg0)));
+
+      /* A < 0 ? <sign bit of A> : 0 is simply (A & <sign bit of A>).  */
+      if (TREE_CODE (arg0) == LT_EXPR
+          && integer_zerop (TREE_OPERAND (arg0, 1))
+          && integer_zerop (TREE_OPERAND (t, 2))
+          && (tem = sign_bit_p (TREE_OPERAND (arg0, 0), arg1)))
+        return fold_convert (type, fold (build2 (BIT_AND_EXPR,
+                                                TREE_TYPE (tem), tem, arg1)));
+
+      /* (A >> N) & 1 ? (1 << N) : 0 is simply A & (1 << N).  A & 1 was
+        already handled above.  */
+      if (TREE_CODE (arg0) == BIT_AND_EXPR
+         && integer_onep (TREE_OPERAND (arg0, 1))
+         && integer_zerop (TREE_OPERAND (t, 2))
+         && integer_pow2p (arg1))
+       {
+         tree tem = TREE_OPERAND (arg0, 0);
+         STRIP_NOPS (tem);
+         if (TREE_CODE (tem) == RSHIFT_EXPR
+              && TREE_CODE (TREE_OPERAND (tem, 1)) == INTEGER_CST
+              && (unsigned HOST_WIDE_INT) tree_log2 (arg1) ==
+                TREE_INT_CST_LOW (TREE_OPERAND (tem, 1)))
+           return fold (build2 (BIT_AND_EXPR, type,
+                                TREE_OPERAND (tem, 0), arg1));
+       }
+
+      /* A & N ? N : 0 is simply A & N if N is a power of two.  This
+        is probably obsolete because the first operand should be a
+        truth value (that's why we have the two cases above), but let's
+        leave it in until we can confirm this for all front-ends.  */
+      if (integer_zerop (TREE_OPERAND (t, 2))
+         && TREE_CODE (arg0) == NE_EXPR
+         && integer_zerop (TREE_OPERAND (arg0, 1))
+         && integer_pow2p (arg1)
+         && TREE_CODE (TREE_OPERAND (arg0, 0)) == BIT_AND_EXPR
+         && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1),
+                             arg1, OEP_ONLY_CONST))
+       return pedantic_non_lvalue (fold_convert (type,
+                                                 TREE_OPERAND (arg0, 0)));
+
+      /* Convert A ? B : 0 into A && B if A and B are truth values.  */
+      if (integer_zerop (TREE_OPERAND (t, 2))
+         && truth_value_p (TREE_CODE (arg0))
+         && truth_value_p (TREE_CODE (arg1)))
+       return fold (build2 (TRUTH_ANDIF_EXPR, type, arg0, arg1));
+
+      /* Convert A ? B : 1 into !A || B if A and B are truth values.  */
+      if (integer_onep (TREE_OPERAND (t, 2))
+         && truth_value_p (TREE_CODE (arg0))
+         && truth_value_p (TREE_CODE (arg1)))
+       {
+         /* Only perform transformation if ARG0 is easily inverted.  */
+         tem = invert_truthvalue (arg0);
+         if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
+           return fold (build2 (TRUTH_ORIF_EXPR, type, tem, arg1));
+       }
+
+      /* Convert A ? 0 : B into !A && B if A and B are truth values.  */
+      if (integer_zerop (arg1)
+         && truth_value_p (TREE_CODE (arg0))
+         && truth_value_p (TREE_CODE (TREE_OPERAND (t, 2))))
+       {
+         /* Only perform transformation if ARG0 is easily inverted.  */
+         tem = invert_truthvalue (arg0);
+         if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
+           return fold (build2 (TRUTH_ANDIF_EXPR, type, tem,
+                                TREE_OPERAND (t, 2)));
+       }
+
+      /* Convert A ? 1 : B into A || B if A and B are truth values.  */
+      if (integer_onep (arg1)
+         && truth_value_p (TREE_CODE (arg0))
+         && truth_value_p (TREE_CODE (TREE_OPERAND (t, 2))))
+       return fold (build2 (TRUTH_ORIF_EXPR, type, arg0,
+                            TREE_OPERAND (t, 2)));
+
+      return t;
+
+    case CALL_EXPR:
+      /* Check for a built-in function.  */
+      if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
+         && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 0))
+             == FUNCTION_DECL)
+         && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (t, 0), 0)))
+       {
+         tree tmp = fold_builtin (t, false);
+         if (tmp)
+           return tmp;
+       }
+      return t;
+
+    default:
+      return t;
+    } /* switch (code) */
+}
+
+/* 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.
+   NOP_EXPR conversions may be removed freely (as long as we
+   are careful not to change the type of the overall expression).
+   We cannot simplify through a CONVERT_EXPR, FIX_EXPR or FLOAT_EXPR,
+   but we can constant-fold them if they have constant operands.  */
+
+#ifdef ENABLE_FOLD_CHECKING
+# define fold(x) fold_1 (x)
+static tree fold_1 (tree);
+static
+#endif
+tree
+fold (tree expr)
+{
+  const tree t = expr;
+  const tree type = TREE_TYPE (expr);
+  tree t1 = NULL_TREE;
+  tree tem;
+  tree arg0 = NULL_TREE, arg1 = NULL_TREE;
+  enum tree_code code = TREE_CODE (t);
+  enum tree_code_class kind = TREE_CODE_CLASS (code);
+
+  /* WINS will be nonzero when the switch is done
+     if all operands are constant.  */
+  int wins = 1;
+
+  /* Return right away if a constant.  */
+  if (kind == tcc_constant)
+    return t;
+
+  if (IS_EXPR_CODE_CLASS (kind))
+    {
+      switch (TREE_CODE_LENGTH (code))
+       {
+       case 1:
+         return fold_unary (expr);
+       case 3:
+         return fold_ternary (expr);
+       default:
+         break;
+       }
+    }
+
+  if (IS_EXPR_CODE_CLASS (kind))
+    {
+      int len = TREE_CODE_LENGTH (code);
+      int i;
+      for (i = 0; i < len; i++)
+       {
+         tree op = TREE_OPERAND (t, i);
+         tree subop;
+
+         if (op == 0)
+           continue;           /* Valid for CALL_EXPR, at least.  */
+
+         /* Strip any conversions that don't change the mode.  This is
+            safe for every expression, except for a comparison expression
+            because its signedness is derived from its operands.  So, in
+            the latter case, only strip conversions that don't change the
+            signedness.
+
+            Note that this is done as an internal manipulation within the
+            constant folder, in order to find the simplest representation
+            of the arguments so that their form can be studied.  In any
+            cases, the appropriate type conversions should be put back in
+            the tree that will get out of the constant folder.  */
+         if (kind == tcc_comparison)
+           STRIP_SIGN_NOPS (op);
+         else
+           STRIP_NOPS (op);
+
+         if (TREE_CODE (op) == COMPLEX_CST)
+           subop = TREE_REALPART (op);
+         else
+           subop = op;
+
+         if (TREE_CODE (subop) != INTEGER_CST
+             && TREE_CODE (subop) != REAL_CST)
+           /* Note that TREE_CONSTANT isn't enough:
+              static var addresses are constant but we can't
+              do arithmetic on them.  */
+           wins = 0;
+
+         if (i == 0)
+           arg0 = op;
+         else if (i == 1)
+           arg1 = op;
+       }
+    }
+
+  /* If this is a commutative operation, and ARG0 is a constant, move it
+     to ARG1 to reduce the number of tests below.  */
+  if (commutative_tree_code (code)
+      && tree_swap_operands_p (arg0, arg1, true))
+    return fold (build2 (code, type, TREE_OPERAND (t, 1),
+                        TREE_OPERAND (t, 0)));
+
+  /* Now WINS is set as described above,
+     ARG0 is the first operand of EXPR,
+     and ARG1 is the second operand (if it has more than one operand).
+
+     First check for cases where an arithmetic operation is applied to a
+     compound, conditional, or comparison operation.  Push the arithmetic
+     operation inside the compound or conditional to see if any folding
+     can then be done.  Convert comparison to conditional for this purpose.
+     The also optimizes non-constant cases that used to be done in
+     expand_expr.
+
+     Before we do that, see if this is a BIT_AND_EXPR or a BIT_IOR_EXPR,
+     one of the operands is a comparison and the other is a comparison, a
+     BIT_AND_EXPR with the constant 1, or a truth value.  In that case, the
+     code below would make the expression more complex.  Change it to a
+     TRUTH_{AND,OR}_EXPR.  Likewise, convert a similar NE_EXPR to
+     TRUTH_XOR_EXPR and an EQ_EXPR to the inversion of a TRUTH_XOR_EXPR.  */
+
+  if ((code == BIT_AND_EXPR || code == BIT_IOR_EXPR
+       || code == EQ_EXPR || code == NE_EXPR)
+      && ((truth_value_p (TREE_CODE (arg0))
+          && (truth_value_p (TREE_CODE (arg1))
+              || (TREE_CODE (arg1) == BIT_AND_EXPR
+                  && integer_onep (TREE_OPERAND (arg1, 1)))))
+         || (truth_value_p (TREE_CODE (arg1))
+             && (truth_value_p (TREE_CODE (arg0))
+                 || (TREE_CODE (arg0) == BIT_AND_EXPR
+                     && integer_onep (TREE_OPERAND (arg0, 1)))))))
+    {
+      tem = fold (build2 (code == BIT_AND_EXPR ? TRUTH_AND_EXPR
+                         : code == BIT_IOR_EXPR ? TRUTH_OR_EXPR
+                         : TRUTH_XOR_EXPR,
+                         type, fold_convert (boolean_type_node, arg0),
+                         fold_convert (boolean_type_node, arg1)));
+
+      if (code == EQ_EXPR)
+       tem = invert_truthvalue (tem);
+
+      return tem;
+    }
+
+  if (TREE_CODE_CLASS (code) == tcc_comparison
+          && TREE_CODE (arg0) == COMPOUND_EXPR)
+    return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
+                  fold (build2 (code, type, TREE_OPERAND (arg0, 1), arg1)));
+  else if (TREE_CODE_CLASS (code) == tcc_comparison
+          && TREE_CODE (arg1) == COMPOUND_EXPR)
+    return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
+                  fold (build2 (code, type, arg0, TREE_OPERAND (arg1, 1))));
+  else if (TREE_CODE_CLASS (code) == tcc_binary
+          || TREE_CODE_CLASS (code) == tcc_comparison)
+    {
+      if (TREE_CODE (arg0) == COMPOUND_EXPR)
+       return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
+                      fold (build2 (code, type, TREE_OPERAND (arg0, 1),
+                                    arg1)));
+      if (TREE_CODE (arg1) == COMPOUND_EXPR
+         && reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
+       return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
+                      fold (build2 (code, type,
+                                    arg0, TREE_OPERAND (arg1, 1))));
+
+      if (TREE_CODE (arg0) == COND_EXPR || COMPARISON_CLASS_P (arg0))
+       {
+         tem = fold_binary_op_with_conditional_arg (t, code, arg0, arg1, 
+                                                    /*cond_first_p=*/1);
+         if (tem != NULL_TREE)
+           return tem;
+       }
+
+      if (TREE_CODE (arg1) == COND_EXPR || COMPARISON_CLASS_P (arg1))
+       {
+         tem = fold_binary_op_with_conditional_arg (t, code, arg1, arg0, 
+                                                    /*cond_first_p=*/0);
+         if (tem != NULL_TREE)
+           return tem;
+       }
+    }
+
+  switch (code)
+    {
+    case CONST_DECL:
+      return fold (DECL_INITIAL (t));
+
+    case RANGE_EXPR:
+      if (TREE_CONSTANT (t) != wins)
+       {
+         tem = copy_node (t);
+         TREE_CONSTANT (tem) = wins;
+         TREE_INVARIANT (tem) = wins;
+         return tem;
+       }
       return t;
 
     case PLUS_EXPR:
@@ -6736,6 +7454,14 @@ fold (tree expr)
       if (TREE_CODE (arg0) == NEGATE_EXPR
          && reorder_operands_p (TREE_OPERAND (arg0, 0), arg1))
        return fold (build2 (MINUS_EXPR, type, arg1, TREE_OPERAND (arg0, 0)));
+
+      if (TREE_CODE (type) == COMPLEX_TYPE)
+       {
+         tem = fold_complex_add (type, arg0, arg1, PLUS_EXPR);
+         if (tem)
+           return tem;
+       }
+
       if (! FLOAT_TYPE_P (type))
        {
          if (integer_zerop (arg1))
@@ -6867,16 +7593,16 @@ fold (tree expr)
          if (TREE_CODE (arg0) == ADDR_EXPR
              && TREE_CODE (arg1) == MULT_EXPR)
            {
-             tem = try_move_mult_to_index (type, PLUS_EXPR, arg0, arg1);
+             tem = try_move_mult_to_index (PLUS_EXPR, arg0, arg1);
              if (tem)
-               return fold (tem);
+               return fold_convert (type, fold (tem));
            }
          else if (TREE_CODE (arg1) == ADDR_EXPR
                   && TREE_CODE (arg0) == MULT_EXPR)
            {
-             tem = try_move_mult_to_index (type, PLUS_EXPR, arg1, arg0);
+             tem = try_move_mult_to_index (PLUS_EXPR, arg1, arg0);
              if (tem)
-               return fold (tem);
+               return fold_convert (type, fold (tem));
            }
        }
       else
@@ -7167,6 +7893,13 @@ fold (tree expr)
        return fold (build2 (MINUS_EXPR, type, negate_expr (arg1),
                             TREE_OPERAND (arg0, 0)));
 
+      if (TREE_CODE (type) == COMPLEX_TYPE)
+       {
+         tem = fold_complex_add (type, arg0, arg1, MINUS_EXPR);
+         if (tem)
+           return tem;
+       }
+
       if (! FLOAT_TYPE_P (type))
        {
          if (! wins && integer_zerop (arg0))
@@ -7255,9 +7988,9 @@ fold (tree expr)
       if (TREE_CODE (arg0) == ADDR_EXPR
          && TREE_CODE (arg1) == MULT_EXPR)
        {
-         tem = try_move_mult_to_index (type, MINUS_EXPR, arg0, arg1);
+         tem = try_move_mult_to_index (MINUS_EXPR, arg0, arg1);
          if (tem)
-           return fold (tem);
+           return fold_convert (type, fold (tem));
        }
 
       if (TREE_CODE (arg0) == MULT_EXPR
@@ -7295,6 +8028,13 @@ fold (tree expr)
                             negate_expr (arg0),
                             TREE_OPERAND (arg1, 0)));
 
+      if (TREE_CODE (type) == COMPLEX_TYPE)
+       {
+         tem = fold_complex_mult (type, arg0, arg1);
+         if (tem)
+           return tem;
+       }
+
       if (! FLOAT_TYPE_P (type))
        {
          if (integer_zerop (arg1))
@@ -7352,6 +8092,17 @@ fold (tree expr)
                                     TREE_OPERAND (arg0, 1)));
            }
 
+          /* Strip sign operations from X in X*X, i.e. -Y*-Y -> Y*Y.  */
+         if (operand_equal_p (arg0, arg1, 0))
+           {
+             tree tem = fold_strip_sign_ops (arg0);
+             if (tem != NULL_TREE)
+               {
+                 tem = fold_convert (type, tem);
+                 return fold (build2 (MULT_EXPR, type, tem, tem));
+               }
+           }
+
          if (flag_unsafe_math_optimizations)
            {
              enum built_in_function fcode0 = builtin_mathfn_code (arg0);
@@ -7734,6 +8485,13 @@ fold (tree expr)
                                 TREE_OPERAND (arg1, 0)));
        }
 
+      if (TREE_CODE (type) == COMPLEX_TYPE)
+       {
+         tem = fold_complex_div (type, arg0, arg1, code);
+         if (tem)
+           return tem;
+       }
+
       if (flag_unsafe_math_optimizations)
        {
          enum built_in_function fcode = builtin_mathfn_code (arg1);
@@ -7858,17 +8616,33 @@ fold (tree expr)
                                         code, NULL_TREE)))
        return fold_convert (type, tem);
 
+      if (TREE_CODE (type) == COMPLEX_TYPE)
+       {
+         tem = fold_complex_div (type, arg0, arg1, code);
+         if (tem)
+           return tem;
+       }
       goto binary;
 
     case CEIL_MOD_EXPR:
     case FLOOR_MOD_EXPR:
     case ROUND_MOD_EXPR:
     case TRUNC_MOD_EXPR:
+      /* X % 1 is always zero, but be sure to preserve any side
+        effects in X.  */
       if (integer_onep (arg1))
        return omit_one_operand (type, integer_zero_node, arg0);
+
+      /* X % 0, return X % 0 unchanged so that we can get the
+        proper warnings and errors.  */
       if (integer_zerop (arg1))
        return t;
 
+      /* 0 % X is always zero, but be sure to preserve any side
+        effects in X.  Place this after checking for X == 0.  */
+      if (integer_zerop (arg0))
+       return omit_one_operand (type, integer_zero_node, arg1);
+
       /* X % -1 is zero.  */
       if (!TYPE_UNSIGNED (type)
          && TREE_CODE (arg1) == INTEGER_CST
@@ -8009,26 +8783,6 @@ fold (tree expr)
        return omit_one_operand (type, arg1, arg0);
       goto associate;
 
-    case TRUTH_NOT_EXPR:
-      /* The argument to invert_truthvalue must have Boolean type.  */
-      if (TREE_CODE (TREE_TYPE (arg0)) != BOOLEAN_TYPE)
-          arg0 = fold_convert (boolean_type_node, arg0);
-
-      /* Note that the operand of this must be an int
-        and its values must be 0 or 1.
-        ("true" is a fixed value perhaps depending on the language,
-        but we don't handle values other than 1 correctly yet.)  */
-      tem = invert_truthvalue (arg0);
-      /* Avoid infinite recursion.  */
-      if (TREE_CODE (tem) == TRUTH_NOT_EXPR)
-       {
-         tem = fold_single_bit_test (code, arg0, arg1, type);
-         if (tem)
-           return tem;
-         return t;
-       }
-      return fold_convert (type, tem);
-
     case TRUTH_ANDIF_EXPR:
       /* Note that the operands of this must be ints
         and their values must be 0 or 1.
@@ -8239,6 +8993,33 @@ fold (tree expr)
                                      ? code == EQ_EXPR : code != EQ_EXPR,
                                      type);
 
+      /* If this is a comparison of two exprs that look like an
+        ARRAY_REF of the same object, then we can fold this to a
+        comparison of the two offsets.  */
+      if (COMPARISON_CLASS_P (t))
+       {
+         tree base0, offset0, base1, offset1;
+
+         if (extract_array_ref (arg0, &base0, &offset0)
+             && extract_array_ref (arg1, &base1, &offset1)
+             && operand_equal_p (base0, base1, 0))
+           {
+             if (offset0 == NULL_TREE
+                 && offset1 == NULL_TREE)
+               {
+                 offset0 = integer_zero_node;
+                 offset1 = integer_zero_node;
+               }
+             else if (offset0 == NULL_TREE)
+               offset0 = build_int_cst (TREE_TYPE (offset1), 0);
+             else if (offset1 == NULL_TREE)
+               offset1 = build_int_cst (TREE_TYPE (offset0), 0);
+
+             if (TREE_TYPE (offset0) == TREE_TYPE (offset1))
+               return fold (build2 (code, type, offset0, offset1));
+           }
+       }
+
       if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
        {
          tree targ0 = strip_float_extensions (arg0);
@@ -8428,36 +9209,64 @@ fold (tree expr)
       /* Comparisons with the highest or lowest possible integer of
         the specified size will have known values.
 
-        This is quite similar to fold_relational_hi_lo; however, my
-        attempts to share the code have been nothing but trouble.
-        I give up for now.  */
+        This is quite similar to fold_relational_hi_lo, however,
+        attempts to share the code have been nothing but trouble.  */
       {
        int width = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (arg1)));
 
        if (TREE_CODE (arg1) == INTEGER_CST
            && ! TREE_CONSTANT_OVERFLOW (arg1)
-           && width <= HOST_BITS_PER_WIDE_INT
+           && width <= 2 * HOST_BITS_PER_WIDE_INT
            && (INTEGRAL_TYPE_P (TREE_TYPE (arg1))
                || POINTER_TYPE_P (TREE_TYPE (arg1))))
          {
-           unsigned HOST_WIDE_INT signed_max;
-           unsigned HOST_WIDE_INT max, min;
+           HOST_WIDE_INT signed_max_hi;
+           unsigned HOST_WIDE_INT signed_max_lo;
+           unsigned HOST_WIDE_INT max_hi, max_lo, min_hi, min_lo;
 
-           signed_max = ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1;
-
-           if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
+           if (width <= HOST_BITS_PER_WIDE_INT)
              {
-               max = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1;
-               min = 0;
+               signed_max_lo = ((unsigned HOST_WIDE_INT) 1 << (width - 1))
+                               - 1;
+               signed_max_hi = 0;
+               max_hi = 0;
+
+               if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
+                 {
+                   max_lo = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1;
+                   min_lo = 0;
+                   min_hi = 0;
+                 }
+               else
+                 {
+                   max_lo = signed_max_lo;
+                   min_lo = ((unsigned HOST_WIDE_INT) -1 << (width - 1));
+                   min_hi = -1;
+                 }
              }
            else
              {
-               max = signed_max;
-               min = ((unsigned HOST_WIDE_INT) -1 << (width - 1));
+               width -= HOST_BITS_PER_WIDE_INT;
+               signed_max_lo = -1;
+               signed_max_hi = ((unsigned HOST_WIDE_INT) 1 << (width - 1))
+                               - 1;
+               max_lo = -1;
+               min_lo = 0;
+
+               if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
+                 {
+                   max_hi = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1;
+                   min_hi = 0;
+                 }
+               else
+                 {
+                   max_hi = signed_max_hi;
+                   min_hi = ((unsigned HOST_WIDE_INT) -1 << (width - 1));
+                 }
              }
 
-           if (TREE_INT_CST_HIGH (arg1) == 0
-               && TREE_INT_CST_LOW (arg1) == max)
+           if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1) == max_hi
+               && TREE_INT_CST_LOW (arg1) == max_lo)
              switch (code)
                {
                case GT_EXPR:
@@ -8478,8 +9287,9 @@ fold (tree expr)
                default:
                  break;
                }
-           else if (TREE_INT_CST_HIGH (arg1) == 0
-                    && TREE_INT_CST_LOW (arg1) == max - 1)
+           else if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1)
+                    == max_hi
+                    && TREE_INT_CST_LOW (arg1) == max_lo - 1)
              switch (code)
                {
                case GT_EXPR:
@@ -8491,8 +9301,9 @@ fold (tree expr)
                default:
                  break;
                }
-           else if (TREE_INT_CST_HIGH (arg1) == (min ? -1 : 0)
-                    && TREE_INT_CST_LOW (arg1) == min)
+           else if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1)
+                    == min_hi
+                    && TREE_INT_CST_LOW (arg1) == min_lo)
              switch (code)
                {
                case LT_EXPR:
@@ -8510,8 +9321,9 @@ fold (tree expr)
                default:
                  break;
                }
-           else if (TREE_INT_CST_HIGH (arg1) == (min ? -1 : 0)
-                    && TREE_INT_CST_LOW (arg1) == min + 1)
+           else if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1)
+                    == min_hi
+                    && TREE_INT_CST_LOW (arg1) == min_lo + 1)
              switch (code)
                {
                case GE_EXPR:
@@ -8525,8 +9337,8 @@ fold (tree expr)
                }
 
            else if (!in_gimple_form
-                    && TREE_INT_CST_HIGH (arg1) == 0
-                    && TREE_INT_CST_LOW (arg1) == signed_max
+                    && TREE_INT_CST_HIGH (arg1) == signed_max_hi
+                    && TREE_INT_CST_LOW (arg1) == signed_max_lo
                     && TYPE_UNSIGNED (TREE_TYPE (arg1))
                     /* signed_type does not work on pointer types.  */
                     && INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
@@ -8618,6 +9430,26 @@ fold (tree expr)
                             build2 (LE_EXPR, type,
                                     TREE_OPERAND (arg0, 0), arg1)));
 
+      /* Convert ABS_EXPR<x> >= 0 to true.  */
+      else if (code == GE_EXPR
+              && tree_expr_nonnegative_p (arg0)
+              && (integer_zerop (arg1)
+                  || (! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0)))
+                       && real_zerop (arg1))))
+       return omit_one_operand (type, integer_one_node, arg0);
+
+      /* Convert ABS_EXPR<x> < 0 to false.  */
+      else if (code == LT_EXPR
+              && tree_expr_nonnegative_p (arg0)
+              && (integer_zerop (arg1) || real_zerop (arg1)))
+       return omit_one_operand (type, integer_zero_node, arg0);
+
+      /* Convert ABS_EXPR<x> == 0 or ABS_EXPR<x> != 0 to x == 0 or x != 0.  */
+      else if ((code == EQ_EXPR || code == NE_EXPR)
+              && TREE_CODE (arg0) == ABS_EXPR
+              && (integer_zerop (arg1) || real_zerop (arg1)))
+       return fold (build2 (code, type, TREE_OPERAND (arg0, 0), arg1));
+
       /* If this is an EQ or NE comparison with zero and ARG0 is
         (1 << foo) & bar, convert it to (bar >> foo) & 1.  Both require
         two operations, but the latter can be done in one less insn
@@ -8947,264 +9779,102 @@ fold (tree expr)
          tree arglist;
 
          if (fndecl
-             && DECL_BUILT_IN (fndecl)
-             && DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_MD
+             && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
              && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STRLEN
              && (arglist = TREE_OPERAND (arg0, 1))
              && TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) == POINTER_TYPE
              && ! TREE_CHAIN (arglist))
-           return fold (build2 (code, type,
-                                build1 (INDIRECT_REF, char_type_node,
-                                        TREE_VALUE (arglist)),
-                                fold_convert (char_type_node,
-                                              integer_zero_node)));
-       }
-
-      /* We can fold X/C1 op C2 where C1 and C2 are integer constants
-        into a single range test.  */
-      if (TREE_CODE (arg0) == TRUNC_DIV_EXPR
-         && TREE_CODE (arg1) == INTEGER_CST
-         && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
-         && !integer_zerop (TREE_OPERAND (arg0, 1))
-         && !TREE_OVERFLOW (TREE_OPERAND (arg0, 1))
-         && !TREE_OVERFLOW (arg1))
-       {
-         t1 = fold_div_compare (code, type, arg0, arg1);
-         if (t1 != NULL_TREE)
-           return t1;
-       }
-
-      if ((code == EQ_EXPR || code == NE_EXPR)
-         && !TREE_SIDE_EFFECTS (arg0)
-         && integer_zerop (arg1)
-         && tree_expr_nonzero_p (arg0))
-       return constant_boolean_node (code==NE_EXPR, type);
-
-      t1 = fold_relational_const (code, type, arg0, arg1);
-      return t1 == NULL_TREE ? t : t1;
-
-    case UNORDERED_EXPR:
-    case ORDERED_EXPR:
-    case UNLT_EXPR:
-    case UNLE_EXPR:
-    case UNGT_EXPR:
-    case UNGE_EXPR:
-    case UNEQ_EXPR:
-    case LTGT_EXPR:
-      if (TREE_CODE (arg0) == REAL_CST && TREE_CODE (arg1) == REAL_CST)
-       {
-         t1 = fold_relational_const (code, type, arg0, arg1);
-         if (t1 != NULL_TREE)
-           return t1;
-       }
-
-      /* If the first operand is NaN, the result is constant.  */
-      if (TREE_CODE (arg0) == REAL_CST
-         && REAL_VALUE_ISNAN (TREE_REAL_CST (arg0))
-         && (code != LTGT_EXPR || ! flag_trapping_math))
-       {
-         t1 = (code == ORDERED_EXPR || code == LTGT_EXPR)
-              ? integer_zero_node
-              : integer_one_node;
-         return omit_one_operand (type, t1, arg1);
-       }
-
-      /* If the second operand is NaN, the result is constant.  */
-      if (TREE_CODE (arg1) == REAL_CST
-         && REAL_VALUE_ISNAN (TREE_REAL_CST (arg1))
-         && (code != LTGT_EXPR || ! flag_trapping_math))
-       {
-         t1 = (code == ORDERED_EXPR || code == LTGT_EXPR)
-              ? integer_zero_node
-              : integer_one_node;
-         return omit_one_operand (type, t1, arg0);
-       }
-
-      /* Simplify unordered comparison of something with itself.  */
-      if ((code == UNLE_EXPR || code == UNGE_EXPR || code == UNEQ_EXPR)
-         && operand_equal_p (arg0, arg1, 0))
-       return constant_boolean_node (1, type);
-
-      if (code == LTGT_EXPR
-         && !flag_trapping_math
-         && operand_equal_p (arg0, arg1, 0))
-       return constant_boolean_node (0, type);
-
-      /* Fold (double)float1 CMP (double)float2 into float1 CMP float2.  */
-      {
-       tree targ0 = strip_float_extensions (arg0);
-       tree targ1 = strip_float_extensions (arg1);
-       tree newtype = TREE_TYPE (targ0);
-
-       if (TYPE_PRECISION (TREE_TYPE (targ1)) > TYPE_PRECISION (newtype))
-         newtype = TREE_TYPE (targ1);
-
-       if (TYPE_PRECISION (newtype) < TYPE_PRECISION (TREE_TYPE (arg0)))
-         return fold (build2 (code, type, fold_convert (newtype, targ0),
-                              fold_convert (newtype, targ1)));
-      }
-
-      return t;
-
-    case COND_EXPR:
-      /* Pedantic ANSI C says that a conditional expression is never an lvalue,
-        so all simple results must be passed through pedantic_non_lvalue.  */
-      if (TREE_CODE (arg0) == INTEGER_CST)
-       {
-         tem = TREE_OPERAND (t, (integer_zerop (arg0) ? 2 : 1));
-         /* Only optimize constant conditions when the selected branch
-            has the same type as the COND_EXPR.  This avoids optimizing
-            away "c ? x : throw", where the throw has a void type.  */
-         if (! VOID_TYPE_P (TREE_TYPE (tem))
-             || VOID_TYPE_P (type))
-           return pedantic_non_lvalue (tem);
-         return t;
-       }
-      if (operand_equal_p (arg1, TREE_OPERAND (t, 2), 0))
-       return pedantic_omit_one_operand (type, arg1, arg0);
-
-      /* If we have A op B ? A : C, we may be able to convert this to a
-        simpler expression, depending on the operation and the values
-        of B and C.  Signed zeros prevent all of these transformations,
-        for reasons given above each one.
-
-         Also try swapping the arguments and inverting the conditional.  */
-      if (COMPARISON_CLASS_P (arg0)
-         && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
-                                            arg1, TREE_OPERAND (arg0, 1))
-         && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
-       {
-         tem = fold_cond_expr_with_comparison (type, arg0,
-                                               TREE_OPERAND (t, 1),
-                                               TREE_OPERAND (t, 2));
-         if (tem)
-           return tem;
-       }
-
-      if (COMPARISON_CLASS_P (arg0)
-         && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
-                                            TREE_OPERAND (t, 2),
-                                            TREE_OPERAND (arg0, 1))
-         && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 2)))))
-       {
-         tem = invert_truthvalue (arg0);
-         if (COMPARISON_CLASS_P (tem))
-           {
-             tem = fold_cond_expr_with_comparison (type, tem,
-                                                   TREE_OPERAND (t, 2),
-                                                   TREE_OPERAND (t, 1));
-             if (tem)
-               return tem;
-           }
-       }
-
-      /* If the second operand is simpler than the third, swap them
-        since that produces better jump optimization results.  */
-      if (tree_swap_operands_p (TREE_OPERAND (t, 1),
-                               TREE_OPERAND (t, 2), false))
-       {
-         /* See if this can be inverted.  If it can't, possibly because
-            it was a floating-point inequality comparison, don't do
-            anything.  */
-         tem = invert_truthvalue (arg0);
-
-         if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
-           return fold (build3 (code, type, tem,
-                                TREE_OPERAND (t, 2), TREE_OPERAND (t, 1)));
+           return fold (build2 (code, type,
+                                build1 (INDIRECT_REF, char_type_node,
+                                        TREE_VALUE (arglist)),
+                                fold_convert (char_type_node,
+                                              integer_zero_node)));
        }
 
-      /* Convert A ? 1 : 0 to simply A.  */
-      if (integer_onep (TREE_OPERAND (t, 1))
-         && integer_zerop (TREE_OPERAND (t, 2))
-         /* If we try to convert TREE_OPERAND (t, 0) to our type, the
-            call to fold will try to move the conversion inside
-            a COND, which will recurse.  In that case, the COND_EXPR
-            is probably the best choice, so leave it alone.  */
-         && type == TREE_TYPE (arg0))
-       return pedantic_non_lvalue (arg0);
+      /* We can fold X/C1 op C2 where C1 and C2 are integer constants
+        into a single range test.  */
+      if ((TREE_CODE (arg0) == TRUNC_DIV_EXPR
+          || TREE_CODE (arg0) == EXACT_DIV_EXPR)
+         && TREE_CODE (arg1) == INTEGER_CST
+         && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
+         && !integer_zerop (TREE_OPERAND (arg0, 1))
+         && !TREE_OVERFLOW (TREE_OPERAND (arg0, 1))
+         && !TREE_OVERFLOW (arg1))
+       {
+         t1 = fold_div_compare (code, type, arg0, arg1);
+         if (t1 != NULL_TREE)
+           return t1;
+       }
 
-      /* Convert A ? 0 : 1 to !A.  This prefers the use of NOT_EXPR
-        over COND_EXPR in cases such as floating point comparisons.  */
-      if (integer_zerop (TREE_OPERAND (t, 1))
-         && integer_onep (TREE_OPERAND (t, 2))
-         && truth_value_p (TREE_CODE (arg0)))
-       return pedantic_non_lvalue (fold_convert (type,
-                                                 invert_truthvalue (arg0)));
+      if ((code == EQ_EXPR || code == NE_EXPR)
+         && !TREE_SIDE_EFFECTS (arg0)
+         && integer_zerop (arg1)
+         && tree_expr_nonzero_p (arg0))
+       return constant_boolean_node (code==NE_EXPR, type);
 
-      /* A < 0 ? <sign bit of A> : 0 is simply (A & <sign bit of A>).  */
-      if (TREE_CODE (arg0) == LT_EXPR
-          && integer_zerop (TREE_OPERAND (arg0, 1))
-          && integer_zerop (TREE_OPERAND (t, 2))
-          && (tem = sign_bit_p (TREE_OPERAND (arg0, 0), arg1)))
-        return fold_convert (type, fold (build2 (BIT_AND_EXPR,
-                                                TREE_TYPE (tem), tem, arg1)));
+      t1 = fold_relational_const (code, type, arg0, arg1);
+      return t1 == NULL_TREE ? t : t1;
 
-      /* (A >> N) & 1 ? (1 << N) : 0 is simply A & (1 << N).  A & 1 was
-        already handled above.  */
-      if (TREE_CODE (arg0) == BIT_AND_EXPR
-         && integer_onep (TREE_OPERAND (arg0, 1))
-         && integer_zerop (TREE_OPERAND (t, 2))
-         && integer_pow2p (arg1))
+    case UNORDERED_EXPR:
+    case ORDERED_EXPR:
+    case UNLT_EXPR:
+    case UNLE_EXPR:
+    case UNGT_EXPR:
+    case UNGE_EXPR:
+    case UNEQ_EXPR:
+    case LTGT_EXPR:
+      if (TREE_CODE (arg0) == REAL_CST && TREE_CODE (arg1) == REAL_CST)
        {
-         tree tem = TREE_OPERAND (arg0, 0);
-         STRIP_NOPS (tem);
-         if (TREE_CODE (tem) == RSHIFT_EXPR
-              && TREE_CODE (TREE_OPERAND (tem, 1)) == INTEGER_CST
-              && (unsigned HOST_WIDE_INT) tree_log2 (arg1) ==
-                TREE_INT_CST_LOW (TREE_OPERAND (tem, 1)))
-           return fold (build2 (BIT_AND_EXPR, type,
-                                TREE_OPERAND (tem, 0), arg1));
+         t1 = fold_relational_const (code, type, arg0, arg1);
+         if (t1 != NULL_TREE)
+           return t1;
        }
 
-      /* A & N ? N : 0 is simply A & N if N is a power of two.  This
-        is probably obsolete because the first operand should be a
-        truth value (that's why we have the two cases above), but let's
-        leave it in until we can confirm this for all front-ends.  */
-      if (integer_zerop (TREE_OPERAND (t, 2))
-         && TREE_CODE (arg0) == NE_EXPR
-         && integer_zerop (TREE_OPERAND (arg0, 1))
-         && integer_pow2p (arg1)
-         && TREE_CODE (TREE_OPERAND (arg0, 0)) == BIT_AND_EXPR
-         && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1),
-                             arg1, OEP_ONLY_CONST))
-       return pedantic_non_lvalue (fold_convert (type,
-                                                 TREE_OPERAND (arg0, 0)));
-
-      /* Convert A ? B : 0 into A && B if A and B are truth values.  */
-      if (integer_zerop (TREE_OPERAND (t, 2))
-         && truth_value_p (TREE_CODE (arg0))
-         && truth_value_p (TREE_CODE (arg1)))
-       return fold (build2 (TRUTH_ANDIF_EXPR, type, arg0, arg1));
-
-      /* Convert A ? B : 1 into !A || B if A and B are truth values.  */
-      if (integer_onep (TREE_OPERAND (t, 2))
-         && truth_value_p (TREE_CODE (arg0))
-         && truth_value_p (TREE_CODE (arg1)))
+      /* If the first operand is NaN, the result is constant.  */
+      if (TREE_CODE (arg0) == REAL_CST
+         && REAL_VALUE_ISNAN (TREE_REAL_CST (arg0))
+         && (code != LTGT_EXPR || ! flag_trapping_math))
        {
-         /* Only perform transformation if ARG0 is easily inverted.  */
-         tem = invert_truthvalue (arg0);
-         if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
-           return fold (build2 (TRUTH_ORIF_EXPR, type, tem, arg1));
+         t1 = (code == ORDERED_EXPR || code == LTGT_EXPR)
+              ? integer_zero_node
+              : integer_one_node;
+         return omit_one_operand (type, t1, arg1);
        }
 
-      /* Convert A ? 0 : B into !A && B if A and B are truth values.  */
-      if (integer_zerop (arg1)
-         && truth_value_p (TREE_CODE (arg0))
-         && truth_value_p (TREE_CODE (TREE_OPERAND (t, 2))))
+      /* If the second operand is NaN, the result is constant.  */
+      if (TREE_CODE (arg1) == REAL_CST
+         && REAL_VALUE_ISNAN (TREE_REAL_CST (arg1))
+         && (code != LTGT_EXPR || ! flag_trapping_math))
        {
-         /* Only perform transformation if ARG0 is easily inverted.  */
-         tem = invert_truthvalue (arg0);
-         if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
-           return fold (build2 (TRUTH_ANDIF_EXPR, type, tem,
-                                TREE_OPERAND (t, 2)));
+         t1 = (code == ORDERED_EXPR || code == LTGT_EXPR)
+              ? integer_zero_node
+              : integer_one_node;
+         return omit_one_operand (type, t1, arg0);
        }
 
-      /* Convert A ? 1 : B into A || B if A and B are truth values.  */
-      if (integer_onep (arg1)
-         && truth_value_p (TREE_CODE (arg0))
-         && truth_value_p (TREE_CODE (TREE_OPERAND (t, 2))))
-       return fold (build2 (TRUTH_ORIF_EXPR, type, arg0,
-                            TREE_OPERAND (t, 2)));
+      /* Simplify unordered comparison of something with itself.  */
+      if ((code == UNLE_EXPR || code == UNGE_EXPR || code == UNEQ_EXPR)
+         && operand_equal_p (arg0, arg1, 0))
+       return constant_boolean_node (1, type);
+
+      if (code == LTGT_EXPR
+         && !flag_trapping_math
+         && operand_equal_p (arg0, arg1, 0))
+       return constant_boolean_node (0, type);
+
+      /* Fold (double)float1 CMP (double)float2 into float1 CMP float2.  */
+      {
+       tree targ0 = strip_float_extensions (arg0);
+       tree targ1 = strip_float_extensions (arg1);
+       tree newtype = TREE_TYPE (targ0);
+
+       if (TYPE_PRECISION (TREE_TYPE (targ1)) > TYPE_PRECISION (newtype))
+         newtype = TREE_TYPE (targ1);
+
+       if (TYPE_PRECISION (newtype) < TYPE_PRECISION (TREE_TYPE (arg0)))
+         return fold (build2 (code, type, fold_convert (newtype, targ0),
+                              fold_convert (newtype, targ1)));
+      }
 
       return t;
 
@@ -9223,51 +9893,6 @@ fold (tree expr)
        return build_complex (type, arg0, arg1);
       return t;
 
-    case REALPART_EXPR:
-      if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
-       return t;
-      else if (TREE_CODE (arg0) == COMPLEX_EXPR)
-       return omit_one_operand (type, TREE_OPERAND (arg0, 0),
-                                TREE_OPERAND (arg0, 1));
-      else if (TREE_CODE (arg0) == COMPLEX_CST)
-       return TREE_REALPART (arg0);
-      else if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
-       return fold (build2 (TREE_CODE (arg0), type,
-                            fold (build1 (REALPART_EXPR, type,
-                                          TREE_OPERAND (arg0, 0))),
-                            fold (build1 (REALPART_EXPR, type,
-                                          TREE_OPERAND (arg0, 1)))));
-      return t;
-
-    case IMAGPART_EXPR:
-      if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
-       return fold_convert (type, integer_zero_node);
-      else if (TREE_CODE (arg0) == COMPLEX_EXPR)
-       return omit_one_operand (type, TREE_OPERAND (arg0, 1),
-                                TREE_OPERAND (arg0, 0));
-      else if (TREE_CODE (arg0) == COMPLEX_CST)
-       return TREE_IMAGPART (arg0);
-      else if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
-       return fold (build2 (TREE_CODE (arg0), type,
-                            fold (build1 (IMAGPART_EXPR, type,
-                                          TREE_OPERAND (arg0, 0))),
-                            fold (build1 (IMAGPART_EXPR, type,
-                                          TREE_OPERAND (arg0, 1)))));
-      return t;
-
-    case CALL_EXPR:
-      /* Check for a built-in function.  */
-      if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
-         && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 0))
-             == FUNCTION_DECL)
-         && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (t, 0), 0)))
-       {
-         tree tmp = fold_builtin (t, false);
-         if (tmp)
-           return tmp;
-       }
-      return t;
-
     default:
       return t;
     } /* switch (code) */
@@ -9418,7 +10043,7 @@ fold_checksum_tree (tree expr, struct md5_ctx *ctx, htab_t ht)
     case tcc_unary:
     case tcc_binary:
     case tcc_statement:
-      len = first_rtl_op (code);
+      len = TREE_CODE_LENGTH (code);
       for (i = 0; i < len; ++i)
        fold_checksum_tree (TREE_OPERAND (expr, i), ctx, ht);
       break;
@@ -9471,17 +10096,20 @@ fold_initializer (tree expr)
 {
   int saved_signaling_nans = flag_signaling_nans;
   int saved_trapping_math = flag_trapping_math;
+  int saved_rounding_math = flag_rounding_math;
   int saved_trapv = flag_trapv;
   tree result;
 
   flag_signaling_nans = 0;
   flag_trapping_math = 0;
+  flag_rounding_math = 0;
   flag_trapv = 0;
 
   result = fold (expr);
 
   flag_signaling_nans = saved_signaling_nans;
   flag_trapping_math = saved_trapping_math;
+  flag_rounding_math = saved_rounding_math;
   flag_trapv = saved_trapv;
 
   return result;
@@ -9538,6 +10166,13 @@ multiple_of_p (tree type, tree top, tree bottom)
 
   switch (TREE_CODE (top))
     {
+    case BIT_AND_EXPR:
+      /* Bitwise and provides a power of two multiple.  If the mask is
+        a multiple of BOTTOM then TOP is a multiple of BOTTOM.  */
+      if (!integer_pow2p (bottom))
+       return 0;
+      /* FALLTHRU */
+
     case MULT_EXPR:
       return (multiple_of_p (type, TREE_OPERAND (top, 0), bottom)
              || multiple_of_p (type, TREE_OPERAND (top, 1), bottom));
@@ -9766,9 +10401,7 @@ tree_expr_nonnegative_p (tree t)
       {
        tree fndecl = get_callee_fndecl (t);
        tree arglist = TREE_OPERAND (t, 1);
-       if (fndecl
-           && DECL_BUILT_IN (fndecl)
-           && DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_MD)
+       if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
          switch (DECL_FUNCTION_CODE (fndecl))
            {
 #define CASE_BUILTIN_F(BUILT_IN_FN) \
@@ -10773,6 +11406,21 @@ fold_build_cleanup_point_expr (tree type, tree expr)
      it with a cleanup point expression.  */
   if (!TREE_SIDE_EFFECTS (expr))
     return expr;
+
+  /* If the expression is a return, check to see if the expression inside the
+     return has no side effects or the right hand side of the modify expression
+     inside the return. If either don't have side effects set we don't need to
+     wrap the expression in a cleanup point expression.  Note we don't check the
+     left hand side of the modify because it should always be a return decl.  */
+  if (TREE_CODE (expr) == RETURN_EXPR)
+    {
+      tree op = TREE_OPERAND (expr, 0);
+      if (!op || !TREE_SIDE_EFFECTS (op))
+        return expr;
+      op = TREE_OPERAND (op, 1);
+      if (!TREE_SIDE_EFFECTS (op))
+        return expr;
+    }
   
   return build1 (CLEANUP_POINT_EXPR, type, expr);
 }
@@ -10799,9 +11447,7 @@ build_fold_addr_expr_with_type (tree t, tree ptrtype)
     {
       tree base = t;
 
-      while (handled_component_p (base)
-            || TREE_CODE (base) == REALPART_EXPR
-            || TREE_CODE (base) == IMAGPART_EXPR)
+      while (handled_component_p (base))
        base = TREE_OPERAND (base, 0);
       if (DECL_P (base))
        TREE_ADDRESSABLE (base) = 1;
@@ -10818,17 +11464,21 @@ build_fold_addr_expr (tree t)
   return build_fold_addr_expr_with_type (t, build_pointer_type (TREE_TYPE (t)));
 }
 
-/* Builds an expression for an indirection through T, simplifying some
-   cases.  */
+/* Given a pointer value T, return a simplified version of an indirection
+   through T, or NULL_TREE if no simplification is possible.  */
 
-tree
-build_fold_indirect_ref (tree t)
+static tree
+fold_indirect_ref_1 (tree t)
 {
   tree type = TREE_TYPE (TREE_TYPE (t));
   tree sub = t;
   tree subtype;
 
   STRIP_NOPS (sub);
+  subtype = TREE_TYPE (sub);
+  if (!POINTER_TYPE_P (subtype))
+    return NULL_TREE;
+
   if (TREE_CODE (sub) == ADDR_EXPR)
     {
       tree op = TREE_OPERAND (sub, 0);
@@ -10839,19 +11489,56 @@ build_fold_indirect_ref (tree t)
       /* *(foo *)&fooarray => fooarray[0] */
       else if (TREE_CODE (optype) == ARRAY_TYPE
               && lang_hooks.types_compatible_p (type, TREE_TYPE (optype)))
-       return build4 (ARRAY_REF, type, op, size_zero_node, NULL_TREE, NULL_TREE);
+       {
+         tree type_domain = TYPE_DOMAIN (optype);
+         tree min_val = size_zero_node;
+         if (type_domain && TYPE_MIN_VALUE (type_domain))
+           min_val = TYPE_MIN_VALUE (type_domain);
+         return build4 (ARRAY_REF, type, op, min_val, NULL_TREE, NULL_TREE);
+       }
     }
 
   /* *(foo *)fooarrptr => (*fooarrptr)[0] */
-  subtype = TREE_TYPE (sub);
   if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
       && lang_hooks.types_compatible_p (type, TREE_TYPE (TREE_TYPE (subtype))))
     {
+      tree type_domain;
+      tree min_val = size_zero_node;
       sub = build_fold_indirect_ref (sub);
-      return build4 (ARRAY_REF, type, sub, size_zero_node, NULL_TREE, NULL_TREE);
+      type_domain = TYPE_DOMAIN (TREE_TYPE (sub));
+      if (type_domain && TYPE_MIN_VALUE (type_domain))
+       min_val = TYPE_MIN_VALUE (type_domain);
+      return build4 (ARRAY_REF, type, sub, min_val, NULL_TREE, NULL_TREE);
     }
 
-  return build1 (INDIRECT_REF, type, t);
+  return NULL_TREE;
+}
+
+/* Builds an expression for an indirection through T, simplifying some
+   cases.  */
+
+tree
+build_fold_indirect_ref (tree t)
+{
+  tree sub = fold_indirect_ref_1 (t);
+
+  if (sub)
+    return sub;
+  else
+    return build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (t)), t);
+}
+
+/* Given an INDIRECT_REF T, return either T or a simplified version.  */
+
+tree
+fold_indirect_ref (tree t)
+{
+  tree sub = fold_indirect_ref_1 (TREE_OPERAND (t, 0));
+
+  if (sub)
+    return sub;
+  else
+    return t;
 }
 
 /* Strip non-trapping, non-side-effecting tree nodes from an expression
@@ -11010,7 +11697,8 @@ split_address_to_core_and_offset (tree exp,
   if (TREE_CODE (exp) == ADDR_EXPR)
     {
       core = get_inner_reference (TREE_OPERAND (exp, 0), &bitsize, pbitpos,
-                                 poffset, &mode, &unsignedp, &volatilep);
+                                 poffset, &mode, &unsignedp, &volatilep,
+                                 false);
 
       if (TREE_CODE (core) == INDIRECT_REF)
        core = TREE_OPERAND (core, 0);
@@ -11067,3 +11755,38 @@ ptr_difference_const (tree e1, tree e2, HOST_WIDE_INT *diff)
   *diff += (bitpos1 - bitpos2) / BITS_PER_UNIT;
   return true;
 }
+
+/* Simplify the floating point expression EXP when the sign of the
+   result is not significant.  Return NULL_TREE if no simplification
+   is possible.  */
+
+tree
+fold_strip_sign_ops (tree exp)
+{
+  tree arg0, arg1;
+
+  switch (TREE_CODE (exp))
+    {
+    case ABS_EXPR:
+    case NEGATE_EXPR:
+      arg0 = fold_strip_sign_ops (TREE_OPERAND (exp, 0));
+      return arg0 ? arg0 : TREE_OPERAND (exp, 0);
+
+    case MULT_EXPR:
+    case RDIV_EXPR:
+      if (HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (TREE_TYPE (exp))))
+       return NULL_TREE;
+      arg0 = fold_strip_sign_ops (TREE_OPERAND (exp, 0));
+      arg1 = fold_strip_sign_ops (TREE_OPERAND (exp, 1));
+      if (arg0 != NULL_TREE || arg1 != NULL_TREE)
+       return fold (build2 (TREE_CODE (exp), TREE_TYPE (exp),
+                            arg0 ? arg0 : TREE_OPERAND (exp, 0),
+                            arg1 ? arg1 : TREE_OPERAND (exp, 1)));
+      break;
+
+    default:
+      break;
+    }
+  return NULL_TREE;
+}
+