diff options
author | Richard Kenner <kenner@vlsi1.ultra.nyu.edu> | 1999-12-18 21:33:23 +0000 |
---|---|---|
committer | Richard Kenner <kenner@gcc.gnu.org> | 1999-12-18 16:33:23 -0500 |
commit | d4b60170fd601e84cdafca12ea3365488ee93635 (patch) | |
tree | b29d6812261abeb25b182a176f35382f12cb98bd /gcc/fold-const.c | |
parent | 3f0aabf20a84ccd50d38dca8f252f887558d31ff (diff) | |
download | gcc-d4b60170fd601e84cdafca12ea3365488ee93635.zip gcc-d4b60170fd601e84cdafca12ea3365488ee93635.tar.gz gcc-d4b60170fd601e84cdafca12ea3365488ee93635.tar.bz2 |
alias.c: Minor reformatting.
* alias.c: Minor reformatting.
* flow.c: Likewise.
* regs.h: Likewise.
* stor-layout.c: Likewise.
* fold-const.c: Likewise.
(OVERFLOW_SUM_SIGN): Renamed from overflow_sum_sign.
(struct cb_args, const_binop_1, const_binop): Pass type of arg,
not arg itself.
(size_int_wide): Cache nodes even if garbage collecting.
(twoval_comparison_p): Reenable SAVE_EXPR case if operand
of SAVE_EXPR has no side effects.
* cse.c: Move a comment.
* tree.c: Minor reformatting.
(int_size_in_bytes): Return -1 if constant overflows.
* reload.c (combine_reloads): Do nothing if no output reload
From-SVN: r31017
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r-- | gcc/fold-const.c | 242 |
1 files changed, 132 insertions, 110 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c index c13b907..335cb5c 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -66,7 +66,9 @@ static tree split_tree PROTO((tree, enum tree_code, tree *, tree *, int)); static tree associate_trees PROTO((tree, tree, enum tree_code, tree)); static tree int_const_binop PROTO((enum tree_code, tree, tree, int, int)); +static void const_binop_1 PROTO((PTR)); static tree const_binop PROTO((enum tree_code, tree, tree, int)); +static void fold_convert_1 PROTO((PTR)); static tree fold_convert PROTO((tree, tree)); static enum tree_code invert_tree_comparison PROTO((enum tree_code)); static enum tree_code swap_tree_comparison PROTO((enum tree_code)); @@ -100,29 +102,31 @@ static tree strip_compound_expr PROTO((tree, tree)); static int multiple_of_p PROTO((tree, tree, tree)); static tree constant_boolean_node PROTO((int, tree)); static int count_cond PROTO((tree, int)); -static void const_binop_1 PROTO((PTR)); -static void fold_convert_1 PROTO((PTR)); #ifndef BRANCH_COST #define BRANCH_COST 1 #endif -/* Suppose A1 + B1 = SUM1, using 2's complement arithmetic ignoring overflow. - Suppose A, B and SUM have the same respective signs as A1, B1, and SUM1. - Then this yields nonzero if overflow occurred during the addition. - Overflow occurs if A and B have the same sign, but A and SUM differ in sign. - Use `^' to test whether signs differ, and `< 0' to isolate the sign. */ -#define overflow_sum_sign(a, b, sum) ((~((a) ^ (b)) & ((a) ^ (sum))) < 0) +/* We know that A1 + B1 = SUM1, using 2's complement arithmetic and ignoring + overflow. Suppose A, B and SUM have the same respective signs as A1, B1, + and SUM1. Then this yields nonzero if overflow occurred during the + addition. + + Overflow occurs if A and B have the same sign, but A and SUM differ in + sign. Use `^' to test whether signs differ, and `< 0' to isolate the + sign. */ +#define OVERFLOW_SUM_SIGN(a, b, sum) ((~((a) ^ (b)) & ((a) ^ (sum))) < 0) /* 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. */ + 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)) + ((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) + ((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. @@ -148,16 +152,16 @@ decode (words, low, hi) HOST_WIDE_INT *words; HOST_WIDE_INT *low, *hi; { - *low = words[0] | words[1] * BASE; - *hi = words[2] | words[3] * BASE; + *low = words[0] + words[1] * BASE; + *hi = words[2] + words[3] * BASE; } -/* Make the integer constant T valid for its type - by setting to 0 or 1 all the bits in the constant - that don't belong in the type. - Yield 1 if a signed overflow occurs, 0 otherwise. - If OVERFLOW is nonzero, a signed overflow has already occurred - in calculating T, so propagate it. +/* Make the integer constant T valid for its type by setting to 0 or 1 all + the bits in the constant that don't belong in the type. + + Return 1 if a signed overflow occurs, 0 otherwise. If OVERFLOW is + nonzero, a signed overflow has already occurred in calculating T, so + propagate it. Make the real constant T valid for its type by calling CHECK_FLOAT_VALUE, if it exists. */ @@ -195,10 +199,8 @@ force_fit_type (t, overflow) if (prec == 2 * HOST_BITS_PER_WIDE_INT) ; else if (prec > HOST_BITS_PER_WIDE_INT) - { - TREE_INT_CST_HIGH (t) - &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT)); - } + TREE_INT_CST_HIGH (t) + &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT)); else { TREE_INT_CST_HIGH (t) = 0; @@ -220,10 +222,8 @@ force_fit_type (t, overflow) /* Value is negative: set to 1 all the bits that are outside this type's precision. */ if (prec > HOST_BITS_PER_WIDE_INT) - { - TREE_INT_CST_HIGH (t) - |= ((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT)); - } + TREE_INT_CST_HIGH (t) + |= ((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT)); else { TREE_INT_CST_HIGH (t) = -1; @@ -232,7 +232,7 @@ force_fit_type (t, overflow) } } - /* Yield nonzero if signed overflow occurred. */ + /* Return nonzero if signed overflow occurred. */ return ((overflow | (low ^ TREE_INT_CST_LOW (t)) | (high ^ TREE_INT_CST_HIGH (t))) != 0); @@ -255,7 +255,7 @@ add_double (l1, h1, l2, h2, lv, hv) *lv = l; *hv = h; - return overflow_sum_sign (h1, h2, h); + return OVERFLOW_SUM_SIGN (h1, h2, h); } /* Negate a doubleword integer with doubleword result. @@ -975,10 +975,9 @@ fail: return 1; } - /* Convert C9X hexadecimal floating point string constant S. Return real value type in mode MODE. This function uses the host computer's - fp arithmetic when there is no REAL_ARITHMETIC. */ + floating point arithmetic when there is no REAL_ARITHMETIC. */ REAL_VALUE_TYPE real_hex_to_f (s, mode) @@ -988,8 +987,13 @@ real_hex_to_f (s, mode) REAL_VALUE_TYPE ip; char *p = s; unsigned HOST_WIDE_INT low, high; - int frexpon, expon, shcount, nrmcount, k; - int sign, expsign, decpt, isfloat, isldouble, gotp, lost; + int expon, shcount, nrmcount, k; + int sign, expsign, isfloat, isldouble; + int lost = 0;/* Nonzero low order bits shifted out and discarded. */ + int frexpon = 0; /* Bits after the decimal point. */ + int expon = 0; /* Value of exponent. */ + int decpt = 0; /* How many decimal points. */ + int gotp = 0; /* How many P's. */ char c; isldouble = 0; @@ -1027,11 +1031,6 @@ real_hex_to_f (s, mode) high = 0; low = 0; - lost = 0; /* Nonzero low order bits shifted out and discarded. */ - frexpon = 0; /* Bits after the decimal point. */ - expon = 0; /* Value of exponent. */ - decpt = 0; /* How many decimal points. */ - gotp = 0; /* How many P's. */ shcount = 0; while ((c = *p) != '\0') { @@ -1058,7 +1057,7 @@ real_hex_to_f (s, mode) { /* Record nonzero lost bits. */ lost |= k; - if (!decpt) + if (! decpt) frexpon -= 4; } ++p; @@ -1068,6 +1067,7 @@ real_hex_to_f (s, mode) ++decpt; ++p; } + else if (c == 'p' || c == 'P') { ++gotp; @@ -1078,6 +1078,7 @@ real_hex_to_f (s, mode) expsign = -1; ++p; } + /* Value of exponent. The exponent field is a decimal integer. */ while (ISDIGIT(*p)) @@ -1085,6 +1086,7 @@ real_hex_to_f (s, mode) k = (*p++ & 0x7f) - '0'; expon = 10 * expon + k; } + expon *= expsign; /* F suffix is ambiguous in the significand part so it must appear after the decimal exponent field. */ @@ -1095,6 +1097,7 @@ real_hex_to_f (s, mode) break; } } + else if (c == 'l' || c == 'L') { isldouble = 1; @@ -1104,18 +1107,19 @@ real_hex_to_f (s, mode) else break; } + /* Abort if last character read was not legitimate. */ c = *p; if ((c != '\0' && c != ' ' && c != '\n' && c != '\r') || (decpt > 1)) abort (); + /* There must be either one decimal point or one p. */ if (decpt == 0 && gotp == 0) abort (); + shcount -= 4; - if ((high == 0) && (low == 0)) - { - return dconst0; - } + if (high == 0 && low == 0)) + return dconst0; /* Normalize. */ nrmcount = 0; @@ -1125,6 +1129,7 @@ real_hex_to_f (s, mode) low = 0; nrmcount += 32; } + /* Leave a high guard bit for carry-out. */ if ((high & 0x80000000) != 0) { @@ -1133,18 +1138,21 @@ real_hex_to_f (s, mode) high = high >> 1; nrmcount -= 1; } + if ((high & 0xffff8000) == 0) { high = (high << 16) + ((low >> 16) & 0xffff); low = low << 16; nrmcount += 16; } + while ((high & 0xc0000000) == 0) { high = (high << 1) + ((low >> 31) & 1); low = low << 1; nrmcount += 1; } + if (isfloat || GET_MODE_SIZE(mode) == UNITS_PER_WORD) { /* Keep 24 bits precision, bits 0x7fffff80. @@ -1193,6 +1201,7 @@ real_hex_to_f (s, mode) low &= 0xffffff80; #endif } + ip = (double) high; ip = REAL_VALUE_LDEXP (ip, 32) + (double) low; /* Apply shifts and exponent value as power of 2. */ @@ -1449,7 +1458,7 @@ int_const_binop (code, arg1, arg2, notrunc, forsize) case MINUS_EXPR: neg_double (int2l, int2h, &low, &hi); add_double (int1l, int1h, low, hi, &low, &hi); - overflow = overflow_sum_sign (hi, int2h, int1h); + overflow = OVERFLOW_SUM_SIGN (hi, int2h, int1h); break; case MULT_EXPR: @@ -1515,21 +1524,18 @@ int_const_binop (code, arg1, arg2, notrunc, forsize) case MIN_EXPR: case MAX_EXPR: if (uns) - { - low = (((unsigned HOST_WIDE_INT) int1h - < (unsigned HOST_WIDE_INT) int2h) - || (((unsigned HOST_WIDE_INT) int1h - == (unsigned HOST_WIDE_INT) int2h) - && ((unsigned HOST_WIDE_INT) int1l - < (unsigned HOST_WIDE_INT) int2l))); - } + low = (((unsigned HOST_WIDE_INT) int1h + < (unsigned HOST_WIDE_INT) int2h) + || (((unsigned HOST_WIDE_INT) int1h + == (unsigned HOST_WIDE_INT) int2h) + && ((unsigned HOST_WIDE_INT) int1l + < (unsigned HOST_WIDE_INT) int2l))); else - { - low = ((int1h < int2h) - || ((int1h == int2h) - && ((unsigned HOST_WIDE_INT) int1l - < (unsigned HOST_WIDE_INT) int2l))); - } + low = ((int1h < int2h) + || ((int1h == int2h) + && ((unsigned HOST_WIDE_INT) int1l + < (unsigned HOST_WIDE_INT) int2l))); + if (low == (code == MIN_EXPR)) low = int1l, hi = int1h; else @@ -1558,6 +1564,7 @@ int_const_binop (code, arg1, arg2, notrunc, forsize) : force_fit_type (t, (!uns || forsize) && overflow) && ! no_overflow) | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2)); + /* If we're doing a size calculation, unsigned arithmetic does overflow. So check if force_fit_type truncated the value. */ if (forsize @@ -1565,27 +1572,30 @@ int_const_binop (code, arg1, arg2, notrunc, forsize) && (TREE_INT_CST_HIGH (t) != hi || TREE_INT_CST_LOW (t) != low)) TREE_OVERFLOW (t) = 1; + TREE_CONSTANT_OVERFLOW (t) = (TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1) | TREE_CONSTANT_OVERFLOW (arg2)); return t; } +/* Define input and output argument for const_binop_1. */ struct cb_args { - /* Input */ - tree arg1; - REAL_VALUE_TYPE d1, d2; - enum tree_code code; - /* Output */ - tree t; + enum tree_code code; /* Input: tree code for operation*/ + tree type; /* Input: tree type for operation. */ + REAL_VALUE_TYPE d1, d2; /* Input: floating point operands. */ + tree t; /* Output: constant for result. */ }; +/* Do the real arithmetic for const_binop while protected by a + float overflow handler. */ + static void const_binop_1 (data) PTR data; { - struct cb_args * args = (struct cb_args *) data; + struct cb_args *args = (struct cb_args *) data; REAL_VALUE_TYPE value; #ifdef REAL_ARITHMETIC @@ -1626,16 +1636,15 @@ const_binop_1 (data) abort (); } #endif /* no REAL_ARITHMETIC */ - args->t = - build_real (TREE_TYPE (args->arg1), - real_value_truncate (TYPE_MODE (TREE_TYPE (args->arg1)), - value)); + + args->t + = build_real (args->type, + real_value_truncate (TYPE_MODE (args->type), value)); } -/* Combine two constants ARG1 and ARG2 under operation CODE - to produce a new constant. - We assume ARG1 and ARG2 have the same data type, - or at least are the same kind of constant and the same machine mode. +/* Combine two constants ARG1 and ARG2 under operation CODE to produce a new + constant. We assume ARG1 and ARG2 have the same data type, or at least + are the same kind of constant and the same machine mode. If NOTRUNC is nonzero, do not truncate the result to fit the data type. */ @@ -1670,19 +1679,17 @@ const_binop (code, arg1, arg2, notrunc) return arg2; /* Setup input for const_binop_1() */ - args.arg1 = arg1; + args.type = TREE_TYPE (arg1); args.d1 = d1; args.d2 = d2; args.code = code; if (do_float_handler (const_binop_1, (PTR) &args)) - { - /* Receive output from const_binop_1() */ - t = args.t; - } + /* Receive output from const_binop_1. */ + t = args.t; else { - /* We got an exception from const_binop_1() */ + /* We got an exception from const_binop_1. */ t = copy_node (arg1); overflow = 1; } @@ -1776,36 +1783,51 @@ const_binop (code, arg1, arg2, notrunc) return 0; } -/* Return an INTEGER_CST with value V . The type is determined by bit_p: - if it is zero, the type is taken from sizetype; if it is one, the type - is taken from bitsizetype. */ +/* Return an INTEGER_CST with value whose HOST_BITS_PER_WIDE_INT bits are + given by HIGH and whose HOST_BITS_PER_WIDE_INT bits are given by NUMBER. + + If BIT_P is nonzero, this represents a size in bit and the type of the + result will be bitsizetype, othewise it represents a size in bytes and + the type of the result will be sizetype. */ tree size_int_wide (number, high, bit_p) unsigned HOST_WIDE_INT number, high; int bit_p; { + /* Type-size nodes already made for small sizes. */ + static tree size_table[2 * HOST_BITS_PER_WIDE_INT + 1][2]; + static int init_p = 0; tree t; - if (!ggc_p) + if (ggc_p && ! init_p) { - /* Type-size nodes already made for small sizes. */ - static tree size_table[2*HOST_BITS_PER_WIDE_INT + 1][2]; + ggc_add_tree_root ((tree *) size_table, + sizeof size_table / sizeof (tree)); + init_p = 1; + } + + if (number < 2*HOST_BITS_PER_WIDE_INT + 1 && high == 0 + && size_table[number][bit_p] != 0) + return size_table[number][bit_p]; - if (number < 2*HOST_BITS_PER_WIDE_INT + 1 && ! high - && size_table[number][bit_p] != 0) - return size_table[number][bit_p]; - if (number < 2*HOST_BITS_PER_WIDE_INT + 1 && ! high) + if (number < 2*HOST_BITS_PER_WIDE_INT + 1 && high == 0) + { + if (! ggc_p) { - push_obstacks_nochange (); /* Make this a permanent node. */ + push_obstacks_nochange (); end_temporary_allocation (); - t = build_int_2 (number, 0); - TREE_TYPE (t) = bit_p ? bitsizetype : sizetype; - size_table[number][bit_p] = t; - pop_obstacks (); - return t; } + + t = build_int_2 (number, 0); + TREE_TYPE (t) = bit_p ? bitsizetype : sizetype; + size_table[number][bit_p] = t; + + if (! ggc_p) + pop_obstacks (); + + return t; } t = build_int_2 (number, high); @@ -1879,14 +1901,17 @@ ssize_binop (code, arg0, arg1) return fold (build (code, ssizetype, arg0, arg1)); } +/* This structure is used to communicate arguments to fold_convert_1. */ struct fc_args { - /* Input */ - tree arg1, type; - /* Output */ - tree t; + tree arg1; /* Input: value to convert. */ + tree type; /* Input: type to convert value to. */ + tree t; /* Ouput: result of conversion. */ }; +/* Function to convert floating-point constants, protected by floating + point exception handler. */ + static void fold_convert_1 (data) PTR data; @@ -2400,11 +2425,8 @@ twoval_comparison_p (arg, cval1, cval2, save_p) || code == COMPOUND_EXPR)) class = '2'; - /* ??? Disable this since the SAVE_EXPR might already be in use outside - the expression. There may be no way to make this work, but it needs - to be looked at again for 2.6. */ -#if 0 - else if (class == 'e' && code == SAVE_EXPR && SAVE_EXPR_RTL (arg) == 0) + else if (class == 'e' && code == SAVE_EXPR && SAVE_EXPR_RTL (arg) == 0 + && ! TREE_SIDE_EFFECTS (TREE_OPERAND (arg, 0))) { /* If we've already found a CVAL1 or CVAL2, this expression is two complex to handle. */ @@ -2414,7 +2436,6 @@ twoval_comparison_p (arg, cval1, cval2, save_p) class = '1'; *save_p = 1; } -#endif switch (class) { @@ -4513,6 +4534,7 @@ constant_boolean_node (value, type) else { tree t = build_int_2 (value, 0); + TREE_TYPE (t) = type; return t; } @@ -4559,10 +4581,8 @@ fold (expr) register enum tree_code code = TREE_CODE (t); register int kind; int invert; - /* WINS will be nonzero when the switch is done if all operands are constant. */ - int wins = 1; /* Don't try to process an RTL_EXPR since its operands aren't trees. @@ -4737,11 +4757,13 @@ fold (expr) && (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 1), 0)) == TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 2), 0))) && ! (INTEGRAL_TYPE_P (TREE_TYPE (t)) - && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 1), 0))) + && (INTEGRAL_TYPE_P + (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 1), 0)))) && TYPE_PRECISION (TREE_TYPE (t)) <= BITS_PER_WORD)) t = build1 (code, type, build (COND_EXPR, - TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 1), 0)), + TREE_TYPE (TREE_OPERAND + (TREE_OPERAND (t, 1), 0)), TREE_OPERAND (t, 0), TREE_OPERAND (TREE_OPERAND (t, 1), 0), TREE_OPERAND (TREE_OPERAND (t, 2), 0))); |