| /* Fold a constant sub-tree into a single node for C-compiler |
| Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, |
| 2000, 2001, 2002, 2003, 2004, 2005 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 2, 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 COPYING. If not, write to the Free |
| Software Foundation, 59 Temple Place - Suite 330, Boston, MA |
| 02111-1307, USA. */ |
| |
| /*@@ This file should be rewritten to use an arbitrary precision |
| @@ representation for "struct tree_int_cst" and "struct tree_real_cst". |
| @@ Perhaps the routines could also be used for bc/dc, and made a lib. |
| @@ The routines that translate from the ap rep should |
| @@ warn if precision et. al. is lost. |
| @@ This would also make life easier when this technology is used |
| @@ for cross-compilers. */ |
| |
| /* The entry points in this file are fold, size_int_wide, size_binop |
| and force_fit_type. |
| |
| fold takes a tree as argument and returns a simplified tree. |
| |
| size_binop takes a tree code for an arithmetic operation |
| and two operands that are trees, and produces a tree for the |
| result, assuming the type comes from `sizetype'. |
| |
| size_int takes an integer value, and creates a tree constant |
| with type from `sizetype'. |
| |
| force_fit_type takes a constant, an overflowable flag and prior |
| overflow indicators. It forces the value to fit the type and sets |
| TREE_OVERFLOW and TREE_CONSTANT_OVERFLOW as appropriate. */ |
| |
| #include "config.h" |
| #include "system.h" |
| #include "coretypes.h" |
| #include "tm.h" |
| #include "flags.h" |
| #include "tree.h" |
| #include "real.h" |
| #include "rtl.h" |
| #include "expr.h" |
| #include "tm_p.h" |
| #include "toplev.h" |
| #include "ggc.h" |
| #include "hashtab.h" |
| #include "langhooks.h" |
| #include "md5.h" |
| |
| /* The following constants represent a bit based encoding of GCC's |
| comparison operators. This encoding simplifies transformations |
| on relational comparison operators, such as AND and OR. */ |
| enum comparison_code { |
| COMPCODE_FALSE = 0, |
| COMPCODE_LT = 1, |
| COMPCODE_EQ = 2, |
| COMPCODE_LE = 3, |
| COMPCODE_GT = 4, |
| COMPCODE_LTGT = 5, |
| COMPCODE_GE = 6, |
| COMPCODE_ORD = 7, |
| COMPCODE_UNORD = 8, |
| COMPCODE_UNLT = 9, |
| COMPCODE_UNEQ = 10, |
| COMPCODE_UNLE = 11, |
| COMPCODE_UNGT = 12, |
| COMPCODE_NE = 13, |
| COMPCODE_UNGE = 14, |
| 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); |
| static tree split_tree (tree, enum tree_code, tree *, tree *, tree *, int); |
| static tree associate_trees (tree, tree, enum tree_code, tree); |
| static tree const_binop (enum tree_code, tree, tree, int); |
| static enum tree_code invert_tree_comparison (enum tree_code, bool); |
| static enum comparison_code comparison_to_compcode (enum tree_code); |
| static enum tree_code compcode_to_comparison (enum comparison_code); |
| static tree combine_comparisons (enum tree_code, enum tree_code, |
| enum tree_code, tree, tree, tree); |
| static int truth_value_p (enum tree_code); |
| static int operand_equal_for_comparison_p (tree, tree, tree); |
| static int twoval_comparison_p (tree, tree *, tree *, int *); |
| static tree eval_subst (tree, tree, tree, tree, tree); |
| static tree pedantic_omit_one_operand (tree, tree, tree); |
| static tree distribute_bit_expr (enum tree_code, tree, tree, tree); |
| static tree make_bit_field_ref (tree, tree, int, int, int); |
| static tree optimize_bit_field_compare (enum tree_code, tree, tree, tree); |
| static tree decode_field_reference (tree, HOST_WIDE_INT *, HOST_WIDE_INT *, |
| enum machine_mode *, int *, int *, |
| tree *, tree *); |
| static int all_ones_mask_p (tree, int); |
| static tree sign_bit_p (tree, tree); |
| static int simple_operand_p (tree); |
| static tree range_binop (enum tree_code, tree, tree, int, tree, int); |
| static tree make_range (tree, int *, tree *, tree *); |
| static tree build_range_check (tree, tree, int, tree, tree); |
| static int merge_ranges (int *, tree *, tree *, int, tree, tree, int, tree, |
| tree); |
| static tree fold_range_test (tree); |
| static tree fold_cond_expr_with_comparison (tree, tree, tree, tree); |
| static tree unextend (tree, int, int, tree); |
| static tree fold_truthop (enum tree_code, tree, tree, tree); |
| static tree optimize_minmax_comparison (tree); |
| static tree extract_muldiv (tree, tree, enum tree_code, tree); |
| static tree extract_muldiv_1 (tree, tree, enum tree_code, tree); |
| static int multiple_of_p (tree, tree, tree); |
| static tree fold_binary_op_with_conditional_arg (tree, enum tree_code, |
| tree, tree, int); |
| static bool fold_real_zero_addition_p (tree, tree, int); |
| static tree fold_mathfn_compare (enum built_in_function, enum tree_code, |
| tree, tree, tree); |
| static tree fold_inf_compare (enum tree_code, tree, tree, tree); |
| static tree fold_div_compare (enum tree_code, tree, tree, tree); |
| static bool reorder_operands_p (tree, tree); |
| static tree fold_negate_const (tree, tree); |
| static tree fold_not_const (tree, tree); |
| static tree fold_relational_const (enum tree_code, tree, tree, tree); |
| static tree fold_relational_hi_lo (enum tree_code *, const tree, |
| tree *, tree *); |
| static bool tree_expr_nonzero_p (tree); |
| |
| /* 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. 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; |
| } |
| |
| /* T is an INT_CST node. 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 set TREE_CONSTANT_OVERFLOWED if, |
| CONST_OVERFLOWED is nonzero |
| or we set TREE_OVERFLOWED. |
| We return either the original T, or a copy. */ |
| |
| tree |
| force_fit_type (tree t, int overflowable, |
| bool overflowed, bool overflowed_const) |
| { |
| unsigned HOST_WIDE_INT low; |
| HOST_WIDE_INT high; |
| unsigned int prec; |
| int sign_extended_type; |
| |
| gcc_assert (TREE_CODE (t) == INTEGER_CST); |
| |
| low = TREE_INT_CST_LOW (t); |
| high = TREE_INT_CST_HIGH (t); |
| |
| if (POINTER_TYPE_P (TREE_TYPE (t)) |
| || TREE_CODE (TREE_TYPE (t)) == OFFSET_TYPE) |
| prec = POINTER_SIZE; |
| else |
| prec = TYPE_PRECISION (TREE_TYPE (t)); |
| /* Size types *are* sign extended. */ |
| sign_extended_type = (!TYPE_UNSIGNED (TREE_TYPE (t)) |
| || (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE |
| && TYPE_IS_SIZETYPE (TREE_TYPE (t)))); |
| |
| /* 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) |
| high &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT)); |
| else |
| { |
| high = 0; |
| if (prec < HOST_BITS_PER_WIDE_INT) |
| low &= ~((HOST_WIDE_INT) (-1) << prec); |
| } |
| |
| 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 (high & ((unsigned HOST_WIDE_INT)1 |
| << (prec - HOST_BITS_PER_WIDE_INT - 1))) |
| high |= (HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT); |
| } |
| else if (prec == HOST_BITS_PER_WIDE_INT) |
| { |
| if ((HOST_WIDE_INT)low < 0) |
| high = -1; |
| } |
| else |
| { |
| /* Sign extend bottom half? */ |
| if (low & ((unsigned HOST_WIDE_INT)1 << (prec - 1))) |
| { |
| high = -1; |
| low |= (HOST_WIDE_INT)(-1) << prec; |
| } |
| } |
| |
| /* If the value changed, return a new node. */ |
| if (overflowed || overflowed_const |
| || low != TREE_INT_CST_LOW (t) || high != TREE_INT_CST_HIGH (t)) |
| { |
| t = build_int_cst_wide (TREE_TYPE (t), low, high); |
| |
| if (overflowed |
| || overflowable < 0 |
| || (overflowable > 0 && sign_extended_type)) |
| { |
| t = copy_node (t); |
| TREE_OVERFLOW (t) = 1; |
| TREE_CONSTANT_OVERFLOW (t) = 1; |
| } |
| else if (overflowed_const) |
| { |
| t = copy_node (t); |
| TREE_CONSTANT_OVERFLOW (t) = 1; |
| } |
| } |
| |
| return t; |
| } |
| |
| /* Add two doubleword integers with doubleword result. |
| 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 (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) |
| { |
| unsigned HOST_WIDE_INT l; |
| HOST_WIDE_INT h; |
| |
| l = l1 + l2; |
| h = h1 + h2 + (l < l1); |
| |
| *lv = l; |
| *hv = h; |
| 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; |
| } |
| } |
| |
| /* Multiply two doubleword integers with doubleword result. |
| Return nonzero if the operation overflows, assuming it's signed. |
| 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 (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) |
| { |
| 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); /* This ignores prod[4] through prod[4*2-1] */ |
| |
| /* Check for overflow by calculating the top half of the answer in full; |
| it should agree with the low half's sign bit. */ |
| decode (prod + 4, &toplow, &tophigh); |
| 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; |
| } |
| |
| /* 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); |
| } |
| } |
| |
| /* 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; |
| } |
| |
| /* 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)) */ |
| 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; |
| } |
| |
| /* Return true if built-in mathematical function specified by CODE |
| preserves the sign of it argument, i.e. -f(x) == f(-x). */ |
| |
| static bool |
| negate_mathfn_p (enum built_in_function code) |
| { |
| switch (code) |
| { |
| case BUILT_IN_ASIN: |
| case BUILT_IN_ASINF: |
| case BUILT_IN_ASINL: |
| case BUILT_IN_ATAN: |
| case BUILT_IN_ATANF: |
| case BUILT_IN_ATANL: |
| case BUILT_IN_SIN: |
| case BUILT_IN_SINF: |
| case BUILT_IN_SINL: |
| case BUILT_IN_TAN: |
| case BUILT_IN_TANF: |
| case BUILT_IN_TANL: |
| return true; |
| |
| default: |
| break; |
| } |
| return false; |
| } |
| |
| /* Check whether we may negate an integer constant T without causing |
| overflow. */ |
| |
| bool |
| may_negate_without_overflow_p (tree t) |
| { |
| unsigned HOST_WIDE_INT val; |
| unsigned int prec; |
| tree type; |
| |
| gcc_assert (TREE_CODE (t) == INTEGER_CST); |
| |
| type = TREE_TYPE (t); |
| if (TYPE_UNSIGNED (type)) |
| return false; |
| |
| prec = TYPE_PRECISION (type); |
| if (prec > HOST_BITS_PER_WIDE_INT) |
| { |
| if (TREE_INT_CST_LOW (t) != 0) |
| return true; |
| prec -= HOST_BITS_PER_WIDE_INT; |
| val = TREE_INT_CST_HIGH (t); |
| } |
| else |
| val = TREE_INT_CST_LOW (t); |
| if (prec < HOST_BITS_PER_WIDE_INT) |
| val &= ((unsigned HOST_WIDE_INT) 1 << prec) - 1; |
| return val != ((unsigned HOST_WIDE_INT) 1 << (prec - 1)); |
| } |
| |
| /* Determine whether an expression T can be cheaply negated using |
| the function negate_expr. */ |
| |
| static bool |
| negate_expr_p (tree t) |
| { |
| tree type; |
| |
| if (t == 0) |
| return false; |
| |
| type = TREE_TYPE (t); |
| |
| STRIP_SIGN_NOPS (t); |
| switch (TREE_CODE (t)) |
| { |
| case INTEGER_CST: |
| if (TYPE_UNSIGNED (type) || ! flag_trapv) |
| return true; |
| |
| /* Check that -CST will not overflow type. */ |
| return may_negate_without_overflow_p (t); |
| |
| case REAL_CST: |
| case NEGATE_EXPR: |
| return true; |
| |
| case COMPLEX_CST: |
| return negate_expr_p (TREE_REALPART (t)) |
| && negate_expr_p (TREE_IMAGPART (t)); |
| |
| case PLUS_EXPR: |
| if (FLOAT_TYPE_P (type) && !flag_unsafe_math_optimizations) |
| return false; |
| /* -(A + B) -> (-B) - A. */ |
| if (negate_expr_p (TREE_OPERAND (t, 1)) |
| && reorder_operands_p (TREE_OPERAND (t, 0), |
| TREE_OPERAND (t, 1))) |
| return true; |
| /* -(A + B) -> (-A) - B. */ |
| return negate_expr_p (TREE_OPERAND (t, 0)); |
| |
| case MINUS_EXPR: |
| /* We can't turn -(A-B) into B-A when we honor signed zeros. */ |
| return (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations) |
| && reorder_operands_p (TREE_OPERAND (t, 0), |
| TREE_OPERAND (t, 1)); |
| |
| case MULT_EXPR: |
| if (TYPE_UNSIGNED (TREE_TYPE (t))) |
| break; |
| |
| /* Fall through. */ |
| |
| case RDIV_EXPR: |
| if (! HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (TREE_TYPE (t)))) |
| return negate_expr_p (TREE_OPERAND (t, 1)) |
| || negate_expr_p (TREE_OPERAND (t, 0)); |
| break; |
| |
| case NOP_EXPR: |
| /* Negate -((double)float) as (double)(-float). */ |
| if (TREE_CODE (type) == REAL_TYPE) |
| { |
| tree tem = strip_float_extensions (t); |
| if (tem != t) |
| return negate_expr_p (tem); |
| } |
| break; |
| |
| case CALL_EXPR: |
| /* Negate -f(x) as f(-x). */ |
| if (negate_mathfn_p (builtin_mathfn_code (t))) |
| return negate_expr_p (TREE_VALUE (TREE_OPERAND (t, 1))); |
| break; |
| |
| case RSHIFT_EXPR: |
| /* Optimize -((int)x >> 31) into (unsigned)x >> 31. */ |
| if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST) |
| { |
| tree op1 = TREE_OPERAND (t, 1); |
| if (TREE_INT_CST_HIGH (op1) == 0 |
| && (unsigned HOST_WIDE_INT) (TYPE_PRECISION (type) - 1) |
| == TREE_INT_CST_LOW (op1)) |
| return true; |
| } |
| break; |
| |
| default: |
| break; |
| } |
| return false; |
| } |
| |
| /* Given T, an expression, return the negation of T. Allow for T to be |
| null, in which case return null. */ |
| |
| static tree |
| negate_expr (tree t) |
| { |
| tree type; |
| tree tem; |
| |
| if (t == 0) |
| return 0; |
| |
| type = TREE_TYPE (t); |
| STRIP_SIGN_NOPS (t); |
| |
| switch (TREE_CODE (t)) |
| { |
| case INTEGER_CST: |
| tem = fold_negate_const (t, type); |
| if (! TREE_OVERFLOW (tem) |
| || TYPE_UNSIGNED (type) |
| || ! flag_trapv) |
| return tem; |
| break; |
| |
| case REAL_CST: |
| tem = fold_negate_const (t, type); |
| /* Two's complement FP formats, such as c4x, may overflow. */ |
| if (! TREE_OVERFLOW (tem) || ! flag_trapping_math) |
| return fold_convert (type, tem); |
| break; |
| |
| case COMPLEX_CST: |
| { |
| tree rpart = negate_expr (TREE_REALPART (t)); |
| tree ipart = negate_expr (TREE_IMAGPART (t)); |
| |
| if ((TREE_CODE (rpart) == REAL_CST |
| && TREE_CODE (ipart) == REAL_CST) |
| || (TREE_CODE (rpart) == INTEGER_CST |
| && TREE_CODE (ipart) == INTEGER_CST)) |
| return build_complex (type, rpart, ipart); |
| } |
| break; |
| |
| case NEGATE_EXPR: |
| return fold_convert (type, TREE_OPERAND (t, 0)); |
| |
| case PLUS_EXPR: |
| if (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations) |
| { |
| /* -(A + B) -> (-B) - A. */ |
| if (negate_expr_p (TREE_OPERAND (t, 1)) |
| && reorder_operands_p (TREE_OPERAND (t, 0), |
| TREE_OPERAND (t, 1))) |
| { |
| tem = negate_expr (TREE_OPERAND (t, 1)); |
| tem = fold (build2 (MINUS_EXPR, TREE_TYPE (t), |
| tem, TREE_OPERAND (t, 0))); |
| return fold_convert (type, tem); |
| } |
| |
| /* -(A + B) -> (-A) - B. */ |
| if (negate_expr_p (TREE_OPERAND (t, 0))) |
| { |
| tem = negate_expr (TREE_OPERAND (t, 0)); |
| tem = fold (build2 (MINUS_EXPR, TREE_TYPE (t), |
| tem, TREE_OPERAND (t, 1))); |
| return fold_convert (type, tem); |
| } |
| } |
| break; |
| |
| case MINUS_EXPR: |
| /* - (A - B) -> B - A */ |
| if ((! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations) |
| && reorder_operands_p (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1))) |
| return fold_convert (type, |
| fold (build2 (MINUS_EXPR, TREE_TYPE (t), |
| TREE_OPERAND (t, 1), |
| TREE_OPERAND (t, 0)))); |
| break; |
| |
| case MULT_EXPR: |
| if (TYPE_UNSIGNED (TREE_TYPE (t))) |
| break; |
| |
| /* Fall through. */ |
| |
| case RDIV_EXPR: |
| if (! HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (TREE_TYPE (t)))) |
| { |
| tem = TREE_OPERAND (t, 1); |
| if (negate_expr_p (tem)) |
| return fold_convert (type, |
| fold (build2 (TREE_CODE (t), TREE_TYPE (t), |
| TREE_OPERAND (t, 0), |
| negate_expr (tem)))); |
| tem = TREE_OPERAND (t, 0); |
| if (negate_expr_p (tem)) |
| return fold_convert (type, |
| fold (build2 (TREE_CODE (t), TREE_TYPE (t), |
| negate_expr (tem), |
| TREE_OPERAND (t, 1)))); |
| } |
| break; |
| |
| case NOP_EXPR: |
| /* Convert -((double)float) into (double)(-float). */ |
| if (TREE_CODE (type) == REAL_TYPE) |
| { |
| tem = strip_float_extensions (t); |
| if (tem != t && negate_expr_p (tem)) |
| return fold_convert (type, negate_expr (tem)); |
| } |
| break; |
| |
| case CALL_EXPR: |
| /* Negate -f(x) as f(-x). */ |
| if (negate_mathfn_p (builtin_mathfn_code (t)) |
| && negate_expr_p (TREE_VALUE (TREE_OPERAND (t, 1)))) |
| { |
| tree fndecl, arg, arglist; |
| |
| fndecl = get_callee_fndecl (t); |
| arg = negate_expr (TREE_VALUE (TREE_OPERAND (t, 1))); |
| arglist = build_tree_list (NULL_TREE, arg); |
| return build_function_call_expr (fndecl, arglist); |
| } |
| break; |
| |
| case RSHIFT_EXPR: |
| /* Optimize -((int)x >> 31) into (unsigned)x >> 31. */ |
| if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST) |
| { |
| tree op1 = TREE_OPERAND (t, 1); |
| if (TREE_INT_CST_HIGH (op1) == 0 |
| && (unsigned HOST_WIDE_INT) (TYPE_PRECISION (type) - 1) |
| == TREE_INT_CST_LOW (op1)) |
| { |
| tree ntype = TYPE_UNSIGNED (type) |
| ? lang_hooks.types.signed_type (type) |
| : lang_hooks.types.unsigned_type (type); |
| tree temp = fold_convert (ntype, TREE_OPERAND (t, 0)); |
| temp = fold (build2 (RSHIFT_EXPR, ntype, temp, op1)); |
| return fold_convert (type, temp); |
| } |
| } |
| break; |
| |
| default: |
| break; |
| } |
| |
| tem = fold (build1 (NEGATE_EXPR, TREE_TYPE (t), t)); |
| return fold_convert (type, tem); |
| } |
| |
| /* Split a tree IN into a constant, literal and variable parts that could be |
| combined with CODE to make IN. "constant" means an expression with |
| TREE_CONSTANT but that isn't an actual constant. CODE must be a |
| commutative arithmetic operation. Store the constant part into *CONP, |
| the literal in *LITP and return the variable part. If a part isn't |
| present, set it to null. If the tree does not decompose in this way, |
| return the entire tree as the variable part and the other parts as null. |
| |
| If CODE is PLUS_EXPR we also split trees that use MINUS_EXPR. In that |
| case, we negate an operand that was subtracted. Except if it is a |
| literal for which we use *MINUS_LITP instead. |
| |
| If NEGATE_P is true, we are negating all of IN, again except a literal |
| for which we use *MINUS_LITP instead. |
| |
| If IN is itself a literal or constant, return it as appropriate. |
| |
| Note that we do not guarantee that any of the three values will be the |
| same type as IN, but they will have the same signedness and mode. */ |
| |
| static tree |
| split_tree (tree in, enum tree_code code, tree *conp, tree *litp, |
| tree *minus_litp, int negate_p) |
| { |
| tree var = 0; |
| |
| *conp = 0; |
| *litp = 0; |
| *minus_litp = 0; |
| |
| /* Strip any conversions that don't change the machine mode or signedness. */ |
| STRIP_SIGN_NOPS (in); |
| |
| if (TREE_CODE (in) == INTEGER_CST || TREE_CODE (in) == REAL_CST) |
| *litp = in; |
| else if (TREE_CODE (in) == code |
| || (! FLOAT_TYPE_P (TREE_TYPE (in)) |
| /* We can associate addition and subtraction together (even |
| though the C standard doesn't say so) for integers because |
| the value is not affected. For reals, the value might be |
| affected, so we can't. */ |
| && ((code == PLUS_EXPR && TREE_CODE (in) == MINUS_EXPR) |
| || (code == MINUS_EXPR && TREE_CODE (in) == PLUS_EXPR)))) |
| { |
| tree op0 = TREE_OPERAND (in, 0); |
| tree op1 = TREE_OPERAND (in, 1); |
| int neg1_p = TREE_CODE (in) == MINUS_EXPR; |
| int neg_litp_p = 0, neg_conp_p = 0, neg_var_p = 0; |
| |
| /* First see if either of the operands is a literal, then a constant. */ |
| if (TREE_CODE (op0) == INTEGER_CST || TREE_CODE (op0) == REAL_CST) |
| *litp = op0, op0 = 0; |
| else if (TREE_CODE (op1) == INTEGER_CST || TREE_CODE (op1) == REAL_CST) |
| *litp = op1, neg_litp_p = neg1_p, op1 = 0; |
| |
| if (op0 != 0 && TREE_CONSTANT (op0)) |
| *conp = op0, op0 = 0; |
| else if (op1 != 0 && TREE_CONSTANT (op1)) |
| *conp = op1, neg_conp_p = neg1_p, op1 = 0; |
| |
| /* If we haven't dealt with either operand, this is not a case we can |
| decompose. Otherwise, VAR is either of the ones remaining, if any. */ |
| if (op0 != 0 && op1 != 0) |
| var = in; |
| else if (op0 != 0) |
| var = op0; |
| else |
| var = op1, neg_var_p = neg1_p; |
| |
| /* Now do any needed negations. */ |
| if (neg_litp_p) |
| *minus_litp = *litp, *litp = 0; |
| if (neg_conp_p) |
| *conp = negate_expr (*conp); |
| if (neg_var_p) |
| var = negate_expr (var); |
| } |
| else if (TREE_CONSTANT (in)) |
| *conp = in; |
| else |
| var = in; |
| |
| if (negate_p) |
| { |
| if (*litp) |
| *minus_litp = *litp, *litp = 0; |
| else if (*minus_litp) |
| *litp = *minus_litp, *minus_litp = 0; |
| *conp = negate_expr (*conp); |
| var = negate_expr (var); |
| } |
| |
| return var; |
| } |
| |
| /* Re-associate trees split by the above function. T1 and T2 are either |
| expressions to associate or null. Return the new expression, if any. If |
| we build an operation, do it in TYPE and with CODE. */ |
| |
| static tree |
| associate_trees (tree t1, tree t2, enum tree_code code, tree type) |
| { |
| if (t1 == 0) |
| return t2; |
| else if (t2 == 0) |
| return t1; |
| |
| /* If either input is CODE, a PLUS_EXPR, or a MINUS_EXPR, don't |
| try to fold this since we will have infinite recursion. But do |
| deal with any NEGATE_EXPRs. */ |
| if (TREE_CODE (t1) == code || TREE_CODE (t2) == code |
| || TREE_CODE (t1) == MINUS_EXPR || TREE_CODE (t2) == MINUS_EXPR) |
| { |
| if (code == PLUS_EXPR) |
| { |
| if (TREE_CODE (t1) == NEGATE_EXPR) |
| return build2 (MINUS_EXPR, type, fold_convert (type, t2), |
| fold_convert (type, TREE_OPERAND (t1, 0))); |
| else if (TREE_CODE (t2) == NEGATE_EXPR) |
| return build2 (MINUS_EXPR, type, fold_convert (type, t1), |
| fold_convert (type, TREE_OPERAND (t2, 0))); |
| else if (integer_zerop (t2)) |
| return fold_convert (type, t1); |
| } |
| else if (code == MINUS_EXPR) |
| { |
| if (integer_zerop (t2)) |
| return fold_convert (type, t1); |
| } |
| |
| return build2 (code, type, fold_convert (type, t1), |
| fold_convert (type, t2)); |
| } |
| |
| return fold (build2 (code, type, fold_convert (type, t1), |
| fold_convert (type, t2))); |
| } |
| |
| /* Combine two integer constants ARG1 and ARG2 under operation CODE |
| to produce a new constant. |
| |
| If NOTRUNC is nonzero, do not truncate the result to fit the data type. */ |
| |
| tree |
| int_const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc) |
| { |
| unsigned HOST_WIDE_INT int1l, int2l; |
| HOST_WIDE_INT int1h, int2h; |
| unsigned HOST_WIDE_INT low; |
| HOST_WIDE_INT hi; |
| unsigned HOST_WIDE_INT garbagel; |
| HOST_WIDE_INT garbageh; |
| tree t; |
| tree type = TREE_TYPE (arg1); |
| int uns = TYPE_UNSIGNED (type); |
| int is_sizetype |
| = (TREE_CODE (type) == INTEGER_TYPE && TYPE_IS_SIZETYPE (type)); |
| int overflow = 0; |
| int no_overflow = 0; |
| |
| int1l = TREE_INT_CST_LOW (arg1); |
| int1h = TREE_INT_CST_HIGH (arg1); |
| int2l = TREE_INT_CST_LOW (arg2); |
| int2h = TREE_INT_CST_HIGH (arg2); |
| |
| switch (code) |
| { |
| case BIT_IOR_EXPR: |
| low = int1l | int2l, hi = int1h | int2h; |
| break; |
| |
| case BIT_XOR_EXPR: |
| low = int1l ^ int2l, hi = int1h ^ int2h; |
| break; |
| |
| case BIT_AND_EXPR: |
| low = int1l & int2l, hi = int1h & int2h; |
| break; |
| |
| case RSHIFT_EXPR: |
| int2l = -int2l; |
| case LSHIFT_EXPR: |
| /* It's unclear from the C standard whether shifts can overflow. |
| The following code ignores overflow; perhaps a C standard |
| interpretation ruling is needed. */ |
| lshift_double (int1l, int1h, int2l, TYPE_PRECISION (type), |
| &low, &hi, !uns); |
| no_overflow = 1; |
| break; |
| |
| case RROTATE_EXPR: |
| int2l = - int2l; |
| case LROTATE_EXPR: |
| lrotate_double (int1l, int1h, int2l, TYPE_PRECISION (type), |
| &low, &hi); |
| break; |
| |
| case PLUS_EXPR: |
| overflow = add_double (int1l, int1h, int2l, int2h, &low, &hi); |
| break; |
| |
| case MINUS_EXPR: |
| neg_double (int2l, int2h, &low, &hi); |
| add_double (int1l, int1h, low, hi, &low, &hi); |
| overflow = OVERFLOW_SUM_SIGN (hi, int2h, int1h); |
| break; |
| |
| case MULT_EXPR: |
| overflow = mul_double (int1l, int1h, int2l, int2h, &low, &hi); |
| break; |
| |
| case TRUNC_DIV_EXPR: |
| case FLOOR_DIV_EXPR: case CEIL_DIV_EXPR: |
| case EXACT_DIV_EXPR: |
| /* This is a shortcut for a common special case. */ |
| if (int2h == 0 && (HOST_WIDE_INT) int2l > 0 |
| && ! TREE_CONSTANT_OVERFLOW (arg1) |
| && ! TREE_CONSTANT_OVERFLOW (arg2) |
| && int1h == 0 && (HOST_WIDE_INT) int1l >= 0) |
| { |
| if (code == CEIL_DIV_EXPR) |
| int1l += int2l - 1; |
| |
| low = int1l / int2l, hi = 0; |
| break; |
| } |
| |
| /* ... fall through ... */ |
| |
| case ROUND_DIV_EXPR: |
| if (int2h == 0 && int2l == 1) |
| { |
| low = int1l, hi = int1h; |
| break; |
| } |
| if (int1l == int2l && int1h == int2h |
| && ! (int1l == 0 && int1h == 0)) |
| { |
| low = 1, hi = 0; |
| break; |
| } |
| overflow = div_and_round_double (code, uns, int1l, int1h, int2l, int2h, |
| &low, &hi, &garbagel, &garbageh); |
| break; |
| |
| case TRUNC_MOD_EXPR: |
| case FLOOR_MOD_EXPR: case CEIL_MOD_EXPR: |
| /* This is a shortcut for a common special case. */ |
| if (int2h == 0 && (HOST_WIDE_INT) int2l > 0 |
| && ! TREE_CONSTANT_OVERFLOW (arg1) |
| && ! TREE_CONSTANT_OVERFLOW (arg2) |
| && int1h == 0 && (HOST_WIDE_INT) int1l >= 0) |
| { |
| if (code == CEIL_MOD_EXPR) |
| int1l += int2l - 1; |
| low = int1l % int2l, hi = 0; |
| break; |
| } |
| |
| /* ... fall through ... */ |
| |
| case ROUND_MOD_EXPR: |
| overflow = div_and_round_double (code, uns, |
| int1l, int1h, int2l, int2h, |
| &garbagel, &garbageh, &low, &hi); |
| break; |
| |
| 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) |
| && int1l < int2l)); |
| else |
| low = (int1h < int2h |
| || (int1h == int2h && int1l < int2l)); |
| |
| if (low == (code == MIN_EXPR)) |
| low = int1l, hi = int1h; |
| else |
| low = int2l, hi = int2h; |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| t = build_int_cst_wide (TREE_TYPE (arg1), low, hi); |
| |
| if (notrunc) |
| { |
| /* Propagate overflow flags ourselves. */ |
| if (((!uns || is_sizetype) && overflow) |
| | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2)) |
| { |
| t = copy_node (t); |
| TREE_OVERFLOW (t) = 1; |
| TREE_CONSTANT_OVERFLOW (t) = 1; |
| } |
| else if (TREE_CONSTANT_OVERFLOW (arg1) | TREE_CONSTANT_OVERFLOW (arg2)) |
| { |
| t = copy_node (t); |
| TREE_CONSTANT_OVERFLOW (t) = 1; |
| } |
| } |
| else |
| t = force_fit_type (t, 1, |
| ((!uns || is_sizetype) && overflow) |
| | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2), |
| TREE_CONSTANT_OVERFLOW (arg1) |
| | TREE_CONSTANT_OVERFLOW (arg2)); |
| |
| return t; |
| } |
| |
| /* 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. */ |
| |
| static tree |
| const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc) |
| { |
| STRIP_NOPS (arg1); |
| STRIP_NOPS (arg2); |
| |
| if (TREE_CODE (arg1) == INTEGER_CST) |
| return int_const_binop (code, arg1, arg2, notrunc); |
| |
| if (TREE_CODE (arg1) == REAL_CST) |
| { |
| enum machine_mode mode; |
| REAL_VALUE_TYPE d1; |
| REAL_VALUE_TYPE d2; |
| REAL_VALUE_TYPE value; |
| REAL_VALUE_TYPE result; |
| bool inexact; |
| tree t, type; |
| |
| d1 = TREE_REAL_CST (arg1); |
| d2 = TREE_REAL_CST (arg2); |
| |
| type = TREE_TYPE (arg1); |
| mode = TYPE_MODE (type); |
| |
| /* Don't perform operation if we honor signaling NaNs and |
| either operand is a NaN. */ |
| if (HONOR_SNANS (mode) |
| && (REAL_VALUE_ISNAN (d1) || REAL_VALUE_ISNAN (d2))) |
| return NULL_TREE; |
| |
| /* Don't perform operation if it would raise a division |
| by zero exception. */ |
| if (code == RDIV_EXPR |
| && REAL_VALUES_EQUAL (d2, dconst0) |
| && (flag_trapping_math || ! MODE_HAS_INFINITIES (mode))) |
| return NULL_TREE; |
| |
| /* If either operand is a NaN, just return it. Otherwise, set up |
| for floating-point trap; we return an overflow. */ |
| if (REAL_VALUE_ISNAN (d1)) |
| return arg1; |
| else if (REAL_VALUE_ISNAN (d2)) |
| return arg2; |
| |
| inexact = real_arithmetic (&value, code, &d1, &d2); |
| real_convert (&result, mode, &value); |
| |
| /* Don't constant fold this floating point operation if the |
| result may dependent upon the run-time rounding mode and |
| flag_rounding_math is set, or if GCC's software emulation |
| is unable to accurately represent the result. */ |
| |
| if ((flag_rounding_math |
| || (REAL_MODE_FORMAT_COMPOSITE_P (mode) |
| && !flag_unsafe_math_optimizations)) |
| && (inexact || !real_identical (&result, &value))) |
| return NULL_TREE; |
| |
| t = build_real (type, result); |
| |
| TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2); |
| TREE_CONSTANT_OVERFLOW (t) |
| = TREE_OVERFLOW (t) |
| | TREE_CONSTANT_OVERFLOW (arg1) |
| | TREE_CONSTANT_OVERFLOW (arg2); |
| return t; |
| } |
| if (TREE_CODE (arg1) == COMPLEX_CST) |
| { |
| tree type = TREE_TYPE (arg1); |
| tree r1 = TREE_REALPART (arg1); |
| tree i1 = TREE_IMAGPART (arg1); |
| tree r2 = TREE_REALPART (arg2); |
| tree i2 = TREE_IMAGPART (arg2); |
| tree t; |
| |
| switch (code) |
| { |
| case PLUS_EXPR: |
| t = build_complex (type, |
| const_binop (PLUS_EXPR, r1, r2, notrunc), |
| const_binop (PLUS_EXPR, i1, i2, notrunc)); |
| break; |
| |
| case MINUS_EXPR: |
| t = build_complex (type, |
| const_binop (MINUS_EXPR, r1, r2, notrunc), |
| const_binop (MINUS_EXPR, i1, i2, notrunc)); |
| break; |
| |
| case MULT_EXPR: |
| t = build_complex (type, |
| const_binop (MINUS_EXPR, |
| const_binop (MULT_EXPR, |
| r1, r2, notrunc), |
| const_binop (MULT_EXPR, |
| i1, i2, notrunc), |
| notrunc), |
| const_binop (PLUS_EXPR, |
| const_binop (MULT_EXPR, |
| r1, i2, notrunc), |
| const_binop (MULT_EXPR, |
| i1, r2, notrunc), |
| notrunc)); |
| break; |
| |
| case RDIV_EXPR: |
| { |
| tree magsquared |
| = const_binop (PLUS_EXPR, |
| const_binop (MULT_EXPR, r2, r2, notrunc), |
| const_binop (MULT_EXPR, i2, i2, notrunc), |
| notrunc); |
| |
| t = build_complex (type, |
| const_binop |
| (INTEGRAL_TYPE_P (TREE_TYPE (r1)) |
| ? TRUNC_DIV_EXPR : RDIV_EXPR, |
| const_binop (PLUS_EXPR, |
| const_binop (MULT_EXPR, r1, r2, |
| notrunc), |
| const_binop (MULT_EXPR, i1, i2, |
| notrunc), |
| notrunc), |
| magsquared, notrunc), |
| const_binop |
| (INTEGRAL_TYPE_P (TREE_TYPE (r1)) |
| ? TRUNC_DIV_EXPR : RDIV_EXPR, |
| const_binop (MINUS_EXPR, |
| const_binop (MULT_EXPR, i1, r2, |
| notrunc), |
| const_binop (MULT_EXPR, r1, i2, |
| notrunc), |
| notrunc), |
| magsquared, notrunc)); |
| } |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| return t; |
| } |
| return 0; |
| } |
| |
| /* Create a size type INT_CST node with NUMBER sign extended. KIND |
| indicates which particular sizetype to create. */ |
| |
| tree |
| size_int_kind (HOST_WIDE_INT number, enum size_type_kind kind) |
| { |
| return build_int_cst (sizetype_tab[(int) kind], number); |
| } |
| |
| /* Combine operands OP1 and OP2 with arithmetic operation CODE. CODE |
| is a tree code. The type of the result is taken from the operands. |
| Both must be the same type integer type and it must be a size type. |
| If the operands are constant, so is the result. */ |
| |
| tree |
| size_binop (enum tree_code code, tree arg0, tree arg1) |
| { |
| tree type = TREE_TYPE (arg0); |
| |
| gcc_assert (TREE_CODE (type) == INTEGER_TYPE && TYPE_IS_SIZETYPE (type) |
| && type == TREE_TYPE (arg1)); |
| |
| /* Handle the special case of two integer constants faster. */ |
| if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST) |
| { |
| /* And some specific cases even faster than that. */ |
| if (code == PLUS_EXPR && integer_zerop (arg0)) |
| return arg1; |
| else if ((code == MINUS_EXPR || code == PLUS_EXPR) |
| && integer_zerop (arg1)) |
| return arg0; |
| else if (code == MULT_EXPR && integer_onep (arg0)) |
| return arg1; |
| |
| /* Handle general case of two integer constants. */ |
| return int_const_binop (code, arg0, arg1, 0); |
| } |
| |
| if (arg0 == error_mark_node || arg1 == error_mark_node) |
| return error_mark_node; |
| |
| return fold (build2 (code, type, arg0, arg1)); |
| } |
| |
| /* Given two values, either both of sizetype or both of bitsizetype, |
| compute the difference between the two values. Return the value |
| in signed type corresponding to the type of the operands. */ |
| |
| tree |
| size_diffop (tree arg0, tree arg1) |
| { |
| tree type = TREE_TYPE (arg0); |
| tree ctype; |
| |
| gcc_assert (TREE_CODE (type) == INTEGER_TYPE && TYPE_IS_SIZETYPE (type) |
| && type == TREE_TYPE (arg1)); |
| |
| /* If the type is already signed, just do the simple thing. */ |
| if (!TYPE_UNSIGNED (type)) |
| return size_binop (MINUS_EXPR, arg0, arg1); |
| |
| ctype = type == bitsizetype ? sbitsizetype : ssizetype; |
| |
| /* If either operand is not a constant, do the conversions to the signed |
| type and subtract. The hardware will do the right thing with any |
| overflow in the subtraction. */ |
| if (TREE_CODE (arg0) != INTEGER_CST || TREE_CODE (arg1) != INTEGER_CST) |
| return size_binop (MINUS_EXPR, fold_convert (ctype, arg0), |
| fold_convert (ctype, arg1)); |
| |
| /* If ARG0 is larger than ARG1, subtract and return the result in CTYPE. |
| Otherwise, subtract the other way, convert to CTYPE (we know that can't |
| overflow) and negate (which can't either). Special-case a result |
| of zero while we're here. */ |
| if (tree_int_cst_equal (arg0, arg1)) |
| return fold_convert (ctype, integer_zero_node); |
| else if (tree_int_cst_lt (arg1, arg0)) |
| return fold_convert (ctype, size_binop (MINUS_EXPR, arg0, arg1)); |
| else |
| return size_binop (MINUS_EXPR, fold_convert (ctype, integer_zero_node), |
| fold_convert (ctype, size_binop (MINUS_EXPR, |
| arg1, arg0))); |
| } |
| |
| /* A subroutine of fold_convert_const handling conversions of an |
| INTEGER_CST to another integer type. */ |
| |
| static tree |
| fold_convert_const_int_from_int (tree type, tree arg1) |
| { |
| tree t; |
| |
| /* Given an integer constant, make new constant with new type, |
| appropriately sign-extended or truncated. */ |
| t = build_int_cst_wide (type, TREE_INT_CST_LOW (arg1), |
| TREE_INT_CST_HIGH (arg1)); |
| |
| t = force_fit_type (t, |
| /* Don't set the overflow when |
| converting a pointer */ |
| !POINTER_TYPE_P (TREE_TYPE (arg1)), |
| (TREE_INT_CST_HIGH (arg1) < 0 |
| && (TYPE_UNSIGNED (type) |
| < TYPE_UNSIGNED (TREE_TYPE (arg1)))) |
| | TREE_OVERFLOW (arg1), |
| TREE_CONSTANT_OVERFLOW (arg1)); |
| |
| return t; |
| } |
| |
| /* A subroutine of fold_convert_const handling conversions a REAL_CST |
| to an integer type. */ |
| |
| static tree |
| fold_convert_const_int_from_real (enum tree_code code, tree type, tree arg1) |
| { |
| int overflow = 0; |
| tree t; |
| |
| /* The following code implements the floating point to integer |
| conversion rules required by the Java Language Specification, |
| that IEEE NaNs are mapped to zero and values that overflow |
| the target precision saturate, i.e. values greater than |
| INT_MAX are mapped to INT_MAX, and values less than INT_MIN |
| are mapped to INT_MIN. These semantics are allowed by the |
| C and C++ standards that simply state that the behavior of |
| FP-to-integer conversion is unspecified upon overflow. */ |
| |
| HOST_WIDE_INT high, low; |
| REAL_VALUE_TYPE r; |
| REAL_VALUE_TYPE x = TREE_REAL_CST (arg1); |
| |
| switch (code) |
| { |
| case FIX_TRUNC_EXPR: |
| real_trunc (&r, VOIDmode, &x); |
| break; |
| |
| case FIX_CEIL_EXPR: |
| real_ceil (&r, VOIDmode, &x); |
| break; |
| |
| case FIX_FLOOR_EXPR: |
| real_floor (&r, VOIDmode, &x); |
| break; |
| |
| case FIX_ROUND_EXPR: |
| real_round (&r, VOIDmode, &x); |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| /* If R is NaN, return zero and show we have an overflow. */ |
| if (REAL_VALUE_ISNAN (r)) |
| { |
| overflow = 1; |
| high = 0; |
| low = 0; |
| } |
| |
| /* See if R is less than the lower bound or greater than the |
| upper bound. */ |
| |
| if (! overflow) |
| { |
| tree lt = TYPE_MIN_VALUE (type); |
| REAL_VALUE_TYPE l = real_value_from_int_cst (NULL_TREE, lt); |
| if (REAL_VALUES_LESS (r, l)) |
| { |
| overflow = 1; |
| high = TREE_INT_CST_HIGH (lt); |
| low = TREE_INT_CST_LOW (lt); |
| } |
| } |
| |
| if (! overflow) |
| { |
| tree ut = TYPE_MAX_VALUE (type); |
| if (ut) |
| { |
| REAL_VALUE_TYPE u = real_value_from_int_cst (NULL_TREE, ut); |
| if (REAL_VALUES_LESS (u, r)) |
| { |
| overflow = 1; |
| high = TREE_INT_CST_HIGH (ut); |
| low = TREE_INT_CST_LOW (ut); |
| } |
| } |
| } |
| |
| if (! overflow) |
| REAL_VALUE_TO_INT (&low, &high, r); |
| |
| t = build_int_cst_wide (type, low, high); |
| |
| t = force_fit_type (t, -1, overflow | TREE_OVERFLOW (arg1), |
| TREE_CONSTANT_OVERFLOW (arg1)); |
| return t; |
| } |
| |
| /* A subroutine of fold_convert_const handling conversions a REAL_CST |
| to another floating point type. */ |
| |
| static tree |
| fold_convert_const_real_from_real (tree type, tree arg1) |
| { |
| REAL_VALUE_TYPE value; |
| tree t; |
| |
| real_convert (&value, TYPE_MODE (type), &TREE_REAL_CST (arg1)); |
| t = build_real (type, value); |
| |
| TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1); |
| TREE_CONSTANT_OVERFLOW (t) |
| = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1); |
| return t; |
| } |
| |
| /* Attempt to fold type conversion operation CODE of expression ARG1 to |
| type TYPE. If no simplification can be done return NULL_TREE. */ |
| |
| static tree |
| fold_convert_const (enum tree_code code, tree type, tree arg1) |
| { |
| if (TREE_TYPE (arg1) == type) |
| return arg1; |
| |
| if (POINTER_TYPE_P (type) || INTEGRAL_TYPE_P (type)) |
| { |
| if (TREE_CODE (arg1) == INTEGER_CST) |
| return fold_convert_const_int_from_int (type, arg1); |
| else if (TREE_CODE (arg1) == REAL_CST) |
| return fold_convert_const_int_from_real (code, type, arg1); |
| } |
| else if (TREE_CODE (type) == REAL_TYPE) |
| { |
| if (TREE_CODE (arg1) == INTEGER_CST) |
| return build_real_from_int_cst (type, arg1); |
| if (TREE_CODE (arg1) == REAL_CST) |
| return fold_convert_const_real_from_real (type, arg1); |
| } |
| return NULL_TREE; |
| } |
| |
| /* Construct a vector of zero elements of vector type TYPE. */ |
| |
| static tree |
| build_zero_vector (tree type) |
| { |
| tree elem, list; |
| int i, units; |
| |
| elem = fold_convert_const (NOP_EXPR, TREE_TYPE (type), integer_zero_node); |
| units = TYPE_VECTOR_SUBPARTS (type); |
| |
| list = NULL_TREE; |
| for (i = 0; i < units; i++) |
| list = tree_cons (NULL_TREE, elem, list); |
| return build_vector (type, list); |
| } |
| |
| /* Convert expression ARG to type TYPE. Used by the middle-end for |
| simple conversions in preference to calling the front-end's convert. */ |
| |
| tree |
| fold_convert (tree type, tree arg) |
| { |
| tree orig = TREE_TYPE (arg); |
| tree tem; |
| |
| if (type == orig) |
| return arg; |
| |
| if (TREE_CODE (arg) == ERROR_MARK |
| || TREE_CODE (type) == ERROR_MARK |
| || TREE_CODE (orig) == ERROR_MARK) |
| return error_mark_node; |
| |
| if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (orig) |
| || lang_hooks.types_compatible_p (TYPE_MAIN_VARIANT (type), |
| TYPE_MAIN_VARIANT (orig))) |
| return fold (build1 (NOP_EXPR, type, arg)); |
| |
| switch (TREE_CODE (type)) |
| { |
| case INTEGER_TYPE: case CHAR_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: |
| case POINTER_TYPE: case REFERENCE_TYPE: |
| case OFFSET_TYPE: |
| if (TREE_CODE (arg) == INTEGER_CST) |
| { |
| tem = fold_convert_const (NOP_EXPR, type, arg); |
| if (tem != NULL_TREE) |
| return tem; |
| } |
| if (INTEGRAL_TYPE_P (orig) || POINTER_TYPE_P (orig) |
| || TREE_CODE (orig) == OFFSET_TYPE) |
| return fold (build1 (NOP_EXPR, type, arg)); |
| if (TREE_CODE (orig) == COMPLEX_TYPE) |
| { |
| tem = fold (build1 (REALPART_EXPR, TREE_TYPE (orig), arg)); |
| return fold_convert (type, tem); |
| } |
| gcc_assert (TREE_CODE (orig) == VECTOR_TYPE |
| && tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (orig))); |
| return fold (build1 (NOP_EXPR, type, arg)); |
| |
| case REAL_TYPE: |
| if (TREE_CODE (arg) == INTEGER_CST) |
| { |
| tem = fold_convert_const (FLOAT_EXPR, type, arg); |
| if (tem != NULL_TREE) |
| return tem; |
| } |
| else if (TREE_CODE (arg) == REAL_CST) |
| { |
| tem = fold_convert_const (NOP_EXPR, type, arg); |
| if (tem != NULL_TREE) |
| return tem; |
| } |
| |
| switch (TREE_CODE (orig)) |
| { |
| case INTEGER_TYPE: case CHAR_TYPE: |
| case BOOLEAN_TYPE: case ENUMERAL_TYPE: |
| case POINTER_TYPE: case REFERENCE_TYPE: |
| return fold (build1 (FLOAT_EXPR, type, arg)); |
| |
| case REAL_TYPE: |
| return fold (build1 (flag_float_store ? CONVERT_EXPR : NOP_EXPR, |
| type, arg)); |
| |
| case COMPLEX_TYPE: |
| tem = fold (build1 (REALPART_EXPR, TREE_TYPE (orig), arg)); |
| return fold_convert (type, tem); |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| case COMPLEX_TYPE: |
| switch (TREE_CODE (orig)) |
| { |
| case INTEGER_TYPE: case CHAR_TYPE: |
| case BOOLEAN_TYPE: case ENUMERAL_TYPE: |
| case POINTER_TYPE: case REFERENCE_TYPE: |
| case REAL_TYPE: |
| return build2 (COMPLEX_EXPR, type, |
| fold_convert (TREE_TYPE (type), arg), |
| fold_convert (TREE_TYPE (type), integer_zero_node)); |
| case COMPLEX_TYPE: |
| { |
| tree rpart, ipart; |
| |
| if (TREE_CODE (arg) == COMPLEX_EXPR) |
| { |
| rpart = fold_convert (TREE_TYPE (type), TREE_OPERAND (arg, 0)); |
| ipart = fold_convert (TREE_TYPE (type), TREE_OPERAND (arg, 1)); |
| return fold (build2 (COMPLEX_EXPR, type, rpart, ipart)); |
| } |
| |
| arg = save_expr (arg); |
| rpart = fold (build1 (REALPART_EXPR, TREE_TYPE (orig), arg)); |
| ipart = fold (build1 (IMAGPART_EXPR, TREE_TYPE (orig), arg)); |
| rpart = fold_convert (TREE_TYPE (type), rpart); |
| ipart = fold_convert (TREE_TYPE (type), ipart); |
| return fold (build2 (COMPLEX_EXPR, type, rpart, ipart)); |
| } |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| case VECTOR_TYPE: |
| if (integer_zerop (arg)) |
| return build_zero_vector (type); |
| gcc_assert (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (orig))); |
| gcc_assert (INTEGRAL_TYPE_P (orig) || POINTER_TYPE_P (orig) |
| || TREE_CODE (orig) == VECTOR_TYPE); |
| /* APPLE LOCAL mainline 4.0.2 4043818 */ |
| return fold (build1 (VIEW_CONVERT_EXPR, type, arg)); |
| |
| case VOID_TYPE: |
| return fold (build1 (CONVERT_EXPR, type, fold_ignored_result (arg))); |
| |
| default: |
| gcc_unreachable (); |
| } |
| } |
| |
| /* Return false if expr can be assumed not to be an value, true |
| otherwise. */ |
| |
| static bool |
| maybe_lvalue_p (tree x) |
| { |
| /* We only need to wrap lvalue tree codes. */ |
| switch (TREE_CODE (x)) |
| { |
| case VAR_DECL: |
| case PARM_DECL: |
| case RESULT_DECL: |
| case LABEL_DECL: |
| case FUNCTION_DECL: |
| case SSA_NAME: |
| |
| case COMPONENT_REF: |
| case INDIRECT_REF: |
| case ALIGN_INDIRECT_REF: |
| case MISALIGNED_INDIRECT_REF: |
| case ARRAY_REF: |
| case ARRAY_RANGE_REF: |
| case BIT_FIELD_REF: |
| case OBJ_TYPE_REF: |
| |
| case REALPART_EXPR: |
| case IMAGPART_EXPR: |
| case PREINCREMENT_EXPR: |
| case PREDECREMENT_EXPR: |
| case SAVE_EXPR: |
| case TRY_CATCH_EXPR: |
| case WITH_CLEANUP_EXPR: |
| case COMPOUND_EXPR: |
| case MODIFY_EXPR: |
| case TARGET_EXPR: |
| case COND_EXPR: |
| case BIND_EXPR: |
| case MIN_EXPR: |
| case MAX_EXPR: |
| break; |
| |
| default: |
| /* Assume the worst for front-end tree codes. */ |
| if ((int)TREE_CODE (x) >= NUM_TREE_CODES) |
| break; |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /* Return an expr equal to X but certainly not valid as an lvalue. */ |
| |
| tree |
| non_lvalue (tree x) |
| { |
| /* While we are in GIMPLE, NON_LVALUE_EXPR doesn't mean anything to |
| us. */ |
| if (in_gimple_form) |
| return x; |
| |
| if (! maybe_lvalue_p (x)) |
| return x; |
| return build1 (NON_LVALUE_EXPR, TREE_TYPE (x), x); |
| } |
| |
| /* Nonzero means lvalues are limited to those valid in pedantic ANSI C. |
| Zero means allow extended lvalues. */ |
| |
| int pedantic_lvalues; |
| |
| /* When pedantic, return an expr equal to X but certainly not valid as a |
| pedantic lvalue. Otherwise, return X. */ |
| |
| static tree |
| pedantic_non_lvalue (tree x) |
| { |
| if (pedantic_lvalues) |
| return non_lvalue (x); |
| else |
| return x; |
| } |
| |
| /* Given a tree comparison code, return the code that is the logical inverse |
| of the given code. It is not safe to do this for floating-point |
| comparisons, except for NE_EXPR and EQ_EXPR, so we receive a machine mode |
| as well: if reversing the comparison is unsafe, return ERROR_MARK. */ |
| |
| static enum tree_code |
| invert_tree_comparison (enum tree_code code, bool honor_nans) |
| { |
| if (honor_nans && flag_trapping_math) |
| return ERROR_MARK; |
| |
| switch (code) |
| { |
| case EQ_EXPR: |
| return NE_EXPR; |
| case NE_EXPR: |
| return EQ_EXPR; |
| case GT_EXPR: |
| return honor_nans ? UNLE_EXPR : LE_EXPR; |
| case GE_EXPR: |
| return honor_nans ? UNLT_EXPR : LT_EXPR; |
| case LT_EXPR: |
| return honor_nans ? UNGE_EXPR : GE_EXPR; |
| case LE_EXPR: |
| return honor_nans ? UNGT_EXPR : GT_EXPR; |
| case LTGT_EXPR: |
| return UNEQ_EXPR; |
| case UNEQ_EXPR: |
| return LTGT_EXPR; |
| case UNGT_EXPR: |
| return LE_EXPR; |
| case UNGE_EXPR: |
| return LT_EXPR; |
| case UNLT_EXPR: |
| return GE_EXPR; |
| case UNLE_EXPR: |
| return GT_EXPR; |
| case ORDERED_EXPR: |
| return UNORDERED_EXPR; |
| case UNORDERED_EXPR: |
| return ORDERED_EXPR; |
| default: |
| gcc_unreachable (); |
| } |
| } |
| |
| /* Similar, but return the comparison that results if the operands are |
| swapped. This is safe for floating-point. */ |
| |
| enum tree_code |
| swap_tree_comparison (enum tree_code code) |
| { |
| switch (code) |
| { |
| case EQ_EXPR: |
| case NE_EXPR: |
| return code; |
| case GT_EXPR: |
| return LT_EXPR; |
| case GE_EXPR: |
| return LE_EXPR; |
| case LT_EXPR: |
| return GT_EXPR; |
| case LE_EXPR: |
| return GE_EXPR; |
| default: |
| gcc_unreachable (); |
| } |
| } |
| |
| |
| /* Convert a comparison tree code from an enum tree_code representation |
| into a compcode bit-based encoding. This function is the inverse of |
| compcode_to_comparison. */ |
| |
| static enum comparison_code |
| comparison_to_compcode (enum tree_code code) |
| { |
| switch (code) |
| { |
| case LT_EXPR: |
| return COMPCODE_LT; |
| case EQ_EXPR: |
| return COMPCODE_EQ; |
| case LE_EXPR: |
| return COMPCODE_LE; |
| case GT_EXPR: |
| return COMPCODE_GT; |
| case NE_EXPR: |
| return COMPCODE_NE; |
| case GE_EXPR: |
| return COMPCODE_GE; |
| case ORDERED_EXPR: |
| return COMPCODE_ORD; |
| case UNORDERED_EXPR: |
| return COMPCODE_UNORD; |
| case UNLT_EXPR: |
| return COMPCODE_UNLT; |
| case UNEQ_EXPR: |
| return COMPCODE_UNEQ; |
| case UNLE_EXPR: |
| return COMPCODE_UNLE; |
| case UNGT_EXPR: |
| return COMPCODE_UNGT; |
| case LTGT_EXPR: |
| return COMPCODE_LTGT; |
| case UNGE_EXPR: |
| return COMPCODE_UNGE; |
| default: |
| gcc_unreachable (); |
| } |
| } |
| |
| /* Convert a compcode bit-based encoding of a comparison operator back |
| to GCC's enum tree_code representation. This function is the |
| inverse of comparison_to_compcode. */ |
| |
| static enum tree_code |
| compcode_to_comparison (enum comparison_code code) |
| { |
| switch (code) |
| { |
| case COMPCODE_LT: |
| return LT_EXPR; |
| case COMPCODE_EQ: |
| return EQ_EXPR; |
| case COMPCODE_LE: |
| return LE_EXPR; |
| case COMPCODE_GT: |
| return GT_EXPR; |
| case COMPCODE_NE: |
| return NE_EXPR; |
| case COMPCODE_GE: |
| return GE_EXPR; |
| case COMPCODE_ORD: |
| return ORDERED_EXPR; |
| case COMPCODE_UNORD: |
| return UNORDERED_EXPR; |
| case COMPCODE_UNLT: |
| return UNLT_EXPR; |
| case COMPCODE_UNEQ: |
| return UNEQ_EXPR; |
| case COMPCODE_UNLE: |
| return UNLE_EXPR; |
| case COMPCODE_UNGT: |
| return UNGT_EXPR; |
| case COMPCODE_LTGT: |
| return LTGT_EXPR; |
| case COMPCODE_UNGE: |
| return UNGE_EXPR; |
| default: |
| gcc_unreachable (); |
| } |
| } |
| |
| /* Return a tree for the comparison which is the combination of |
| doing the AND or OR (depending on CODE) of the two operations LCODE |
| and RCODE on the identical operands LL_ARG and LR_ARG. Take into account |
| the possibility of trapping if the mode has NaNs, and return NULL_TREE |
| if this makes the transformation invalid. */ |
| |
| tree |
| combine_comparisons (enum tree_code code, enum tree_code lcode, |
| enum tree_code rcode, tree truth_type, |
| tree ll_arg, tree lr_arg) |
| { |
| bool honor_nans = HONOR_NANS (TYPE_MODE (TREE_TYPE (ll_arg))); |
| enum comparison_code lcompcode = comparison_to_compcode (lcode); |
| enum comparison_code rcompcode = comparison_to_compcode (rcode); |
| enum comparison_code compcode; |
| |
| switch (code) |
| { |
| case TRUTH_AND_EXPR: case TRUTH_ANDIF_EXPR: |
| compcode = lcompcode & rcompcode; |
| break; |
| |
| case TRUTH_OR_EXPR: case TRUTH_ORIF_EXPR: |
| compcode = lcompcode | rcompcode; |
| break; |
| |
| default: |
| return NULL_TREE; |
| } |
| |
| if (!honor_nans) |
| { |
| /* Eliminate unordered comparisons, as well as LTGT and ORD |
| which are not used unless the mode has NaNs. */ |
| compcode &= ~COMPCODE_UNORD; |
| if (compcode == COMPCODE_LTGT) |
| compcode = COMPCODE_NE; |
| else if (compcode == COMPCODE_ORD) |
| compcode = COMPCODE_TRUE; |
| } |
| else if (flag_trapping_math) |
| { |
| /* Check that the original operation and the optimized ones will trap |
| under the same condition. */ |
| bool ltrap = (lcompcode & COMPCODE_UNORD) == 0 |
| && (lcompcode != COMPCODE_EQ) |
| && (lcompcode != COMPCODE_ORD); |
| bool rtrap = (rcompcode & COMPCODE_UNORD) == 0 |
| && (rcompcode != COMPCODE_EQ) |
| && (rcompcode != COMPCODE_ORD); |
| bool trap = (compcode & COMPCODE_UNORD) == 0 |
| && (compcode != COMPCODE_EQ) |
| && (compcode != COMPCODE_ORD); |
| |
| /* In a short-circuited boolean expression the LHS might be |
| such that the RHS, if evaluated, will never trap. For |
| example, in ORD (x, y) && (x < y), we evaluate the RHS only |
| if neither x nor y is NaN. (This is a mixed blessing: for |
| example, the expression above will never trap, hence |
| optimizing it to x < y would be invalid). */ |
| if ((code == TRUTH_ORIF_EXPR && (lcompcode & COMPCODE_UNORD)) |
| || (code == TRUTH_ANDIF_EXPR && !(lcompcode & COMPCODE_UNORD))) |
| rtrap = false; |
| |
| /* If the comparison was short-circuited, and only the RHS |
| trapped, we may now generate a spurious trap. */ |
| if (rtrap && !ltrap |
| && (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)) |
| return NULL_TREE; |
| |
| /* If we changed the conditions that cause a trap, we lose. */ |
| if ((ltrap || rtrap) != trap) |
| return NULL_TREE; |
| } |
| |
| if (compcode == COMPCODE_TRUE) |
| return constant_boolean_node (true, truth_type); |
| else if (compcode == COMPCODE_FALSE) |
| return constant_boolean_node (false, truth_type); |
| else |
| return fold (build2 (compcode_to_comparison (compcode), |
| truth_type, ll_arg, lr_arg)); |
| } |
| |
| /* Return nonzero if CODE is a tree code that represents a truth value. */ |
| |
| static int |
| truth_value_p (enum tree_code code) |
| { |
| return (TREE_CODE_CLASS (code) == tcc_comparison |
| || code == TRUTH_AND_EXPR || code == TRUTH_ANDIF_EXPR |
| || code == TRUTH_OR_EXPR || code == TRUTH_ORIF_EXPR |
| || code == TRUTH_XOR_EXPR || code == TRUTH_NOT_EXPR); |
| } |
| |
| /* Return nonzero if two operands (typically of the same tree node) |
| are necessarily equal. If either argument has side-effects this |
| function returns zero. FLAGS modifies behavior as follows: |
| |
| If OEP_ONLY_CONST is set, only return nonzero for constants. |
| This function tests whether the operands are indistinguishable; |
| it does not test whether they are equal using C's == operation. |
| The distinction is important for IEEE floating point, because |
| (1) -0.0 and 0.0 are distinguishable, but -0.0==0.0, and |
| (2) two NaNs may be indistinguishable, but NaN!=NaN. |
| |
| If OEP_ONLY_CONST is unset, a VAR_DECL is considered equal to itself |
| even though it may hold multiple values during a function. |
| This is because a GCC tree node guarantees that nothing else is |
| executed between the evaluation of its "operands" (which may often |
| be evaluated in arbitrary order). Hence if the operands themselves |
| don't side-effect, the VAR_DECLs, PARM_DECLs etc... must hold the |
| same value in each operand/subexpression. Hence leaving OEP_ONLY_CONST |
| unset means assuming isochronic (or instantaneous) tree equivalence. |
| Unless comparing arbitrary expression trees, such as from different |
| statements, this flag can usually be left unset. |
| |
| If OEP_PURE_SAME is set, then pure functions with identical arguments |
| are considered the same. It is used when the caller has other ways |
| to ensure that global memory is unchanged in between. */ |
| |
| int |
| operand_equal_p (tree arg0, tree arg1, unsigned int flags) |
| { |
| /* If either is ERROR_MARK, they aren't equal. */ |
| if (TREE_CODE (arg0) == ERROR_MARK || TREE_CODE (arg1) == ERROR_MARK) |
| return 0; |
| |
| /* If both types don't have the same signedness, then we can't consider |
| them equal. We must check this before the STRIP_NOPS calls |
| because they may change the signedness of the arguments. */ |
| if (TYPE_UNSIGNED (TREE_TYPE (arg0)) != TYPE_UNSIGNED (TREE_TYPE (arg1))) |
| return 0; |
| |
| /* If both types don't have the same precision, then it is not safe |
| to strip NOPs. */ |
| if (TYPE_PRECISION (TREE_TYPE (arg0)) != TYPE_PRECISION (TREE_TYPE (arg1))) |
| return 0; |
| |
| STRIP_NOPS (arg0); |
| STRIP_NOPS (arg1); |
| |
| if (TREE_CODE (arg0) != TREE_CODE (arg1) |
| /* This is needed for conversions and for COMPONENT_REF. |
| Might as well play it safe and always test this. */ |
| || TREE_CODE (TREE_TYPE (arg0)) == ERROR_MARK |
| || TREE_CODE (TREE_TYPE (arg1)) == ERROR_MARK |
| || TYPE_MODE (TREE_TYPE (arg0)) != TYPE_MODE (TREE_TYPE (arg1))) |
| return 0; |
| |
| /* If ARG0 and ARG1 are the same SAVE_EXPR, they are necessarily equal. |
| We don't care about side effects in that case because the SAVE_EXPR |
| takes care of that for us. In all other cases, two expressions are |
| equal if they have no side effects. If we have two identical |
| expressions with side effects that should be treated the same due |
| to the only side effects being identical SAVE_EXPR's, that will |
| be detected in the recursive calls below. */ |
| if (arg0 == arg1 && ! (flags & OEP_ONLY_CONST) |
| && (TREE_CODE (arg0) == SAVE_EXPR |
| || (! TREE_SIDE_EFFECTS (arg0) && ! TREE_SIDE_EFFECTS (arg1)))) |
| return 1; |
| |
| /* Next handle constant cases, those for which we can return 1 even |
| if ONLY_CONST is set. */ |
| if (TREE_CONSTANT (arg0) && TREE_CONSTANT (arg1)) |
| switch (TREE_CODE (arg0)) |
| { |
| case INTEGER_CST: |
| return (! TREE_CONSTANT_OVERFLOW (arg0) |
| && ! TREE_CONSTANT_OVERFLOW (arg1) |
| && tree_int_cst_equal (arg0, arg1)); |
| |
| case REAL_CST: |
| return (! TREE_CONSTANT_OVERFLOW (arg0) |
| && ! TREE_CONSTANT_OVERFLOW (arg1) |
| && REAL_VALUES_IDENTICAL (TREE_REAL_CST (arg0), |
| TREE_REAL_CST (arg1))); |
| |
| case VECTOR_CST: |
| { |
| tree v1, v2; |
| |
| if (TREE_CONSTANT_OVERFLOW (arg0) |
| || TREE_CONSTANT_OVERFLOW (arg1)) |
| return 0; |
| |
| v1 = TREE_VECTOR_CST_ELTS (arg0); |
| v2 = TREE_VECTOR_CST_ELTS (arg1); |
| while (v1 && v2) |
| { |
| if (!operand_equal_p (TREE_VALUE (v1), TREE_VALUE (v2), |
| flags)) |
| return 0; |
| v1 = TREE_CHAIN (v1); |
| v2 = TREE_CHAIN (v2); |
| } |
| |
| return 1; |
| } |
| |
| case COMPLEX_CST: |
| return (operand_equal_p (TREE_REALPART (arg0), TREE_REALPART (arg1), |
| flags) |
| && operand_equal_p (TREE_IMAGPART (arg0), TREE_IMAGPART (arg1), |
| flags)); |
| |
| case STRING_CST: |
| return (TREE_STRING_LENGTH (arg0) == TREE_STRING_LENGTH (arg1) |
| && ! memcmp (TREE_STRING_POINTER (arg0), |
| TREE_STRING_POINTER (arg1), |
| TREE_STRING_LENGTH (arg0))); |
| |
| case ADDR_EXPR: |
| return operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0), |
| 0); |
| default: |
| break; |
| } |
| |
| if (flags & OEP_ONLY_CONST) |
| return 0; |
| |
| /* Define macros to test an operand from arg0 and arg1 for equality and a |
| variant that allows null and views null as being different from any |
| non-null value. In the latter case, if either is null, the both |
| must be; otherwise, do the normal comparison. */ |
| #define OP_SAME(N) operand_equal_p (TREE_OPERAND (arg0, N), \ |
| TREE_OPERAND (arg1, N), flags) |
| |
| #define OP_SAME_WITH_NULL(N) \ |
| ((!TREE_OPERAND (arg0, N) || !TREE_OPERAND (arg1, N)) \ |
| ? TREE_OPERAND (arg0, N) == TREE_OPERAND (arg1, N) : OP_SAME (N)) |
| |
| switch (TREE_CODE_CLASS (TREE_CODE (arg0))) |
| { |
| case tcc_unary: |
| /* Two conversions are equal only if signedness and modes match. */ |
| switch (TREE_CODE (arg0)) |
| { |
| case NOP_EXPR: |
| case CONVERT_EXPR: |
| case FIX_CEIL_EXPR: |
| case FIX_TRUNC_EXPR: |
| case FIX_FLOOR_EXPR: |
| case FIX_ROUND_EXPR: |
| if (TYPE_UNSIGNED (TREE_TYPE (arg0)) |
| != TYPE_UNSIGNED (TREE_TYPE (arg1))) |
| return 0; |
| break; |
| default: |
| break; |
| } |
| |
| return OP_SAME (0); |
| |
| |
| case tcc_comparison: |
| case tcc_binary: |
| if (OP_SAME (0) && OP_SAME (1)) |
| return 1; |
| |
| /* For commutative ops, allow the other order. */ |
| return (commutative_tree_code (TREE_CODE (arg0)) |
| && operand_equal_p (TREE_OPERAND (arg0, 0), |
| TREE_OPERAND (arg1, 1), flags) |
| && operand_equal_p (TREE_OPERAND (arg0, 1), |
| TREE_OPERAND (arg1, 0), flags)); |
| |
| case tcc_reference: |
| /* If either of the pointer (or reference) expressions we are |
| dereferencing contain a side effect, these cannot be equal. */ |
| if (TREE_SIDE_EFFECTS (arg0) |
| || TREE_SIDE_EFFECTS (arg1)) |
| return 0; |
| |
| switch (TREE_CODE (arg0)) |
| { |
| case INDIRECT_REF: |
| case ALIGN_INDIRECT_REF: |
| case MISALIGNED_INDIRECT_REF: |
| case REALPART_EXPR: |
| case IMAGPART_EXPR: |
| return OP_SAME (0); |
| |
| case ARRAY_REF: |
| case ARRAY_RANGE_REF: |
| /* Operands 2 and 3 may be null. */ |
| return (OP_SAME (0) |
| && OP_SAME (1) |
| && OP_SAME_WITH_NULL (2) |
| && OP_SAME_WITH_NULL (3)); |
| |
| case COMPONENT_REF: |
| /* Handle operand 2 the same as for ARRAY_REF. */ |
| return OP_SAME (0) && OP_SAME (1) && OP_SAME_WITH_NULL (2); |
| |
| case BIT_FIELD_REF: |
| return OP_SAME (0) && OP_SAME (1) && OP_SAME (2); |
| |
| default: |
| return 0; |
| } |
| |
| case tcc_expression: |
| switch (TREE_CODE (arg0)) |
| { |
| case ADDR_EXPR: |
| case TRUTH_NOT_EXPR: |
| return OP_SAME (0); |
| |
| case TRUTH_ANDIF_EXPR: |
| case TRUTH_ORIF_EXPR: |
| return OP_SAME (0) && OP_SAME (1); |
| |
| case TRUTH_AND_EXPR: |
| case TRUTH_OR_EXPR: |
| case TRUTH_XOR_EXPR: |
| if (OP_SAME (0) && OP_SAME (1)) |
| return 1; |
| |
| /* Otherwise take into account this is a commutative operation. */ |
| return (operand_equal_p (TREE_OPERAND (arg0, 0), |
| TREE_OPERAND (arg1, 1), flags) |
| && operand_equal_p (TREE_OPERAND (arg0, 1), |
| TREE_OPERAND (arg1, 0), flags)); |
| |
| case CALL_EXPR: |
| /* If the CALL_EXPRs call different functions, then they |
| clearly can not be equal. */ |
| if (!OP_SAME (0)) |
| return 0; |
| |
| { |
| unsigned int cef = call_expr_flags (arg0); |
| if (flags & OEP_PURE_SAME) |
| cef &= ECF_CONST | ECF_PURE; |
| else |
| cef &= ECF_CONST; |
| if (!cef) |
| return 0; |
| } |
| |
| /* Now see if all the arguments are the same. operand_equal_p |
| does not handle TREE_LIST, so we walk the operands here |
| feeding them to operand_equal_p. */ |
| arg0 = TREE_OPERAND (arg0, 1); |
| arg1 = TREE_OPERAND (arg1, 1); |
| while (arg0 && arg1) |
| { |
| if (! operand_equal_p (TREE_VALUE (arg0), TREE_VALUE (arg1), |
| flags)) |
| return 0; |
| |
| arg0 = TREE_CHAIN (arg0); |
| arg1 = TREE_CHAIN (arg1); |
| } |
| |
| /* If we get here and both argument lists are exhausted |
| then the CALL_EXPRs are equal. */ |
| return ! (arg0 || arg1); |
| |
| default: |
| return 0; |
| } |
| |
| case tcc_declaration: |
| /* Consider __builtin_sqrt equal to sqrt. */ |
| return (TREE_CODE (arg0) == FUNCTION_DECL |
| && DECL_BUILT_IN (arg0) && DECL_BUILT_IN (arg1) |
| && DECL_BUILT_IN_CLASS (arg0) == DECL_BUILT_IN_CLASS (arg1) |
| && DECL_FUNCTION_CODE (arg0) == DECL_FUNCTION_CODE (arg1)); |
| |
| default: |
| return 0; |
| } |
| |
| #undef OP_SAME |
| #undef OP_SAME_WITH_NULL |
| } |
| |
| /* Similar to operand_equal_p, but see if ARG0 might have been made by |
| shorten_compare from ARG1 when ARG1 was being compared with OTHER. |
| |
| When in doubt, return 0. */ |
| |
| static int |
| operand_equal_for_comparison_p (tree arg0, tree arg1, tree other) |
| { |
| int unsignedp1, unsignedpo; |
| tree primarg0, primarg1, primother; |
| unsigned int correct_width; |
| |
| if (operand_equal_p (arg0, arg1, 0)) |
| return 1; |
| |
| if (! INTEGRAL_TYPE_P (TREE_TYPE (arg0)) |
| || ! INTEGRAL_TYPE_P (TREE_TYPE (arg1))) |
| return 0; |
| |
| /* Discard any conversions that don't change the modes of ARG0 and ARG1 |
| and see if the inner values are the same. This removes any |
| signedness comparison, which doesn't matter here. */ |
| primarg0 = arg0, primarg1 = arg1; |
| STRIP_NOPS (primarg0); |
| STRIP_NOPS (primarg1); |
| if (operand_equal_p (primarg0, primarg1, 0)) |
| return 1; |
| |
| /* Duplicate what shorten_compare does to ARG1 and see if that gives the |
| actual comparison operand, ARG0. |
| |
| First throw away any conversions to wider types |
| already present in the operands. */ |
| |
| primarg1 = get_narrower (arg1, &unsignedp1); |
| primother = get_narrower (other, &unsignedpo); |
| |
| correct_width = TYPE_PRECISION (TREE_TYPE (arg1)); |
| if (unsignedp1 == unsignedpo |
| && TYPE_PRECISION (TREE_TYPE (primarg1)) < correct_width |
| && TYPE_PRECISION (TREE_TYPE (primother)) < correct_width) |
| { |
| tree type = TREE_TYPE (arg0); |
| |
| /* Make sure shorter operand is extended the right way |
| to match the longer operand. */ |
| primarg1 = fold_convert (lang_hooks.types.signed_or_unsigned_type |
| (unsignedp1, TREE_TYPE (primarg1)), primarg1); |
| |
| if (operand_equal_p (arg0, fold_convert (type, primarg1), 0)) |
| return 1; |
| } |
| |
| return 0; |
| } |
| |
| /* See if ARG is an expression that is either a comparison or is performing |
| arithmetic on comparisons. The comparisons must only be comparing |
| two different values, which will be stored in *CVAL1 and *CVAL2; if |
| they are nonzero it means that some operands have already been found. |
| No variables may be used anywhere else in the expression except in the |
| comparisons. If SAVE_P is true it means we removed a SAVE_EXPR around |
| the expression and save_expr needs to be called with CVAL1 and CVAL2. |
| |
| If this is true, return 1. Otherwise, return zero. */ |
| |
| static int |
| twoval_comparison_p (tree arg, tree *cval1, tree *cval2, int *save_p) |
| { |
| enum tree_code code = TREE_CODE (arg); |
| enum tree_code_class class = TREE_CODE_CLASS (code); |
| |
| /* We can handle some of the tcc_expression cases here. */ |
| if (class == tcc_expression && code == TRUTH_NOT_EXPR) |
| class = tcc_unary; |
| else if (class == tcc_expression |
| && (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR |
| || code == COMPOUND_EXPR)) |
| class = tcc_binary; |
| |
| else if (class == tcc_expression && code == SAVE_EXPR |
| && ! TREE_SIDE_EFFECTS (TREE_OPERAND (arg, 0))) |
| { |
| /* If we've already found a CVAL1 or CVAL2, this expression is |
| two complex to handle. */ |
| if (*cval1 || *cval2) |
| return 0; |
| |
| class = tcc_unary; |
| *save_p = 1; |
| } |
| |
| switch (class) |
| { |
| case tcc_unary: |
| return twoval_comparison_p (TREE_OPERAND (arg, 0), cval1, cval2, save_p); |
| |
| case tcc_binary: |
| return (twoval_comparison_p (TREE_OPERAND (arg, 0), cval1, cval2, save_p) |
| && twoval_comparison_p (TREE_OPERAND (arg, 1), |
| cval1, cval2, save_p)); |
| |
| case tcc_constant: |
| return 1; |
| |
| case tcc_expression: |
| if (code == COND_EXPR) |
| return (twoval_comparison_p (TREE_OPERAND (arg, 0), |
| cval1, cval2, save_p) |
| && twoval_comparison_p (TREE_OPERAND (arg, 1), |
| cval1, cval2, save_p) |
| && twoval_comparison_p (TREE_OPERAND (arg, 2), |
| cval1, cval2, save_p)); |
| return 0; |
| |
| case tcc_comparison: |
| /* First see if we can handle the first operand, then the second. For |
| the second operand, we know *CVAL1 can't be zero. It must be that |
| one side of the comparison is each of the values; test for the |
| case where this isn't true by failing if the two operands |
| are the same. */ |
| |
| if (operand_equal_p (TREE_OPERAND (arg, 0), |
| TREE_OPERAND (arg, 1), 0)) |
| return 0; |
| |
| if (*cval1 == 0) |
| *cval1 = TREE_OPERAND (arg, 0); |
| else if (operand_equal_p (*cval1, TREE_OPERAND (arg, 0), 0)) |
| ; |
| else if (*cval2 == 0) |
| *cval2 = TREE_OPERAND (arg, 0); |
| else if (operand_equal_p (*cval2, TREE_OPERAND (arg, 0), 0)) |
| ; |
| else |
| return 0; |
| |
| if (operand_equal_p (*cval1, TREE_OPERAND (arg, 1), 0)) |
| ; |
| else if (*cval2 == 0) |
| *cval2 = TREE_OPERAND (arg, 1); |
| else if (operand_equal_p (*cval2, TREE_OPERAND (arg, 1), 0)) |
| ; |
| else |
| return 0; |
| |
| return 1; |
| |
| default: |
| return 0; |
| } |
| } |
| |
| /* ARG is a tree that is known to contain just arithmetic operations and |
| comparisons. Evaluate the operations in the tree substituting NEW0 for |
| any occurrence of OLD0 as an operand of a comparison and likewise for |
| NEW1 and OLD1. */ |
| |
| static tree |
| eval_subst (tree arg, tree old0, tree new0, tree old1, tree new1) |
| { |
| tree type = TREE_TYPE (arg); |
| enum tree_code code = TREE_CODE (arg); |
| enum tree_code_class class = TREE_CODE_CLASS (code); |
| |
| /* We can handle some of the tcc_expression cases here. */ |
| if (class == tcc_expression && code == TRUTH_NOT_EXPR) |
| class = tcc_unary; |
| else if (class == tcc_expression |
| && (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)) |
| class = tcc_binary; |
| |
| switch (class) |
| { |
| case tcc_unary: |
| return fold (build1 (code, type, |
| eval_subst (TREE_OPERAND (arg, 0), |
| old0, new0, old1, new1))); |
| |
| case tcc_binary: |
| return fold (build2 (code, type, |
| eval_subst (TREE_OPERAND (arg, 0), |
| old0, new0, old1, new1), |
| eval_subst (TREE_OPERAND (arg, 1), |
| old0, new0, old1, new1))); |
| |
| case tcc_expression: |
| switch (code) |
| { |
| case SAVE_EXPR: |
| return eval_subst (TREE_OPERAND (arg, 0), old0, new0, old1, new1); |
| |
| case COMPOUND_EXPR: |
| return eval_subst (TREE_OPERAND (arg, 1), old0, new0, old1, new1); |
| |
| case COND_EXPR: |
| return fold (build3 (code, type, |
| eval_subst (TREE_OPERAND (arg, 0), |
| old0, new0, old1, new1), |
| eval_subst (TREE_OPERAND (arg, 1), |
| old0, new0, old1, new1), |
| eval_subst (TREE_OPERAND (arg, 2), |
| old0, new0, old1, new1))); |
| default: |
| break; |
| } |
| /* Fall through - ??? */ |
| |
| case tcc_comparison: |
| { |
| tree arg0 = TREE_OPERAND (arg, 0); |
| tree arg1 = TREE_OPERAND (arg, 1); |
| |
| /* We need to check both for exact equality and tree equality. The |
| former will be true if the operand has a side-effect. In that |
| case, we know the operand occurred exactly once. */ |
| |
| if (arg0 == old0 || operand_equal_p (arg0, old0, 0)) |
| arg0 = new0; |
| else if (arg0 == old1 || operand_equal_p (arg0, old1, 0)) |
| arg0 = new1; |
| |
| if (arg1 == old0 || operand_equal_p (arg1, old0, 0)) |
| arg1 = new0; |
| else if (arg1 == old1 || operand_equal_p (arg1, old1, 0)) |
| arg1 = new1; |
| |
| return fold (build2 (code, type, arg0, arg1)); |
| } |
| |
| default: |
| return arg; |
| } |
| } |
| |
| /* Return a tree for the case when the result of an expression is RESULT |
| converted to TYPE and OMITTED was previously an operand of the expression |
| but is now not needed (e.g., we folded OMITTED * 0). |
| |
| If OMITTED has side effects, we must evaluate it. Otherwise, just do |
| the conversion of RESULT to TYPE. */ |
| |
| tree |
| omit_one_operand (tree type, tree result, tree omitted) |
| { |
| tree t = fold_convert (type, result); |
| |
| if (TREE_SIDE_EFFECTS (omitted)) |
| return build2 (COMPOUND_EXPR, type, fold_ignored_result (omitted), t); |
| |
| return non_lvalue (t); |
| } |
| |
| /* Similar, but call pedantic_non_lvalue instead of non_lvalue. */ |
| |
| static tree |
| pedantic_omit_one_operand (tree type, tree result, tree omitted) |
| { |
| tree t = fold_convert (type, result); |
| |
| if (TREE_SIDE_EFFECTS (omitted)) |
| return build2 (COMPOUND_EXPR, type, fold_ignored_result (omitted), t); |
| |
| return pedantic_non_lvalue (t); |
| } |
| |
| /* Return a tree for the case when the result of an expression is RESULT |
| converted to TYPE and OMITTED1 and OMITTED2 were previously operands |
| of the expression but are now not needed. |
| |
| If OMITTED1 or OMITTED2 has side effects, they must be evaluated. |
| If both OMITTED1 and OMITTED2 have side effects, OMITTED1 is |
| evaluated before OMITTED2. Otherwise, if neither has side effects, |
| just do the conversion of RESULT to TYPE. */ |
| |
| tree |
| omit_two_operands (tree type, tree result, tree omitted1, tree omitted2) |
| { |
| tree t = fold_convert (type, result); |
| |
| if (TREE_SIDE_EFFECTS (omitted2)) |
| t = build2 (COMPOUND_EXPR, type, omitted2, t); |
| if (TREE_SIDE_EFFECTS (omitted1)) |
| t = build2 (COMPOUND_EXPR, type, omitted1, t); |
| |
| return TREE_CODE (t) != COMPOUND_EXPR ? non_lvalue (t) : t; |
| } |
| |
| |
| /* Return a simplified tree node for the truth-negation of ARG. This |
| never alters ARG itself. We assume that ARG is an operation that |
| returns a truth value (0 or 1). |
| |
| FIXME: one would think we would fold the result, but it causes |
| problems with the dominator optimizer. */ |
| tree |
| invert_truthvalue (tree arg) |
| { |
| tree type = TREE_TYPE (arg); |
| enum tree_code code = TREE_CODE (arg); |
| |
| if (code == ERROR_MARK) |
| return arg; |
| |
| /* If this is a comparison, we can simply invert it, except for |
| floating-point non-equality comparisons, in which case we just |
| enclose a TRUTH_NOT_EXPR around what we have. */ |
| |
| if (TREE_CODE_CLASS (code) == tcc_comparison) |
| { |
| tree op_type = TREE_TYPE (TREE_OPERAND (arg, 0)); |
| if (FLOAT_TYPE_P (op_type) |
| && flag_trapping_math |
| && code != ORDERED_EXPR && code != UNORDERED_EXPR |
| && code != NE_EXPR && code != EQ_EXPR) |
| return build1 (TRUTH_NOT_EXPR, type, arg); |
| else |
| { |
| code = invert_tree_comparison (code, |
| HONOR_NANS (TYPE_MODE (op_type))); |
| if (code == ERROR_MARK) |
| return build1 (TRUTH_NOT_EXPR, type, arg); |
| else |
| return build2 (code, type, |
| TREE_OPERAND (arg, 0), TREE_OPERAND (arg, 1)); |
| } |
| } |
| |
| switch (code) |
| { |
| case INTEGER_CST: |
| return constant_boolean_node (integer_zerop (arg), type); |
| |
| case TRUTH_AND_EXPR: |
| return build2 (TRUTH_OR_EXPR, type, |
| invert_truthvalue (TREE_OPERAND (arg, 0)), |
| invert_truthvalue (TREE_OPERAND (arg, 1))); |
| |
| case TRUTH_OR_EXPR: |
| return build2 (TRUTH_AND_EXPR, type, |
| invert_truthvalue (TREE_OPERAND (arg, 0)), |
| invert_truthvalue (TREE_OPERAND (arg, 1))); |
| |
| case TRUTH_XOR_EXPR: |
| /* Here we can invert either operand. We invert the first operand |
| unless the second operand is a TRUTH_NOT_EXPR in which case our |
| result is the XOR of the first operand with the inside of the |
| negation of the second operand. */ |
| |
| if (TREE_CODE (TREE_OPERAND (arg, 1)) == TRUTH_NOT_EXPR) |
| return build2 (TRUTH_XOR_EXPR, type, TREE_OPERAND (arg, 0), |
| TREE_OPERAND (TREE_OPERAND (arg, 1), 0)); |
| else |
| return build2 (TRUTH_XOR_EXPR, type, |
| invert_truthvalue (TREE_OPERAND (arg, 0)), |
| TREE_OPERAND (arg, 1)); |
| |
| case TRUTH_ANDIF_EXPR: |
| return build2 (TRUTH_ORIF_EXPR, type, |
| invert_truthvalue (TREE_OPERAND (arg, 0)), |
| invert_truthvalue (TREE_OPERAND (arg, 1))); |
| |
| case TRUTH_ORIF_EXPR: |
| return build2 (TRUTH_ANDIF_EXPR, type, |
| invert_truthvalue (TREE_OPERAND (arg, 0)), |
| invert_truthvalue (TREE_OPERAND (arg, 1))); |
| |
| case TRUTH_NOT_EXPR: |
| return TREE_OPERAND (arg, 0); |
| |
| case COND_EXPR: |
| return build3 (COND_EXPR, type, TREE_OPERAND (arg, 0), |
| invert_truthvalue (TREE_OPERAND (arg, 1)), |
| invert_truthvalue (TREE_OPERAND (arg, 2))); |
| |
| case COMPOUND_EXPR: |
| return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg, 0), |
| invert_truthvalue (TREE_OPERAND (arg, 1))); |
| |
| case NON_LVALUE_EXPR: |
| return invert_truthvalue (TREE_OPERAND (arg, 0)); |
| |
| case NOP_EXPR: |
| if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE) |
| break; |
| |
| case CONVERT_EXPR: |
| case FLOAT_EXPR: |
| return build1 (TREE_CODE (arg), type, |
| invert_truthvalue (TREE_OPERAND (arg, 0))); |
| |
| case BIT_AND_EXPR: |
| if (!integer_onep (TREE_OPERAND (arg, 1))) |
| break; |
| return build2 (EQ_EXPR, type, arg, |
| fold_convert (type, integer_zero_node)); |
| |
| case SAVE_EXPR: |
| return build1 (TRUTH_NOT_EXPR, type, arg); |
| |
| case CLEANUP_POINT_EXPR: |
| return build1 (CLEANUP_POINT_EXPR, type, |
| invert_truthvalue (TREE_OPERAND (arg, 0))); |
| |
| default: |
| break; |
| } |
| gcc_assert (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE); |
| return build1 (TRUTH_NOT_EXPR, type, arg); |
| } |
| |
| /* Given a bit-wise operation CODE applied to ARG0 and ARG1, see if both |
| operands are another bit-wise operation with a common input. If so, |
| distribute the bit operations to save an operation and possibly two if |
| constants are involved. For example, convert |
| (A | B) & (A | C) into A | (B & C) |
| Further simplification will occur if B and C are constants. |
| |
| If this optimization cannot be done, 0 will be returned. */ |
| |
| static tree |
| distribute_bit_expr (enum tree_code code, tree type, tree arg0, tree arg1) |
| { |
| tree common; |
| tree left, right; |
| |
| if (TREE_CODE (arg0) != TREE_CODE (arg1) |
| || TREE_CODE (arg0) == code |
| || (TREE_CODE (arg0) != BIT_AND_EXPR |
| && TREE_CODE (arg0) != BIT_IOR_EXPR)) |
| return 0; |
| |
| if (operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0), 0)) |
| { |
| common = TREE_OPERAND (arg0, 0); |
| left = TREE_OPERAND (arg0, 1); |
| right = TREE_OPERAND (arg1, 1); |
| } |
| else if (operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 1), 0)) |
| { |
| common = TREE_OPERAND (arg0, 0); |
| left = TREE_OPERAND (arg0, 1); |
| right = TREE_OPERAND (arg1, 0); |
| } |
|