GCC Middle and Back End API Reference
|
Macros | |
#define | add_double(l1, h1, l2, h2, lv, hv) add_double_with_sign (l1, h1, l2, h2, lv, hv, false) |
#define | mul_double(l1, h1, l2, h2, lv, hv) mul_double_wide_with_sign (l1, h1, l2, h2, lv, hv, NULL, NULL, false) |
#define | OVERFLOW_SUM_SIGN(a, b, sum) ((~((a) ^ (b)) & ((a) ^ (sum))) < 0) |
#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) |
#define add_double | ( | l1, | |
h1, | |||
l2, | |||
h2, | |||
lv, | |||
hv | |||
) | add_double_with_sign (l1, h1, l2, h2, lv, hv, false) |
#define BASE ((unsigned HOST_WIDE_INT) 1 << HOST_BITS_PER_WIDE_INT / 2) |
#define HIGHPART | ( | x | ) | ((unsigned HOST_WIDE_INT) (x) >> HOST_BITS_PER_WIDE_INT / 2) |
#define LOWPART | ( | x | ) | ((x) & (((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2)) - 1)) |
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 mul_double | ( | l1, | |
h1, | |||
l2, | |||
h2, | |||
lv, | |||
hv | |||
) | mul_double_wide_with_sign (l1, h1, l2, h2, lv, hv, NULL, NULL, false) |
#define OVERFLOW_SUM_SIGN | ( | a, | |
b, | |||
sum | |||
) | ((~((a) ^ (b)) & ((a) ^ (sum))) < 0) |
We know that A1 + B1 = SUM1, using 2's complement arithmetic and ignoring overflow. Suppose A, B and SUM have the same respective signs as A1, B1, and SUM1. Then this yields nonzero if overflow occurred during the addition.
Overflow occurs if A and B have the same sign, but A and SUM differ in sign. Use `^' to test whether signs differ, and `< 0' to isolate the sign.
Referenced by double_int::operator+().
|
static |
Operations with long integers. Copyright (C) 2006-2013 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see http://www.gnu.org/licenses/.
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.
Referenced by double_int::operator*=().
|
static |
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 |
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.
Calculate quotient sign and convert operands to unsigned.
(minimum integer) / (-1) is the only overflow case.
This unsigned division rounds toward zero.
hden != 0 already checked.
Special code for when the divisor < BASE.
hnum != 0 already checked.
Full double precision division, with thanks to Don Knuth's "Seminumerical Algorithms".
Find the highest nonzero divisor digit.
Insure that the first digit of the divisor is at least BASE/2. This is required by the quotient digit estimation algorithm.
Main loop
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.
Refine quo_est so it's usually correct, and at most one high.
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.
If quo_est was high by one, then num[i] went negative and we need to correct things.
Store the quotient digit.
If result is negative, make it so.
Compute trial remainder: rem = num - (quo * den)
quo = quo - 1;
Get absolute values.
If (2 * abs (lrem) >= abs (lden)), adjust the quotient.
quo = quo - 1;
quo = quo + 1;
Compute true remainder: rem = num - (quo * den)
lnum_orig | num == numerator == dividend |
lden_orig | den == denominator == divisor |
References neg_double().
|
static |
Splits last digit of *CST (taken as unsigned) in BASE and returns it.
void dump_double_int | ( | ) |
Dumps CST to FILE. If UNS is true, CST is considered to be unsigned, otherwise it is signed.
Referenced by aff_combination_constant_multiple_p().
|
static |
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 |
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.
Shifting by the host word size is undefined according to the ANSI standard, so we must handle this as a special case.
Sign extend all bits that are beyond the precision.
References HOST_BITS_PER_WIDE_INT.
Referenced by double_int::lshift(), double_int::rshift(), and double_int::trailing_zeros().
double_int mpz_get_double_int | ( | ) |
Returns VAL converted to TYPE. If WRAP is true, then out-of-range values of VAL will be wrapped; otherwise, they will be set to the appropriate minimum or maximum TYPE bound.
Determine the number of unsigned HOST_WIDE_INT that are required for representing the value. The code to calculate count is extracted from the GMP manual, section "Integer Import and Export": http://gmplib.org/manual/Integer-Import-and-Export.html
void mpz_set_double_int | ( | ) |
Sets RESULT to VAL, taken unsigned if UNS is true and as signed otherwise.
Referenced by build_method_type_directly(), and number_of_iterations_ne_max().
|
static |
Multiply two doubleword integers with quadword 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 four `HOST_WIDE_INT' pieces in *LV and *HV, *LW and *HW. If lw is NULL then only the low part and no overflow is computed.
This product is <= 0xFFFE0001, the sum <= 0xFFFF0000.
Since prod[p] < 0xFFFF, this sum <= 0xFFFFFFFF.
We are not interested in the wide part nor in overflow.
Unsigned overflow is immediate.
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.
|
static |
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.
Referenced by div_and_round_double(), double_int::mul_with_sign(), double_int::operator+(), double_int::operator+=(), and double_int::wide_mul_with_sign().
|
static |
Shift the doubleword integer in L1, H1 right by COUNT places keeping only PREC bits of result. ARITH nonzero specifies arithmetic shifting; otherwise use logical shift. Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV.
Shifting by the host word size is undefined according to the ANSI standard, so we must handle this as a special case.
Zero / sign extend all bits that are beyond the precision.
Referenced by double_int::lshift(), double_int::rshift(), and double_int::trailing_zeros().