OSDN Git Service

gcc/ChangeLog:
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index aab4fac..17672ad 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
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -53,8 +53,7 @@ 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"
@@ -93,8 +92,6 @@ 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);
@@ -159,723 +156,6 @@ static tree fold_convert_const (enum tree_code, tree, tree);
    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)
-{
-  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);
-}
-
-/* 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.  */
-
-int
-neg_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
-           unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv)
-{
-  if (l1 == 0)
-    {
-      *lv = 0;
-      *hv = - h1;
-      return (*hv & h1) < 0;
-    }
-  else
-    {
-      *lv = -l1;
-      *hv = ~h1;
-      return 0;
-    }
-}
-\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;
-
-  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;
-}
-\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.  */
@@ -883,35 +163,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
@@ -1070,7 +340,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;
     }
@@ -1135,10 +405,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));
@@ -1250,7 +524,7 @@ fold_negate_expr (location_t loc, tree t)
         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)
@@ -1288,7 +562,7 @@ fold_negate_expr (location_t loc, tree t)
                            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_loc (loc, CONJ_EXPR, type,
@@ -1972,12 +1246,10 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
          break;
 
        case MULT_EXPR:
-#ifdef HAVE_mpc
          if (COMPLEX_FLOAT_TYPE_P (type))
            return do_mpc_arg2 (arg1, arg2, type,
                                /* do_nonfinite= */ folding_initializer,
                                mpc_mul);
-#endif
 
          real = const_binop (MINUS_EXPR,
                              const_binop (MULT_EXPR, r1, r2, notrunc),
@@ -1990,14 +1262,11 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
          break;
 
        case RDIV_EXPR:
-#ifdef HAVE_mpc
          if (COMPLEX_FLOAT_TYPE_P (type))
            return do_mpc_arg2 (arg1, arg2, type,
                                 /* do_nonfinite= */ folding_initializer,
                                mpc_div);
          /* Fallthru ... */
-#endif
-
        case TRUNC_DIV_EXPR:
        case CEIL_DIV_EXPR:
        case FLOOR_DIV_EXPR:
@@ -2037,10 +1306,10 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
 
               Expand complex division to scalars, modified algorithm to minimize
               overflow with wide input ranges.  */
-           tree inner_type = TREE_TYPE (type);
-           tree absr2 = fold_build1 (ABS_EXPR, inner_type, r2);
-           tree absi2 = fold_build1 (ABS_EXPR, inner_type, i2);
-           tree compare = fold_build2 (LT_EXPR, boolean_type_node, absr2, absi2);
+           tree compare = fold_build2 (LT_EXPR, boolean_type_node,
+                                       fold_abs_const (r2, TREE_TYPE (type)),
+                                       fold_abs_const (i2, TREE_TYPE (type)));
+
            if (integer_nonzerop (compare))
              {
                /* In the TRUE branch, we compute
@@ -2050,17 +1319,18 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
                   ti = (ai * ratio) - ar;
                   tr = tr / div;
                   ti = ti / div;  */
-               tree ratio = fold_build2 (code, inner_type, r2, i2);
-               tree div = fold_build2 (PLUS_EXPR, inner_type, i2,
-                                       fold_build2 (MULT_EXPR, inner_type,
-                                                    r2, ratio));
-               real = fold_build2 (MULT_EXPR, inner_type, r1, ratio);
-               real = fold_build2 (PLUS_EXPR, inner_type, real, i1);
-               real = fold_build2 (code, inner_type, real, div);
-
-               imag = fold_build2 (MULT_EXPR, inner_type, i1, ratio);
-               imag = fold_build2 (MINUS_EXPR, inner_type, imag, r1);
-               imag = fold_build2 (code, inner_type, imag, div);
+               tree ratio = const_binop (code, r2, i2, notrunc);
+               tree div = const_binop (PLUS_EXPR, i2,
+                                       const_binop (MULT_EXPR, r2, ratio,
+                                                    notrunc),
+                                       notrunc);
+               real = const_binop (MULT_EXPR, r1, ratio, notrunc);
+               real = const_binop (PLUS_EXPR, real, i1, notrunc);
+               real = const_binop (code, real, div, notrunc);
+
+               imag = const_binop (MULT_EXPR, i1, ratio, notrunc);
+               imag = const_binop (MINUS_EXPR, imag, r1, notrunc);
+               imag = const_binop (code, imag, div, notrunc);
              }
            else
              {
@@ -2071,18 +1341,19 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
                   ti = b - (a * ratio);
                   tr = tr / div;
                   ti = ti / div;  */
-               tree ratio = fold_build2 (code, inner_type, i2, r2);
-               tree div = fold_build2 (PLUS_EXPR, inner_type, r2,
-                                        fold_build2 (MULT_EXPR, inner_type,
-                                                     i2, ratio));
-
-               real = fold_build2 (MULT_EXPR, inner_type, i1, ratio);
-               real = fold_build2 (PLUS_EXPR, inner_type, real, r1);
-               real = fold_build2 (code, inner_type, real, div);
-
-               imag = fold_build2 (MULT_EXPR, inner_type, r1, ratio);
-               imag = fold_build2 (MINUS_EXPR, inner_type, i1, imag);
-               imag = fold_build2 (code, inner_type, imag, div);
+               tree ratio = const_binop (code, i2, r2, notrunc);
+               tree div = const_binop (PLUS_EXPR, r2,
+                                        const_binop (MULT_EXPR, i2, ratio,
+                                                    notrunc),
+                                       notrunc);
+
+               real = const_binop (MULT_EXPR, i1, ratio, notrunc);
+               real = const_binop (PLUS_EXPR, real, r1, notrunc);
+               real = const_binop (code, real, div, notrunc);
+
+               imag = const_binop (MULT_EXPR, r1, ratio, notrunc);
+               imag = const_binop (MINUS_EXPR, i1, imag, notrunc);
+               imag = const_binop (code, imag, div, notrunc);
              }
          }
          break;
@@ -2100,17 +1371,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);
@@ -2118,8 +1389,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
@@ -2127,17 +1398,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);
-          
+
           /* 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;
 }
@@ -2257,23 +1528,7 @@ fold_convert_const_int_from_int (tree type, const_tree arg1)
      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)))),
+                            !POINTER_TYPE_P (TREE_TYPE (arg1)),
                             (TREE_INT_CST_HIGH (arg1) < 0
                              && (TYPE_UNSIGNED (type)
                                  < TYPE_UNSIGNED (TREE_TYPE (arg1))))
@@ -2300,7 +1555,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);
 
@@ -2318,8 +1573,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
@@ -2332,8 +1586,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);
        }
     }
 
@@ -2346,16 +1599,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,
+  t = force_fit_type_double (type, val.low, val.high, -1,
                             overflow | TREE_OVERFLOW (arg1));
   return t;
 }
@@ -2375,39 +1627,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
+                            (double_int_negative_p (temp)
                              && (TYPE_UNSIGNED (type)
                                  < TYPE_UNSIGNED (TREE_TYPE (arg1))))
                             | TREE_OVERFLOW (arg1));
@@ -2577,7 +1822,7 @@ build_zero_vector (tree type)
 
   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);
@@ -3170,7 +2415,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
@@ -3254,7 +2506,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,
@@ -3413,7 +2665,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
 
        case COND_EXPR:
          return OP_SAME (0) && OP_SAME (1) && OP_SAME (2);
-         
+
        default:
          return 0;
        }
@@ -4130,7 +3382,7 @@ make_bit_field_ref (location_t loc, tree inner, tree type,
       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_loc (loc, type, inner);
     }
@@ -5540,7 +4792,7 @@ fold_cond_expr_with_comparison (location_t loc, tree type,
            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, 
+           return pedantic_non_lvalue_loc (loc,
                                            fold_convert_loc (loc, type, tem));
          }
        break;
@@ -5744,6 +4996,76 @@ unextend (tree c, int p, int unsignedp, tree mask)
                       const_binop (BIT_XOR_EXPR, c, temp, 0));
 }
 \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'".
@@ -6729,12 +6051,6 @@ fold_binary_op_with_conditional_arg (location_t loc,
   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);
@@ -6756,6 +6072,14 @@ fold_binary_op_with_conditional_arg (location_t loc,
       false_value = constant_boolean_node (false, testtype);
     }
 
+  /* 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)
     {
@@ -6774,8 +6098,11 @@ fold_binary_op_with_conditional_arg (location_t loc,
        rhs = fold_build2_loc (loc, code, type, arg, false_value);
     }
 
-  test = fold_build3_loc (loc, COND_EXPR, type, test, lhs, rhs);
-  return fold_convert_loc (loc, 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
@@ -7275,7 +6602,7 @@ fold_single_bit_test (location_t loc, enum tree_code code,
         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;
@@ -7560,7 +6887,7 @@ try_move_mult_to_index (location_t loc, tree addr, tree op1)
 
       STRIP_NOPS (arg0);
       STRIP_NOPS (arg1);
-  
+
       if (TREE_CODE (arg0) == INTEGER_CST)
         {
           s = arg0;
@@ -7590,13 +6917,16 @@ try_move_mult_to_index (location_t loc, 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)
@@ -7623,18 +6953,17 @@ try_move_mult_to_index (location_t loc, 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_loc (loc, PLUS_EXPR, itype,
-                                fold_convert_loc (loc, itype,
-                                                  TREE_OPERAND (ref, 1)),
-                                fold_convert_loc (loc, itype, delta));
+                                    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;
            }
 
@@ -8078,13 +7407,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++)
@@ -8106,13 +7436,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);
 }
 
 
@@ -8449,7 +7779,7 @@ fold_unary_loc (location_t loc, 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))
@@ -8557,10 +7887,11 @@ fold_unary_loc (location_t loc, 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)))
+             && TYPE_QUALS (type) == TYPE_UNQUALIFIED)
            return fold_convert_loc (loc, type,
                                     build_fold_addr_expr_loc (loc, base));
         }
@@ -8953,6 +8284,19 @@ fold_unary_loc (location_t loc, 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) */
@@ -9369,9 +8713,33 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
          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.  */
@@ -9381,7 +8749,7 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
              && (code == EQ_EXPR
                  || code == NE_EXPR
                  || POINTER_TYPE_OVERFLOW_UNDEFINED))
-               
+
            {
              if (code != EQ_EXPR
                  && code != NE_EXPR
@@ -9421,24 +8789,19 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
                   && ((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_loc (loc, 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_loc (loc, signed_size_type_node,
-                                           offset1);
+               offset1 = fold_convert_loc (loc, ssizetype, offset1);
 
              if (code != EQ_EXPR
                  && code != NE_EXPR
@@ -9564,7 +8927,9 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
       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 "
@@ -9613,7 +8978,7 @@ fold_comparison (location_t loc, enum tree_code code, tree 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  */
@@ -9656,7 +9021,7 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
 
       /* 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
@@ -9980,7 +9345,7 @@ get_pointer_modulus_and_residue (tree expr, unsigned HOST_WIDE_INT *residue,
       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,
@@ -10000,7 +9365,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;
@@ -10153,7 +9518,6 @@ fold_binary_loc (location_t loc,
          tem = fold_build2_loc (loc, code, type,
                             fold_convert_loc (loc, TREE_TYPE (op0),
                                               TREE_OPERAND (arg0, 1)), op1);
-         protected_set_expr_location (tem, loc);
          tem = build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0), tem);
          goto fold_binary_exit;
        }
@@ -10163,7 +9527,6 @@ fold_binary_loc (location_t loc,
          tem = fold_build2_loc (loc, code, type, op0,
                             fold_convert_loc (loc, TREE_TYPE (op1),
                                               TREE_OPERAND (arg1, 1)));
-         protected_set_expr_location (tem, loc);
          tem = build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0), tem);
          goto fold_binary_exit;
        }
@@ -10171,7 +9534,7 @@ fold_binary_loc (location_t loc,
       if (TREE_CODE (arg0) == COND_EXPR || COMPARISON_CLASS_P (arg0))
        {
          tem = fold_binary_op_with_conditional_arg (loc, code, type, op0, op1,
-                                                    arg0, arg1, 
+                                                    arg0, arg1,
                                                     /*cond_first_p=*/1);
          if (tem != NULL_TREE)
            return tem;
@@ -10180,7 +9543,7 @@ fold_binary_loc (location_t loc,
       if (TREE_CODE (arg1) == COND_EXPR || COMPARISON_CLASS_P (arg1))
        {
          tem = fold_binary_op_with_conditional_arg (loc, code, type, op0, op1,
-                                                    arg1, arg0, 
+                                                    arg1, arg0,
                                                     /*cond_first_p=*/0);
          if (tem != NULL_TREE)
            return tem;
@@ -10462,7 +9825,7 @@ fold_binary_loc (location_t loc,
            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
@@ -10479,7 +9842,7 @@ fold_binary_loc (location_t loc,
                   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
@@ -10610,23 +9973,39 @@ fold_binary_loc (location_t loc,
          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,
@@ -10637,10 +10016,6 @@ fold_binary_loc (location_t loc,
                       + (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 (loc, var0, var1, code, type);
              con0 = associate_trees (loc, con0, con1, code, type);
              lit0 = associate_trees (loc, lit0, lit1, code, type);
@@ -10915,7 +10290,7 @@ fold_binary_loc (location_t loc,
              tree diff = build2 (MINUS_EXPR, type, op0, op1);
              return fold_build2_loc (loc, MULT_EXPR, type, diff,
                                  fold_convert_loc (loc, type, esz));
-                                 
+
            }
        }
 
@@ -11294,7 +10669,7 @@ fold_binary_loc (location_t loc,
 
          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;
            }
@@ -11481,7 +10856,7 @@ fold_binary_loc (location_t loc,
                            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)
@@ -11511,7 +10886,7 @@ fold_binary_loc (location_t loc,
          && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
        {
          tem = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
-         return fold_build2_loc (loc, BIT_AND_EXPR, type, 
+         return fold_build2_loc (loc, BIT_AND_EXPR, type,
                              fold_build1_loc (loc, BIT_NOT_EXPR, type, tem),
                              fold_convert_loc (loc, type, arg1));
        }
@@ -11630,7 +11005,7 @@ fold_binary_loc (location_t loc,
          && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
        {
          tem = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
-         return fold_build2_loc (loc, BIT_AND_EXPR, type, 
+         return fold_build2_loc (loc, BIT_AND_EXPR, type,
                              fold_build1_loc (loc, BIT_NOT_EXPR, type, tem),
                              fold_convert_loc (loc, type, arg1));
        }
@@ -11895,7 +11270,7 @@ fold_binary_loc (location_t loc,
                }
            }
        }
-      /* 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_loc (loc, RDIV_EXPR, type, TREE_OPERAND (arg0, 0),
@@ -12204,34 +11579,6 @@ fold_binary_loc (location_t loc,
          && TREE_INT_CST_HIGH (arg1) == -1)
        return omit_one_operand_loc (loc, 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_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));
-           }
-       }
-
       /* X % -C is the same as X % C.  */
       if (code == TRUNC_MOD_EXPR
          && !TYPE_UNSIGNED (type)
@@ -12255,6 +11602,7 @@ fold_binary_loc (location_t loc,
                            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)))
@@ -12266,6 +11614,34 @@ fold_binary_loc (location_t loc,
          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;
 
     case LROTATE_EXPR:
@@ -12527,6 +11903,22 @@ fold_binary_loc (location_t loc,
       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.  */
@@ -14228,7 +13620,7 @@ fold_checksum_tree (const_tree expr, struct md5_ctx *ctx, htab_t ht)
   enum tree_code code;
   union tree_node buf;
   int i, len;
-  
+
 recursive_label:
 
   gcc_assert ((sizeof (struct tree_exp) + 5 * sizeof (tree)
@@ -14338,7 +13730,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);
@@ -14383,7 +13775,7 @@ debug_fold_checksum (const_tree t)
   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);
@@ -14418,14 +13810,14 @@ fold_build1_stat_loc (location_t loc,
   md5_finish_ctx (&ctx, checksum_before);
   htab_empty (ht);
 #endif
-  
+
   tem = fold_unary_loc (loc, code, type, op0);
   if (!tem)
     {
       tem = build1_stat (code, type, op0 PASS_MEM_STAT);
       SET_EXPR_LOCATION (tem, loc);
     }
-  
+
 #ifdef ENABLE_FOLD_CHECKING
   md5_init_ctx (&ctx);
   fold_checksum_tree (op0, &ctx, ht);
@@ -14476,7 +13868,7 @@ fold_build2_stat_loc (location_t loc,
       tem = build2_stat (code, type, op0, op1 PASS_MEM_STAT);
       SET_EXPR_LOCATION (tem, loc);
     }
-  
+
 #ifdef ENABLE_FOLD_CHECKING
   md5_init_ctx (&ctx);
   fold_checksum_tree (op0, &ctx, ht);
@@ -14485,7 +13877,7 @@ fold_build2_stat_loc (location_t loc,
 
   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);
@@ -14541,7 +13933,7 @@ fold_build3_stat_loc (location_t loc, enum tree_code code, tree type,
       tem =  build3_stat (code, type, op0, op1, op2 PASS_MEM_STAT);
       SET_EXPR_LOCATION (tem, loc);
     }
-      
+
 #ifdef ENABLE_FOLD_CHECKING
   md5_init_ctx (&ctx);
   fold_checksum_tree (op0, &ctx, ht);
@@ -14550,7 +13942,7 @@ fold_build3_stat_loc (location_t loc, enum tree_code code, tree type,
 
   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);
@@ -14558,7 +13950,7 @@ fold_build3_stat_loc (location_t loc, enum tree_code code, tree type,
 
   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);
@@ -14603,7 +13995,7 @@ fold_build_call_array_loc (location_t loc, tree type, tree fn,
 #endif
 
   tem = fold_builtin_call_array (loc, type, fn, nargs, argarray);
-      
+
 #ifdef ENABLE_FOLD_CHECKING
   md5_init_ctx (&ctx);
   fold_checksum_tree (fn, &ctx, ht);
@@ -14612,7 +14004,7 @@ fold_build_call_array_loc (location_t loc, tree type, tree fn,
 
   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);
@@ -14802,6 +14194,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)
@@ -14958,10 +14354,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);
 
@@ -15521,7 +14917,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;
@@ -15531,7 +14929,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.  */
@@ -15767,7 +15167,7 @@ fold_negate_const (tree arg0, tree type)
       }
 
     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:
@@ -15826,7 +15226,7 @@ fold_abs_const (tree arg0, tree type)
 
     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;
@@ -16009,7 +15409,7 @@ fold_build_cleanup_point_expr (tree type, tree expr)
       if (!TREE_SIDE_EFFECTS (op))
         return expr;
     }
-  
+
   return build1 (CLEANUP_POINT_EXPR, type, expr);
 }
 
@@ -16073,17 +15473,17 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0)
   /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */
   if (TREE_CODE (sub) == POINTER_PLUS_EXPR
       && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
-    { 
+    {
       tree op00 = TREE_OPERAND (sub, 0);
       tree op01 = TREE_OPERAND (sub, 1);
       tree op00type;
-      
+
       STRIP_NOPS (op00);
       op00type = TREE_TYPE (op00);
       if (TREE_CODE (op00) == ADDR_EXPR
           && TREE_CODE (TREE_TYPE (op00type)) == VECTOR_TYPE
           && type == TREE_TYPE (TREE_TYPE (op00type)))
-       { 
+       {
          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;
@@ -16094,7 +15494,7 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0)
            return fold_build3_loc (loc,
                                BIT_FIELD_REF, type, TREE_OPERAND (op00, 0),
                                part_width, index);
-        
+
        }
     }
 
@@ -16119,7 +15519,7 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0)
                                TREE_OPERAND (op00, 0));
        }
     }
-  
+
   /* *(foo *)fooarrptr => (*fooarrptr)[0] */
   if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
       && type == TREE_TYPE (TREE_TYPE (subtype)))
@@ -16443,7 +15843,7 @@ fold_strip_sign_ops (tree exp)
       if (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));
@@ -16453,7 +15853,7 @@ fold_strip_sign_ops (tree exp)
                            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);