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);
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, <wice, &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. */
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
&& 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
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))))
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);
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
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);
}
}
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;
}
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));
|| 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)
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);
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)
{
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
&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));
}
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. */
&& ((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
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 "
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,
+ (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);
&& 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)
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)))
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:
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)