OSDN Git Service

PR middle-end/20623
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index 5c7effe..c3b77d4 100644 (file)
@@ -1410,7 +1410,7 @@ fold_negate_expr (tree t)
                 == TREE_INT_CST_LOW (op1))
            {
              tree ntype = TYPE_UNSIGNED (type)
-                          ? lang_hooks.types.signed_type (type)
+                          ? signed_type_for (type)
                           : unsigned_type_for (type);
              tree temp = fold_convert (ntype, TREE_OPERAND (t, 0));
              temp = fold_build2 (RSHIFT_EXPR, ntype, temp, op1);
@@ -2028,7 +2028,7 @@ size_diffop (tree arg0, tree arg1)
   else if (type == bitsizetype)
     ctype = sbitsizetype;
   else
-    ctype = lang_hooks.types.signed_type (type);
+    ctype = signed_type_for (type);
 
   /* If either operand is not a constant, do the conversions to the signed
      type and subtract.  The hardware will do the right thing with any
@@ -3045,7 +3045,7 @@ operand_equal_for_comparison_p (tree arg0, tree arg1, tree other)
 
       /* Make sure shorter operand is extended the right way
         to match the longer operand.  */
-      primarg1 = fold_convert (get_signed_or_unsigned_type
+      primarg1 = fold_convert (signed_or_unsigned_type_for
                               (unsignedp1, TREE_TYPE (primarg1)), primarg1);
 
       if (operand_equal_p (arg0, fold_convert (type, primarg1), 0))
@@ -3828,7 +3828,7 @@ all_ones_mask_p (tree mask, int size)
   unsigned int precision = TYPE_PRECISION (type);
   tree tmask;
 
-  tmask = build_int_cst_type (lang_hooks.types.signed_type (type), -1);
+  tmask = build_int_cst_type (signed_type_for (type), -1);
 
   return
     tree_int_cst_equal (mask,
@@ -4382,7 +4382,7 @@ build_range_check (tree type, tree exp, int in_p, tree low, tree high)
        {
          if (TYPE_UNSIGNED (etype))
            {
-             etype = lang_hooks.types.signed_type (etype);
+             etype = signed_type_for (etype);
              exp = fold_convert (etype, exp);
            }
          return fold_build2 (GT_EXPR, type, exp,
@@ -4439,6 +4439,20 @@ build_range_check (tree type, tree exp, int in_p, tree low, tree high)
 
   value = const_binop (MINUS_EXPR, high, low, 0);
 
+
+  if (POINTER_TYPE_P (etype))
+    {
+      if (value != 0 && !TREE_OVERFLOW (value))
+       {
+         low = fold_convert (sizetype, low);
+         low = fold_build1 (NEGATE_EXPR, sizetype, low);
+          return build_range_check (type,
+                                   fold_build2 (POINTER_PLUS_EXPR, etype, exp, low),
+                                   1, build_int_cst (etype, 0), value);
+       }
+      return 0;
+    }
+
   if (value != 0 && !TREE_OVERFLOW (value))
     return build_range_check (type,
                              fold_build2 (MINUS_EXPR, etype, exp, low),
@@ -4756,7 +4770,7 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
       case GE_EXPR:
       case GT_EXPR:
        if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
-         arg1 = fold_convert (lang_hooks.types.signed_type
+         arg1 = fold_convert (signed_type_for
                               (TREE_TYPE (arg1)), arg1);
        tem = fold_build1 (ABS_EXPR, TREE_TYPE (arg1), arg1);
        return pedantic_non_lvalue (fold_convert (type, tem));
@@ -4767,7 +4781,7 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
       case LE_EXPR:
       case LT_EXPR:
        if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
-         arg1 = fold_convert (lang_hooks.types.signed_type
+         arg1 = fold_convert (signed_type_for
                               (TREE_TYPE (arg1)), arg1);
        tem = fold_build1 (ABS_EXPR, TREE_TYPE (arg1), arg1);
        return negate_expr (fold_convert (type, tem));
@@ -5075,7 +5089,7 @@ unextend (tree c, int p, int unsignedp, tree mask)
      zero or one, and the conversion to a signed type can never overflow.
      We could get an overflow if this conversion is done anywhere else.  */
   if (TYPE_UNSIGNED (type))
-    temp = fold_convert (lang_hooks.types.signed_type (type), temp);
+    temp = fold_convert (signed_type_for (type), temp);
 
   temp = const_binop (LSHIFT_EXPR, temp, size_int (modesize - 1), 0);
   temp = const_binop (RSHIFT_EXPR, temp, size_int (modesize - p - 1), 0);
@@ -5747,7 +5761,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
          must avoid building ABS_EXPR itself as unsigned.  */
       if (TYPE_UNSIGNED (ctype) && !TYPE_UNSIGNED (type))
         {
-          tree cstype = (*lang_hooks.types.signed_type) (ctype);
+          tree cstype = (*signed_type_for) (ctype);
           if ((t1 = extract_muldiv (op0, c, code, cstype, strict_overflow_p))
              != 0)
             {
@@ -5992,7 +6006,7 @@ constant_boolean_node (int value, tree type)
    offset is set to NULL_TREE.  Base will be canonicalized to
    something you can get the element type from using
    TREE_TYPE (TREE_TYPE (base)).  Offset will be the offset
-   in bytes to the base.  */
+   in bytes to the base in sizetype.  */
 
 static bool
 extract_array_ref (tree expr, tree *base, tree *offset)
@@ -6000,21 +6014,20 @@ extract_array_ref (tree expr, tree *base, tree *offset)
   /* 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)
+  if (TREE_CODE (expr) == POINTER_PLUS_EXPR)
     {
       tree op0 = TREE_OPERAND (expr, 0);
       tree inner_base, dummy1;
       /* Strip NOP_EXPRs here because the C frontends and/or
-        folders present us (int *)&x.a + 4B possibly.  */
+        folders present us (int *)&x.a p+ 4 possibly.  */
       STRIP_NOPS (op0);
       if (extract_array_ref (op0, &inner_base, &dummy1))
        {
          *base = inner_base;
-         if (dummy1 == NULL_TREE)
-           *offset = TREE_OPERAND (expr, 1);
-         else
-           *offset = fold_build2 (PLUS_EXPR, TREE_TYPE (expr),
-                                  dummy1, TREE_OPERAND (expr, 1));
+         *offset = fold_convert (sizetype, TREE_OPERAND (expr, 1));
+         if (dummy1 != NULL_TREE)
+           *offset = fold_build2 (PLUS_EXPR, sizetype,
+                                  dummy1, *offset);
          return true;
        }
     }
@@ -6032,6 +6045,7 @@ extract_array_ref (tree expr, tree *base, tree *offset)
          *base = TREE_OPERAND (op0, 0);
          *offset = fold_build2 (MULT_EXPR, TREE_TYPE (idx), idx,
                                 array_ref_element_size (op0)); 
+         *offset = fold_convert (sizetype, *offset);
        }
       else
        {
@@ -6558,7 +6572,7 @@ fold_single_bit_test_into_sign_test (enum tree_code code, tree arg0, tree arg1,
          && TYPE_PRECISION (TREE_TYPE (arg00))
             == GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (arg00))))
        {
-         tree stype = lang_hooks.types.signed_type (TREE_TYPE (arg00));
+         tree stype = signed_type_for (TREE_TYPE (arg00));
          return fold_build2 (code == EQ_EXPR ? GE_EXPR : LT_EXPR,
                              result_type, fold_convert (stype, arg00),
                              build_int_cst (stype, 0));
@@ -6866,7 +6880,7 @@ fold_sign_changed_comparison (enum tree_code code, tree type,
   return fold_build2 (code, type, arg0_inner, arg1);
 }
 
-/* Tries to replace &a[idx] CODE s * delta with &a[idx CODE delta], if s is
+/* Tries to replace &a[idx] p+ s * delta with &a[idx + delta], if s is
    step of the array.  Reconstructs s and delta in the case of s * delta
    being an integer constant (and thus already folded).
    ADDR is the address. MULT is the multiplicative expression.
@@ -6874,7 +6888,7 @@ fold_sign_changed_comparison (enum tree_code code, tree type,
    NULL_TREE is returned.  */
 
 static tree
-try_move_mult_to_index (enum tree_code code, tree addr, tree op1)
+try_move_mult_to_index (tree addr, tree op1)
 {
   tree s, delta, step;
   tree ref = TREE_OPERAND (addr, 0), pref;
@@ -6882,6 +6896,9 @@ try_move_mult_to_index (enum tree_code code, tree addr, tree op1)
   tree itype;
   bool mdim = false;
 
+  /*  Strip the nops that might be added when converting op1 to sizetype. */
+  STRIP_NOPS (op1);
+
   /* Canonicalize op1 into a possibly non-constant delta
      and an INTEGER_CST s.  */
   if (TREE_CODE (op1) == MULT_EXPR)
@@ -6958,7 +6975,7 @@ try_move_mult_to_index (enum tree_code code, tree addr, tree op1)
                  || TREE_CODE (TYPE_MAX_VALUE (itype)) != INTEGER_CST)
                continue;
 
-             tmp = fold_binary (code, itype,
+             tmp = fold_binary (PLUS_EXPR, itype,
                                 fold_convert (itype,
                                               TREE_OPERAND (ref, 1)),
                                 fold_convert (itype, delta));
@@ -6991,7 +7008,7 @@ try_move_mult_to_index (enum tree_code code, tree addr, tree op1)
       pos = TREE_OPERAND (pos, 0);
     }
 
-  TREE_OPERAND (pos, 1) = fold_build2 (code, itype,
+  TREE_OPERAND (pos, 1) = fold_build2 (PLUS_EXPR, itype,
                                       fold_convert (itype,
                                                     TREE_OPERAND (pos, 1)),
                                       fold_convert (itype, delta));
@@ -7037,9 +7054,18 @@ fold_to_nonsharp_ineq_using_bound (tree ineq, tree bound)
   if (TREE_TYPE (a1) != typea)
     return NULL_TREE;
 
-  diff = fold_build2 (MINUS_EXPR, typea, a1, a);
-  if (!integer_onep (diff))
-    return NULL_TREE;
+  if (POINTER_TYPE_P (typea))
+    {
+      /* Convert the pointer types into integer before taking the difference.  */
+      tree ta = fold_convert (ssizetype, a);
+      tree ta1 = fold_convert (ssizetype, a1);
+      diff = fold_binary (MINUS_EXPR, ssizetype, ta1, ta);
+    }
+  else
+   diff = fold_binary (MINUS_EXPR, typea, a1, a);
+
+  if (!diff || !integer_onep (diff))
+   return NULL_TREE;
 
   return fold_build2 (GE_EXPR, type, a, y);
 }
@@ -7526,6 +7552,77 @@ fold_view_convert_expr (tree type, tree expr)
   return native_interpret_expr (type, buffer, len);
 }
 
+/* Build an expression for the address of T.  Folds away INDIRECT_REF
+   to avoid confusing the gimplify process.  When IN_FOLD is true
+   avoid modifications of T.  */
+
+static tree
+build_fold_addr_expr_with_type_1 (tree t, tree ptrtype, bool in_fold)
+{
+  /* The size of the object is not relevant when talking about its address.  */
+  if (TREE_CODE (t) == WITH_SIZE_EXPR)
+    t = TREE_OPERAND (t, 0);
+
+  /* Note: doesn't apply to ALIGN_INDIRECT_REF */
+  if (TREE_CODE (t) == INDIRECT_REF
+      || TREE_CODE (t) == MISALIGNED_INDIRECT_REF)
+    {
+      t = TREE_OPERAND (t, 0);
+
+      if (TREE_TYPE (t) != ptrtype)
+       t = build1 (NOP_EXPR, ptrtype, t);
+    }
+  else if (!in_fold)
+    {
+      tree base = t;
+
+      while (handled_component_p (base))
+       base = TREE_OPERAND (base, 0);
+
+      if (DECL_P (base))
+       TREE_ADDRESSABLE (base) = 1;
+
+      t = build1 (ADDR_EXPR, ptrtype, t);
+    }
+  else
+    t = build1 (ADDR_EXPR, ptrtype, t);
+
+  return t;
+}
+
+/* Build an expression for the address of T with type PTRTYPE.  This
+   function modifies the input parameter 'T' by sometimes setting the
+   TREE_ADDRESSABLE flag.  */
+
+tree
+build_fold_addr_expr_with_type (tree t, tree ptrtype)
+{
+  return build_fold_addr_expr_with_type_1 (t, ptrtype, false);
+}
+
+/* Build an expression for the address of T.  This function modifies
+   the input parameter 'T' by sometimes setting the TREE_ADDRESSABLE
+   flag.  When called from fold functions, use fold_addr_expr instead.  */
+
+tree
+build_fold_addr_expr (tree t)
+{
+  return build_fold_addr_expr_with_type_1 (t, 
+                                          build_pointer_type (TREE_TYPE (t)),
+                                          false);
+}
+
+/* Same as build_fold_addr_expr, builds an expression for the address
+   of T, but avoids touching the input node 't'.  Fold functions
+   should use this version.  */
+
+static tree
+fold_addr_expr (tree t)
+{
+  tree ptrtype = build_pointer_type (TREE_TYPE (t));
+
+  return build_fold_addr_expr_with_type_1 (t, ptrtype, true);
+}
 
 /* Fold a unary expression of code CODE and type TYPE with operand
    OP0.  Return the folded expression if folding is successful.
@@ -7761,7 +7858,7 @@ fold_unary (enum tree_code code, tree type, tree op0)
          if (! offset && bitpos == 0
              && TYPE_MAIN_VARIANT (TREE_TYPE (type))
                  == TYPE_MAIN_VARIANT (TREE_TYPE (base)))
-           return fold_convert (type, build_fold_addr_expr (base));
+           return fold_convert (type, fold_addr_expr (base));
         }
 
       if ((TREE_CODE (op0) == MODIFY_EXPR
@@ -7830,11 +7927,11 @@ fold_unary (enum tree_code code, tree type, tree op0)
            }
        }
 
-      /* Convert (T1)(X op Y) into ((T1)X op (T1)Y), for pointer type,
+      /* Convert (T1)(X p+ Y) into ((T1)X p+ Y), for pointer type,
          when one of the new casts will fold away. Conservatively we assume
-        that this happens when X or Y is NOP_EXPR or Y is INTEGER_CST.  */
-      if (POINTER_TYPE_P (type) && POINTER_TYPE_P (TREE_TYPE (arg0))
-         && BINARY_CLASS_P (arg0)
+        that this happens when X or Y is NOP_EXPR or Y is INTEGER_CST. */
+      if (POINTER_TYPE_P (type)
+         && TREE_CODE (arg0) == POINTER_PLUS_EXPR
          && (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
              || TREE_CODE (TREE_OPERAND (arg0, 0)) == NOP_EXPR
              || TREE_CODE (TREE_OPERAND (arg0, 1)) == NOP_EXPR))
@@ -7843,7 +7940,7 @@ fold_unary (enum tree_code code, tree type, tree op0)
          tree arg01 = TREE_OPERAND (arg0, 1);
 
          return fold_build2 (TREE_CODE (arg0), type, fold_convert (type, arg00),
-                             fold_convert (type, arg01));
+                             fold_convert (sizetype, arg01));
        }
 
       /* Convert (T1)(~(T2)X) into ~(T1)X if T1 and T2 are integral types
@@ -8838,8 +8935,8 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
          tree op0 = TREE_OPERAND (cref0, 0);
          tree op1 = TREE_OPERAND (cref1, 0);
          return fold_build2 (code, type,
-                             build_fold_addr_expr (op0),
-                             build_fold_addr_expr (op1));
+                             fold_addr_expr (op0),
+                             fold_addr_expr (op1));
        }
     }
 
@@ -9066,7 +9163,68 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
 
   switch (code)
     {
+    case POINTER_PLUS_EXPR:
+      /* 0 +p index -> (type)index */
+      if (integer_zerop (arg0))
+       return non_lvalue (fold_convert (type, arg1));
+
+      /* PTR +p 0 -> PTR */
+      if (integer_zerop (arg1))
+       return non_lvalue (fold_convert (type, arg0));
+
+      /* INT +p INT -> (PTR)(INT + INT).  Stripping types allows for this. */
+      if (INTEGRAL_TYPE_P (TREE_TYPE (arg1))
+          && INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
+        return fold_convert (type, fold_build2 (PLUS_EXPR, sizetype,
+                                               fold_convert (sizetype, arg1),
+                                               fold_convert (sizetype, arg0)));
+
+      /* index +p PTR -> PTR +p index */
+      if (POINTER_TYPE_P (TREE_TYPE (arg1))
+         && INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
+        return fold_build2 (POINTER_PLUS_EXPR, type,
+                           fold_convert (type, arg1), fold_convert (sizetype, arg0));
+
+      /* (PTR +p B) +p A -> PTR +p (B + A) */
+      if (TREE_CODE (arg0) == POINTER_PLUS_EXPR)
+       {
+         tree inner;
+         tree arg01 = fold_convert (sizetype, TREE_OPERAND (arg0, 1));
+         tree arg00 = TREE_OPERAND (arg0, 0);
+         inner = fold_build2 (PLUS_EXPR, sizetype, arg01, fold_convert (sizetype, arg1));
+         return fold_build2 (POINTER_PLUS_EXPR, type, arg00, inner);
+       }
+
+      /* PTR_CST +p CST -> CST1 */
+      if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
+       return fold_build2 (PLUS_EXPR, type, arg0, fold_convert (type, arg1));
+
+     /* Try replacing &a[i1] +p c * i2 with &a[i1 + i2], if c is step
+       of the array.  Loop optimizer sometimes produce this type of
+       expressions.  */
+      if (TREE_CODE (arg0) == ADDR_EXPR)
+       {
+         tem = try_move_mult_to_index (arg0, fold_convert (sizetype, arg1));
+         if (tem)
+           return fold_convert (type, tem);
+       }
+
+      return NULL_TREE;
     case PLUS_EXPR:
+      /* PTR + INT -> (INT)(PTR p+ INT) */
+      if (POINTER_TYPE_P (TREE_TYPE (arg0))
+         && INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
+       return fold_convert (type, fold_build2 (POINTER_PLUS_EXPR,
+                                               TREE_TYPE (arg0),
+                                               arg0,
+                                               fold_convert (sizetype, arg1)));
+      /* INT + PTR -> (INT)(PTR p+ INT) */
+      if (POINTER_TYPE_P (TREE_TYPE (arg1))
+         && INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
+       return fold_convert (type, fold_build2 (POINTER_PLUS_EXPR,
+                                               TREE_TYPE (arg1),
+                                               arg1,
+                                               fold_convert (sizetype, arg0)));
       /* A + (-B) -> A - B */
       if (TREE_CODE (arg1) == NEGATE_EXPR)
        return fold_build2 (MINUS_EXPR, type,
@@ -9173,22 +9331,6 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                                                 fold_convert (type,
                                                               parg1)));
            }
-
-         /* Try replacing &a[i1] + c * i2 with &a[i1 + i2], if c is step
-            of the array.  Loop optimizer sometimes produce this type of
-            expressions.  */
-         if (TREE_CODE (arg0) == ADDR_EXPR)
-           {
-             tem = try_move_mult_to_index (PLUS_EXPR, arg0, arg1);
-             if (tem)
-               return fold_convert (type, tem);
-           }
-         else if (TREE_CODE (arg1) == ADDR_EXPR)
-           {
-             tem = try_move_mult_to_index (PLUS_EXPR, arg1, arg0);
-             if (tem)
-               return fold_convert (type, tem);
-           }
        }
       else
        {
@@ -9465,6 +9607,31 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
       return NULL_TREE;
 
     case MINUS_EXPR:
+      /* Pointer simplifications for subtraction, simple reassociations. */
+      if (POINTER_TYPE_P (TREE_TYPE (arg1)) && POINTER_TYPE_P (TREE_TYPE (arg0)))
+       {
+         /* (PTR0 p+ A) - (PTR1 p+ B) -> (PTR0 - PTR1) + (A - B) */
+         if (TREE_CODE (arg0) == POINTER_PLUS_EXPR
+             && TREE_CODE (arg1) == POINTER_PLUS_EXPR)
+           {
+             tree arg00 = fold_convert (type, TREE_OPERAND (arg0, 0));
+             tree arg01 = fold_convert (type, TREE_OPERAND (arg0, 1));
+             tree arg10 = fold_convert (type, TREE_OPERAND (arg1, 0));
+             tree arg11 = fold_convert (type, TREE_OPERAND (arg1, 1));
+             return fold_build2 (PLUS_EXPR, type,
+                                 fold_build2 (MINUS_EXPR, type, arg00, arg10),
+                                 fold_build2 (MINUS_EXPR, type, arg01, arg11));
+           }
+         /* (PTR0 p+ A) - PTR1 -> (PTR0 - PTR1) + A, assuming PTR0 - PTR1 simplifies. */
+         else if (TREE_CODE (arg0) == POINTER_PLUS_EXPR)
+           {
+             tree arg00 = fold_convert (type, TREE_OPERAND (arg0, 0));
+             tree arg01 = fold_convert (type, TREE_OPERAND (arg0, 1));
+             tree tmp = fold_binary (MINUS_EXPR, type, arg00, fold_convert (type, arg1));
+             if (tmp)
+               return fold_build2 (PLUS_EXPR, type, tmp, arg01);
+           }
+       }
       /* A - (-B) -> A + B */
       if (TREE_CODE (arg1) == NEGATE_EXPR)
        return fold_build2 (PLUS_EXPR, type, arg0, TREE_OPERAND (arg1, 0));
@@ -9585,7 +9752,10 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
         Also note that operand_equal_p is always false if an operand
         is volatile.  */
 
-      if ((! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
+      if ((! FLOAT_TYPE_P (type)
+          || (flag_unsafe_math_optimizations
+              && !HONOR_NANS (TYPE_MODE (type))
+              && !HONOR_INFINITIES (TYPE_MODE (type))))
          && operand_equal_p (arg0, arg1, 0))
        return fold_convert (type, integer_zero_node);
 
@@ -9631,16 +9801,6 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
            }
        }
 
-      /* Try replacing &a[i1] - c * i2 with &a[i1 - i2], if c is step
-        of the array.  Loop optimizer sometimes produce this type of
-        expressions.  */
-      if (TREE_CODE (arg0) == ADDR_EXPR)
-       {
-         tem = try_move_mult_to_index (MINUS_EXPR, arg0, arg1);
-         if (tem)
-           return fold_convert (type, tem);
-       }
-
       if (flag_unsafe_math_optimizations
          && (TREE_CODE (arg0) == RDIV_EXPR || TREE_CODE (arg0) == MULT_EXPR)
          && (TREE_CODE (arg1) == RDIV_EXPR || TREE_CODE (arg1) == MULT_EXPR)
@@ -10555,8 +10715,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                }
            }
 
-         /* Optimize a/sqrt(b/c) into a*sqrt(c/b).  */
-         if (BUILTIN_SQRT_P (fcode1))
+         /* Optimize a/root(b/c) into a*root(c/b).  */
+         if (BUILTIN_ROOT_P (fcode1))
            {
              tree rootarg = CALL_EXPR_ARG (arg1, 0);
 
@@ -11414,7 +11574,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
            {
              if (TYPE_UNSIGNED (itype))
                {
-                 itype = lang_hooks.types.signed_type (itype);
+                 itype = signed_type_for (itype);
                  arg00 = fold_convert (itype, arg00);
                }
              return fold_build2 (code == EQ_EXPR ? GE_EXPR : LT_EXPR,
@@ -11967,7 +12127,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                if (code == LE_EXPR || code == GT_EXPR)
                  {
                    tree st;
-                   st = lang_hooks.types.signed_type (TREE_TYPE (arg1));
+                   st = signed_type_for (TREE_TYPE (arg1));
                    return fold_build2 (code == LE_EXPR ? GE_EXPR : LT_EXPR,
                                        type, fold_convert (st, arg0),
                                        build_int_cst (st, 0));
@@ -12357,7 +12517,7 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2)
              if ((TREE_INT_CST_HIGH (arg1) & mask_hi) == mask_hi
                  && (TREE_INT_CST_LOW (arg1) & mask_lo) == mask_lo)
                {
-                 tem_type = lang_hooks.types.signed_type (TREE_TYPE (tem));
+                 tem_type = signed_type_for (TREE_TYPE (tem));
                  tem = fold_convert (tem_type, tem);
                }
              else if ((TREE_INT_CST_HIGH (arg1) & mask_hi) == 0
@@ -12686,7 +12846,8 @@ recursive_label:
   fold_checksum_tree (TREE_TYPE (expr), ctx, ht);
   if (TREE_CODE_CLASS (code) != tcc_type
       && TREE_CODE_CLASS (code) != tcc_declaration
-      && code != TREE_LIST)
+      && code != TREE_LIST
+      && code != SSA_NAME)
     fold_checksum_tree (TREE_CHAIN (expr), ctx, ht);
   switch (TREE_CODE_CLASS (code))
     {
@@ -12821,6 +12982,30 @@ fold_build1_stat (enum tree_code code, tree type, tree op0 MEM_STAT_DECL)
   return tem;
 }
 
+/* Helper function for outputting the checksum of a tree T.  When
+   debugging with gdb, you can "define mynext" to be "next" followed
+   by "call debug_fold_checksum (op0)", then just trace down till the
+   outputs differ.  */
+
+void
+debug_fold_checksum (tree t)
+{
+  int i;
+  unsigned char checksum[16];
+  struct md5_ctx ctx;
+  htab_t ht = htab_create (32, htab_hash_pointer, htab_eq_pointer, NULL);
+  
+  md5_init_ctx (&ctx);
+  fold_checksum_tree (t, &ctx, ht);
+  md5_finish_ctx (&ctx, checksum);
+  htab_empty (ht);
+
+  for (i = 0; i < 16; i++)
+    fprintf (stderr, "%d ", checksum[i]);
+
+  fprintf (stderr, "\n");
+}
+
 /* Fold a binary tree expression with code CODE of type TYPE with
    operands OP0 and OP1.  Return a folded expression if successful.
    Otherwise, return a tree expression with code CODE of type TYPE
@@ -13228,6 +13413,7 @@ tree_expr_nonnegative_warnv_p (tree t, bool *strict_overflow_p)
     case REAL_CST:
       return ! REAL_VALUE_NEGATIVE (TREE_REAL_CST (t));
 
+    case POINTER_PLUS_EXPR:
     case PLUS_EXPR:
       if (FLOAT_TYPE_P (TREE_TYPE (t)))
        return (tree_expr_nonnegative_warnv_p (TREE_OPERAND (t, 0),
@@ -13583,6 +13769,7 @@ tree_expr_nonzero_warnv_p (tree t, bool *strict_overflow_p)
     case INTEGER_CST:
       return !integer_zerop (t);
 
+    case POINTER_PLUS_EXPR:
     case PLUS_EXPR:
       if (TYPE_OVERFLOW_UNDEFINED (type))
        {
@@ -14080,45 +14267,6 @@ fold_build_cleanup_point_expr (tree type, tree expr)
   return build1 (CLEANUP_POINT_EXPR, type, expr);
 }
 
-/* Build an expression for the address of T.  Folds away INDIRECT_REF to
-   avoid confusing the gimplify process.  */
-
-tree
-build_fold_addr_expr_with_type (tree t, tree ptrtype)
-{
-  /* The size of the object is not relevant when talking about its address.  */
-  if (TREE_CODE (t) == WITH_SIZE_EXPR)
-    t = TREE_OPERAND (t, 0);
-
-  /* Note: doesn't apply to ALIGN_INDIRECT_REF */
-  if (TREE_CODE (t) == INDIRECT_REF
-      || TREE_CODE (t) == MISALIGNED_INDIRECT_REF)
-    {
-      t = TREE_OPERAND (t, 0);
-      if (TREE_TYPE (t) != ptrtype)
-       t = build1 (NOP_EXPR, ptrtype, t);
-    }
-  else
-    {
-      tree base = t;
-
-      while (handled_component_p (base))
-       base = TREE_OPERAND (base, 0);
-      if (DECL_P (base))
-       TREE_ADDRESSABLE (base) = 1;
-
-      t = build1 (ADDR_EXPR, ptrtype, t);
-    }
-
-  return t;
-}
-
-tree
-build_fold_addr_expr (tree t)
-{
-  return build_fold_addr_expr_with_type (t, build_pointer_type (TREE_TYPE (t)));
-}
-
 /* Given a pointer value OP0 and a type TYPE, return a simplified version
    of an indirection through OP0, or NULL_TREE if no simplification is
    possible.  */
@@ -14175,7 +14323,7 @@ fold_indirect_ref_1 (tree type, tree op0)
     }
 
   /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
-  if (TREE_CODE (sub) == PLUS_EXPR
+  if (TREE_CODE (sub) == POINTER_PLUS_EXPR
       && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
     {
       tree op00 = TREE_OPERAND (sub, 0);
@@ -14422,7 +14570,7 @@ split_address_to_core_and_offset (tree exp,
       core = get_inner_reference (TREE_OPERAND (exp, 0), &bitsize, pbitpos,
                                  poffset, &mode, &unsignedp, &volatilep,
                                  false);
-      core = build_fold_addr_expr (core);
+      core = fold_addr_expr (core);
     }
   else
     {