OSDN Git Service

PR target/47935
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index 02ddac5..07b59d8 100644 (file)
@@ -54,7 +54,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm_p.h"
 #include "target.h"
 #include "diagnostic-core.h"
-#include "toplev.h"
 #include "intl.h"
 #include "ggc.h"
 #include "hashtab.h"
@@ -143,6 +142,25 @@ static tree fold_relational_const (enum tree_code, tree, tree, tree);
 static tree fold_convert_const (enum tree_code, tree, tree);
 
 
+/* Similar to protected_set_expr_location, but never modify x in place,
+   if location can and needs to be set, unshare it.  */
+
+static inline tree
+protected_set_expr_location_unshare (tree x, location_t loc)
+{
+  if (CAN_HAVE_LOCATION_P (x)
+      && EXPR_LOCATION (x) != loc
+      && !(TREE_CODE (x) == SAVE_EXPR
+          || TREE_CODE (x) == TARGET_EXPR
+          || TREE_CODE (x) == BIND_EXPR))
+    {
+      x = copy_node (x);
+      SET_EXPR_LOCATION (x, loc);
+    }
+  return x;
+}
+
+
 /* We know that A1 + B1 = SUM1, using 2's complement arithmetic and ignoring
    overflow.  Suppose A, B and SUM have the same respective signs as A1, B1,
    and SUM1.  Then this yields nonzero if overflow occurred during the
@@ -727,10 +745,7 @@ negate_expr (tree t)
 
   tem = fold_negate_expr (loc, t);
   if (!tem)
-    {
-      tem = build1 (NEGATE_EXPR, TREE_TYPE (t), t);
-      SET_EXPR_LOCATION (tem, loc);
-    }
+    tem = build1_loc (loc, NEGATE_EXPR, TREE_TYPE (t), t);
   return fold_convert_loc (loc, type, tem);
 }
 \f
@@ -841,8 +856,6 @@ split_tree (tree in, enum tree_code code, tree *conp, tree *litp,
 static tree
 associate_trees (location_t loc, tree t1, tree t2, enum tree_code code, tree type)
 {
-  tree tem;
-
   if (t1 == 0)
     return t2;
   else if (t2 == 0)
@@ -857,11 +870,15 @@ associate_trees (location_t loc, tree t1, tree t2, enum tree_code code, tree typ
       if (code == PLUS_EXPR)
        {
          if (TREE_CODE (t1) == NEGATE_EXPR)
-           tem = build2 (MINUS_EXPR, type, fold_convert_loc (loc, type, t2),
-                         fold_convert_loc (loc, type, TREE_OPERAND (t1, 0)));
+           return build2_loc (loc, MINUS_EXPR, type,
+                              fold_convert_loc (loc, type, t2),
+                              fold_convert_loc (loc, type,
+                                                TREE_OPERAND (t1, 0)));
          else if (TREE_CODE (t2) == NEGATE_EXPR)
-           tem = build2 (MINUS_EXPR, type, fold_convert_loc (loc, type, t1),
-                         fold_convert_loc (loc, type, TREE_OPERAND (t2, 0)));
+           return build2_loc (loc, MINUS_EXPR, type,
+                              fold_convert_loc (loc, type, t1),
+                              fold_convert_loc (loc, type,
+                                                TREE_OPERAND (t2, 0)));
          else if (integer_zerop (t2))
            return fold_convert_loc (loc, type, t1);
        }
@@ -871,16 +888,12 @@ associate_trees (location_t loc, tree t1, tree t2, enum tree_code code, tree typ
            return fold_convert_loc (loc, type, t1);
        }
 
-      tem = build2 (code, type, fold_convert_loc (loc, type, t1),
-                   fold_convert_loc (loc, type, t2));
-      goto associate_trees_exit;
+      return build2_loc (loc, code, type, fold_convert_loc (loc, type, t1),
+                        fold_convert_loc (loc, type, t2));
     }
 
   return fold_build2_loc (loc, code, type, fold_convert_loc (loc, type, t1),
-                     fold_convert_loc (loc, type, t2));
- associate_trees_exit:
-  protected_set_expr_location (tem, loc);
-  return tem;
+                         fold_convert_loc (loc, type, t2));
 }
 \f
 /* Check whether TYPE1 and TYPE2 are equivalent integer types, suitable
@@ -1796,16 +1809,10 @@ fold_convert_const (enum tree_code code, tree type, tree arg1)
 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);
+  tree t;
 
-  list = NULL_TREE;
-  for (i = 0; i < units; i++)
-    list = tree_cons (NULL_TREE, elem, list);
-  return build_vector (type, list);
+  t = fold_convert_const (NOP_EXPR, TREE_TYPE (type), integer_zero_node);
+  return build_vector_from_val (type, t);
 }
 
 /* Returns true, if ARG is convertible to TYPE using a NOP_EXPR.  */
@@ -2021,7 +2028,7 @@ fold_convert_loc (location_t loc, tree type, tree arg)
       gcc_unreachable ();
     }
  fold_convert_exit:
-  protected_set_expr_location (tem, loc);
+  protected_set_expr_location_unshare (tem, loc);
   return tem;
 }
 \f
@@ -2044,7 +2051,6 @@ maybe_lvalue_p (const_tree x)
   case COMPONENT_REF:
   case MEM_REF:
   case INDIRECT_REF:
-  case MISALIGNED_INDIRECT_REF:
   case ARRAY_REF:
   case ARRAY_RANGE_REF:
   case BIT_FIELD_REF:
@@ -2086,9 +2092,7 @@ non_lvalue_loc (location_t loc, tree x)
 
   if (! maybe_lvalue_p (x))
     return x;
-  x = build1 (NON_LVALUE_EXPR, TREE_TYPE (x), x);
-  SET_EXPR_LOCATION (x, loc);
-  return x;
+  return build1_loc (loc, NON_LVALUE_EXPR, TREE_TYPE (x), x);
 }
 
 /* Nonzero means lvalues are limited to those valid in pedantic ANSI C.
@@ -2104,8 +2108,8 @@ pedantic_non_lvalue_loc (location_t loc, tree x)
 {
   if (pedantic_lvalues)
     return non_lvalue_loc (loc, x);
-  protected_set_expr_location (x, loc);
-  return x;
+
+  return protected_set_expr_location_unshare (x, loc);
 }
 \f
 /* Given a tree comparison code, return the code that is the logical inverse
@@ -2587,20 +2591,22 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
       switch (TREE_CODE (arg0))
        {
        case INDIRECT_REF:
-       case MISALIGNED_INDIRECT_REF:
        case REALPART_EXPR:
        case IMAGPART_EXPR:
          return OP_SAME (0);
 
        case MEM_REF:
-         /* Require equal access sizes.  We can have incomplete types
-            for array references of variable-sized arrays from the
-            Fortran frontent though.  */
+         /* Require equal access sizes, and similar pointer types.
+            We can have incomplete types for array references of
+            variable-sized arrays from the Fortran frontent
+            though.  */
          return ((TYPE_SIZE (TREE_TYPE (arg0)) == TYPE_SIZE (TREE_TYPE (arg1))
                   || (TYPE_SIZE (TREE_TYPE (arg0))
                       && TYPE_SIZE (TREE_TYPE (arg1))
                       && operand_equal_p (TYPE_SIZE (TREE_TYPE (arg0)),
                                           TYPE_SIZE (TREE_TYPE (arg1)), flags)))
+                 && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg0, 1)))
+                     == TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg1, 1))))
                  && OP_SAME (0) && OP_SAME (1));
 
        case ARRAY_REF:
@@ -2640,6 +2646,14 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
        case TRUTH_ORIF_EXPR:
          return OP_SAME (0) && OP_SAME (1);
 
+       case FMA_EXPR:
+       case WIDEN_MULT_PLUS_EXPR:
+       case WIDEN_MULT_MINUS_EXPR:
+         if (!OP_SAME (2))
+           return 0;
+         /* The multiplcation operands are commutative.  */
+         /* FALLTHRU */
+
        case TRUTH_AND_EXPR:
        case TRUTH_OR_EXPR:
        case TRUTH_XOR_EXPR:
@@ -2653,6 +2667,8 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
                                      TREE_OPERAND (arg1, 0), flags));
 
        case COND_EXPR:
+       case VEC_COND_EXPR:
+       case DOT_PROD_EXPR:
          return OP_SAME (0) && OP_SAME (1) && OP_SAME (2);
 
        default:
@@ -2967,22 +2983,14 @@ omit_one_operand_loc (location_t loc, tree type, tree result, tree omitted)
   /* If the resulting operand is an empty statement, just return the omitted
      statement casted to void. */
   if (IS_EMPTY_STMT (t) && TREE_SIDE_EFFECTS (omitted))
-    {
-      t = build1 (NOP_EXPR, void_type_node, fold_ignored_result (omitted));
-      goto omit_one_operand_exit;
-    }
+    return build1_loc (loc, NOP_EXPR, void_type_node,
+                      fold_ignored_result (omitted));
 
   if (TREE_SIDE_EFFECTS (omitted))
-    {
-      t = build2 (COMPOUND_EXPR, type, fold_ignored_result (omitted), t);
-      goto omit_one_operand_exit;
-    }
+    return build2_loc (loc, COMPOUND_EXPR, type,
+                      fold_ignored_result (omitted), t);
 
   return non_lvalue_loc (loc, t);
-
- omit_one_operand_exit:
-  protected_set_expr_location (t, loc);
-  return t;
 }
 
 /* Similar, but call pedantic_non_lvalue instead of non_lvalue.  */
@@ -2996,22 +3004,14 @@ pedantic_omit_one_operand_loc (location_t loc, tree type, tree result,
   /* If the resulting operand is an empty statement, just return the omitted
      statement casted to void. */
   if (IS_EMPTY_STMT (t) && TREE_SIDE_EFFECTS (omitted))
-    {
-      t = build1 (NOP_EXPR, void_type_node, fold_ignored_result (omitted));
-      goto pedantic_omit_one_operand_exit;
-    }
+    return build1_loc (loc, NOP_EXPR, void_type_node,
+                      fold_ignored_result (omitted));
 
   if (TREE_SIDE_EFFECTS (omitted))
-    {
-      t = build2 (COMPOUND_EXPR, type, fold_ignored_result (omitted), t);
-      goto pedantic_omit_one_operand_exit;
-    }
+    return build2_loc (loc, COMPOUND_EXPR, type,
+                      fold_ignored_result (omitted), t);
 
   return pedantic_non_lvalue_loc (loc, t);
-
- pedantic_omit_one_operand_exit:
-  protected_set_expr_location (t, loc);
-  return t;
 }
 
 /* Return a tree for the case when the result of an expression is RESULT
@@ -3025,20 +3025,14 @@ pedantic_omit_one_operand_loc (location_t loc, tree type, tree result,
 
 tree
 omit_two_operands_loc (location_t loc, tree type, tree result,
-                  tree omitted1, tree omitted2)
+                      tree omitted1, tree omitted2)
 {
   tree t = fold_convert_loc (loc, type, result);
 
   if (TREE_SIDE_EFFECTS (omitted2))
-    {
-      t = build2 (COMPOUND_EXPR, type, omitted2, t);
-      SET_EXPR_LOCATION (t, loc);
-    }
+    t = build2_loc (loc, COMPOUND_EXPR, type, omitted2, t);
   if (TREE_SIDE_EFFECTS (omitted1))
-    {
-      t = build2 (COMPOUND_EXPR, type, omitted1, t);
-      SET_EXPR_LOCATION (t, loc);
-    }
+    t = build2_loc (loc, COMPOUND_EXPR, type, omitted1, t);
 
   return TREE_CODE (t) != COMPOUND_EXPR ? non_lvalue_loc (loc, t) : t;
 }
@@ -3054,7 +3048,7 @@ omit_two_operands_loc (location_t loc, tree type, tree result,
 tree
 fold_truth_not_expr (location_t loc, tree arg)
 {
-  tree t, type = TREE_TYPE (arg);
+  tree type = TREE_TYPE (arg);
   enum tree_code code = TREE_CODE (arg);
   location_t loc1, loc2;
 
@@ -3075,9 +3069,8 @@ fold_truth_not_expr (location_t loc, tree arg)
       if (code == ERROR_MARK)
        return NULL_TREE;
 
-      t = build2 (code, type, TREE_OPERAND (arg, 0), TREE_OPERAND (arg, 1));
-      SET_EXPR_LOCATION (t, loc);
-      return t;
+      return build2_loc (loc, code, type, TREE_OPERAND (arg, 0),
+                        TREE_OPERAND (arg, 1));
     }
 
   switch (code)
@@ -3092,10 +3085,9 @@ fold_truth_not_expr (location_t loc, tree arg)
        loc1 = loc;
       if (loc2 == UNKNOWN_LOCATION)
        loc2 = loc;
-      t = build2 (TRUTH_OR_EXPR, type,
-                 invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
-                 invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
-      break;
+      return build2_loc (loc, TRUTH_OR_EXPR, type,
+                        invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
+                        invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
 
     case TRUTH_OR_EXPR:
       loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 0));
@@ -3104,10 +3096,9 @@ fold_truth_not_expr (location_t loc, tree arg)
        loc1 = loc;
       if (loc2 == UNKNOWN_LOCATION)
        loc2 = loc;
-      t = build2 (TRUTH_AND_EXPR, type,
-                 invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
-                 invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
-      break;
+      return build2_loc (loc, TRUTH_AND_EXPR, type,
+                        invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
+                        invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
 
     case TRUTH_XOR_EXPR:
       /* Here we can invert either operand.  We invert the first operand
@@ -3116,13 +3107,12 @@ fold_truth_not_expr (location_t loc, tree arg)
         negation of the second operand.  */
 
       if (TREE_CODE (TREE_OPERAND (arg, 1)) == TRUTH_NOT_EXPR)
-       t = build2 (TRUTH_XOR_EXPR, type, TREE_OPERAND (arg, 0),
-                   TREE_OPERAND (TREE_OPERAND (arg, 1), 0));
+       return build2_loc (loc, TRUTH_XOR_EXPR, type, TREE_OPERAND (arg, 0),
+                          TREE_OPERAND (TREE_OPERAND (arg, 1), 0));
       else
-       t = build2 (TRUTH_XOR_EXPR, type,
-                   invert_truthvalue_loc (loc, TREE_OPERAND (arg, 0)),
-                   TREE_OPERAND (arg, 1));
-      break;
+       return build2_loc (loc, TRUTH_XOR_EXPR, type,
+                          invert_truthvalue_loc (loc, TREE_OPERAND (arg, 0)),
+                          TREE_OPERAND (arg, 1));
 
     case TRUTH_ANDIF_EXPR:
       loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 0));
@@ -3131,10 +3121,9 @@ fold_truth_not_expr (location_t loc, tree arg)
        loc1 = loc;
       if (loc2 == UNKNOWN_LOCATION)
        loc2 = loc;
-      t = build2 (TRUTH_ORIF_EXPR, type,
-                 invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
-                 invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
-      break;
+      return build2_loc (loc, TRUTH_ORIF_EXPR, type,
+                        invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
+                        invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
 
     case TRUTH_ORIF_EXPR:
       loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 0));
@@ -3143,10 +3132,9 @@ fold_truth_not_expr (location_t loc, tree arg)
        loc1 = loc;
       if (loc2 == UNKNOWN_LOCATION)
        loc2 = loc;
-      t = build2 (TRUTH_ANDIF_EXPR, type,
-                 invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
-                 invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
-      break;
+      return build2_loc (loc, TRUTH_ANDIF_EXPR, type,
+                        invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
+                        invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
 
     case TRUTH_NOT_EXPR:
       return TREE_OPERAND (arg, 0);
@@ -3166,22 +3154,20 @@ fold_truth_not_expr (location_t loc, tree arg)
        /* A COND_EXPR may have a throw as one operand, which
           then has void type.  Just leave void operands
           as they are.  */
-       t = build3 (COND_EXPR, type, TREE_OPERAND (arg, 0),
-                   VOID_TYPE_P (TREE_TYPE (arg1))
-                   ? arg1 : invert_truthvalue_loc (loc1, arg1),
-                   VOID_TYPE_P (TREE_TYPE (arg2))
-                   ? arg2 : invert_truthvalue_loc (loc2, arg2));
-       break;
+       return build3_loc (loc, COND_EXPR, type, TREE_OPERAND (arg, 0),
+                          VOID_TYPE_P (TREE_TYPE (arg1))
+                          ? arg1 : invert_truthvalue_loc (loc1, arg1),
+                          VOID_TYPE_P (TREE_TYPE (arg2))
+                          ? arg2 : invert_truthvalue_loc (loc2, arg2));
       }
 
     case COMPOUND_EXPR:
       loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 1));
       if (loc1 == UNKNOWN_LOCATION)
        loc1 = loc;
-      t = build2 (COMPOUND_EXPR, type,
-                 TREE_OPERAND (arg, 0),
-                 invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 1)));
-      break;
+      return build2_loc (loc, COMPOUND_EXPR, type,
+                        TREE_OPERAND (arg, 0),
+                        invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 1)));
 
     case NON_LVALUE_EXPR:
       loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 0));
@@ -3191,10 +3177,7 @@ fold_truth_not_expr (location_t loc, tree arg)
 
     CASE_CONVERT:
       if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
-       {
-         t = build1 (TRUTH_NOT_EXPR, type, arg);
-         break;
-       }
+       return build1_loc (loc, TRUTH_NOT_EXPR, type, arg);
 
       /* ... fall through ...  */
 
@@ -3202,37 +3185,27 @@ fold_truth_not_expr (location_t loc, tree arg)
       loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 0));
       if (loc1 == UNKNOWN_LOCATION)
        loc1 = loc;
-      t = build1 (TREE_CODE (arg), type,
-                 invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)));
-      break;
+      return build1_loc (loc, TREE_CODE (arg), type,
+                        invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)));
 
     case BIT_AND_EXPR:
       if (!integer_onep (TREE_OPERAND (arg, 1)))
        return NULL_TREE;
-      t = build2 (EQ_EXPR, type, arg, build_int_cst (type, 0));
-      break;
+      return build2_loc (loc, EQ_EXPR, type, arg, build_int_cst (type, 0));
 
     case SAVE_EXPR:
-      t = build1 (TRUTH_NOT_EXPR, type, arg);
-      break;
+      return build1_loc (loc, TRUTH_NOT_EXPR, type, arg);
 
     case CLEANUP_POINT_EXPR:
       loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 0));
       if (loc1 == UNKNOWN_LOCATION)
        loc1 = loc;
-      t = build1 (CLEANUP_POINT_EXPR, type,
-                 invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)));
-      break;
+      return build1_loc (loc, CLEANUP_POINT_EXPR, type,
+                        invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)));
 
     default:
-      t = NULL_TREE;
-      break;
+      return NULL_TREE;
     }
-
-  if (t)
-    SET_EXPR_LOCATION (t, loc);
-
-  return t;
 }
 
 /* Return a simplified tree node for the truth-negation of ARG.  This
@@ -3252,10 +3225,7 @@ invert_truthvalue_loc (location_t loc, tree arg)
 
   tem = fold_truth_not_expr (loc, arg);
   if (!tem)
-    {
-      tem = build1 (TRUTH_NOT_EXPR, TREE_TYPE (arg), arg);
-      SET_EXPR_LOCATION (tem, loc);
-    }
+    tem = build1_loc (loc, TRUTH_NOT_EXPR, TREE_TYPE (arg), arg);
 
   return tem;
 }
@@ -3381,9 +3351,8 @@ make_bit_field_ref (location_t loc, tree inner, tree type,
       || TYPE_UNSIGNED (bftype) == !unsignedp)
     bftype = build_nonstandard_integer_type (bitsize, 0);
 
-  result = build3 (BIT_FIELD_REF, bftype, inner,
-                  size_int (bitsize), bitsize_int (bitpos));
-  SET_EXPR_LOCATION (result, loc);
+  result = build3_loc (loc, BIT_FIELD_REF, bftype, inner,
+                      size_int (bitsize), bitsize_int (bitpos));
 
   if (bftype != type)
     result = fold_convert_loc (loc, type, result);
@@ -3562,10 +3531,8 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
                                  size_int (lbitpos)),
                     mask);
 
-  lhs = build2 (code, compare_type,
-               build2 (BIT_AND_EXPR, unsigned_type, lhs, mask),
-               rhs);
-  SET_EXPR_LOCATION (lhs, loc);
+  lhs = build2_loc (loc, code, compare_type,
+                   build2 (BIT_AND_EXPR, unsigned_type, lhs, mask), rhs);
   return lhs;
 }
 \f
@@ -3991,9 +3958,8 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh,
 
        case BIT_NOT_EXPR:
          /* ~ X -> -X - 1  */
-         exp = build2 (MINUS_EXPR, exp_type, negate_expr (arg0),
-                       build_int_cst (exp_type, 1));
-         SET_EXPR_LOCATION (exp, loc);
+         exp = build2_loc (loc, MINUS_EXPR, exp_type, negate_expr (arg0),
+                           build_int_cst (exp_type, 1));
          continue;
 
        case PLUS_EXPR:  case MINUS_EXPR:
@@ -4911,13 +4877,9 @@ fold_range_test (location_t loc, enum tree_code code, tree type,
         unless we are at top level or LHS contains a PLACEHOLDER_EXPR, in
         which cases we can't do this.  */
       if (simple_operand_p (lhs))
-       {
-         tem = build2 (code == TRUTH_ANDIF_EXPR
-                       ? TRUTH_AND_EXPR : TRUTH_OR_EXPR,
-                       type, op0, op1);
-         SET_EXPR_LOCATION (tem, loc);
-         return tem;
-       }
+       return build2_loc (loc, code == TRUTH_ANDIF_EXPR
+                          ? TRUTH_AND_EXPR : TRUTH_OR_EXPR,
+                          type, op0, op1);
 
       else if (lang_hooks.decls.global_bindings_p () == 0
               && ! CONTAINS_PLACEHOLDER_P (lhs))
@@ -4934,11 +4896,9 @@ fold_range_test (location_t loc, enum tree_code code, tree type,
              if (strict_overflow_p)
                fold_overflow_warning (warnmsg,
                                       WARN_STRICT_OVERFLOW_COMPARISON);
-             tem = build2 (code == TRUTH_ANDIF_EXPR
-                           ? TRUTH_AND_EXPR : TRUTH_OR_EXPR,
-                           type, lhs, rhs);
-             SET_EXPR_LOCATION (tem, loc);
-             return tem;
+             return build2_loc (loc, code == TRUTH_ANDIF_EXPR
+                                ? TRUTH_AND_EXPR : TRUTH_OR_EXPR,
+                                type, lhs, rhs);
            }
        }
     }
@@ -5152,7 +5112,6 @@ fold_truthop (location_t loc, enum tree_code code, tree truth_type,
   if (simple_operand_p (ll_arg)
       && simple_operand_p (lr_arg))
     {
-      tree result;
       if (operand_equal_p (ll_arg, rl_arg, 0)
           && operand_equal_p (lr_arg, rr_arg, 0))
        {
@@ -5193,13 +5152,10 @@ fold_truthop (location_t loc, enum tree_code code, tree truth_type,
          && rcode == NE_EXPR && integer_zerop (rr_arg)
          && TREE_TYPE (ll_arg) == TREE_TYPE (rl_arg)
          && INTEGRAL_TYPE_P (TREE_TYPE (ll_arg)))
-       {
-         result = build2 (NE_EXPR, truth_type,
+       return build2_loc (loc, NE_EXPR, truth_type,
                           build2 (BIT_IOR_EXPR, TREE_TYPE (ll_arg),
                                   ll_arg, rl_arg),
                           build_int_cst (TREE_TYPE (ll_arg), 0));
-         goto fold_truthop_exit;
-       }
 
       /* Convert (a == 0) && (b == 0) into (a | b) == 0.  */
       if (code == TRUTH_AND_EXPR
@@ -5207,21 +5163,15 @@ fold_truthop (location_t loc, enum tree_code code, tree truth_type,
          && rcode == EQ_EXPR && integer_zerop (rr_arg)
          && TREE_TYPE (ll_arg) == TREE_TYPE (rl_arg)
          && INTEGRAL_TYPE_P (TREE_TYPE (ll_arg)))
-       {
-         result = build2 (EQ_EXPR, truth_type,
+       return build2_loc (loc, EQ_EXPR, truth_type,
                           build2 (BIT_IOR_EXPR, TREE_TYPE (ll_arg),
                                   ll_arg, rl_arg),
                           build_int_cst (TREE_TYPE (ll_arg), 0));
-         goto fold_truthop_exit;
-       }
 
       if (LOGICAL_OP_NON_SHORT_CIRCUIT)
        {
          if (code != orig_code || lhs != orig_lhs || rhs != orig_rhs)
-           {
-             result = build2 (code, truth_type, lhs, rhs);
-             goto fold_truthop_exit;
-           }
+           return build2_loc (loc, code, truth_type, lhs, rhs);
          return NULL_TREE;
        }
     }
@@ -5412,8 +5362,7 @@ fold_truthop (location_t loc, enum tree_code code, tree truth_type,
          if (! all_ones_mask_p (lr_mask, rnbitsize))
            rhs = build2 (BIT_AND_EXPR, rntype, rhs, lr_mask);
 
-         result = build2 (wanted_code, truth_type, lhs, rhs);
-         goto fold_truthop_exit;
+         return build2_loc (loc, wanted_code, truth_type, lhs, rhs);
        }
 
       /* There is still another way we can do something:  If both pairs of
@@ -5466,8 +5415,7 @@ fold_truthop (location_t loc, enum tree_code code, tree truth_type,
          if (! all_ones_mask_p (lr_mask, lr_bitsize + rr_bitsize))
            rhs = build2 (BIT_AND_EXPR, type, rhs, lr_mask);
 
-         result = build2 (wanted_code, truth_type, lhs, rhs);
-         goto fold_truthop_exit;
+         return build2_loc (loc, wanted_code, truth_type, lhs, rhs);
        }
 
       return 0;
@@ -5503,17 +5451,10 @@ fold_truthop (location_t loc, enum tree_code code, tree truth_type,
 
   ll_mask = const_binop (BIT_IOR_EXPR, ll_mask, rl_mask);
   if (! all_ones_mask_p (ll_mask, lnbitsize))
-    {
-      result = build2 (BIT_AND_EXPR, lntype, result, ll_mask);
-      SET_EXPR_LOCATION (result, loc);
-    }
-
-  result = build2 (wanted_code, truth_type, result,
-                  const_binop (BIT_IOR_EXPR, l_const, r_const));
+    result = build2_loc (loc, BIT_AND_EXPR, lntype, result, ll_mask);
 
- fold_truthop_exit:
-  SET_EXPR_LOCATION (result, loc);
-  return result;
+  return build2_loc (loc, wanted_code, truth_type, result,
+                    const_binop (BIT_IOR_EXPR, l_const, r_const));
 }
 \f
 /* Optimize T, which is a comparison of a MIN_EXPR or MAX_EXPR with a
@@ -7597,16 +7538,12 @@ build_fold_addr_expr_with_type_loc (location_t loc, tree t, tree ptrtype)
   if (TREE_CODE (t) == WITH_SIZE_EXPR)
     t = TREE_OPERAND (t, 0);
 
-  if (TREE_CODE (t) == INDIRECT_REF
-      || TREE_CODE (t) == MISALIGNED_INDIRECT_REF)
+  if (TREE_CODE (t) == INDIRECT_REF)
     {
       t = TREE_OPERAND (t, 0);
 
       if (TREE_TYPE (t) != ptrtype)
-       {
-         t = build1 (NOP_EXPR, ptrtype, t);
-         SET_EXPR_LOCATION (t, loc);
-       }
+       t = build1_loc (loc, NOP_EXPR, ptrtype, t);
     }
   else if (TREE_CODE (t) == MEM_REF
       && integer_zerop (TREE_OPERAND (t, 1)))
@@ -7619,10 +7556,7 @@ build_fold_addr_expr_with_type_loc (location_t loc, tree t, tree ptrtype)
        t = fold_convert_loc (loc, ptrtype, t);
     }
   else
-    {
-      t = build1 (ADDR_EXPR, ptrtype, t);
-      SET_EXPR_LOCATION (t, loc);
-    }
+    t = build1_loc (loc, ADDR_EXPR, ptrtype, t);
 
   return t;
 }
@@ -7723,16 +7657,14 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
                         (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
-                                              (TREE_OPERAND (tem, 1), 0)),
-                                   TREE_OPERAND (tem, 0),
-                                   TREE_OPERAND (TREE_OPERAND (tem, 1), 0),
-                                   TREE_OPERAND (TREE_OPERAND (tem, 2), 0)));
-             SET_EXPR_LOCATION (tem, loc);
-           }
+           tem = build1_loc (loc, code, type,
+                             build3 (COND_EXPR,
+                                     TREE_TYPE (TREE_OPERAND
+                                                (TREE_OPERAND (tem, 1), 0)),
+                                     TREE_OPERAND (tem, 0),
+                                     TREE_OPERAND (TREE_OPERAND (tem, 1), 0),
+                                     TREE_OPERAND (TREE_OPERAND (tem, 2),
+                                                   0)));
          return tem;
        }
       else if (COMPARISON_CLASS_P (arg0))
@@ -7895,10 +7827,9 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
             unless assigning a bitfield.  */
          tem = fold_build1_loc (loc, code, type, TREE_OPERAND (op0, 1));
          /* First do the assignment, then return converted constant.  */
-         tem = build2 (COMPOUND_EXPR, TREE_TYPE (tem), op0, tem);
+         tem = build2_loc (loc, COMPOUND_EXPR, TREE_TYPE (tem), op0, tem);
          TREE_NO_WARNING (tem) = 1;
          TREE_USED (tem) = 1;
-         SET_EXPR_LOCATION (tem, loc);
          return tem;
        }
 
@@ -8234,7 +8165,7 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
 
     case IMAGPART_EXPR:
       if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
-       return fold_convert_loc (loc, type, integer_zero_node);
+       return build_zero_cst (type);
       if (TREE_CODE (arg0) == COMPLEX_EXPR)
        return omit_one_operand_loc (loc, type, TREE_OPERAND (arg0, 1),
                                 TREE_OPERAND (arg0, 0));
@@ -9289,7 +9220,7 @@ fold_mult_zconjz (location_t loc, tree type, tree expr)
                     fold_build2_loc (loc, MULT_EXPR, itype, rpart, rpart),
                     fold_build2_loc (loc, MULT_EXPR, itype, ipart, ipart));
   return fold_build2_loc (loc, COMPLEX_EXPR, type, tem,
-                     fold_convert_loc (loc, itype, integer_zero_node));
+                         build_zero_cst (itype));
 }
 
 
@@ -9520,8 +9451,8 @@ fold_binary_loc (location_t loc,
          tem = fold_build2_loc (loc, code, type,
                             fold_convert_loc (loc, TREE_TYPE (op0),
                                               TREE_OPERAND (arg0, 1)), op1);
-         tem = build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0), tem);
-         goto fold_binary_exit;
+         return build2_loc (loc, COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
+                            tem);
        }
       if (TREE_CODE (arg1) == COMPOUND_EXPR
          && reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
@@ -9529,8 +9460,8 @@ fold_binary_loc (location_t loc,
          tem = fold_build2_loc (loc, code, type, op0,
                             fold_convert_loc (loc, TREE_TYPE (op1),
                                               TREE_OPERAND (arg1, 1)));
-         tem = build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0), tem);
-         goto fold_binary_exit;
+         return build2_loc (loc, COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
+                            tem);
        }
 
       if (TREE_CODE (arg0) == COND_EXPR || COMPARISON_CLASS_P (arg0))
@@ -9929,12 +9860,10 @@ fold_binary_loc (location_t loc,
                && ((TREE_INT_CST_LOW (tree01) + TREE_INT_CST_LOW (tree11))
                    == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))))
              {
-               tem = build2 (LROTATE_EXPR,
-                             TREE_TYPE (TREE_OPERAND (arg0, 0)),
-                             TREE_OPERAND (arg0, 0),
-                             code0 == LSHIFT_EXPR
-                             ? tree01 : tree11);
-               SET_EXPR_LOCATION (tem, loc);
+               tem = build2_loc (loc, LROTATE_EXPR,
+                                 TREE_TYPE (TREE_OPERAND (arg0, 0)),
+                                 TREE_OPERAND (arg0, 0),
+                                 code0 == LSHIFT_EXPR ? tree01 : tree11);
                return fold_convert_loc (loc, type, tem);
              }
            else if (code11 == MINUS_EXPR)
@@ -10281,7 +10210,7 @@ fold_binary_loc (location_t loc,
 
       if ((!FLOAT_TYPE_P (type) || !HONOR_NANS (TYPE_MODE (type)))
          && operand_equal_p (arg0, arg1, 0))
-       return fold_convert_loc (loc, type, integer_zero_node);
+       return build_zero_cst (type);
 
       /* A - B -> A + (-B) if B is easily negatable.  */
       if (negate_expr_p (arg1)
@@ -10668,7 +10597,7 @@ fold_binary_loc (location_t loc,
       if (TREE_CODE (arg0) == BIT_NOT_EXPR
          && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
        {
-         t1 = fold_convert_loc (loc, type, integer_zero_node);
+         t1 = build_zero_cst (type);
          t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
          return omit_one_operand_loc (loc, type, t1, arg1);
        }
@@ -10677,7 +10606,7 @@ fold_binary_loc (location_t loc,
       if (TREE_CODE (arg1) == BIT_NOT_EXPR
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
        {
-         t1 = fold_convert_loc (loc, type, integer_zero_node);
+         t1 = build_zero_cst (type);
          t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
          return omit_one_operand_loc (loc, type, t1, arg0);
        }
@@ -10807,7 +10736,7 @@ fold_binary_loc (location_t loc,
       if (TREE_CODE (arg0) == BIT_NOT_EXPR
          && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
        {
-         t1 = fold_convert_loc (loc, type, integer_zero_node);
+         t1 = build_zero_cst (type);
          t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
          return omit_one_operand_loc (loc, type, t1, arg1);
        }
@@ -10816,7 +10745,7 @@ fold_binary_loc (location_t loc,
       if (TREE_CODE (arg1) == BIT_NOT_EXPR
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
        {
-         t1 = fold_convert_loc (loc, type, integer_zero_node);
+         t1 = build_zero_cst (type);
          t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
          return omit_one_operand_loc (loc, type, t1, arg0);
        }
@@ -11071,6 +11000,126 @@ fold_binary_loc (location_t loc,
                              fold_convert_loc (loc, type, arg0));
        }
 
+      /* For constants M and N, if M == (1LL << cst) - 1 && (N & M) == M,
+        ((A & N) + B) & M -> (A + B) & M
+        Similarly if (N & M) == 0,
+        ((A | N) + B) & M -> (A + B) & M
+        and for - instead of + (or unary - instead of +)
+        and/or ^ instead of |.
+        If B is constant and (B & M) == 0, fold into A & M.  */
+      if (host_integerp (arg1, 1))
+       {
+         unsigned HOST_WIDE_INT cst1 = tree_low_cst (arg1, 1);
+         if (~cst1 && (cst1 & (cst1 + 1)) == 0
+             && INTEGRAL_TYPE_P (TREE_TYPE (arg0))
+             && (TREE_CODE (arg0) == PLUS_EXPR
+                 || TREE_CODE (arg0) == MINUS_EXPR
+                 || TREE_CODE (arg0) == NEGATE_EXPR)
+             && (TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg0))
+                 || TREE_CODE (TREE_TYPE (arg0)) == INTEGER_TYPE))
+           {
+             tree pmop[2];
+             int which = 0;
+             unsigned HOST_WIDE_INT cst0;
+
+             /* Now we know that arg0 is (C + D) or (C - D) or
+                -C and arg1 (M) is == (1LL << cst) - 1.
+                Store C into PMOP[0] and D into PMOP[1].  */
+             pmop[0] = TREE_OPERAND (arg0, 0);
+             pmop[1] = NULL;
+             if (TREE_CODE (arg0) != NEGATE_EXPR)
+               {
+                 pmop[1] = TREE_OPERAND (arg0, 1);
+                 which = 1;
+               }
+
+             if (!host_integerp (TYPE_MAX_VALUE (TREE_TYPE (arg0)), 1)
+                 || (tree_low_cst (TYPE_MAX_VALUE (TREE_TYPE (arg0)), 1)
+                     & cst1) != cst1)
+               which = -1;
+
+             for (; which >= 0; which--)
+               switch (TREE_CODE (pmop[which]))
+                 {
+                 case BIT_AND_EXPR:
+                 case BIT_IOR_EXPR:
+                 case BIT_XOR_EXPR:
+                   if (TREE_CODE (TREE_OPERAND (pmop[which], 1))
+                       != INTEGER_CST)
+                     break;
+                   /* tree_low_cst not used, because we don't care about
+                      the upper bits.  */
+                   cst0 = TREE_INT_CST_LOW (TREE_OPERAND (pmop[which], 1));
+                   cst0 &= cst1;
+                   if (TREE_CODE (pmop[which]) == BIT_AND_EXPR)
+                     {
+                       if (cst0 != cst1)
+                         break;
+                     }
+                   else if (cst0 != 0)
+                     break;
+                   /* If C or D is of the form (A & N) where
+                      (N & M) == M, or of the form (A | N) or
+                      (A ^ N) where (N & M) == 0, replace it with A.  */
+                   pmop[which] = TREE_OPERAND (pmop[which], 0);
+                   break;
+                 case INTEGER_CST:
+                   /* If C or D is a N where (N & M) == 0, it can be
+                      omitted (assumed 0).  */
+                   if ((TREE_CODE (arg0) == PLUS_EXPR
+                        || (TREE_CODE (arg0) == MINUS_EXPR && which == 0))
+                       && (TREE_INT_CST_LOW (pmop[which]) & cst1) == 0)
+                     pmop[which] = NULL;
+                   break;
+                 default:
+                   break;
+                 }
+
+             /* Only build anything new if we optimized one or both arguments
+                above.  */
+             if (pmop[0] != TREE_OPERAND (arg0, 0)
+                 || (TREE_CODE (arg0) != NEGATE_EXPR
+                     && pmop[1] != TREE_OPERAND (arg0, 1)))
+               {
+                 tree utype = TREE_TYPE (arg0);
+                 if (! TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg0)))
+                   {
+                     /* Perform the operations in a type that has defined
+                        overflow behavior.  */
+                     utype = unsigned_type_for (TREE_TYPE (arg0));
+                     if (pmop[0] != NULL)
+                       pmop[0] = fold_convert_loc (loc, utype, pmop[0]);
+                     if (pmop[1] != NULL)
+                       pmop[1] = fold_convert_loc (loc, utype, pmop[1]);
+                   }
+
+                 if (TREE_CODE (arg0) == NEGATE_EXPR)
+                   tem = fold_build1_loc (loc, NEGATE_EXPR, utype, pmop[0]);
+                 else if (TREE_CODE (arg0) == PLUS_EXPR)
+                   {
+                     if (pmop[0] != NULL && pmop[1] != NULL)
+                       tem = fold_build2_loc (loc, PLUS_EXPR, utype,
+                                              pmop[0], pmop[1]);
+                     else if (pmop[0] != NULL)
+                       tem = pmop[0];
+                     else if (pmop[1] != NULL)
+                       tem = pmop[1];
+                     else
+                       return build_int_cst (type, 0);
+                   }
+                 else if (pmop[0] == NULL)
+                   tem = fold_build1_loc (loc, NEGATE_EXPR, utype, pmop[1]);
+                 else
+                   tem = fold_build2_loc (loc, MINUS_EXPR, utype,
+                                          pmop[0], pmop[1]);
+                 /* TEM is now the new binary +, - or unary - replacement.  */
+                 tem = fold_build2_loc (loc, BIT_AND_EXPR, utype, tem,
+                                        fold_convert_loc (loc, utype, arg1));
+                 return fold_convert_loc (loc, type, tem);
+               }
+           }
+       }
+
       t1 = distribute_bit_expr (loc, code, type, arg0, arg1);
       if (t1 != NULL_TREE)
        return t1;
@@ -11479,6 +11528,31 @@ fold_binary_loc (location_t loc,
       return NULL_TREE;
 
     case TRUNC_DIV_EXPR:
+      /* Optimize (X & (-A)) / A where A is a power of 2,
+        to X >> log2(A) */
+      if (TREE_CODE (arg0) == BIT_AND_EXPR
+         && !TYPE_UNSIGNED (type) && TREE_CODE (arg1) == INTEGER_CST
+         && integer_pow2p (arg1) && tree_int_cst_sgn (arg1) > 0)
+       {
+         tree sum = fold_binary_loc (loc, PLUS_EXPR, TREE_TYPE (arg1),
+                                     arg1, TREE_OPERAND (arg0, 1));
+         if (sum && integer_zerop (sum)) {
+           unsigned long pow2;
+
+           if (TREE_INT_CST_LOW (arg1))
+             pow2 = exact_log2 (TREE_INT_CST_LOW (arg1));
+           else
+             pow2 = exact_log2 (TREE_INT_CST_HIGH (arg1))
+                     + HOST_BITS_PER_WIDE_INT;
+
+           return fold_build2_loc (loc, RSHIFT_EXPR, type,
+                         TREE_OPERAND (arg0, 0),
+                         build_int_cst (NULL_TREE, pow2));
+         }
+       }
+
+      /* Fall thru */
+      
     case FLOOR_DIV_EXPR:
       /* Simplify A / (B << N) where A and B are positive and B is
         a power of 2, to A >> (N + log2(B)).  */
@@ -11491,7 +11565,13 @@ fold_binary_loc (location_t loc,
          if (integer_pow2p (sval) && tree_int_cst_sgn (sval) > 0)
            {
              tree sh_cnt = TREE_OPERAND (arg1, 1);
-             unsigned long pow2 = exact_log2 (TREE_INT_CST_LOW (sval));
+             unsigned long pow2;
+
+             if (TREE_INT_CST_LOW (sval))
+               pow2 = exact_log2 (TREE_INT_CST_LOW (sval));
+             else
+               pow2 = exact_log2 (TREE_INT_CST_HIGH (sval))
+                      + HOST_BITS_PER_WIDE_INT;
 
              if (strict_overflow_p)
                fold_overflow_warning (("assuming signed overflow does not "
@@ -12978,13 +13058,10 @@ fold_binary_loc (location_t loc,
          && TYPE_UNSIGNED (TREE_TYPE (arg0))
          && TREE_CODE (arg1) == LSHIFT_EXPR
          && integer_onep (TREE_OPERAND (arg1, 0)))
-       {
-         tem = build2 (code == LT_EXPR ? EQ_EXPR : NE_EXPR, type,
-                       build2 (RSHIFT_EXPR, TREE_TYPE (arg0), arg0,
-                               TREE_OPERAND (arg1, 1)),
-                       build_int_cst (TREE_TYPE (arg0), 0));
-         goto fold_binary_exit;
-       }
+       return build2_loc (loc, code == LT_EXPR ? EQ_EXPR : NE_EXPR, type,
+                          build2 (RSHIFT_EXPR, TREE_TYPE (arg0), arg0,
+                                  TREE_OPERAND (arg1, 1)),
+                          build_int_cst (TREE_TYPE (arg0), 0));
 
       if ((code == LT_EXPR || code == GE_EXPR)
          && TYPE_UNSIGNED (TREE_TYPE (arg0))
@@ -12992,14 +13069,11 @@ fold_binary_loc (location_t loc,
          && TREE_CODE (TREE_OPERAND (arg1, 0)) == LSHIFT_EXPR
          && integer_onep (TREE_OPERAND (TREE_OPERAND (arg1, 0), 0)))
        {
-         tem = build2 (code == LT_EXPR ? EQ_EXPR : NE_EXPR, type,
-                       fold_convert_loc (loc, TREE_TYPE (arg0),
-                                         build2 (RSHIFT_EXPR,
-                                                 TREE_TYPE (arg0), arg0,
-                                                 TREE_OPERAND (TREE_OPERAND (arg1, 0),
-                                                               1))),
-                       build_int_cst (TREE_TYPE (arg0), 0));
-         goto fold_binary_exit;
+         tem = build2 (RSHIFT_EXPR, TREE_TYPE (arg0), arg0,
+                       TREE_OPERAND (TREE_OPERAND (arg1, 0), 1));
+         return build2_loc (loc, code == LT_EXPR ? EQ_EXPR : NE_EXPR, type,
+                            fold_convert_loc (loc, TREE_TYPE (arg0), tem),
+                            build_int_cst (TREE_TYPE (arg0), 0));
        }
 
       return NULL_TREE;
@@ -13093,9 +13167,6 @@ fold_binary_loc (location_t loc,
     default:
       return NULL_TREE;
     } /* switch (code) */
- fold_binary_exit:
-  protected_set_expr_location (tem, loc);
-  return tem;
 }
 
 /* Callback for walk_tree, looking for LABEL_EXPR.  Return *TP if it is
@@ -13136,10 +13207,10 @@ contains_label_p (tree st)
 
 tree
 fold_ternary_loc (location_t loc, enum tree_code code, tree type,
-             tree op0, tree op1, tree op2)
+                 tree op0, tree op1, tree op2)
 {
   tree tem;
-  tree arg0 = NULL_TREE, arg1 = NULL_TREE;
+  tree arg0 = NULL_TREE, arg1 = NULL_TREE, arg2 = NULL_TREE;
   enum tree_code_class kind = TREE_CODE_CLASS (code);
 
   gcc_assert (IS_EXPR_CODE_CLASS (kind)
@@ -13167,6 +13238,12 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
       STRIP_NOPS (arg1);
     }
 
+  if (op2)
+    {
+      arg2 = op2;
+      STRIP_NOPS (arg2);
+    }
+
   switch (code)
     {
     case COMPONENT_REF:
@@ -13453,7 +13530,7 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
              if (elements)
                return TREE_VALUE (elements);
              else
-               return fold_convert_loc (loc, type, integer_zero_node);
+               return build_zero_cst (type);
            }
        }
 
@@ -13465,6 +13542,17 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
 
       return NULL_TREE;
 
+    case FMA_EXPR:
+      /* For integers we can decompose the FMA if possible.  */
+      if (TREE_CODE (arg0) == INTEGER_CST
+         && TREE_CODE (arg1) == INTEGER_CST)
+       return fold_build2_loc (loc, PLUS_EXPR, type,
+                               const_binop (MULT_EXPR, arg0, arg1), arg2);
+      if (integer_zerop (arg2))
+       return fold_build2_loc (loc, MULT_EXPR, type, arg0, arg1);
+
+      return fold_fma (loc, type, arg0, arg1, arg2);
+
     default:
       return NULL_TREE;
     } /* switch (code) */
@@ -13648,7 +13736,7 @@ fold_check_failed (const_tree expr ATTRIBUTE_UNUSED, const_tree ret ATTRIBUTE_UN
 static void
 fold_checksum_tree (const_tree expr, struct md5_ctx *ctx, htab_t ht)
 {
-  const void **slot;
+  void **slot;
   enum tree_code code;
   union tree_node buf;
   int i, len;
@@ -13660,10 +13748,10 @@ recursive_label:
              && sizeof (struct tree_type) <= sizeof (struct tree_function_decl));
   if (expr == NULL)
     return;
-  slot = (const void **) htab_find_slot (ht, expr, INSERT);
+  slot = (void **) htab_find_slot (ht, expr, INSERT);
   if (*slot != NULL)
     return;
-  *slot = expr;
+  *slot = CONST_CAST_TREE (expr);
   code = TREE_CODE (expr);
   if (TREE_CODE_CLASS (code) == tcc_declaration
       && DECL_ASSEMBLER_NAME_SET_P (expr))
@@ -13845,10 +13933,7 @@ fold_build1_stat_loc (location_t loc,
 
   tem = fold_unary_loc (loc, code, type, op0);
   if (!tem)
-    {
-      tem = build1_stat (code, type, op0 PASS_MEM_STAT);
-      SET_EXPR_LOCATION (tem, loc);
-    }
+    tem = build1_stat_loc (loc, code, type, op0 PASS_MEM_STAT);
 
 #ifdef ENABLE_FOLD_CHECKING
   md5_init_ctx (&ctx);
@@ -13896,10 +13981,7 @@ fold_build2_stat_loc (location_t loc,
 
   tem = fold_binary_loc (loc, code, type, op0, op1);
   if (!tem)
-    {
-      tem = build2_stat (code, type, op0, op1 PASS_MEM_STAT);
-      SET_EXPR_LOCATION (tem, loc);
-    }
+    tem = build2_stat_loc (loc, code, type, op0, op1 PASS_MEM_STAT);
 
 #ifdef ENABLE_FOLD_CHECKING
   md5_init_ctx (&ctx);
@@ -13961,10 +14043,7 @@ fold_build3_stat_loc (location_t loc, enum tree_code code, tree type,
   gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp);
   tem = fold_ternary_loc (loc, code, type, op0, op1, op2);
   if (!tem)
-    {
-      tem =  build3_stat (code, type, op0, op1, op2 PASS_MEM_STAT);
-      SET_EXPR_LOCATION (tem, loc);
-    }
+    tem = build3_stat_loc (loc, code, type, op0, op1, op2 PASS_MEM_STAT);
 
 #ifdef ENABLE_FOLD_CHECKING
   md5_init_ctx (&ctx);
@@ -15480,9 +15559,8 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0)
          tree min_val = size_zero_node;
          if (type_domain && TYPE_MIN_VALUE (type_domain))
            min_val = TYPE_MIN_VALUE (type_domain);
-         op0 = build4 (ARRAY_REF, type, op, min_val, NULL_TREE, NULL_TREE);
-         SET_EXPR_LOCATION (op0, loc);
-         return op0;
+         return build4_loc (loc, ARRAY_REF, type, op, min_val,
+                            NULL_TREE, NULL_TREE);
        }
       /* *(foo *)&complexfoo => __real__ complexfoo */
       else if (TREE_CODE (optype) == COMPLEX_TYPE
@@ -15498,53 +15576,57 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0)
        }
     }
 
-  /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */
   if (TREE_CODE (sub) == POINTER_PLUS_EXPR
       && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
     {
       tree op00 = TREE_OPERAND (sub, 0);
       tree op01 = TREE_OPERAND (sub, 1);
-      tree op00type;
 
       STRIP_NOPS (op00);
-      op00type = TREE_TYPE (op00);
-      if (TREE_CODE (op00) == ADDR_EXPR
-          && TREE_CODE (TREE_TYPE (op00type)) == VECTOR_TYPE
-          && type == TREE_TYPE (TREE_TYPE (op00type)))
+      if (TREE_CODE (op00) == ADDR_EXPR)
        {
-         HOST_WIDE_INT offset = tree_low_cst (op01, 0);
-         tree part_width = TYPE_SIZE (type);
-         unsigned HOST_WIDE_INT part_widthi = tree_low_cst (part_width, 0)/BITS_PER_UNIT;
-         unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
-         tree index = bitsize_int (indexi);
-
-         if (offset/part_widthi <= TYPE_VECTOR_SUBPARTS (TREE_TYPE (op00type)))
-           return fold_build3_loc (loc,
-                               BIT_FIELD_REF, type, TREE_OPERAND (op00, 0),
-                               part_width, index);
+         tree op00type;
+         op00 = TREE_OPERAND (op00, 0);
+         op00type = TREE_TYPE (op00);
 
-       }
-    }
+         /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */
+         if (TREE_CODE (op00type) == VECTOR_TYPE
+             && type == TREE_TYPE (op00type))
+           {
+             HOST_WIDE_INT offset = tree_low_cst (op01, 0);
+             tree part_width = TYPE_SIZE (type);
+             unsigned HOST_WIDE_INT part_widthi = tree_low_cst (part_width, 0)/BITS_PER_UNIT;
+             unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
+             tree index = bitsize_int (indexi);
 
+             if (offset/part_widthi <= TYPE_VECTOR_SUBPARTS (op00type))
+               return fold_build3_loc (loc,
+                                       BIT_FIELD_REF, type, op00,
+                                       part_width, index);
 
-  /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
-  if (TREE_CODE (sub) == POINTER_PLUS_EXPR
-      && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
-    {
-      tree op00 = TREE_OPERAND (sub, 0);
-      tree op01 = TREE_OPERAND (sub, 1);
-      tree op00type;
-
-      STRIP_NOPS (op00);
-      op00type = TREE_TYPE (op00);
-      if (TREE_CODE (op00) == ADDR_EXPR
-         && TREE_CODE (TREE_TYPE (op00type)) == COMPLEX_TYPE
-         && type == TREE_TYPE (TREE_TYPE (op00type)))
-       {
-         tree size = TYPE_SIZE_UNIT (type);
-         if (tree_int_cst_equal (size, op01))
-           return fold_build1_loc (loc, IMAGPART_EXPR, type,
-                               TREE_OPERAND (op00, 0));
+           }
+         /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
+         else if (TREE_CODE (op00type) == COMPLEX_TYPE
+                  && type == TREE_TYPE (op00type))
+           {
+             tree size = TYPE_SIZE_UNIT (type);
+             if (tree_int_cst_equal (size, op01))
+               return fold_build1_loc (loc, IMAGPART_EXPR, type, op00);
+           }
+         /* ((foo *)&fooarray)[1] => fooarray[1] */
+         else if (TREE_CODE (op00type) == ARRAY_TYPE
+                  && type == TREE_TYPE (op00type))
+           {
+             tree type_domain = TYPE_DOMAIN (op00type);
+             tree min_val = size_zero_node;
+             if (type_domain && TYPE_MIN_VALUE (type_domain))
+               min_val = TYPE_MIN_VALUE (type_domain);
+             op01 = size_binop_loc (loc, EXACT_DIV_EXPR, op01,
+                                    TYPE_SIZE_UNIT (type));
+             op01 = size_binop_loc (loc, PLUS_EXPR, op01, min_val);
+             return build4_loc (loc, ARRAY_REF, type, op00, op01,
+                                NULL_TREE, NULL_TREE);
+           }
        }
     }
 
@@ -15558,9 +15640,8 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0)
       type_domain = TYPE_DOMAIN (TREE_TYPE (sub));
       if (type_domain && TYPE_MIN_VALUE (type_domain))
        min_val = TYPE_MIN_VALUE (type_domain);
-      op0 = build4 (ARRAY_REF, type, sub, min_val, NULL_TREE, NULL_TREE);
-      SET_EXPR_LOCATION (op0, loc);
-      return op0;
+      return build4_loc (loc, ARRAY_REF, type, sub, min_val, NULL_TREE,
+                        NULL_TREE);
     }
 
   return NULL_TREE;
@@ -15578,9 +15659,7 @@ build_fold_indirect_ref_loc (location_t loc, tree t)
   if (sub)
     return sub;
 
-  t = build1 (INDIRECT_REF, type, t);
-  SET_EXPR_LOCATION (t, loc);
-  return t;
+  return build1_loc (loc, INDIRECT_REF, type, t);
 }
 
 /* Given an INDIRECT_REF T, return either T or a simplified version.  */