OSDN Git Service

2011-05-26 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index fb59049..c9c7afa 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, 2005, 2006, 2007, 2008, 2009
+   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -27,8 +27,7 @@ along with GCC; see the file COPYING3.  If not see
   @@ This would also make life easier when this technology is used
   @@ for cross-compilers.  */
 
-/* The entry points in this file are fold, size_int_wide, size_binop
-   and force_fit_type_double.
+/* The entry points in this file are fold, size_int_wide and size_binop.
 
    fold takes a tree as argument and returns a simplified tree.
 
@@ -39,10 +38,6 @@ along with GCC; see the file COPYING3.  If not see
    size_int takes an integer value, and creates a tree constant
    with type from `sizetype'.
 
-   force_fit_type_double takes a constant, an overflowable flag and a
-   prior overflow indicator.  It forces the value to fit the type and
-   sets TREE_OVERFLOW.
-
    Note: Since the folders get called on non-gimple code as well as
    gimple code, we need to handle GIMPLE tuples as well as their
    corresponding tree equivalents.  */
@@ -53,19 +48,19 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm.h"
 #include "flags.h"
 #include "tree.h"
-#include "real.h"
-#include "fixed-value.h"
+#include "realmpfr.h"
 #include "rtl.h"
 #include "expr.h"
 #include "tm_p.h"
 #include "target.h"
-#include "toplev.h"
+#include "diagnostic-core.h"
 #include "intl.h"
 #include "ggc.h"
 #include "hashtab.h"
 #include "langhooks.h"
 #include "md5.h"
 #include "gimple.h"
+#include "tree-flow.h"
 
 /* Nonzero if we are folding constants inside an initializer; zero
    otherwise.  */
@@ -93,24 +88,25 @@ enum comparison_code {
   COMPCODE_TRUE = 15
 };
 
-static void encode (HOST_WIDE_INT *, unsigned HOST_WIDE_INT, HOST_WIDE_INT);
-static void decode (HOST_WIDE_INT *, unsigned HOST_WIDE_INT *, HOST_WIDE_INT *);
 static bool negate_mathfn_p (enum built_in_function);
 static bool negate_expr_p (tree);
 static tree negate_expr (tree);
 static tree split_tree (tree, enum tree_code, tree *, tree *, tree *, int);
-static tree associate_trees (tree, tree, enum tree_code, tree);
-static tree const_binop (enum tree_code, tree, tree, int);
+static tree associate_trees (location_t, tree, tree, enum tree_code, tree);
+static tree const_binop (enum tree_code, tree, tree);
 static enum comparison_code comparison_to_compcode (enum tree_code);
 static enum tree_code compcode_to_comparison (enum comparison_code);
 static int operand_equal_for_comparison_p (tree, tree, tree);
 static int twoval_comparison_p (tree, tree *, tree *, int *);
-static tree eval_subst (tree, tree, tree, tree, tree);
-static tree pedantic_omit_one_operand (tree, tree, tree);
-static tree distribute_bit_expr (enum tree_code, tree, tree, tree);
-static tree make_bit_field_ref (tree, tree, HOST_WIDE_INT, HOST_WIDE_INT, int);
-static tree optimize_bit_field_compare (enum tree_code, tree, tree, tree);
-static tree decode_field_reference (tree, HOST_WIDE_INT *, HOST_WIDE_INT *,
+static tree eval_subst (location_t, tree, tree, tree, tree, tree);
+static tree pedantic_omit_one_operand_loc (location_t, tree, tree, tree);
+static tree distribute_bit_expr (location_t, enum tree_code, tree, tree, tree);
+static tree make_bit_field_ref (location_t, tree, tree,
+                               HOST_WIDE_INT, HOST_WIDE_INT, int);
+static tree optimize_bit_field_compare (location_t, enum tree_code,
+                                       tree, tree, tree);
+static tree decode_field_reference (location_t, tree, HOST_WIDE_INT *,
+                                   HOST_WIDE_INT *,
                                    enum machine_mode *, int *, int *,
                                    tree *, tree *);
 static int all_ones_mask_p (const_tree, int);
@@ -119,758 +115,71 @@ static int simple_operand_p (const_tree);
 static tree range_binop (enum tree_code, tree, tree, int, tree, int);
 static tree range_predecessor (tree);
 static tree range_successor (tree);
-static tree make_range (tree, int *, tree *, tree *, bool *);
-static tree build_range_check (tree, tree, int, tree, tree);
-static int merge_ranges (int *, tree *, tree *, int, tree, tree, int, tree,
-                        tree);
-static tree fold_range_test (enum tree_code, tree, tree, tree);
-static tree fold_cond_expr_with_comparison (tree, tree, tree, tree);
+extern tree make_range (tree, int *, tree *, tree *, bool *);
+extern bool merge_ranges (int *, tree *, tree *, int, tree, tree, int,
+                         tree, tree);
+static tree fold_range_test (location_t, enum tree_code, tree, tree, tree);
+static tree fold_cond_expr_with_comparison (location_t, tree, tree, tree, tree);
 static tree unextend (tree, int, int, tree);
-static tree fold_truthop (enum tree_code, tree, tree, tree);
-static tree optimize_minmax_comparison (enum tree_code, tree, tree, tree);
+static tree fold_truthop (location_t, enum tree_code, tree, tree, tree);
+static tree optimize_minmax_comparison (location_t, enum tree_code,
+                                       tree, tree, tree);
 static tree extract_muldiv (tree, tree, enum tree_code, tree, bool *);
 static tree extract_muldiv_1 (tree, tree, enum tree_code, tree, bool *);
-static tree fold_binary_op_with_conditional_arg (enum tree_code, tree,
+static tree fold_binary_op_with_conditional_arg (location_t,
+                                                enum tree_code, tree,
                                                 tree, tree,
                                                 tree, tree, int);
-static tree fold_mathfn_compare (enum built_in_function, enum tree_code,
+static tree fold_mathfn_compare (location_t,
+                                enum built_in_function, enum tree_code,
                                 tree, tree, tree);
-static tree fold_inf_compare (enum tree_code, tree, tree, tree);
-static tree fold_div_compare (enum tree_code, tree, tree, tree);
+static tree fold_inf_compare (location_t, enum tree_code, tree, tree, tree);
+static tree fold_div_compare (location_t, enum tree_code, tree, tree, tree);
 static bool reorder_operands_p (const_tree, const_tree);
 static tree fold_negate_const (tree, tree);
-static tree fold_not_const (tree, tree);
+static tree fold_not_const (const_tree, tree);
 static tree fold_relational_const (enum tree_code, tree, tree, tree);
 static tree fold_convert_const (enum tree_code, tree, tree);
 
+/* Return EXPR_LOCATION of T if it is not UNKNOWN_LOCATION.
+   Otherwise, return LOC.  */
 
-/* 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
-   addition.
-
-   Overflow occurs if A and B have the same sign, but A and SUM differ in
-   sign.  Use `^' to test whether signs differ, and `< 0' to isolate the
-   sign.  */
-#define OVERFLOW_SUM_SIGN(a, b, sum) ((~((a) ^ (b)) & ((a) ^ (sum))) < 0)
-\f
-/* To do constant folding on INTEGER_CST nodes requires two-word arithmetic.
-   We do that by representing the two-word integer in 4 words, with only
-   HOST_BITS_PER_WIDE_INT / 2 bits stored in each word, as a positive
-   number.  The value of the word is LOWPART + HIGHPART * BASE.  */
-
-#define LOWPART(x) \
-  ((x) & (((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2)) - 1))
-#define HIGHPART(x) \
-  ((unsigned HOST_WIDE_INT) (x) >> HOST_BITS_PER_WIDE_INT / 2)
-#define BASE ((unsigned HOST_WIDE_INT) 1 << HOST_BITS_PER_WIDE_INT / 2)
-
-/* Unpack a two-word integer into 4 words.
-   LOW and HI are the integer, as two `HOST_WIDE_INT' pieces.
-   WORDS points to the array of HOST_WIDE_INTs.  */
-
-static void
-encode (HOST_WIDE_INT *words, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi)
-{
-  words[0] = LOWPART (low);
-  words[1] = HIGHPART (low);
-  words[2] = LOWPART (hi);
-  words[3] = HIGHPART (hi);
-}
-
-/* Pack an array of 4 words into a two-word integer.
-   WORDS points to the array of words.
-   The integer is stored into *LOW and *HI as two `HOST_WIDE_INT' pieces.  */
-
-static void
-decode (HOST_WIDE_INT *words, unsigned HOST_WIDE_INT *low,
-       HOST_WIDE_INT *hi)
-{
-  *low = words[0] + words[1] * BASE;
-  *hi = words[2] + words[3] * BASE;
-}
-\f
-/* Force the double-word integer L1, H1 to be within the range of the
-   integer type TYPE.  Stores the properly truncated and sign-extended
-   double-word integer in *LV, *HV.  Returns true if the operation
-   overflows, that is, argument and result are different.  */
-
-int
-fit_double_type (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
-                unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv, const_tree type)
-{
-  unsigned HOST_WIDE_INT low0 = l1;
-  HOST_WIDE_INT high0 = h1;
-  unsigned int prec;
-  int sign_extended_type;
-
-  if (POINTER_TYPE_P (type)
-      || TREE_CODE (type) == OFFSET_TYPE)
-    prec = POINTER_SIZE;
-  else
-    prec = TYPE_PRECISION (type);
-
-  /* Size types *are* sign extended.  */
-  sign_extended_type = (!TYPE_UNSIGNED (type)
-                       || (TREE_CODE (type) == INTEGER_TYPE
-                           && TYPE_IS_SIZETYPE (type)));
-
-  /* First clear all bits that are beyond the type's precision.  */
-  if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
-    ;
-  else if (prec > HOST_BITS_PER_WIDE_INT)
-    h1 &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
-  else
-    {
-      h1 = 0;
-      if (prec < HOST_BITS_PER_WIDE_INT)
-       l1 &= ~((HOST_WIDE_INT) (-1) << prec);
-    }
-
-  /* Then do sign extension if necessary.  */
-  if (!sign_extended_type)
-    /* No sign extension */;
-  else if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
-    /* Correct width already.  */;
-  else if (prec > HOST_BITS_PER_WIDE_INT)
-    {
-      /* Sign extend top half? */
-      if (h1 & ((unsigned HOST_WIDE_INT)1
-               << (prec - HOST_BITS_PER_WIDE_INT - 1)))
-       h1 |= (HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT);
-    }
-  else if (prec == HOST_BITS_PER_WIDE_INT)
-    {
-      if ((HOST_WIDE_INT)l1 < 0)
-       h1 = -1;
-    }
-  else
-    {
-      /* Sign extend bottom half? */
-      if (l1 & ((unsigned HOST_WIDE_INT)1 << (prec - 1)))
-       {
-         h1 = -1;
-         l1 |= (HOST_WIDE_INT)(-1) << prec;
-       }
-    }
-
-  *lv = l1;
-  *hv = h1;
-
-  /* If the value didn't fit, signal overflow.  */
-  return l1 != low0 || h1 != high0;
-}
-
-/* We force the double-int HIGH:LOW to the range of the type TYPE by
-   sign or zero extending it.
-   OVERFLOWABLE indicates if we are interested
-   in overflow of the value, when >0 we are only interested in signed
-   overflow, for <0 we are interested in any overflow.  OVERFLOWED
-   indicates whether overflow has already occurred.  CONST_OVERFLOWED
-   indicates whether constant overflow has already occurred.  We force
-   T's value to be within range of T's type (by setting to 0 or 1 all
-   the bits outside the type's range).  We set TREE_OVERFLOWED if,
-       OVERFLOWED is nonzero,
-       or OVERFLOWABLE is >0 and signed overflow occurs
-       or OVERFLOWABLE is <0 and any overflow occurs
-   We return a new tree node for the extended double-int.  The node
-   is shared if no overflow flags are set.  */
-
-tree
-force_fit_type_double (tree type, unsigned HOST_WIDE_INT low,
-                      HOST_WIDE_INT high, int overflowable,
-                      bool overflowed)
-{
-  int sign_extended_type;
-  bool overflow;
-
-  /* Size types *are* sign extended.  */
-  sign_extended_type = (!TYPE_UNSIGNED (type)
-                       || (TREE_CODE (type) == INTEGER_TYPE
-                           && TYPE_IS_SIZETYPE (type)));
-
-  overflow = fit_double_type (low, high, &low, &high, type);
-
-  /* If we need to set overflow flags, return a new unshared node.  */
-  if (overflowed || overflow)
-    {
-      if (overflowed
-         || overflowable < 0
-         || (overflowable > 0 && sign_extended_type))
-       {
-          tree t = make_node (INTEGER_CST);
-          TREE_INT_CST_LOW (t) = low;
-          TREE_INT_CST_HIGH (t) = high;
-          TREE_TYPE (t) = type;
-         TREE_OVERFLOW (t) = 1;
-         return t;
-       }
-    }
-
-  /* Else build a shared node.  */
-  return build_int_cst_wide (type, low, high);
-}
-\f
-/* Add two doubleword integers with doubleword result.
-   Return nonzero if the operation overflows according to UNSIGNED_P.
-   Each argument is given as two `HOST_WIDE_INT' pieces.
-   One argument is L1 and H1; the other, L2 and H2.
-   The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV.  */
-
-int
-add_double_with_sign (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
-                     unsigned HOST_WIDE_INT l2, HOST_WIDE_INT h2,
-                     unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv,
-                     bool unsigned_p)
+static location_t
+expr_location_or (tree t, location_t loc)
 {
-  unsigned HOST_WIDE_INT l;
-  HOST_WIDE_INT h;
-
-  l = l1 + l2;
-  h = h1 + h2 + (l < l1);
-
-  *lv = l;
-  *hv = h;
-
-  if (unsigned_p)
-    return (unsigned HOST_WIDE_INT) h < (unsigned HOST_WIDE_INT) h1;
-  else
-    return OVERFLOW_SUM_SIGN (h1, h2, h);
+  location_t tloc = EXPR_LOCATION (t);
+  return tloc != UNKNOWN_LOCATION ? tloc : loc;
 }
 
-/* Negate a doubleword integer with doubleword result.
-   Return nonzero if the operation overflows, assuming it's signed.
-   The argument is given as two `HOST_WIDE_INT' pieces in L1 and H1.
-   The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV.  */
+/* Similar to protected_set_expr_location, but never modify x in place,
+   if location can and needs to be set, unshare it.  */
 
-int
-neg_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
-           unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv)
+static inline tree
+protected_set_expr_location_unshare (tree x, location_t loc)
 {
-  if (l1 == 0)
+  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))
     {
-      *lv = 0;
-      *hv = - h1;
-      return (*hv & h1) < 0;
-    }
-  else
-    {
-      *lv = -l1;
-      *hv = ~h1;
-      return 0;
+      x = copy_node (x);
+      SET_EXPR_LOCATION (x, loc);
     }
+  return x;
 }
-\f
-/* Multiply two doubleword integers with doubleword result.
-   Return nonzero if the operation overflows according to UNSIGNED_P.
-   Each argument is given as two `HOST_WIDE_INT' pieces.
-   One argument is L1 and H1; the other, L2 and H2.
-   The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV.  */
-
-int
-mul_double_with_sign (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
-                     unsigned HOST_WIDE_INT l2, HOST_WIDE_INT h2,
-                     unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv,
-                     bool unsigned_p)
-{
-  HOST_WIDE_INT arg1[4];
-  HOST_WIDE_INT arg2[4];
-  HOST_WIDE_INT prod[4 * 2];
-  unsigned HOST_WIDE_INT carry;
-  int i, j, k;
-  unsigned HOST_WIDE_INT toplow, neglow;
-  HOST_WIDE_INT tophigh, neghigh;
 
-  encode (arg1, l1, h1);
-  encode (arg2, l2, h2);
 
-  memset (prod, 0, sizeof prod);
-
-  for (i = 0; i < 4; i++)
-    {
-      carry = 0;
-      for (j = 0; j < 4; j++)
-       {
-         k = i + j;
-         /* This product is <= 0xFFFE0001, the sum <= 0xFFFF0000.  */
-         carry += arg1[i] * arg2[j];
-         /* Since prod[p] < 0xFFFF, this sum <= 0xFFFFFFFF.  */
-         carry += prod[k];
-         prod[k] = LOWPART (carry);
-         carry = HIGHPART (carry);
-       }
-      prod[i + 4] = carry;
-    }
-
-  decode (prod, lv, hv);
-  decode (prod + 4, &toplow, &tophigh);
-
-  /* Unsigned overflow is immediate.  */
-  if (unsigned_p)
-    return (toplow | tophigh) != 0;
-
-  /* Check for signed overflow by calculating the signed representation of the
-     top half of the result; it should agree with the low half's sign bit.  */
-  if (h1 < 0)
-    {
-      neg_double (l2, h2, &neglow, &neghigh);
-      add_double (neglow, neghigh, toplow, tophigh, &toplow, &tophigh);
-    }
-  if (h2 < 0)
-    {
-      neg_double (l1, h1, &neglow, &neghigh);
-      add_double (neglow, neghigh, toplow, tophigh, &toplow, &tophigh);
-    }
-  return (*hv < 0 ? ~(toplow & tophigh) : toplow | tophigh) != 0;
-}
-\f
-/* Shift the doubleword integer in L1, H1 left by COUNT places
-   keeping only PREC bits of result.
-   Shift right if COUNT is negative.
-   ARITH nonzero specifies arithmetic shifting; otherwise use logical shift.
-   Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV.  */
-
-void
-lshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
-              HOST_WIDE_INT count, unsigned int prec,
-              unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv, int arith)
-{
-  unsigned HOST_WIDE_INT signmask;
-
-  if (count < 0)
-    {
-      rshift_double (l1, h1, -count, prec, lv, hv, arith);
-      return;
-    }
-
-  if (SHIFT_COUNT_TRUNCATED)
-    count %= prec;
-
-  if (count >= 2 * HOST_BITS_PER_WIDE_INT)
-    {
-      /* Shifting by the host word size is undefined according to the
-        ANSI standard, so we must handle this as a special case.  */
-      *hv = 0;
-      *lv = 0;
-    }
-  else if (count >= HOST_BITS_PER_WIDE_INT)
-    {
-      *hv = l1 << (count - HOST_BITS_PER_WIDE_INT);
-      *lv = 0;
-    }
-  else
-    {
-      *hv = (((unsigned HOST_WIDE_INT) h1 << count)
-            | (l1 >> (HOST_BITS_PER_WIDE_INT - count - 1) >> 1));
-      *lv = l1 << count;
-    }
-
-  /* Sign extend all bits that are beyond the precision.  */
-
-  signmask = -((prec > HOST_BITS_PER_WIDE_INT
-               ? ((unsigned HOST_WIDE_INT) *hv
-                  >> (prec - HOST_BITS_PER_WIDE_INT - 1))
-               : (*lv >> (prec - 1))) & 1);
-
-  if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
-    ;
-  else if (prec >= HOST_BITS_PER_WIDE_INT)
-    {
-      *hv &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
-      *hv |= signmask << (prec - HOST_BITS_PER_WIDE_INT);
-    }
-  else
-    {
-      *hv = signmask;
-      *lv &= ~((unsigned HOST_WIDE_INT) (-1) << prec);
-      *lv |= signmask << prec;
-    }
-}
-
-/* Shift the doubleword integer in L1, H1 right by COUNT places
-   keeping only PREC bits of result.  COUNT must be positive.
-   ARITH nonzero specifies arithmetic shifting; otherwise use logical shift.
-   Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV.  */
-
-void
-rshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
-              HOST_WIDE_INT count, unsigned int prec,
-              unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv,
-              int arith)
-{
-  unsigned HOST_WIDE_INT signmask;
-
-  signmask = (arith
-             ? -((unsigned HOST_WIDE_INT) h1 >> (HOST_BITS_PER_WIDE_INT - 1))
-             : 0);
-
-  if (SHIFT_COUNT_TRUNCATED)
-    count %= prec;
-
-  if (count >= 2 * HOST_BITS_PER_WIDE_INT)
-    {
-      /* Shifting by the host word size is undefined according to the
-        ANSI standard, so we must handle this as a special case.  */
-      *hv = 0;
-      *lv = 0;
-    }
-  else if (count >= HOST_BITS_PER_WIDE_INT)
-    {
-      *hv = 0;
-      *lv = (unsigned HOST_WIDE_INT) h1 >> (count - HOST_BITS_PER_WIDE_INT);
-    }
-  else
-    {
-      *hv = (unsigned HOST_WIDE_INT) h1 >> count;
-      *lv = ((l1 >> count)
-            | ((unsigned HOST_WIDE_INT) h1 << (HOST_BITS_PER_WIDE_INT - count - 1) << 1));
-    }
-
-  /* Zero / sign extend all bits that are beyond the precision.  */
-
-  if (count >= (HOST_WIDE_INT)prec)
-    {
-      *hv = signmask;
-      *lv = signmask;
-    }
-  else if ((prec - count) >= 2 * HOST_BITS_PER_WIDE_INT)
-    ;
-  else if ((prec - count) >= HOST_BITS_PER_WIDE_INT)
-    {
-      *hv &= ~((HOST_WIDE_INT) (-1) << (prec - count - HOST_BITS_PER_WIDE_INT));
-      *hv |= signmask << (prec - count - HOST_BITS_PER_WIDE_INT);
-    }
-  else
-    {
-      *hv = signmask;
-      *lv &= ~((unsigned HOST_WIDE_INT) (-1) << (prec - count));
-      *lv |= signmask << (prec - count);
-    }
-}
-\f
-/* Rotate the doubleword integer in L1, H1 left by COUNT places
-   keeping only PREC bits of result.
-   Rotate right if COUNT is negative.
-   Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV.  */
-
-void
-lrotate_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
-               HOST_WIDE_INT count, unsigned int prec,
-               unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv)
-{
-  unsigned HOST_WIDE_INT s1l, s2l;
-  HOST_WIDE_INT s1h, s2h;
-
-  count %= prec;
-  if (count < 0)
-    count += prec;
-
-  lshift_double (l1, h1, count, prec, &s1l, &s1h, 0);
-  rshift_double (l1, h1, prec - count, prec, &s2l, &s2h, 0);
-  *lv = s1l | s2l;
-  *hv = s1h | s2h;
-}
-
-/* Rotate the doubleword integer in L1, H1 left by COUNT places
-   keeping only PREC bits of result.  COUNT must be positive.
-   Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV.  */
-
-void
-rrotate_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
-               HOST_WIDE_INT count, unsigned int prec,
-               unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv)
-{
-  unsigned HOST_WIDE_INT s1l, s2l;
-  HOST_WIDE_INT s1h, s2h;
-
-  count %= prec;
-  if (count < 0)
-    count += prec;
+/* 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
+   addition.
 
-  rshift_double (l1, h1, count, prec, &s1l, &s1h, 0);
-  lshift_double (l1, h1, prec - count, prec, &s2l, &s2h, 0);
-  *lv = s1l | s2l;
-  *hv = s1h | s2h;
-}
+   Overflow occurs if A and B have the same sign, but A and SUM differ in
+   sign.  Use `^' to test whether signs differ, and `< 0' to isolate the
+   sign.  */
+#define OVERFLOW_SUM_SIGN(a, b, sum) ((~((a) ^ (b)) & ((a) ^ (sum))) < 0)
 \f
-/* Divide doubleword integer LNUM, HNUM by doubleword integer LDEN, HDEN
-   for a quotient (stored in *LQUO, *HQUO) and remainder (in *LREM, *HREM).
-   CODE is a tree code for a kind of division, one of
-   TRUNC_DIV_EXPR, FLOOR_DIV_EXPR, CEIL_DIV_EXPR, ROUND_DIV_EXPR
-   or EXACT_DIV_EXPR
-   It controls how the quotient is rounded to an integer.
-   Return nonzero if the operation overflows.
-   UNS nonzero says do unsigned division.  */
-
-int
-div_and_round_double (enum tree_code code, int uns,
-                     unsigned HOST_WIDE_INT lnum_orig, /* num == numerator == dividend */
-                     HOST_WIDE_INT hnum_orig,
-                     unsigned HOST_WIDE_INT lden_orig, /* den == denominator == divisor */
-                     HOST_WIDE_INT hden_orig,
-                     unsigned HOST_WIDE_INT *lquo,
-                     HOST_WIDE_INT *hquo, unsigned HOST_WIDE_INT *lrem,
-                     HOST_WIDE_INT *hrem)
-{
-  int quo_neg = 0;
-  HOST_WIDE_INT num[4 + 1];    /* extra element for scaling.  */
-  HOST_WIDE_INT den[4], quo[4];
-  int i, j;
-  unsigned HOST_WIDE_INT work;
-  unsigned HOST_WIDE_INT carry = 0;
-  unsigned HOST_WIDE_INT lnum = lnum_orig;
-  HOST_WIDE_INT hnum = hnum_orig;
-  unsigned HOST_WIDE_INT lden = lden_orig;
-  HOST_WIDE_INT hden = hden_orig;
-  int overflow = 0;
-
-  if (hden == 0 && lden == 0)
-    overflow = 1, lden = 1;
-
-  /* Calculate quotient sign and convert operands to unsigned.  */
-  if (!uns)
-    {
-      if (hnum < 0)
-       {
-         quo_neg = ~ quo_neg;
-         /* (minimum integer) / (-1) is the only overflow case.  */
-         if (neg_double (lnum, hnum, &lnum, &hnum)
-             && ((HOST_WIDE_INT) lden & hden) == -1)
-           overflow = 1;
-       }
-      if (hden < 0)
-       {
-         quo_neg = ~ quo_neg;
-         neg_double (lden, hden, &lden, &hden);
-       }
-    }
-
-  if (hnum == 0 && hden == 0)
-    {                          /* single precision */
-      *hquo = *hrem = 0;
-      /* This unsigned division rounds toward zero.  */
-      *lquo = lnum / lden;
-      goto finish_up;
-    }
-
-  if (hnum == 0)
-    {                          /* trivial case: dividend < divisor */
-      /* hden != 0 already checked.  */
-      *hquo = *lquo = 0;
-      *hrem = hnum;
-      *lrem = lnum;
-      goto finish_up;
-    }
-
-  memset (quo, 0, sizeof quo);
-
-  memset (num, 0, sizeof num); /* to zero 9th element */
-  memset (den, 0, sizeof den);
-
-  encode (num, lnum, hnum);
-  encode (den, lden, hden);
-
-  /* Special code for when the divisor < BASE.  */
-  if (hden == 0 && lden < (unsigned HOST_WIDE_INT) BASE)
-    {
-      /* hnum != 0 already checked.  */
-      for (i = 4 - 1; i >= 0; i--)
-       {
-         work = num[i] + carry * BASE;
-         quo[i] = work / lden;
-         carry = work % lden;
-       }
-    }
-  else
-    {
-      /* Full double precision division,
-        with thanks to Don Knuth's "Seminumerical Algorithms".  */
-      int num_hi_sig, den_hi_sig;
-      unsigned HOST_WIDE_INT quo_est, scale;
-
-      /* Find the highest nonzero divisor digit.  */
-      for (i = 4 - 1;; i--)
-       if (den[i] != 0)
-         {
-           den_hi_sig = i;
-           break;
-         }
-
-      /* Insure that the first digit of the divisor is at least BASE/2.
-        This is required by the quotient digit estimation algorithm.  */
-
-      scale = BASE / (den[den_hi_sig] + 1);
-      if (scale > 1)
-       {               /* scale divisor and dividend */
-         carry = 0;
-         for (i = 0; i <= 4 - 1; i++)
-           {
-             work = (num[i] * scale) + carry;
-             num[i] = LOWPART (work);
-             carry = HIGHPART (work);
-           }
-
-         num[4] = carry;
-         carry = 0;
-         for (i = 0; i <= 4 - 1; i++)
-           {
-             work = (den[i] * scale) + carry;
-             den[i] = LOWPART (work);
-             carry = HIGHPART (work);
-             if (den[i] != 0) den_hi_sig = i;
-           }
-       }
-
-      num_hi_sig = 4;
-
-      /* Main loop */
-      for (i = num_hi_sig - den_hi_sig - 1; i >= 0; i--)
-       {
-         /* Guess the next quotient digit, quo_est, by dividing the first
-            two remaining dividend digits by the high order quotient digit.
-            quo_est is never low and is at most 2 high.  */
-         unsigned HOST_WIDE_INT tmp;
-
-         num_hi_sig = i + den_hi_sig + 1;
-         work = num[num_hi_sig] * BASE + num[num_hi_sig - 1];
-         if (num[num_hi_sig] != den[den_hi_sig])
-           quo_est = work / den[den_hi_sig];
-         else
-           quo_est = BASE - 1;
-
-         /* Refine quo_est so it's usually correct, and at most one high.  */
-         tmp = work - quo_est * den[den_hi_sig];
-         if (tmp < BASE
-             && (den[den_hi_sig - 1] * quo_est
-                 > (tmp * BASE + num[num_hi_sig - 2])))
-           quo_est--;
-
-         /* Try QUO_EST as the quotient digit, by multiplying the
-            divisor by QUO_EST and subtracting from the remaining dividend.
-            Keep in mind that QUO_EST is the I - 1st digit.  */
-
-         carry = 0;
-         for (j = 0; j <= den_hi_sig; j++)
-           {
-             work = quo_est * den[j] + carry;
-             carry = HIGHPART (work);
-             work = num[i + j] - LOWPART (work);
-             num[i + j] = LOWPART (work);
-             carry += HIGHPART (work) != 0;
-           }
-
-         /* If quo_est was high by one, then num[i] went negative and
-            we need to correct things.  */
-         if (num[num_hi_sig] < (HOST_WIDE_INT) carry)
-           {
-             quo_est--;
-             carry = 0;                /* add divisor back in */
-             for (j = 0; j <= den_hi_sig; j++)
-               {
-                 work = num[i + j] + den[j] + carry;
-                 carry = HIGHPART (work);
-                 num[i + j] = LOWPART (work);
-               }
-
-             num [num_hi_sig] += carry;
-           }
-
-         /* Store the quotient digit.  */
-         quo[i] = quo_est;
-       }
-    }
-
-  decode (quo, lquo, hquo);
-
- finish_up:
-  /* If result is negative, make it so.  */
-  if (quo_neg)
-    neg_double (*lquo, *hquo, lquo, hquo);
-
-  /* Compute trial remainder:  rem = num - (quo * den)  */
-  mul_double (*lquo, *hquo, lden_orig, hden_orig, lrem, hrem);
-  neg_double (*lrem, *hrem, lrem, hrem);
-  add_double (lnum_orig, hnum_orig, *lrem, *hrem, lrem, hrem);
-
-  switch (code)
-    {
-    case TRUNC_DIV_EXPR:
-    case TRUNC_MOD_EXPR:       /* round toward zero */
-    case EXACT_DIV_EXPR:       /* for this one, it shouldn't matter */
-      return overflow;
-
-    case FLOOR_DIV_EXPR:
-    case FLOOR_MOD_EXPR:       /* round toward negative infinity */
-      if (quo_neg && (*lrem != 0 || *hrem != 0))   /* ratio < 0 && rem != 0 */
-       {
-         /* quo = quo - 1;  */
-         add_double (*lquo, *hquo, (HOST_WIDE_INT) -1, (HOST_WIDE_INT)  -1,
-                     lquo, hquo);
-       }
-      else
-       return overflow;
-      break;
-
-    case CEIL_DIV_EXPR:
-    case CEIL_MOD_EXPR:                /* round toward positive infinity */
-      if (!quo_neg && (*lrem != 0 || *hrem != 0))  /* ratio > 0 && rem != 0 */
-       {
-         add_double (*lquo, *hquo, (HOST_WIDE_INT) 1, (HOST_WIDE_INT) 0,
-                     lquo, hquo);
-       }
-      else
-       return overflow;
-      break;
-
-    case ROUND_DIV_EXPR:
-    case ROUND_MOD_EXPR:       /* round to closest integer */
-      {
-       unsigned HOST_WIDE_INT labs_rem = *lrem;
-       HOST_WIDE_INT habs_rem = *hrem;
-       unsigned HOST_WIDE_INT labs_den = lden, ltwice;
-       HOST_WIDE_INT habs_den = hden, htwice;
-
-       /* Get absolute values.  */
-       if (*hrem < 0)
-         neg_double (*lrem, *hrem, &labs_rem, &habs_rem);
-       if (hden < 0)
-         neg_double (lden, hden, &labs_den, &habs_den);
-
-       /* If (2 * abs (lrem) >= abs (lden)), adjust the quotient.  */
-       mul_double ((HOST_WIDE_INT) 2, (HOST_WIDE_INT) 0,
-                   labs_rem, habs_rem, &ltwice, &htwice);
-
-       if (((unsigned HOST_WIDE_INT) habs_den
-            < (unsigned HOST_WIDE_INT) htwice)
-           || (((unsigned HOST_WIDE_INT) habs_den
-                == (unsigned HOST_WIDE_INT) htwice)
-               && (labs_den <= ltwice)))
-         {
-           if (*hquo < 0)
-             /* quo = quo - 1;  */
-             add_double (*lquo, *hquo,
-                         (HOST_WIDE_INT) -1, (HOST_WIDE_INT) -1, lquo, hquo);
-           else
-             /* quo = quo + 1; */
-             add_double (*lquo, *hquo, (HOST_WIDE_INT) 1, (HOST_WIDE_INT) 0,
-                         lquo, hquo);
-         }
-       else
-         return overflow;
-      }
-      break;
-
-    default:
-      gcc_unreachable ();
-    }
-
-  /* Compute true remainder:  rem = num - (quo * den)  */
-  mul_double (*lquo, *hquo, lden_orig, hden_orig, lrem, hrem);
-  neg_double (*lrem, *hrem, lrem, hrem);
-  add_double (lnum_orig, hnum_orig, *lrem, *hrem, lrem, hrem);
-  return overflow;
-}
-
 /* If ARG2 divides ARG1 with zero remainder, carries out the division
    of type CODE and returns the quotient.
    Otherwise returns NULL_TREE.  */
@@ -878,35 +187,25 @@ div_and_round_double (enum tree_code code, int uns,
 tree
 div_if_zero_remainder (enum tree_code code, const_tree arg1, const_tree arg2)
 {
-  unsigned HOST_WIDE_INT int1l, int2l;
-  HOST_WIDE_INT int1h, int2h;
-  unsigned HOST_WIDE_INT quol, reml;
-  HOST_WIDE_INT quoh, remh;
-  tree type = TREE_TYPE (arg1);
-  int uns = TYPE_UNSIGNED (type);
+  double_int quo, rem;
+  int uns;
 
-  int1l = TREE_INT_CST_LOW (arg1);
-  int1h = TREE_INT_CST_HIGH (arg1);
-  /* &obj[0] + -128 really should be compiled as &obj[-8] rather than
-     &obj[some_exotic_number].  */
-  if (POINTER_TYPE_P (type))
-    {
-      uns = false;
-      type = signed_type_for (type);
-      fit_double_type (int1l, int1h, &int1l, &int1h,
-                      type);
-    }
-  else
-    fit_double_type (int1l, int1h, &int1l, &int1h, type);
-  int2l = TREE_INT_CST_LOW (arg2);
-  int2h = TREE_INT_CST_HIGH (arg2);
+  /* The sign of the division is according to operand two, that
+     does the correct thing for POINTER_PLUS_EXPR where we want
+     a signed division.  */
+  uns = TYPE_UNSIGNED (TREE_TYPE (arg2));
+  if (TREE_CODE (TREE_TYPE (arg2)) == INTEGER_TYPE
+      && TYPE_IS_SIZETYPE (TREE_TYPE (arg2)))
+    uns = false;
 
-  div_and_round_double (code, uns, int1l, int1h, int2l, int2h,
-                       &quol, &quoh, &reml, &remh);
-  if (remh != 0 || reml != 0)
-    return NULL_TREE;
+  quo = double_int_divmod (tree_to_double_int (arg1),
+                          tree_to_double_int (arg2),
+                          uns, code, &rem);
+
+  if (double_int_zero_p (rem))
+    return build_int_cst_wide (TREE_TYPE (arg1), quo.low, quo.high);
 
-  return build_int_cst_wide (type, quol, quoh);
+  return NULL_TREE; 
 }
 \f
 /* This is nonzero if we should defer warnings about undefined
@@ -988,7 +287,7 @@ fold_undefer_overflow_warnings (bool issue, const_gimple stmt, int code)
     locus = input_location;
   else
     locus = gimple_location (stmt);
-  warning (OPT_Wstrict_overflow, "%H%s", &locus, warnmsg);
+  warning_at (locus, OPT_Wstrict_overflow, "%s", warnmsg);
 }
 
 /* Stop deferring overflow warnings, ignoring any deferred
@@ -1065,7 +364,7 @@ negate_mathfn_p (enum built_in_function code)
     CASE_FLT_FN (BUILT_IN_NEARBYINT):
     CASE_FLT_FN (BUILT_IN_RINT):
       return !flag_rounding_math;
-    
+
     default:
       break;
     }
@@ -1130,10 +429,14 @@ negate_expr_p (tree t)
              && TYPE_OVERFLOW_WRAPS (type));
 
     case FIXED_CST:
-    case REAL_CST:
     case NEGATE_EXPR:
       return true;
 
+    case REAL_CST:
+      /* We want to canonicalize to positive real constants.  Pretend
+         that only negative ones can be easily negated.  */
+      return REAL_VALUE_NEGATIVE (TREE_REAL_CST (t));
+
     case COMPLEX_CST:
       return negate_expr_p (TREE_REALPART (t))
             && negate_expr_p (TREE_IMAGPART (t));
@@ -1232,7 +535,7 @@ negate_expr_p (tree t)
    returned.  */
 
 static tree
-fold_negate_expr (tree t)
+fold_negate_expr (location_t loc, tree t)
 {
   tree type = TREE_TYPE (t);
   tree tem;
@@ -1242,10 +545,10 @@ fold_negate_expr (tree t)
     /* Convert - (~A) to A + 1.  */
     case BIT_NOT_EXPR:
       if (INTEGRAL_TYPE_P (type))
-        return fold_build2 (PLUS_EXPR, type, TREE_OPERAND (t, 0),
+        return fold_build2_loc (loc, PLUS_EXPR, type, TREE_OPERAND (t, 0),
                             build_int_cst (type, 1));
       break;
-      
+
     case INTEGER_CST:
       tem = fold_negate_const (t, type);
       if (TREE_OVERFLOW (tem) == TREE_OVERFLOW (t)
@@ -1279,15 +582,15 @@ fold_negate_expr (tree t)
 
     case COMPLEX_EXPR:
       if (negate_expr_p (t))
-       return fold_build2 (COMPLEX_EXPR, type,
-                           fold_negate_expr (TREE_OPERAND (t, 0)),
-                           fold_negate_expr (TREE_OPERAND (t, 1)));
+       return fold_build2_loc (loc, COMPLEX_EXPR, type,
+                           fold_negate_expr (loc, TREE_OPERAND (t, 0)),
+                           fold_negate_expr (loc, TREE_OPERAND (t, 1)));
       break;
-      
+
     case CONJ_EXPR:
       if (negate_expr_p (t))
-       return fold_build1 (CONJ_EXPR, type,
-                           fold_negate_expr (TREE_OPERAND (t, 0)));
+       return fold_build1_loc (loc, CONJ_EXPR, type,
+                           fold_negate_expr (loc, TREE_OPERAND (t, 0)));
       break;
 
     case NEGATE_EXPR:
@@ -1303,7 +606,7 @@ fold_negate_expr (tree t)
                                     TREE_OPERAND (t, 1)))
            {
              tem = negate_expr (TREE_OPERAND (t, 1));
-             return fold_build2 (MINUS_EXPR, type,
+             return fold_build2_loc (loc, MINUS_EXPR, type,
                                  tem, TREE_OPERAND (t, 0));
            }
 
@@ -1311,7 +614,7 @@ fold_negate_expr (tree t)
          if (negate_expr_p (TREE_OPERAND (t, 0)))
            {
              tem = negate_expr (TREE_OPERAND (t, 0));
-             return fold_build2 (MINUS_EXPR, type,
+             return fold_build2_loc (loc, MINUS_EXPR, type,
                                  tem, TREE_OPERAND (t, 1));
            }
        }
@@ -1322,7 +625,7 @@ fold_negate_expr (tree t)
       if (!HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type))
          && !HONOR_SIGNED_ZEROS (TYPE_MODE (type))
          && reorder_operands_p (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1)))
-       return fold_build2 (MINUS_EXPR, type,
+       return fold_build2_loc (loc, MINUS_EXPR, type,
                            TREE_OPERAND (t, 1), TREE_OPERAND (t, 0));
       break;
 
@@ -1337,11 +640,11 @@ fold_negate_expr (tree t)
        {
          tem = TREE_OPERAND (t, 1);
          if (negate_expr_p (tem))
-           return fold_build2 (TREE_CODE (t), type,
+           return fold_build2_loc (loc, TREE_CODE (t), type,
                                TREE_OPERAND (t, 0), negate_expr (tem));
          tem = TREE_OPERAND (t, 0);
          if (negate_expr_p (tem))
-           return fold_build2 (TREE_CODE (t), type,
+           return fold_build2_loc (loc, TREE_CODE (t), type,
                                negate_expr (tem), TREE_OPERAND (t, 1));
        }
       break;
@@ -1367,7 +670,7 @@ fold_negate_expr (tree t)
                  && (TREE_CODE (tem) != INTEGER_CST
                      || integer_onep (tem)))
                fold_overflow_warning (warnmsg, WARN_STRICT_OVERFLOW_MISC);
-             return fold_build2 (TREE_CODE (t), type,
+             return fold_build2_loc (loc, TREE_CODE (t), type,
                                  TREE_OPERAND (t, 0), negate_expr (tem));
            }
           tem = TREE_OPERAND (t, 0);
@@ -1377,7 +680,7 @@ fold_negate_expr (tree t)
                  && (TREE_CODE (tem) != INTEGER_CST
                      || tree_int_cst_equal (tem, TYPE_MIN_VALUE (type))))
                fold_overflow_warning (warnmsg, WARN_STRICT_OVERFLOW_MISC);
-             return fold_build2 (TREE_CODE (t), type,
+             return fold_build2_loc (loc, TREE_CODE (t), type,
                                  negate_expr (tem), TREE_OPERAND (t, 1));
            }
         }
@@ -1389,7 +692,7 @@ fold_negate_expr (tree t)
        {
          tem = strip_float_extensions (t);
          if (tem != t && negate_expr_p (tem))
-           return fold_convert (type, negate_expr (tem));
+           return fold_convert_loc (loc, type, negate_expr (tem));
        }
       break;
 
@@ -1402,7 +705,7 @@ fold_negate_expr (tree t)
 
          fndecl = get_callee_fndecl (t);
          arg = negate_expr (CALL_EXPR_ARG (t, 0));
-         return build_call_expr (fndecl, 1, arg);
+         return build_call_expr_loc (loc, fndecl, 1, arg);
        }
       break;
 
@@ -1418,9 +721,9 @@ fold_negate_expr (tree t)
              tree ntype = TYPE_UNSIGNED (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);
-             return fold_convert (type, temp);
+             tree temp = fold_convert_loc (loc, ntype, TREE_OPERAND (t, 0));
+             temp = fold_build2_loc (loc, RSHIFT_EXPR, ntype, temp, op1);
+             return fold_convert_loc (loc, type, temp);
            }
        }
       break;
@@ -1440,17 +743,19 @@ static tree
 negate_expr (tree t)
 {
   tree type, tem;
+  location_t loc;
 
   if (t == NULL_TREE)
     return NULL_TREE;
 
+  loc = EXPR_LOCATION (t);
   type = TREE_TYPE (t);
   STRIP_SIGN_NOPS (t);
 
-  tem = fold_negate_expr (t);
+  tem = fold_negate_expr (loc, t);
   if (!tem)
-    tem = build1 (NEGATE_EXPR, TREE_TYPE (t), t);
-  return fold_convert (type, tem);
+    tem = build1_loc (loc, NEGATE_EXPR, TREE_TYPE (t), t);
+  return fold_convert_loc (loc, type, tem);
 }
 \f
 /* Split a tree IN into a constant, literal and variable parts that could be
@@ -1552,12 +857,13 @@ split_tree (tree in, enum tree_code code, tree *conp, tree *litp,
   return var;
 }
 
-/* Re-associate trees split by the above function.  T1 and T2 are either
-   expressions to associate or null.  Return the new expression, if any.  If
+/* Re-associate trees split by the above function.  T1 and T2 are
+   either expressions to associate or null.  Return the new
+   expression, if any.  LOC is the location of the new expression.  If
    we build an operation, do it in TYPE and with CODE.  */
 
 static tree
-associate_trees (tree t1, tree t2, enum tree_code code, tree type)
+associate_trees (location_t loc, tree t1, tree t2, enum tree_code code, tree type)
 {
   if (t1 == 0)
     return t2;
@@ -1573,26 +879,30 @@ associate_trees (tree t1, tree t2, enum tree_code code, tree type)
       if (code == PLUS_EXPR)
        {
          if (TREE_CODE (t1) == NEGATE_EXPR)
-           return build2 (MINUS_EXPR, type, fold_convert (type, t2),
-                          fold_convert (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)
-           return build2 (MINUS_EXPR, type, fold_convert (type, t1),
-                          fold_convert (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 (type, t1);
+           return fold_convert_loc (loc, type, t1);
        }
       else if (code == MINUS_EXPR)
        {
          if (integer_zerop (t2))
-           return fold_convert (type, t1);
+           return fold_convert_loc (loc, type, t1);
        }
 
-      return build2 (code, type, fold_convert (type, t1),
-                    fold_convert (type, t2));
+      return build2_loc (loc, code, type, fold_convert_loc (loc, type, t1),
+                        fold_convert_loc (loc, type, t2));
     }
 
-  return fold_build2 (code, type, fold_convert (type, t1),
-                     fold_convert (type, t2));
+  return fold_build2_loc (loc, code, type, fold_convert_loc (loc, type, t1),
+                         fold_convert_loc (loc, type, t2));
 }
 \f
 /* Check whether TYPE1 and TYPE2 are equivalent integer types, suitable
@@ -1626,174 +936,154 @@ int_binop_types_match_p (enum tree_code code, const_tree type1, const_tree type2
 
 /* Combine two integer constants ARG1 and ARG2 under operation CODE
    to produce a new constant.  Return NULL_TREE if we don't know how
-   to evaluate CODE at compile-time.
-
-   If NOTRUNC is nonzero, do not truncate the result to fit the data type.  */
+   to evaluate CODE at compile-time.  */
 
 tree
-int_const_binop (enum tree_code code, const_tree arg1, const_tree arg2, int notrunc)
-{
-  unsigned HOST_WIDE_INT int1l, int2l;
-  HOST_WIDE_INT int1h, int2h;
-  unsigned HOST_WIDE_INT low;
-  HOST_WIDE_INT hi;
-  unsigned HOST_WIDE_INT garbagel;
-  HOST_WIDE_INT garbageh;
+int_const_binop (enum tree_code code, const_tree arg1, const_tree arg2)
+{
+  double_int op1, op2, res, tmp;
   tree t;
   tree type = TREE_TYPE (arg1);
-  int uns = TYPE_UNSIGNED (type);
-  int is_sizetype
+  bool uns = TYPE_UNSIGNED (type);
+  bool is_sizetype
     = (TREE_CODE (type) == INTEGER_TYPE && TYPE_IS_SIZETYPE (type));
-  int overflow = 0;
+  bool overflow = false;
 
-  int1l = TREE_INT_CST_LOW (arg1);
-  int1h = TREE_INT_CST_HIGH (arg1);
-  int2l = TREE_INT_CST_LOW (arg2);
-  int2h = TREE_INT_CST_HIGH (arg2);
+  op1 = tree_to_double_int (arg1);
+  op2 = tree_to_double_int (arg2);
 
   switch (code)
     {
     case BIT_IOR_EXPR:
-      low = int1l | int2l, hi = int1h | int2h;
+      res = double_int_ior (op1, op2);
       break;
 
     case BIT_XOR_EXPR:
-      low = int1l ^ int2l, hi = int1h ^ int2h;
+      res = double_int_xor (op1, op2);
       break;
 
     case BIT_AND_EXPR:
-      low = int1l & int2l, hi = int1h & int2h;
+      res = double_int_and (op1, op2);
       break;
 
     case RSHIFT_EXPR:
-      int2l = -int2l;
+      res = double_int_rshift (op1, double_int_to_shwi (op2),
+                              TYPE_PRECISION (type), !uns);
+      break;
+
     case LSHIFT_EXPR:
       /* It's unclear from the C standard whether shifts can overflow.
         The following code ignores overflow; perhaps a C standard
         interpretation ruling is needed.  */
-      lshift_double (int1l, int1h, int2l, TYPE_PRECISION (type),
-                    &low, &hi, !uns);
+      res = double_int_lshift (op1, double_int_to_shwi (op2),
+                              TYPE_PRECISION (type), !uns);
       break;
 
     case RROTATE_EXPR:
-      int2l = - int2l;
+      res = double_int_rrotate (op1, double_int_to_shwi (op2),
+                               TYPE_PRECISION (type));
+      break;
+
     case LROTATE_EXPR:
-      lrotate_double (int1l, int1h, int2l, TYPE_PRECISION (type),
-                     &low, &hi);
+      res = double_int_lrotate (op1, double_int_to_shwi (op2),
+                               TYPE_PRECISION (type));
       break;
 
     case PLUS_EXPR:
-      overflow = add_double (int1l, int1h, int2l, int2h, &low, &hi);
+      overflow = add_double (op1.low, op1.high, op2.low, op2.high,
+                            &res.low, &res.high);
       break;
 
     case MINUS_EXPR:
-      neg_double (int2l, int2h, &low, &hi);
-      add_double (int1l, int1h, low, hi, &low, &hi);
-      overflow = OVERFLOW_SUM_SIGN (hi, int2h, int1h);
+      neg_double (op2.low, op2.high, &res.low, &res.high);
+      add_double (op1.low, op1.high, res.low, res.high,
+                 &res.low, &res.high);
+      overflow = OVERFLOW_SUM_SIGN (res.high, op2.high, op1.high);
       break;
 
     case MULT_EXPR:
-      overflow = mul_double (int1l, int1h, int2l, int2h, &low, &hi);
+      overflow = mul_double (op1.low, op1.high, op2.low, op2.high,
+                            &res.low, &res.high);
       break;
 
     case TRUNC_DIV_EXPR:
     case FLOOR_DIV_EXPR: case CEIL_DIV_EXPR:
     case EXACT_DIV_EXPR:
       /* This is a shortcut for a common special case.  */
-      if (int2h == 0 && (HOST_WIDE_INT) int2l > 0
+      if (op2.high == 0 && (HOST_WIDE_INT) op2.low > 0
          && !TREE_OVERFLOW (arg1)
          && !TREE_OVERFLOW (arg2)
-         && int1h == 0 && (HOST_WIDE_INT) int1l >= 0)
+         && op1.high == 0 && (HOST_WIDE_INT) op1.low >= 0)
        {
          if (code == CEIL_DIV_EXPR)
-           int1l += int2l - 1;
+           op1.low += op2.low - 1;
 
-         low = int1l / int2l, hi = 0;
+         res.low = op1.low / op2.low, res.high = 0;
          break;
        }
 
       /* ... fall through ...  */
 
     case ROUND_DIV_EXPR:
-      if (int2h == 0 && int2l == 0)
+      if (double_int_zero_p (op2))
        return NULL_TREE;
-      if (int2h == 0 && int2l == 1)
+      if (double_int_one_p (op2))
        {
-         low = int1l, hi = int1h;
+         res = op1;
          break;
        }
-      if (int1l == int2l && int1h == int2h
-         && ! (int1l == 0 && int1h == 0))
+      if (double_int_equal_p (op1, op2)
+         && ! double_int_zero_p (op1))
        {
-         low = 1, hi = 0;
+         res = double_int_one;
          break;
        }
-      overflow = div_and_round_double (code, uns, int1l, int1h, int2l, int2h,
-                                      &low, &hi, &garbagel, &garbageh);
+      overflow = div_and_round_double (code, uns,
+                                      op1.low, op1.high, op2.low, op2.high,
+                                      &res.low, &res.high,
+                                      &tmp.low, &tmp.high);
       break;
 
     case TRUNC_MOD_EXPR:
     case FLOOR_MOD_EXPR: case CEIL_MOD_EXPR:
       /* This is a shortcut for a common special case.  */
-      if (int2h == 0 && (HOST_WIDE_INT) int2l > 0
+      if (op2.high == 0 && (HOST_WIDE_INT) op2.low > 0
          && !TREE_OVERFLOW (arg1)
          && !TREE_OVERFLOW (arg2)
-         && int1h == 0 && (HOST_WIDE_INT) int1l >= 0)
+         && op1.high == 0 && (HOST_WIDE_INT) op1.low >= 0)
        {
          if (code == CEIL_MOD_EXPR)
-           int1l += int2l - 1;
-         low = int1l % int2l, hi = 0;
+           op1.low += op2.low - 1;
+         res.low = op1.low % op2.low, res.high = 0;
          break;
        }
 
       /* ... fall through ...  */
 
     case ROUND_MOD_EXPR:
-      if (int2h == 0 && int2l == 0)
+      if (double_int_zero_p (op2))
        return NULL_TREE;
       overflow = div_and_round_double (code, uns,
-                                      int1l, int1h, int2l, int2h,
-                                      &garbagel, &garbageh, &low, &hi);
+                                      op1.low, op1.high, op2.low, op2.high,
+                                      &tmp.low, &tmp.high,
+                                      &res.low, &res.high);
       break;
 
     case MIN_EXPR:
-    case MAX_EXPR:
-      if (uns)
-       low = (((unsigned HOST_WIDE_INT) int1h
-               < (unsigned HOST_WIDE_INT) int2h)
-              || (((unsigned HOST_WIDE_INT) int1h
-                   == (unsigned HOST_WIDE_INT) int2h)
-                  && int1l < int2l));
-      else
-       low = (int1h < int2h
-              || (int1h == int2h && int1l < int2l));
+      res = double_int_min (op1, op2, uns);
+      break;
 
-      if (low == (code == MIN_EXPR))
-       low = int1l, hi = int1h;
-      else
-       low = int2l, hi = int2h;
+    case MAX_EXPR:
+      res = double_int_max (op1, op2, uns);
       break;
 
     default:
       return NULL_TREE;
     }
 
-  if (notrunc)
-    {
-      t = build_int_cst_wide (TREE_TYPE (arg1), low, hi);
-
-      /* Propagate overflow flags ourselves.  */
-      if (((!uns || is_sizetype) && overflow)
-         | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2))
-       {
-         t = copy_node (t);
-         TREE_OVERFLOW (t) = 1;
-       }
-    }
-  else
-    t = force_fit_type_double (TREE_TYPE (arg1), low, hi, 1,
-                              ((!uns || is_sizetype) && overflow)
-                              | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2));
+  t = force_fit_type_double (TREE_TYPE (arg1), res, 1,
+                            ((!uns || is_sizetype) && overflow)
+                            | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2));
 
   return t;
 }
@@ -1801,12 +1091,10 @@ int_const_binop (enum tree_code code, const_tree arg1, const_tree arg2, int notr
 /* Combine two constants ARG1 and ARG2 under operation CODE to produce a new
    constant.  We assume ARG1 and ARG2 have the same data type, or at least
    are the same kind of constant and the same machine mode.  Return zero if
-   combining the constants is not allowed in the current operating mode.
-
-   If NOTRUNC is nonzero, do not truncate the result to fit the data type.  */
+   combining the constants is not allowed in the current operating mode.  */
 
 static tree
-const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
+const_binop (enum tree_code code, tree arg1, tree arg2)
 {
   /* Sanity check for the recursive cases.  */
   if (!arg1 || !arg2)
@@ -1816,7 +1104,7 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
   STRIP_NOPS (arg2);
 
   if (TREE_CODE (arg1) == INTEGER_CST)
-    return int_const_binop (code, arg1, arg2, notrunc);
+    return int_const_binop (code, arg1, arg2);
 
   if (TREE_CODE (arg1) == REAL_CST)
     {
@@ -1950,44 +1238,111 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
        {
        case PLUS_EXPR:
        case MINUS_EXPR:
-         real = const_binop (code, r1, r2, notrunc);
-         imag = const_binop (code, i1, i2, notrunc);
+         real = const_binop (code, r1, r2);
+         imag = const_binop (code, i1, i2);
          break;
 
        case MULT_EXPR:
+         if (COMPLEX_FLOAT_TYPE_P (type))
+           return do_mpc_arg2 (arg1, arg2, type,
+                               /* do_nonfinite= */ folding_initializer,
+                               mpc_mul);
+
          real = const_binop (MINUS_EXPR,
-                             const_binop (MULT_EXPR, r1, r2, notrunc),
-                             const_binop (MULT_EXPR, i1, i2, notrunc),
-                             notrunc);
+                             const_binop (MULT_EXPR, r1, r2),
+                             const_binop (MULT_EXPR, i1, i2));
          imag = const_binop (PLUS_EXPR,
-                             const_binop (MULT_EXPR, r1, i2, notrunc),
-                             const_binop (MULT_EXPR, i1, r2, notrunc),
-                             notrunc);
+                             const_binop (MULT_EXPR, r1, i2),
+                             const_binop (MULT_EXPR, i1, r2));
          break;
 
        case RDIV_EXPR:
+         if (COMPLEX_FLOAT_TYPE_P (type))
+           return do_mpc_arg2 (arg1, arg2, type,
+                                /* do_nonfinite= */ folding_initializer,
+                               mpc_div);
+         /* Fallthru ... */
+       case TRUNC_DIV_EXPR:
+       case CEIL_DIV_EXPR:
+       case FLOOR_DIV_EXPR:
+       case ROUND_DIV_EXPR:
+         if (flag_complex_method == 0)
          {
+           /* Keep this algorithm in sync with
+              tree-complex.c:expand_complex_div_straight().
+
+              Expand complex division to scalars, straightforward algorithm.
+              a / b = ((ar*br + ai*bi)/t) + i((ai*br - ar*bi)/t)
+              t = br*br + bi*bi
+           */
            tree magsquared
              = const_binop (PLUS_EXPR,
-                            const_binop (MULT_EXPR, r2, r2, notrunc),
-                            const_binop (MULT_EXPR, i2, i2, notrunc),
-                            notrunc);
+                            const_binop (MULT_EXPR, r2, r2),
+                            const_binop (MULT_EXPR, i2, i2));
            tree t1
              = const_binop (PLUS_EXPR,
-                            const_binop (MULT_EXPR, r1, r2, notrunc),
-                            const_binop (MULT_EXPR, i1, i2, notrunc),
-                            notrunc);
+                            const_binop (MULT_EXPR, r1, r2),
+                            const_binop (MULT_EXPR, i1, i2));
            tree t2
              = const_binop (MINUS_EXPR,
-                            const_binop (MULT_EXPR, i1, r2, notrunc),
-                            const_binop (MULT_EXPR, r1, i2, notrunc),
-                            notrunc);
+                            const_binop (MULT_EXPR, i1, r2),
+                            const_binop (MULT_EXPR, r1, i2));
+
+           real = const_binop (code, t1, magsquared);
+           imag = const_binop (code, t2, magsquared);
+         }
+         else
+         {
+           /* Keep this algorithm in sync with
+               tree-complex.c:expand_complex_div_wide().
 
-           if (INTEGRAL_TYPE_P (TREE_TYPE (r1)))
-             code = TRUNC_DIV_EXPR;
+              Expand complex division to scalars, modified algorithm to minimize
+              overflow with wide input ranges.  */
+           tree compare = fold_build2 (LT_EXPR, boolean_type_node,
+                                       fold_abs_const (r2, TREE_TYPE (type)),
+                                       fold_abs_const (i2, TREE_TYPE (type)));
 
-           real = const_binop (code, t1, magsquared, notrunc);
-           imag = const_binop (code, t2, magsquared, notrunc);
+           if (integer_nonzerop (compare))
+             {
+               /* In the TRUE branch, we compute
+                  ratio = br/bi;
+                  div = (br * ratio) + bi;
+                  tr = (ar * ratio) + ai;
+                  ti = (ai * ratio) - ar;
+                  tr = tr / div;
+                  ti = ti / div;  */
+               tree ratio = const_binop (code, r2, i2);
+               tree div = const_binop (PLUS_EXPR, i2,
+                                       const_binop (MULT_EXPR, r2, ratio));
+               real = const_binop (MULT_EXPR, r1, ratio);
+               real = const_binop (PLUS_EXPR, real, i1);
+               real = const_binop (code, real, div);
+
+               imag = const_binop (MULT_EXPR, i1, ratio);
+               imag = const_binop (MINUS_EXPR, imag, r1);
+               imag = const_binop (code, imag, div);
+             }
+           else
+             {
+               /* In the FALSE branch, we compute
+                  ratio = d/c;
+                  divisor = (d * ratio) + c;
+                  tr = (b * ratio) + a;
+                  ti = b - (a * ratio);
+                  tr = tr / div;
+                  ti = ti / div;  */
+               tree ratio = const_binop (code, i2, r2);
+               tree div = const_binop (PLUS_EXPR, r2,
+                                        const_binop (MULT_EXPR, i2, ratio));
+
+               real = const_binop (MULT_EXPR, i1, ratio);
+               real = const_binop (PLUS_EXPR, real, r1);
+               real = const_binop (code, real, div);
+
+               imag = const_binop (MULT_EXPR, r1, ratio);
+               imag = const_binop (MINUS_EXPR, i1, imag);
+               imag = const_binop (code, imag, div);
+             }
          }
          break;
 
@@ -2004,17 +1359,17 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
       tree type = TREE_TYPE(arg1);
       int count = TYPE_VECTOR_SUBPARTS (type), i;
       tree elements1, elements2, list = NULL_TREE;
-      
+
       if(TREE_CODE(arg2) != VECTOR_CST)
         return NULL_TREE;
-        
+
       elements1 = TREE_VECTOR_CST_ELTS (arg1);
       elements2 = TREE_VECTOR_CST_ELTS (arg2);
 
       for (i = 0; i < count; i++)
        {
           tree elem1, elem2, elem;
-          
+
           /* The trailing elements can be empty and should be treated as 0 */
           if(!elements1)
             elem1 = fold_convert_const (NOP_EXPR, TREE_TYPE (type), integer_zero_node);
@@ -2022,8 +1377,8 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
             {
               elem1 = TREE_VALUE(elements1);
               elements1 = TREE_CHAIN (elements1);
-            }  
-            
+            }
+
           if(!elements2)
             elem2 = fold_convert_const (NOP_EXPR, TREE_TYPE (type), integer_zero_node);
           else
@@ -2031,17 +1386,17 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
               elem2 = TREE_VALUE(elements2);
               elements2 = TREE_CHAIN (elements2);
             }
-              
-          elem = const_binop (code, elem1, elem2, notrunc);
-          
+
+          elem = const_binop (code, elem1, elem2);
+
           /* It is possible that const_binop cannot handle the given
             code and return NULL_TREE */
           if(elem == NULL_TREE)
             return NULL_TREE;
-          
+
           list = tree_cons (NULL_TREE, elem, list);
        }
-      return build_vector(type, nreverse(list));  
+      return build_vector(type, nreverse(list));
     }
   return NULL_TREE;
 }
@@ -2061,7 +1416,7 @@ size_int_kind (HOST_WIDE_INT number, enum size_type_kind kind)
    If the operands are constant, so is the result.  */
 
 tree
-size_binop (enum tree_code code, tree arg0, tree arg1)
+size_binop_loc (location_t loc, enum tree_code code, tree arg0, tree arg1)
 {
   tree type = TREE_TYPE (arg0);
 
@@ -2094,10 +1449,10 @@ size_binop (enum tree_code code, tree arg0, tree arg1)
        }
 
       /* Handle general case of two integer constants.  */
-      return int_const_binop (code, arg0, arg1, 0);
+      return int_const_binop (code, arg0, arg1);
     }
 
-  return fold_build2 (code, type, arg0, arg1);
+  return fold_build2_loc (loc, code, type, arg0, arg1);
 }
 
 /* Given two values, either both of sizetype or both of bitsizetype,
@@ -2105,7 +1460,7 @@ size_binop (enum tree_code code, tree arg0, tree arg1)
    in signed type corresponding to the type of the operands.  */
 
 tree
-size_diffop (tree arg0, tree arg1)
+size_diffop_loc (location_t loc, tree arg0, tree arg1)
 {
   tree type = TREE_TYPE (arg0);
   tree ctype;
@@ -2115,7 +1470,7 @@ size_diffop (tree arg0, tree arg1)
 
   /* If the type is already signed, just do the simple thing.  */
   if (!TYPE_UNSIGNED (type))
-    return size_binop (MINUS_EXPR, arg0, arg1);
+    return size_binop_loc (loc, MINUS_EXPR, arg0, arg1);
 
   if (type == sizetype)
     ctype = ssizetype;
@@ -2128,8 +1483,9 @@ size_diffop (tree arg0, tree arg1)
      type and subtract.  The hardware will do the right thing with any
      overflow in the subtraction.  */
   if (TREE_CODE (arg0) != INTEGER_CST || TREE_CODE (arg1) != INTEGER_CST)
-    return size_binop (MINUS_EXPR, fold_convert (ctype, arg0),
-                      fold_convert (ctype, arg1));
+    return size_binop_loc (loc, MINUS_EXPR,
+                          fold_convert_loc (loc, ctype, arg0),
+                          fold_convert_loc (loc, ctype, arg1));
 
   /* If ARG0 is larger than ARG1, subtract and return the result in CTYPE.
      Otherwise, subtract the other way, convert to CTYPE (we know that can't
@@ -2138,11 +1494,14 @@ size_diffop (tree arg0, tree arg1)
   if (tree_int_cst_equal (arg0, arg1))
     return build_int_cst (ctype, 0);
   else if (tree_int_cst_lt (arg1, arg0))
-    return fold_convert (ctype, size_binop (MINUS_EXPR, arg0, arg1));
+    return fold_convert_loc (loc, ctype,
+                            size_binop_loc (loc, MINUS_EXPR, arg0, arg1));
   else
-    return size_binop (MINUS_EXPR, build_int_cst (ctype, 0),
-                      fold_convert (ctype, size_binop (MINUS_EXPR,
-                                                       arg1, arg0)));
+    return size_binop_loc (loc, MINUS_EXPR, build_int_cst (ctype, 0),
+                          fold_convert_loc (loc, ctype,
+                                            size_binop_loc (loc,
+                                                            MINUS_EXPR,
+                                                            arg1, arg0)));
 }
 \f
 /* A subroutine of fold_convert_const handling conversions of an
@@ -2155,25 +1514,8 @@ fold_convert_const_int_from_int (tree type, const_tree arg1)
 
   /* Given an integer constant, make new constant with new type,
      appropriately sign-extended or truncated.  */
-  t = force_fit_type_double (type, TREE_INT_CST_LOW (arg1),
-                            TREE_INT_CST_HIGH (arg1),
-                            /* Don't set the overflow when
-                               converting from a pointer,  */
-                            !POINTER_TYPE_P (TREE_TYPE (arg1))
-                            /* or to a sizetype with same signedness
-                               and the precision is unchanged.
-                               ???  sizetype is always sign-extended,
-                               but its signedness depends on the
-                               frontend.  Thus we see spurious overflows
-                               here if we do not check this.  */
-                            && !((TYPE_PRECISION (TREE_TYPE (arg1))
-                                  == TYPE_PRECISION (type))
-                                 && (TYPE_UNSIGNED (TREE_TYPE (arg1))
-                                     == TYPE_UNSIGNED (type))
-                                 && ((TREE_CODE (TREE_TYPE (arg1)) == INTEGER_TYPE
-                                      && TYPE_IS_SIZETYPE (TREE_TYPE (arg1)))
-                                     || (TREE_CODE (type) == INTEGER_TYPE
-                                         && TYPE_IS_SIZETYPE (type)))),
+  t = force_fit_type_double (type, tree_to_double_int (arg1),
+                            !POINTER_TYPE_P (TREE_TYPE (arg1)),
                             (TREE_INT_CST_HIGH (arg1) < 0
                              && (TYPE_UNSIGNED (type)
                                  < TYPE_UNSIGNED (TREE_TYPE (arg1))))
@@ -2200,7 +1542,7 @@ fold_convert_const_int_from_real (enum tree_code code, tree type, const_tree arg
      C and C++ standards that simply state that the behavior of
      FP-to-integer conversion is unspecified upon overflow.  */
 
-  HOST_WIDE_INT high, low;
+  double_int val;
   REAL_VALUE_TYPE r;
   REAL_VALUE_TYPE x = TREE_REAL_CST (arg1);
 
@@ -2218,8 +1560,7 @@ fold_convert_const_int_from_real (enum tree_code code, tree type, const_tree arg
   if (REAL_VALUE_ISNAN (r))
     {
       overflow = 1;
-      high = 0;
-      low = 0;
+      val = double_int_zero;
     }
 
   /* See if R is less than the lower bound or greater than the
@@ -2232,8 +1573,7 @@ fold_convert_const_int_from_real (enum tree_code code, tree type, const_tree arg
       if (REAL_VALUES_LESS (r, l))
        {
          overflow = 1;
-         high = TREE_INT_CST_HIGH (lt);
-         low = TREE_INT_CST_LOW (lt);
+         val = tree_to_double_int (lt);
        }
     }
 
@@ -2246,17 +1586,15 @@ fold_convert_const_int_from_real (enum tree_code code, tree type, const_tree arg
          if (REAL_VALUES_LESS (u, r))
            {
              overflow = 1;
-             high = TREE_INT_CST_HIGH (ut);
-             low = TREE_INT_CST_LOW (ut);
+             val = tree_to_double_int (ut);
            }
        }
     }
 
   if (! overflow)
-    REAL_VALUE_TO_INT (&low, &high, r);
+    real_to_integer2 ((HOST_WIDE_INT *) &val.low, &val.high, &r);
 
-  t = force_fit_type_double (type, low, high, -1,
-                            overflow | TREE_OVERFLOW (arg1));
+  t = force_fit_type_double (type, val, -1, overflow | TREE_OVERFLOW (arg1));
   return t;
 }
 
@@ -2275,39 +1613,32 @@ fold_convert_const_int_from_fixed (tree type, const_tree arg1)
   mode = TREE_FIXED_CST (arg1).mode;
   if (GET_MODE_FBIT (mode) < 2 * HOST_BITS_PER_WIDE_INT)
     {
-      lshift_double (temp.low, temp.high,
-                    - GET_MODE_FBIT (mode), 2 * HOST_BITS_PER_WIDE_INT,
-                    &temp.low, &temp.high, SIGNED_FIXED_POINT_MODE_P (mode));
+      temp = double_int_rshift (temp, GET_MODE_FBIT (mode),
+                               HOST_BITS_PER_DOUBLE_INT,
+                               SIGNED_FIXED_POINT_MODE_P (mode));
 
       /* Left shift temp to temp_trunc by fbit.  */
-      lshift_double (temp.low, temp.high,
-                    GET_MODE_FBIT (mode), 2 * HOST_BITS_PER_WIDE_INT,
-                    &temp_trunc.low, &temp_trunc.high,
-                    SIGNED_FIXED_POINT_MODE_P (mode));
+      temp_trunc = double_int_lshift (temp, GET_MODE_FBIT (mode),
+                                     HOST_BITS_PER_DOUBLE_INT,
+                                     SIGNED_FIXED_POINT_MODE_P (mode));
     }
   else
     {
-      temp.low = 0;
-      temp.high = 0;
-      temp_trunc.low = 0;
-      temp_trunc.high = 0;
+      temp = double_int_zero;
+      temp_trunc = double_int_zero;
     }
 
   /* If FIXED_CST is negative, we need to round the value toward 0.
      By checking if the fractional bits are not zero to add 1 to temp.  */
-  if (SIGNED_FIXED_POINT_MODE_P (mode) && temp_trunc.high < 0
+  if (SIGNED_FIXED_POINT_MODE_P (mode)
+      && double_int_negative_p (temp_trunc)
       && !double_int_equal_p (TREE_FIXED_CST (arg1).data, temp_trunc))
-    {
-      double_int one;
-      one.low = 1;
-      one.high = 0;
-      temp = double_int_add (temp, one);
-    }
+    temp = double_int_add (temp, double_int_one);
 
   /* Given a fixed-point constant, make new constant with new type,
      appropriately sign-extended or truncated.  */
-  t = force_fit_type_double (type, temp.low, temp.high, -1,
-                            (temp.high < 0
+  t = force_fit_type_double (type, temp, -1,
+                            (double_int_negative_p (temp)
                              && (TYPE_UNSIGNED (type)
                                  < TYPE_UNSIGNED (TREE_TYPE (arg1))))
                             | TREE_OVERFLOW (arg1));
@@ -2327,7 +1658,24 @@ fold_convert_const_real_from_real (tree type, const_tree arg1)
   real_convert (&value, TYPE_MODE (type), &TREE_REAL_CST (arg1));
   t = build_real (type, value);
 
-  TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1);
+  /* If converting an infinity or NAN to a representation that doesn't
+     have one, set the overflow bit so that we can produce some kind of
+     error message at the appropriate point if necessary.  It's not the
+     most user-friendly message, but it's better than nothing.  */
+  if (REAL_VALUE_ISINF (TREE_REAL_CST (arg1))
+      && !MODE_HAS_INFINITIES (TYPE_MODE (type)))
+    TREE_OVERFLOW (t) = 1;
+  else if (REAL_VALUE_ISNAN (TREE_REAL_CST (arg1))
+          && !MODE_HAS_NANS (TYPE_MODE (type)))
+    TREE_OVERFLOW (t) = 1;
+  /* Regular overflow, conversion produced an infinity in a mode that
+     can't represent them.  */
+  else if (!MODE_HAS_INFINITIES (TYPE_MODE (type))
+          && REAL_VALUE_ISINF (value)
+          && !REAL_VALUE_ISINF (TREE_REAL_CST (arg1)))
+    TREE_OVERFLOW (t) = 1;
+  else
+    TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1);
   return t;
 }
 
@@ -2455,16 +1803,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;
+  tree t;
 
-  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);
+  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.  */
@@ -2512,7 +1854,7 @@ fold_convertible_p (const_tree type, const_tree arg)
    simple conversions in preference to calling the front-end's convert.  */
 
 tree
-fold_convert (tree type, tree arg)
+fold_convert_loc (location_t loc, tree type, tree arg)
 {
   tree orig = TREE_TYPE (arg);
   tree tem;
@@ -2526,12 +1868,20 @@ fold_convert (tree type, tree arg)
     return error_mark_node;
 
   if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (orig))
-    return fold_build1 (NOP_EXPR, type, arg);
+    return fold_build1_loc (loc, NOP_EXPR, type, arg);
 
   switch (TREE_CODE (type))
     {
+    case POINTER_TYPE:
+    case REFERENCE_TYPE:
+      /* Handle conversions between pointers to different address spaces.  */
+      if (POINTER_TYPE_P (orig)
+         && (TYPE_ADDR_SPACE (TREE_TYPE (type))
+             != TYPE_ADDR_SPACE (TREE_TYPE (orig))))
+       return fold_build1_loc (loc, ADDR_SPACE_CONVERT_EXPR, type, arg);
+      /* fall through */
+
     case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
-    case POINTER_TYPE: case REFERENCE_TYPE:
     case OFFSET_TYPE:
       if (TREE_CODE (arg) == INTEGER_CST)
        {
@@ -2541,15 +1891,14 @@ fold_convert (tree type, tree arg)
        }
       if (INTEGRAL_TYPE_P (orig) || POINTER_TYPE_P (orig)
          || TREE_CODE (orig) == OFFSET_TYPE)
-        return fold_build1 (NOP_EXPR, type, arg);
+       return fold_build1_loc (loc, NOP_EXPR, type, arg);
       if (TREE_CODE (orig) == COMPLEX_TYPE)
-       {
-         tem = fold_build1 (REALPART_EXPR, TREE_TYPE (orig), arg);
-         return fold_convert (type, tem);
-       }
+       return fold_convert_loc (loc, type,
+                            fold_build1_loc (loc, REALPART_EXPR,
+                                         TREE_TYPE (orig), arg));
       gcc_assert (TREE_CODE (orig) == VECTOR_TYPE
                  && tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (orig)));
-      return fold_build1 (NOP_EXPR, type, arg);
+      return fold_build1_loc (loc, NOP_EXPR, type, arg);
 
     case REAL_TYPE:
       if (TREE_CODE (arg) == INTEGER_CST)
@@ -2576,17 +1925,17 @@ fold_convert (tree type, tree arg)
        case INTEGER_TYPE:
        case BOOLEAN_TYPE: case ENUMERAL_TYPE:
        case POINTER_TYPE: case REFERENCE_TYPE:
-         return fold_build1 (FLOAT_EXPR, type, arg);
+         return fold_build1_loc (loc, FLOAT_EXPR, type, arg);
 
        case REAL_TYPE:
-         return fold_build1 (NOP_EXPR, type, arg);
+         return fold_build1_loc (loc, NOP_EXPR, type, arg);
 
        case FIXED_POINT_TYPE:
-         return fold_build1 (FIXED_CONVERT_EXPR, type, arg);
+         return fold_build1_loc (loc, FIXED_CONVERT_EXPR, type, arg);
 
        case COMPLEX_TYPE:
-         tem = fold_build1 (REALPART_EXPR, TREE_TYPE (orig), arg);
-         return fold_convert (type, tem);
+         tem = fold_build1_loc (loc, REALPART_EXPR, TREE_TYPE (orig), arg);
+         return fold_convert_loc (loc, type, tem);
 
        default:
          gcc_unreachable ();
@@ -2598,7 +1947,7 @@ fold_convert (tree type, tree arg)
        {
          tem = fold_convert_const (FIXED_CONVERT_EXPR, type, arg);
          if (tem != NULL_TREE)
-           return tem;
+           goto fold_convert_exit;
        }
 
       switch (TREE_CODE (orig))
@@ -2608,11 +1957,11 @@ fold_convert (tree type, tree arg)
        case ENUMERAL_TYPE:
        case BOOLEAN_TYPE:
        case REAL_TYPE:
-         return fold_build1 (FIXED_CONVERT_EXPR, type, arg);
+         return fold_build1_loc (loc, FIXED_CONVERT_EXPR, type, arg);
 
        case COMPLEX_TYPE:
-         tem = fold_build1 (REALPART_EXPR, TREE_TYPE (orig), arg);
-         return fold_convert (type, tem);
+         tem = fold_build1_loc (loc, REALPART_EXPR, TREE_TYPE (orig), arg);
+         return fold_convert_loc (loc, type, tem);
 
        default:
          gcc_unreachable ();
@@ -2626,26 +1975,29 @@ fold_convert (tree type, tree arg)
        case POINTER_TYPE: case REFERENCE_TYPE:
        case REAL_TYPE:
        case FIXED_POINT_TYPE:
-         return build2 (COMPLEX_EXPR, type,
-                        fold_convert (TREE_TYPE (type), arg),
-                        fold_convert (TREE_TYPE (type), integer_zero_node));
+         return fold_build2_loc (loc, COMPLEX_EXPR, type,
+                             fold_convert_loc (loc, TREE_TYPE (type), arg),
+                             fold_convert_loc (loc, TREE_TYPE (type),
+                                           integer_zero_node));
        case COMPLEX_TYPE:
          {
            tree rpart, ipart;
 
            if (TREE_CODE (arg) == COMPLEX_EXPR)
              {
-               rpart = fold_convert (TREE_TYPE (type), TREE_OPERAND (arg, 0));
-               ipart = fold_convert (TREE_TYPE (type), TREE_OPERAND (arg, 1));
-               return fold_build2 (COMPLEX_EXPR, type, rpart, ipart);
+               rpart = fold_convert_loc (loc, TREE_TYPE (type),
+                                     TREE_OPERAND (arg, 0));
+               ipart = fold_convert_loc (loc, TREE_TYPE (type),
+                                     TREE_OPERAND (arg, 1));
+               return fold_build2_loc (loc, COMPLEX_EXPR, type, rpart, ipart);
              }
 
            arg = save_expr (arg);
-           rpart = fold_build1 (REALPART_EXPR, TREE_TYPE (orig), arg);
-           ipart = fold_build1 (IMAGPART_EXPR, TREE_TYPE (orig), arg);
-           rpart = fold_convert (TREE_TYPE (type), rpart);
-           ipart = fold_convert (TREE_TYPE (type), ipart);
-           return fold_build2 (COMPLEX_EXPR, type, rpart, ipart);
+           rpart = fold_build1_loc (loc, REALPART_EXPR, TREE_TYPE (orig), arg);
+           ipart = fold_build1_loc (loc, IMAGPART_EXPR, TREE_TYPE (orig), arg);
+           rpart = fold_convert_loc (loc, TREE_TYPE (type), rpart);
+           ipart = fold_convert_loc (loc, TREE_TYPE (type), ipart);
+           return fold_build2_loc (loc, COMPLEX_EXPR, type, rpart, ipart);
          }
 
        default:
@@ -2658,17 +2010,18 @@ fold_convert (tree type, tree arg)
       gcc_assert (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (orig)));
       gcc_assert (INTEGRAL_TYPE_P (orig) || POINTER_TYPE_P (orig)
                  || TREE_CODE (orig) == VECTOR_TYPE);
-      return fold_build1 (VIEW_CONVERT_EXPR, type, arg);
+      return fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, arg);
 
     case VOID_TYPE:
       tem = fold_ignored_result (arg);
-      if (TREE_CODE (tem) == MODIFY_EXPR)
-       return tem;
-      return fold_build1 (NOP_EXPR, type, tem);
+      return fold_build1_loc (loc, NOP_EXPR, type, tem);
 
     default:
       gcc_unreachable ();
     }
+ fold_convert_exit:
+  protected_set_expr_location_unshare (tem, loc);
+  return tem;
 }
 \f
 /* Return false if expr can be assumed not to be an lvalue, true
@@ -2688,9 +2041,8 @@ maybe_lvalue_p (const_tree x)
   case SSA_NAME:
 
   case COMPONENT_REF:
+  case MEM_REF:
   case INDIRECT_REF:
-  case ALIGN_INDIRECT_REF:
-  case MISALIGNED_INDIRECT_REF:
   case ARRAY_REF:
   case ARRAY_RANGE_REF:
   case BIT_FIELD_REF:
@@ -2708,8 +2060,6 @@ maybe_lvalue_p (const_tree x)
   case TARGET_EXPR:
   case COND_EXPR:
   case BIND_EXPR:
-  case MIN_EXPR:
-  case MAX_EXPR:
     break;
 
   default:
@@ -2725,7 +2075,7 @@ maybe_lvalue_p (const_tree x)
 /* Return an expr equal to X but certainly not valid as an lvalue.  */
 
 tree
-non_lvalue (tree x)
+non_lvalue_loc (location_t loc, tree x)
 {
   /* While we are in GIMPLE, NON_LVALUE_EXPR doesn't mean anything to
      us.  */
@@ -2734,7 +2084,7 @@ non_lvalue (tree x)
 
   if (! maybe_lvalue_p (x))
     return x;
-  return build1 (NON_LVALUE_EXPR, TREE_TYPE (x), x);
+  return build1_loc (loc, NON_LVALUE_EXPR, TREE_TYPE (x), x);
 }
 
 /* Nonzero means lvalues are limited to those valid in pedantic ANSI C.
@@ -2746,12 +2096,12 @@ int pedantic_lvalues;
    pedantic lvalue.  Otherwise, return X.  */
 
 static tree
-pedantic_non_lvalue (tree x)
+pedantic_non_lvalue_loc (location_t loc, tree x)
 {
   if (pedantic_lvalues)
-    return non_lvalue (x);
-  else
-    return x;
+    return non_lvalue_loc (loc, x);
+
+  return protected_set_expr_location_unshare (x, loc);
 }
 \f
 /* Given a tree comparison code, return the code that is the logical inverse
@@ -2928,7 +2278,8 @@ compcode_to_comparison (enum comparison_code code)
    if this makes the transformation invalid.  */
 
 tree
-combine_comparisons (enum tree_code code, enum tree_code lcode,
+combine_comparisons (location_t loc,
+                    enum tree_code code, enum tree_code lcode,
                     enum tree_code rcode, tree truth_type,
                     tree ll_arg, tree lr_arg)
 {
@@ -3005,7 +2356,7 @@ combine_comparisons (enum tree_code code, enum tree_code lcode,
       enum tree_code tcode;
 
       tcode = compcode_to_comparison ((enum comparison_code) compcode);
-      return fold_build2 (tcode, truth_type, ll_arg, lr_arg);
+      return fold_build2_loc (loc, tcode, truth_type, ll_arg, lr_arg);
     }
 }
 \f
@@ -3039,7 +2390,14 @@ int
 operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
 {
   /* If either is ERROR_MARK, they aren't equal.  */
-  if (TREE_CODE (arg0) == ERROR_MARK || TREE_CODE (arg1) == ERROR_MARK)
+  if (TREE_CODE (arg0) == ERROR_MARK || TREE_CODE (arg1) == ERROR_MARK
+      || TREE_TYPE (arg0) == error_mark_node
+      || TREE_TYPE (arg1) == error_mark_node)
+    return 0;
+
+  /* Similar, if either does not have a type (like a released SSA name), 
+     they aren't equal.  */
+  if (!TREE_TYPE (arg0) || !TREE_TYPE (arg1))
     return 0;
 
   /* Check equality of integer constants before bailing out due to
@@ -3056,6 +2414,12 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
       || POINTER_TYPE_P (TREE_TYPE (arg0)) != POINTER_TYPE_P (TREE_TYPE (arg1)))
     return 0;
 
+  /* We cannot consider pointers to different address space equal.  */
+  if (POINTER_TYPE_P (TREE_TYPE (arg0)) && POINTER_TYPE_P (TREE_TYPE (arg1))
+      && (TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (arg0)))
+         != TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (arg1)))))
+    return 0;
+
   /* If both types don't have the same precision, then it is not safe
      to strip NOPs.  */
   if (TYPE_PRECISION (TREE_TYPE (arg0)) != TYPE_PRECISION (TREE_TYPE (arg1)))
@@ -3094,9 +2458,12 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
      equal if they have no side effects.  If we have two identical
      expressions with side effects that should be treated the same due
      to the only side effects being identical SAVE_EXPR's, that will
-     be detected in the recursive calls below.  */
+     be detected in the recursive calls below.
+     If we are taking an invariant address of two identical objects
+     they are necessarily equal as well.  */
   if (arg0 == arg1 && ! (flags & OEP_ONLY_CONST)
       && (TREE_CODE (arg0) == SAVE_EXPR
+         || (flags & OEP_CONSTANT_ADDRESS_OF)
          || (! TREE_SIDE_EFFECTS (arg0) && ! TREE_SIDE_EFFECTS (arg1))))
     return 1;
 
@@ -3117,7 +2484,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
                                   TREE_REAL_CST (arg1)))
          return 1;
 
-       
+
        if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0))))
          {
            /* If we do not distinguish between signed and unsigned zero,
@@ -3159,7 +2526,8 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
 
       case ADDR_EXPR:
        return operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0),
-                               0);
+                               TREE_CONSTANT (arg0) && TREE_CONSTANT (arg1)
+                               ? OEP_CONSTANT_ADDRESS_OF : 0);
       default:
        break;
       }
@@ -3219,12 +2587,24 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
       switch (TREE_CODE (arg0))
        {
        case INDIRECT_REF:
-       case ALIGN_INDIRECT_REF:
-       case MISALIGNED_INDIRECT_REF:
        case REALPART_EXPR:
        case IMAGPART_EXPR:
          return OP_SAME (0);
 
+       case MEM_REF:
+         /* 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:
        case ARRAY_RANGE_REF:
          /* Operands 2 and 3 may be null.
@@ -3262,6 +2642,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:
@@ -3275,8 +2663,10 @@ 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:
          return 0;
        }
@@ -3495,7 +2885,8 @@ twoval_comparison_p (tree arg, tree *cval1, tree *cval2, int *save_p)
    NEW1 and OLD1.  */
 
 static tree
-eval_subst (tree arg, tree old0, tree new0, tree old1, tree new1)
+eval_subst (location_t loc, tree arg, tree old0, tree new0,
+           tree old1, tree new1)
 {
   tree type = TREE_TYPE (arg);
   enum tree_code code = TREE_CODE (arg);
@@ -3511,33 +2902,35 @@ eval_subst (tree arg, tree old0, tree new0, tree old1, tree new1)
   switch (tclass)
     {
     case tcc_unary:
-      return fold_build1 (code, type,
-                         eval_subst (TREE_OPERAND (arg, 0),
+      return fold_build1_loc (loc, code, type,
+                         eval_subst (loc, TREE_OPERAND (arg, 0),
                                      old0, new0, old1, new1));
 
     case tcc_binary:
-      return fold_build2 (code, type,
-                         eval_subst (TREE_OPERAND (arg, 0),
+      return fold_build2_loc (loc, code, type,
+                         eval_subst (loc, TREE_OPERAND (arg, 0),
                                      old0, new0, old1, new1),
-                         eval_subst (TREE_OPERAND (arg, 1),
+                         eval_subst (loc, TREE_OPERAND (arg, 1),
                                      old0, new0, old1, new1));
 
     case tcc_expression:
       switch (code)
        {
        case SAVE_EXPR:
-         return eval_subst (TREE_OPERAND (arg, 0), old0, new0, old1, new1);
+         return eval_subst (loc, TREE_OPERAND (arg, 0), old0, new0,
+                            old1, new1);
 
        case COMPOUND_EXPR:
-         return eval_subst (TREE_OPERAND (arg, 1), old0, new0, old1, new1);
+         return eval_subst (loc, TREE_OPERAND (arg, 1), old0, new0,
+                            old1, new1);
 
        case COND_EXPR:
-         return fold_build3 (code, type,
-                             eval_subst (TREE_OPERAND (arg, 0),
+         return fold_build3_loc (loc, code, type,
+                             eval_subst (loc, TREE_OPERAND (arg, 0),
                                          old0, new0, old1, new1),
-                             eval_subst (TREE_OPERAND (arg, 1),
+                             eval_subst (loc, TREE_OPERAND (arg, 1),
                                          old0, new0, old1, new1),
-                             eval_subst (TREE_OPERAND (arg, 2),
+                             eval_subst (loc, TREE_OPERAND (arg, 2),
                                          old0, new0, old1, new1));
        default:
          break;
@@ -3563,7 +2956,7 @@ eval_subst (tree arg, tree old0, tree new0, tree old1, tree new1)
        else if (arg1 == old1 || operand_equal_p (arg1, old1, 0))
          arg1 = new1;
 
-       return fold_build2 (code, type, arg0, arg1);
+       return fold_build2_loc (loc, code, type, arg0, arg1);
       }
 
     default:
@@ -3579,37 +2972,42 @@ eval_subst (tree arg, tree old0, tree new0, tree old1, tree new1)
    the conversion of RESULT to TYPE.  */
 
 tree
-omit_one_operand (tree type, tree result, tree omitted)
+omit_one_operand_loc (location_t loc, tree type, tree result, tree omitted)
 {
-  tree t = fold_convert (type, result);
+  tree t = fold_convert_loc (loc, type, 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))
-    return build1 (NOP_EXPR, void_type_node, fold_ignored_result (omitted));
+    return build1_loc (loc, NOP_EXPR, void_type_node,
+                      fold_ignored_result (omitted));
 
   if (TREE_SIDE_EFFECTS (omitted))
-    return build2 (COMPOUND_EXPR, type, fold_ignored_result (omitted), t);
+    return build2_loc (loc, COMPOUND_EXPR, type,
+                      fold_ignored_result (omitted), t);
 
-  return non_lvalue (t);
+  return non_lvalue_loc (loc, t);
 }
 
 /* Similar, but call pedantic_non_lvalue instead of non_lvalue.  */
 
 static tree
-pedantic_omit_one_operand (tree type, tree result, tree omitted)
+pedantic_omit_one_operand_loc (location_t loc, tree type, tree result,
+                              tree omitted)
 {
-  tree t = fold_convert (type, result);
+  tree t = fold_convert_loc (loc, type, 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))
-    return build1 (NOP_EXPR, void_type_node, fold_ignored_result (omitted));
+    return build1_loc (loc, NOP_EXPR, void_type_node,
+                      fold_ignored_result (omitted));
 
   if (TREE_SIDE_EFFECTS (omitted))
-    return build2 (COMPOUND_EXPR, type, fold_ignored_result (omitted), t);
+    return build2_loc (loc, COMPOUND_EXPR, type,
+                      fold_ignored_result (omitted), t);
 
-  return pedantic_non_lvalue (t);
+  return pedantic_non_lvalue_loc (loc, t);
 }
 
 /* Return a tree for the case when the result of an expression is RESULT
@@ -3622,16 +3020,17 @@ pedantic_omit_one_operand (tree type, tree result, tree omitted)
    just do the conversion of RESULT to TYPE.  */
 
 tree
-omit_two_operands (tree type, tree result, tree omitted1, tree omitted2)
+omit_two_operands_loc (location_t loc, tree type, tree result,
+                      tree omitted1, tree omitted2)
 {
-  tree t = fold_convert (type, result);
+  tree t = fold_convert_loc (loc, type, result);
 
   if (TREE_SIDE_EFFECTS (omitted2))
-    t = build2 (COMPOUND_EXPR, type, omitted2, t);
+    t = build2_loc (loc, COMPOUND_EXPR, type, omitted2, t);
   if (TREE_SIDE_EFFECTS (omitted1))
-    t = build2 (COMPOUND_EXPR, type, omitted1, t);
+    t = build2_loc (loc, COMPOUND_EXPR, type, omitted1, t);
 
-  return TREE_CODE (t) != COMPOUND_EXPR ? non_lvalue (t) : t;
+  return TREE_CODE (t) != COMPOUND_EXPR ? non_lvalue_loc (loc, t) : t;
 }
 
 \f
@@ -3643,10 +3042,11 @@ omit_two_operands (tree type, tree result, tree omitted1, tree omitted2)
    problems with the dominator optimizer.  */
 
 tree
-fold_truth_not_expr (tree arg)
+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;
 
   /* If this is a comparison, we can simply invert it, except for
      floating-point non-equality comparisons, in which case we just
@@ -3665,10 +3065,8 @@ fold_truth_not_expr (tree arg)
       if (code == ERROR_MARK)
        return NULL_TREE;
 
-      t = build2 (code, type, TREE_OPERAND (arg, 0), TREE_OPERAND (arg, 1));
-      if (EXPR_HAS_LOCATION (arg))
-       SET_EXPR_LOCATION (t, EXPR_LOCATION (arg));
-      return t;
+      return build2_loc (loc, code, type, TREE_OPERAND (arg, 0),
+                        TREE_OPERAND (arg, 1));
     }
 
   switch (code)
@@ -3677,16 +3075,18 @@ fold_truth_not_expr (tree arg)
       return constant_boolean_node (integer_zerop (arg), type);
 
     case TRUTH_AND_EXPR:
-      t = build2 (TRUTH_OR_EXPR, type,
-                 invert_truthvalue (TREE_OPERAND (arg, 0)),
-                 invert_truthvalue (TREE_OPERAND (arg, 1)));
-      break;
+      loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
+      loc2 = expr_location_or (TREE_OPERAND (arg, 1), loc);
+      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:
-      t = build2 (TRUTH_AND_EXPR, type,
-                 invert_truthvalue (TREE_OPERAND (arg, 0)),
-                 invert_truthvalue (TREE_OPERAND (arg, 1)));
-      break;
+      loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
+      loc2 = expr_location_or (TREE_OPERAND (arg, 1), loc);
+      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
@@ -3695,25 +3095,26 @@ fold_truth_not_expr (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 (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:
-      t = build2 (TRUTH_ORIF_EXPR, type,
-                 invert_truthvalue (TREE_OPERAND (arg, 0)),
-                 invert_truthvalue (TREE_OPERAND (arg, 1)));
-      break;
+      loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
+      loc2 = expr_location_or (TREE_OPERAND (arg, 1), loc);
+      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:
-      t = build2 (TRUTH_ANDIF_EXPR, type,
-                 invert_truthvalue (TREE_OPERAND (arg, 0)),
-                 invert_truthvalue (TREE_OPERAND (arg, 1)));
-      break;
+      loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
+      loc2 = expr_location_or (TREE_OPERAND (arg, 1), loc);
+      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);
@@ -3722,64 +3123,57 @@ fold_truth_not_expr (tree arg)
       {
        tree arg1 = TREE_OPERAND (arg, 1);
        tree arg2 = TREE_OPERAND (arg, 2);
+
+       loc1 = expr_location_or (TREE_OPERAND (arg, 1), loc);
+       loc2 = expr_location_or (TREE_OPERAND (arg, 2), loc);
+
        /* 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 (arg1),
-                   VOID_TYPE_P (TREE_TYPE (arg2))
-                   ? arg2 : invert_truthvalue (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:
-      t = build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg, 0),
-                 invert_truthvalue (TREE_OPERAND (arg, 1)));
-      break;
+      loc1 = expr_location_or (TREE_OPERAND (arg, 1), loc);
+      return build2_loc (loc, COMPOUND_EXPR, type,
+                        TREE_OPERAND (arg, 0),
+                        invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 1)));
 
     case NON_LVALUE_EXPR:
-      return invert_truthvalue (TREE_OPERAND (arg, 0));
+      loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
+      return invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0));
 
-    case NOP_EXPR:
+    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 ...  */
 
-    case CONVERT_EXPR:
     case FLOAT_EXPR:
-      t = build1 (TREE_CODE (arg), type,
-                 invert_truthvalue (TREE_OPERAND (arg, 0)));
-      break;
+      loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
+      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:
-      t = build1 (CLEANUP_POINT_EXPR, type,
-                 invert_truthvalue (TREE_OPERAND (arg, 0)));
-      break;
+      loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
+      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 && EXPR_HAS_LOCATION (arg))
-    SET_EXPR_LOCATION (t, EXPR_LOCATION (arg));
-
-  return t;
 }
 
 /* Return a simplified tree node for the truth-negation of ARG.  This
@@ -3790,16 +3184,16 @@ fold_truth_not_expr (tree arg)
    problems with the dominator optimizer.  */
 
 tree
-invert_truthvalue (tree arg)
+invert_truthvalue_loc (location_t loc, tree arg)
 {
   tree tem;
 
   if (TREE_CODE (arg) == ERROR_MARK)
     return arg;
 
-  tem = fold_truth_not_expr (arg);
+  tem = fold_truth_not_expr (loc, arg);
   if (!tem)
-    tem = build1 (TRUTH_NOT_EXPR, TREE_TYPE (arg), arg);
+    tem = build1_loc (loc, TRUTH_NOT_EXPR, TREE_TYPE (arg), arg);
 
   return tem;
 }
@@ -3814,7 +3208,8 @@ invert_truthvalue (tree arg)
    If this optimization cannot be done, 0 will be returned.  */
 
 static tree
-distribute_bit_expr (enum tree_code code, tree type, tree arg0, tree arg1)
+distribute_bit_expr (location_t loc, enum tree_code code, tree type,
+                    tree arg0, tree arg1)
 {
   tree common;
   tree left, right;
@@ -3852,17 +3247,18 @@ distribute_bit_expr (enum tree_code code, tree type, tree arg0, tree arg1)
   else
     return 0;
 
-  common = fold_convert (type, common);
-  left = fold_convert (type, left);
-  right = fold_convert (type, right);
-  return fold_build2 (TREE_CODE (arg0), type, common,
-                     fold_build2 (code, type, left, right));
+  common = fold_convert_loc (loc, type, common);
+  left = fold_convert_loc (loc, type, left);
+  right = fold_convert_loc (loc, type, right);
+  return fold_build2_loc (loc, TREE_CODE (arg0), type, common,
+                     fold_build2_loc (loc, code, type, left, right));
 }
 
 /* Knowing that ARG0 and ARG1 are both RDIV_EXPRs, simplify a binary operation
    with code CODE.  This optimization is unsafe.  */
 static tree
-distribute_real_division (enum tree_code code, tree type, tree arg0, tree arg1)
+distribute_real_division (location_t loc, enum tree_code code, tree type,
+                         tree arg0, tree arg1)
 {
   bool mul0 = TREE_CODE (arg0) == MULT_EXPR;
   bool mul1 = TREE_CODE (arg1) == MULT_EXPR;
@@ -3871,8 +3267,8 @@ distribute_real_division (enum tree_code code, tree type, tree arg0, tree arg1)
   if (mul0 == mul1
       && operand_equal_p (TREE_OPERAND (arg0, 1),
                       TREE_OPERAND (arg1, 1), 0))
-    return fold_build2 (mul0 ? MULT_EXPR : RDIV_EXPR, type,
-                       fold_build2 (code, type,
+    return fold_build2_loc (loc, mul0 ? MULT_EXPR : RDIV_EXPR, type,
+                       fold_build2_loc (loc, code, type,
                                     TREE_OPERAND (arg0, 0),
                                     TREE_OPERAND (arg1, 0)),
                        TREE_OPERAND (arg0, 1));
@@ -3891,7 +3287,7 @@ distribute_real_division (enum tree_code code, tree type, tree arg0, tree arg1)
       if (!mul1)
         real_arithmetic (&r1, RDIV_EXPR, &dconst1, &r1);
       real_arithmetic (&r0, code, &r0, &r1);
-      return fold_build2 (MULT_EXPR, type,
+      return fold_build2_loc (loc, MULT_EXPR, type,
                          TREE_OPERAND (arg0, 0),
                          build_real (type, r0));
     }
@@ -3903,8 +3299,8 @@ distribute_real_division (enum tree_code code, tree type, tree arg0, tree arg1)
    starting at BITPOS.  The field is unsigned if UNSIGNEDP is nonzero.  */
 
 static tree
-make_bit_field_ref (tree inner, tree type, HOST_WIDE_INT bitsize,
-                   HOST_WIDE_INT bitpos, int unsignedp)
+make_bit_field_ref (location_t loc, tree inner, tree type,
+                   HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos, int unsignedp)
 {
   tree result, bftype;
 
@@ -3913,9 +3309,9 @@ make_bit_field_ref (tree inner, tree type, HOST_WIDE_INT bitsize,
       tree size = TYPE_SIZE (TREE_TYPE (inner));
       if ((INTEGRAL_TYPE_P (TREE_TYPE (inner))
           || POINTER_TYPE_P (TREE_TYPE (inner)))
-         && host_integerp (size, 0) 
+         && host_integerp (size, 0)
          && tree_low_cst (size, 0) == bitsize)
-       return fold_convert (type, inner);
+       return fold_convert_loc (loc, type, inner);
     }
 
   bftype = type;
@@ -3923,11 +3319,11 @@ make_bit_field_ref (tree inner, tree type, HOST_WIDE_INT bitsize,
       || TYPE_UNSIGNED (bftype) == !unsignedp)
     bftype = build_nonstandard_integer_type (bitsize, 0);
 
-  result = build3 (BIT_FIELD_REF, bftype, inner,
-                  size_int (bitsize), bitsize_int (bitpos));
+  result = build3_loc (loc, BIT_FIELD_REF, bftype, inner,
+                      size_int (bitsize), bitsize_int (bitpos));
 
   if (bftype != type)
-    result = fold_convert (type, result);
+    result = fold_convert_loc (loc, type, result);
 
   return result;
 }
@@ -3953,8 +3349,8 @@ make_bit_field_ref (tree inner, tree type, HOST_WIDE_INT bitsize,
    tree.  Otherwise we return zero.  */
 
 static tree
-optimize_bit_field_compare (enum tree_code code, tree compare_type,
-                           tree lhs, tree rhs)
+optimize_bit_field_compare (location_t loc, enum tree_code code,
+                           tree compare_type, tree lhs, tree rhs)
 {
   HOST_WIDE_INT lbitpos, lbitsize, rbitpos, rbitsize, nbitpos, nbitsize;
   tree type = TREE_TYPE (lhs);
@@ -3993,11 +3389,16 @@ optimize_bit_field_compare (enum tree_code code, tree compare_type,
 
   /* See if we can find a mode to refer to this field.  We should be able to,
      but fail if we can't.  */
-  nmode = get_best_mode (lbitsize, lbitpos,
-                        const_p ? TYPE_ALIGN (TREE_TYPE (linner))
-                        : MIN (TYPE_ALIGN (TREE_TYPE (linner)),
-                               TYPE_ALIGN (TREE_TYPE (rinner))),
-                        word_mode, lvolatilep || rvolatilep);
+  if (lvolatilep
+      && GET_MODE_BITSIZE (lmode) > 0
+      && flag_strict_volatile_bitfields > 0)
+    nmode = lmode;
+  else
+    nmode = get_best_mode (lbitsize, lbitpos,
+                          const_p ? TYPE_ALIGN (TREE_TYPE (linner))
+                          : MIN (TYPE_ALIGN (TREE_TYPE (linner)),
+                                 TYPE_ALIGN (TREE_TYPE (rinner))),
+                          word_mode, lvolatilep || rvolatilep);
   if (nmode == VOIDmode)
     return 0;
 
@@ -4020,22 +3421,22 @@ optimize_bit_field_compare (enum tree_code code, tree compare_type,
 
   /* Make the mask to be used against the extracted field.  */
   mask = build_int_cst_type (unsigned_type, -1);
-  mask = const_binop (LSHIFT_EXPR, mask, size_int (nbitsize - lbitsize), 0);
+  mask = const_binop (LSHIFT_EXPR, mask, size_int (nbitsize - lbitsize));
   mask = const_binop (RSHIFT_EXPR, mask,
-                     size_int (nbitsize - lbitsize - lbitpos), 0);
+                     size_int (nbitsize - lbitsize - lbitpos));
 
   if (! const_p)
     /* If not comparing with constant, just rework the comparison
        and return.  */
-    return fold_build2 (code, compare_type,
-                       fold_build2 (BIT_AND_EXPR, unsigned_type,
-                                    make_bit_field_ref (linner,
+    return fold_build2_loc (loc, code, compare_type,
+                       fold_build2_loc (loc, BIT_AND_EXPR, unsigned_type,
+                                    make_bit_field_ref (loc, linner,
                                                         unsigned_type,
                                                         nbitsize, nbitpos,
                                                         1),
                                     mask),
-                       fold_build2 (BIT_AND_EXPR, unsigned_type,
-                                    make_bit_field_ref (rinner,
+                       fold_build2_loc (loc, BIT_AND_EXPR, unsigned_type,
+                                    make_bit_field_ref (loc, rinner,
                                                         unsigned_type,
                                                         nbitsize, nbitpos,
                                                         1),
@@ -4053,8 +3454,9 @@ optimize_bit_field_compare (enum tree_code code, tree compare_type,
   if (lunsignedp)
     {
       if (! integer_zerop (const_binop (RSHIFT_EXPR,
-                                       fold_convert (unsigned_type, rhs),
-                                       size_int (lbitsize), 0)))
+                                       fold_convert_loc (loc,
+                                                         unsigned_type, rhs),
+                                       size_int (lbitsize))))
        {
          warning (0, "comparison is always %d due to width of bit-field",
                   code == NE_EXPR);
@@ -4063,8 +3465,9 @@ optimize_bit_field_compare (enum tree_code code, tree compare_type,
     }
   else
     {
-      tree tem = const_binop (RSHIFT_EXPR, fold_convert (signed_type, rhs),
-                             size_int (lbitsize - 1), 0);
+      tree tem = const_binop (RSHIFT_EXPR,
+                             fold_convert_loc (loc, signed_type, rhs),
+                             size_int (lbitsize - 1));
       if (! integer_zerop (tem) && ! integer_all_onesp (tem))
        {
          warning (0, "comparison is always %d due to width of bit-field",
@@ -4083,7 +3486,7 @@ optimize_bit_field_compare (enum tree_code code, tree compare_type,
   /* Make a new bitfield reference, shift the constant over the
      appropriate number of bits and mask it with the computed mask
      (in case this was a signed field).  If we changed it, make a new one.  */
-  lhs = make_bit_field_ref (linner, unsigned_type, nbitsize, nbitpos, 1);
+  lhs = make_bit_field_ref (loc, linner, unsigned_type, nbitsize, nbitpos, 1);
   if (lvolatilep)
     {
       TREE_SIDE_EFFECTS (lhs) = 1;
@@ -4092,13 +3495,13 @@ optimize_bit_field_compare (enum tree_code code, tree compare_type,
 
   rhs = const_binop (BIT_AND_EXPR,
                     const_binop (LSHIFT_EXPR,
-                                 fold_convert (unsigned_type, rhs),
-                                 size_int (lbitpos), 0),
-                    mask, 0);
+                                 fold_convert_loc (loc, unsigned_type, rhs),
+                                 size_int (lbitpos)),
+                    mask);
 
-  return build2 (code, compare_type,
-                build2 (BIT_AND_EXPR, unsigned_type, lhs, mask),
-                rhs);
+  lhs = build2_loc (loc, code, compare_type,
+                   build2 (BIT_AND_EXPR, unsigned_type, lhs, mask), rhs);
+  return lhs;
 }
 \f
 /* Subroutine for fold_truthop: decode a field reference.
@@ -4125,7 +3528,7 @@ optimize_bit_field_compare (enum tree_code code, tree compare_type,
    do anything with.  */
 
 static tree
-decode_field_reference (tree exp, HOST_WIDE_INT *pbitsize,
+decode_field_reference (location_t loc, tree exp, HOST_WIDE_INT *pbitsize,
                        HOST_WIDE_INT *pbitpos, enum machine_mode *pmode,
                        int *punsignedp, int *pvolatilep,
                        tree *pmask, tree *pand_mask)
@@ -4178,13 +3581,13 @@ decode_field_reference (tree exp, HOST_WIDE_INT *pbitsize,
 
   mask = build_int_cst_type (unsigned_type, -1);
 
-  mask = const_binop (LSHIFT_EXPR, mask, size_int (precision - *pbitsize), 0);
-  mask = const_binop (RSHIFT_EXPR, mask, size_int (precision - *pbitsize), 0);
+  mask = const_binop (LSHIFT_EXPR, mask, size_int (precision - *pbitsize));
+  mask = const_binop (RSHIFT_EXPR, mask, size_int (precision - *pbitsize));
 
   /* Merge it with the mask we found in the BIT_AND_EXPR, if any.  */
   if (and_mask != 0)
-    mask = fold_build2 (BIT_AND_EXPR, unsigned_type,
-                       fold_convert (unsigned_type, and_mask), mask);
+    mask = fold_build2_loc (loc, BIT_AND_EXPR, unsigned_type,
+                       fold_convert_loc (loc, unsigned_type, and_mask), mask);
 
   *pmask = mask;
   *pand_mask = and_mask;
@@ -4207,9 +3610,8 @@ all_ones_mask_p (const_tree mask, int size)
     tree_int_cst_equal (mask,
                        const_binop (RSHIFT_EXPR,
                                     const_binop (LSHIFT_EXPR, tmask,
-                                                 size_int (precision - size),
-                                                 0),
-                                    size_int (precision - size), 0));
+                                                 size_int (precision - size)),
+                                    size_int (precision - size)));
 }
 
 /* Subroutine for fold: determine if VAL is the INTEGER_CONST that
@@ -4398,7 +3800,7 @@ range_binop (enum tree_code code, tree type, tree arg0, int upper0_p,
    because signed overflow is undefined; otherwise, do not change
    *STRICT_OVERFLOW_P.  */
 
-static tree
+tree
 make_range (tree exp, int *pin_p, tree *plow, tree *phigh,
            bool *strict_overflow_p)
 {
@@ -4407,6 +3809,7 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh,
   tree exp_type = NULL_TREE, arg0_type = NULL_TREE;
   int in_p, n_in_p;
   tree low, high, n_low, n_high;
+  location_t loc = EXPR_LOCATION (exp);
 
   /* Start with simply saying "EXP != 0" and then look at the code of EXP
      and see if we can refine the range.  Some of the cases below may not
@@ -4517,14 +3920,14 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh,
          n_high = range_binop (MINUS_EXPR, exp_type,
                                build_int_cst (exp_type, 0),
                                0, low, 0);
-         low = n_low, high = n_high;
-         exp = arg0;
-         continue;
+         if (n_high != 0 && TREE_OVERFLOW (n_high))
+           break;
+         goto normalize;
 
        case BIT_NOT_EXPR:
          /* ~ X -> -X - 1  */
-         exp = build2 (MINUS_EXPR, exp_type, negate_expr (arg0),
-                       build_int_cst (exp_type, 1));
+         exp = build2_loc (loc, MINUS_EXPR, exp_type, negate_expr (arg0),
+                           build_int_cst (exp_type, 1));
          continue;
 
        case PLUS_EXPR:  case MINUS_EXPR:
@@ -4552,6 +3955,7 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh,
          if (TYPE_OVERFLOW_UNDEFINED (arg0_type))
            *strict_overflow_p = true;
 
+       normalize:
          /* Check for an unsigned range which has wrapped around the maximum
             value thus making n_high < n_low, and normalize it.  */
          if (n_low && n_high && tree_int_cst_lt (n_high, n_low))
@@ -4589,10 +3993,10 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh,
          n_low = low, n_high = high;
 
          if (n_low != 0)
-           n_low = fold_convert (arg0_type, n_low);
+           n_low = fold_convert_loc (loc, arg0_type, n_low);
 
          if (n_high != 0)
-           n_high = fold_convert (arg0_type, n_high);
+           n_high = fold_convert_loc (loc, arg0_type, n_high);
 
 
          /* If we're converting arg0 from an unsigned type, to exp,
@@ -4626,9 +4030,9 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh,
                : TYPE_MAX_VALUE (arg0_type);
 
              if (TYPE_PRECISION (exp_type) == TYPE_PRECISION (arg0_type))
-               high_positive = fold_build2 (RSHIFT_EXPR, arg0_type,
-                                            fold_convert (arg0_type,
-                                                          high_positive),
+               high_positive = fold_build2_loc (loc, RSHIFT_EXPR, arg0_type,
+                                            fold_convert_loc (loc, arg0_type,
+                                                              high_positive),
                                             build_int_cst (arg0_type, 1));
 
              /* If the low bound is specified, "and" the range with the
@@ -4638,8 +4042,8 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh,
                {
                  if (! merge_ranges (&n_in_p, &n_low, &n_high,
                                      1, n_low, n_high, 1,
-                                     fold_convert (arg0_type,
-                                                   integer_zero_node),
+                                     fold_convert_loc (loc, arg0_type,
+                                                       integer_zero_node),
                                      high_positive))
                    break;
 
@@ -4651,8 +4055,8 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh,
                     that will be interpreted as negative.  */
                  if (! merge_ranges (&n_in_p, &n_low, &n_high,
                                      0, n_low, n_high, 1,
-                                     fold_convert (arg0_type,
-                                                   integer_zero_node),
+                                     fold_convert_loc (loc, arg0_type,
+                                                       integer_zero_node),
                                      high_positive))
                    break;
 
@@ -4690,11 +4094,11 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh,
    type, TYPE, return an expression to test if EXP is in (or out of, depending
    on IN_P) the range.  Return 0 if the test couldn't be created.  */
 
-static tree
-build_range_check (tree type, tree exp, int in_p, tree low, tree high)
+tree
+build_range_check (location_t loc, tree type, tree exp, int in_p,
+                  tree low, tree high)
 {
   tree etype = TREE_TYPE (exp), value;
-  enum tree_code code;
 
 #ifdef HAVE_canonicalize_funcptr_for_compare
   /* Disable this optimization for function pointer expressions
@@ -4707,9 +4111,9 @@ build_range_check (tree type, tree exp, int in_p, tree low, tree high)
 
   if (! in_p)
     {
-      value = build_range_check (type, exp, 1, low, high);
+      value = build_range_check (loc, type, exp, 1, low, high);
       if (value != 0)
-        return invert_truthvalue (value);
+        return invert_truthvalue_loc (loc, value);
 
       return 0;
     }
@@ -4718,26 +4122,26 @@ build_range_check (tree type, tree exp, int in_p, tree low, tree high)
     return build_int_cst (type, 1);
 
   if (low == 0)
-    return fold_build2 (LE_EXPR, type, exp,
-                       fold_convert (etype, high));
+    return fold_build2_loc (loc, LE_EXPR, type, exp,
+                       fold_convert_loc (loc, etype, high));
 
   if (high == 0)
-    return fold_build2 (GE_EXPR, type, exp,
-                       fold_convert (etype, low));
+    return fold_build2_loc (loc, GE_EXPR, type, exp,
+                       fold_convert_loc (loc, etype, low));
 
   if (operand_equal_p (low, high, 0))
-    return fold_build2 (EQ_EXPR, type, exp,
-                       fold_convert (etype, low));
+    return fold_build2_loc (loc, EQ_EXPR, type, exp,
+                       fold_convert_loc (loc, etype, low));
 
   if (integer_zerop (low))
     {
       if (! TYPE_UNSIGNED (etype))
        {
          etype = unsigned_type_for (etype);
-         high = fold_convert (etype, high);
-         exp = fold_convert (etype, exp);
+         high = fold_convert_loc (loc, etype, high);
+         exp = fold_convert_loc (loc, etype, exp);
        }
-      return build_range_check (type, exp, 1, 0, high);
+      return build_range_check (loc, type, exp, 1, 0, high);
     }
 
   /* Optimize (c>=1) && (c<=127) into (signed char)c > 0.  */
@@ -4769,53 +4173,32 @@ build_range_check (tree type, tree exp, int in_p, tree low, tree high)
                  = build_nonstandard_integer_type (TYPE_PRECISION (etype), 0);
              else
                etype = signed_etype;
-             exp = fold_convert (etype, exp);
+             exp = fold_convert_loc (loc, etype, exp);
            }
-         return fold_build2 (GT_EXPR, type, exp,
+         return fold_build2_loc (loc, GT_EXPR, type, exp,
                              build_int_cst (etype, 0));
        }
     }
 
   /* Optimize (c>=low) && (c<=high) into (c-low>=0) && (c-low<=high-low).
-     This requires wrap-around arithmetics for the type of the expression.  */
-  code = TREE_CODE (etype);
-  switch (code)
-    {
-    case INTEGER_TYPE:
-    case ENUMERAL_TYPE:
-    case BOOLEAN_TYPE:
-      /* There is no requirement that LOW be within the range of ETYPE
-        if the latter is a subtype.  It must, however, be within the base
-        type of ETYPE.  So be sure we do the subtraction in that type.  */
-      if (code == INTEGER_TYPE && TREE_TYPE (etype))
-       {
-         etype = TREE_TYPE (etype);
-         /* But not in an enumeral or boolean type though.  */
-         code = TREE_CODE (etype);
-       }
+     This requires wrap-around arithmetics for the type of the expression.
+     First make sure that arithmetics in this type is valid, then make sure
+     that it wraps around.  */
+  if (TREE_CODE (etype) == ENUMERAL_TYPE || TREE_CODE (etype) == BOOLEAN_TYPE)
+    etype = lang_hooks.types.type_for_size (TYPE_PRECISION (etype),
+                                           TYPE_UNSIGNED (etype));
 
-      if (code != INTEGER_TYPE)
-       etype = lang_hooks.types.type_for_size (TYPE_PRECISION (etype),
-                                               TYPE_UNSIGNED (etype));
-      break;
-
-    default:
-      break;
-    }
-
-  /* If we don't have wrap-around arithmetics upfront, try to force it.  */
-  if (TREE_CODE (etype) == INTEGER_TYPE
-      && !TYPE_OVERFLOW_WRAPS (etype))
+  if (TREE_CODE (etype) == INTEGER_TYPE && !TYPE_OVERFLOW_WRAPS (etype))
     {
       tree utype, minv, maxv;
 
       /* Check if (unsigned) INT_MAX + 1 == (unsigned) INT_MIN
         for the type in question, as we rely on this here.  */
       utype = unsigned_type_for (etype);
-      maxv = fold_convert (utype, TYPE_MAX_VALUE (etype));
+      maxv = fold_convert_loc (loc, utype, TYPE_MAX_VALUE (etype));
       maxv = range_binop (PLUS_EXPR, NULL_TREE, maxv, 1,
                          integer_one_node, 1);
-      minv = fold_convert (utype, TYPE_MIN_VALUE (etype));
+      minv = fold_convert_loc (loc, utype, TYPE_MIN_VALUE (etype));
 
       if (integer_zerop (range_binop (NE_EXPR, integer_type_node,
                                      minv, 1, maxv, 1)))
@@ -4824,29 +4207,30 @@ build_range_check (tree type, tree exp, int in_p, tree low, tree high)
        return 0;
     }
 
-  high = fold_convert (etype, high);
-  low = fold_convert (etype, low);
-  exp = fold_convert (etype, exp);
+  high = fold_convert_loc (loc, etype, high);
+  low = fold_convert_loc (loc, etype, low);
+  exp = fold_convert_loc (loc, etype, exp);
 
-  value = const_binop (MINUS_EXPR, high, low, 0);
+  value = const_binop (MINUS_EXPR, high, low);
 
 
   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),
+         low = fold_convert_loc (loc, sizetype, low);
+         low = fold_build1_loc (loc, NEGATE_EXPR, sizetype, low);
+          return build_range_check (loc, type,
+                                   fold_build2_loc (loc, 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),
+    return build_range_check (loc, type,
+                             fold_build2_loc (loc, MINUS_EXPR, etype, exp, low),
                              1, build_int_cst (etype, 0), value);
 
   return 0;
@@ -4883,7 +4267,7 @@ range_successor (tree val)
 /* Given two ranges, see if we can merge them into one.  Return 1 if we
    can, 0 if we can't.  Set the output range into the specified parameters.  */
 
-static int
+bool
 merge_ranges (int *pin_p, tree *plow, tree *phigh, int in0_p, tree low0,
              tree high0, int in1_p, tree low1, tree high1)
 {
@@ -5101,7 +4485,8 @@ merge_ranges (int *pin_p, tree *plow, tree *phigh, int in0_p, tree low0,
    anymore, or NULL_TREE if no folding opportunity is found.  */
 
 static tree
-fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
+fold_cond_expr_with_comparison (location_t loc, tree type,
+                               tree arg0, tree arg1, tree arg2)
 {
   enum tree_code comp_code = TREE_CODE (arg0);
   tree arg00 = TREE_OPERAND (arg0, 0);
@@ -5149,11 +4534,13 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
       {
       case EQ_EXPR:
       case UNEQ_EXPR:
-       tem = fold_convert (arg1_type, arg1);
-       return pedantic_non_lvalue (fold_convert (type, negate_expr (tem)));
+       tem = fold_convert_loc (loc, arg1_type, arg1);
+       return pedantic_non_lvalue_loc (loc,
+                                   fold_convert_loc (loc, type,
+                                                 negate_expr (tem)));
       case NE_EXPR:
       case LTGT_EXPR:
-       return pedantic_non_lvalue (fold_convert (type, arg1));
+       return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1));
       case UNGE_EXPR:
       case UNGT_EXPR:
        if (flag_trapping_math)
@@ -5162,10 +4549,10 @@ 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 (signed_type_for
+         arg1 = fold_convert_loc (loc, signed_type_for
                               (TREE_TYPE (arg1)), arg1);
-       tem = fold_build1 (ABS_EXPR, TREE_TYPE (arg1), arg1);
-       return pedantic_non_lvalue (fold_convert (type, tem));
+       tem = fold_build1_loc (loc, ABS_EXPR, TREE_TYPE (arg1), arg1);
+       return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, tem));
       case UNLE_EXPR:
       case UNLT_EXPR:
        if (flag_trapping_math)
@@ -5173,10 +4560,10 @@ 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 (signed_type_for
+         arg1 = fold_convert_loc (loc, signed_type_for
                               (TREE_TYPE (arg1)), arg1);
-       tem = fold_build1 (ABS_EXPR, TREE_TYPE (arg1), arg1);
-       return negate_expr (fold_convert (type, tem));
+       tem = fold_build1_loc (loc, ABS_EXPR, TREE_TYPE (arg1), arg1);
+       return negate_expr (fold_convert_loc (loc, type, tem));
       default:
        gcc_assert (TREE_CODE_CLASS (comp_code) == tcc_comparison);
        break;
@@ -5191,7 +4578,7 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
       && integer_zerop (arg01) && integer_zerop (arg2))
     {
       if (comp_code == NE_EXPR)
-       return pedantic_non_lvalue (fold_convert (type, arg1));
+       return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1));
       else if (comp_code == EQ_EXPR)
        return build_int_cst (type, 0);
     }
@@ -5247,9 +4634,9 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
       switch (comp_code)
        {
        case EQ_EXPR:
-         return pedantic_non_lvalue (fold_convert (type, arg2));
+         return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, arg2));
        case NE_EXPR:
-         return pedantic_non_lvalue (fold_convert (type, arg1));
+         return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1));
        case LE_EXPR:
        case LT_EXPR:
        case UNLE_EXPR:
@@ -5260,12 +4647,14 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
             corresponding COND_EXPR.  */
          if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
            {
-             comp_op0 = fold_convert (comp_type, comp_op0);
-             comp_op1 = fold_convert (comp_type, comp_op1);
+             comp_op0 = fold_convert_loc (loc, comp_type, comp_op0);
+             comp_op1 = fold_convert_loc (loc, comp_type, comp_op1);
              tem = (comp_code == LE_EXPR || comp_code == UNLE_EXPR)
-                   ? fold_build2 (MIN_EXPR, comp_type, comp_op0, comp_op1)
-                   : fold_build2 (MIN_EXPR, comp_type, comp_op1, comp_op0);
-             return pedantic_non_lvalue (fold_convert (type, tem));
+                   ? fold_build2_loc (loc, MIN_EXPR, comp_type, comp_op0, comp_op1)
+                   : fold_build2_loc (loc, MIN_EXPR, comp_type,
+                                  comp_op1, comp_op0);
+             return pedantic_non_lvalue_loc (loc,
+                                         fold_convert_loc (loc, type, tem));
            }
          break;
        case GE_EXPR:
@@ -5274,21 +4663,25 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
        case UNGT_EXPR:
          if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
            {
-             comp_op0 = fold_convert (comp_type, comp_op0);
-             comp_op1 = fold_convert (comp_type, comp_op1);
+             comp_op0 = fold_convert_loc (loc, comp_type, comp_op0);
+             comp_op1 = fold_convert_loc (loc, comp_type, comp_op1);
              tem = (comp_code == GE_EXPR || comp_code == UNGE_EXPR)
-                   ? fold_build2 (MAX_EXPR, comp_type, comp_op0, comp_op1)
-                   : fold_build2 (MAX_EXPR, comp_type, comp_op1, comp_op0);
-             return pedantic_non_lvalue (fold_convert (type, tem));
+                   ? fold_build2_loc (loc, MAX_EXPR, comp_type, comp_op0, comp_op1)
+                   : fold_build2_loc (loc, MAX_EXPR, comp_type,
+                                  comp_op1, comp_op0);
+             return pedantic_non_lvalue_loc (loc,
+                                         fold_convert_loc (loc, type, tem));
            }
          break;
        case UNEQ_EXPR:
          if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
-           return pedantic_non_lvalue (fold_convert (type, arg2));
+           return pedantic_non_lvalue_loc (loc,
+                                       fold_convert_loc (loc, type, arg2));
          break;
        case LTGT_EXPR:
          if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
-           return pedantic_non_lvalue (fold_convert (type, arg1));
+           return pedantic_non_lvalue_loc (loc,
+                                       fold_convert_loc (loc, type, arg1));
          break;
        default:
          gcc_assert (TREE_CODE_CLASS (comp_code) == tcc_comparison);
@@ -5308,36 +4701,46 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
     switch (comp_code)
       {
       case EQ_EXPR:
+       if (TREE_CODE (arg1) == INTEGER_CST)
+         break;
        /* We can replace A with C1 in this case.  */
-       arg1 = fold_convert (type, arg01);
-       return fold_build3 (COND_EXPR, type, arg0, arg1, arg2);
+       arg1 = fold_convert_loc (loc, type, arg01);
+       return fold_build3_loc (loc, COND_EXPR, type, arg0, arg1, arg2);
 
       case LT_EXPR:
-       /* If C1 is C2 + 1, this is min(A, C2).  */
+       /* If C1 is C2 + 1, this is min(A, C2), but use ARG00's type for
+          MIN_EXPR, to preserve the signedness of the comparison.  */
        if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type),
                               OEP_ONLY_CONST)
            && operand_equal_p (arg01,
                                const_binop (PLUS_EXPR, arg2,
-                                            build_int_cst (type, 1), 0),
+                                            build_int_cst (type, 1)),
                                OEP_ONLY_CONST))
-         return pedantic_non_lvalue (fold_build2 (MIN_EXPR,
-                                                  type,
-                                                  fold_convert (type, arg1),
-                                                  arg2));
+         {
+           tem = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (arg00), arg00,
+                                  fold_convert_loc (loc, TREE_TYPE (arg00),
+                                                    arg2));
+           return pedantic_non_lvalue_loc (loc,
+                                           fold_convert_loc (loc, type, tem));
+         }
        break;
 
       case LE_EXPR:
-       /* If C1 is C2 - 1, this is min(A, C2).  */
+       /* If C1 is C2 - 1, this is min(A, C2), with the same care
+          as above.  */
        if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type),
                               OEP_ONLY_CONST)
            && operand_equal_p (arg01,
                                const_binop (MINUS_EXPR, arg2,
-                                            build_int_cst (type, 1), 0),
+                                            build_int_cst (type, 1)),
                                OEP_ONLY_CONST))
-         return pedantic_non_lvalue (fold_build2 (MIN_EXPR,
-                                                  type,
-                                                  fold_convert (type, arg1),
-                                                  arg2));
+         {
+           tem = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (arg00), arg00,
+                                  fold_convert_loc (loc, TREE_TYPE (arg00),
+                                                    arg2));
+           return pedantic_non_lvalue_loc (loc,
+                                           fold_convert_loc (loc, type, tem));
+         }
        break;
 
       case GT_EXPR:
@@ -5347,13 +4750,14 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
                               OEP_ONLY_CONST)
            && operand_equal_p (arg01,
                                const_binop (MINUS_EXPR, arg2,
-                                            build_int_cst (type, 1), 0),
+                                            build_int_cst (type, 1)),
                                OEP_ONLY_CONST))
-         return pedantic_non_lvalue (fold_convert (type,
-                                     fold_build2 (MAX_EXPR, TREE_TYPE (arg00),
-                                                  arg00,
-                                                  fold_convert (TREE_TYPE (arg00),
-                                                                arg2))));
+         {
+           tem = fold_build2_loc (loc, MAX_EXPR, TREE_TYPE (arg00), arg00,
+                                  fold_convert_loc (loc, TREE_TYPE (arg00),
+                                                    arg2));
+           return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, tem));
+         }
        break;
 
       case GE_EXPR:
@@ -5362,13 +4766,14 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
                               OEP_ONLY_CONST)
            && operand_equal_p (arg01,
                                const_binop (PLUS_EXPR, arg2,
-                                            build_int_cst (type, 1), 0),
+                                            build_int_cst (type, 1)),
                                OEP_ONLY_CONST))
-         return pedantic_non_lvalue (fold_convert (type,
-                                     fold_build2 (MAX_EXPR, TREE_TYPE (arg00),
-                                                  arg00,
-                                                  fold_convert (TREE_TYPE (arg00),
-                                                                arg2))));
+         {
+           tem = fold_build2_loc (loc, MAX_EXPR, TREE_TYPE (arg00), arg00,
+                                  fold_convert_loc (loc, TREE_TYPE (arg00),
+                                                    arg2));
+           return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, tem));
+         }
        break;
       case NE_EXPR:
        break;
@@ -5391,7 +4796,8 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
    merge it into some range test.  Return the new tree if so.  */
 
 static tree
-fold_range_test (enum tree_code code, tree type, tree op0, tree op1)
+fold_range_test (location_t loc, enum tree_code code, tree type,
+                tree op0, tree op1)
 {
   int or_op = (code == TRUTH_ORIF_EXPR
               || code == TRUTH_OR_EXPR);
@@ -5416,14 +4822,14 @@ fold_range_test (enum tree_code code, tree type, tree op0, tree op1)
   if ((lhs == 0 || rhs == 0 || operand_equal_p (lhs, rhs, 0))
       && merge_ranges (&in_p, &low, &high, in0_p, low0, high0,
                       in1_p, low1, high1)
-      && 0 != (tem = (build_range_check (type,
+      && 0 != (tem = (build_range_check (loc, type,
                                         lhs != 0 ? lhs
                                         : rhs != 0 ? rhs : integer_zero_node,
                                         in_p, low, high))))
     {
       if (strict_overflow_p)
        fold_overflow_warning (warnmsg, WARN_STRICT_OVERFLOW_COMPARISON);
-      return or_op ? invert_truthvalue (tem) : tem;
+      return or_op ? invert_truthvalue_loc (loc, tem) : tem;
     }
 
   /* On machines where the branch cost is expensive, if this is a
@@ -5439,28 +4845,28 @@ fold_range_test (enum tree_code code, tree type, tree op0, tree op1)
         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))
-       return build2 (code == TRUTH_ANDIF_EXPR
-                      ? TRUTH_AND_EXPR : TRUTH_OR_EXPR,
-                      type, op0, op1);
+       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))
+      else if (!lang_hooks.decls.global_bindings_p ()
+              && !CONTAINS_PLACEHOLDER_P (lhs))
        {
          tree common = save_expr (lhs);
 
-         if (0 != (lhs = build_range_check (type, common,
+         if (0 != (lhs = build_range_check (loc, type, common,
                                             or_op ? ! in0_p : in0_p,
                                             low0, high0))
-             && (0 != (rhs = build_range_check (type, common,
+             && (0 != (rhs = build_range_check (loc, type, common,
                                                 or_op ? ! in1_p : in1_p,
                                                 low1, high1))))
            {
              if (strict_overflow_p)
                fold_overflow_warning (warnmsg,
                                       WARN_STRICT_OVERFLOW_COMPARISON);
-             return build2 (code == TRUTH_ANDIF_EXPR
-                            ? TRUTH_AND_EXPR : TRUTH_OR_EXPR,
-                            type, lhs, rhs);
+             return build2_loc (loc, code == TRUTH_ANDIF_EXPR
+                                ? TRUTH_AND_EXPR : TRUTH_OR_EXPR,
+                                type, lhs, rhs);
            }
        }
     }
@@ -5486,8 +4892,8 @@ unextend (tree c, int p, int unsignedp, tree mask)
   /* We work by getting just the sign bit into the low-order bit, then
      into the high-order bit, then sign-extend.  We then XOR that value
      with C.  */
-  temp = const_binop (RSHIFT_EXPR, c, size_int (p - 1), 0);
-  temp = const_binop (BIT_AND_EXPR, temp, size_int (1), 0);
+  temp = const_binop (RSHIFT_EXPR, c, size_int (p - 1));
+  temp = const_binop (BIT_AND_EXPR, temp, size_int (1));
 
   /* We must use a signed type in order to get an arithmetic right shift.
      However, we must also avoid introducing accidental overflows, so that
@@ -5498,18 +4904,88 @@ unextend (tree c, int p, int unsignedp, tree mask)
   if (TYPE_UNSIGNED (type))
     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);
+  temp = const_binop (LSHIFT_EXPR, temp, size_int (modesize - 1));
+  temp = const_binop (RSHIFT_EXPR, temp, size_int (modesize - p - 1));
   if (mask != 0)
     temp = const_binop (BIT_AND_EXPR, temp,
-                       fold_convert (TREE_TYPE (c), mask), 0);
+                       fold_convert (TREE_TYPE (c), mask));
   /* If necessary, convert the type back to match the type of C.  */
   if (TYPE_UNSIGNED (type))
     temp = fold_convert (type, temp);
 
-  return fold_convert (type, const_binop (BIT_XOR_EXPR, c, temp, 0));
+  return fold_convert (type, const_binop (BIT_XOR_EXPR, c, temp));
 }
 \f
+/* For an expression that has the form
+     (A && B) || ~B
+   or
+     (A || B) && ~B,
+   we can drop one of the inner expressions and simplify to
+     A || ~B
+   or
+     A && ~B
+   LOC is the location of the resulting expression.  OP is the inner 
+   logical operation; the left-hand side in the examples above, while CMPOP
+   is the right-hand side.  RHS_ONLY is used to prevent us from accidentally
+   removing a condition that guards another, as in
+     (A != NULL && A->...) || A == NULL
+   which we must not transform.  If RHS_ONLY is true, only eliminate the
+   right-most operand of the inner logical operation.  */
+
+static tree
+merge_truthop_with_opposite_arm (location_t loc, tree op, tree cmpop,
+                                bool rhs_only)
+{
+  tree type = TREE_TYPE (cmpop);
+  enum tree_code code = TREE_CODE (cmpop);
+  enum tree_code truthop_code = TREE_CODE (op);
+  tree lhs = TREE_OPERAND (op, 0);
+  tree rhs = TREE_OPERAND (op, 1);
+  tree orig_lhs = lhs, orig_rhs = rhs;
+  enum tree_code rhs_code = TREE_CODE (rhs);
+  enum tree_code lhs_code = TREE_CODE (lhs);
+  enum tree_code inv_code;
+
+  if (TREE_SIDE_EFFECTS (op) || TREE_SIDE_EFFECTS (cmpop))
+    return NULL_TREE;
+
+  if (TREE_CODE_CLASS (code) != tcc_comparison)
+    return NULL_TREE;
+
+  if (rhs_code == truthop_code)
+    {
+      tree newrhs = merge_truthop_with_opposite_arm (loc, rhs, cmpop, rhs_only);
+      if (newrhs != NULL_TREE)
+       {
+         rhs = newrhs;
+         rhs_code = TREE_CODE (rhs);
+       }
+    }
+  if (lhs_code == truthop_code && !rhs_only)
+    {
+      tree newlhs = merge_truthop_with_opposite_arm (loc, lhs, cmpop, false);
+      if (newlhs != NULL_TREE)
+       {
+         lhs = newlhs;
+         lhs_code = TREE_CODE (lhs);
+       }
+    }
+
+  inv_code = invert_tree_comparison (code, HONOR_NANS (TYPE_MODE (type)));
+  if (inv_code == rhs_code
+      && operand_equal_p (TREE_OPERAND (rhs, 0), TREE_OPERAND (cmpop, 0), 0)
+      && operand_equal_p (TREE_OPERAND (rhs, 1), TREE_OPERAND (cmpop, 1), 0))
+    return lhs;
+  if (!rhs_only && inv_code == lhs_code
+      && operand_equal_p (TREE_OPERAND (lhs, 0), TREE_OPERAND (cmpop, 0), 0)
+      && operand_equal_p (TREE_OPERAND (lhs, 1), TREE_OPERAND (cmpop, 1), 0))
+    return rhs;
+  if (rhs != orig_rhs || lhs != orig_lhs)
+    return fold_build2_loc (loc, truthop_code, TREE_TYPE (cmpop),
+                           lhs, rhs);
+  return NULL_TREE;
+}
+
 /* Find ways of folding logical expressions of LHS and RHS:
    Try to merge two comparisons to the same innermost item.
    Look for range tests like "ch >= '0' && ch <= '9'".
@@ -5535,7 +5011,8 @@ unextend (tree c, int p, int unsignedp, tree mask)
    We return the simplified tree or 0 if no optimization is possible.  */
 
 static tree
-fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs)
+fold_truthop (location_t loc, enum tree_code code, tree truth_type,
+             tree lhs, tree rhs)
 {
   /* If this is the "or" of two comparisons, we can do something if
      the comparisons are NE_EXPR.  If this is the "and", we can do something
@@ -5603,11 +5080,10 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs)
   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))
        {
-          result = combine_comparisons (code, lcode, rcode,
+          result = combine_comparisons (loc, code, lcode, rcode,
                                        truth_type, ll_arg, lr_arg);
          if (result)
            return result;
@@ -5615,7 +5091,7 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs)
       else if (operand_equal_p (ll_arg, rr_arg, 0)
                && operand_equal_p (lr_arg, rl_arg, 0))
        {
-          result = combine_comparisons (code, lcode,
+          result = combine_comparisons (loc, code, lcode,
                                        swap_tree_comparison (rcode),
                                        truth_type, ll_arg, lr_arg);
          if (result)
@@ -5644,10 +5120,10 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs)
          && rcode == NE_EXPR && integer_zerop (rr_arg)
          && TREE_TYPE (ll_arg) == TREE_TYPE (rl_arg)
          && INTEGRAL_TYPE_P (TREE_TYPE (ll_arg)))
-       return build2 (NE_EXPR, truth_type,
-                      build2 (BIT_IOR_EXPR, TREE_TYPE (ll_arg),
-                              ll_arg, rl_arg),
-                      build_int_cst (TREE_TYPE (ll_arg), 0));
+       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));
 
       /* Convert (a == 0) && (b == 0) into (a | b) == 0.  */
       if (code == TRUTH_AND_EXPR
@@ -5655,15 +5131,15 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs)
          && rcode == EQ_EXPR && integer_zerop (rr_arg)
          && TREE_TYPE (ll_arg) == TREE_TYPE (rl_arg)
          && INTEGRAL_TYPE_P (TREE_TYPE (ll_arg)))
-       return build2 (EQ_EXPR, truth_type,
-                      build2 (BIT_IOR_EXPR, TREE_TYPE (ll_arg),
-                              ll_arg, rl_arg),
-                      build_int_cst (TREE_TYPE (ll_arg), 0));
+       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));
 
       if (LOGICAL_OP_NON_SHORT_CIRCUIT)
        {
          if (code != orig_code || lhs != orig_lhs || rhs != orig_rhs)
-           return build2 (code, truth_type, lhs, rhs);
+           return build2_loc (loc, code, truth_type, lhs, rhs);
          return NULL_TREE;
        }
     }
@@ -5676,19 +5152,19 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs)
     return 0;
 
   volatilep = 0;
-  ll_inner = decode_field_reference (ll_arg,
+  ll_inner = decode_field_reference (loc, ll_arg,
                                     &ll_bitsize, &ll_bitpos, &ll_mode,
                                     &ll_unsignedp, &volatilep, &ll_mask,
                                     &ll_and_mask);
-  lr_inner = decode_field_reference (lr_arg,
+  lr_inner = decode_field_reference (loc, lr_arg,
                                     &lr_bitsize, &lr_bitpos, &lr_mode,
                                     &lr_unsignedp, &volatilep, &lr_mask,
                                     &lr_and_mask);
-  rl_inner = decode_field_reference (rl_arg,
+  rl_inner = decode_field_reference (loc, rl_arg,
                                     &rl_bitsize, &rl_bitpos, &rl_mode,
                                     &rl_unsignedp, &volatilep, &rl_mask,
                                     &rl_and_mask);
-  rr_inner = decode_field_reference (rr_arg,
+  rr_inner = decode_field_reference (loc, rr_arg,
                                     &rr_bitsize, &rr_bitpos, &rr_mode,
                                     &rr_unsignedp, &volatilep, &rr_mask,
                                     &rr_and_mask);
@@ -5763,20 +5239,19 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs)
       xrl_bitpos = lnbitsize - xrl_bitpos - rl_bitsize;
     }
 
-  ll_mask = const_binop (LSHIFT_EXPR, fold_convert (lntype, ll_mask),
-                        size_int (xll_bitpos), 0);
-  rl_mask = const_binop (LSHIFT_EXPR, fold_convert (lntype, rl_mask),
-                        size_int (xrl_bitpos), 0);
+  ll_mask = const_binop (LSHIFT_EXPR, fold_convert_loc (loc, lntype, ll_mask),
+                        size_int (xll_bitpos));
+  rl_mask = const_binop (LSHIFT_EXPR, fold_convert_loc (loc, lntype, rl_mask),
+                        size_int (xrl_bitpos));
 
   if (l_const)
     {
-      l_const = fold_convert (lntype, l_const);
+      l_const = fold_convert_loc (loc, lntype, l_const);
       l_const = unextend (l_const, ll_bitsize, ll_unsignedp, ll_and_mask);
-      l_const = const_binop (LSHIFT_EXPR, l_const, size_int (xll_bitpos), 0);
+      l_const = const_binop (LSHIFT_EXPR, l_const, size_int (xll_bitpos));
       if (! integer_zerop (const_binop (BIT_AND_EXPR, l_const,
-                                       fold_build1 (BIT_NOT_EXPR,
-                                                    lntype, ll_mask),
-                                       0)))
+                                       fold_build1_loc (loc, BIT_NOT_EXPR,
+                                                    lntype, ll_mask))))
        {
          warning (0, "comparison is always %d", wanted_code == NE_EXPR);
 
@@ -5785,13 +5260,12 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs)
     }
   if (r_const)
     {
-      r_const = fold_convert (lntype, r_const);
+      r_const = fold_convert_loc (loc, lntype, r_const);
       r_const = unextend (r_const, rl_bitsize, rl_unsignedp, rl_and_mask);
-      r_const = const_binop (LSHIFT_EXPR, r_const, size_int (xrl_bitpos), 0);
+      r_const = const_binop (LSHIFT_EXPR, r_const, size_int (xrl_bitpos));
       if (! integer_zerop (const_binop (BIT_AND_EXPR, r_const,
-                                       fold_build1 (BIT_NOT_EXPR,
-                                                    lntype, rl_mask),
-                                       0)))
+                                       fold_build1_loc (loc, BIT_NOT_EXPR,
+                                                    lntype, rl_mask))))
        {
          warning (0, "comparison is always %d", wanted_code == NE_EXPR);
 
@@ -5830,31 +5304,33 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs)
          xrr_bitpos = rnbitsize - xrr_bitpos - rr_bitsize;
        }
 
-      lr_mask = const_binop (LSHIFT_EXPR, fold_convert (rntype, lr_mask),
-                            size_int (xlr_bitpos), 0);
-      rr_mask = const_binop (LSHIFT_EXPR, fold_convert (rntype, rr_mask),
-                            size_int (xrr_bitpos), 0);
+      lr_mask = const_binop (LSHIFT_EXPR, fold_convert_loc (loc,
+                                                           rntype, lr_mask),
+                            size_int (xlr_bitpos));
+      rr_mask = const_binop (LSHIFT_EXPR, fold_convert_loc (loc,
+                                                           rntype, rr_mask),
+                            size_int (xrr_bitpos));
 
       /* Make a mask that corresponds to both fields being compared.
         Do this for both items being compared.  If the operands are the
         same size and the bits being compared are in the same position
         then we can do this by masking both and comparing the masked
         results.  */
-      ll_mask = const_binop (BIT_IOR_EXPR, ll_mask, rl_mask, 0);
-      lr_mask = const_binop (BIT_IOR_EXPR, lr_mask, rr_mask, 0);
+      ll_mask = const_binop (BIT_IOR_EXPR, ll_mask, rl_mask);
+      lr_mask = const_binop (BIT_IOR_EXPR, lr_mask, rr_mask);
       if (lnbitsize == rnbitsize && xll_bitpos == xlr_bitpos)
        {
-         lhs = make_bit_field_ref (ll_inner, lntype, lnbitsize, lnbitpos,
+         lhs = make_bit_field_ref (loc, ll_inner, lntype, lnbitsize, lnbitpos,
                                    ll_unsignedp || rl_unsignedp);
          if (! all_ones_mask_p (ll_mask, lnbitsize))
            lhs = build2 (BIT_AND_EXPR, lntype, lhs, ll_mask);
 
-         rhs = make_bit_field_ref (lr_inner, rntype, rnbitsize, rnbitpos,
+         rhs = make_bit_field_ref (loc, lr_inner, rntype, rnbitsize, rnbitpos,
                                    lr_unsignedp || rr_unsignedp);
          if (! all_ones_mask_p (lr_mask, rnbitsize))
            rhs = build2 (BIT_AND_EXPR, rntype, rhs, lr_mask);
 
-         return build2 (wanted_code, truth_type, lhs, rhs);
+         return build2_loc (loc, wanted_code, truth_type, lhs, rhs);
        }
 
       /* There is still another way we can do something:  If both pairs of
@@ -5871,15 +5347,17 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs)
        {
          tree type;
 
-         lhs = make_bit_field_ref (ll_inner, lntype, ll_bitsize + rl_bitsize,
+         lhs = make_bit_field_ref (loc, ll_inner, lntype,
+                                   ll_bitsize + rl_bitsize,
                                    MIN (ll_bitpos, rl_bitpos), ll_unsignedp);
-         rhs = make_bit_field_ref (lr_inner, rntype, lr_bitsize + rr_bitsize,
+         rhs = make_bit_field_ref (loc, lr_inner, rntype,
+                                   lr_bitsize + rr_bitsize,
                                    MIN (lr_bitpos, rr_bitpos), lr_unsignedp);
 
          ll_mask = const_binop (RSHIFT_EXPR, ll_mask,
-                                size_int (MIN (xll_bitpos, xrl_bitpos)), 0);
+                                size_int (MIN (xll_bitpos, xrl_bitpos)));
          lr_mask = const_binop (RSHIFT_EXPR, lr_mask,
-                                size_int (MIN (xlr_bitpos, xrr_bitpos)), 0);
+                                size_int (MIN (xlr_bitpos, xrr_bitpos)));
 
          /* Convert to the smaller type before masking out unwanted bits.  */
          type = lntype;
@@ -5887,14 +5365,14 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs)
            {
              if (lnbitsize > rnbitsize)
                {
-                 lhs = fold_convert (rntype, lhs);
-                 ll_mask = fold_convert (rntype, ll_mask);
+                 lhs = fold_convert_loc (loc, rntype, lhs);
+                 ll_mask = fold_convert_loc (loc, rntype, ll_mask);
                  type = rntype;
                }
              else if (lnbitsize < rnbitsize)
                {
-                 rhs = fold_convert (lntype, rhs);
-                 lr_mask = fold_convert (lntype, lr_mask);
+                 rhs = fold_convert_loc (loc, lntype, rhs);
+                 lr_mask = fold_convert_loc (loc, lntype, lr_mask);
                  type = lntype;
                }
            }
@@ -5905,7 +5383,7 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs)
          if (! all_ones_mask_p (lr_mask, lr_bitsize + rr_bitsize))
            rhs = build2 (BIT_AND_EXPR, type, rhs, lr_mask);
 
-         return build2 (wanted_code, truth_type, lhs, rhs);
+         return build2_loc (loc, wanted_code, truth_type, lhs, rhs);
        }
 
       return 0;
@@ -5915,10 +5393,10 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs)
      common between the masks, those bits of the constants must be the same.
      If not, the condition is always false.  Test for this to avoid generating
      incorrect code below.  */
-  result = const_binop (BIT_AND_EXPR, ll_mask, rl_mask, 0);
+  result = const_binop (BIT_AND_EXPR, ll_mask, rl_mask);
   if (! integer_zerop (result)
-      && simple_cst_equal (const_binop (BIT_AND_EXPR, result, l_const, 0),
-                          const_binop (BIT_AND_EXPR, result, r_const, 0)) != 1)
+      && simple_cst_equal (const_binop (BIT_AND_EXPR, result, l_const),
+                          const_binop (BIT_AND_EXPR, result, r_const)) != 1)
     {
       if (wanted_code == NE_EXPR)
        {
@@ -5936,22 +5414,23 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs)
      reference we will make.  Unless the mask is all ones the width of
      that field, perform the mask operation.  Then compare with the
      merged constant.  */
-  result = make_bit_field_ref (ll_inner, lntype, lnbitsize, lnbitpos,
+  result = make_bit_field_ref (loc, ll_inner, lntype, lnbitsize, lnbitpos,
                               ll_unsignedp || rl_unsignedp);
 
-  ll_mask = const_binop (BIT_IOR_EXPR, ll_mask, rl_mask, 0);
+  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);
+    result = build2_loc (loc, BIT_AND_EXPR, lntype, result, ll_mask);
 
-  return build2 (wanted_code, truth_type, result,
-                const_binop (BIT_IOR_EXPR, l_const, r_const, 0));
+  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
    constant.  */
 
 static tree
-optimize_minmax_comparison (enum tree_code code, tree type, tree op0, tree op1)
+optimize_minmax_comparison (location_t loc, enum tree_code code, tree type,
+                           tree op0, tree op1)
 {
   tree arg0 = op0;
   enum tree_code op_code;
@@ -5964,7 +5443,7 @@ optimize_minmax_comparison (enum tree_code code, tree type, tree op0, tree op1)
 
   op_code = TREE_CODE (arg0);
   minmax_const = TREE_OPERAND (arg0, 1);
-  comp_const = fold_convert (TREE_TYPE (arg0), op1);
+  comp_const = fold_convert_loc (loc, TREE_TYPE (arg0), op1);
   consts_equal = tree_int_cst_equal (minmax_const, comp_const);
   consts_lt = tree_int_cst_lt (minmax_const, comp_const);
   inner = TREE_OPERAND (arg0, 0);
@@ -5984,64 +5463,66 @@ optimize_minmax_comparison (enum tree_code code, tree type, tree op0, tree op1)
     {
     case NE_EXPR:  case LT_EXPR:  case LE_EXPR:
       {
-       tree tem = optimize_minmax_comparison (invert_tree_comparison (code, false),
-                                         type, op0, op1);
+       tree tem
+         = optimize_minmax_comparison (loc,
+                                       invert_tree_comparison (code, false),
+                                       type, op0, op1);
        if (tem)
-         return invert_truthvalue (tem);
+         return invert_truthvalue_loc (loc, tem);
        return NULL_TREE;
       }
 
     case GE_EXPR:
       return
-       fold_build2 (TRUTH_ORIF_EXPR, type,
+       fold_build2_loc (loc, TRUTH_ORIF_EXPR, type,
                     optimize_minmax_comparison
-                    (EQ_EXPR, type, arg0, comp_const),
+                    (loc, EQ_EXPR, type, arg0, comp_const),
                     optimize_minmax_comparison
-                    (GT_EXPR, type, arg0, comp_const));
+                    (loc, GT_EXPR, type, arg0, comp_const));
 
     case EQ_EXPR:
       if (op_code == MAX_EXPR && consts_equal)
        /* MAX (X, 0) == 0  ->  X <= 0  */
-       return fold_build2 (LE_EXPR, type, inner, comp_const);
+       return fold_build2_loc (loc, LE_EXPR, type, inner, comp_const);
 
       else if (op_code == MAX_EXPR && consts_lt)
        /* MAX (X, 0) == 5  ->  X == 5   */
-       return fold_build2 (EQ_EXPR, type, inner, comp_const);
+       return fold_build2_loc (loc, EQ_EXPR, type, inner, comp_const);
 
       else if (op_code == MAX_EXPR)
        /* MAX (X, 0) == -1  ->  false  */
-       return omit_one_operand (type, integer_zero_node, inner);
+       return omit_one_operand_loc (loc, type, integer_zero_node, inner);
 
       else if (consts_equal)
        /* MIN (X, 0) == 0  ->  X >= 0  */
-       return fold_build2 (GE_EXPR, type, inner, comp_const);
+       return fold_build2_loc (loc, GE_EXPR, type, inner, comp_const);
 
       else if (consts_lt)
        /* MIN (X, 0) == 5  ->  false  */
-       return omit_one_operand (type, integer_zero_node, inner);
+       return omit_one_operand_loc (loc, type, integer_zero_node, inner);
 
       else
        /* MIN (X, 0) == -1  ->  X == -1  */
-       return fold_build2 (EQ_EXPR, type, inner, comp_const);
+       return fold_build2_loc (loc, EQ_EXPR, type, inner, comp_const);
 
     case GT_EXPR:
       if (op_code == MAX_EXPR && (consts_equal || consts_lt))
        /* MAX (X, 0) > 0  ->  X > 0
           MAX (X, 0) > 5  ->  X > 5  */
-       return fold_build2 (GT_EXPR, type, inner, comp_const);
+       return fold_build2_loc (loc, GT_EXPR, type, inner, comp_const);
 
       else if (op_code == MAX_EXPR)
        /* MAX (X, 0) > -1  ->  true  */
-       return omit_one_operand (type, integer_one_node, inner);
+       return omit_one_operand_loc (loc, type, integer_one_node, inner);
 
       else if (op_code == MIN_EXPR && (consts_equal || consts_lt))
        /* MIN (X, 0) > 0  ->  false
           MIN (X, 0) > 5  ->  false  */
-       return omit_one_operand (type, integer_zero_node, inner);
+       return omit_one_operand_loc (loc, type, integer_zero_node, inner);
 
       else
        /* MIN (X, 0) > -1  ->  X > -1  */
-       return fold_build2 (GT_EXPR, type, inner, comp_const);
+       return fold_build2_loc (loc, GT_EXPR, type, inner, comp_const);
 
     default:
       return NULL_TREE;
@@ -6120,9 +5601,9 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
       /* For a constant, we can always simplify if we are a multiply
         or (for divide and modulus) if it is a multiple of our constant.  */
       if (code == MULT_EXPR
-         || integer_zerop (const_binop (TRUNC_MOD_EXPR, t, c, 0)))
+         || integer_zerop (const_binop (TRUNC_MOD_EXPR, t, c)))
        return const_binop (code, fold_convert (ctype, t),
-                           fold_convert (ctype, c), 0);
+                           fold_convert (ctype, c));
       break;
 
     CASE_CONVERT: case NON_LVALUE_EXPR:
@@ -6230,11 +5711,13 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
          && 0 != (t1 = fold_convert (ctype,
                                      const_binop (LSHIFT_EXPR,
                                                   size_one_node,
-                                                  op1, 0)))
+                                                  op1)))
          && !TREE_OVERFLOW (t1))
        return extract_muldiv (build2 (tcode == LSHIFT_EXPR
                                       ? MULT_EXPR : FLOOR_DIV_EXPR,
-                                      ctype, fold_convert (ctype, op0), t1),
+                                      ctype,
+                                      fold_convert (ctype, op0),
+                                      t1),
                               c, code, wide_type, strict_overflow_p);
       break;
 
@@ -6262,7 +5745,19 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
       /* If this was a subtraction, negate OP1 and set it to be an addition.
         This simplifies the logic below.  */
       if (tcode == MINUS_EXPR)
-       tcode = PLUS_EXPR, op1 = negate_expr (op1);
+       {
+         tcode = PLUS_EXPR, op1 = negate_expr (op1);
+         /* If OP1 was not easily negatable, the constant may be OP0.  */
+         if (TREE_CODE (op0) == INTEGER_CST)
+           {
+             tree tem = op0;
+             op0 = op1;
+             op1 = tem;
+             tem = t1;
+             t1 = t2;
+             t2 = tem;
+           }
+       }
 
       if (TREE_CODE (op1) != INTEGER_CST)
        break;
@@ -6284,10 +5779,10 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
       /* If it's a multiply or a division/modulus operation of a multiple
          of our constant, do the operation and verify it doesn't overflow.  */
       if (code == MULT_EXPR
-         || integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c, 0)))
+         || integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c)))
        {
          op1 = const_binop (code, fold_convert (ctype, op1),
-                            fold_convert (ctype, c), 0);
+                            fold_convert (ctype, c));
          /* We allow the constant to overflow with wrapping semantics.  */
          if (op1 == 0
              || (TREE_OVERFLOW (op1) && !TYPE_OVERFLOW_WRAPS (ctype)))
@@ -6335,7 +5830,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
              || (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
                  && TYPE_IS_SIZETYPE (TREE_TYPE (t))))
          && TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST
-         && integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c, 0)))
+         && integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c)))
        {
          *strict_overflow_p = true;
          return omit_one_operand (type, integer_zero_node, op0);
@@ -6363,16 +5858,33 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
 
       /* If these are the same operation types, we can associate them
         assuming no overflow.  */
-      if (tcode == code
-         && 0 != (t1 = int_const_binop (MULT_EXPR, fold_convert (ctype, op1),
-                                        fold_convert (ctype, c), 1))
-         && 0 != (t1 = force_fit_type_double (ctype, TREE_INT_CST_LOW (t1),
-                                              TREE_INT_CST_HIGH (t1),
-                                              (TYPE_UNSIGNED (ctype)
-                                               && tcode != MULT_EXPR) ? -1 : 1,
-                                              TREE_OVERFLOW (t1)))
-         && !TREE_OVERFLOW (t1))
-       return fold_build2 (tcode, ctype, fold_convert (ctype, op0), t1);
+      if (tcode == code)
+       {
+         double_int mul;
+         int overflow_p;
+         mul = double_int_mul_with_sign
+                 (double_int_ext
+                    (tree_to_double_int (op1),
+                     TYPE_PRECISION (ctype), TYPE_UNSIGNED (ctype)),
+                  double_int_ext
+                    (tree_to_double_int (c),
+                     TYPE_PRECISION (ctype), TYPE_UNSIGNED (ctype)),
+                  false, &overflow_p);
+         overflow_p = (((!TYPE_UNSIGNED (ctype)
+                         || (TREE_CODE (ctype) == INTEGER_TYPE
+                             && TYPE_IS_SIZETYPE (ctype)))
+                        && overflow_p)
+                       | TREE_OVERFLOW (c) | TREE_OVERFLOW (op1));
+         if (!double_int_fits_to_tree_p (ctype, mul)
+             && ((TYPE_UNSIGNED (ctype) && tcode != MULT_EXPR)
+                 || !TYPE_UNSIGNED (ctype)
+                 || (TREE_CODE (ctype) == INTEGER_TYPE
+                     && TYPE_IS_SIZETYPE (ctype))))
+           overflow_p = 1;
+         if (!overflow_p)
+           return fold_build2 (tcode, ctype, fold_convert (ctype, op0),
+                               double_int_to_tree (ctype, mul));
+       }
 
       /* If these operations "cancel" each other, we have the main
         optimizations of this pass, which occur when either constant is a
@@ -6390,23 +5902,23 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
                  && code != FLOOR_MOD_EXPR && code != ROUND_MOD_EXPR
                  && code != MULT_EXPR)))
        {
-         if (integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c, 0)))
+         if (integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c)))
            {
              if (TYPE_OVERFLOW_UNDEFINED (ctype))
                *strict_overflow_p = true;
              return fold_build2 (tcode, ctype, fold_convert (ctype, op0),
                                  fold_convert (ctype,
                                                const_binop (TRUNC_DIV_EXPR,
-                                                            op1, c, 0)));
+                                                            op1, c)));
            }
-         else if (integer_zerop (const_binop (TRUNC_MOD_EXPR, c, op1, 0)))
+         else if (integer_zerop (const_binop (TRUNC_MOD_EXPR, c, op1)))
            {
              if (TYPE_OVERFLOW_UNDEFINED (ctype))
                *strict_overflow_p = true;
              return fold_build2 (code, ctype, fold_convert (ctype, op0),
                                  fold_convert (ctype,
                                                const_binop (TRUNC_DIV_EXPR,
-                                                            c, op1, 0)));
+                                                            c, op1)));
            }
        }
       break;
@@ -6443,7 +5955,8 @@ constant_boolean_node (int value, tree type)
    possible.  */
 
 static tree
-fold_binary_op_with_conditional_arg (enum tree_code code,
+fold_binary_op_with_conditional_arg (location_t loc,
+                                    enum tree_code code,
                                     tree type, tree op0, tree op1,
                                     tree cond, tree arg, int cond_first_p)
 {
@@ -6453,12 +5966,6 @@ fold_binary_op_with_conditional_arg (enum tree_code code,
   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 at least
-     one of the branches once its pushed inside the COND_EXPR.  */
-  if (!TREE_CONSTANT (arg))
-    return NULL_TREE;
-
   if (TREE_CODE (cond) == COND_EXPR)
     {
       test = TREE_OPERAND (cond, 0);
@@ -6480,26 +5987,37 @@ fold_binary_op_with_conditional_arg (enum tree_code code,
       false_value = constant_boolean_node (false, testtype);
     }
 
-  arg = fold_convert (arg_type, arg);
+  /* This transformation is only worthwhile if we don't have to wrap 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)
+      && (TREE_SIDE_EFFECTS (arg)
+         || TREE_CONSTANT (true_value) || TREE_CONSTANT (false_value)))
+    return NULL_TREE;
+
+  arg = fold_convert_loc (loc, arg_type, arg);
   if (lhs == 0)
     {
-      true_value = fold_convert (cond_type, true_value);
+      true_value = fold_convert_loc (loc, cond_type, true_value);
       if (cond_first_p)
-       lhs = fold_build2 (code, type, true_value, arg);
+       lhs = fold_build2_loc (loc, code, type, true_value, arg);
       else
-       lhs = fold_build2 (code, type, arg, true_value);
+       lhs = fold_build2_loc (loc, code, type, arg, true_value);
     }
   if (rhs == 0)
     {
-      false_value = fold_convert (cond_type, false_value);
+      false_value = fold_convert_loc (loc, cond_type, false_value);
       if (cond_first_p)
-       rhs = fold_build2 (code, type, false_value, arg);
+       rhs = fold_build2_loc (loc, code, type, false_value, arg);
       else
-       rhs = fold_build2 (code, type, arg, false_value);
+       rhs = fold_build2_loc (loc, code, type, arg, false_value);
     }
 
-  test = fold_build3 (COND_EXPR, type, test, lhs, rhs);
-  return fold_convert (type, test);
+  /* Check that we have simplified at least one of the branches.  */
+  if (!TREE_CONSTANT (arg) && !TREE_CONSTANT (lhs) && !TREE_CONSTANT (rhs))
+    return NULL_TREE;
+
+  return fold_build3_loc (loc, COND_EXPR, type, test, lhs, rhs);
 }
 
 \f
@@ -6553,7 +6071,8 @@ fold_real_zero_addition_p (const_tree type, const_tree addend, int negate)
    can be made, and NULL_TREE otherwise.  */
 
 static tree
-fold_mathfn_compare (enum built_in_function fcode, enum tree_code code,
+fold_mathfn_compare (location_t loc,
+                    enum built_in_function fcode, enum tree_code code,
                     tree type, tree arg0, tree arg1)
 {
   REAL_VALUE_TYPE c;
@@ -6568,15 +6087,15 @@ fold_mathfn_compare (enum built_in_function fcode, enum tree_code code,
        {
          /* sqrt(x) < y is always false, if y is negative.  */
          if (code == EQ_EXPR || code == LT_EXPR || code == LE_EXPR)
-           return omit_one_operand (type, integer_zero_node, arg);
+           return omit_one_operand_loc (loc, type, integer_zero_node, arg);
 
          /* sqrt(x) > y is always true, if y is negative and we
             don't care about NaNs, i.e. negative values of x.  */
          if (code == NE_EXPR || !HONOR_NANS (mode))
-           return omit_one_operand (type, integer_one_node, arg);
+           return omit_one_operand_loc (loc, type, integer_one_node, arg);
 
          /* sqrt(x) > y is the same as x >= 0, if y is negative.  */
-         return fold_build2 (GE_EXPR, type, arg,
+         return fold_build2_loc (loc, GE_EXPR, type, arg,
                              build_real (TREE_TYPE (arg), dconst0));
        }
       else if (code == GT_EXPR || code == GE_EXPR)
@@ -6590,16 +6109,16 @@ fold_mathfn_compare (enum built_in_function fcode, enum tree_code code,
            {
              /* sqrt(x) > y is x == +Inf, when y is very large.  */
              if (HONOR_INFINITIES (mode))
-               return fold_build2 (EQ_EXPR, type, arg,
+               return fold_build2_loc (loc, EQ_EXPR, type, arg,
                                    build_real (TREE_TYPE (arg), c2));
 
              /* sqrt(x) > y is always false, when y is very large
                 and we don't care about infinities.  */
-             return omit_one_operand (type, integer_zero_node, arg);
+             return omit_one_operand_loc (loc, type, integer_zero_node, arg);
            }
 
          /* sqrt(x) > c is the same as x > c*c.  */
-         return fold_build2 (code, type, arg,
+         return fold_build2_loc (loc, code, type, arg,
                              build_real (TREE_TYPE (arg), c2));
        }
       else if (code == LT_EXPR || code == LE_EXPR)
@@ -6614,53 +6133,45 @@ fold_mathfn_compare (enum built_in_function fcode, enum tree_code code,
              /* sqrt(x) < y is always true, when y is a very large
                 value and we don't care about NaNs or Infinities.  */
              if (! HONOR_NANS (mode) && ! HONOR_INFINITIES (mode))
-               return omit_one_operand (type, integer_one_node, arg);
+               return omit_one_operand_loc (loc, type, integer_one_node, arg);
 
              /* sqrt(x) < y is x != +Inf when y is very large and we
                 don't care about NaNs.  */
              if (! HONOR_NANS (mode))
-               return fold_build2 (NE_EXPR, type, arg,
+               return fold_build2_loc (loc, NE_EXPR, type, arg,
                                    build_real (TREE_TYPE (arg), c2));
 
              /* sqrt(x) < y is x >= 0 when y is very large and we
                 don't care about Infinities.  */
              if (! HONOR_INFINITIES (mode))
-               return fold_build2 (GE_EXPR, type, arg,
+               return fold_build2_loc (loc, GE_EXPR, type, arg,
                                    build_real (TREE_TYPE (arg), dconst0));
 
              /* sqrt(x) < y is x >= 0 && x != +Inf, when y is large.  */
-             if (lang_hooks.decls.global_bindings_p () != 0
-                 || CONTAINS_PLACEHOLDER_P (arg))
-               return NULL_TREE;
-
              arg = save_expr (arg);
-             return fold_build2 (TRUTH_ANDIF_EXPR, type,
-                                 fold_build2 (GE_EXPR, type, arg,
+             return fold_build2_loc (loc, TRUTH_ANDIF_EXPR, type,
+                                 fold_build2_loc (loc, GE_EXPR, type, arg,
                                               build_real (TREE_TYPE (arg),
                                                           dconst0)),
-                                 fold_build2 (NE_EXPR, type, arg,
+                                 fold_build2_loc (loc, NE_EXPR, type, arg,
                                               build_real (TREE_TYPE (arg),
                                                           c2)));
            }
 
          /* sqrt(x) < c is the same as x < c*c, if we ignore NaNs.  */
          if (! HONOR_NANS (mode))
-           return fold_build2 (code, type, arg,
+           return fold_build2_loc (loc, code, type, arg,
                                build_real (TREE_TYPE (arg), c2));
 
          /* sqrt(x) < c is the same as x >= 0 && x < c*c.  */
-         if (lang_hooks.decls.global_bindings_p () == 0
-             && ! CONTAINS_PLACEHOLDER_P (arg))
-           {
-             arg = save_expr (arg);
-             return fold_build2 (TRUTH_ANDIF_EXPR, type,
-                                 fold_build2 (GE_EXPR, type, arg,
+         arg = save_expr (arg);
+         return fold_build2_loc (loc, TRUTH_ANDIF_EXPR, type,
+                                 fold_build2_loc (loc, GE_EXPR, type, arg,
                                               build_real (TREE_TYPE (arg),
                                                           dconst0)),
-                                 fold_build2 (code, type, arg,
+                                 fold_build2_loc (loc, code, type, arg,
                                               build_real (TREE_TYPE (arg),
                                                           c2)));
-           }
        }
     }
 
@@ -6678,7 +6189,8 @@ fold_mathfn_compare (enum built_in_function fcode, enum tree_code code,
    can be made, and NULL_TREE otherwise.  */
 
 static tree
-fold_inf_compare (enum tree_code code, tree type, tree arg0, tree arg1)
+fold_inf_compare (location_t loc, enum tree_code code, tree type,
+                 tree arg0, tree arg1)
 {
   enum machine_mode mode;
   REAL_VALUE_TYPE max;
@@ -6698,45 +6210,40 @@ fold_inf_compare (enum tree_code code, tree type, tree arg0, tree arg1)
       /* x > +Inf is always false, if with ignore sNANs.  */
       if (HONOR_SNANS (mode))
         return NULL_TREE;
-      return omit_one_operand (type, integer_zero_node, arg0);
+      return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
 
     case LE_EXPR:
       /* x <= +Inf is always true, if we don't case about NaNs.  */
       if (! HONOR_NANS (mode))
-       return omit_one_operand (type, integer_one_node, arg0);
+       return omit_one_operand_loc (loc, type, integer_one_node, arg0);
 
       /* x <= +Inf is the same as x == x, i.e. isfinite(x).  */
-      if (lang_hooks.decls.global_bindings_p () == 0
-         && ! CONTAINS_PLACEHOLDER_P (arg0))
-       {
-         arg0 = save_expr (arg0);
-         return fold_build2 (EQ_EXPR, type, arg0, arg0);
-       }
-      break;
+      arg0 = save_expr (arg0);
+      return fold_build2_loc (loc, EQ_EXPR, type, arg0, arg0);
 
     case EQ_EXPR:
     case GE_EXPR:
       /* x == +Inf and x >= +Inf are always equal to x > DBL_MAX.  */
       real_maxval (&max, neg, mode);
-      return fold_build2 (neg ? LT_EXPR : GT_EXPR, type,
+      return fold_build2_loc (loc, neg ? LT_EXPR : GT_EXPR, type,
                          arg0, build_real (TREE_TYPE (arg0), max));
 
     case LT_EXPR:
       /* x < +Inf is always equal to x <= DBL_MAX.  */
       real_maxval (&max, neg, mode);
-      return fold_build2 (neg ? GE_EXPR : LE_EXPR, type,
+      return fold_build2_loc (loc, neg ? GE_EXPR : LE_EXPR, type,
                          arg0, build_real (TREE_TYPE (arg0), max));
 
     case NE_EXPR:
       /* x != +Inf is always equal to !(x > DBL_MAX).  */
       real_maxval (&max, neg, mode);
       if (! HONOR_NANS (mode))
-       return fold_build2 (neg ? GE_EXPR : LE_EXPR, type,
+       return fold_build2_loc (loc, neg ? GE_EXPR : LE_EXPR, type,
                            arg0, build_real (TREE_TYPE (arg0), max));
 
-      temp = fold_build2 (neg ? LT_EXPR : GT_EXPR, type,
+      temp = fold_build2_loc (loc, neg ? LT_EXPR : GT_EXPR, type,
                          arg0, build_real (TREE_TYPE (arg0), max));
-      return fold_build1 (TRUTH_NOT_EXPR, type, temp);
+      return fold_build1_loc (loc, TRUTH_NOT_EXPR, type, temp);
 
     default:
       break;
@@ -6757,52 +6264,51 @@ fold_inf_compare (enum tree_code code, tree type, tree arg0, tree arg1)
    can be made, and NULL_TREE otherwise.  */
 
 static tree
-fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
+fold_div_compare (location_t loc,
+                 enum tree_code code, tree type, tree arg0, tree arg1)
 {
   tree prod, tmp, hi, lo;
   tree arg00 = TREE_OPERAND (arg0, 0);
   tree arg01 = TREE_OPERAND (arg0, 1);
-  unsigned HOST_WIDE_INT lpart;
-  HOST_WIDE_INT hpart;
+  double_int val;
   bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (arg0));
   bool neg_overflow;
   int overflow;
 
   /* We have to do this the hard way to detect unsigned overflow.
-     prod = int_const_binop (MULT_EXPR, arg01, arg1, 0);  */
+     prod = int_const_binop (MULT_EXPR, arg01, arg1);  */
   overflow = mul_double_with_sign (TREE_INT_CST_LOW (arg01),
                                   TREE_INT_CST_HIGH (arg01),
                                   TREE_INT_CST_LOW (arg1),
                                   TREE_INT_CST_HIGH (arg1),
-                                  &lpart, &hpart, unsigned_p);
-  prod = force_fit_type_double (TREE_TYPE (arg00), lpart, hpart,
-                               -1, overflow);
+                                  &val.low, &val.high, unsigned_p);
+  prod = force_fit_type_double (TREE_TYPE (arg00), val, -1, overflow);
   neg_overflow = false;
 
   if (unsigned_p)
     {
       tmp = int_const_binop (MINUS_EXPR, arg01,
-                             build_int_cst (TREE_TYPE (arg01), 1), 0);
+                             build_int_cst (TREE_TYPE (arg01), 1));
       lo = prod;
 
-      /* Likewise hi = int_const_binop (PLUS_EXPR, prod, tmp, 0).  */
+      /* Likewise hi = int_const_binop (PLUS_EXPR, prod, tmp).  */
       overflow = add_double_with_sign (TREE_INT_CST_LOW (prod),
                                       TREE_INT_CST_HIGH (prod),
                                       TREE_INT_CST_LOW (tmp),
                                       TREE_INT_CST_HIGH (tmp),
-                                      &lpart, &hpart, unsigned_p);
-      hi = force_fit_type_double (TREE_TYPE (arg00), lpart, hpart,
+                                      &val.low, &val.high, unsigned_p);
+      hi = force_fit_type_double (TREE_TYPE (arg00), val,
                                  -1, overflow | TREE_OVERFLOW (prod));
     }
   else if (tree_int_cst_sgn (arg01) >= 0)
     {
       tmp = int_const_binop (MINUS_EXPR, arg01,
-                            build_int_cst (TREE_TYPE (arg01), 1), 0);
+                            build_int_cst (TREE_TYPE (arg01), 1));
       switch (tree_int_cst_sgn (arg1))
        {
        case -1:
          neg_overflow = true;
-         lo = int_const_binop (MINUS_EXPR, prod, tmp, 0);
+         lo = int_const_binop (MINUS_EXPR, prod, tmp);
          hi = prod;
          break;
 
@@ -6812,7 +6318,7 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
          break;
 
        case  1:
-          hi = int_const_binop (PLUS_EXPR, prod, tmp, 0);
+          hi = int_const_binop (PLUS_EXPR, prod, tmp);
          lo = prod;
          break;
 
@@ -6826,11 +6332,11 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
       code = swap_tree_comparison (code);
 
       tmp = int_const_binop (PLUS_EXPR, arg01,
-                            build_int_cst (TREE_TYPE (arg01), 1), 0);
+                            build_int_cst (TREE_TYPE (arg01), 1));
       switch (tree_int_cst_sgn (arg1))
        {
        case -1:
-         hi = int_const_binop (MINUS_EXPR, prod, tmp, 0);
+         hi = int_const_binop (MINUS_EXPR, prod, tmp);
          lo = prod;
          break;
 
@@ -6841,7 +6347,7 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
 
        case  1:
          neg_overflow = true;
-         lo = int_const_binop (PLUS_EXPR, prod, tmp, 0);
+         lo = int_const_binop (PLUS_EXPR, prod, tmp);
          hi = prod;
          break;
 
@@ -6854,53 +6360,53 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
     {
     case EQ_EXPR:
       if (TREE_OVERFLOW (lo) && TREE_OVERFLOW (hi))
-       return omit_one_operand (type, integer_zero_node, arg00);
+       return omit_one_operand_loc (loc, type, integer_zero_node, arg00);
       if (TREE_OVERFLOW (hi))
-       return fold_build2 (GE_EXPR, type, arg00, lo);
+       return fold_build2_loc (loc, GE_EXPR, type, arg00, lo);
       if (TREE_OVERFLOW (lo))
-       return fold_build2 (LE_EXPR, type, arg00, hi);
-      return build_range_check (type, arg00, 1, lo, hi);
+       return fold_build2_loc (loc, LE_EXPR, type, arg00, hi);
+      return build_range_check (loc, type, arg00, 1, lo, hi);
 
     case NE_EXPR:
       if (TREE_OVERFLOW (lo) && TREE_OVERFLOW (hi))
-       return omit_one_operand (type, integer_one_node, arg00);
+       return omit_one_operand_loc (loc, type, integer_one_node, arg00);
       if (TREE_OVERFLOW (hi))
-       return fold_build2 (LT_EXPR, type, arg00, lo);
+       return fold_build2_loc (loc, LT_EXPR, type, arg00, lo);
       if (TREE_OVERFLOW (lo))
-       return fold_build2 (GT_EXPR, type, arg00, hi);
-      return build_range_check (type, arg00, 0, lo, hi);
+       return fold_build2_loc (loc, GT_EXPR, type, arg00, hi);
+      return build_range_check (loc, type, arg00, 0, lo, hi);
 
     case LT_EXPR:
       if (TREE_OVERFLOW (lo))
        {
          tmp = neg_overflow ? integer_zero_node : integer_one_node;
-         return omit_one_operand (type, tmp, arg00);
+         return omit_one_operand_loc (loc, type, tmp, arg00);
        }
-      return fold_build2 (LT_EXPR, type, arg00, lo);
+      return fold_build2_loc (loc, LT_EXPR, type, arg00, lo);
 
     case LE_EXPR:
       if (TREE_OVERFLOW (hi))
        {
          tmp = neg_overflow ? integer_zero_node : integer_one_node;
-         return omit_one_operand (type, tmp, arg00);
+         return omit_one_operand_loc (loc, type, tmp, arg00);
        }
-      return fold_build2 (LE_EXPR, type, arg00, hi);
+      return fold_build2_loc (loc, LE_EXPR, type, arg00, hi);
 
     case GT_EXPR:
       if (TREE_OVERFLOW (hi))
        {
          tmp = neg_overflow ? integer_one_node : integer_zero_node;
-         return omit_one_operand (type, tmp, arg00);
+         return omit_one_operand_loc (loc, type, tmp, arg00);
        }
-      return fold_build2 (GT_EXPR, type, arg00, hi);
+      return fold_build2_loc (loc, GT_EXPR, type, arg00, hi);
 
     case GE_EXPR:
       if (TREE_OVERFLOW (lo))
        {
          tmp = neg_overflow ? integer_one_node : integer_zero_node;
-         return omit_one_operand (type, tmp, arg00);
+         return omit_one_operand_loc (loc, type, tmp, arg00);
        }
-      return fold_build2 (GE_EXPR, type, arg00, lo);
+      return fold_build2_loc (loc, GE_EXPR, type, arg00, lo);
 
     default:
       break;
@@ -6916,7 +6422,8 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
    result type.  */
 
 static tree
-fold_single_bit_test_into_sign_test (enum tree_code code, tree arg0, tree arg1,
+fold_single_bit_test_into_sign_test (location_t loc,
+                                    enum tree_code code, tree arg0, tree arg1,
                                     tree result_type)
 {
   /* If this is testing a single bit, we can optimize the test.  */
@@ -6935,8 +6442,9 @@ fold_single_bit_test_into_sign_test (enum tree_code code, tree arg0, tree arg1,
             == GET_MODE_BITSIZE (TYPE_MODE (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),
+         return fold_build2_loc (loc, code == EQ_EXPR ? GE_EXPR : LT_EXPR,
+                             result_type,
+                             fold_convert_loc (loc, stype, arg00),
                              build_int_cst (stype, 0));
        }
     }
@@ -6950,8 +6458,8 @@ fold_single_bit_test_into_sign_test (enum tree_code code, tree arg0, tree arg1,
    NULL.  TYPE is the desired result type.  */
 
 tree
-fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
-                     tree result_type)
+fold_single_bit_test (location_t loc, enum tree_code code,
+                     tree arg0, tree arg1, tree result_type)
 {
   /* If this is testing a single bit, we can optimize the test.  */
   if ((code == NE_EXPR || code == EQ_EXPR)
@@ -6968,7 +6476,7 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
 
       /* First, see if we can fold the single bit test into a sign-bit
         test.  */
-      tem = fold_single_bit_test_into_sign_test (code, arg0, arg1,
+      tem = fold_single_bit_test_into_sign_test (loc, code, arg0, arg1,
                                                 result_type);
       if (tem)
        return tem;
@@ -6994,7 +6502,7 @@ 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 
+      ops_unsigned = (LOAD_EXTEND_OP (operand_mode) == SIGN_EXTEND
                      && !flag_syntax_only) ? 0 : 1;
 #else
       ops_unsigned = 1;
@@ -7003,7 +6511,7 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
       signed_type = lang_hooks.types.type_for_mode (operand_mode, 0);
       unsigned_type = lang_hooks.types.type_for_mode (operand_mode, 1);
       intermediate_type = ops_unsigned ? unsigned_type : signed_type;
-      inner = fold_convert (intermediate_type, inner);
+      inner = fold_convert_loc (loc, intermediate_type, inner);
 
       if (bitnum != 0)
        inner = build2 (RSHIFT_EXPR, intermediate_type,
@@ -7012,13 +6520,13 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
       one = build_int_cst (intermediate_type, 1);
 
       if (code == EQ_EXPR)
-       inner = fold_build2 (BIT_XOR_EXPR, intermediate_type, inner, one);
+       inner = fold_build2_loc (loc, BIT_XOR_EXPR, intermediate_type, inner, one);
 
       /* Put the AND last so it can combine with more things.  */
       inner = build2 (BIT_AND_EXPR, intermediate_type, inner, one);
 
       /* Make sure to return the proper type.  */
-      inner = fold_convert (result_type, inner);
+      inner = fold_convert_loc (loc, result_type, inner);
 
       return inner;
     }
@@ -7110,7 +6618,8 @@ tree_swap_operands_p (const_tree arg0, const_tree arg1, bool reorder)
    ARG0 is extended to a wider type.  */
 
 static tree
-fold_widened_comparison (enum tree_code code, tree type, tree arg0, tree arg1)
+fold_widened_comparison (location_t loc, enum tree_code code,
+                        tree type, tree arg0, tree arg1)
 {
   tree arg0_unw = get_unwidened (arg0, NULL_TREE);
   tree arg1_unw;
@@ -7148,8 +6657,8 @@ fold_widened_comparison (enum tree_code code, tree type, tree arg0, tree arg1)
              && (TREE_CODE (shorter_type) == INTEGER_TYPE
                  || TREE_CODE (shorter_type) == BOOLEAN_TYPE)
              && int_fits_type_p (arg1_unw, shorter_type))))
-    return fold_build2 (code, type, arg0_unw,
-                      fold_convert (shorter_type, arg1_unw));
+    return fold_build2_loc (loc, code, type, arg0_unw,
+                       fold_convert_loc (loc, shorter_type, arg1_unw));
 
   if (TREE_CODE (arg1_unw) != INTEGER_CST
       || TREE_CODE (shorter_type) != INTEGER_TYPE
@@ -7171,27 +6680,27 @@ fold_widened_comparison (enum tree_code code, tree type, tree arg0, tree arg1)
     {
     case EQ_EXPR:
       if (above || below)
-       return omit_one_operand (type, integer_zero_node, arg0);
+       return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
       break;
 
     case NE_EXPR:
       if (above || below)
-       return omit_one_operand (type, integer_one_node, arg0);
+       return omit_one_operand_loc (loc, type, integer_one_node, arg0);
       break;
 
     case LT_EXPR:
     case LE_EXPR:
       if (above)
-       return omit_one_operand (type, integer_one_node, arg0);
+       return omit_one_operand_loc (loc, type, integer_one_node, arg0);
       else if (below)
-       return omit_one_operand (type, integer_zero_node, arg0);
+       return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
 
     case GT_EXPR:
     case GE_EXPR:
       if (above)
-       return omit_one_operand (type, integer_zero_node, arg0);
+       return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
       else if (below)
-       return omit_one_operand (type, integer_one_node, arg0);
+       return omit_one_operand_loc (loc, type, integer_one_node, arg0);
 
     default:
       break;
@@ -7204,7 +6713,7 @@ fold_widened_comparison (enum tree_code code, tree type, tree arg0, tree arg1)
    ARG0 just the signedness is changed.  */
 
 static tree
-fold_sign_changed_comparison (enum tree_code code, tree type,
+fold_sign_changed_comparison (location_t loc, enum tree_code code, tree type,
                              tree arg0, tree arg1)
 {
   tree arg0_inner;
@@ -7229,11 +6738,6 @@ fold_sign_changed_comparison (enum tree_code code, tree type,
   if (TYPE_PRECISION (inner_type) != TYPE_PRECISION (outer_type))
     return NULL_TREE;
 
-  /* If the conversion is from an integral subtype to its basetype
-     leave it alone.  */
-  if (TREE_TYPE (inner_type) == outer_type)
-    return NULL_TREE;
-
   if (TREE_CODE (arg1) != INTEGER_CST
       && !(CONVERT_EXPR_P (arg1)
           && TREE_TYPE (TREE_OPERAND (arg1, 0)) == inner_type))
@@ -7246,24 +6750,24 @@ fold_sign_changed_comparison (enum tree_code code, tree type,
     return NULL_TREE;
 
   if (TREE_CODE (arg1) == INTEGER_CST)
-    arg1 = force_fit_type_double (inner_type, TREE_INT_CST_LOW (arg1),
-                                 TREE_INT_CST_HIGH (arg1), 0,
-                                 TREE_OVERFLOW (arg1));
+    arg1 = force_fit_type_double (inner_type, tree_to_double_int (arg1),
+                                 0, TREE_OVERFLOW (arg1));
   else
-    arg1 = fold_convert (inner_type, arg1);
+    arg1 = fold_convert_loc (loc, inner_type, arg1);
 
-  return fold_build2 (code, type, arg0_inner, arg1);
+  return fold_build2_loc (loc, code, type, arg0_inner, arg1);
 }
 
 /* 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.
-   If the function succeeds, the new address expression is returned.  Otherwise
-   NULL_TREE is returned.  */
+   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.  If the
+   function succeeds, the new address expression is returned.
+   Otherwise NULL_TREE is returned.  LOC is the location of the
+   resulting expression.  */
 
 static tree
-try_move_mult_to_index (tree addr, tree op1)
+try_move_mult_to_index (location_t loc, tree addr, tree op1)
 {
   tree s, delta, step;
   tree ref = TREE_OPERAND (addr, 0), pref;
@@ -7282,7 +6786,7 @@ try_move_mult_to_index (tree addr, tree op1)
 
       STRIP_NOPS (arg0);
       STRIP_NOPS (arg1);
-  
+
       if (TREE_CODE (arg0) == INTEGER_CST)
         {
           s = arg0;
@@ -7312,13 +6816,16 @@ try_move_mult_to_index (tree addr, tree op1)
     {
       if (TREE_CODE (ref) == ARRAY_REF)
        {
+         tree domain;
+
          /* Remember if this was a multi-dimensional array.  */
          if (TREE_CODE (TREE_OPERAND (ref, 0)) == ARRAY_REF)
            mdim = true;
 
-         itype = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (ref, 0)));
-         if (! itype)
+         domain = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (ref, 0)));
+         if (! domain)
            continue;
+         itype = TREE_TYPE (domain);
 
          step = array_ref_element_size (ref);
          if (TREE_CODE (step) != INTEGER_CST)
@@ -7345,18 +6852,17 @@ try_move_mult_to_index (tree addr, tree op1)
              tree tmp;
 
              if (TREE_CODE (TREE_OPERAND (ref, 1)) != INTEGER_CST
-                 || !INTEGRAL_TYPE_P (itype)
-                 || !TYPE_MAX_VALUE (itype)
-                 || TREE_CODE (TYPE_MAX_VALUE (itype)) != INTEGER_CST)
+                 || !TYPE_MAX_VALUE (domain)
+                 || TREE_CODE (TYPE_MAX_VALUE (domain)) != INTEGER_CST)
                continue;
 
-             tmp = fold_binary (PLUS_EXPR, itype,
-                                fold_convert (itype,
-                                              TREE_OPERAND (ref, 1)),
-                                fold_convert (itype, delta));
+             tmp = fold_binary_loc (loc, PLUS_EXPR, itype,
+                                    fold_convert_loc (loc, itype,
+                                                      TREE_OPERAND (ref, 1)),
+                                    fold_convert_loc (loc, itype, delta));
              if (!tmp
                  || TREE_CODE (tmp) != INTEGER_CST
-                 || tree_int_cst_lt (TYPE_MAX_VALUE (itype), tmp))
+                 || tree_int_cst_lt (TYPE_MAX_VALUE (domain), tmp))
                continue;
            }
 
@@ -7374,6 +6880,7 @@ try_move_mult_to_index (tree addr, tree op1)
 
   pref = TREE_OPERAND (addr, 0);
   ret = copy_node (pref);
+  SET_EXPR_LOCATION (ret, loc);
   pos = ret;
 
   while (pref != ref)
@@ -7383,12 +6890,12 @@ try_move_mult_to_index (tree addr, tree op1)
       pos = TREE_OPERAND (pos, 0);
     }
 
-  TREE_OPERAND (pos, 1) = fold_build2 (PLUS_EXPR, itype,
-                                      fold_convert (itype,
-                                                    TREE_OPERAND (pos, 1)),
-                                      fold_convert (itype, delta));
+  TREE_OPERAND (pos, 1) = fold_build2_loc (loc, PLUS_EXPR, itype,
+                                      fold_convert_loc (loc, itype,
+                                                        TREE_OPERAND (pos, 1)),
+                                      fold_convert_loc (loc, itype, delta));
 
-  return fold_build1 (ADDR_EXPR, TREE_TYPE (addr), ret);
+  return fold_build1_loc (loc, ADDR_EXPR, TREE_TYPE (addr), ret);
 }
 
 
@@ -7397,7 +6904,7 @@ try_move_mult_to_index (tree addr, tree op1)
    A < X <= MAX.  INEQ is A + 1 > Y, BOUND is A < X.  */
 
 static tree
-fold_to_nonsharp_ineq_using_bound (tree ineq, tree bound)
+fold_to_nonsharp_ineq_using_bound (location_t loc, tree ineq, tree bound)
 {
   tree a, typea, type = TREE_TYPE (ineq), a1, diff, y;
 
@@ -7432,24 +6939,25 @@ fold_to_nonsharp_ineq_using_bound (tree ineq, tree bound)
   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);
+      tree ta = fold_convert_loc (loc, ssizetype, a);
+      tree ta1 = fold_convert_loc (loc, ssizetype, a1);
+      diff = fold_binary_loc (loc, MINUS_EXPR, ssizetype, ta1, ta);
     }
   else
-   diff = fold_binary (MINUS_EXPR, typea, a1, a);
+    diff = fold_binary_loc (loc, MINUS_EXPR, typea, a1, a);
 
   if (!diff || !integer_onep (diff))
    return NULL_TREE;
 
-  return fold_build2 (GE_EXPR, type, a, y);
+  return fold_build2_loc (loc, GE_EXPR, type, a, y);
 }
 
 /* Fold a sum or difference of at least one multiplication.
    Returns the folded tree or NULL if no simplification could be made.  */
 
 static tree
-fold_plusminus_mult_expr (enum tree_code code, tree type, tree arg0, tree arg1)
+fold_plusminus_mult_expr (location_t loc, enum tree_code code, tree type,
+                         tree arg0, tree arg1)
 {
   tree arg00, arg01, arg10, arg11;
   tree alt0 = NULL_TREE, alt1 = NULL_TREE, same;
@@ -7547,7 +7055,7 @@ fold_plusminus_mult_expr (enum tree_code code, tree type, tree arg0, tree arg1)
             increased the number of multiplications necessary.  */
          && TREE_CODE (arg10) != INTEGER_CST)
         {
-         alt0 = fold_build2 (MULT_EXPR, TREE_TYPE (arg00), arg00,
+         alt0 = fold_build2_loc (loc, MULT_EXPR, TREE_TYPE (arg00), arg00,
                              build_int_cst (TREE_TYPE (arg00),
                                             int01 / int11));
          alt1 = arg10;
@@ -7558,11 +7066,11 @@ fold_plusminus_mult_expr (enum tree_code code, tree type, tree arg0, tree arg1)
     }
 
   if (same)
-    return fold_build2 (MULT_EXPR, type,
-                       fold_build2 (code, type,
-                                    fold_convert (type, alt0),
-                                    fold_convert (type, alt1)),
-                       fold_convert (type, same));
+    return fold_build2_loc (loc, MULT_EXPR, type,
+                       fold_build2_loc (loc, code, type,
+                                    fold_convert_loc (loc, type, alt0),
+                                    fold_convert_loc (loc, type, alt1)),
+                       fold_convert_loc (loc, type, same));
 
   return NULL_TREE;
 }
@@ -7798,13 +7306,14 @@ native_interpret_int (tree type, const unsigned char *ptr, int len)
   int total_bytes = GET_MODE_SIZE (TYPE_MODE (type));
   int byte, offset, word, words;
   unsigned char value;
-  unsigned int HOST_WIDE_INT lo = 0;
-  HOST_WIDE_INT hi = 0;
+  double_int result;
 
   if (total_bytes > len)
     return NULL_TREE;
   if (total_bytes * BITS_PER_UNIT > 2 * HOST_BITS_PER_WIDE_INT)
     return NULL_TREE;
+
+  result = double_int_zero;
   words = total_bytes / UNITS_PER_WORD;
 
   for (byte = 0; byte < total_bytes; byte++)
@@ -7826,13 +7335,13 @@ native_interpret_int (tree type, const unsigned char *ptr, int len)
       value = ptr[offset];
 
       if (bitpos < HOST_BITS_PER_WIDE_INT)
-       lo |= (unsigned HOST_WIDE_INT) value << bitpos;
+       result.low |= (unsigned HOST_WIDE_INT) value << bitpos;
       else
-       hi |= (unsigned HOST_WIDE_INT) value
-             << (bitpos - HOST_BITS_PER_WIDE_INT);
+       result.high |= (unsigned HOST_WIDE_INT) value
+                      << (bitpos - HOST_BITS_PER_WIDE_INT);
     }
 
-  return build_int_cst_wide_type (type, lo, hi);
+  return double_int_to_tree (type, result);
 }
 
 
@@ -7995,23 +7504,31 @@ fold_view_convert_expr (tree type, tree expr)
    to avoid confusing the gimplify process.  */
 
 tree
-build_fold_addr_expr_with_type (tree t, tree ptrtype)
+build_fold_addr_expr_with_type_loc (location_t loc, 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)
+  if (TREE_CODE (t) == INDIRECT_REF)
     {
       t = TREE_OPERAND (t, 0);
 
       if (TREE_TYPE (t) != ptrtype)
-       t = build1 (NOP_EXPR, ptrtype, t);
+       t = build1_loc (loc, NOP_EXPR, ptrtype, t);
+    }
+  else if (TREE_CODE (t) == MEM_REF
+      && integer_zerop (TREE_OPERAND (t, 1)))
+    return TREE_OPERAND (t, 0);
+  else if (TREE_CODE (t) == VIEW_CONVERT_EXPR)
+    {
+      t = build_fold_addr_expr_loc (loc, TREE_OPERAND (t, 0));
+
+      if (TREE_TYPE (t) != ptrtype)
+       t = fold_convert_loc (loc, ptrtype, t);
     }
   else
-    t = build1 (ADDR_EXPR, ptrtype, t);
+    t = build1_loc (loc, ADDR_EXPR, ptrtype, t);
 
   return t;
 }
@@ -8019,11 +7536,11 @@ build_fold_addr_expr_with_type (tree t, tree ptrtype)
 /* Build an expression for the address of T.  */
 
 tree
-build_fold_addr_expr (tree t)
+build_fold_addr_expr_loc (location_t loc, tree t)
 {
   tree ptrtype = build_pointer_type (TREE_TYPE (t));
 
-  return build_fold_addr_expr_with_type (t, ptrtype);
+  return build_fold_addr_expr_with_type_loc (loc, t, ptrtype);
 }
 
 /* Fold a unary expression of code CODE and type TYPE with operand
@@ -8031,7 +7548,7 @@ build_fold_addr_expr (tree t)
    Otherwise, return NULL_TREE.  */
 
 tree
-fold_unary (enum tree_code code, tree type, tree op0)
+fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
 {
   tree tem;
   tree arg0;
@@ -8071,20 +7588,22 @@ fold_unary (enum tree_code code, tree type, tree op0)
     {
       if (TREE_CODE (arg0) == COMPOUND_EXPR)
        return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
-                      fold_build1 (code, type,
-                                   fold_convert (TREE_TYPE (op0),
-                                                 TREE_OPERAND (arg0, 1))));
+                      fold_build1_loc (loc, code, type,
+                                   fold_convert_loc (loc, TREE_TYPE (op0),
+                                                     TREE_OPERAND (arg0, 1))));
       else if (TREE_CODE (arg0) == COND_EXPR)
        {
          tree arg01 = TREE_OPERAND (arg0, 1);
          tree arg02 = TREE_OPERAND (arg0, 2);
          if (! VOID_TYPE_P (TREE_TYPE (arg01)))
-           arg01 = fold_build1 (code, type,
-                                fold_convert (TREE_TYPE (op0), arg01));
+           arg01 = fold_build1_loc (loc, code, type,
+                                fold_convert_loc (loc,
+                                                  TREE_TYPE (op0), arg01));
          if (! VOID_TYPE_P (TREE_TYPE (arg02)))
-           arg02 = fold_build1 (code, type,
-                                fold_convert (TREE_TYPE (op0), arg02));
-         tem = fold_build3 (COND_EXPR, type, TREE_OPERAND (arg0, 0),
+           arg02 = fold_build1_loc (loc, code, type,
+                                fold_convert_loc (loc,
+                                                  TREE_TYPE (op0), arg02));
+         tem = fold_build3_loc (loc, COND_EXPR, type, TREE_OPERAND (arg0, 0),
                             arg01, arg02);
 
          /* If this was a conversion, and all we did was to move into
@@ -8110,30 +7629,16 @@ fold_unary (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)));
+           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))
-       {
-         if (TREE_CODE (type) == BOOLEAN_TYPE)
-           {
-             arg0 = copy_node (arg0);
-             TREE_TYPE (arg0) = type;
-             return arg0;
-           }
-         else if (TREE_CODE (type) != INTEGER_TYPE)
-           return fold_build3 (COND_EXPR, type, arg0,
-                               fold_build1 (code, type,
-                                            integer_one_node),
-                               fold_build1 (code, type,
-                                            integer_zero_node));
-       }
    }
 
   switch (code)
@@ -8143,7 +7648,7 @@ fold_unary (enum tree_code code, tree type, tree op0)
         barriers can be removed.  */
       if (CONSTANT_CLASS_P (op0)
          || TREE_CODE (op0) == PAREN_EXPR)
-       return fold_convert (type, op0);
+       return fold_convert_loc (loc, type, op0);
       return NULL_TREE;
 
     CASE_CONVERT:
@@ -8151,11 +7656,11 @@ fold_unary (enum tree_code code, tree type, tree op0)
     case FIX_TRUNC_EXPR:
       if (TREE_TYPE (op0) == type)
        return op0;
-      
+
       /* If we have (type) (a CMP b) and type is an integral type, return
          new expression involving the new type.  */
       if (COMPARISON_CLASS_P (op0) && INTEGRAL_TYPE_P (type))
-       return fold_build2 (TREE_CODE (op0), type, TREE_OPERAND (op0, 0),
+       return fold_build2_loc (loc, TREE_CODE (op0), type, TREE_OPERAND (op0, 0),
                            TREE_OPERAND (op0, 1));
 
       /* Handle cases of two conversions in a row.  */
@@ -8190,7 +7695,7 @@ fold_unary (enum tree_code code, tree type, tree op0)
              && (((inter_int || inter_ptr) && final_int)
                  || (inter_float && final_float))
              && inter_prec >= final_prec)
-           return fold_build1 (code, type, TREE_OPERAND (op0, 0));
+           return fold_build1_loc (loc, code, type, TREE_OPERAND (op0, 0));
 
          /* Likewise, if the intermediate and initial types are either both
             float or both integer, we don't need the middle conversion if the
@@ -8208,14 +7713,14 @@ fold_unary (enum tree_code code, tree type, tree op0)
                    && TYPE_MODE (type) == TYPE_MODE (inter_type))
              && ! final_ptr
              && (! final_vec || inter_prec == inside_prec))
-           return fold_build1 (code, type, TREE_OPERAND (op0, 0));
+           return fold_build1_loc (loc, 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 (op0, 0));
+           return fold_build1_loc (loc, code, type, TREE_OPERAND (op0, 0));
 
          /* Two conversions in a row are not needed unless:
             - some conversion is floating-point (overstrict for now), or
@@ -8240,7 +7745,7 @@ fold_unary (enum tree_code code, tree type, tree op0)
              && ! (final_ptr && inside_prec != inter_prec)
              && ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (type))
                    && TYPE_MODE (type) == TYPE_MODE (inter_type)))
-           return fold_build1 (code, type, TREE_OPERAND (op0, 0));
+           return fold_build1_loc (loc, code, type, TREE_OPERAND (op0, 0));
        }
 
       /* Handle (T *)&A.B.C for A being of type T and B and C
@@ -8259,11 +7764,13 @@ fold_unary (enum tree_code code, tree type, tree op0)
                                      &mode, &unsignedp, &volatilep, false);
          /* If the reference was to a (constant) zero offset, we can use
             the address of the base if it has the same base type
-            as the result type.  */
+            as the result type and the pointer type is unqualified.  */
          if (! offset && bitpos == 0
-             && TYPE_MAIN_VARIANT (TREE_TYPE (type))
+             && (TYPE_MAIN_VARIANT (TREE_TYPE (type))
                  == TYPE_MAIN_VARIANT (TREE_TYPE (base)))
-           return fold_convert (type, build_fold_addr_expr (base));
+             && TYPE_QUALS (type) == TYPE_UNQUALIFIED)
+           return fold_convert_loc (loc, type,
+                                    build_fold_addr_expr_loc (loc, base));
         }
 
       if (TREE_CODE (op0) == MODIFY_EXPR
@@ -8275,9 +7782,9 @@ fold_unary (enum tree_code code, tree type, tree op0)
        {
          /* Don't leave an assignment inside a conversion
             unless assigning a bitfield.  */
-         tem = fold_build1 (code, type, TREE_OPERAND (op0, 1));
+         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;
          return tem;
@@ -8291,17 +7798,16 @@ fold_unary (enum tree_code code, tree type, tree op0)
         transformation effectively doesn't preserve non-maximal ranges.  */
       if (TREE_CODE (type) == INTEGER_TYPE
          && TREE_CODE (op0) == BIT_AND_EXPR
-         && TREE_CODE (TREE_OPERAND (op0, 1)) == INTEGER_CST
-         /* Not if the conversion is to the sub-type.  */
-         && TREE_TYPE (type) != TREE_TYPE (op0))
+         && TREE_CODE (TREE_OPERAND (op0, 1)) == INTEGER_CST)
        {
-         tree and = op0;
-         tree and0 = TREE_OPERAND (and, 0), and1 = TREE_OPERAND (and, 1);
+         tree and_expr = op0;
+         tree and0 = TREE_OPERAND (and_expr, 0);
+         tree and1 = TREE_OPERAND (and_expr, 1);
          int change = 0;
 
-         if (TYPE_UNSIGNED (TREE_TYPE (and))
+         if (TYPE_UNSIGNED (TREE_TYPE (and_expr))
              || (TYPE_PRECISION (type)
-                 <= TYPE_PRECISION (TREE_TYPE (and))))
+                 <= TYPE_PRECISION (TREE_TYPE (and_expr))))
            change = 1;
          else if (TYPE_PRECISION (TREE_TYPE (and1))
                   <= HOST_BITS_PER_WIDE_INT
@@ -8320,18 +7826,17 @@ fold_unary (enum tree_code code, tree type, tree op0)
                      == ZERO_EXTEND))
                {
                  tree uns = unsigned_type_for (TREE_TYPE (and0));
-                 and0 = fold_convert (uns, and0);
-                 and1 = fold_convert (uns, and1);
+                 and0 = fold_convert_loc (loc, uns, and0);
+                 and1 = fold_convert_loc (loc, uns, and1);
                }
 #endif
            }
          if (change)
            {
-             tem = force_fit_type_double (type, TREE_INT_CST_LOW (and1),
-                                          TREE_INT_CST_HIGH (and1), 0,
-                                          TREE_OVERFLOW (and1));
-             return fold_build2 (BIT_AND_EXPR, type,
-                                 fold_convert (type, and0), tem);
+             tem = force_fit_type_double (type, tree_to_double_int (and1),
+                                          0, TREE_OVERFLOW (and1));
+             return fold_build2_loc (loc, BIT_AND_EXPR, type,
+                                 fold_convert_loc (loc, type, and0), tem);
            }
        }
 
@@ -8347,8 +7852,10 @@ fold_unary (enum tree_code code, tree type, tree op0)
          tree arg00 = TREE_OPERAND (arg0, 0);
          tree arg01 = TREE_OPERAND (arg0, 1);
 
-         return fold_build2 (TREE_CODE (arg0), type, fold_convert (type, arg00),
-                             fold_convert (sizetype, arg01));
+         return fold_build2_loc (loc,
+                             TREE_CODE (arg0), type,
+                             fold_convert_loc (loc, type, arg00),
+                             fold_convert_loc (loc, sizetype, arg01));
        }
 
       /* Convert (T1)(~(T2)X) into ~(T1)X if T1 and T2 are integral types
@@ -8363,7 +7870,8 @@ fold_unary (enum tree_code code, tree type, tree op0)
          tem = TREE_OPERAND (TREE_OPERAND (op0, 0), 0);
          if (INTEGRAL_TYPE_P (TREE_TYPE (tem))
              && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (tem)))
-           return fold_build1 (BIT_NOT_EXPR, type, fold_convert (type, tem));
+           return fold_build1_loc (loc, BIT_NOT_EXPR, type,
+                               fold_convert_loc (loc, type, tem));
        }
 
       /* Convert (T1)(X * Y) into (T1)X * (T1)Y if T1 is narrower than the
@@ -8382,18 +7890,23 @@ fold_unary (enum tree_code code, tree type, tree op0)
 
          if (TYPE_PRECISION (mult_type) < TYPE_PRECISION (TREE_TYPE (op0)))
            {
-             tem = fold_build2 (MULT_EXPR, mult_type,
-                                fold_convert (mult_type,
-                                              TREE_OPERAND (op0, 0)),
-                                fold_convert (mult_type,
-                                              TREE_OPERAND (op0, 1)));
-             return fold_convert (type, tem);
+             tem = fold_build2_loc (loc, MULT_EXPR, mult_type,
+                                fold_convert_loc (loc, mult_type,
+                                                  TREE_OPERAND (op0, 0)),
+                                fold_convert_loc (loc, mult_type,
+                                                  TREE_OPERAND (op0, 1)));
+             return fold_convert_loc (loc, type, tem);
            }
        }
 
       tem = fold_convert_const (code, type, op0);
       return tem ? tem : NULL_TREE;
 
+    case ADDR_SPACE_CONVERT_EXPR:
+      if (integer_zerop (arg0))
+       return fold_convert_const (code, type, arg0);
+      return NULL_TREE;
+
     case FIXED_CONVERT_EXPR:
       tem = fold_convert_const (code, type, arg0);
       return tem ? tem : NULL_TREE;
@@ -8402,7 +7915,11 @@ fold_unary (enum tree_code code, tree type, tree op0)
       if (TREE_TYPE (op0) == type)
        return op0;
       if (TREE_CODE (op0) == VIEW_CONVERT_EXPR)
-       return fold_build1 (VIEW_CONVERT_EXPR, type, TREE_OPERAND (op0, 0));
+       return fold_build1_loc (loc, VIEW_CONVERT_EXPR,
+                           type, TREE_OPERAND (op0, 0));
+      if (TREE_CODE (op0) == MEM_REF)
+       return fold_build2_loc (loc, MEM_REF, type,
+                               TREE_OPERAND (op0, 0), TREE_OPERAND (op0, 1));
 
       /* For integral conversions with the same precision or pointer
         conversions use a NOP_EXPR instead.  */
@@ -8410,12 +7927,8 @@ fold_unary (enum tree_code code, tree type, tree op0)
           || POINTER_TYPE_P (type))
          && (INTEGRAL_TYPE_P (TREE_TYPE (op0))
              || POINTER_TYPE_P (TREE_TYPE (op0)))
-         && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (op0))
-         /* Do not muck with VIEW_CONVERT_EXPRs that convert from
-            a sub-type to its base type as generated by the Ada FE.  */
-         && !(INTEGRAL_TYPE_P (TREE_TYPE (op0))
-              && TREE_TYPE (TREE_TYPE (op0))))
-       return fold_convert (type, op0);
+         && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (op0)))
+       return fold_convert_loc (loc, type, op0);
 
       /* Strip inner integral conversions that do not change the precision.  */
       if (CONVERT_EXPR_P (op0)
@@ -8425,30 +7938,32 @@ fold_unary (enum tree_code code, tree type, tree op0)
              || POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (op0, 0))))
          && (TYPE_PRECISION (TREE_TYPE (op0))
              == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op0, 0)))))
-       return fold_build1 (VIEW_CONVERT_EXPR, type, TREE_OPERAND (op0, 0));
+       return fold_build1_loc (loc, VIEW_CONVERT_EXPR,
+                           type, TREE_OPERAND (op0, 0));
 
       return fold_view_convert_expr (type, op0);
 
     case NEGATE_EXPR:
-      tem = fold_negate_expr (arg0);
+      tem = fold_negate_expr (loc, arg0);
       if (tem)
-       return fold_convert (type, tem);
+       return fold_convert_loc (loc, type, tem);
       return NULL_TREE;
 
     case ABS_EXPR:
       if (TREE_CODE (arg0) == INTEGER_CST || TREE_CODE (arg0) == REAL_CST)
        return fold_abs_const (arg0, type);
       else if (TREE_CODE (arg0) == NEGATE_EXPR)
-       return fold_build1 (ABS_EXPR, type, TREE_OPERAND (arg0, 0));
+       return fold_build1_loc (loc, ABS_EXPR, type, TREE_OPERAND (arg0, 0));
       /* Convert fabs((double)float) into (double)fabsf(float).  */
       else if (TREE_CODE (arg0) == NOP_EXPR
               && TREE_CODE (type) == REAL_TYPE)
        {
          tree targ0 = strip_float_extensions (arg0);
          if (targ0 != arg0)
-           return fold_convert (type, fold_build1 (ABS_EXPR,
-                                                   TREE_TYPE (targ0),
-                                                   targ0));
+           return fold_convert_loc (loc, type,
+                                    fold_build1_loc (loc, ABS_EXPR,
+                                                 TREE_TYPE (targ0),
+                                                 targ0));
        }
       /* ABS_EXPR<ABS_EXPR<x>> = ABS_EXPR<x> even if flag_wrapv is on.  */
       else if (TREE_CODE (arg0) == ABS_EXPR)
@@ -8461,40 +7976,42 @@ fold_unary (enum tree_code code, tree type, tree op0)
        {
          tem = fold_strip_sign_ops (arg0);
          if (tem)
-           return fold_build1 (ABS_EXPR, type, fold_convert (type, tem));
+           return fold_build1_loc (loc, ABS_EXPR, type,
+                               fold_convert_loc (loc, type, tem));
        }
       return NULL_TREE;
 
     case CONJ_EXPR:
       if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
-       return fold_convert (type, arg0);
+       return fold_convert_loc (loc, type, arg0);
       if (TREE_CODE (arg0) == COMPLEX_EXPR)
        {
          tree itype = TREE_TYPE (type);
-         tree rpart = fold_convert (itype, TREE_OPERAND (arg0, 0));
-         tree ipart = fold_convert (itype, TREE_OPERAND (arg0, 1));
-         return fold_build2 (COMPLEX_EXPR, type, rpart, negate_expr (ipart));
+         tree rpart = fold_convert_loc (loc, itype, TREE_OPERAND (arg0, 0));
+         tree ipart = fold_convert_loc (loc, itype, TREE_OPERAND (arg0, 1));
+         return fold_build2_loc (loc, COMPLEX_EXPR, type, rpart,
+                             negate_expr (ipart));
        }
       if (TREE_CODE (arg0) == COMPLEX_CST)
        {
          tree itype = TREE_TYPE (type);
-         tree rpart = fold_convert (itype, TREE_REALPART (arg0));
-         tree ipart = fold_convert (itype, TREE_IMAGPART (arg0));
+         tree rpart = fold_convert_loc (loc, itype, TREE_REALPART (arg0));
+         tree ipart = fold_convert_loc (loc, itype, TREE_IMAGPART (arg0));
          return build_complex (type, rpart, negate_expr (ipart));
        }
       if (TREE_CODE (arg0) == CONJ_EXPR)
-       return fold_convert (type, TREE_OPERAND (arg0, 0));
+       return fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
       return NULL_TREE;
 
     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 fold_convert (type, TREE_OPERAND (arg0, 0));
+       return fold_convert_loc (loc, type, 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,
-                           fold_convert (type, TREE_OPERAND (arg0, 0)),
+       return fold_build2_loc (loc, MINUS_EXPR, type,
+                           fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0)),
                            build_int_cst (type, 1));
       /* Convert ~ (A - 1) or ~ (A + -1) to -A.  */
       else if (INTEGRAL_TYPE_P (type)
@@ -8502,21 +8019,24 @@ fold_unary (enum tree_code code, tree type, tree op0)
                    && integer_onep (TREE_OPERAND (arg0, 1)))
                   || (TREE_CODE (arg0) == PLUS_EXPR
                       && integer_all_onesp (TREE_OPERAND (arg0, 1)))))
-       return fold_build1 (NEGATE_EXPR, type,
-                           fold_convert (type, TREE_OPERAND (arg0, 0)));
+       return fold_build1_loc (loc, NEGATE_EXPR, type,
+                           fold_convert_loc (loc, type,
+                                             TREE_OPERAND (arg0, 0)));
       /* Convert ~(X ^ Y) to ~X ^ Y or X ^ ~Y if ~X or ~Y simplify.  */
       else if (TREE_CODE (arg0) == BIT_XOR_EXPR
-              && (tem = fold_unary (BIT_NOT_EXPR, type,
-                                    fold_convert (type,
-                                                  TREE_OPERAND (arg0, 0)))))
-       return fold_build2 (BIT_XOR_EXPR, type, tem,
-                           fold_convert (type, TREE_OPERAND (arg0, 1)));
+              && (tem = fold_unary_loc (loc, BIT_NOT_EXPR, type,
+                                    fold_convert_loc (loc, type,
+                                                      TREE_OPERAND (arg0, 0)))))
+       return fold_build2_loc (loc, BIT_XOR_EXPR, type, tem,
+                           fold_convert_loc (loc, type,
+                                             TREE_OPERAND (arg0, 1)));
       else if (TREE_CODE (arg0) == BIT_XOR_EXPR
-              && (tem = fold_unary (BIT_NOT_EXPR, type,
-                                    fold_convert (type,
-                                                  TREE_OPERAND (arg0, 1)))))
-       return fold_build2 (BIT_XOR_EXPR, type,
-                           fold_convert (type, TREE_OPERAND (arg0, 0)), tem);
+              && (tem = fold_unary_loc (loc, BIT_NOT_EXPR, type,
+                                    fold_convert_loc (loc, type,
+                                                      TREE_OPERAND (arg0, 1)))))
+       return fold_build2_loc (loc, BIT_XOR_EXPR, type,
+                           fold_convert_loc (loc, type,
+                                             TREE_OPERAND (arg0, 0)), tem);
       /* Perform BIT_NOT_EXPR on each element individually.  */
       else if (TREE_CODE (arg0) == VECTOR_CST)
        {
@@ -8528,7 +8048,7 @@ fold_unary (enum tree_code code, tree type, tree op0)
              if (elements)
                {
                  elem = TREE_VALUE (elements);
-                 elem = fold_unary (BIT_NOT_EXPR, TREE_TYPE (type), elem);
+                 elem = fold_unary_loc (loc, BIT_NOT_EXPR, TREE_TYPE (type), elem);
                  if (elem == NULL_TREE)
                    break;
                  elements = TREE_CHAIN (elements);
@@ -8546,40 +8066,41 @@ fold_unary (enum tree_code code, tree type, tree op0)
     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);
+          arg0 = fold_convert_loc (loc, 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 = fold_truth_not_expr (arg0);
+      tem = fold_truth_not_expr (loc, arg0);
       if (!tem)
        return NULL_TREE;
-      return fold_convert (type, tem);
+      return fold_convert_loc (loc, type, tem);
 
     case REALPART_EXPR:
       if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
-       return fold_convert (type, arg0);
+       return fold_convert_loc (loc, type, arg0);
       if (TREE_CODE (arg0) == COMPLEX_EXPR)
-       return omit_one_operand (type, TREE_OPERAND (arg0, 0),
+       return omit_one_operand_loc (loc, type, TREE_OPERAND (arg0, 0),
                                 TREE_OPERAND (arg0, 1));
       if (TREE_CODE (arg0) == COMPLEX_CST)
-       return fold_convert (type, TREE_REALPART (arg0));
+       return fold_convert_loc (loc, type, TREE_REALPART (arg0));
       if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
        {
          tree itype = TREE_TYPE (TREE_TYPE (arg0));
-         tem = fold_build2 (TREE_CODE (arg0), itype,
-                            fold_build1 (REALPART_EXPR, itype,
+         tem = fold_build2_loc (loc, TREE_CODE (arg0), itype,
+                            fold_build1_loc (loc, REALPART_EXPR, itype,
                                          TREE_OPERAND (arg0, 0)),
-                            fold_build1 (REALPART_EXPR, itype,
+                            fold_build1_loc (loc, REALPART_EXPR, itype,
                                          TREE_OPERAND (arg0, 1)));
-         return fold_convert (type, tem);
+         return fold_convert_loc (loc, type, tem);
        }
       if (TREE_CODE (arg0) == CONJ_EXPR)
        {
          tree itype = TREE_TYPE (TREE_TYPE (arg0));
-         tem = fold_build1 (REALPART_EXPR, itype, TREE_OPERAND (arg0, 0));
-         return fold_convert (type, tem);
+         tem = fold_build1_loc (loc, REALPART_EXPR, itype,
+                            TREE_OPERAND (arg0, 0));
+         return fold_convert_loc (loc, type, tem);
        }
       if (TREE_CODE (arg0) == CALL_EXPR)
        {
@@ -8590,7 +8111,7 @@ fold_unary (enum tree_code code, tree type, tree op0)
              CASE_FLT_FN (BUILT_IN_CEXPI):
                fn = mathfn_built_in (type, BUILT_IN_COS);
                if (fn)
-                 return build_call_expr (fn, 1, CALL_EXPR_ARG (arg0, 0));
+                 return build_call_expr_loc (loc, fn, 1, CALL_EXPR_ARG (arg0, 0));
                break;
 
              default:
@@ -8601,27 +8122,27 @@ fold_unary (enum tree_code code, tree type, tree op0)
 
     case IMAGPART_EXPR:
       if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
-       return fold_convert (type, integer_zero_node);
+       return build_zero_cst (type);
       if (TREE_CODE (arg0) == COMPLEX_EXPR)
-       return omit_one_operand (type, TREE_OPERAND (arg0, 1),
+       return omit_one_operand_loc (loc, type, TREE_OPERAND (arg0, 1),
                                 TREE_OPERAND (arg0, 0));
       if (TREE_CODE (arg0) == COMPLEX_CST)
-       return fold_convert (type, TREE_IMAGPART (arg0));
+       return fold_convert_loc (loc, type, TREE_IMAGPART (arg0));
       if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
        {
          tree itype = TREE_TYPE (TREE_TYPE (arg0));
-         tem = fold_build2 (TREE_CODE (arg0), itype,
-                            fold_build1 (IMAGPART_EXPR, itype,
+         tem = fold_build2_loc (loc, TREE_CODE (arg0), itype,
+                            fold_build1_loc (loc, IMAGPART_EXPR, itype,
                                          TREE_OPERAND (arg0, 0)),
-                            fold_build1 (IMAGPART_EXPR, itype,
+                            fold_build1_loc (loc, IMAGPART_EXPR, itype,
                                          TREE_OPERAND (arg0, 1)));
-         return fold_convert (type, tem);
+         return fold_convert_loc (loc, type, tem);
        }
       if (TREE_CODE (arg0) == CONJ_EXPR)
        {
          tree itype = TREE_TYPE (TREE_TYPE (arg0));
-         tem = fold_build1 (IMAGPART_EXPR, itype, TREE_OPERAND (arg0, 0));
-         return fold_convert (type, negate_expr (tem));
+         tem = fold_build1_loc (loc, IMAGPART_EXPR, itype, TREE_OPERAND (arg0, 0));
+         return fold_convert_loc (loc, type, negate_expr (tem));
        }
       if (TREE_CODE (arg0) == CALL_EXPR)
        {
@@ -8632,7 +8153,7 @@ fold_unary (enum tree_code code, tree type, tree op0)
              CASE_FLT_FN (BUILT_IN_CEXPI):
                fn = mathfn_built_in (type, BUILT_IN_SIN);
                if (fn)
-                 return build_call_expr (fn, 1, CALL_EXPR_ARG (arg0, 0));
+                 return build_call_expr_loc (loc, fn, 1, CALL_EXPR_ARG (arg0, 0));
                break;
 
              default:
@@ -8641,6 +8162,19 @@ fold_unary (enum tree_code code, tree type, tree op0)
        }
       return NULL_TREE;
 
+    case INDIRECT_REF:
+      /* Fold *&X to X if X is an lvalue.  */
+      if (TREE_CODE (op0) == ADDR_EXPR)
+       {
+         tree op00 = TREE_OPERAND (op0, 0);
+         if ((TREE_CODE (op00) == VAR_DECL
+              || TREE_CODE (op00) == PARM_DECL
+              || TREE_CODE (op00) == RESULT_DECL)
+             && !TREE_READONLY (op00))
+           return op00;
+       }
+      return NULL_TREE;
+
     default:
       return NULL_TREE;
     } /* switch (code) */
@@ -8652,9 +8186,10 @@ fold_unary (enum tree_code code, tree type, tree op0)
    have implementation defined behavior and retaining the TREE_OVERFLOW
    flag here would confuse later passes such as VRP.  */
 tree
-fold_unary_ignore_overflow (enum tree_code code, tree type, tree op0)
+fold_unary_ignore_overflow_loc (location_t loc, enum tree_code code,
+                               tree type, tree op0)
 {
-  tree res = fold_unary (code, type, op0);
+  tree res = fold_unary_loc (loc, code, type, op0);
   if (res
       && TREE_CODE (res) == INTEGER_CST
       && TREE_CODE (op0) == INTEGER_CST
@@ -8670,7 +8205,7 @@ fold_unary_ignore_overflow (enum tree_code code, tree type, tree op0)
    return NULL_TREE.  */
 
 static tree
-fold_minmax (enum tree_code code, tree type, tree op0, tree op1)
+fold_minmax (location_t loc, enum tree_code code, tree type, tree op0, tree op1)
 {
   enum tree_code compl_code;
 
@@ -8684,25 +8219,25 @@ fold_minmax (enum tree_code code, tree type, tree op0, tree op1)
   /* MIN (MAX (a, b), b) == b.  */
   if (TREE_CODE (op0) == compl_code
       && operand_equal_p (TREE_OPERAND (op0, 1), op1, 0))
-    return omit_one_operand (type, op1, TREE_OPERAND (op0, 0));
+    return omit_one_operand_loc (loc, type, op1, TREE_OPERAND (op0, 0));
 
   /* MIN (MAX (b, a), b) == b.  */
   if (TREE_CODE (op0) == compl_code
       && operand_equal_p (TREE_OPERAND (op0, 0), op1, 0)
       && reorder_operands_p (TREE_OPERAND (op0, 1), op1))
-    return omit_one_operand (type, op1, TREE_OPERAND (op0, 1));
+    return omit_one_operand_loc (loc, type, op1, TREE_OPERAND (op0, 1));
 
   /* MIN (a, MAX (a, b)) == a.  */
   if (TREE_CODE (op1) == compl_code
       && operand_equal_p (op0, TREE_OPERAND (op1, 0), 0)
       && reorder_operands_p (op0, TREE_OPERAND (op1, 1)))
-    return omit_one_operand (type, op0, TREE_OPERAND (op1, 1));
+    return omit_one_operand_loc (loc, type, op0, TREE_OPERAND (op1, 1));
 
   /* MIN (a, MAX (b, a)) == a.  */
   if (TREE_CODE (op1) == compl_code
       && operand_equal_p (op0, TREE_OPERAND (op1, 1), 0)
       && reorder_operands_p (op0, TREE_OPERAND (op1, 0)))
-    return omit_one_operand (type, op0, TREE_OPERAND (op1, 0));
+    return omit_one_operand_loc (loc, type, op0, TREE_OPERAND (op1, 0));
 
   return NULL_TREE;
 }
@@ -8716,7 +8251,7 @@ fold_minmax (enum tree_code code, tree type, tree op0, tree op1)
    valid if signed overflow is undefined.  */
 
 static tree
-maybe_canonicalize_comparison_1 (enum tree_code code, tree type,
+maybe_canonicalize_comparison_1 (location_t loc, enum tree_code code, tree type,
                                 tree arg0, tree arg1,
                                 bool *strict_overflow_p)
 {
@@ -8807,15 +8342,15 @@ maybe_canonicalize_comparison_1 (enum tree_code code, tree type,
     return NULL_TREE;
 
   t = int_const_binop (sgn0 == -1 ? PLUS_EXPR : MINUS_EXPR,
-                      cst0, build_int_cst (TREE_TYPE (cst0), 1), 0);
+                      cst0, build_int_cst (TREE_TYPE (cst0), 1));
   if (code0 != INTEGER_CST)
-    t = fold_build2 (code0, TREE_TYPE (arg0), TREE_OPERAND (arg0, 0), t);
+    t = fold_build2_loc (loc, code0, TREE_TYPE (arg0), TREE_OPERAND (arg0, 0), t);
 
   /* If swapping might yield to a more canonical form, do so.  */
   if (swap)
-    return fold_build2 (swap_tree_comparison (code), type, arg1, t);
+    return fold_build2_loc (loc, swap_tree_comparison (code), type, arg1, t);
   else
-    return fold_build2 (code, type, t, arg1);
+    return fold_build2_loc (loc, code, type, t, arg1);
 }
 
 /* Canonicalize the comparison ARG0 CODE ARG1 with type TYPE with undefined
@@ -8825,7 +8360,7 @@ maybe_canonicalize_comparison_1 (enum tree_code code, tree type,
    Returns the canonicalized tree if changed, otherwise NULL_TREE.  */
 
 static tree
-maybe_canonicalize_comparison (enum tree_code code, tree type,
+maybe_canonicalize_comparison (location_t loc, enum tree_code code, tree type,
                               tree arg0, tree arg1)
 {
   tree t;
@@ -8835,7 +8370,7 @@ maybe_canonicalize_comparison (enum tree_code code, tree type,
 
   /* Try canonicalization by simplifying arg0.  */
   strict_overflow_p = false;
-  t = maybe_canonicalize_comparison_1 (code, type, arg0, arg1,
+  t = maybe_canonicalize_comparison_1 (loc, code, type, arg0, arg1,
                                       &strict_overflow_p);
   if (t)
     {
@@ -8848,7 +8383,7 @@ maybe_canonicalize_comparison (enum tree_code code, tree type,
      comparison.  */
   code = swap_tree_comparison (code);
   strict_overflow_p = false;
-  t = maybe_canonicalize_comparison_1 (code, type, arg1, arg0,
+  t = maybe_canonicalize_comparison_1 (loc, code, type, arg1, arg0,
                                       &strict_overflow_p);
   if (t && strict_overflow_p)
     fold_overflow_warning (warnmsg, WARN_STRICT_OVERFLOW_MAGNITUDE);
@@ -8920,7 +8455,8 @@ pointer_may_wrap_p (tree base, tree offset, HOST_WIDE_INT bitpos)
    the folded comparison or NULL_TREE.  */
 
 static tree
-fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
+fold_comparison (location_t loc, enum tree_code code, tree type,
+                tree op0, tree op1)
 {
   tree arg0, arg1, tem;
 
@@ -8936,7 +8472,7 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
 
   /* If one arg is a real or integer constant, put it last.  */
   if (tree_swap_operands_p (arg0, arg1, true))
-    return fold_build2 (swap_tree_comparison (code), type, op1, op0);
+    return fold_build2_loc (loc, swap_tree_comparison (code), type, op1, op0);
 
   /* Transform comparisons of the form X +- C1 CMP C2 to X CMP C2 +- C1.  */
   if ((TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
@@ -8953,7 +8489,7 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
       int lhs_add;
       lhs_add = TREE_CODE (arg0) != PLUS_EXPR;
 
-      lhs = fold_build2 (lhs_add ? PLUS_EXPR : MINUS_EXPR,
+      lhs = fold_build2_loc (loc, lhs_add ? PLUS_EXPR : MINUS_EXPR,
                         TREE_TYPE (arg1), const2, const1);
 
       /* If the constant operation overflowed this can be
@@ -8982,22 +8518,23 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
          if (code2 == LT_EXPR
              || code2 == LE_EXPR
              || code2 == EQ_EXPR)
-           return omit_one_operand (type, boolean_false_node, variable);
+           return omit_one_operand_loc (loc, type, boolean_false_node, variable);
          else if (code2 == NE_EXPR
                   || code2 == GE_EXPR
                   || code2 == GT_EXPR)
-           return omit_one_operand (type, boolean_true_node, variable);
+           return omit_one_operand_loc (loc, type, boolean_true_node, variable);
        }
 
       if (TREE_CODE (lhs) == TREE_CODE (arg1)
          && (TREE_CODE (lhs) != INTEGER_CST
              || !TREE_OVERFLOW (lhs)))
        {
-         fold_overflow_warning (("assuming signed overflow does not occur "
-                                 "when changing X +- C1 cmp C2 to "
-                                 "X cmp C1 +- C2"),
-                                WARN_STRICT_OVERFLOW_COMPARISON);
-         return fold_build2 (code, type, variable, lhs);
+         if (code != EQ_EXPR && code != NE_EXPR)
+           fold_overflow_warning ("assuming signed overflow does not occur "
+                                  "when changing X +- C1 cmp C2 to "
+                                  "X cmp C1 +- C2",
+                                  WARN_STRICT_OVERFLOW_COMPARISON);
+         return fold_build2_loc (loc, code, type, variable, lhs);
        }
     }
 
@@ -9035,6 +8572,12 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
       else if (TREE_CODE (arg0) == POINTER_PLUS_EXPR)
        {
          base0 = TREE_OPERAND (arg0, 0);
+         STRIP_SIGN_NOPS (base0);
+         if (TREE_CODE (base0) == ADDR_EXPR)
+           {
+             base0 = TREE_OPERAND (base0, 0);
+             indirect_base0 = true;
+           }
          offset0 = TREE_OPERAND (arg0, 1);
        }
 
@@ -9052,12 +8595,42 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
       else if (TREE_CODE (arg1) == POINTER_PLUS_EXPR)
        {
          base1 = TREE_OPERAND (arg1, 0);
+         STRIP_SIGN_NOPS (base1);
+         if (TREE_CODE (base1) == ADDR_EXPR)
+           {
+             base1 = TREE_OPERAND (base1, 0);
+             indirect_base1 = true;
+           }
          offset1 = TREE_OPERAND (arg1, 1);
        }
 
+      /* A local variable can never be pointed to by
+         the default SSA name of an incoming parameter.  */
+      if ((TREE_CODE (arg0) == ADDR_EXPR
+           && indirect_base0
+           && TREE_CODE (base0) == VAR_DECL
+           && auto_var_in_fn_p (base0, current_function_decl)
+           && !indirect_base1
+           && TREE_CODE (base1) == SSA_NAME
+           && TREE_CODE (SSA_NAME_VAR (base1)) == PARM_DECL
+           && SSA_NAME_IS_DEFAULT_DEF (base1))
+          || (TREE_CODE (arg1) == ADDR_EXPR
+              && indirect_base1
+              && TREE_CODE (base1) == VAR_DECL
+              && auto_var_in_fn_p (base1, current_function_decl)
+              && !indirect_base0
+              && TREE_CODE (base0) == SSA_NAME
+              && TREE_CODE (SSA_NAME_VAR (base0)) == PARM_DECL
+              && SSA_NAME_IS_DEFAULT_DEF (base0)))
+        {
+          if (code == NE_EXPR)
+            return constant_boolean_node (1, type);
+          else if (code == EQ_EXPR)
+            return constant_boolean_node (0, type);
+        }
       /* If we have equivalent bases we might be able to simplify.  */
-      if (indirect_base0 == indirect_base1
-         && operand_equal_p (base0, base1, 0))
+      else if (indirect_base0 == indirect_base1
+               && operand_equal_p (base0, base1, 0))
        {
          /* We can fold this expression to a constant if the non-constant
             offset parts are equal.  */
@@ -9067,7 +8640,7 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
              && (code == EQ_EXPR
                  || code == NE_EXPR
                  || POINTER_TYPE_OVERFLOW_UNDEFINED))
-               
+
            {
              if (code != EQ_EXPR
                  && code != NE_EXPR
@@ -9107,22 +8680,19 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
                   && ((code == EQ_EXPR || code == NE_EXPR)
                       || POINTER_TYPE_OVERFLOW_UNDEFINED))
            {
-             tree signed_size_type_node;
-             signed_size_type_node = signed_type_for (size_type_node);
-
              /* By converting to signed size type we cover middle-end pointer
                 arithmetic which operates on unsigned pointer types of size
                 type size and ARRAY_REF offsets which are properly sign or
                 zero extended from their type in case it is narrower than
                 size type.  */
              if (offset0 == NULL_TREE)
-               offset0 = build_int_cst (signed_size_type_node, 0);
+               offset0 = build_int_cst (ssizetype, 0);
              else
-               offset0 = fold_convert (signed_size_type_node, offset0);
+               offset0 = fold_convert_loc (loc, ssizetype, offset0);
              if (offset1 == NULL_TREE)
-               offset1 = build_int_cst (signed_size_type_node, 0);
+               offset1 = build_int_cst (ssizetype, 0);
              else
-               offset1 = fold_convert (signed_size_type_node, offset1);
+               offset1 = fold_convert_loc (loc, ssizetype, offset1);
 
              if (code != EQ_EXPR
                  && code != NE_EXPR
@@ -9133,7 +8703,7 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
                                        "P +- C2"),
                                       WARN_STRICT_OVERFLOW_COMPARISON);
 
-             return fold_build2 (code, type, offset0, offset1);
+             return fold_build2_loc (loc, code, type, offset0, offset1);
            }
        }
       /* For non-equal bases we can simplify if they are addresses
@@ -9157,9 +8727,11 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
                   || CONSTANT_CLASS_P (base1)))
        {
          if (code == EQ_EXPR)
-           return omit_two_operands (type, boolean_false_node, arg0, arg1);
+           return omit_two_operands_loc (loc, type, boolean_false_node,
+                                     arg0, arg1);
          else if (code == NE_EXPR)
-           return omit_two_operands (type, boolean_true_node, arg0, arg1);
+           return omit_two_operands_loc (loc, type, boolean_true_node,
+                                     arg0, arg1);
        }
       /* For equal offsets we can simplify to a comparison of the
         base addresses.  */
@@ -9173,10 +8745,10 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
                       && operand_equal_p (offset0, offset1, 0))))
        {
          if (indirect_base0)
-           base0 = build_fold_addr_expr (base0);
+           base0 = build_fold_addr_expr_loc (loc, base0);
          if (indirect_base1)
-           base1 = build_fold_addr_expr (base1);
-         return fold_build2 (code, type, base0, base1);
+           base1 = build_fold_addr_expr_loc (loc, base1);
+         return fold_build2_loc (loc, code, type, base0, base1);
        }
     }
 
@@ -9205,26 +8777,27 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
         of lower absolute value than before.  */
       cst = int_const_binop (TREE_CODE (arg0) == TREE_CODE (arg1)
                             ? MINUS_EXPR : PLUS_EXPR,
-                            const2, const1, 0);
+                            const2, const1);
       if (!TREE_OVERFLOW (cst)
          && tree_int_cst_compare (const2, cst) == tree_int_cst_sgn (const2))
        {
          fold_overflow_warning (warnmsg, WARN_STRICT_OVERFLOW_COMPARISON);
-         return fold_build2 (code, type,
+         return fold_build2_loc (loc, code, type,
                              variable1,
-                             fold_build2 (TREE_CODE (arg1), TREE_TYPE (arg1),
+                             fold_build2_loc (loc,
+                                          TREE_CODE (arg1), TREE_TYPE (arg1),
                                           variable2, cst));
        }
 
       cst = int_const_binop (TREE_CODE (arg0) == TREE_CODE (arg1)
                             ? MINUS_EXPR : PLUS_EXPR,
-                            const1, const2, 0);
+                            const1, const2);
       if (!TREE_OVERFLOW (cst)
          && tree_int_cst_compare (const1, cst) == tree_int_cst_sgn (const1))
        {
          fold_overflow_warning (warnmsg, WARN_STRICT_OVERFLOW_COMPARISON);
-         return fold_build2 (code, type,
-                             fold_build2 (TREE_CODE (arg0), TREE_TYPE (arg0),
+         return fold_build2_loc (loc, code, type,
+                             fold_build2_loc (loc, TREE_CODE (arg0), TREE_TYPE (arg0),
                                           variable1, cst),
                              variable2);
        }
@@ -9245,7 +8818,9 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
       tree variable1 = TREE_OPERAND (arg0, 0);
       enum tree_code cmp_code = code;
 
-      gcc_assert (!integer_zerop (const1));
+      /* Handle unfolded multiplication by zero.  */
+      if (integer_zerop (const1))
+       return fold_build2_loc (loc, cmp_code, type, const1, const2);
 
       fold_overflow_warning (("assuming signed overflow does not occur when "
                              "eliminating multiplication in comparison "
@@ -9256,10 +8831,10 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
       if (tree_int_cst_sgn (const1) < 0)
         cmp_code = swap_tree_comparison (cmp_code);
 
-      return fold_build2 (cmp_code, type, variable1, const2);
+      return fold_build2_loc (loc, cmp_code, type, variable1, const2);
     }
 
-  tem = maybe_canonicalize_comparison (code, type, op0, op1);
+  tem = maybe_canonicalize_comparison (loc, code, type, op0, op1);
   if (tem)
     return tem;
 
@@ -9274,13 +8849,14 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
 
       /* Fold (double)float1 CMP (double)float2 into float1 CMP float2.  */
       if (TYPE_PRECISION (newtype) < TYPE_PRECISION (TREE_TYPE (arg0)))
-       return fold_build2 (code, type, fold_convert (newtype, targ0),
-                           fold_convert (newtype, targ1));
+       return fold_build2_loc (loc, code, type,
+                           fold_convert_loc (loc, newtype, targ0),
+                           fold_convert_loc (loc, newtype, targ1));
 
       /* (-a) CMP (-b) -> b CMP a  */
       if (TREE_CODE (arg0) == NEGATE_EXPR
          && TREE_CODE (arg1) == NEGATE_EXPR)
-       return fold_build2 (code, type, TREE_OPERAND (arg1, 0),
+       return fold_build2_loc (loc, code, type, TREE_OPERAND (arg1, 0),
                            TREE_OPERAND (arg0, 0));
 
       if (TREE_CODE (arg1) == REAL_CST)
@@ -9290,15 +8866,15 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
 
          /* (-a) CMP CST -> a swap(CMP) (-CST)  */
          if (TREE_CODE (arg0) == NEGATE_EXPR)
-           return fold_build2 (swap_tree_comparison (code), type,
+           return fold_build2_loc (loc, swap_tree_comparison (code), type,
                                TREE_OPERAND (arg0, 0),
                                build_real (TREE_TYPE (arg1),
-                                           REAL_VALUE_NEGATE (cst)));
+                                           real_value_negate (&cst)));
 
          /* IEEE doesn't distinguish +0 and -0 in comparisons.  */
          /* a CMP (-0) -> a CMP 0  */
          if (REAL_VALUE_MINUS_ZERO (cst))
-           return fold_build2 (code, type, arg0,
+           return fold_build2_loc (loc, code, type, arg0,
                                build_real (TREE_TYPE (arg1), dconst0));
 
          /* x != NaN is always true, other ops are always false.  */
@@ -9306,14 +8882,14 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
              && ! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1))))
            {
              tem = (code == NE_EXPR) ? integer_one_node : integer_zero_node;
-             return omit_one_operand (type, tem, arg0);
+             return omit_one_operand_loc (loc, type, tem, arg0);
            }
 
          /* Fold comparisons against infinity.  */
          if (REAL_VALUE_ISINF (cst)
              && MODE_HAS_INFINITIES (TYPE_MODE (TREE_TYPE (arg1))))
            {
-             tem = fold_inf_compare (code, type, arg0, arg1);
+             tem = fold_inf_compare (loc, code, type, arg0, arg1);
              if (tem != NULL_TREE)
                return tem;
            }
@@ -9330,22 +8906,22 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
          && TREE_CODE (TREE_OPERAND (arg0, 1)) == REAL_CST
          && 0 != (tem = const_binop (TREE_CODE (arg0) == PLUS_EXPR
                                      ? MINUS_EXPR : PLUS_EXPR,
-                                     arg1, TREE_OPERAND (arg0, 1), 0))
+                                     arg1, TREE_OPERAND (arg0, 1)))
          && !TREE_OVERFLOW (tem))
-       return fold_build2 (code, type, TREE_OPERAND (arg0, 0), tem);
+       return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), tem);
 
       /* Likewise, we can simplify a comparison of a real constant with
          a MINUS_EXPR whose first operand is also a real constant, i.e.
-         (c1 - x) < c2 becomes x > c1-c2.  Reordering is allowed on 
+         (c1 - x) < c2 becomes x > c1-c2.  Reordering is allowed on
          floating-point types only if -fassociative-math is set.  */
       if (flag_associative_math
          && TREE_CODE (arg1) == REAL_CST
          && TREE_CODE (arg0) == MINUS_EXPR
          && TREE_CODE (TREE_OPERAND (arg0, 0)) == REAL_CST
          && 0 != (tem = const_binop (MINUS_EXPR, TREE_OPERAND (arg0, 0),
-                                     arg1, 0))
+                                     arg1))
          && !TREE_OVERFLOW (tem))
-       return fold_build2 (swap_tree_comparison (code), type,
+       return fold_build2_loc (loc, swap_tree_comparison (code), type,
                            TREE_OPERAND (arg0, 1), tem);
 
       /* Fold comparisons against built-in math functions.  */
@@ -9357,7 +8933,7 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
 
          if (fcode != END_BUILTINS)
            {
-             tem = fold_mathfn_compare (fcode, code, type, arg0, arg1);
+             tem = fold_mathfn_compare (loc, fcode, code, type, arg0, arg1);
              if (tem != NULL_TREE)
                return tem;
            }
@@ -9370,12 +8946,12 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
       /* If we are widening one operand of an integer comparison,
         see if the other operand is similarly being widened.  Perhaps we
         can do the comparison in the narrower type.  */
-      tem = fold_widened_comparison (code, type, arg0, arg1);
+      tem = fold_widened_comparison (loc, code, type, arg0, arg1);
       if (tem)
        return tem;
 
       /* Or if we are changing signedness.  */
-      tem = fold_sign_changed_comparison (code, type, arg0, arg1);
+      tem = fold_sign_changed_comparison (loc, code, type, arg0, arg1);
       if (tem)
        return tem;
     }
@@ -9387,7 +8963,7 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
          || TREE_CODE (arg0) == MAX_EXPR)
       && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
     {
-      tem = optimize_minmax_comparison (code, type, op0, op1);
+      tem = optimize_minmax_comparison (loc, code, type, op0, op1);
       if (tem)
        return tem;
     }
@@ -9409,7 +8985,7 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
          if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
              || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
            return constant_boolean_node (1, type);
-         return fold_build2 (EQ_EXPR, type, arg0, arg1);
+         return fold_build2_loc (loc, EQ_EXPR, type, arg0, arg1);
 
        case NE_EXPR:
          /* For NE, we can only do this simplification if integer
@@ -9463,18 +9039,18 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
             was the same as ARG1.  */
 
          tree high_result
-               = fold_build2 (code, type,
-                              eval_subst (arg0, cval1, maxval,
+               = fold_build2_loc (loc, code, type,
+                              eval_subst (loc, arg0, cval1, maxval,
                                           cval2, minval),
                               arg1);
          tree equal_result
-               = fold_build2 (code, type,
-                              eval_subst (arg0, cval1, maxval,
+               = fold_build2_loc (loc, code, type,
+                              eval_subst (loc, arg0, cval1, maxval,
                                           cval2, maxval),
                               arg1);
          tree low_result
-               = fold_build2 (code, type,
-                              eval_subst (arg0, cval1, minval,
+               = fold_build2_loc (loc, code, type,
+                              eval_subst (loc, arg0, cval1, minval,
                                           cval2, maxval),
                               arg1);
 
@@ -9493,7 +9069,7 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
                {
                case 0:
                  /* Always false.  */
-                 return omit_one_operand (type, integer_zero_node, arg0);
+                 return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
                case 1:
                  code = LT_EXPR;
                  break;
@@ -9514,12 +9090,16 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
                  break;
                case 7:
                  /* Always true.  */
-                 return omit_one_operand (type, integer_one_node, arg0);
+                 return omit_one_operand_loc (loc, type, integer_one_node, arg0);
                }
 
              if (save_p)
-               return save_expr (build2 (code, type, cval1, cval2));
-             return fold_build2 (code, type, cval1, cval2);
+               {
+                 tem = save_expr (build2 (code, type, cval1, cval2));
+                 SET_EXPR_LOCATION (tem, loc);
+                 return tem;
+               }
+             return fold_build2_loc (loc, code, type, cval1, cval2);
            }
        }
     }
@@ -9534,7 +9114,7 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
       && !TREE_OVERFLOW (TREE_OPERAND (arg0, 1))
       && !TREE_OVERFLOW (arg1))
     {
-      tem = fold_div_compare (code, type, arg0, arg1);
+      tem = fold_div_compare (loc, code, type, arg0, arg1);
       if (tem != NULL_TREE)
        return tem;
     }
@@ -9544,8 +9124,9 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
       && TREE_CODE (arg1) == BIT_NOT_EXPR)
     {
       tree cmp_type = TREE_TYPE (TREE_OPERAND (arg0, 0));
-      return fold_build2 (code, type,
-                         fold_convert (cmp_type, TREE_OPERAND (arg1, 0)),
+      return fold_build2_loc (loc, code, type,
+                         fold_convert_loc (loc, cmp_type,
+                                           TREE_OPERAND (arg1, 0)),
                          TREE_OPERAND (arg0, 0));
     }
 
@@ -9554,10 +9135,10 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
       && TREE_CODE (arg1) == INTEGER_CST)
     {
       tree cmp_type = TREE_TYPE (TREE_OPERAND (arg0, 0));
-      return fold_build2 (swap_tree_comparison (code), type,
+      return fold_build2_loc (loc, swap_tree_comparison (code), type,
                          TREE_OPERAND (arg0, 0),
-                         fold_build1 (BIT_NOT_EXPR, cmp_type,
-                                      fold_convert (cmp_type, arg1)));
+                         fold_build1_loc (loc, BIT_NOT_EXPR, cmp_type,
+                                      fold_convert_loc (loc, cmp_type, arg1)));
     }
 
   return NULL_TREE;
@@ -9569,7 +9150,7 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
    argument EXPR represents the expression "z" of type TYPE.  */
 
 static tree
-fold_mult_zconjz (tree type, tree expr)
+fold_mult_zconjz (location_t loc, tree type, tree expr)
 {
   tree itype = TREE_TYPE (type);
   tree rpart, ipart, tem;
@@ -9587,17 +9168,17 @@ fold_mult_zconjz (tree type, tree expr)
   else
     {
       expr = save_expr (expr);
-      rpart = fold_build1 (REALPART_EXPR, itype, expr);
-      ipart = fold_build1 (IMAGPART_EXPR, itype, expr);
+      rpart = fold_build1_loc (loc, REALPART_EXPR, itype, expr);
+      ipart = fold_build1_loc (loc, IMAGPART_EXPR, itype, expr);
     }
 
   rpart = save_expr (rpart);
   ipart = save_expr (ipart);
-  tem = fold_build2 (PLUS_EXPR, itype,
-                    fold_build2 (MULT_EXPR, itype, rpart, rpart),
-                    fold_build2 (MULT_EXPR, itype, ipart, ipart));
-  return fold_build2 (COMPLEX_EXPR, type, tem,
-                     fold_convert (itype, integer_zero_node));
+  tem = fold_build2_loc (loc, PLUS_EXPR, itype,
+                    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,
+                         build_zero_cst (itype));
 }
 
 
@@ -9625,37 +9206,17 @@ get_pointer_modulus_and_residue (tree expr, unsigned HOST_WIDE_INT *residue,
   code = TREE_CODE (expr);
   if (code == ADDR_EXPR)
     {
-      expr = TREE_OPERAND (expr, 0);
-      if (handled_component_p (expr))
-       {
-         HOST_WIDE_INT bitsize, bitpos;
-         tree offset;
-         enum machine_mode mode;
-         int unsignedp, volatilep;
-
-         expr = get_inner_reference (expr, &bitsize, &bitpos, &offset,
-                                     &mode, &unsignedp, &volatilep, false);
-         *residue = bitpos / BITS_PER_UNIT;
-         if (offset)
-           {
-             if (TREE_CODE (offset) == INTEGER_CST)
-               *residue += TREE_INT_CST_LOW (offset);
-             else
-               /* We don't handle more complicated offset expressions.  */
-               return 1;
-           }
-       }
-
-      if (DECL_P (expr)
-         && (allow_func_align || TREE_CODE (expr) != FUNCTION_DECL))
-       return DECL_ALIGN_UNIT (expr);
+      unsigned int bitalign;
+      bitalign = get_object_alignment_1 (TREE_OPERAND (expr, 0), residue);
+      *residue /= BITS_PER_UNIT;
+      return bitalign / BITS_PER_UNIT;
     }
   else if (code == POINTER_PLUS_EXPR)
     {
       tree op0, op1;
       unsigned HOST_WIDE_INT modulus;
       enum tree_code inner_code;
-      
+
       op0 = TREE_OPERAND (expr, 0);
       STRIP_NOPS (op0);
       modulus = get_pointer_modulus_and_residue (op0, residue,
@@ -9675,7 +9236,7 @@ get_pointer_modulus_and_residue (tree expr, unsigned HOST_WIDE_INT *residue,
          if (TREE_CODE (op1) == INTEGER_CST)
            {
              unsigned HOST_WIDE_INT align;
-             
+
              /* Compute the greatest power-of-2 divisor of op1.  */
              align = TREE_INT_CST_LOW (op1);
              align &= -align;
@@ -9693,18 +9254,20 @@ get_pointer_modulus_and_residue (tree expr, unsigned HOST_WIDE_INT *residue,
        }
     }
 
-    /* If we get here, we were unable to determine anything useful about the
-       expression.  */
-    return 1;
+  /* If we get here, we were unable to determine anything useful about the
+     expression.  */
+  return 1;
 }
 
 
 /* Fold a binary expression of code CODE and type TYPE with operands
-   OP0 and OP1.  Return the folded expression if folding is
-   successful.  Otherwise, return NULL_TREE.  */
+   OP0 and OP1.  LOC is the location of the resulting expression.
+   Return the folded expression if folding is successful.  Otherwise,
+   return NULL_TREE.  */
 
 tree
-fold_binary (enum tree_code code, tree type, tree op0, tree op1)
+fold_binary_loc (location_t loc,
+            enum tree_code code, tree type, tree op0, tree op1)
 {
   enum tree_code_class kind = TREE_CODE_CLASS (code);
   tree arg0, arg1, tem;
@@ -9757,7 +9320,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          /* Make sure type and arg0 have the same saturating flag.  */
          gcc_assert (TYPE_SATURATING (type)
                      == TYPE_SATURATING (TREE_TYPE (arg0)));
-         tem = const_binop (code, arg0, arg1, 0);
+         tem = const_binop (code, arg0, arg1);
        }
       else if (kind == tcc_comparison)
        tem = fold_relational_const (code, type, arg0, arg1);
@@ -9767,7 +9330,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
       if (tem != NULL_TREE)
        {
          if (TREE_TYPE (tem) != type)
-           tem = fold_convert (type, tem);
+           tem = fold_convert_loc (loc, type, tem);
          return tem;
        }
     }
@@ -9776,7 +9339,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
      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, op1, op0);
+    return fold_build2_loc (loc, code, type, op1, op0);
 
   /* ARG0 is the first operand of EXPR, and ARG1 is the second operand.
 
@@ -9805,39 +9368,44 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                  || (TREE_CODE (arg0) == BIT_AND_EXPR
                      && integer_onep (TREE_OPERAND (arg0, 1)))))))
     {
-      tem = fold_build2 (code == BIT_AND_EXPR ? TRUTH_AND_EXPR
+      tem = fold_build2_loc (loc, code == BIT_AND_EXPR ? TRUTH_AND_EXPR
                         : code == BIT_IOR_EXPR ? TRUTH_OR_EXPR
                         : TRUTH_XOR_EXPR,
                         boolean_type_node,
-                        fold_convert (boolean_type_node, arg0),
-                        fold_convert (boolean_type_node, arg1));
+                        fold_convert_loc (loc, boolean_type_node, arg0),
+                        fold_convert_loc (loc, boolean_type_node, arg1));
 
       if (code == EQ_EXPR)
-       tem = invert_truthvalue (tem);
+       tem = invert_truthvalue_loc (loc, tem);
 
-      return fold_convert (type, tem);
+      return fold_convert_loc (loc, type, tem);
     }
 
   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,
-                                   fold_convert (TREE_TYPE (op0),
-                                                 TREE_OPERAND (arg0, 1)),
-                                   op1));
+       {
+         tem = fold_build2_loc (loc, code, type,
+                            fold_convert_loc (loc, TREE_TYPE (op0),
+                                              TREE_OPERAND (arg0, 1)), op1);
+         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)))
-       return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
-                      fold_build2 (code, type, op0,
-                                   fold_convert (TREE_TYPE (op1),
-                                                 TREE_OPERAND (arg1, 1))));
+       {
+         tem = fold_build2_loc (loc, code, type, op0,
+                            fold_convert_loc (loc, TREE_TYPE (op1),
+                                              TREE_OPERAND (arg1, 1)));
+         return build2_loc (loc, COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
+                            tem);
+       }
 
       if (TREE_CODE (arg0) == COND_EXPR || COMPARISON_CLASS_P (arg0))
        {
-         tem = fold_binary_op_with_conditional_arg (code, type, op0, op1,
-                                                    arg0, arg1, 
+         tem = fold_binary_op_with_conditional_arg (loc, code, type, op0, op1,
+                                                    arg0, arg1,
                                                     /*cond_first_p=*/1);
          if (tem != NULL_TREE)
            return tem;
@@ -9845,8 +9413,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
 
       if (TREE_CODE (arg1) == COND_EXPR || COMPARISON_CLASS_P (arg1))
        {
-         tem = fold_binary_op_with_conditional_arg (code, type, op0, op1,
-                                                    arg1, arg0, 
+         tem = fold_binary_op_with_conditional_arg (loc, code, type, op0, op1,
+                                                    arg1, arg0,
                                                     /*cond_first_p=*/0);
          if (tem != NULL_TREE)
            return tem;
@@ -9855,54 +9423,90 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
 
   switch (code)
     {
+    case MEM_REF:
+      /* MEM[&MEM[p, CST1], CST2] -> MEM[p, CST1 + CST2].  */
+      if (TREE_CODE (arg0) == ADDR_EXPR
+         && TREE_CODE (TREE_OPERAND (arg0, 0)) == MEM_REF)
+       {
+         tree iref = TREE_OPERAND (arg0, 0);
+         return fold_build2 (MEM_REF, type,
+                             TREE_OPERAND (iref, 0),
+                             int_const_binop (PLUS_EXPR, arg1,
+                                              TREE_OPERAND (iref, 1)));
+       }
+
+      /* MEM[&a.b, CST2] -> MEM[&a, offsetof (a, b) + CST2].  */
+      if (TREE_CODE (arg0) == ADDR_EXPR
+         && handled_component_p (TREE_OPERAND (arg0, 0)))
+       {
+         tree base;
+         HOST_WIDE_INT coffset;
+         base = get_addr_base_and_unit_offset (TREE_OPERAND (arg0, 0),
+                                               &coffset);
+         if (!base)
+           return NULL_TREE;
+         return fold_build2 (MEM_REF, type,
+                             build_fold_addr_expr (base),
+                             int_const_binop (PLUS_EXPR, arg1,
+                                              size_int (coffset)));
+       }
+
+      return NULL_TREE;
+
     case POINTER_PLUS_EXPR:
       /* 0 +p index -> (type)index */
       if (integer_zerop (arg0))
-       return non_lvalue (fold_convert (type, arg1));
+       return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1));
 
       /* PTR +p 0 -> PTR */
       if (integer_zerop (arg1))
-       return non_lvalue (fold_convert (type, arg0));
+       return non_lvalue_loc (loc, fold_convert_loc (loc, 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)));
+        return fold_convert_loc (loc, type,
+                                fold_build2_loc (loc, PLUS_EXPR, sizetype,
+                                             fold_convert_loc (loc, sizetype,
+                                                               arg1),
+                                             fold_convert_loc (loc, 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));
+        return fold_build2_loc (loc, POINTER_PLUS_EXPR, type,
+                           fold_convert_loc (loc, type, arg1),
+                           fold_convert_loc (loc, 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 arg01 = fold_convert_loc (loc, sizetype, TREE_OPERAND (arg0, 1));
          tree arg00 = TREE_OPERAND (arg0, 0);
-         inner = fold_build2 (PLUS_EXPR, sizetype,
-                              arg01, fold_convert (sizetype, arg1));
-         return fold_convert (type,
-                              fold_build2 (POINTER_PLUS_EXPR,
-                                           TREE_TYPE (arg00), arg00, inner));
+         inner = fold_build2_loc (loc, PLUS_EXPR, sizetype,
+                              arg01, fold_convert_loc (loc, sizetype, arg1));
+         return fold_convert_loc (loc, type,
+                                  fold_build2_loc (loc, POINTER_PLUS_EXPR,
+                                               TREE_TYPE (arg00),
+                                               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));
+       return fold_build2_loc (loc, PLUS_EXPR, type, arg0,
+                           fold_convert_loc (loc, 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));
+         tem = try_move_mult_to_index (loc, arg0,
+                                       fold_convert_loc (loc, sizetype, arg1));
          if (tem)
-           return fold_convert (type, tem);
+           return fold_convert_loc (loc, type, tem);
        }
 
       return NULL_TREE;
@@ -9910,23 +9514,26 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
     case PLUS_EXPR:
       /* A + (-B) -> A - B */
       if (TREE_CODE (arg1) == NEGATE_EXPR)
-       return fold_build2 (MINUS_EXPR, type,
-                           fold_convert (type, arg0),
-                           fold_convert (type, TREE_OPERAND (arg1, 0)));
+       return fold_build2_loc (loc, MINUS_EXPR, type,
+                           fold_convert_loc (loc, type, arg0),
+                           fold_convert_loc (loc, type,
+                                             TREE_OPERAND (arg1, 0)));
       /* (-A) + B -> B - A */
       if (TREE_CODE (arg0) == NEGATE_EXPR
          && reorder_operands_p (TREE_OPERAND (arg0, 0), arg1))
-       return fold_build2 (MINUS_EXPR, type,
-                           fold_convert (type, arg1),
-                           fold_convert (type, TREE_OPERAND (arg0, 0)));
+       return fold_build2_loc (loc, MINUS_EXPR, type,
+                           fold_convert_loc (loc, type, arg1),
+                           fold_convert_loc (loc, type,
+                                             TREE_OPERAND (arg0, 0)));
 
       if (INTEGRAL_TYPE_P (type))
        {
          /* Convert ~A + 1 to -A.  */
          if (TREE_CODE (arg0) == BIT_NOT_EXPR
              && integer_onep (arg1))
-           return fold_build1 (NEGATE_EXPR, type,
-                               fold_convert (type, TREE_OPERAND (arg0, 0)));
+           return fold_build1_loc (loc, NEGATE_EXPR, type,
+                               fold_convert_loc (loc, type,
+                                                 TREE_OPERAND (arg0, 0)));
 
          /* ~X + X is -1.  */
          if (TREE_CODE (arg0) == BIT_NOT_EXPR
@@ -9938,7 +9545,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
              if (operand_equal_p (tem, arg1, 0))
                {
                  t1 = build_int_cst_type (type, -1);
-                 return omit_one_operand (type, t1, arg1);
+                 return omit_one_operand_loc (loc, type, t1, arg1);
                }
            }
 
@@ -9952,7 +9559,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
              if (operand_equal_p (arg0, tem, 0))
                {
                  t1 = build_int_cst_type (type, -1);
-                 return omit_one_operand (type, t1, arg0);
+                 return omit_one_operand_loc (loc, type, t1, arg0);
                }
            }
 
@@ -9964,11 +9571,13 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
            {
              tree cst0 = TREE_OPERAND (TREE_OPERAND (arg1, 0), 1);
              tree cst1 = TREE_OPERAND (arg1, 1);
-             tree sum = fold_binary (PLUS_EXPR, TREE_TYPE (cst1), cst1, cst0);
+             tree sum = fold_binary_loc (loc, PLUS_EXPR, TREE_TYPE (cst1),
+                                     cst1, cst0);
              if (sum && integer_zerop (sum))
-               return fold_convert (type,
-                                    fold_build2 (TRUNC_MOD_EXPR,
-                                                 TREE_TYPE (arg0), arg0, cst0));
+               return fold_convert_loc (loc, type,
+                                        fold_build2_loc (loc, TRUNC_MOD_EXPR,
+                                                     TREE_TYPE (arg0), arg0,
+                                                     cst0));
            }
        }
 
@@ -9980,7 +9589,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && !TYPE_SATURATING (type)
          && (!FLOAT_TYPE_P (type) || flag_associative_math))
         {
-         tree tem = fold_plusminus_mult_expr (code, type, arg0, arg1);
+         tree tem = fold_plusminus_mult_expr (loc, code, type, arg0, arg1);
          if (tem)
            return tem;
        }
@@ -9988,7 +9597,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
       if (! FLOAT_TYPE_P (type))
        {
          if (integer_zerop (arg1))
-           return non_lvalue (fold_convert (type, arg0));
+           return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
 
          /* If we are adding two BIT_AND_EXPR's, both of which are and'ing
             with a constant, and the two constants have no bits in common,
@@ -10000,7 +9609,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
              && TREE_CODE (TREE_OPERAND (arg1, 1)) == INTEGER_CST
              && integer_zerop (const_binop (BIT_AND_EXPR,
                                             TREE_OPERAND (arg0, 1),
-                                            TREE_OPERAND (arg1, 1), 0)))
+                                            TREE_OPERAND (arg1, 1))))
            {
              code = BIT_IOR_EXPR;
              goto bit_ior;
@@ -10031,30 +9640,33 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
 
              if (TREE_CODE (parg0) == MULT_EXPR
                  && TREE_CODE (parg1) != MULT_EXPR)
-               return fold_build2 (pcode, type,
-                                   fold_build2 (PLUS_EXPR, type,
-                                                fold_convert (type, parg0),
-                                                fold_convert (type, marg)),
-                                   fold_convert (type, parg1));
+               return fold_build2_loc (loc, pcode, type,
+                                   fold_build2_loc (loc, PLUS_EXPR, type,
+                                                fold_convert_loc (loc, type,
+                                                                  parg0),
+                                                fold_convert_loc (loc, type,
+                                                                  marg)),
+                                   fold_convert_loc (loc, type, parg1));
              if (TREE_CODE (parg0) != MULT_EXPR
                  && TREE_CODE (parg1) == MULT_EXPR)
-               return fold_build2 (PLUS_EXPR, type,
-                                   fold_convert (type, parg0),
-                                   fold_build2 (pcode, type,
-                                                fold_convert (type, marg),
-                                                fold_convert (type,
-                                                              parg1)));
+               return
+                 fold_build2_loc (loc, PLUS_EXPR, type,
+                              fold_convert_loc (loc, type, parg0),
+                              fold_build2_loc (loc, pcode, type,
+                                           fold_convert_loc (loc, type, marg),
+                                           fold_convert_loc (loc, type,
+                                                             parg1)));
            }
        }
       else
        {
          /* See if ARG1 is zero and X + ARG1 reduces to X.  */
          if (fold_real_zero_addition_p (TREE_TYPE (arg0), arg1, 0))
-           return non_lvalue (fold_convert (type, arg0));
+           return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
 
          /* Likewise if the operands are reversed.  */
          if (fold_real_zero_addition_p (TREE_TYPE (arg1), arg0, 0))
-           return non_lvalue (fold_convert (type, arg1));
+           return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1));
 
          /* Convert X + -C into X - C.  */
          if (TREE_CODE (arg1) == REAL_CST
@@ -10062,9 +9674,9 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
            {
              tem = fold_negate_const (arg1, type);
              if (!TREE_OVERFLOW (arg1) || !flag_trapping_math)
-               return fold_build2 (MINUS_EXPR, type,
-                                   fold_convert (type, arg0),
-                                   fold_convert (type, tem));
+               return fold_build2_loc (loc, MINUS_EXPR, type,
+                                   fold_convert_loc (loc, type, arg0),
+                                   fold_convert_loc (loc, type, tem));
            }
 
          /* Fold __complex__ ( x, 0 ) + __complex__ ( 0, y )
@@ -10075,21 +9687,21 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
              && COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg0)))
            {
              tree rtype = TREE_TYPE (TREE_TYPE (arg0));
-             tree arg0r = fold_unary (REALPART_EXPR, rtype, arg0);
-             tree arg0i = fold_unary (IMAGPART_EXPR, rtype, arg0);
+             tree arg0r = fold_unary_loc (loc, REALPART_EXPR, rtype, arg0);
+             tree arg0i = fold_unary_loc (loc, IMAGPART_EXPR, rtype, arg0);
              bool arg0rz = false, arg0iz = false;
              if ((arg0r && (arg0rz = real_zerop (arg0r)))
                  || (arg0i && (arg0iz = real_zerop (arg0i))))
                {
-                 tree arg1r = fold_unary (REALPART_EXPR, rtype, arg1);
-                 tree arg1i = fold_unary (IMAGPART_EXPR, rtype, arg1);
+                 tree arg1r = fold_unary_loc (loc, REALPART_EXPR, rtype, arg1);
+                 tree arg1i = fold_unary_loc (loc, IMAGPART_EXPR, rtype, arg1);
                  if (arg0rz && arg1i && real_zerop (arg1i))
                    {
                      tree rp = arg1r ? arg1r
                                  : build1 (REALPART_EXPR, rtype, arg1);
                      tree ip = arg0i ? arg0i
                                  : build1 (IMAGPART_EXPR, rtype, arg0);
-                     return fold_build2 (COMPLEX_EXPR, type, rp, ip);
+                     return fold_build2_loc (loc, COMPLEX_EXPR, type, rp, ip);
                    }
                  else if (arg0iz && arg1r && real_zerop (arg1r))
                    {
@@ -10097,7 +9709,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                                  : build1 (REALPART_EXPR, rtype, arg0);
                      tree ip = arg1i ? arg1i
                                  : build1 (IMAGPART_EXPR, rtype, arg1);
-                     return fold_build2 (COMPLEX_EXPR, type, rp, ip);
+                     return fold_build2_loc (loc, COMPLEX_EXPR, type, rp, ip);
                    }
                }
            }
@@ -10105,16 +9717,16 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          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)
-             && (tem = distribute_real_division (code, type, arg0, arg1)))
+             && (tem = distribute_real_division (loc, code, type, arg0, arg1)))
            return tem;
 
          /* Convert x+x into x*2.0.  */
          if (operand_equal_p (arg0, arg1, 0)
              && SCALAR_FLOAT_TYPE_P (type))
-           return fold_build2 (MULT_EXPR, type, arg0,
+           return fold_build2_loc (loc, MULT_EXPR, type, arg0,
                                build_real (type, dconst2));
 
-          /* Convert a + (b*c + d*e) into (a + b*c) + d*e.  
+          /* Convert a + (b*c + d*e) into (a + b*c) + d*e.
              We associate floats only if the user has specified
              -fassociative-math.  */
           if (flag_associative_math
@@ -10127,11 +9739,11 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                  && TREE_CODE (tree10) == MULT_EXPR)
                 {
                   tree tree0;
-                  tree0 = fold_build2 (PLUS_EXPR, type, arg0, tree10);
-                  return fold_build2 (PLUS_EXPR, type, tree0, tree11);
+                  tree0 = fold_build2_loc (loc, PLUS_EXPR, type, arg0, tree10);
+                  return fold_build2_loc (loc, PLUS_EXPR, type, tree0, tree11);
                 }
             }
-          /* Convert (b*c + d*e) + a into b*c + (d*e +a).  
+          /* Convert (b*c + d*e) + a into b*c + (d*e +a).
              We associate floats only if the user has specified
              -fassociative-math.  */
           if (flag_associative_math
@@ -10144,8 +9756,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                  && TREE_CODE (tree00) == MULT_EXPR)
                 {
                   tree tree0;
-                  tree0 = fold_build2 (PLUS_EXPR, type, tree01, arg1);
-                  return fold_build2 (PLUS_EXPR, type, tree00, tree0);
+                  tree0 = fold_build2_loc (loc, PLUS_EXPR, type, tree01, arg1);
+                  return fold_build2_loc (loc, PLUS_EXPR, type, tree00, tree0);
                 }
             }
        }
@@ -10185,8 +9797,13 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                && TREE_INT_CST_HIGH (tree11) == 0
                && ((TREE_INT_CST_LOW (tree01) + TREE_INT_CST_LOW (tree11))
                    == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))))
-             return build2 (LROTATE_EXPR, type, TREE_OPERAND (arg0, 0),
-                            code0 == LSHIFT_EXPR ? tree01 : tree11);
+             {
+               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)
              {
                tree tree110, tree111;
@@ -10200,10 +9817,13 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                                              (TREE_TYPE (TREE_OPERAND
                                                          (arg0, 0))))
                    && operand_equal_p (tree01, tree111, 0))
-                 return build2 ((code0 == LSHIFT_EXPR
-                                 ? LROTATE_EXPR
-                                 : RROTATE_EXPR),
-                                type, TREE_OPERAND (arg0, 0), tree01);
+                 return
+                   fold_convert_loc (loc, type,
+                                     build2 ((code0 == LSHIFT_EXPR
+                                              ? LROTATE_EXPR
+                                              : RROTATE_EXPR),
+                                             TREE_TYPE (TREE_OPERAND (arg0, 0)),
+                                             TREE_OPERAND (arg0, 0), tree01));
              }
            else if (code01 == MINUS_EXPR)
              {
@@ -10218,10 +9838,13 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                                              (TREE_TYPE (TREE_OPERAND
                                                          (arg0, 0))))
                    && operand_equal_p (tree11, tree011, 0))
-                 return build2 ((code0 != LSHIFT_EXPR
-                                 ? LROTATE_EXPR
-                                 : RROTATE_EXPR),
-                                type, TREE_OPERAND (arg0, 0), tree11);
+                   return fold_convert_loc
+                     (loc, type,
+                      build2 ((code0 != LSHIFT_EXPR
+                               ? LROTATE_EXPR
+                               : RROTATE_EXPR),
+                              TREE_TYPE (TREE_OPERAND (arg0, 0)),
+                              TREE_OPERAND (arg0, 0), tree11));
              }
          }
       }
@@ -10249,23 +9872,39 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          var1 = split_tree (arg1, code, &con1, &lit1, &minus_lit1,
                             code == MINUS_EXPR);
 
-         /* With undefined overflow we can only associate constants
-            with one variable.  */
-         if (((POINTER_TYPE_P (type) && POINTER_TYPE_OVERFLOW_UNDEFINED)
-              || (INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_WRAPS (type)))
-             && var0 && var1)
+         /* Recombine MINUS_EXPR operands by using PLUS_EXPR.  */
+         if (code == MINUS_EXPR)
+           code = PLUS_EXPR;
+
+         /* With undefined overflow we can only associate constants with one
+            variable, and constants whose association doesn't overflow.  */
+         if ((POINTER_TYPE_P (type) && POINTER_TYPE_OVERFLOW_UNDEFINED)
+             || (INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_WRAPS (type)))
            {
-             tree tmp0 = var0;
-             tree tmp1 = var1;
-
-             if (TREE_CODE (tmp0) == NEGATE_EXPR)
-               tmp0 = TREE_OPERAND (tmp0, 0);
-             if (TREE_CODE (tmp1) == NEGATE_EXPR)
-               tmp1 = TREE_OPERAND (tmp1, 0);
-             /* The only case we can still associate with two variables
-                is if they are the same, modulo negation.  */
-             if (!operand_equal_p (tmp0, tmp1, 0))
-               ok = false;
+             if (var0 && var1)
+               {
+                 tree tmp0 = var0;
+                 tree tmp1 = var1;
+
+                 if (TREE_CODE (tmp0) == NEGATE_EXPR)
+                   tmp0 = TREE_OPERAND (tmp0, 0);
+                 if (TREE_CODE (tmp1) == NEGATE_EXPR)
+                   tmp1 = TREE_OPERAND (tmp1, 0);
+                 /* The only case we can still associate with two variables
+                    is if they are the same, modulo negation.  */
+                 if (!operand_equal_p (tmp0, tmp1, 0))
+                   ok = false;
+               }
+
+             if (ok && lit0 && lit1)
+               {
+                 tree tmp0 = fold_convert (type, lit0);
+                 tree tmp1 = fold_convert (type, lit1);
+
+                 if (!TREE_OVERFLOW (tmp0) && !TREE_OVERFLOW (tmp1)
+                     && TREE_OVERFLOW (fold_build2 (code, type, tmp0, tmp1)))
+                   ok = false;
+               }
            }
 
          /* Only do something if we found more than two objects.  Otherwise,
@@ -10276,14 +9915,10 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                       + (lit0 != 0) + (lit1 != 0)
                       + (minus_lit0 != 0) + (minus_lit1 != 0))))
            {
-             /* Recombine MINUS_EXPR operands by using PLUS_EXPR.  */
-             if (code == MINUS_EXPR)
-               code = PLUS_EXPR;
-
-             var0 = associate_trees (var0, var1, code, type);
-             con0 = associate_trees (con0, con1, code, type);
-             lit0 = associate_trees (lit0, lit1, code, type);
-             minus_lit0 = associate_trees (minus_lit0, minus_lit1, code, type);
+             var0 = associate_trees (loc, var0, var1, code, type);
+             con0 = associate_trees (loc, con0, con1, code, type);
+             lit0 = associate_trees (loc, lit0, lit1, code, type);
+             minus_lit0 = associate_trees (loc, minus_lit0, minus_lit1, code, type);
 
              /* Preserve the MINUS_EXPR if the negative part of the literal is
                 greater than the positive part.  Otherwise, the multiplicative
@@ -10296,13 +9931,13 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                      && TREE_CODE (minus_lit0) == INTEGER_CST
                      && tree_int_cst_lt (lit0, minus_lit0))
                    {
-                     minus_lit0 = associate_trees (minus_lit0, lit0,
+                     minus_lit0 = associate_trees (loc, minus_lit0, lit0,
                                                    MINUS_EXPR, type);
                      lit0 = 0;
                    }
                  else
                    {
-                     lit0 = associate_trees (lit0, minus_lit0,
+                     lit0 = associate_trees (loc, lit0, minus_lit0,
                                              MINUS_EXPR, type);
                      minus_lit0 = 0;
                    }
@@ -10310,22 +9945,25 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
              if (minus_lit0)
                {
                  if (con0 == 0)
-                   return fold_convert (type,
-                                        associate_trees (var0, minus_lit0,
-                                                         MINUS_EXPR, type));
+                   return
+                     fold_convert_loc (loc, type,
+                                       associate_trees (loc, var0, minus_lit0,
+                                                        MINUS_EXPR, type));
                  else
                    {
-                     con0 = associate_trees (con0, minus_lit0,
+                     con0 = associate_trees (loc, con0, minus_lit0,
                                              MINUS_EXPR, type);
-                     return fold_convert (type,
-                                          associate_trees (var0, con0,
-                                                           PLUS_EXPR, type));
+                     return
+                       fold_convert_loc (loc, type,
+                                         associate_trees (loc, var0, con0,
+                                                          PLUS_EXPR, type));
                    }
                }
 
-             con0 = associate_trees (con0, lit0, code, type);
-             return fold_convert (type, associate_trees (var0, con0,
-                                                         code, type));
+             con0 = associate_trees (loc, con0, lit0, code, type);
+             return
+               fold_convert_loc (loc, type, associate_trees (loc, var0, con0,
+                                                             code, type));
            }
        }
 
@@ -10339,49 +9977,56 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          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));
+             tree arg00 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
+             tree arg01 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
+             tree arg10 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 0));
+             tree arg11 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 1));
+             return fold_build2_loc (loc, PLUS_EXPR, type,
+                                 fold_build2_loc (loc, MINUS_EXPR, type,
+                                              arg00, arg10),
+                                 fold_build2_loc (loc, 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));
+             tree arg00 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
+             tree arg01 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
+             tree tmp = fold_binary_loc (loc, MINUS_EXPR, type, arg00,
+                                     fold_convert_loc (loc, type, arg1));
              if (tmp)
-               return fold_build2 (PLUS_EXPR, type, tmp, arg01);
+               return fold_build2_loc (loc, PLUS_EXPR, type, tmp, arg01);
            }
        }
       /* A - (-B) -> A + B */
       if (TREE_CODE (arg1) == NEGATE_EXPR)
-       return fold_build2 (PLUS_EXPR, type, op0,
-                           fold_convert (type, TREE_OPERAND (arg1, 0)));
+       return fold_build2_loc (loc, PLUS_EXPR, type, op0,
+                           fold_convert_loc (loc, type,
+                                             TREE_OPERAND (arg1, 0)));
       /* (-A) - B -> (-B) - A  where B is easily negated and we can swap.  */
       if (TREE_CODE (arg0) == NEGATE_EXPR
          && (FLOAT_TYPE_P (type)
              || INTEGRAL_TYPE_P (type))
          && negate_expr_p (arg1)
          && reorder_operands_p (arg0, arg1))
-       return fold_build2 (MINUS_EXPR, type,
-                           fold_convert (type, negate_expr (arg1)),
-                           fold_convert (type, TREE_OPERAND (arg0, 0)));
+       return fold_build2_loc (loc, MINUS_EXPR, type,
+                           fold_convert_loc (loc, type,
+                                             negate_expr (arg1)),
+                           fold_convert_loc (loc, type,
+                                             TREE_OPERAND (arg0, 0)));
       /* Convert -A - 1 to ~A.  */
       if (INTEGRAL_TYPE_P (type)
          && TREE_CODE (arg0) == NEGATE_EXPR
          && integer_onep (arg1)
          && !TYPE_OVERFLOW_TRAPS (type))
-       return fold_build1 (BIT_NOT_EXPR, type,
-                           fold_convert (type, TREE_OPERAND (arg0, 0)));
+       return fold_build1_loc (loc, BIT_NOT_EXPR, type,
+                           fold_convert_loc (loc, type,
+                                             TREE_OPERAND (arg0, 0)));
 
       /* Convert -1 - A to ~A.  */
       if (INTEGRAL_TYPE_P (type)
          && integer_all_onesp (arg0))
-       return fold_build1 (BIT_NOT_EXPR, type, op1);
+       return fold_build1_loc (loc, BIT_NOT_EXPR, type, op1);
 
 
       /* X - (X / CST) * CST is X % CST.  */
@@ -10392,16 +10037,17 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                              TREE_OPERAND (TREE_OPERAND (arg1, 0), 0), 0)
          && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg1, 0), 1),
                              TREE_OPERAND (arg1, 1), 0))
-       return fold_convert (type,
-                            fold_build2 (TRUNC_MOD_EXPR, TREE_TYPE (arg0),
-                                         arg0, TREE_OPERAND (arg1, 1)));
+       return
+         fold_convert_loc (loc, type,
+                           fold_build2_loc (loc, TRUNC_MOD_EXPR, TREE_TYPE (arg0),
+                                        arg0, TREE_OPERAND (arg1, 1)));
 
       if (! FLOAT_TYPE_P (type))
        {
          if (integer_zerop (arg0))
-           return negate_expr (fold_convert (type, arg1));
+           return negate_expr (fold_convert_loc (loc, type, arg1));
          if (integer_zerop (arg1))
-           return non_lvalue (fold_convert (type, arg0));
+           return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
 
          /* Fold A - (A & B) into ~B & A.  */
          if (!TREE_SIDE_EFFECTS (arg0)
@@ -10409,17 +10055,21 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
            {
              if (operand_equal_p (arg0, TREE_OPERAND (arg1, 1), 0))
                {
-                 tree arg10 = fold_convert (type, TREE_OPERAND (arg1, 0));
-                 return fold_build2 (BIT_AND_EXPR, type,
-                                     fold_build1 (BIT_NOT_EXPR, type, arg10),
-                                     fold_convert (type, arg0));
+                 tree arg10 = fold_convert_loc (loc, type,
+                                                TREE_OPERAND (arg1, 0));
+                 return fold_build2_loc (loc, BIT_AND_EXPR, type,
+                                     fold_build1_loc (loc, BIT_NOT_EXPR,
+                                                  type, arg10),
+                                     fold_convert_loc (loc, type, arg0));
                }
              if (operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
                {
-                 tree arg11 = fold_convert (type, TREE_OPERAND (arg1, 1));
-                 return fold_build2 (BIT_AND_EXPR, type,
-                                     fold_build1 (BIT_NOT_EXPR, type, arg11),
-                                     fold_convert (type, arg0));
+                 tree arg11 = fold_convert_loc (loc,
+                                                type, TREE_OPERAND (arg1, 1));
+                 return fold_build2_loc (loc, BIT_AND_EXPR, type,
+                                     fold_build1_loc (loc, BIT_NOT_EXPR,
+                                                  type, arg11),
+                                     fold_convert_loc (loc, type, arg0));
                }
            }
 
@@ -10432,26 +10082,26 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
            {
              tree mask0 = TREE_OPERAND (arg0, 1);
              tree mask1 = TREE_OPERAND (arg1, 1);
-             tree tem = fold_build1 (BIT_NOT_EXPR, type, mask0);
+             tree tem = fold_build1_loc (loc, BIT_NOT_EXPR, type, mask0);
 
              if (operand_equal_p (tem, mask1, 0))
                {
-                 tem = fold_build2 (BIT_XOR_EXPR, type,
+                 tem = fold_build2_loc (loc, BIT_XOR_EXPR, type,
                                     TREE_OPERAND (arg0, 0), mask1);
-                 return fold_build2 (MINUS_EXPR, type, tem, mask1);
+                 return fold_build2_loc (loc, MINUS_EXPR, type, tem, mask1);
                }
            }
        }
 
       /* See if ARG1 is zero and X - ARG1 reduces to X.  */
       else if (fold_real_zero_addition_p (TREE_TYPE (arg0), arg1, 1))
-       return non_lvalue (fold_convert (type, arg0));
+       return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
 
       /* (ARG0 - ARG1) is the same as (-ARG1 + ARG0).  So check whether
         ARG0 is zero and X + ARG0 reduces to X, since that would mean
         (-ARG1 + ARG0) reduces to -ARG1.  */
       else if (fold_real_zero_addition_p (TREE_TYPE (arg1), arg0, 0))
-       return negate_expr (fold_convert (type, arg1));
+       return negate_expr (fold_convert_loc (loc, type, arg1));
 
       /* Fold __complex__ ( x, 0 ) - __complex__ ( 0, y ) to
         __complex__ ( x, -y ).  This is not the same for SNaNs or if
@@ -10461,31 +10111,31 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg0)))
         {
          tree rtype = TREE_TYPE (TREE_TYPE (arg0));
-         tree arg0r = fold_unary (REALPART_EXPR, rtype, arg0);
-         tree arg0i = fold_unary (IMAGPART_EXPR, rtype, arg0);
+         tree arg0r = fold_unary_loc (loc, REALPART_EXPR, rtype, arg0);
+         tree arg0i = fold_unary_loc (loc, IMAGPART_EXPR, rtype, arg0);
          bool arg0rz = false, arg0iz = false;
          if ((arg0r && (arg0rz = real_zerop (arg0r)))
              || (arg0i && (arg0iz = real_zerop (arg0i))))
            {
-             tree arg1r = fold_unary (REALPART_EXPR, rtype, arg1);
-             tree arg1i = fold_unary (IMAGPART_EXPR, rtype, arg1);
+             tree arg1r = fold_unary_loc (loc, REALPART_EXPR, rtype, arg1);
+             tree arg1i = fold_unary_loc (loc, IMAGPART_EXPR, rtype, arg1);
              if (arg0rz && arg1i && real_zerop (arg1i))
                {
-                 tree rp = fold_build1 (NEGATE_EXPR, rtype,
+                 tree rp = fold_build1_loc (loc, NEGATE_EXPR, rtype,
                                         arg1r ? arg1r
                                         : build1 (REALPART_EXPR, rtype, arg1));
                  tree ip = arg0i ? arg0i
                    : build1 (IMAGPART_EXPR, rtype, arg0);
-                 return fold_build2 (COMPLEX_EXPR, type, rp, ip);
+                 return fold_build2_loc (loc, COMPLEX_EXPR, type, rp, ip);
                }
              else if (arg0iz && arg1r && real_zerop (arg1r))
                {
                  tree rp = arg0r ? arg0r
                    : build1 (REALPART_EXPR, rtype, arg0);
-                 tree ip = fold_build1 (NEGATE_EXPR, rtype,
+                 tree ip = fold_build1_loc (loc, NEGATE_EXPR, rtype,
                                         arg1i ? arg1i
                                         : build1 (IMAGPART_EXPR, rtype, arg1));
-                 return fold_build2 (COMPLEX_EXPR, type, rp, ip);
+                 return fold_build2_loc (loc, COMPLEX_EXPR, type, rp, ip);
                }
            }
        }
@@ -10498,7 +10148,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
 
       if ((!FLOAT_TYPE_P (type) || !HONOR_NANS (TYPE_MODE (type)))
          && operand_equal_p (arg0, arg1, 0))
-       return fold_convert (type, integer_zero_node);
+       return build_zero_cst (type);
 
       /* A - B -> A + (-B) if B is easily negatable.  */
       if (negate_expr_p (arg1)
@@ -10507,9 +10157,10 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
               && (TREE_CODE (arg1) != REAL_CST
                   ||  REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg1))))
              || INTEGRAL_TYPE_P (type)))
-       return fold_build2 (PLUS_EXPR, type,
-                           fold_convert (type, arg0),
-                           fold_convert (type, negate_expr (arg1)));
+       return fold_build2_loc (loc, PLUS_EXPR, type,
+                           fold_convert_loc (loc, type, arg0),
+                           fold_convert_loc (loc, type,
+                                             negate_expr (arg1)));
 
       /* Try folding difference of addresses.  */
       {
@@ -10532,13 +10183,13 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          if (operand_equal_p (TREE_OPERAND (aref0, 0),
                               TREE_OPERAND (aref1, 0), 0))
            {
-             tree op0 = fold_convert (type, TREE_OPERAND (aref0, 1));
-             tree op1 = fold_convert (type, TREE_OPERAND (aref1, 1));
+             tree op0 = fold_convert_loc (loc, type, TREE_OPERAND (aref0, 1));
+             tree op1 = fold_convert_loc (loc, type, TREE_OPERAND (aref1, 1));
              tree esz = array_ref_element_size (aref0);
              tree diff = build2 (MINUS_EXPR, type, op0, op1);
-             return fold_build2 (MULT_EXPR, type, diff,
-                                 fold_convert (type, esz));
-                                 
+             return fold_build2_loc (loc, MULT_EXPR, type, diff,
+                                 fold_convert_loc (loc, type, esz));
+
            }
        }
 
@@ -10546,7 +10197,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && flag_unsafe_math_optimizations
          && (TREE_CODE (arg0) == RDIV_EXPR || TREE_CODE (arg0) == MULT_EXPR)
          && (TREE_CODE (arg1) == RDIV_EXPR || TREE_CODE (arg1) == MULT_EXPR)
-         && (tem = distribute_real_division (code, type, arg0, arg1)))
+         && (tem = distribute_real_division (loc, code, type, arg0, arg1)))
        return tem;
 
       /* Handle (A1 * C1) - (A2 * C2) with A1, A2 or C1, C2 being the
@@ -10557,7 +10208,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && !TYPE_SATURATING (type)
          && (!FLOAT_TYPE_P (type) || flag_associative_math))
         {
-         tree tem = fold_plusminus_mult_expr (code, type, arg0, arg1);
+         tree tem = fold_plusminus_mult_expr (loc, code, type, arg0, arg1);
          if (tem)
            return tem;
        }
@@ -10567,42 +10218,48 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
     case MULT_EXPR:
       /* (-A) * (-B) -> A * B  */
       if (TREE_CODE (arg0) == NEGATE_EXPR && negate_expr_p (arg1))
-       return fold_build2 (MULT_EXPR, type,
-                           fold_convert (type, TREE_OPERAND (arg0, 0)),
-                           fold_convert (type, negate_expr (arg1)));
+       return fold_build2_loc (loc, MULT_EXPR, type,
+                           fold_convert_loc (loc, type,
+                                             TREE_OPERAND (arg0, 0)),
+                           fold_convert_loc (loc, type,
+                                             negate_expr (arg1)));
       if (TREE_CODE (arg1) == NEGATE_EXPR && negate_expr_p (arg0))
-       return fold_build2 (MULT_EXPR, type,
-                           fold_convert (type, negate_expr (arg0)),
-                           fold_convert (type, TREE_OPERAND (arg1, 0)));
+       return fold_build2_loc (loc, MULT_EXPR, type,
+                           fold_convert_loc (loc, type,
+                                             negate_expr (arg0)),
+                           fold_convert_loc (loc, type,
+                                             TREE_OPERAND (arg1, 0)));
 
       if (! FLOAT_TYPE_P (type))
        {
          if (integer_zerop (arg1))
-           return omit_one_operand (type, arg1, arg0);
+           return omit_one_operand_loc (loc, type, arg1, arg0);
          if (integer_onep (arg1))
-           return non_lvalue (fold_convert (type, arg0));
+           return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
          /* Transform x * -1 into -x.  Make sure to do the negation
             on the original operand with conversions not stripped
             because we can only strip non-sign-changing conversions.  */
          if (integer_all_onesp (arg1))
-           return fold_convert (type, negate_expr (op0));
+           return fold_convert_loc (loc, type, negate_expr (op0));
          /* Transform x * -C into -x * C if x is easily negatable.  */
          if (TREE_CODE (arg1) == INTEGER_CST
              && tree_int_cst_sgn (arg1) == -1
              && negate_expr_p (arg0)
              && (tem = negate_expr (arg1)) != arg1
              && !TREE_OVERFLOW (tem))
-           return fold_build2 (MULT_EXPR, type,
-                               fold_convert (type, negate_expr (arg0)), tem);
+           return fold_build2_loc (loc, MULT_EXPR, type,
+                               fold_convert_loc (loc, type,
+                                                 negate_expr (arg0)),
+                               tem);
 
          /* (a * (1 << b)) is (a << b)  */
          if (TREE_CODE (arg1) == LSHIFT_EXPR
              && integer_onep (TREE_OPERAND (arg1, 0)))
-           return fold_build2 (LSHIFT_EXPR, type, op0,
+           return fold_build2_loc (loc, LSHIFT_EXPR, type, op0,
                                TREE_OPERAND (arg1, 1));
          if (TREE_CODE (arg0) == LSHIFT_EXPR
              && integer_onep (TREE_OPERAND (arg0, 0)))
-           return fold_build2 (LSHIFT_EXPR, type, op1,
+           return fold_build2_loc (loc, LSHIFT_EXPR, type, op1,
                                TREE_OPERAND (arg0, 1));
 
          /* (A + A) * C -> A * 2 * C  */
@@ -10610,10 +10267,11 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
              && TREE_CODE (arg1) == INTEGER_CST
              && operand_equal_p (TREE_OPERAND (arg0, 0),
                                  TREE_OPERAND (arg0, 1), 0))
-           return fold_build2 (MULT_EXPR, type,
-                               omit_one_operand (type, TREE_OPERAND (arg0, 0),
+           return fold_build2_loc (loc, MULT_EXPR, type,
+                               omit_one_operand_loc (loc, type,
+                                                 TREE_OPERAND (arg0, 0),
                                                  TREE_OPERAND (arg0, 1)),
-                               fold_build2 (MULT_EXPR, type,
+                               fold_build2_loc (loc, MULT_EXPR, type,
                                             build_int_cst (type, 2) , arg1));
 
          strict_overflow_p = false;
@@ -10626,16 +10284,16 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                                        "occur when simplifying "
                                        "multiplication"),
                                       WARN_STRICT_OVERFLOW_MISC);
-             return fold_convert (type, tem);
+             return fold_convert_loc (loc, type, tem);
            }
 
          /* Optimize z * conj(z) for integer complex numbers.  */
          if (TREE_CODE (arg0) == CONJ_EXPR
              && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
-           return fold_mult_zconjz (type, arg1);
+           return fold_mult_zconjz (loc, type, arg1);
          if (TREE_CODE (arg1) == CONJ_EXPR
              && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
-           return fold_mult_zconjz (type, arg0);
+           return fold_mult_zconjz (loc, type, arg0);
        }
       else
        {
@@ -10646,21 +10304,21 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0)))
              && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0)))
              && real_zerop (arg1))
-           return omit_one_operand (type, arg1, arg0);
+           return omit_one_operand_loc (loc, type, arg1, arg0);
          /* In IEEE floating point, x*1 is not equivalent to x for snans.
             Likewise for complex arithmetic with signed zeros.  */
          if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
              && (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0)))
                  || !COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg0)))
              && real_onep (arg1))
-           return non_lvalue (fold_convert (type, arg0));
+           return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
 
          /* Transform x * -1.0 into -x.  */
          if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
              && (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0)))
                  || !COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg0)))
              && real_minus_onep (arg1))
-           return fold_convert (type, negate_expr (arg0));
+           return fold_convert_loc (loc, type, negate_expr (arg0));
 
          /* Convert (C1/X)*C2 into (C1*C2)/X.  This transformation may change
              the result for floating point types due to rounding so it is applied
@@ -10671,9 +10329,9 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
              && TREE_CODE (TREE_OPERAND (arg0, 0)) == REAL_CST)
            {
              tree tem = const_binop (MULT_EXPR, TREE_OPERAND (arg0, 0),
-                                     arg1, 0);
+                                     arg1);
              if (tem)
-               return fold_build2 (RDIV_EXPR, type, tem,
+               return fold_build2_loc (loc, RDIV_EXPR, type, tem,
                                    TREE_OPERAND (arg0, 1));
            }
 
@@ -10683,8 +10341,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
              tree tem = fold_strip_sign_ops (arg0);
              if (tem != NULL_TREE)
                {
-                 tem = fold_convert (type, tem);
-                 return fold_build2 (MULT_EXPR, type, tem, tem);
+                 tem = fold_convert_loc (loc, type, tem);
+                 return fold_build2_loc (loc, MULT_EXPR, type, tem, tem);
                }
            }
 
@@ -10699,15 +10357,17 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
            {
              tree rtype = TREE_TYPE (TREE_TYPE (arg0));
              if (real_onep (TREE_IMAGPART (arg1)))
-               return fold_build2 (COMPLEX_EXPR, type,
-                                   negate_expr (fold_build1 (IMAGPART_EXPR,
-                                                             rtype, arg0)),
-                                   fold_build1 (REALPART_EXPR, rtype, arg0));
+               return
+                 fold_build2_loc (loc, COMPLEX_EXPR, type,
+                              negate_expr (fold_build1_loc (loc, IMAGPART_EXPR,
+                                                            rtype, arg0)),
+                              fold_build1_loc (loc, REALPART_EXPR, rtype, arg0));
              else if (real_minus_onep (TREE_IMAGPART (arg1)))
-               return fold_build2 (COMPLEX_EXPR, type,
-                                   fold_build1 (IMAGPART_EXPR, rtype, arg0),
-                                   negate_expr (fold_build1 (REALPART_EXPR,
-                                                             rtype, arg0)));
+               return
+                 fold_build2_loc (loc, COMPLEX_EXPR, type,
+                              fold_build1_loc (loc, IMAGPART_EXPR, rtype, arg0),
+                              negate_expr (fold_build1_loc (loc, REALPART_EXPR,
+                                                            rtype, arg0)));
            }
 
          /* Optimize z * conj(z) for floating point complex numbers.
@@ -10716,11 +10376,11 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          if (flag_unsafe_math_optimizations
              && TREE_CODE (arg0) == CONJ_EXPR
              && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
-           return fold_mult_zconjz (type, arg1);
+           return fold_mult_zconjz (loc, type, arg1);
          if (flag_unsafe_math_optimizations
              && TREE_CODE (arg1) == CONJ_EXPR
              && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
-           return fold_mult_zconjz (type, arg0);
+           return fold_mult_zconjz (loc, type, arg0);
 
          if (flag_unsafe_math_optimizations)
            {
@@ -10742,18 +10402,18 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
 
                  /* Optimize root(x)*root(y) as root(x*y).  */
                  rootfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
-                 arg = fold_build2 (MULT_EXPR, type, arg00, arg10);
-                 return build_call_expr (rootfn, 1, arg);
+                 arg = fold_build2_loc (loc, MULT_EXPR, type, arg00, arg10);
+                 return build_call_expr_loc (loc, rootfn, 1, arg);
                }
 
              /* Optimize expN(x)*expN(y) as expN(x+y).  */
              if (fcode0 == fcode1 && BUILTIN_EXPONENT_P (fcode0))
                {
                  tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
-                 tree arg = fold_build2 (PLUS_EXPR, type,
+                 tree arg = fold_build2_loc (loc, PLUS_EXPR, type,
                                          CALL_EXPR_ARG (arg0, 0),
                                          CALL_EXPR_ARG (arg1, 0));
-                 return build_call_expr (expfn, 1, arg);
+                 return build_call_expr_loc (loc, expfn, 1, arg);
                }
 
              /* Optimizations of pow(...)*pow(...).  */
@@ -10770,16 +10430,18 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                  if (operand_equal_p (arg01, arg11, 0))
                    {
                      tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
-                     tree arg = fold_build2 (MULT_EXPR, type, arg00, arg10);
-                     return build_call_expr (powfn, 2, arg, arg01);
+                     tree arg = fold_build2_loc (loc, MULT_EXPR, type,
+                                             arg00, arg10);
+                     return build_call_expr_loc (loc, powfn, 2, arg, arg01);
                    }
 
                  /* Optimize pow(x,y)*pow(x,z) as pow(x,y+z).  */
                  if (operand_equal_p (arg00, arg10, 0))
                    {
                      tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
-                     tree arg = fold_build2 (PLUS_EXPR, type, arg01, arg11);
-                     return build_call_expr (powfn, 2, arg00, arg);
+                     tree arg = fold_build2_loc (loc, PLUS_EXPR, type,
+                                             arg01, arg11);
+                     return build_call_expr_loc (loc, powfn, 2, arg00, arg);
                    }
                }
 
@@ -10796,7 +10458,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                  tree sinfn = mathfn_built_in (type, BUILT_IN_SIN);
 
                  if (sinfn != NULL_TREE)
-                   return build_call_expr (sinfn, 1, CALL_EXPR_ARG (arg0, 0));
+                   return build_call_expr_loc (loc, sinfn, 1,
+                                           CALL_EXPR_ARG (arg0, 0));
                }
 
              /* Optimize x*pow(x,c) as pow(x,c+1).  */
@@ -10817,7 +10480,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                      c = TREE_REAL_CST (arg11);
                      real_arithmetic (&c, PLUS_EXPR, &c, &dconst1);
                      arg = build_real (type, c);
-                     return build_call_expr (powfn, 2, arg0, arg);
+                     return build_call_expr_loc (loc, powfn, 2, arg0, arg);
                    }
                }
 
@@ -10839,7 +10502,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                      c = TREE_REAL_CST (arg01);
                      real_arithmetic (&c, PLUS_EXPR, &c, &dconst1);
                      arg = build_real (type, c);
-                     return build_call_expr (powfn, 2, arg1, arg);
+                     return build_call_expr_loc (loc, powfn, 2, arg1, arg);
                    }
                }
 
@@ -10852,7 +10515,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                  if (powfn)
                    {
                      tree arg = build_real (type, dconst2);
-                     return build_call_expr (powfn, 2, arg0, arg);
+                     return build_call_expr_loc (loc, powfn, 2, arg0, arg);
                    }
                }
            }
@@ -10862,28 +10525,28 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
     case BIT_IOR_EXPR:
     bit_ior:
       if (integer_all_onesp (arg1))
-       return omit_one_operand (type, arg1, arg0);
+       return omit_one_operand_loc (loc, type, arg1, arg0);
       if (integer_zerop (arg1))
-       return non_lvalue (fold_convert (type, arg0));
+       return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
       if (operand_equal_p (arg0, arg1, 0))
-       return non_lvalue (fold_convert (type, arg0));
+       return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
 
       /* ~X | X is -1.  */
       if (TREE_CODE (arg0) == BIT_NOT_EXPR
          && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
        {
-         t1 = fold_convert (type, integer_zero_node);
-         t1 = fold_unary (BIT_NOT_EXPR, type, t1);
-         return omit_one_operand (type, t1, arg1);
+         t1 = build_zero_cst (type);
+         t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
+         return omit_one_operand_loc (loc, type, t1, arg1);
        }
 
       /* X | ~X is -1.  */
       if (TREE_CODE (arg1) == BIT_NOT_EXPR
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
        {
-         t1 = fold_convert (type, integer_zero_node);
-         t1 = fold_unary (BIT_NOT_EXPR, type, t1);
-         return omit_one_operand (type, t1, arg0);
+         t1 = build_zero_cst (type);
+         t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
+         return omit_one_operand_loc (loc, type, t1, arg0);
        }
 
       /* Canonicalize (X & C1) | C2.  */
@@ -10900,11 +10563,12 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
 
          /* If (C1&C2) == C1, then (X&C1)|C2 becomes (X,C2).  */
          if ((hi1 & hi2) == hi1 && (lo1 & lo2) == lo1)
-           return omit_one_operand (type, arg1, TREE_OPERAND (arg0, 0));
+           return omit_one_operand_loc (loc, type, arg1,
+                                    TREE_OPERAND (arg0, 0));
 
          if (width > HOST_BITS_PER_WIDE_INT)
            {
-             mhi = (unsigned HOST_WIDE_INT) -1 
+             mhi = (unsigned HOST_WIDE_INT) -1
                    >> (2 * HOST_BITS_PER_WIDE_INT - width);
              mlo = -1;
            }
@@ -10917,7 +10581,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
 
          /* If (C1|C2) == ~0 then (X&C1)|C2 becomes X|C2.  */
          if ((~(hi1 | hi2) & mhi) == 0 && (~(lo1 | lo2) & mlo) == 0)
-           return fold_build2 (BIT_IOR_EXPR, type,
+           return fold_build2_loc (loc, BIT_IOR_EXPR, type,
                                TREE_OPERAND (arg0, 0), arg1);
 
          /* Minimize the number of bits set in C1, i.e. C1 := C1 & ~C2,
@@ -10944,8 +10608,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                }
            }
          if (hi3 != hi1 || lo3 != lo1)
-           return fold_build2 (BIT_IOR_EXPR, type,
-                               fold_build2 (BIT_AND_EXPR, type,
+           return fold_build2_loc (loc, BIT_IOR_EXPR, type,
+                               fold_build2_loc (loc, BIT_AND_EXPR, type,
                                             TREE_OPERAND (arg0, 0),
                                             build_int_cst_wide (type,
                                                                 lo3, hi3)),
@@ -10955,24 +10619,46 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
       /* (X & Y) | Y is (X, Y).  */
       if (TREE_CODE (arg0) == BIT_AND_EXPR
          && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
-       return omit_one_operand (type, arg1, TREE_OPERAND (arg0, 0));
+       return omit_one_operand_loc (loc, type, arg1, TREE_OPERAND (arg0, 0));
       /* (X & Y) | X is (Y, X).  */
       if (TREE_CODE (arg0) == BIT_AND_EXPR
          && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
          && reorder_operands_p (TREE_OPERAND (arg0, 1), arg1))
-       return omit_one_operand (type, arg1, TREE_OPERAND (arg0, 1));
+       return omit_one_operand_loc (loc, type, arg1, TREE_OPERAND (arg0, 1));
       /* X | (X & Y) is (Y, X).  */
       if (TREE_CODE (arg1) == BIT_AND_EXPR
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0)
          && reorder_operands_p (arg0, TREE_OPERAND (arg1, 1)))
-       return omit_one_operand (type, arg0, TREE_OPERAND (arg1, 1));
+       return omit_one_operand_loc (loc, type, arg0, TREE_OPERAND (arg1, 1));
       /* X | (Y & X) is (Y, X).  */
       if (TREE_CODE (arg1) == BIT_AND_EXPR
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 1), 0)
          && reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
-       return omit_one_operand (type, arg0, TREE_OPERAND (arg1, 0));
+       return omit_one_operand_loc (loc, type, arg0, TREE_OPERAND (arg1, 0));
+
+      /* (X & ~Y) | (~X & Y) is X ^ Y */
+      if (TREE_CODE (arg0) == BIT_AND_EXPR
+         && TREE_CODE (arg1) == BIT_AND_EXPR)
+        {
+         tree a0, a1, l0, l1, n0, n1;
 
-      t1 = distribute_bit_expr (code, type, arg0, arg1);
+         a0 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 0));
+         a1 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 1));
+
+         l0 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
+         l1 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
+         
+         n0 = fold_build1_loc (loc, BIT_NOT_EXPR, type, l0);
+         n1 = fold_build1_loc (loc, BIT_NOT_EXPR, type, l1);
+         
+         if ((operand_equal_p (n0, a0, 0)
+              && operand_equal_p (n1, a1, 0))
+             || (operand_equal_p (n0, a1, 0)
+                 && operand_equal_p (n1, a0, 0)))
+           return fold_build2_loc (loc, BIT_XOR_EXPR, type, l0, n1);
+       }
+
+      t1 = distribute_bit_expr (loc, code, type, arg0, arg1);
       if (t1 != NULL_TREE)
        return t1;
 
@@ -10985,12 +10671,13 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
       if (TREE_CODE (arg0) == BIT_NOT_EXPR
          && TREE_CODE (arg1) == BIT_NOT_EXPR)
        {
-         return fold_build1 (BIT_NOT_EXPR, type,
-                             build2 (BIT_AND_EXPR, type,
-                                     fold_convert (type,
-                                                   TREE_OPERAND (arg0, 0)),
-                                     fold_convert (type,
-                                                   TREE_OPERAND (arg1, 0))));
+         return
+           fold_build1_loc (loc, BIT_NOT_EXPR, type,
+                        build2 (BIT_AND_EXPR, type,
+                                fold_convert_loc (loc, type,
+                                                  TREE_OPERAND (arg0, 0)),
+                                fold_convert_loc (loc, type,
+                                                  TREE_OPERAND (arg1, 0))));
        }
 
       /* See if this can be simplified into a rotate first.  If that
@@ -10999,28 +10686,28 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
 
     case BIT_XOR_EXPR:
       if (integer_zerop (arg1))
-       return non_lvalue (fold_convert (type, arg0));
+       return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
       if (integer_all_onesp (arg1))
-       return fold_build1 (BIT_NOT_EXPR, type, op0);
+       return fold_build1_loc (loc, BIT_NOT_EXPR, type, op0);
       if (operand_equal_p (arg0, arg1, 0))
-       return omit_one_operand (type, integer_zero_node, arg0);
+       return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
 
       /* ~X ^ X is -1.  */
       if (TREE_CODE (arg0) == BIT_NOT_EXPR
          && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
        {
-         t1 = fold_convert (type, integer_zero_node);
-         t1 = fold_unary (BIT_NOT_EXPR, type, t1);
-         return omit_one_operand (type, t1, arg1);
+         t1 = build_zero_cst (type);
+         t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
+         return omit_one_operand_loc (loc, type, t1, arg1);
        }
 
       /* X ^ ~X is -1.  */
       if (TREE_CODE (arg1) == BIT_NOT_EXPR
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
        {
-         t1 = fold_convert (type, integer_zero_node);
-         t1 = fold_unary (BIT_NOT_EXPR, type, t1);
-         return omit_one_operand (type, t1, arg0);
+         t1 = build_zero_cst (type);
+         t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
+         return omit_one_operand_loc (loc, type, t1, arg0);
        }
 
       /* If we are XORing two BIT_AND_EXPR's, both of which are and'ing
@@ -11033,7 +10720,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && TREE_CODE (TREE_OPERAND (arg1, 1)) == INTEGER_CST
          && integer_zerop (const_binop (BIT_AND_EXPR,
                                         TREE_OPERAND (arg0, 1),
-                                        TREE_OPERAND (arg1, 1), 0)))
+                                        TREE_OPERAND (arg1, 1))))
        {
          code = BIT_IOR_EXPR;
          goto bit_ior;
@@ -11044,10 +10731,11 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
           && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
         {
          tree t2 = TREE_OPERAND (arg0, 1);
-         t1 = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (arg1),
+         t1 = fold_build1_loc (loc, BIT_NOT_EXPR, TREE_TYPE (arg1),
                            arg1);
-         t1 = fold_build2 (BIT_AND_EXPR, type, fold_convert (type, t2),
-                           fold_convert (type, t1));
+         t1 = fold_build2_loc (loc, BIT_AND_EXPR, type,
+                           fold_convert_loc (loc, type, t2),
+                           fold_convert_loc (loc, type, t1));
          return t1;
        }
 
@@ -11056,10 +10744,11 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
           && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
         {
          tree t2 = TREE_OPERAND (arg0, 0);
-         t1 = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (arg1),
+         t1 = fold_build1_loc (loc, BIT_NOT_EXPR, TREE_TYPE (arg1),
                            arg1);
-         t1 = fold_build2 (BIT_AND_EXPR, type, fold_convert (type, t2),
-                           fold_convert (type, t1));
+         t1 = fold_build2_loc (loc, BIT_AND_EXPR, type,
+                           fold_convert_loc (loc, type, t2),
+                           fold_convert_loc (loc, type, t1));
          return t1;
        }
 
@@ -11068,10 +10757,11 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
           && operand_equal_p (TREE_OPERAND (arg1, 0), arg0, 0))
         {
          tree t2 = TREE_OPERAND (arg1, 1);
-         t1 = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (arg0),
+         t1 = fold_build1_loc (loc, BIT_NOT_EXPR, TREE_TYPE (arg0),
                            arg0);
-         t1 = fold_build2 (BIT_AND_EXPR, type, fold_convert (type, t2),
-                           fold_convert (type, t1));
+         t1 = fold_build2_loc (loc, BIT_AND_EXPR, type,
+                           fold_convert_loc (loc, type, t2),
+                           fold_convert_loc (loc, type, t1));
          return t1;
        }
 
@@ -11080,71 +10770,75 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
           && operand_equal_p (TREE_OPERAND (arg1, 1), arg0, 0))
         {
          tree t2 = TREE_OPERAND (arg1, 0);
-         t1 = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (arg0),
+         t1 = fold_build1_loc (loc, BIT_NOT_EXPR, TREE_TYPE (arg0),
                            arg0);
-         t1 = fold_build2 (BIT_AND_EXPR, type, fold_convert (type, t2),
-                           fold_convert (type, t1));
+         t1 = fold_build2_loc (loc, BIT_AND_EXPR, type,
+                           fold_convert_loc (loc, type, t2),
+                           fold_convert_loc (loc, type, t1));
          return t1;
        }
-       
+
       /* Convert ~X ^ ~Y to X ^ Y.  */
       if (TREE_CODE (arg0) == BIT_NOT_EXPR
          && TREE_CODE (arg1) == BIT_NOT_EXPR)
-       return fold_build2 (code, type,
-                           fold_convert (type, TREE_OPERAND (arg0, 0)),
-                           fold_convert (type, TREE_OPERAND (arg1, 0)));
+       return fold_build2_loc (loc, code, type,
+                           fold_convert_loc (loc, type,
+                                             TREE_OPERAND (arg0, 0)),
+                           fold_convert_loc (loc, type,
+                                             TREE_OPERAND (arg1, 0)));
 
       /* Convert ~X ^ C to X ^ ~C.  */
       if (TREE_CODE (arg0) == BIT_NOT_EXPR
          && TREE_CODE (arg1) == INTEGER_CST)
-       return fold_build2 (code, type,
-                           fold_convert (type, TREE_OPERAND (arg0, 0)),
-                           fold_build1 (BIT_NOT_EXPR, type, arg1));
+       return fold_build2_loc (loc, code, type,
+                           fold_convert_loc (loc, type,
+                                             TREE_OPERAND (arg0, 0)),
+                           fold_build1_loc (loc, BIT_NOT_EXPR, type, arg1));
 
       /* Fold (X & 1) ^ 1 as (X & 1) == 0.  */
       if (TREE_CODE (arg0) == BIT_AND_EXPR
          && integer_onep (TREE_OPERAND (arg0, 1))
          && integer_onep (arg1))
-       return fold_build2 (EQ_EXPR, type, arg0,
+       return fold_build2_loc (loc, EQ_EXPR, type, arg0,
                            build_int_cst (TREE_TYPE (arg0), 0));
 
       /* Fold (X & Y) ^ Y as ~X & Y.  */
       if (TREE_CODE (arg0) == BIT_AND_EXPR
          && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
        {
-         tem = fold_convert (type, TREE_OPERAND (arg0, 0));
-         return fold_build2 (BIT_AND_EXPR, type, 
-                             fold_build1 (BIT_NOT_EXPR, type, tem),
-                             fold_convert (type, arg1));
+         tem = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
+         return fold_build2_loc (loc, BIT_AND_EXPR, type,
+                             fold_build1_loc (loc, BIT_NOT_EXPR, type, tem),
+                             fold_convert_loc (loc, type, arg1));
        }
       /* Fold (X & Y) ^ X as ~Y & X.  */
       if (TREE_CODE (arg0) == BIT_AND_EXPR
          && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
          && reorder_operands_p (TREE_OPERAND (arg0, 1), arg1))
        {
-         tem = fold_convert (type, TREE_OPERAND (arg0, 1));
-         return fold_build2 (BIT_AND_EXPR, type,
-                             fold_build1 (BIT_NOT_EXPR, type, tem),
-                             fold_convert (type, arg1));
+         tem = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
+         return fold_build2_loc (loc, BIT_AND_EXPR, type,
+                             fold_build1_loc (loc, BIT_NOT_EXPR, type, tem),
+                             fold_convert_loc (loc, type, arg1));
        }
       /* Fold X ^ (X & Y) as X & ~Y.  */
       if (TREE_CODE (arg1) == BIT_AND_EXPR
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
        {
-         tem = fold_convert (type, TREE_OPERAND (arg1, 1));
-         return fold_build2 (BIT_AND_EXPR, type,
-                             fold_convert (type, arg0),
-                             fold_build1 (BIT_NOT_EXPR, type, tem));
+         tem = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 1));
+         return fold_build2_loc (loc, BIT_AND_EXPR, type,
+                             fold_convert_loc (loc, type, arg0),
+                             fold_build1_loc (loc, BIT_NOT_EXPR, type, tem));
        }
       /* Fold X ^ (Y & X) as ~Y & X.  */
       if (TREE_CODE (arg1) == BIT_AND_EXPR
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 1), 0)
          && reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
        {
-         tem = fold_convert (type, TREE_OPERAND (arg1, 0));
-         return fold_build2 (BIT_AND_EXPR, type,
-                             fold_build1 (BIT_NOT_EXPR, type, tem),
-                             fold_convert (type, arg0));
+         tem = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 0));
+         return fold_build2_loc (loc, BIT_AND_EXPR, type,
+                             fold_build1_loc (loc, BIT_NOT_EXPR, type, tem),
+                             fold_convert_loc (loc, type, arg0));
        }
 
       /* See if this can be simplified into a rotate first.  If that
@@ -11153,55 +10847,57 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
 
     case BIT_AND_EXPR:
       if (integer_all_onesp (arg1))
-       return non_lvalue (fold_convert (type, arg0));
+       return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
       if (integer_zerop (arg1))
-       return omit_one_operand (type, arg1, arg0);
+       return omit_one_operand_loc (loc, type, arg1, arg0);
       if (operand_equal_p (arg0, arg1, 0))
-       return non_lvalue (fold_convert (type, arg0));
+       return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
 
       /* ~X & X is always zero.  */
       if (TREE_CODE (arg0) == BIT_NOT_EXPR
          && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
-       return omit_one_operand (type, integer_zero_node, arg1);
+       return omit_one_operand_loc (loc, type, integer_zero_node, arg1);
 
       /* X & ~X is always zero.  */
       if (TREE_CODE (arg1) == BIT_NOT_EXPR
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
-       return omit_one_operand (type, integer_zero_node, arg0);
+       return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
 
       /* Canonicalize (X | C1) & C2 as (X & C2) | (C1 & C2).  */
       if (TREE_CODE (arg0) == BIT_IOR_EXPR
          && TREE_CODE (arg1) == INTEGER_CST
          && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
        {
-         tree tmp1 = fold_convert (type, arg1);
-         tree tmp2 = fold_convert (type, TREE_OPERAND (arg0, 0));
-         tree tmp3 = fold_convert (type, TREE_OPERAND (arg0, 1));
-         tmp2 = fold_build2 (BIT_AND_EXPR, type, tmp2, tmp1);
-         tmp3 = fold_build2 (BIT_AND_EXPR, type, tmp3, tmp1);
-         return fold_convert (type,
-                              fold_build2 (BIT_IOR_EXPR, type, tmp2, tmp3));
+         tree tmp1 = fold_convert_loc (loc, type, arg1);
+         tree tmp2 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
+         tree tmp3 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
+         tmp2 = fold_build2_loc (loc, BIT_AND_EXPR, type, tmp2, tmp1);
+         tmp3 = fold_build2_loc (loc, BIT_AND_EXPR, type, tmp3, tmp1);
+         return
+           fold_convert_loc (loc, type,
+                             fold_build2_loc (loc, BIT_IOR_EXPR,
+                                          type, tmp2, tmp3));
        }
 
       /* (X | Y) & Y is (X, Y).  */
       if (TREE_CODE (arg0) == BIT_IOR_EXPR
          && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
-       return omit_one_operand (type, arg1, TREE_OPERAND (arg0, 0));
+       return omit_one_operand_loc (loc, type, arg1, TREE_OPERAND (arg0, 0));
       /* (X | Y) & X is (Y, X).  */
       if (TREE_CODE (arg0) == BIT_IOR_EXPR
          && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
          && reorder_operands_p (TREE_OPERAND (arg0, 1), arg1))
-       return omit_one_operand (type, arg1, TREE_OPERAND (arg0, 1));
+       return omit_one_operand_loc (loc, type, arg1, TREE_OPERAND (arg0, 1));
       /* X & (X | Y) is (Y, X).  */
       if (TREE_CODE (arg1) == BIT_IOR_EXPR
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0)
          && reorder_operands_p (arg0, TREE_OPERAND (arg1, 1)))
-       return omit_one_operand (type, arg0, TREE_OPERAND (arg1, 1));
+       return omit_one_operand_loc (loc, type, arg0, TREE_OPERAND (arg1, 1));
       /* X & (Y | X) is (Y, X).  */
       if (TREE_CODE (arg1) == BIT_IOR_EXPR
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 1), 0)
          && reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
-       return omit_one_operand (type, arg0, TREE_OPERAND (arg1, 0));
+       return omit_one_operand_loc (loc, type, arg0, TREE_OPERAND (arg1, 0));
 
       /* Fold (X ^ 1) & 1 as (X & 1) == 0.  */
       if (TREE_CODE (arg0) == BIT_XOR_EXPR
@@ -11209,8 +10905,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && integer_onep (arg1))
        {
          tem = TREE_OPERAND (arg0, 0);
-         return fold_build2 (EQ_EXPR, type,
-                             fold_build2 (BIT_AND_EXPR, TREE_TYPE (tem), tem,
+         return fold_build2_loc (loc, EQ_EXPR, type,
+                             fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (tem), tem,
                                           build_int_cst (TREE_TYPE (tem), 1)),
                              build_int_cst (TREE_TYPE (tem), 0));
        }
@@ -11219,8 +10915,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && integer_onep (arg1))
        {
          tem = TREE_OPERAND (arg0, 0);
-         return fold_build2 (EQ_EXPR, type,
-                             fold_build2 (BIT_AND_EXPR, TREE_TYPE (tem), tem,
+         return fold_build2_loc (loc, EQ_EXPR, type,
+                             fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (tem), tem,
                                           build_int_cst (TREE_TYPE (tem), 1)),
                              build_int_cst (TREE_TYPE (tem), 0));
        }
@@ -11229,42 +10925,162 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
       if (TREE_CODE (arg0) == BIT_XOR_EXPR
          && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
        {
-         tem = fold_convert (type, TREE_OPERAND (arg0, 0));
-         return fold_build2 (BIT_AND_EXPR, type, 
-                             fold_build1 (BIT_NOT_EXPR, type, tem),
-                             fold_convert (type, arg1));
+         tem = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
+         return fold_build2_loc (loc, BIT_AND_EXPR, type,
+                             fold_build1_loc (loc, BIT_NOT_EXPR, type, tem),
+                             fold_convert_loc (loc, type, arg1));
        }
       /* Fold (X ^ Y) & X as ~Y & X.  */
       if (TREE_CODE (arg0) == BIT_XOR_EXPR
          && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
          && reorder_operands_p (TREE_OPERAND (arg0, 1), arg1))
        {
-         tem = fold_convert (type, TREE_OPERAND (arg0, 1));
-         return fold_build2 (BIT_AND_EXPR, type,
-                             fold_build1 (BIT_NOT_EXPR, type, tem),
-                             fold_convert (type, arg1));
+         tem = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
+         return fold_build2_loc (loc, BIT_AND_EXPR, type,
+                             fold_build1_loc (loc, BIT_NOT_EXPR, type, tem),
+                             fold_convert_loc (loc, type, arg1));
        }
       /* Fold X & (X ^ Y) as X & ~Y.  */
       if (TREE_CODE (arg1) == BIT_XOR_EXPR
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
        {
-         tem = fold_convert (type, TREE_OPERAND (arg1, 1));
-         return fold_build2 (BIT_AND_EXPR, type,
-                             fold_convert (type, arg0),
-                             fold_build1 (BIT_NOT_EXPR, type, tem));
+         tem = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 1));
+         return fold_build2_loc (loc, BIT_AND_EXPR, type,
+                             fold_convert_loc (loc, type, arg0),
+                             fold_build1_loc (loc, BIT_NOT_EXPR, type, tem));
        }
       /* Fold X & (Y ^ X) as ~Y & X.  */
       if (TREE_CODE (arg1) == BIT_XOR_EXPR
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 1), 0)
          && reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
        {
-         tem = fold_convert (type, TREE_OPERAND (arg1, 0));
-         return fold_build2 (BIT_AND_EXPR, type,
-                             fold_build1 (BIT_NOT_EXPR, type, tem),
-                             fold_convert (type, arg0));
+         tem = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 0));
+         return fold_build2_loc (loc, BIT_AND_EXPR, type,
+                             fold_build1_loc (loc, BIT_NOT_EXPR, type, tem),
+                             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 (code, type, arg0, arg1);
+      t1 = distribute_bit_expr (loc, code, type, arg0, arg1);
       if (t1 != NULL_TREE)
        return t1;
       /* Simplify ((int)c & 0377) into (int)c, if c is unsigned char.  */
@@ -11277,7 +11093,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          if (prec < BITS_PER_WORD && prec < HOST_BITS_PER_WIDE_INT
              && (~TREE_INT_CST_LOW (arg1)
                  & (((HOST_WIDE_INT) 1 << prec) - 1)) == 0)
-           return fold_convert (type, TREE_OPERAND (arg0, 0));
+           return
+             fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
        }
 
       /* Convert (and (not arg0) (not arg1)) to (not (or (arg0) (arg1))).
@@ -11289,12 +11106,12 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
       if (TREE_CODE (arg0) == BIT_NOT_EXPR
          && TREE_CODE (arg1) == BIT_NOT_EXPR)
        {
-         return fold_build1 (BIT_NOT_EXPR, type,
+         return fold_build1_loc (loc, BIT_NOT_EXPR, type,
                              build2 (BIT_IOR_EXPR, type,
-                                     fold_convert (type,
-                                                   TREE_OPERAND (arg0, 0)),
-                                     fold_convert (type,
-                                                   TREE_OPERAND (arg1, 0))));
+                                     fold_convert_loc (loc, type,
+                                                       TREE_OPERAND (arg0, 0)),
+                                     fold_convert_loc (loc, type,
+                                                       TREE_OPERAND (arg1, 0))));
        }
 
       /* If arg0 is derived from the address of an object or function, we may
@@ -11376,7 +11193,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
 
          /* ((X << 16) & 0xff00) is (X, 0).  */
          if ((mask & zerobits) == mask)
-           return omit_one_operand (type, build_int_cst (type, 0), arg0);
+           return omit_one_operand_loc (loc, type,
+                                    build_int_cst (type, 0), arg0);
 
          newmask = mask | zerobits;
          if (newmask != mask && (newmask & (newmask + 1)) == 0)
@@ -11392,19 +11210,21 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
              if (prec < HOST_BITS_PER_WIDE_INT
                  || newmask == ~(unsigned HOST_WIDE_INT) 0)
                {
+                 tree newmaskt;
+
                  if (shift_type != TREE_TYPE (arg0))
                    {
-                     tem = fold_build2 (TREE_CODE (arg0), shift_type,
-                                        fold_convert (shift_type,
-                                                      TREE_OPERAND (arg0, 0)),
+                     tem = fold_build2_loc (loc, TREE_CODE (arg0), shift_type,
+                                        fold_convert_loc (loc, shift_type,
+                                                          TREE_OPERAND (arg0, 0)),
                                         TREE_OPERAND (arg0, 1));
-                     tem = fold_convert (type, tem);
+                     tem = fold_convert_loc (loc, type, tem);
                    }
                  else
                    tem = op0;
-                 return fold_build2 (BIT_AND_EXPR, type, tem,
-                                     build_int_cst_type (TREE_TYPE (op1),
-                                                         newmask));
+                 newmaskt = build_int_cst_type (TREE_TYPE (op1), newmask);
+                 if (!tree_int_cst_equal (newmaskt, arg1))
+                   return fold_build2_loc (loc, BIT_AND_EXPR, type, tem, newmaskt);
                }
            }
        }
@@ -11429,7 +11249,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
        {
          tree r = build_real (TREE_TYPE (arg0), dconst1);
 
-         return omit_two_operands (type, r, arg0, arg1);
+         return omit_two_operands_loc (loc, type, r, arg0, arg1);
        }
 
       /* The complex version of the above A / A optimization.  */
@@ -11442,29 +11262,30 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
            {
              tree r = build_real (elem_type, dconst1);
              /* omit_two_operands will call fold_convert for us.  */
-             return omit_two_operands (type, r, arg0, arg1);
+             return omit_two_operands_loc (loc, type, r, arg0, arg1);
            }
        }
 
       /* (-A) / (-B) -> A / B  */
       if (TREE_CODE (arg0) == NEGATE_EXPR && negate_expr_p (arg1))
-       return fold_build2 (RDIV_EXPR, type,
+       return fold_build2_loc (loc, RDIV_EXPR, type,
                            TREE_OPERAND (arg0, 0),
                            negate_expr (arg1));
       if (TREE_CODE (arg1) == NEGATE_EXPR && negate_expr_p (arg0))
-       return fold_build2 (RDIV_EXPR, type,
+       return fold_build2_loc (loc, RDIV_EXPR, type,
                            negate_expr (arg0),
                            TREE_OPERAND (arg1, 0));
 
       /* In IEEE floating point, x/1 is not equivalent to x for snans.  */
       if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
          && real_onep (arg1))
-       return non_lvalue (fold_convert (type, arg0));
+       return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
 
       /* In IEEE floating point, x/-1 is not equivalent to -x for snans.  */
       if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
          && real_minus_onep (arg1))
-       return non_lvalue (fold_convert (type, negate_expr (arg0)));
+       return non_lvalue_loc (loc, fold_convert_loc (loc, type,
+                                                 negate_expr (arg0)));
 
       /* If ARG1 is a constant, we can convert this to a multiply by the
         reciprocal.  This does not have the same rounding properties,
@@ -11475,8 +11296,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
        {
          if (flag_reciprocal_math
              && 0 != (tem = const_binop (code, build_real (type, dconst1),
-                                         arg1, 0)))
-           return fold_build2 (MULT_EXPR, type, arg0, tem);
+                                         arg1)))
+           return fold_build2_loc (loc, MULT_EXPR, type, arg0, tem);
          /* Find the reciprocal if optimizing and the result is exact.  */
          if (optimize)
            {
@@ -11485,23 +11306,23 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
              if (exact_real_inverse (TYPE_MODE(TREE_TYPE(arg0)), &r))
                {
                  tem = build_real (type, r);
-                 return fold_build2 (MULT_EXPR, type,
-                                     fold_convert (type, arg0), tem);
+                 return fold_build2_loc (loc, MULT_EXPR, type,
+                                     fold_convert_loc (loc, type, arg0), tem);
                }
            }
        }
-      /* Convert A/B/C to A/(B*C).  */ 
+      /* Convert A/B/C to A/(B*C).  */
       if (flag_reciprocal_math
          && TREE_CODE (arg0) == RDIV_EXPR)
-       return fold_build2 (RDIV_EXPR, type, TREE_OPERAND (arg0, 0),
-                           fold_build2 (MULT_EXPR, type,
+       return fold_build2_loc (loc, RDIV_EXPR, type, TREE_OPERAND (arg0, 0),
+                           fold_build2_loc (loc, MULT_EXPR, type,
                                         TREE_OPERAND (arg0, 1), arg1));
 
       /* Convert A/(B/C) to (A/B)*C.  */
       if (flag_reciprocal_math
          && TREE_CODE (arg1) == RDIV_EXPR)
-       return fold_build2 (MULT_EXPR, type,
-                           fold_build2 (RDIV_EXPR, type, arg0,
+       return fold_build2_loc (loc, MULT_EXPR, type,
+                           fold_build2_loc (loc, RDIV_EXPR, type, arg0,
                                         TREE_OPERAND (arg1, 0)),
                            TREE_OPERAND (arg1, 1));
 
@@ -11512,9 +11333,9 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && TREE_CODE (TREE_OPERAND (arg1, 1)) == REAL_CST)
        {
          tree tem = const_binop (RDIV_EXPR, arg0,
-                                 TREE_OPERAND (arg1, 1), 0);
+                                 TREE_OPERAND (arg1, 1));
          if (tem)
-           return fold_build2 (RDIV_EXPR, type, tem,
+           return fold_build2_loc (loc, RDIV_EXPR, type, tem,
                                TREE_OPERAND (arg1, 0));
        }
 
@@ -11533,7 +11354,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
              tree tanfn = mathfn_built_in (type, BUILT_IN_TAN);
 
              if (tanfn != NULL_TREE)
-               return build_call_expr (tanfn, 1, CALL_EXPR_ARG (arg0, 0));
+               return build_call_expr_loc (loc, tanfn, 1, CALL_EXPR_ARG (arg0, 0));
            }
 
          /* Optimize cos(x)/sin(x) as 1.0/tan(x).  */
@@ -11547,8 +11368,9 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
 
              if (tanfn != NULL_TREE)
                {
-                 tree tmp = build_call_expr (tanfn, 1, CALL_EXPR_ARG (arg0, 0));
-                 return fold_build2 (RDIV_EXPR, type,
+                 tree tmp = build_call_expr_loc (loc, tanfn, 1,
+                                             CALL_EXPR_ARG (arg0, 0));
+                 return fold_build2_loc (loc, RDIV_EXPR, type,
                                      build_real (type, dconst1), tmp);
                }
            }
@@ -11569,7 +11391,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                  tree cosfn = mathfn_built_in (type, BUILT_IN_COS);
 
                  if (cosfn != NULL_TREE)
-                   return build_call_expr (cosfn, 1, arg00);
+                   return build_call_expr_loc (loc, cosfn, 1, arg00);
                }
            }
 
@@ -11590,8 +11412,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
 
                  if (cosfn != NULL_TREE)
                    {
-                     tree tmp = build_call_expr (cosfn, 1, arg00);
-                     return fold_build2 (RDIV_EXPR, type,
+                     tree tmp = build_call_expr_loc (loc, cosfn, 1, arg00);
+                     return fold_build2_loc (loc, RDIV_EXPR, type,
                                          build_real (type, dconst1),
                                          tmp);
                    }
@@ -11616,7 +11438,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                  c = TREE_REAL_CST (arg01);
                  real_arithmetic (&c, MINUS_EXPR, &c, &dconst1);
                  arg = build_real (type, c);
-                 return build_call_expr (powfn, 2, arg1, arg);
+                 return build_call_expr_loc (loc, powfn, 2, arg1, arg);
                }
            }
 
@@ -11631,10 +11453,10 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                  tree b = TREE_OPERAND (rootarg, 0);
                  tree c = TREE_OPERAND (rootarg, 1);
 
-                 tree tmp = fold_build2 (RDIV_EXPR, type, c, b);
+                 tree tmp = fold_build2_loc (loc, RDIV_EXPR, type, c, b);
 
-                 tmp = build_call_expr (rootfn, 1, tmp);
-                 return fold_build2 (MULT_EXPR, type, arg0, tmp);
+                 tmp = build_call_expr_loc (loc, rootfn, 1, tmp);
+                 return fold_build2_loc (loc, MULT_EXPR, type, arg0, tmp);
                }
            }
 
@@ -11643,8 +11465,10 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
            {
              tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg1), 0);
              tree arg = negate_expr (CALL_EXPR_ARG (arg1, 0));
-             arg1 = build_call_expr (expfn, 1, fold_convert (type, arg));
-             return fold_build2 (MULT_EXPR, type, arg0, arg1);
+             arg1 = build_call_expr_loc (loc,
+                                     expfn, 1,
+                                     fold_convert_loc (loc, type, arg));
+             return fold_build2_loc (loc, MULT_EXPR, type, arg0, arg1);
            }
 
          /* Optimize x/pow(y,z) into x*pow(y,-z).  */
@@ -11655,14 +11479,40 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
              tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg1), 0);
              tree arg10 = CALL_EXPR_ARG (arg1, 0);
              tree arg11 = CALL_EXPR_ARG (arg1, 1);
-             tree neg11 = fold_convert (type, negate_expr (arg11));
-             arg1 = build_call_expr (powfn, 2, arg10, neg11);
-             return fold_build2 (MULT_EXPR, type, arg0, arg1);
+             tree neg11 = fold_convert_loc (loc, type,
+                                            negate_expr (arg11));
+             arg1 = build_call_expr_loc (loc, powfn, 2, arg10, neg11);
+             return fold_build2_loc (loc, MULT_EXPR, type, arg0, arg1);
            }
        }
       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 (integer_type_node, 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)).  */
@@ -11675,17 +11525,25 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          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 "
                                        "occur when simplifying A / (B << N)"),
                                       WARN_STRICT_OVERFLOW_MISC);
 
-             sh_cnt = fold_build2 (PLUS_EXPR, TREE_TYPE (sh_cnt),
-                                   sh_cnt, build_int_cst (NULL_TREE, pow2));
-             return fold_build2 (RSHIFT_EXPR, type,
-                                 fold_convert (type, arg0), sh_cnt);
+             sh_cnt = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (sh_cnt),
+                                       sh_cnt,
+                                       build_int_cst (TREE_TYPE (sh_cnt),
+                                                      pow2));
+             return fold_build2_loc (loc, RSHIFT_EXPR, type,
+                                 fold_convert_loc (loc, type, arg0), sh_cnt);
            }
        }
 
@@ -11694,7 +11552,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
       if (INTEGRAL_TYPE_P (type)
          && TYPE_UNSIGNED (type)
          && code == FLOOR_DIV_EXPR)
-       return fold_build2 (TRUNC_DIV_EXPR, type, op0, op1);
+       return fold_build2_loc (loc, TRUNC_DIV_EXPR, type, op0, op1);
 
       /* Fall thru */
 
@@ -11702,7 +11560,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
     case CEIL_DIV_EXPR:
     case EXACT_DIV_EXPR:
       if (integer_onep (arg1))
-       return non_lvalue (fold_convert (type, arg0));
+       return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
       if (integer_zerop (arg1))
        return NULL_TREE;
       /* X / -1 is -X.  */
@@ -11710,7 +11568,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && TREE_CODE (arg1) == INTEGER_CST
          && TREE_INT_CST_LOW (arg1) == (unsigned HOST_WIDE_INT) -1
          && TREE_INT_CST_HIGH (arg1) == -1)
-       return fold_convert (type, negate_expr (arg0));
+       return fold_convert_loc (loc, type, negate_expr (arg0));
 
       /* Convert -A / -B to A / B when the type is signed and overflow is
         undefined.  */
@@ -11723,9 +11581,11 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                                    "when distributing negation across "
                                    "division"),
                                   WARN_STRICT_OVERFLOW_MISC);
-         return fold_build2 (code, type,
-                             fold_convert (type, TREE_OPERAND (arg0, 0)),
-                             fold_convert (type, negate_expr (arg1)));
+         return fold_build2_loc (loc, code, type,
+                             fold_convert_loc (loc, type,
+                                               TREE_OPERAND (arg0, 0)),
+                             fold_convert_loc (loc, type,
+                                               negate_expr (arg1)));
        }
       if ((!INTEGRAL_TYPE_P (type) || TYPE_OVERFLOW_UNDEFINED (type))
          && TREE_CODE (arg1) == NEGATE_EXPR
@@ -11736,9 +11596,11 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                                    "when distributing negation across "
                                    "division"),
                                   WARN_STRICT_OVERFLOW_MISC);
-         return fold_build2 (code, type,
-                             fold_convert (type, negate_expr (arg0)),
-                             fold_convert (type, TREE_OPERAND (arg1, 0)));
+         return fold_build2_loc (loc, code, type,
+                             fold_convert_loc (loc, type,
+                                               negate_expr (arg0)),
+                             fold_convert_loc (loc, type,
+                                               TREE_OPERAND (arg1, 0)));
        }
 
       /* If arg0 is a multiple of arg1, then rewrite to the fastest div
@@ -11749,7 +11611,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
         after the last round to changes to the DIV code in expmed.c.  */
       if ((code == CEIL_DIV_EXPR || code == FLOOR_DIV_EXPR)
          && multiple_of_p (type, arg0, arg1))
-       return fold_build2 (EXACT_DIV_EXPR, type, arg0, arg1);
+       return fold_build2_loc (loc, EXACT_DIV_EXPR, type, arg0, arg1);
 
       strict_overflow_p = false;
       if (TREE_CODE (arg1) == INTEGER_CST
@@ -11760,7 +11622,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
            fold_overflow_warning (("assuming signed overflow does not occur "
                                    "when simplifying division"),
                                   WARN_STRICT_OVERFLOW_MISC);
-         return fold_convert (type, tem);
+         return fold_convert_loc (loc, type, tem);
        }
 
       return NULL_TREE;
@@ -11772,7 +11634,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
       /* 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);
+       return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
 
       /* X % 0, return X % 0 unchanged so that we can get the
         proper warnings and errors.  */
@@ -11782,42 +11644,14 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
       /* 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);
+       return omit_one_operand_loc (loc, type, integer_zero_node, arg1);
 
       /* X % -1 is zero.  */
       if (!TYPE_UNSIGNED (type)
          && TREE_CODE (arg1) == INTEGER_CST
          && TREE_INT_CST_LOW (arg1) == (unsigned HOST_WIDE_INT) -1
          && TREE_INT_CST_HIGH (arg1) == -1)
-       return omit_one_operand (type, integer_zero_node, arg0);
-
-      /* Optimize TRUNC_MOD_EXPR by a power of two into a BIT_AND_EXPR,
-         i.e. "X % C" into "X & (C - 1)", if X and C are positive.  */
-      strict_overflow_p = false;
-      if ((code == TRUNC_MOD_EXPR || code == FLOOR_MOD_EXPR)
-         && (TYPE_UNSIGNED (type)
-             || tree_expr_nonnegative_warnv_p (op0, &strict_overflow_p)))
-       {
-         tree c = arg1;
-         /* Also optimize A % (C << N)  where C is a power of 2,
-            to A & ((C << N) - 1).  */
-         if (TREE_CODE (arg1) == LSHIFT_EXPR)
-           c = TREE_OPERAND (arg1, 0);
-
-         if (integer_pow2p (c) && tree_int_cst_sgn (c) > 0)
-           {
-             tree mask = fold_build2 (MINUS_EXPR, TREE_TYPE (arg1), arg1,
-                                      build_int_cst (TREE_TYPE (arg1), 1));
-             if (strict_overflow_p)
-               fold_overflow_warning (("assuming signed overflow does not "
-                                       "occur when simplifying "
-                                       "X % (power of two)"),
-                                      WARN_STRICT_OVERFLOW_MISC);
-             return fold_build2 (BIT_AND_EXPR, type,
-                                 fold_convert (type, arg0),
-                                 fold_convert (type, mask));
-           }
-       }
+       return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
 
       /* X % -C is the same as X % C.  */
       if (code == TRUNC_MOD_EXPR
@@ -11828,17 +11662,21 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && !TYPE_OVERFLOW_TRAPS (type)
          /* Avoid this transformation if C is INT_MIN, i.e. C == -C.  */
          && !sign_bit_p (arg1, arg1))
-       return fold_build2 (code, type, fold_convert (type, arg0),
-                           fold_convert (type, negate_expr (arg1)));
+       return fold_build2_loc (loc, code, type,
+                           fold_convert_loc (loc, type, arg0),
+                           fold_convert_loc (loc, type,
+                                             negate_expr (arg1)));
 
       /* X % -Y is the same as X % Y.  */
       if (code == TRUNC_MOD_EXPR
          && !TYPE_UNSIGNED (type)
          && TREE_CODE (arg1) == NEGATE_EXPR
          && !TYPE_OVERFLOW_TRAPS (type))
-       return fold_build2 (code, type, fold_convert (type, arg0),
-                           fold_convert (type, TREE_OPERAND (arg1, 0)));
+       return fold_build2_loc (loc, code, type, fold_convert_loc (loc, type, arg0),
+                           fold_convert_loc (loc, type,
+                                             TREE_OPERAND (arg1, 0)));
 
+      strict_overflow_p = false;
       if (TREE_CODE (arg1) == INTEGER_CST
          && 0 != (tem = extract_muldiv (op0, arg1, code, NULL_TREE,
                                         &strict_overflow_p)))
@@ -11847,7 +11685,35 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
            fold_overflow_warning (("assuming signed overflow does not occur "
                                    "when simplifying modulus"),
                                   WARN_STRICT_OVERFLOW_MISC);
-         return fold_convert (type, tem);
+         return fold_convert_loc (loc, type, tem);
+       }
+
+      /* Optimize TRUNC_MOD_EXPR by a power of two into a BIT_AND_EXPR,
+         i.e. "X % C" into "X & (C - 1)", if X and C are positive.  */
+      if ((code == TRUNC_MOD_EXPR || code == FLOOR_MOD_EXPR)
+         && (TYPE_UNSIGNED (type)
+             || tree_expr_nonnegative_warnv_p (op0, &strict_overflow_p)))
+       {
+         tree c = arg1;
+         /* Also optimize A % (C << N)  where C is a power of 2,
+            to A & ((C << N) - 1).  */
+         if (TREE_CODE (arg1) == LSHIFT_EXPR)
+           c = TREE_OPERAND (arg1, 0);
+
+         if (integer_pow2p (c) && tree_int_cst_sgn (c) > 0)
+           {
+             tree mask
+               = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (arg1), arg1,
+                                  build_int_cst (TREE_TYPE (arg1), 1));
+             if (strict_overflow_p)
+               fold_overflow_warning (("assuming signed overflow does not "
+                                       "occur when simplifying "
+                                       "X % (power of two)"),
+                                      WARN_STRICT_OVERFLOW_MISC);
+             return fold_build2_loc (loc, BIT_AND_EXPR, type,
+                                     fold_convert_loc (loc, type, arg0),
+                                     fold_convert_loc (loc, type, mask));
+           }
        }
 
       return NULL_TREE;
@@ -11855,22 +11721,22 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
     case LROTATE_EXPR:
     case RROTATE_EXPR:
       if (integer_all_onesp (arg0))
-       return omit_one_operand (type, arg0, arg1);
+       return omit_one_operand_loc (loc, type, arg0, arg1);
       goto shift;
 
     case RSHIFT_EXPR:
       /* Optimize -1 >> x for arithmetic right shifts.  */
       if (integer_all_onesp (arg0) && !TYPE_UNSIGNED (type)
          && tree_expr_nonnegative_p (arg1))
-       return omit_one_operand (type, arg0, arg1);
+       return omit_one_operand_loc (loc, type, arg0, arg1);
       /* ... fall through ...  */
 
     case LSHIFT_EXPR:
     shift:
       if (integer_zerop (arg1))
-       return non_lvalue (fold_convert (type, arg0));
+       return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
       if (integer_zerop (arg0))
-       return omit_one_operand (type, arg0, arg1);
+       return omit_one_operand_loc (loc, type, arg0, arg1);
 
       /* Since negative shift count is not well-defined,
         don't try to compute it in the compiler.  */
@@ -11893,13 +11759,13 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
              if (code == LROTATE_EXPR || code == RROTATE_EXPR)
                low = low % TYPE_PRECISION (type);
              else if (TYPE_UNSIGNED (type) || code == LSHIFT_EXPR)
-               return omit_one_operand (type, build_int_cst (type, 0),
+               return omit_one_operand_loc (loc, type, build_int_cst (type, 0),
                                         TREE_OPERAND (arg0, 0));
              else
                low = TYPE_PRECISION (type) - 1;
            }
 
-         return fold_build2 (code, type, TREE_OPERAND (arg0, 0),
+         return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0),
                              build_int_cst (type, low));
        }
 
@@ -11920,12 +11786,12 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
 
          if (low0 == low1)
            {
-             arg00 = fold_convert (type, TREE_OPERAND (arg0, 0));
+             arg00 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
 
              lshift = build_int_cst (type, -1);
-             lshift = int_const_binop (code, lshift, arg1, 0);
+             lshift = int_const_binop (code, lshift, arg1);
 
-             return fold_build2 (BIT_AND_EXPR, type, arg00, lshift);
+             return fold_build2_loc (loc, BIT_AND_EXPR, type, arg00, lshift);
            }
        }
 
@@ -11935,8 +11801,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
        {
          tree tem = build_int_cst (TREE_TYPE (arg1),
                                    TYPE_PRECISION (type));
-         tem = const_binop (MINUS_EXPR, tem, arg1, 0);
-         return fold_build2 (RROTATE_EXPR, type, op0, tem);
+         tem = const_binop (MINUS_EXPR, tem, arg1);
+         return fold_build2_loc (loc, RROTATE_EXPR, type, op0, tem);
        }
 
       /* If we have a rotate of a bit operation with the rotate count and
@@ -11947,10 +11813,10 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
              || TREE_CODE (arg0) == BIT_IOR_EXPR
              || TREE_CODE (arg0) == BIT_XOR_EXPR)
          && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
-       return fold_build2 (TREE_CODE (arg0), type,
-                           fold_build2 (code, type,
+       return fold_build2_loc (loc, TREE_CODE (arg0), type,
+                           fold_build2_loc (loc, code, type,
                                         TREE_OPERAND (arg0, 0), arg1),
-                           fold_build2 (code, type,
+                           fold_build2_loc (loc, code, type,
                                         TREE_OPERAND (arg0, 1), arg1));
 
       /* Two consecutive rotates adding up to the precision of the
@@ -11973,13 +11839,15 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && TREE_CODE (arg1) == INTEGER_CST
          && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
        {
-         tree mask = fold_build2 (code, type,
-                                  fold_convert (type, TREE_OPERAND (arg0, 1)),
+         tree mask = fold_build2_loc (loc, code, type,
+                                  fold_convert_loc (loc, type,
+                                                    TREE_OPERAND (arg0, 1)),
                                   arg1);
-         tree shift = fold_build2 (code, type,
-                                   fold_convert (type, TREE_OPERAND (arg0, 0)),
+         tree shift = fold_build2_loc (loc, code, type,
+                                   fold_convert_loc (loc, type,
+                                                     TREE_OPERAND (arg0, 0)),
                                    arg1);
-         tem = fold_binary (BIT_AND_EXPR, type, shift, mask);
+         tem = fold_binary_loc (loc, BIT_AND_EXPR, type, shift, mask);
          if (tem)
            return tem;
        }
@@ -11988,23 +11856,23 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
 
     case MIN_EXPR:
       if (operand_equal_p (arg0, arg1, 0))
-       return omit_one_operand (type, arg0, arg1);
+       return omit_one_operand_loc (loc, type, arg0, arg1);
       if (INTEGRAL_TYPE_P (type)
          && operand_equal_p (arg1, TYPE_MIN_VALUE (type), OEP_ONLY_CONST))
-       return omit_one_operand (type, arg1, arg0);
-      tem = fold_minmax (MIN_EXPR, type, arg0, arg1);
+       return omit_one_operand_loc (loc, type, arg1, arg0);
+      tem = fold_minmax (loc, MIN_EXPR, type, arg0, arg1);
       if (tem)
        return tem;
       goto associate;
 
     case MAX_EXPR:
       if (operand_equal_p (arg0, arg1, 0))
-       return omit_one_operand (type, arg0, arg1);
+       return omit_one_operand_loc (loc, type, arg0, arg1);
       if (INTEGRAL_TYPE_P (type)
          && TYPE_MAX_VALUE (type)
          && operand_equal_p (arg1, TYPE_MAX_VALUE (type), OEP_ONLY_CONST))
-       return omit_one_operand (type, arg1, arg0);
-      tem = fold_minmax (MAX_EXPR, type, arg0, arg1);
+       return omit_one_operand_loc (loc, type, arg1, arg0);
+      tem = fold_minmax (loc, MAX_EXPR, type, arg0, arg1);
       if (tem)
        return tem;
       goto associate;
@@ -12015,32 +11883,32 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
         ("true" is a fixed value perhaps depending on the language.)  */
       /* If first arg is constant zero, return it.  */
       if (integer_zerop (arg0))
-       return fold_convert (type, arg0);
+       return fold_convert_loc (loc, type, arg0);
     case TRUTH_AND_EXPR:
       /* If either arg is constant true, drop it.  */
       if (TREE_CODE (arg0) == INTEGER_CST && ! integer_zerop (arg0))
-       return non_lvalue (fold_convert (type, arg1));
+       return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1));
       if (TREE_CODE (arg1) == INTEGER_CST && ! integer_zerop (arg1)
          /* Preserve sequence points.  */
          && (code != TRUTH_ANDIF_EXPR || ! TREE_SIDE_EFFECTS (arg0)))
-       return non_lvalue (fold_convert (type, arg0));
+       return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
       /* If second arg is constant zero, result is zero, but first arg
         must be evaluated.  */
       if (integer_zerop (arg1))
-       return omit_one_operand (type, arg1, arg0);
+       return omit_one_operand_loc (loc, type, arg1, arg0);
       /* Likewise for first arg, but note that only the TRUTH_AND_EXPR
         case will be handled here.  */
       if (integer_zerop (arg0))
-       return omit_one_operand (type, arg0, arg1);
+       return omit_one_operand_loc (loc, type, arg0, arg1);
 
       /* !X && X is always false.  */
       if (TREE_CODE (arg0) == TRUTH_NOT_EXPR
          && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
-       return omit_one_operand (type, integer_zero_node, arg1);
+       return omit_one_operand_loc (loc, type, integer_zero_node, arg1);
       /* X && !X is always false.  */
       if (TREE_CODE (arg1) == TRUTH_NOT_EXPR
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
-       return omit_one_operand (type, integer_zero_node, arg0);
+       return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
 
       /* A < X && A + 1 > Y ==> A < X && A >= Y.  Normally A + 1 > Y
         means A >= Y && A != MAX, but in this case we know that
@@ -12049,13 +11917,13 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
       if (!TREE_SIDE_EFFECTS (arg0)
          && !TREE_SIDE_EFFECTS (arg1))
        {
-         tem = fold_to_nonsharp_ineq_using_bound (arg0, arg1);
+         tem = fold_to_nonsharp_ineq_using_bound (loc, arg0, arg1);
          if (tem && !operand_equal_p (tem, arg0, 0))
-           return fold_build2 (code, type, tem, arg1);
+           return fold_build2_loc (loc, code, type, tem, arg1);
 
-         tem = fold_to_nonsharp_ineq_using_bound (arg1, arg0);
+         tem = fold_to_nonsharp_ineq_using_bound (loc, arg1, arg0);
          if (tem && !operand_equal_p (tem, arg1, 0))
-           return fold_build2 (code, type, arg0, tem);
+           return fold_build2_loc (loc, code, type, arg0, tem);
        }
 
     truth_andor:
@@ -12086,38 +11954,54 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                                 || code == TRUTH_OR_EXPR));
 
          if (operand_equal_p (a00, a10, 0))
-           return fold_build2 (TREE_CODE (arg0), type, a00,
-                               fold_build2 (code, type, a01, a11));
+           return fold_build2_loc (loc, TREE_CODE (arg0), type, a00,
+                               fold_build2_loc (loc, code, type, a01, a11));
          else if (commutative && operand_equal_p (a00, a11, 0))
-           return fold_build2 (TREE_CODE (arg0), type, a00,
-                               fold_build2 (code, type, a01, a10));
+           return fold_build2_loc (loc, TREE_CODE (arg0), type, a00,
+                               fold_build2_loc (loc, code, type, a01, a10));
          else if (commutative && operand_equal_p (a01, a10, 0))
-           return fold_build2 (TREE_CODE (arg0), type, a01,
-                               fold_build2 (code, type, a00, a11));
+           return fold_build2_loc (loc, TREE_CODE (arg0), type, a01,
+                               fold_build2_loc (loc, code, type, a00, a11));
 
          /* This case if tricky because we must either have commutative
             operators or else A10 must not have side-effects.  */
 
          else if ((commutative || ! TREE_SIDE_EFFECTS (a10))
                   && operand_equal_p (a01, a11, 0))
-           return fold_build2 (TREE_CODE (arg0), type,
-                               fold_build2 (code, type, a00, a10),
+           return fold_build2_loc (loc, TREE_CODE (arg0), type,
+                               fold_build2_loc (loc, code, type, a00, a10),
                                a01);
        }
 
       /* See if we can build a range comparison.  */
-      if (0 != (tem = fold_range_test (code, type, op0, op1)))
+      if (0 != (tem = fold_range_test (loc, code, type, op0, op1)))
        return tem;
 
+      if ((code == TRUTH_ANDIF_EXPR && TREE_CODE (arg0) == TRUTH_ORIF_EXPR)
+         || (code == TRUTH_ORIF_EXPR && TREE_CODE (arg0) == TRUTH_ANDIF_EXPR))
+       {
+         tem = merge_truthop_with_opposite_arm (loc, arg0, arg1, true);
+         if (tem)
+           return fold_build2_loc (loc, code, type, tem, arg1);
+       }
+
+      if ((code == TRUTH_ANDIF_EXPR && TREE_CODE (arg1) == TRUTH_ORIF_EXPR)
+         || (code == TRUTH_ORIF_EXPR && TREE_CODE (arg1) == TRUTH_ANDIF_EXPR))
+       {
+         tem = merge_truthop_with_opposite_arm (loc, arg1, arg0, false);
+         if (tem)
+           return fold_build2_loc (loc, code, type, arg0, tem);
+       }
+
       /* Check for the possibility of merging component references.  If our
         lhs is another similar operation, try to merge its rhs with our
         rhs.  Then try to merge our lhs and rhs.  */
       if (TREE_CODE (arg0) == code
-         && 0 != (tem = fold_truthop (code, type,
+         && 0 != (tem = fold_truthop (loc, code, type,
                                       TREE_OPERAND (arg0, 1), arg1)))
-       return fold_build2 (code, type, TREE_OPERAND (arg0, 0), tem);
+       return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), tem);
 
-      if ((tem = fold_truthop (code, type, arg0, arg1)) != 0)
+      if ((tem = fold_truthop (loc, code, type, arg0, arg1)) != 0)
        return tem;
 
       return NULL_TREE;
@@ -12128,90 +12012,121 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
         ("true" is a fixed value perhaps depending on the language.)  */
       /* If first arg is constant true, return it.  */
       if (TREE_CODE (arg0) == INTEGER_CST && ! integer_zerop (arg0))
-       return fold_convert (type, arg0);
+       return fold_convert_loc (loc, type, arg0);
     case TRUTH_OR_EXPR:
       /* If either arg is constant zero, drop it.  */
       if (TREE_CODE (arg0) == INTEGER_CST && integer_zerop (arg0))
-       return non_lvalue (fold_convert (type, arg1));
+       return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1));
       if (TREE_CODE (arg1) == INTEGER_CST && integer_zerop (arg1)
          /* Preserve sequence points.  */
          && (code != TRUTH_ORIF_EXPR || ! TREE_SIDE_EFFECTS (arg0)))
-       return non_lvalue (fold_convert (type, arg0));
+       return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
       /* If second arg is constant true, result is true, but we must
         evaluate first arg.  */
       if (TREE_CODE (arg1) == INTEGER_CST && ! integer_zerop (arg1))
-       return omit_one_operand (type, arg1, arg0);
+       return omit_one_operand_loc (loc, type, arg1, arg0);
       /* Likewise for first arg, but note this only occurs here for
         TRUTH_OR_EXPR.  */
       if (TREE_CODE (arg0) == INTEGER_CST && ! integer_zerop (arg0))
-       return omit_one_operand (type, arg0, arg1);
+       return omit_one_operand_loc (loc, type, arg0, arg1);
 
       /* !X || X is always true.  */
       if (TREE_CODE (arg0) == TRUTH_NOT_EXPR
          && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
-       return omit_one_operand (type, integer_one_node, arg1);
+       return omit_one_operand_loc (loc, type, integer_one_node, arg1);
       /* X || !X is always true.  */
       if (TREE_CODE (arg1) == TRUTH_NOT_EXPR
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
-       return omit_one_operand (type, integer_one_node, arg0);
+       return omit_one_operand_loc (loc, type, integer_one_node, arg0);
+
+      /* (X && !Y) || (!X && Y) is X ^ Y */
+      if (TREE_CODE (arg0) == TRUTH_AND_EXPR
+         && TREE_CODE (arg1) == TRUTH_AND_EXPR)
+        {
+         tree a0, a1, l0, l1, n0, n1;
+
+         a0 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 0));
+         a1 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 1));
 
+         l0 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
+         l1 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
+         
+         n0 = fold_build1_loc (loc, TRUTH_NOT_EXPR, type, l0);
+         n1 = fold_build1_loc (loc, TRUTH_NOT_EXPR, type, l1);
+         
+         if ((operand_equal_p (n0, a0, 0)
+              && operand_equal_p (n1, a1, 0))
+             || (operand_equal_p (n0, a1, 0)
+                 && operand_equal_p (n1, a0, 0)))
+           return fold_build2_loc (loc, TRUTH_XOR_EXPR, type, l0, n1);
+       }
       goto truth_andor;
 
     case TRUTH_XOR_EXPR:
       /* If the second arg is constant zero, drop it.  */
       if (integer_zerop (arg1))
-       return non_lvalue (fold_convert (type, arg0));
+       return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
       /* If the second arg is constant true, this is a logical inversion.  */
       if (integer_onep (arg1))
        {
          /* Only call invert_truthvalue if operand is a truth value.  */
          if (TREE_CODE (TREE_TYPE (arg0)) != BOOLEAN_TYPE)
-           tem = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (arg0), arg0);
+           tem = fold_build1_loc (loc, TRUTH_NOT_EXPR, TREE_TYPE (arg0), arg0);
          else
-           tem = invert_truthvalue (arg0);
-         return non_lvalue (fold_convert (type, tem));
+           tem = invert_truthvalue_loc (loc, arg0);
+         return non_lvalue_loc (loc, fold_convert_loc (loc, type, tem));
        }
       /* Identical arguments cancel to zero.  */
       if (operand_equal_p (arg0, arg1, 0))
-       return omit_one_operand (type, integer_zero_node, arg0);
+       return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
 
       /* !X ^ X is always true.  */
       if (TREE_CODE (arg0) == TRUTH_NOT_EXPR
          && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
-       return omit_one_operand (type, integer_one_node, arg1);
+       return omit_one_operand_loc (loc, type, integer_one_node, arg1);
 
       /* X ^ !X is always true.  */
       if (TREE_CODE (arg1) == TRUTH_NOT_EXPR
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
-       return omit_one_operand (type, integer_one_node, arg0);
+       return omit_one_operand_loc (loc, type, integer_one_node, arg0);
 
       return NULL_TREE;
 
     case EQ_EXPR:
     case NE_EXPR:
-      tem = fold_comparison (code, type, op0, op1);
+      STRIP_NOPS (arg0);
+      STRIP_NOPS (arg1);
+
+      tem = fold_comparison (loc, code, type, op0, op1);
       if (tem != NULL_TREE)
        return tem;
 
       /* bool_var != 0 becomes bool_var. */
       if (TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE && integer_zerop (arg1)
           && code == NE_EXPR)
-        return non_lvalue (fold_convert (type, arg0));
+        return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
 
       /* bool_var == 1 becomes bool_var. */
       if (TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE && integer_onep (arg1)
           && code == EQ_EXPR)
-        return non_lvalue (fold_convert (type, arg0));
+        return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
 
       /* bool_var != 1 becomes !bool_var. */
       if (TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE && integer_onep (arg1)
           && code == NE_EXPR)
-        return fold_build1 (TRUTH_NOT_EXPR, type, fold_convert (type, arg0));
+        return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
+                           fold_convert_loc (loc, type, arg0));
 
       /* bool_var == 0 becomes !bool_var. */
       if (TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE && integer_zerop (arg1)
           && code == EQ_EXPR)
-        return fold_build1 (TRUTH_NOT_EXPR, type, fold_convert (type, arg0));
+        return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
+                           fold_convert_loc (loc, type, arg0));
+
+      /* !exp != 0 becomes !exp */
+      if (TREE_CODE (arg0) == TRUTH_NOT_EXPR && integer_zerop (arg1)
+         && code == NE_EXPR)
+        return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
 
       /* If this is an equality comparison of the address of two non-weak,
         unaliased symbols neither of which are extern (since we do not
@@ -12255,39 +12170,45 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
          && 0 != (tem = const_binop (TREE_CODE (arg0) == PLUS_EXPR
                                      ? MINUS_EXPR : PLUS_EXPR,
-                                     fold_convert (TREE_TYPE (arg0), arg1),
-                                     TREE_OPERAND (arg0, 1), 0))
+                                     fold_convert_loc (loc, TREE_TYPE (arg0),
+                                                       arg1),
+                                     TREE_OPERAND (arg0, 1)))
          && !TREE_OVERFLOW (tem))
-       return fold_build2 (code, type, TREE_OPERAND (arg0, 0), tem);
+       return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), tem);
 
       /* Similarly for a NEGATE_EXPR.  */
       if (TREE_CODE (arg0) == NEGATE_EXPR
          && TREE_CODE (arg1) == INTEGER_CST
-         && 0 != (tem = negate_expr (arg1))
+         && 0 != (tem = negate_expr (fold_convert_loc (loc, TREE_TYPE (arg0),
+                                                       arg1)))
          && TREE_CODE (tem) == INTEGER_CST
          && !TREE_OVERFLOW (tem))
-       return fold_build2 (code, type, TREE_OPERAND (arg0, 0), tem);
+       return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), tem);
 
       /* Similarly for a BIT_XOR_EXPR;  X ^ C1 == C2 is X == (C1 ^ C2).  */
       if (TREE_CODE (arg0) == BIT_XOR_EXPR
          && TREE_CODE (arg1) == INTEGER_CST
          && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
-       return fold_build2 (code, type, TREE_OPERAND (arg0, 0),
-                           fold_build2 (BIT_XOR_EXPR, TREE_TYPE (arg0),
-                                        fold_convert (TREE_TYPE (arg0), arg1),
+       return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0),
+                           fold_build2_loc (loc, BIT_XOR_EXPR, TREE_TYPE (arg0),
+                                        fold_convert_loc (loc,
+                                                          TREE_TYPE (arg0),
+                                                          arg1),
                                         TREE_OPERAND (arg0, 1)));
 
       /* Transform comparisons of the form X +- Y CMP X to Y CMP 0.  */
       if ((TREE_CODE (arg0) == PLUS_EXPR
           || TREE_CODE (arg0) == POINTER_PLUS_EXPR
           || TREE_CODE (arg0) == MINUS_EXPR)
-         && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
+         && operand_equal_p (tree_strip_nop_conversions (TREE_OPERAND (arg0,
+                                                                       0)),
+                             arg1, 0)
          && (INTEGRAL_TYPE_P (TREE_TYPE (arg0))
              || POINTER_TYPE_P (TREE_TYPE (arg0))))
        {
          tree val = TREE_OPERAND (arg0, 1);
-         return omit_two_operands (type,
-                                   fold_build2 (code, type,
+         return omit_two_operands_loc (loc, type,
+                                   fold_build2_loc (loc, code, type,
                                                 val,
                                                 build_int_cst (TREE_TYPE (val),
                                                                0)),
@@ -12297,10 +12218,12 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
       /* Transform comparisons of the form C - X CMP X if C % 2 == 1.  */
       if (TREE_CODE (arg0) == MINUS_EXPR
          && TREE_CODE (TREE_OPERAND (arg0, 0)) == INTEGER_CST
-         && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0)
+         && operand_equal_p (tree_strip_nop_conversions (TREE_OPERAND (arg0,
+                                                                       1)),
+                             arg1, 0)
          && (TREE_INT_CST_LOW (TREE_OPERAND (arg0, 0)) & 1) == 1)
        {
-         return omit_two_operands (type,
+         return omit_two_operands_loc (loc, type,
                                    code == NE_EXPR
                                    ? boolean_true_node : boolean_false_node,
                                    TREE_OPERAND (arg0, 1), arg1);
@@ -12310,13 +12233,13 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
         for !=.  Don't do this for ordered comparisons due to overflow.  */
       if (TREE_CODE (arg0) == MINUS_EXPR
          && integer_zerop (arg1))
-       return fold_build2 (code, type,
+       return fold_build2_loc (loc, code, type,
                            TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1));
 
       /* Convert ABS_EXPR<x> == 0 or ABS_EXPR<x> != 0 to x == 0 or x != 0.  */
       if (TREE_CODE (arg0) == ABS_EXPR
          && (integer_zerop (arg1) || real_zerop (arg1)))
-       return fold_build2 (code, type, TREE_OPERAND (arg0, 0), arg1);
+       return fold_build2_loc (loc, 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
@@ -12331,22 +12254,24 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          if (TREE_CODE (arg00) == LSHIFT_EXPR
              && integer_onep (TREE_OPERAND (arg00, 0)))
            {
-             tree tem = fold_build2 (RSHIFT_EXPR, TREE_TYPE (arg00),
+             tree tem = fold_build2_loc (loc, RSHIFT_EXPR, TREE_TYPE (arg00),
                                      arg01, TREE_OPERAND (arg00, 1));
-             tem = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg0), tem,
+             tem = fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (arg0), tem,
                                 build_int_cst (TREE_TYPE (arg0), 1));
-             return fold_build2 (code, type,
-                                 fold_convert (TREE_TYPE (arg1), tem), arg1);
+             return fold_build2_loc (loc, code, type,
+                                 fold_convert_loc (loc, TREE_TYPE (arg1), tem),
+                                 arg1);
            }
          else if (TREE_CODE (arg01) == LSHIFT_EXPR
                   && integer_onep (TREE_OPERAND (arg01, 0)))
            {
-             tree tem = fold_build2 (RSHIFT_EXPR, TREE_TYPE (arg01),
+             tree tem = fold_build2_loc (loc, RSHIFT_EXPR, TREE_TYPE (arg01),
                                      arg00, TREE_OPERAND (arg01, 1));
-             tem = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg0), tem,
+             tem = fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (arg0), tem,
                                 build_int_cst (TREE_TYPE (arg0), 1));
-             return fold_build2 (code, type,
-                                 fold_convert (TREE_TYPE (arg1), tem), arg1);
+             return fold_build2_loc (loc, code, type,
+                                 fold_convert_loc (loc, TREE_TYPE (arg1), tem),
+                                 arg1);
            }
        }
 
@@ -12362,14 +12287,14 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && integer_pow2p (TREE_OPERAND (arg0, 1)))
        {
          tree newtype = unsigned_type_for (TREE_TYPE (arg0));
-         tree newmod = fold_build2 (TREE_CODE (arg0), newtype,
-                                    fold_convert (newtype,
-                                                  TREE_OPERAND (arg0, 0)),
-                                    fold_convert (newtype,
-                                                  TREE_OPERAND (arg0, 1)));
+         tree newmod = fold_build2_loc (loc, TREE_CODE (arg0), newtype,
+                                    fold_convert_loc (loc, newtype,
+                                                      TREE_OPERAND (arg0, 0)),
+                                    fold_convert_loc (loc, newtype,
+                                                      TREE_OPERAND (arg0, 1)));
 
-         return fold_build2 (code, type, newmod,
-                             fold_convert (newtype, arg1));
+         return fold_build2_loc (loc, code, type, newmod,
+                             fold_convert_loc (loc, newtype, arg1));
        }
 
       /* Fold ((X >> C1) & C2) == 0 and ((X >> C1) & C2) != 0 where
@@ -12397,21 +12322,22 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                 can be rewritten as (X & (C2 << C1)) != 0.  */
              if ((log2 + TREE_INT_CST_LOW (arg001)) < prec)
                {
-                 tem = fold_build2 (LSHIFT_EXPR, itype, arg01, arg001);
-                 tem = fold_build2 (BIT_AND_EXPR, itype, arg000, tem);
-                 return fold_build2 (code, type, tem, arg1);
+                 tem = fold_build2_loc (loc, LSHIFT_EXPR, itype, arg01, arg001);
+                 tem = fold_build2_loc (loc, BIT_AND_EXPR, itype, arg000, tem);
+                 return fold_build2_loc (loc, code, type, tem,
+                                         fold_convert_loc (loc, itype, arg1));
                }
              /* Otherwise, for signed (arithmetic) shifts,
                 ((X >> C1) & C2) != 0 is rewritten as X < 0, and
                 ((X >> C1) & C2) == 0 is rewritten as X >= 0.  */
              else if (!TYPE_UNSIGNED (itype))
-               return fold_build2 (code == EQ_EXPR ? GE_EXPR : LT_EXPR, type,
+               return fold_build2_loc (loc, code == EQ_EXPR ? GE_EXPR : LT_EXPR, type,
                                    arg000, build_int_cst (itype, 0));
              /* Otherwise, of unsigned (logical) shifts,
                 ((X >> C1) & C2) != 0 is rewritten as (X,false), and
                 ((X >> C1) & C2) == 0 is rewritten as (X,true).  */
              else
-               return omit_one_operand (type,
+               return omit_one_operand_loc (loc, type,
                                         code == EQ_EXPR ? integer_one_node
                                                         : integer_zero_node,
                                         arg000);
@@ -12424,20 +12350,20 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && integer_zerop (arg1)
          && TREE_CODE (arg0) == BIT_AND_EXPR
          && integer_onep (TREE_OPERAND (arg0, 1)))
-       return fold_convert (type, arg0);
+       return fold_convert_loc (loc, type, arg0);
 
       /* If we have (A & C) == C where C is a power of 2, convert this into
         (A & C) != 0.  Similarly for NE_EXPR.  */
       if (TREE_CODE (arg0) == BIT_AND_EXPR
          && integer_pow2p (TREE_OPERAND (arg0, 1))
          && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
-       return fold_build2 (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
-                           arg0, fold_convert (TREE_TYPE (arg0),
-                                               integer_zero_node));
+       return fold_build2_loc (loc, code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
+                           arg0, fold_convert_loc (loc, TREE_TYPE (arg0),
+                                                   integer_zero_node));
 
       /* If we have (A & C) != 0 or (A & C) == 0 and C is the sign
         bit, then fold the expression into A < 0 or A >= 0.  */
-      tem = fold_single_bit_test_into_sign_test (code, arg0, arg1, type);
+      tem = fold_single_bit_test_into_sign_test (loc, code, arg0, arg1, type);
       if (tem)
        return tem;
 
@@ -12447,14 +12373,16 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && TREE_CODE (arg1) == INTEGER_CST
          && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
        {
-         tree notc = fold_build1 (BIT_NOT_EXPR,
+         tree notc = fold_build1_loc (loc, BIT_NOT_EXPR,
                                   TREE_TYPE (TREE_OPERAND (arg0, 1)),
                                   TREE_OPERAND (arg0, 1));
-         tree dandnotc = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
-                                      arg1, notc);
+         tree dandnotc
+           = fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (arg0),
+                              fold_convert_loc (loc, TREE_TYPE (arg0), arg1),
+                              notc);
          tree rslt = code == EQ_EXPR ? integer_zero_node : integer_one_node;
          if (integer_nonzerop (dandnotc))
-           return omit_one_operand (type, rslt, arg0);
+           return omit_one_operand_loc (loc, type, rslt, arg0);
        }
 
       /* If we have (A | C) == D where C & ~D != 0, convert this into 0.
@@ -12463,12 +12391,14 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && TREE_CODE (arg1) == INTEGER_CST
          && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
        {
-         tree notd = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (arg1), arg1);
-         tree candnotd = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
-                                      TREE_OPERAND (arg0, 1), notd);
+         tree notd = fold_build1_loc (loc, BIT_NOT_EXPR, TREE_TYPE (arg1), arg1);
+         tree candnotd
+           = fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (arg0),
+                              TREE_OPERAND (arg0, 1),
+                              fold_convert_loc (loc, TREE_TYPE (arg0), notd));
          tree rslt = code == EQ_EXPR ? integer_zero_node : integer_one_node;
          if (integer_nonzerop (candnotd))
-           return omit_one_operand (type, rslt, arg0);
+           return omit_one_operand_loc (loc, type, rslt, arg0);
        }
 
       /* If this is a comparison of a field, we may be able to simplify it.  */
@@ -12478,7 +12408,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
             to make sure the warnings are given.  */
          && (optimize || TREE_CODE (arg1) == INTEGER_CST))
        {
-         t1 = optimize_bit_field_compare (code, type, arg0, arg1);
+         t1 = optimize_bit_field_compare (loc, code, type, arg0, arg1);
          if (t1)
            return t1;
        }
@@ -12500,8 +12430,9 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
              && call_expr_nargs (arg0) == 1
              && TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (arg0, 0))) == POINTER_TYPE)
            {
-             tree iref = build_fold_indirect_ref (CALL_EXPR_ARG (arg0, 0));
-             return fold_build2 (code, type, iref,
+             tree iref = build_fold_indirect_ref_loc (loc,
+                                                  CALL_EXPR_ARG (arg0, 0));
+             return fold_build2_loc (loc, code, type, iref,
                                  build_int_cst (TREE_TYPE (iref), 0));
            }
        }
@@ -12522,9 +12453,9 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
              if (TYPE_UNSIGNED (itype))
                {
                  itype = signed_type_for (itype);
-                 arg00 = fold_convert (itype, arg00);
+                 arg00 = fold_convert_loc (loc, itype, arg00);
                }
-             return fold_build2 (code == EQ_EXPR ? GE_EXPR : LT_EXPR,
+             return fold_build2_loc (loc, code == EQ_EXPR ? GE_EXPR : LT_EXPR,
                                  type, arg00, build_int_cst (itype, 0));
            }
        }
@@ -12532,27 +12463,27 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
       /* (X ^ Y) == 0 becomes X == Y, and (X ^ Y) != 0 becomes X != Y.  */
       if (integer_zerop (arg1)
          && TREE_CODE (arg0) == BIT_XOR_EXPR)
-       return fold_build2 (code, type, TREE_OPERAND (arg0, 0),
+       return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0),
                            TREE_OPERAND (arg0, 1));
 
       /* (X ^ Y) == Y becomes X == 0.  We know that Y has no side-effects.  */
       if (TREE_CODE (arg0) == BIT_XOR_EXPR
          && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
-       return fold_build2 (code, type, TREE_OPERAND (arg0, 0),
-                           build_int_cst (TREE_TYPE (arg1), 0));
+       return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0),
+                               build_int_cst (TREE_TYPE (arg0), 0));
       /* Likewise (X ^ Y) == X becomes Y == 0.  X has no side-effects.  */
       if (TREE_CODE (arg0) == BIT_XOR_EXPR
          && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
          && reorder_operands_p (TREE_OPERAND (arg0, 1), arg1))
-       return fold_build2 (code, type, TREE_OPERAND (arg0, 1),
-                           build_int_cst (TREE_TYPE (arg1), 0));
+       return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 1),
+                               build_int_cst (TREE_TYPE (arg0), 0));
 
       /* (X ^ C1) op C2 can be rewritten as X op (C1 ^ C2).  */
       if (TREE_CODE (arg0) == BIT_XOR_EXPR
          && TREE_CODE (arg1) == INTEGER_CST
          && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
-       return fold_build2 (code, type, TREE_OPERAND (arg0, 0),
-                           fold_build2 (BIT_XOR_EXPR, TREE_TYPE (arg1),
+       return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0),
+                           fold_build2_loc (loc, BIT_XOR_EXPR, TREE_TYPE (arg1),
                                         TREE_OPERAND (arg0, 1), arg1));
 
       /* Fold (~X & C) == 0 into (X & C) != 0 and (~X & C) != 0 into
@@ -12562,11 +12493,13 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && integer_zerop (arg1)
          && integer_pow2p (TREE_OPERAND (arg0, 1)))
        {
-         tem = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
-                            TREE_OPERAND (TREE_OPERAND (arg0, 0), 0),
-                            TREE_OPERAND (arg0, 1));
-         return fold_build2 (code == EQ_EXPR ? NE_EXPR : EQ_EXPR,
-                             type, tem, arg1);
+         tem = fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (arg0),
+                                TREE_OPERAND (TREE_OPERAND (arg0, 0), 0),
+                                TREE_OPERAND (arg0, 1));
+         return fold_build2_loc (loc, code == EQ_EXPR ? NE_EXPR : EQ_EXPR,
+                                 type, tem,
+                                 fold_convert_loc (loc, TREE_TYPE (arg0),
+                                                   arg1));
        }
 
       /* Fold ((X & C) ^ C) eq/ne 0 into (X & C) ne/eq 0, when the
@@ -12579,7 +12512,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                              TREE_OPERAND (arg0, 1), OEP_ONLY_CONST))
        {
          tree arg00 = TREE_OPERAND (arg0, 0);
-         return fold_build2 (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
+         return fold_build2_loc (loc, code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
                              arg00, build_int_cst (TREE_TYPE (arg00), 0));
        }
 
@@ -12593,9 +12526,9 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                              TREE_OPERAND (arg0, 1), OEP_ONLY_CONST))
        {
          tree arg000 = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
-         tem = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg000),
+         tem = fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (arg000),
                             arg000, TREE_OPERAND (arg0, 1));
-         return fold_build2 (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
+         return fold_build2_loc (loc, code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
                              tem, build_int_cst (TREE_TYPE (tem), 0));
        }
 
@@ -12603,15 +12536,16 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && tree_expr_nonzero_p (arg0))
         {
          tree res = constant_boolean_node (code==NE_EXPR, type);
-         return omit_one_operand (type, res, arg0);
+         return omit_one_operand_loc (loc, type, res, arg0);
        }
 
       /* Fold -X op -Y as X op Y, where op is eq/ne.  */
       if (TREE_CODE (arg0) == NEGATE_EXPR
           && TREE_CODE (arg1) == NEGATE_EXPR)
-       return fold_build2 (code, type,
-                           TREE_OPERAND (arg0, 0),
-                           TREE_OPERAND (arg1, 0));
+       return fold_build2_loc (loc, code, type,
+                               TREE_OPERAND (arg0, 0),
+                               fold_convert_loc (loc, TREE_TYPE (arg0),
+                                                 TREE_OPERAND (arg1, 0)));
 
       /* Fold (X & C) op (Y & C) as (X ^ Y) & C op 0", and symmetries.  */
       if (TREE_CODE (arg0) == BIT_AND_EXPR
@@ -12624,33 +12558,37 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          tree itype = TREE_TYPE (arg0);
 
          if (operand_equal_p (arg01, arg11, 0))
-           return fold_build2 (code, type,
-                               fold_build2 (BIT_AND_EXPR, itype,
-                                            fold_build2 (BIT_XOR_EXPR, itype,
+           return fold_build2_loc (loc, code, type,
+                               fold_build2_loc (loc, BIT_AND_EXPR, itype,
+                                            fold_build2_loc (loc,
+                                                         BIT_XOR_EXPR, itype,
                                                          arg00, arg10),
                                             arg01),
                                build_int_cst (itype, 0));
 
          if (operand_equal_p (arg01, arg10, 0))
-           return fold_build2 (code, type,
-                               fold_build2 (BIT_AND_EXPR, itype,
-                                            fold_build2 (BIT_XOR_EXPR, itype,
+           return fold_build2_loc (loc, code, type,
+                               fold_build2_loc (loc, BIT_AND_EXPR, itype,
+                                            fold_build2_loc (loc,
+                                                         BIT_XOR_EXPR, itype,
                                                          arg00, arg11),
                                             arg01),
                                build_int_cst (itype, 0));
 
          if (operand_equal_p (arg00, arg11, 0))
-           return fold_build2 (code, type,
-                               fold_build2 (BIT_AND_EXPR, itype,
-                                            fold_build2 (BIT_XOR_EXPR, itype,
+           return fold_build2_loc (loc, code, type,
+                               fold_build2_loc (loc, BIT_AND_EXPR, itype,
+                                            fold_build2_loc (loc,
+                                                         BIT_XOR_EXPR, itype,
                                                          arg01, arg10),
                                             arg00),
                                build_int_cst (itype, 0));
 
          if (operand_equal_p (arg00, arg10, 0))
-           return fold_build2 (code, type,
-                               fold_build2 (BIT_AND_EXPR, itype,
-                                            fold_build2 (BIT_XOR_EXPR, itype,
+           return fold_build2_loc (loc, code, type,
+                               fold_build2_loc (loc, BIT_AND_EXPR, itype,
+                                            fold_build2_loc (loc,
+                                                         BIT_XOR_EXPR, itype,
                                                          arg01, arg11),
                                             arg00),
                                build_int_cst (itype, 0));
@@ -12669,22 +12607,32 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
             operand_equal_p guarantees no side-effects so we don't need
             to use omit_one_operand on Z.  */
          if (operand_equal_p (arg01, arg11, 0))
-           return fold_build2 (code, type, arg00, arg10);
+           return fold_build2_loc (loc, code, type, arg00,
+                                   fold_convert_loc (loc, TREE_TYPE (arg00),
+                                                     arg10));
          if (operand_equal_p (arg01, arg10, 0))
-           return fold_build2 (code, type, arg00, arg11);
+           return fold_build2_loc (loc, code, type, arg00,
+                                   fold_convert_loc (loc, TREE_TYPE (arg00),
+                                                     arg11));
          if (operand_equal_p (arg00, arg11, 0))
-           return fold_build2 (code, type, arg01, arg10);
+           return fold_build2_loc (loc, code, type, arg01,
+                                   fold_convert_loc (loc, TREE_TYPE (arg01),
+                                                     arg10));
          if (operand_equal_p (arg00, arg10, 0))
-           return fold_build2 (code, type, arg01, arg11);
+           return fold_build2_loc (loc, code, type, arg01,
+                                   fold_convert_loc (loc, TREE_TYPE (arg01),
+                                                     arg11));
 
          /* Optimize (X ^ C1) op (Y ^ C2) as (X ^ (C1 ^ C2)) op Y.  */
          if (TREE_CODE (arg01) == INTEGER_CST
              && TREE_CODE (arg11) == INTEGER_CST)
-           return fold_build2 (code, type,
-                               fold_build2 (BIT_XOR_EXPR, itype, arg00,
-                                            fold_build2 (BIT_XOR_EXPR, itype,
-                                                         arg01, arg11)),
-                               arg10);
+           {
+             tem = fold_build2_loc (loc, BIT_XOR_EXPR, itype, arg01,
+                                    fold_convert_loc (loc, itype, arg11));
+             tem = fold_build2_loc (loc, BIT_XOR_EXPR, itype, arg00, tem);
+             return fold_build2_loc (loc, code, type, tem,
+                                     fold_convert_loc (loc, itype, arg10));
+           }
        }
 
       /* Attempt to simplify equality/inequality comparisons of complex
@@ -12720,41 +12668,41 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
              imag1 = TREE_IMAGPART (arg1);
            }
 
-         rcond = fold_binary (code, type, real0, real1);
+         rcond = fold_binary_loc (loc, code, type, real0, real1);
          if (rcond && TREE_CODE (rcond) == INTEGER_CST)
            {
              if (integer_zerop (rcond))
                {
                  if (code == EQ_EXPR)
-                   return omit_two_operands (type, boolean_false_node,
+                   return omit_two_operands_loc (loc, type, boolean_false_node,
                                              imag0, imag1);
-                 return fold_build2 (NE_EXPR, type, imag0, imag1);
+                 return fold_build2_loc (loc, NE_EXPR, type, imag0, imag1);
                }
              else
                {
                  if (code == NE_EXPR)
-                   return omit_two_operands (type, boolean_true_node,
+                   return omit_two_operands_loc (loc, type, boolean_true_node,
                                              imag0, imag1);
-                 return fold_build2 (EQ_EXPR, type, imag0, imag1);
+                 return fold_build2_loc (loc, EQ_EXPR, type, imag0, imag1);
                }
            }
 
-         icond = fold_binary (code, type, imag0, imag1);
+         icond = fold_binary_loc (loc, code, type, imag0, imag1);
          if (icond && TREE_CODE (icond) == INTEGER_CST)
            {
              if (integer_zerop (icond))
                {
                  if (code == EQ_EXPR)
-                   return omit_two_operands (type, boolean_false_node,
+                   return omit_two_operands_loc (loc, type, boolean_false_node,
                                              real0, real1);
-                 return fold_build2 (NE_EXPR, type, real0, real1);
+                 return fold_build2_loc (loc, NE_EXPR, type, real0, real1);
                }
              else
                {
                  if (code == NE_EXPR)
-                   return omit_two_operands (type, boolean_true_node,
+                   return omit_two_operands_loc (loc, type, boolean_true_node,
                                              real0, real1);
-                 return fold_build2 (EQ_EXPR, type, real0, real1);
+                 return fold_build2_loc (loc, EQ_EXPR, type, real0, real1);
                }
            }
        }
@@ -12765,7 +12713,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
     case GT_EXPR:
     case LE_EXPR:
     case GE_EXPR:
-      tem = fold_comparison (code, type, op0, op1);
+      tem = fold_comparison (loc, code, type, op0, op1);
       if (tem != NULL_TREE)
        return tem;
 
@@ -12958,16 +12906,16 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
              switch (code)
                {
                case GT_EXPR:
-                 return omit_one_operand (type, integer_zero_node, arg0);
+                 return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
 
                case GE_EXPR:
-                 return fold_build2 (EQ_EXPR, type, op0, op1);
+                 return fold_build2_loc (loc, EQ_EXPR, type, op0, op1);
 
                case LE_EXPR:
-                 return omit_one_operand (type, integer_one_node, arg0);
+                 return omit_one_operand_loc (loc, type, integer_one_node, arg0);
 
                case LT_EXPR:
-                 return fold_build2 (NE_EXPR, type, op0, op1);
+                 return fold_build2_loc (loc, NE_EXPR, type, op0, op1);
 
                /* The GE_EXPR and LT_EXPR cases above are not normally
                   reached because of previous transformations.  */
@@ -12982,15 +12930,17 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                {
                case GT_EXPR:
                  arg1 = const_binop (PLUS_EXPR, arg1,
-                                     build_int_cst (TREE_TYPE (arg1), 1), 0);
-                 return fold_build2 (EQ_EXPR, type,
-                                     fold_convert (TREE_TYPE (arg1), arg0),
+                                     build_int_cst (TREE_TYPE (arg1), 1));
+                 return fold_build2_loc (loc, EQ_EXPR, type,
+                                     fold_convert_loc (loc,
+                                                       TREE_TYPE (arg1), arg0),
                                      arg1);
                case LE_EXPR:
                  arg1 = const_binop (PLUS_EXPR, arg1,
-                                     build_int_cst (TREE_TYPE (arg1), 1), 0);
-                 return fold_build2 (NE_EXPR, type,
-                                     fold_convert (TREE_TYPE (arg1), arg0),
+                                     build_int_cst (TREE_TYPE (arg1), 1));
+                 return fold_build2_loc (loc, NE_EXPR, type,
+                                     fold_convert_loc (loc, TREE_TYPE (arg1),
+                                                       arg0),
                                      arg1);
                default:
                  break;
@@ -13001,16 +12951,16 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
              switch (code)
                {
                case LT_EXPR:
-                 return omit_one_operand (type, integer_zero_node, arg0);
+                 return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
 
                case LE_EXPR:
-                 return fold_build2 (EQ_EXPR, type, op0, op1);
+                 return fold_build2_loc (loc, EQ_EXPR, type, op0, op1);
 
                case GE_EXPR:
-                 return omit_one_operand (type, integer_one_node, arg0);
+                 return omit_one_operand_loc (loc, type, integer_one_node, arg0);
 
                case GT_EXPR:
-                 return fold_build2 (NE_EXPR, type, op0, op1);
+                 return fold_build2_loc (loc, NE_EXPR, type, op0, op1);
 
                default:
                  break;
@@ -13021,14 +12971,16 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
              switch (code)
                {
                case GE_EXPR:
-                 arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
-                 return fold_build2 (NE_EXPR, type,
-                                     fold_convert (TREE_TYPE (arg1), arg0),
+                 arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node);
+                 return fold_build2_loc (loc, NE_EXPR, type,
+                                     fold_convert_loc (loc,
+                                                       TREE_TYPE (arg1), arg0),
                                      arg1);
                case LT_EXPR:
-                 arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
-                 return fold_build2 (EQ_EXPR, type,
-                                     fold_convert (TREE_TYPE (arg1), arg0),
+                 arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node);
+                 return fold_build2_loc (loc, EQ_EXPR, type,
+                                     fold_convert_loc (loc, TREE_TYPE (arg1),
+                                                       arg0),
                                      arg1);
                default:
                  break;
@@ -13051,8 +13003,9 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                  {
                    tree st;
                    st = signed_type_for (TREE_TYPE (arg1));
-                   return fold_build2 (code == LE_EXPR ? GE_EXPR : LT_EXPR,
-                                       type, fold_convert (st, arg0),
+                   return fold_build2_loc (loc,
+                                       code == LE_EXPR ? GE_EXPR : LT_EXPR,
+                                       type, fold_convert_loc (loc, st, arg0),
                                        build_int_cst (st, 0));
                  }
              }
@@ -13071,7 +13024,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && (0 != (tem = negate_expr (arg1)))
          && TREE_CODE (tem) == INTEGER_CST
          && !TREE_OVERFLOW (tem))
-       return fold_build2 (TRUTH_ANDIF_EXPR, type,
+       return fold_build2_loc (loc, TRUTH_ANDIF_EXPR, type,
                            build2 (GE_EXPR, type,
                                    TREE_OPERAND (arg0, 0), tem),
                            build2 (LE_EXPR, type,
@@ -13090,7 +13043,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                                    "when simplifying comparison of "
                                    "absolute value and zero"),
                                   WARN_STRICT_OVERFLOW_CONDITIONAL);
-         return omit_one_operand (type, integer_one_node, arg0);
+         return omit_one_operand_loc (loc, type, integer_one_node, arg0);
        }
 
       /* Convert ABS_EXPR<x> < 0 to false.  */
@@ -13104,7 +13057,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                                    "when simplifying comparison of "
                                    "absolute value and zero"),
                                   WARN_STRICT_OVERFLOW_CONDITIONAL);
-         return omit_one_operand (type, integer_zero_node, arg0);
+         return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
        }
 
       /* If X is unsigned, convert X < (1 << Y) into X >> Y == 0
@@ -13113,23 +13066,23 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && TYPE_UNSIGNED (TREE_TYPE (arg0))
          && TREE_CODE (arg1) == LSHIFT_EXPR
          && integer_onep (TREE_OPERAND (arg1, 0)))
-       return 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));
+       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))
          && CONVERT_EXPR_P (arg1)
          && TREE_CODE (TREE_OPERAND (arg1, 0)) == LSHIFT_EXPR
          && integer_onep (TREE_OPERAND (TREE_OPERAND (arg1, 0), 0)))
-       return
-         build2 (code == LT_EXPR ? EQ_EXPR : NE_EXPR, type,
-                 fold_convert (TREE_TYPE (arg0),
-                               build2 (RSHIFT_EXPR, TREE_TYPE (arg0), arg0,
-                                       TREE_OPERAND (TREE_OPERAND (arg1, 0),
-                                                     1))),
-                 build_int_cst (TREE_TYPE (arg0), 0));
+       {
+         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;
 
@@ -13156,7 +13109,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          t1 = (code == ORDERED_EXPR || code == LTGT_EXPR)
               ? integer_zero_node
               : integer_one_node;
-         return omit_one_operand (type, t1, arg1);
+         return omit_one_operand_loc (loc, type, t1, arg1);
        }
 
       /* If the second operand is NaN, the result is constant.  */
@@ -13167,7 +13120,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          t1 = (code == ORDERED_EXPR || code == LTGT_EXPR)
               ? integer_zero_node
               : integer_one_node;
-         return omit_one_operand (type, t1, arg0);
+         return omit_one_operand_loc (loc, type, t1, arg0);
        }
 
       /* Simplify unordered comparison of something with itself.  */
@@ -13190,8 +13143,9 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          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 fold_build2_loc (loc, code, type,
+                             fold_convert_loc (loc, newtype, targ0),
+                             fold_convert_loc (loc, newtype, targ1));
       }
 
       return NULL_TREE;
@@ -13203,8 +13157,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
        return NULL_TREE;
       /* Don't let (0, 0) be null pointer constant.  */
       tem = integer_zerop (arg1) ? build1 (NOP_EXPR, type, arg1)
-                                : fold_convert (type, arg1);
-      return pedantic_non_lvalue (tem);
+                                : fold_convert_loc (loc, type, arg1);
+      return pedantic_non_lvalue_loc (loc, tem);
 
     case COMPLEX_EXPR:
       if ((TREE_CODE (arg0) == REAL_CST
@@ -13212,6 +13166,14 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          || (TREE_CODE (arg0) == INTEGER_CST
              && TREE_CODE (arg1) == INTEGER_CST))
        return build_complex (type, arg0, arg1);
+      if (TREE_CODE (arg0) == REALPART_EXPR
+         && TREE_CODE (arg1) == IMAGPART_EXPR
+         && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg0, 0)))
+             == TYPE_MAIN_VARIANT (type))
+         && operand_equal_p (TREE_OPERAND (arg0, 0),
+                             TREE_OPERAND (arg1, 0), 0))
+       return omit_one_operand_loc (loc, type, TREE_OPERAND (arg0, 0),
+                                    TREE_OPERAND (arg1, 0));
       return NULL_TREE;
 
     case ASSERT_EXPR:
@@ -13223,35 +13185,36 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
     } /* switch (code) */
 }
 
-/* Callback for walk_tree, looking for LABEL_EXPR.
-   Returns tree TP if it is LABEL_EXPR. Otherwise it returns NULL_TREE.
-   Do not check the sub-tree of GOTO_EXPR.  */
+/* Callback for walk_tree, looking for LABEL_EXPR.  Return *TP if it is
+   a LABEL_EXPR; otherwise return NULL_TREE.  Do not check the subtrees
+   of GOTO_EXPR.  */
 
 static tree
-contains_label_1 (tree *tp,
-                  int *walk_subtrees,
-                  void *data ATTRIBUTE_UNUSED)
+contains_label_1 (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
 {
   switch (TREE_CODE (*tp))
     {
     case LABEL_EXPR:
       return *tp;
+
     case GOTO_EXPR:
       *walk_subtrees = 0;
-    /* no break */
+
+      /* ... fall through ...  */
+
     default:
       return NULL_TREE;
     }
 }
 
-/* Checks whether the sub-tree ST contains a label LABEL_EXPR which is
-   accessible from outside the sub-tree. Returns NULL_TREE if no
-   addressable label is found.  */
+/* Return whether the sub-tree ST contains a label which is accessible from
+   outside the sub-tree.  */
 
 static bool
 contains_label_p (tree st)
 {
-  return (walk_tree (&st, contains_label_1 , NULL, NULL) != NULL_TREE);
+  return
+   (walk_tree_without_duplicates (&st, contains_label_1 , NULL) != NULL_TREE);
 }
 
 /* Fold a ternary expression of code CODE and type TYPE with operands
@@ -13259,10 +13222,11 @@ contains_label_p (tree st)
    successful.  Otherwise, return NULL_TREE.  */
 
 tree
-fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2)
+fold_ternary_loc (location_t loc, enum tree_code code, tree type,
+                 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)
@@ -13290,6 +13254,12 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2)
       STRIP_NOPS (arg1);
     }
 
+  if (op2)
+    {
+      arg2 = op2;
+      STRIP_NOPS (arg2);
+    }
+
   switch (code)
     {
     case COMPONENT_REF:
@@ -13319,11 +13289,11 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2)
                || !contains_label_p (unused_op))
               && (! VOID_TYPE_P (TREE_TYPE (tem))
                   || VOID_TYPE_P (type)))
-           return pedantic_non_lvalue (tem);
+           return pedantic_non_lvalue_loc (loc, tem);
          return NULL_TREE;
        }
       if (operand_equal_p (arg1, op2, 0))
-       return pedantic_omit_one_operand (type, arg1, arg0);
+       return pedantic_omit_one_operand_loc (loc, 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
@@ -13336,7 +13306,7 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2)
                                             arg1, TREE_OPERAND (arg0, 1))
          && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
        {
-         tem = fold_cond_expr_with_comparison (type, arg0, op1, op2);
+         tem = fold_cond_expr_with_comparison (loc, type, arg0, op1, op2);
          if (tem)
            return tem;
        }
@@ -13347,10 +13317,11 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2)
                                             TREE_OPERAND (arg0, 1))
          && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (op2))))
        {
-         tem = fold_truth_not_expr (arg0);
+         location_t loc0 = expr_location_or (arg0, loc);
+         tem = fold_truth_not_expr (loc0, arg0);
          if (tem && COMPARISON_CLASS_P (tem))
            {
-             tem = fold_cond_expr_with_comparison (type, tem, op2, op1);
+             tem = fold_cond_expr_with_comparison (loc, type, tem, op2, op1);
              if (tem)
                return tem;
            }
@@ -13361,12 +13332,13 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2)
       if (truth_value_p (TREE_CODE (arg0))
          && tree_swap_operands_p (op1, op2, false))
        {
+         location_t loc0 = expr_location_or (arg0, loc);
          /* See if this can be inverted.  If it can't, possibly because
             it was a floating-point inequality comparison, don't do
             anything.  */
-         tem = fold_truth_not_expr (arg0);
+         tem = fold_truth_not_expr (loc0, arg0);
          if (tem)
-           return fold_build3 (code, type, tem, op2, op1);
+           return fold_build3_loc (loc, code, type, tem, op2, op1);
        }
 
       /* Convert A ? 1 : 0 to simply A.  */
@@ -13377,15 +13349,17 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2)
             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);
+       return pedantic_non_lvalue_loc (loc, 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 (op1)
          && integer_onep (op2)
          && truth_value_p (TREE_CODE (arg0)))
-       return pedantic_non_lvalue (fold_convert (type,
-                                                 invert_truthvalue (arg0)));
+       return pedantic_non_lvalue_loc (loc,
+                                   fold_convert_loc (loc, type,
+                                             invert_truthvalue_loc (loc,
+                                                                    arg0)));
 
       /* A < 0 ? <sign bit of A> : 0 is simply (A & <sign bit of A>).  */
       if (TREE_CODE (arg0) == LT_EXPR
@@ -13440,24 +13414,26 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2)
                  && (TREE_INT_CST_LOW (arg1) & mask_lo) == mask_lo)
                {
                  tem_type = signed_type_for (TREE_TYPE (tem));
-                 tem = fold_convert (tem_type, tem);
+                 tem = fold_convert_loc (loc, tem_type, tem);
                }
              else if ((TREE_INT_CST_HIGH (arg1) & mask_hi) == 0
                       && (TREE_INT_CST_LOW (arg1) & mask_lo) == 0)
                {
                  tem_type = unsigned_type_for (TREE_TYPE (tem));
-                 tem = fold_convert (tem_type, tem);
+                 tem = fold_convert_loc (loc, tem_type, tem);
                }
              else
                tem = NULL;
            }
 
          if (tem)
-           return fold_convert (type,
-                                fold_build2 (BIT_AND_EXPR,
-                                             TREE_TYPE (tem), tem,
-                                             fold_convert (TREE_TYPE (tem),
-                                                           arg1)));
+           return
+             fold_convert_loc (loc, type,
+                               fold_build2_loc (loc, BIT_AND_EXPR,
+                                            TREE_TYPE (tem), tem,
+                                            fold_convert_loc (loc,
+                                                              TREE_TYPE (tem),
+                                                              arg1)));
        }
 
       /* (A >> N) & 1 ? (1 << N) : 0 is simply A & (1 << N).  A & 1 was
@@ -13473,7 +13449,7 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2)
               && 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,
+           return fold_build2_loc (loc, BIT_AND_EXPR, type,
                                TREE_OPERAND (tem, 0), arg1);
        }
 
@@ -13488,15 +13464,16 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2)
          && 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)));
+       return pedantic_non_lvalue_loc (loc,
+                                   fold_convert_loc (loc, type,
+                                                     TREE_OPERAND (arg0, 0)));
 
       /* Convert A ? B : 0 into A && B if A and B are truth values.  */
       if (integer_zerop (op2)
          && truth_value_p (TREE_CODE (arg0))
          && truth_value_p (TREE_CODE (arg1)))
-       return fold_build2 (TRUTH_ANDIF_EXPR, type,
-                           fold_convert (type, arg0),
+       return fold_build2_loc (loc, TRUTH_ANDIF_EXPR, type,
+                           fold_convert_loc (loc, type, arg0),
                            arg1);
 
       /* Convert A ? B : 1 into !A || B if A and B are truth values.  */
@@ -13504,11 +13481,12 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2)
          && truth_value_p (TREE_CODE (arg0))
          && truth_value_p (TREE_CODE (arg1)))
        {
+         location_t loc0 = expr_location_or (arg0, loc);
          /* Only perform transformation if ARG0 is easily inverted.  */
-         tem = fold_truth_not_expr (arg0);
+         tem = fold_truth_not_expr (loc0, arg0);
          if (tem)
-           return fold_build2 (TRUTH_ORIF_EXPR, type,
-                               fold_convert (type, tem),
+           return fold_build2_loc (loc, TRUTH_ORIF_EXPR, type,
+                               fold_convert_loc (loc, type, tem),
                                arg1);
        }
 
@@ -13517,11 +13495,12 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2)
          && truth_value_p (TREE_CODE (arg0))
          && truth_value_p (TREE_CODE (op2)))
        {
+         location_t loc0 = expr_location_or (arg0, loc);
          /* Only perform transformation if ARG0 is easily inverted.  */
-         tem = fold_truth_not_expr (arg0);
+         tem = fold_truth_not_expr (loc0, arg0);
          if (tem)
-           return fold_build2 (TRUTH_ANDIF_EXPR, type,
-                               fold_convert (type, tem),
+           return fold_build2_loc (loc, TRUTH_ANDIF_EXPR, type,
+                               fold_convert_loc (loc, type, tem),
                                op2);
        }
 
@@ -13529,8 +13508,8 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2)
       if (integer_onep (arg1)
          && truth_value_p (TREE_CODE (arg0))
          && truth_value_p (TREE_CODE (op2)))
-       return fold_build2 (TRUTH_ORIF_EXPR, type,
-                           fold_convert (type, arg0),
+       return fold_build2_loc (loc, TRUTH_ORIF_EXPR, type,
+                           fold_convert_loc (loc, type, arg0),
                            op2);
 
       return NULL_TREE;
@@ -13571,7 +13550,7 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2)
              if (elements)
                return TREE_VALUE (elements);
              else
-               return fold_convert (type, integer_zero_node);
+               return build_zero_cst (type);
            }
        }
 
@@ -13579,10 +13558,21 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2)
       if (INTEGRAL_TYPE_P (TREE_TYPE (arg0))
          && TYPE_PRECISION (TREE_TYPE (arg0)) == tree_low_cst (arg1, 1)
          && integer_zerop (op2))
-       return fold_convert (type, arg0);
+       return fold_convert_loc (loc, type, arg0);
 
       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) */
@@ -13608,6 +13598,7 @@ fold (tree expr)
   enum tree_code code = TREE_CODE (t);
   enum tree_code_class kind = TREE_CODE_CLASS (code);
   tree tem;
+  location_t loc = EXPR_LOCATION (expr);
 
   /* Return right away if a constant.  */
   if (kind == tcc_constant)
@@ -13619,7 +13610,7 @@ fold (tree expr)
     {
       if (code == CALL_EXPR)
        {
-         tem = fold_call_expr (expr, false);
+         tem = fold_call_expr (loc, expr, false);
          return tem ? tem : expr;
        }
       return expr;
@@ -13634,18 +13625,18 @@ fold (tree expr)
        {
        case 1:
          op0 = TREE_OPERAND (t, 0);
-         tem = fold_unary (code, type, op0);
+         tem = fold_unary_loc (loc, code, type, op0);
          return tem ? tem : expr;
        case 2:
          op0 = TREE_OPERAND (t, 0);
          op1 = TREE_OPERAND (t, 1);
-         tem = fold_binary (code, type, op0, op1);
+         tem = fold_binary_loc (loc, code, type, op0, op1);
          return tem ? tem : expr;
        case 3:
          op0 = TREE_OPERAND (t, 0);
          op1 = TREE_OPERAND (t, 1);
          op2 = TREE_OPERAND (t, 2);
-         tem = fold_ternary (code, type, op0, op1, op2);
+         tem = fold_ternary_loc (loc, code, type, op0, op1, op2);
          return tem ? tem : expr;
        default:
          break;
@@ -13765,11 +13756,11 @@ 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;
-  
+
 recursive_label:
 
   gcc_assert ((sizeof (struct tree_exp) + 5 * sizeof (tree)
@@ -13777,10 +13768,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))
@@ -13816,7 +13807,8 @@ recursive_label:
   if (TREE_CODE_CLASS (code) != tcc_type
       && TREE_CODE_CLASS (code) != tcc_declaration
       && code != TREE_LIST
-      && code != SSA_NAME)
+      && code != SSA_NAME
+      && CODE_CONTAINS_STRUCT (code, TS_COMMON))
     fold_checksum_tree (TREE_CHAIN (expr), ctx, ht);
   switch (TREE_CODE_CLASS (code))
     {
@@ -13879,7 +13871,7 @@ recursive_label:
        }
       if (CODE_CONTAINS_STRUCT (TREE_CODE (expr), TS_DECL_WITH_VIS))
        fold_checksum_tree (DECL_SECTION_NAME (expr), ctx, ht);
-         
+
       if (CODE_CONTAINS_STRUCT (TREE_CODE (expr), TS_DECL_NON_COMMON))
        {
          fold_checksum_tree (DECL_VINDEX (expr), ctx, ht);
@@ -13917,14 +13909,14 @@ recursive_label:
    by "call debug_fold_checksum (op0)", then just trace down till the
    outputs differ.  */
 
-void
+DEBUG_FUNCTION void
 debug_fold_checksum (const_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);
@@ -13939,12 +13931,13 @@ debug_fold_checksum (const_tree t)
 #endif
 
 /* Fold a unary tree expression with code CODE of type TYPE with an
-   operand OP0.  Return a folded expression if successful.  Otherwise,
-   return a tree expression with code CODE of type TYPE with an
-   operand OP0.  */
+   operand OP0.  LOC is the location of the resulting expression.
+   Return a folded expression if successful.  Otherwise, return a tree
+   expression with code CODE of type TYPE with an operand OP0.  */
 
 tree
-fold_build1_stat (enum tree_code code, tree type, tree op0 MEM_STAT_DECL)
+fold_build1_stat_loc (location_t loc,
+                     enum tree_code code, tree type, tree op0 MEM_STAT_DECL)
 {
   tree tem;
 #ifdef ENABLE_FOLD_CHECKING
@@ -13958,11 +13951,11 @@ fold_build1_stat (enum tree_code code, tree type, tree op0 MEM_STAT_DECL)
   md5_finish_ctx (&ctx, checksum_before);
   htab_empty (ht);
 #endif
-  
-  tem = fold_unary (code, type, op0);
+
+  tem = fold_unary_loc (loc, code, type, op0);
   if (!tem)
-    tem = build1_stat (code, type, op0 PASS_MEM_STAT);
-  
+    tem = build1_stat_loc (loc, code, type, op0 PASS_MEM_STAT);
+
 #ifdef ENABLE_FOLD_CHECKING
   md5_init_ctx (&ctx);
   fold_checksum_tree (op0, &ctx, ht);
@@ -13976,13 +13969,15 @@ fold_build1_stat (enum tree_code code, tree type, tree op0 MEM_STAT_DECL)
 }
 
 /* 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
-   with operands OP0 and OP1.  */
+   operands OP0 and OP1.  LOC is the location of the resulting
+   expression.  Return a folded expression if successful.  Otherwise,
+   return a tree expression with code CODE of type TYPE with operands
+   OP0 and OP1.  */
 
 tree
-fold_build2_stat (enum tree_code code, tree type, tree op0, tree op1
-                 MEM_STAT_DECL)
+fold_build2_stat_loc (location_t loc,
+                     enum tree_code code, tree type, tree op0, tree op1
+                     MEM_STAT_DECL)
 {
   tree tem;
 #ifdef ENABLE_FOLD_CHECKING
@@ -14005,10 +14000,10 @@ fold_build2_stat (enum tree_code code, tree type, tree op0, tree op1
   htab_empty (ht);
 #endif
 
-  tem = fold_binary (code, type, op0, op1);
+  tem = fold_binary_loc (loc, code, type, op0, op1);
   if (!tem)
-    tem = build2_stat (code, type, op0, op1 PASS_MEM_STAT);
-  
+    tem = build2_stat_loc (loc, code, type, op0, op1 PASS_MEM_STAT);
+
 #ifdef ENABLE_FOLD_CHECKING
   md5_init_ctx (&ctx);
   fold_checksum_tree (op0, &ctx, ht);
@@ -14017,7 +14012,7 @@ fold_build2_stat (enum tree_code code, tree type, tree op0, tree op1
 
   if (memcmp (checksum_before_op0, checksum_after_op0, 16))
     fold_check_failed (op0, tem);
-  
+
   md5_init_ctx (&ctx);
   fold_checksum_tree (op1, &ctx, ht);
   md5_finish_ctx (&ctx, checksum_after_op1);
@@ -14035,8 +14030,8 @@ fold_build2_stat (enum tree_code code, tree type, tree op0, tree op1
    type TYPE with operands OP0, OP1, and OP2.  */
 
 tree
-fold_build3_stat (enum tree_code code, tree type, tree op0, tree op1, tree op2
-            MEM_STAT_DECL)
+fold_build3_stat_loc (location_t loc, enum tree_code code, tree type,
+                     tree op0, tree op1, tree op2 MEM_STAT_DECL)
 {
   tree tem;
 #ifdef ENABLE_FOLD_CHECKING
@@ -14067,10 +14062,10 @@ fold_build3_stat (enum tree_code code, tree type, tree op0, tree op1, tree op2
 #endif
 
   gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp);
-  tem = fold_ternary (code, type, op0, op1, op2);
+  tem = fold_ternary_loc (loc, code, type, op0, op1, op2);
   if (!tem)
-    tem =  build3_stat (code, type, op0, op1, op2 PASS_MEM_STAT);
-      
+    tem = build3_stat_loc (loc, code, type, op0, op1, op2 PASS_MEM_STAT);
+
 #ifdef ENABLE_FOLD_CHECKING
   md5_init_ctx (&ctx);
   fold_checksum_tree (op0, &ctx, ht);
@@ -14079,7 +14074,7 @@ fold_build3_stat (enum tree_code code, tree type, tree op0, tree op1, tree op2
 
   if (memcmp (checksum_before_op0, checksum_after_op0, 16))
     fold_check_failed (op0, tem);
-  
+
   md5_init_ctx (&ctx);
   fold_checksum_tree (op1, &ctx, ht);
   md5_finish_ctx (&ctx, checksum_after_op1);
@@ -14087,7 +14082,7 @@ fold_build3_stat (enum tree_code code, tree type, tree op0, tree op1, tree op2
 
   if (memcmp (checksum_before_op1, checksum_after_op1, 16))
     fold_check_failed (op1, tem);
-  
+
   md5_init_ctx (&ctx);
   fold_checksum_tree (op2, &ctx, ht);
   md5_finish_ctx (&ctx, checksum_after_op2);
@@ -14105,7 +14100,8 @@ fold_build3_stat (enum tree_code code, tree type, tree op0, tree op1, tree op2
    of type TYPE from the given operands as constructed by build_call_array.  */
 
 tree
-fold_build_call_array (tree type, tree fn, int nargs, tree *argarray)
+fold_build_call_array_loc (location_t loc, tree type, tree fn,
+                          int nargs, tree *argarray)
 {
   tree tem;
 #ifdef ENABLE_FOLD_CHECKING
@@ -14130,8 +14126,8 @@ fold_build_call_array (tree type, tree fn, int nargs, tree *argarray)
   htab_empty (ht);
 #endif
 
-  tem = fold_builtin_call_array (type, fn, nargs, argarray);
-      
+  tem = fold_builtin_call_array (loc, type, fn, nargs, argarray);
+
 #ifdef ENABLE_FOLD_CHECKING
   md5_init_ctx (&ctx);
   fold_checksum_tree (fn, &ctx, ht);
@@ -14140,7 +14136,7 @@ fold_build_call_array (tree type, tree fn, int nargs, tree *argarray)
 
   if (memcmp (checksum_before_fn, checksum_after_fn, 16))
     fold_check_failed (fn, tem);
-  
+
   md5_init_ctx (&ctx);
   for (i = 0; i < nargs; i++)
     fold_checksum_tree (argarray[i], &ctx, ht);
@@ -14177,50 +14173,52 @@ fold_build_call_array (tree type, tree fn, int nargs, tree *argarray)
   folding_initializer = saved_folding_initializer;
 
 tree
-fold_build1_initializer (enum tree_code code, tree type, tree op)
+fold_build1_initializer_loc (location_t loc, enum tree_code code,
+                            tree type, tree op)
 {
   tree result;
   START_FOLD_INIT;
 
-  result = fold_build1 (code, type, op);
+  result = fold_build1_loc (loc, code, type, op);
 
   END_FOLD_INIT;
   return result;
 }
 
 tree
-fold_build2_initializer (enum tree_code code, tree type, tree op0, tree op1)
+fold_build2_initializer_loc (location_t loc, enum tree_code code,
+                            tree type, tree op0, tree op1)
 {
   tree result;
   START_FOLD_INIT;
 
-  result = fold_build2 (code, type, op0, op1);
+  result = fold_build2_loc (loc, code, type, op0, op1);
 
   END_FOLD_INIT;
   return result;
 }
 
 tree
-fold_build3_initializer (enum tree_code code, tree type, tree op0, tree op1,
-                        tree op2)
+fold_build3_initializer_loc (location_t loc, enum tree_code code,
+                            tree type, tree op0, tree op1, tree op2)
 {
   tree result;
   START_FOLD_INIT;
 
-  result = fold_build3 (code, type, op0, op1, op2);
+  result = fold_build3_loc (loc, code, type, op0, op1, op2);
 
   END_FOLD_INIT;
   return result;
 }
 
 tree
-fold_build_call_array_initializer (tree type, tree fn,
-                                  int nargs, tree *argarray)
+fold_build_call_array_initializer_loc (location_t loc, tree type, tree fn,
+                                      int nargs, tree *argarray)
 {
   tree result;
   START_FOLD_INIT;
 
-  result = fold_build_call_array (type, fn, nargs, argarray);
+  result = fold_build_call_array_loc (loc, type, fn, nargs, argarray);
 
   END_FOLD_INIT;
   return result;
@@ -14310,7 +14308,7 @@ multiple_of_p (tree type, const_tree top, const_tree bottom)
              && 0 != (t1 = fold_convert (type,
                                          const_binop (LSHIFT_EXPR,
                                                       size_one_node,
-                                                      op1, 0)))
+                                                      op1)))
              && !TREE_OVERFLOW (t1))
            return multiple_of_p (type, t1, bottom);
        }
@@ -14328,6 +14326,10 @@ multiple_of_p (tree type, const_tree top, const_tree bottom)
     case SAVE_EXPR:
       return multiple_of_p (type, TREE_OPERAND (top, 0), bottom);
 
+    case COND_EXPR:
+      return (multiple_of_p (type, TREE_OPERAND (top, 1), bottom)
+             && multiple_of_p (type, TREE_OPERAND (top, 2), bottom));
+
     case INTEGER_CST:
       if (TREE_CODE (bottom) != INTEGER_CST
          || integer_zerop (bottom)
@@ -14336,7 +14338,7 @@ multiple_of_p (tree type, const_tree top, const_tree bottom)
                  || tree_int_cst_sgn (bottom) < 0)))
        return 0;
       return integer_zerop (int_const_binop (TRUNC_MOD_EXPR,
-                                            top, bottom, 0));
+                                            top, bottom));
 
     default:
       return 0;
@@ -14484,10 +14486,10 @@ tree_binary_nonnegative_warnv_p (enum tree_code code, tree type, tree op0,
          && (TREE_CODE (op0) == NOP_EXPR || TREE_CODE (op0) == INTEGER_CST)
          && (TREE_CODE (op1) == NOP_EXPR || TREE_CODE (op1) == INTEGER_CST))
        {
-         tree inner0 = (TREE_CODE (op0) == NOP_EXPR) 
+         tree inner0 = (TREE_CODE (op0) == NOP_EXPR)
            ? TREE_TYPE (TREE_OPERAND (op0, 0))
            : TREE_TYPE (op0);
-         tree inner1 = (TREE_CODE (op1) == NOP_EXPR) 
+         tree inner1 = (TREE_CODE (op1) == NOP_EXPR)
            ? TREE_TYPE (TREE_OPERAND (op1, 0))
            : TREE_TYPE (op1);
 
@@ -14853,9 +14855,7 @@ tree_expr_nonnegative_warnv_p (tree t, bool *strict_overflow_p)
     case ASSERT_EXPR:
     case ADDR_EXPR:
     case WITH_SIZE_EXPR:
-    case EXC_PTR_EXPR:
     case SSA_NAME:
-    case FILTER_EXPR:
       return tree_single_nonnegative_warnv_p (t, strict_overflow_p);
 
     default:
@@ -15049,7 +15049,9 @@ tree_single_nonzero_warnv_p (tree t, bool *strict_overflow_p)
 
     case ADDR_EXPR:
       {
-       tree base = get_base_address (TREE_OPERAND (t, 0));
+       tree base = TREE_OPERAND (t, 0);
+       if (!DECL_P (base))
+         base = get_base_address (base);
 
        if (!base)
          return false;
@@ -15059,7 +15061,9 @@ tree_single_nonzero_warnv_p (tree t, bool *strict_overflow_p)
           allocated on the stack.  */
        if (DECL_P (base)
            && (flag_delete_null_pointer_checks
-               || (TREE_CODE (base) == VAR_DECL && !TREE_STATIC (base))))
+               || (DECL_CONTEXT (base)
+                   && TREE_CODE (DECL_CONTEXT (base)) == FUNCTION_DECL
+                   && auto_var_in_fn_p (base, DECL_CONTEXT (base)))))
          return !VAR_OR_FUNCTION_DECL_P (base) || !DECL_WEAK (base);
 
        /* Constants are never weak.  */
@@ -15147,9 +15151,7 @@ tree_expr_nonzero_warnv_p (tree t, bool *strict_overflow_p)
     case ASSERT_EXPR:
     case ADDR_EXPR:
     case WITH_SIZE_EXPR:
-    case EXC_PTR_EXPR:
     case SSA_NAME:
-    case FILTER_EXPR:
       return tree_single_nonzero_warnv_p (t, strict_overflow_p);
 
     case COMPOUND_EXPR:
@@ -15233,13 +15235,14 @@ fold_read_from_constant_string (tree exp)
       tree exp1 = TREE_OPERAND (exp, 0);
       tree index;
       tree string;
+      location_t loc = EXPR_LOCATION (exp);
 
       if (TREE_CODE (exp) == INDIRECT_REF)
        string = string_constant (exp1, &index);
       else
        {
          tree low_bound = array_ref_low_bound (exp);
-         index = fold_convert (sizetype, TREE_OPERAND (exp, 1));
+         index = fold_convert_loc (loc, sizetype, TREE_OPERAND (exp, 1));
 
          /* Optimize the special-case of a zero lower bound.
 
@@ -15249,7 +15252,8 @@ fold_read_from_constant_string (tree exp)
             +(INDEX-(unsigned char)1)) becomes ((ARRAY+(-(unsigned char)1))
             +INDEX), which becomes (ARRAY+255+INDEX).  Oops!)  */
          if (! integer_zerop (low_bound))
-           index = size_diffop (index, fold_convert (sizetype, low_bound));
+           index = size_diffop_loc (loc, index,
+                                fold_convert_loc (loc, sizetype, low_bound));
 
          string = exp1;
        }
@@ -15283,19 +15287,17 @@ fold_negate_const (tree arg0, tree type)
     {
     case INTEGER_CST:
       {
-       unsigned HOST_WIDE_INT low;
-       HOST_WIDE_INT high;
-       int overflow = neg_double (TREE_INT_CST_LOW (arg0),
-                                  TREE_INT_CST_HIGH (arg0),
-                                  &low, &high);
-       t = force_fit_type_double (type, low, high, 1,
+       double_int val = tree_to_double_int (arg0);
+       int overflow = neg_double (val.low, val.high, &val.low, &val.high);
+
+       t = force_fit_type_double (type, val, 1,
                                   (overflow | TREE_OVERFLOW (arg0))
                                   && !TYPE_UNSIGNED (type));
        break;
       }
 
     case REAL_CST:
-      t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
+      t = build_real (type, real_value_negate (&TREE_REAL_CST (arg0)));
       break;
 
     case FIXED_CST:
@@ -15331,30 +15333,31 @@ fold_abs_const (tree arg0, tree type)
   switch (TREE_CODE (arg0))
     {
     case INTEGER_CST:
-      /* If the value is unsigned, then the absolute value is
-        the same as the ordinary value.  */
-      if (TYPE_UNSIGNED (type))
-       t = arg0;
-      /* Similarly, if the value is non-negative.  */
-      else if (INT_CST_LT (integer_minus_one_node, arg0))
-       t = arg0;
-      /* If the value is negative, then the absolute value is
-        its negation.  */
-      else
-       {
-         unsigned HOST_WIDE_INT low;
-         HOST_WIDE_INT high;
-         int overflow = neg_double (TREE_INT_CST_LOW (arg0),
-                                    TREE_INT_CST_HIGH (arg0),
-                                    &low, &high);
-         t = force_fit_type_double (type, low, high, -1,
-                                    overflow | TREE_OVERFLOW (arg0));
-       }
+      {
+       double_int val = tree_to_double_int (arg0);
+
+        /* If the value is unsigned or non-negative, then the absolute value
+          is the same as the ordinary value.  */
+       if (TYPE_UNSIGNED (type)
+           || !double_int_negative_p (val))
+         t = arg0;
+
+       /* If the value is negative, then the absolute value is
+          its negation.  */
+       else
+         {
+           int overflow;
+
+           overflow = neg_double (val.low, val.high, &val.low, &val.high);
+           t = force_fit_type_double (type, val, -1,
+                                      overflow | TREE_OVERFLOW (arg0));
+         }
+      }
       break;
 
     case REAL_CST:
       if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg0)))
-       t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
+       t = build_real (type, real_value_negate (&TREE_REAL_CST (arg0)));
       else
        t =  arg0;
       break;
@@ -15370,17 +15373,14 @@ fold_abs_const (tree arg0, tree type)
    constant.  TYPE is the type of the result.  */
 
 static tree
-fold_not_const (tree arg0, tree type)
+fold_not_const (const_tree arg0, tree type)
 {
-  tree t = NULL_TREE;
+  double_int val;  
 
   gcc_assert (TREE_CODE (arg0) == INTEGER_CST);
 
-  t = force_fit_type_double (type, ~TREE_INT_CST_LOW (arg0),
-                            ~TREE_INT_CST_HIGH (arg0), 0,
-                            TREE_OVERFLOW (arg0));
-
-  return t;
+  val = double_int_not (tree_to_double_int (arg0));
+  return force_fit_type_double (type, val, 0, TREE_OVERFLOW (arg0));
 }
 
 /* Given CODE, a relational operator, the target type, TYPE and two
@@ -15537,7 +15537,7 @@ fold_build_cleanup_point_expr (tree type, tree expr)
       if (!TREE_SIDE_EFFECTS (op))
         return expr;
     }
-  
+
   return build1 (CLEANUP_POINT_EXPR, type, expr);
 }
 
@@ -15546,7 +15546,7 @@ fold_build_cleanup_point_expr (tree type, tree expr)
    possible.  */
 
 tree
-fold_indirect_ref_1 (tree type, tree op0)
+fold_indirect_ref_1 (location_t loc, tree type, tree op0)
 {
   tree sub = op0;
   tree subtype;
@@ -15574,87 +15574,105 @@ fold_indirect_ref_1 (tree type, tree op0)
        }
       /* *(foo *)&fooarray => fooarray[0] */
       else if (TREE_CODE (optype) == ARRAY_TYPE
-              && type == TREE_TYPE (optype))
+              && type == TREE_TYPE (optype)
+              && (!in_gimple_form
+                  || TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST))
        {
          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);
+         if (in_gimple_form
+             && TREE_CODE (min_val) != INTEGER_CST)
+           return NULL_TREE;
+         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
               && type == TREE_TYPE (optype))
-       return fold_build1 (REALPART_EXPR, type, op);
+       return fold_build1_loc (loc, REALPART_EXPR, type, op);
       /* *(foo *)&vectorfoo => BIT_FIELD_REF<vectorfoo,...> */
       else if (TREE_CODE (optype) == VECTOR_TYPE
               && type == TREE_TYPE (optype))
        {
          tree part_width = TYPE_SIZE (type);
          tree index = bitsize_int (0);
-         return fold_build3 (BIT_FIELD_REF, type, op, part_width, index);
-       }
-    }
-
-  /* ((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)))
-       { 
-         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 (BIT_FIELD_REF, type, TREE_OPERAND (op00, 0),
-                               part_width, index);
-        
+         return fold_build3_loc (loc, BIT_FIELD_REF, type, op, 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)))
+      if (TREE_CODE (op00) == ADDR_EXPR)
        {
-         tree size = TYPE_SIZE_UNIT (type);
-         if (tree_int_cst_equal (size, op01))
-           return fold_build1 (IMAGPART_EXPR, type, TREE_OPERAND (op00, 0));
+         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 */
+         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);
+           }
        }
     }
-  
+
   /* *(foo *)fooarrptr => (*fooarrptr)[0] */
   if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
-      && type == TREE_TYPE (TREE_TYPE (subtype)))
+      && type == TREE_TYPE (TREE_TYPE (subtype))
+      && (!in_gimple_form
+         || TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST))
     {
       tree type_domain;
       tree min_val = size_zero_node;
-      sub = build_fold_indirect_ref (sub);
+      sub = build_fold_indirect_ref_loc (loc, sub);
       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);
+      if (in_gimple_form
+         && TREE_CODE (min_val) != INTEGER_CST)
+       return NULL_TREE;
+      return build4_loc (loc, ARRAY_REF, type, sub, min_val, NULL_TREE,
+                        NULL_TREE);
     }
 
   return NULL_TREE;
@@ -15664,23 +15682,23 @@ fold_indirect_ref_1 (tree type, tree op0)
    cases.  */
 
 tree
-build_fold_indirect_ref (tree t)
+build_fold_indirect_ref_loc (location_t loc, tree t)
 {
   tree type = TREE_TYPE (TREE_TYPE (t));
-  tree sub = fold_indirect_ref_1 (type, t);
+  tree sub = fold_indirect_ref_1 (loc, type, t);
 
   if (sub)
     return sub;
-  else
-    return build1 (INDIRECT_REF, type, t);
+
+  return build1_loc (loc, INDIRECT_REF, type, t);
 }
 
 /* Given an INDIRECT_REF T, return either T or a simplified version.  */
 
 tree
-fold_indirect_ref (tree t)
+fold_indirect_ref_loc (location_t loc, tree t)
 {
-  tree sub = fold_indirect_ref_1 (TREE_TYPE (t), TREE_OPERAND (t, 0));
+  tree sub = fold_indirect_ref_1 (loc, TREE_TYPE (t), TREE_OPERAND (t, 0));
 
   if (sub)
     return sub;
@@ -15745,7 +15763,7 @@ fold_ignored_result (tree t)
    This can only be applied to objects of a sizetype.  */
 
 tree
-round_up (tree value, int divisor)
+round_up_loc (location_t loc, tree value, int divisor)
 {
   tree div = NULL_TREE;
 
@@ -15770,25 +15788,23 @@ round_up (tree value, int divisor)
     {
       if (TREE_CODE (value) == INTEGER_CST)
        {
-         unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (value);
-         unsigned HOST_WIDE_INT high;
+         double_int val = tree_to_double_int (value);
          bool overflow_p;
 
-         if ((low & (divisor - 1)) == 0)
+         if ((val.low & (divisor - 1)) == 0)
            return value;
 
          overflow_p = TREE_OVERFLOW (value);
-         high = TREE_INT_CST_HIGH (value);
-         low &= ~(divisor - 1);
-         low += divisor;
-         if (low == 0)
+         val.low &= ~(divisor - 1);
+         val.low += divisor;
+         if (val.low == 0)
            {
-             high++;
-             if (high == 0)
+             val.high++;
+             if (val.high == 0)
                overflow_p = true;
            }
 
-         return force_fit_type_double (TREE_TYPE (value), low, high,
+         return force_fit_type_double (TREE_TYPE (value), val,
                                        -1, overflow_p);
        }
       else
@@ -15796,17 +15812,17 @@ round_up (tree value, int divisor)
          tree t;
 
          t = build_int_cst (TREE_TYPE (value), divisor - 1);
-         value = size_binop (PLUS_EXPR, value, t);
+         value = size_binop_loc (loc, PLUS_EXPR, value, t);
          t = build_int_cst (TREE_TYPE (value), -divisor);
-         value = size_binop (BIT_AND_EXPR, value, t);
+         value = size_binop_loc (loc, BIT_AND_EXPR, value, t);
        }
     }
   else
     {
       if (!div)
        div = build_int_cst (TREE_TYPE (value), divisor);
-      value = size_binop (CEIL_DIV_EXPR, value, div);
-      value = size_binop (MULT_EXPR, value, div);
+      value = size_binop_loc (loc, CEIL_DIV_EXPR, value, div);
+      value = size_binop_loc (loc, MULT_EXPR, value, div);
     }
 
   return value;
@@ -15815,7 +15831,7 @@ round_up (tree value, int divisor)
 /* Likewise, but round down.  */
 
 tree
-round_down (tree value, int divisor)
+round_down_loc (location_t loc, tree value, int divisor)
 {
   tree div = NULL_TREE;
 
@@ -15841,14 +15857,14 @@ round_down (tree value, int divisor)
       tree t;
 
       t = build_int_cst (TREE_TYPE (value), -divisor);
-      value = size_binop (BIT_AND_EXPR, value, t);
+      value = size_binop_loc (loc, BIT_AND_EXPR, value, t);
     }
   else
     {
       if (!div)
        div = build_int_cst (TREE_TYPE (value), divisor);
-      value = size_binop (FLOOR_DIV_EXPR, value, div);
-      value = size_binop (MULT_EXPR, value, div);
+      value = size_binop_loc (loc, FLOOR_DIV_EXPR, value, div);
+      value = size_binop_loc (loc, MULT_EXPR, value, div);
     }
 
   return value;
@@ -15866,13 +15882,14 @@ split_address_to_core_and_offset (tree exp,
   enum machine_mode mode;
   int unsignedp, volatilep;
   HOST_WIDE_INT bitsize;
+  location_t loc = EXPR_LOCATION (exp);
 
   if (TREE_CODE (exp) == ADDR_EXPR)
     {
       core = get_inner_reference (TREE_OPERAND (exp, 0), &bitsize, pbitpos,
                                  poffset, &mode, &unsignedp, &volatilep,
                                  false);
-      core = build_fold_addr_expr (core);
+      core = build_fold_addr_expr_loc (loc, core);
     }
   else
     {
@@ -15935,6 +15952,7 @@ tree
 fold_strip_sign_ops (tree exp)
 {
   tree arg0, arg1;
+  location_t loc = EXPR_LOCATION (exp);
 
   switch (TREE_CODE (exp))
     {
@@ -15950,7 +15968,7 @@ fold_strip_sign_ops (tree exp)
       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),
+       return fold_build2_loc (loc, TREE_CODE (exp), TREE_TYPE (exp),
                            arg0 ? arg0 : TREE_OPERAND (exp, 0),
                            arg1 ? arg1 : TREE_OPERAND (exp, 1));
       break;
@@ -15959,18 +15977,19 @@ fold_strip_sign_ops (tree exp)
       arg0 = TREE_OPERAND (exp, 0);
       arg1 = fold_strip_sign_ops (TREE_OPERAND (exp, 1));
       if (arg1)
-       return fold_build2 (COMPOUND_EXPR, TREE_TYPE (exp), arg0, arg1);
+       return fold_build2_loc (loc, COMPOUND_EXPR, TREE_TYPE (exp), arg0, arg1);
       break;
-      
+
     case COND_EXPR:
       arg0 = fold_strip_sign_ops (TREE_OPERAND (exp, 1));
       arg1 = fold_strip_sign_ops (TREE_OPERAND (exp, 2));
       if (arg0 || arg1)
-       return fold_build3 (COND_EXPR, TREE_TYPE (exp), TREE_OPERAND (exp, 0),
+       return fold_build3_loc (loc,
+                           COND_EXPR, TREE_TYPE (exp), TREE_OPERAND (exp, 0),
                            arg0 ? arg0 : TREE_OPERAND (exp, 1),
                            arg1 ? arg1 : TREE_OPERAND (exp, 2));
       break;
-      
+
     case CALL_EXPR:
       {
        const enum built_in_function fcode = builtin_mathfn_code (exp);
@@ -15980,7 +15999,7 @@ fold_strip_sign_ops (tree exp)
          /* Strip copysign function call, return the 1st argument. */
          arg0 = CALL_EXPR_ARG (exp, 0);
          arg1 = CALL_EXPR_ARG (exp, 1);
-         return omit_one_operand (TREE_TYPE (exp), arg0, arg1);
+         return omit_one_operand_loc (loc, TREE_TYPE (exp), arg0, arg1);
 
        default:
          /* Strip sign ops from the argument of "odd" math functions.  */
@@ -15988,7 +16007,7 @@ fold_strip_sign_ops (tree exp)
             {
              arg0 = fold_strip_sign_ops (CALL_EXPR_ARG (exp, 0));
              if (arg0)
-               return build_call_expr (get_callee_fndecl (exp), 1, arg0);
+               return build_call_expr_loc (loc, get_callee_fndecl (exp), 1, arg0);
            }
          break;
        }