OSDN Git Service

gcc/ChangeLog:
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index 8dd68c2..17672ad 100644 (file)
@@ -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,721 +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 = TYPE_PRECISION (type);
-  int sign_extended_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 = (HOST_WIDE_INT) ((unsigned HOST_WIDE_INT) h1
-                      + (unsigned HOST_WIDE_INT) h2
-                      + (l < l1));
-
-  *lv = l;
-  *hv = h;
-
-  if (unsigned_p)
-    return ((unsigned HOST_WIDE_INT) h < (unsigned HOST_WIDE_INT) h1
-           || (h == h1
-               && l < l1));
-  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.  */
@@ -881,10 +163,7 @@ 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;
+  double_int quo, rem;
   int uns;
 
   /* The sign of the division is according to operand two, that
@@ -895,17 +174,14 @@ div_if_zero_remainder (enum tree_code code, const_tree arg1, const_tree arg2)
       && TYPE_IS_SIZETYPE (TREE_TYPE (arg2)))
     uns = 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);
+  quo = double_int_divmod (tree_to_double_int (arg1),
+                          tree_to_double_int (arg2),
+                          uns, code, &rem);
 
-  div_and_round_double (code, uns, int1l, int1h, int2l, int2h,
-                       &quol, &quoh, &reml, &remh);
-  if (remh != 0 || reml != 0)
-    return NULL_TREE;
+  if (double_int_zero_p (rem))
+    return build_int_cst_wide (TREE_TYPE (arg1), quo.low, quo.high);
 
-  return build_int_cst_wide (TREE_TYPE (arg1), quol, quoh);
+  return NULL_TREE; 
 }
 \f
 /* This is nonzero if we should defer warnings about undefined
@@ -2252,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))))
@@ -2295,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);
 
@@ -2313,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
@@ -2327,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);
        }
     }
 
@@ -2341,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;
 }
@@ -2370,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));
@@ -3170,6 +2420,11 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
       || 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
      precision differences.  */
   if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
@@ -5741,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'".
@@ -6726,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);
@@ -6753,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)
     {
@@ -6771,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
@@ -8077,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++)
@@ -8105,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);
 }
 
 
@@ -8556,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));
         }
@@ -9381,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.  */
@@ -9433,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
@@ -9576,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 "
@@ -9625,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  */
@@ -10620,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,
@@ -10647,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);
@@ -12214,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)
@@ -12265,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)))
@@ -12276,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:
@@ -12537,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.  */
@@ -14812,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)
@@ -15531,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;
@@ -15541,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.  */
@@ -15777,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:
@@ -15836,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;