From: jakub Date: Thu, 16 Oct 2008 06:50:30 +0000 (+0000) Subject: PR tree-optimization/37525 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d235ab601f652fcc944f4b5461e9f3c82c7020b4;p=thirdparty%2Fgcc.git PR tree-optimization/37525 * tree.c (int_fits_type_p): Rewrite using double_int. Zero extend sizetype unsigned constants, both in the case of C and bounds. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@141164 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c3d2d9f1d453..057069dc57da 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2008-10-16 Jakub Jelinek + + PR tree-optimization/37525 + * tree.c (int_fits_type_p): Rewrite using double_int. Zero extend + sizetype unsigned constants, both in the case of C and bounds. + 2008-10-15 Jan Hubicka * ira-emit.c (change_regs): Return false when replacing reg by diff --git a/gcc/tree.c b/gcc/tree.c index b131a20875c5..7064e06bcece 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -6406,11 +6406,28 @@ get_narrower (tree op, int *unsignedp_ptr) int int_fits_type_p (const_tree c, const_tree type) { - tree type_low_bound = TYPE_MIN_VALUE (type); - tree type_high_bound = TYPE_MAX_VALUE (type); - bool ok_for_low_bound, ok_for_high_bound; - unsigned HOST_WIDE_INT low; - HOST_WIDE_INT high; + tree type_low_bound, type_high_bound; + bool ok_for_low_bound, ok_for_high_bound, unsc; + double_int dc, dd; + + dc = tree_to_double_int (c); + unsc = TYPE_UNSIGNED (TREE_TYPE (c)); + + if (TREE_CODE (TREE_TYPE (c)) == INTEGER_TYPE + && TYPE_IS_SIZETYPE (TREE_TYPE (c)) + && unsc) + /* So c is an unsigned integer whose type is sizetype and type is not. + sizetype'd integers are sign extended even though they are + unsigned. If the integer value fits in the lower end word of c, + and if the higher end word has all its bits set to 1, that + means the higher end bits are set to 1 only for sign extension. + So let's convert c into an equivalent zero extended unsigned + integer. */ + dc = double_int_zext (dc, TYPE_PRECISION (TREE_TYPE (c))); + +retry: + type_low_bound = TYPE_MIN_VALUE (type); + type_high_bound = TYPE_MAX_VALUE (type); /* If at least one bound of the type is a constant integer, we can check ourselves and maybe make a decision. If no such decision is possible, but @@ -6422,25 +6439,25 @@ int_fits_type_p (const_tree c, const_tree type) for "unknown if constant fits", 0 for "constant known *not* to fit" and 1 for "constant known to fit". */ - if (TREE_TYPE (c) == sizetype - && TYPE_UNSIGNED (TREE_TYPE (c)) - && TREE_INT_CST_HIGH (c) == -1 - && !TREE_OVERFLOW (c)) - /* So c is an unsigned integer which type is sizetype. - sizetype'd integers are sign extended even though they are - unsigned. If the integer value fits in the lower end word of c, - and if the higher end word has all its bits set to 1, that - means the higher end bits are set to 1 only for sign extension. - So let's convert c into an equivalent zero extended unsigned - integer. */ - c = force_fit_type_double (size_type_node, - TREE_INT_CST_LOW (c), - TREE_INT_CST_HIGH (c), - false, false); - /* Check if C >= type_low_bound. */ + /* Check if c >= type_low_bound. */ if (type_low_bound && TREE_CODE (type_low_bound) == INTEGER_CST) { - if (tree_int_cst_lt (c, type_low_bound)) + dd = tree_to_double_int (type_low_bound); + if (TREE_CODE (type) == INTEGER_TYPE + && TYPE_IS_SIZETYPE (type) + && TYPE_UNSIGNED (type)) + dd = double_int_zext (dd, TYPE_PRECISION (type)); + if (unsc != TYPE_UNSIGNED (TREE_TYPE (type_low_bound))) + { + int c_neg = (!unsc && double_int_negative_p (dc)); + int t_neg = (unsc && double_int_negative_p (dd)); + + if (c_neg && !t_neg) + return 0; + if ((c_neg || !t_neg) && double_int_ucmp (dc, dd) < 0) + return 0; + } + else if (double_int_cmp (dc, dd, unsc) < 0) return 0; ok_for_low_bound = true; } @@ -6450,7 +6467,22 @@ int_fits_type_p (const_tree c, const_tree type) /* Check if c <= type_high_bound. */ if (type_high_bound && TREE_CODE (type_high_bound) == INTEGER_CST) { - if (tree_int_cst_lt (type_high_bound, c)) + dd = tree_to_double_int (type_high_bound); + if (TREE_CODE (type) == INTEGER_TYPE + && TYPE_IS_SIZETYPE (type) + && TYPE_UNSIGNED (type)) + dd = double_int_zext (dd, TYPE_PRECISION (type)); + if (unsc != TYPE_UNSIGNED (TREE_TYPE (type_high_bound))) + { + int c_neg = (!unsc && double_int_negative_p (dc)); + int t_neg = (unsc && double_int_negative_p (dd)); + + if (t_neg && !c_neg) + return 0; + if ((t_neg || !c_neg) && double_int_ucmp (dc, dd) > 0) + return 0; + } + else if (double_int_cmp (dc, dd, unsc) > 0) return 0; ok_for_high_bound = true; } @@ -6464,7 +6496,7 @@ int_fits_type_p (const_tree c, const_tree type) /* Perform some generic filtering which may allow making a decision even if the bounds are not constant. First, negative integers never fit in unsigned types, */ - if (TYPE_UNSIGNED (type) && tree_int_cst_sgn (c) < 0) + if (TYPE_UNSIGNED (type) && !unsc && double_int_negative_p (dc)) return 0; /* Second, narrower types always fit in wider ones. */ @@ -6472,10 +6504,18 @@ int_fits_type_p (const_tree c, const_tree type) return 1; /* Third, unsigned integers with top bit set never fit signed types. */ - if (! TYPE_UNSIGNED (type) - && TYPE_UNSIGNED (TREE_TYPE (c)) - && tree_int_cst_msb (c)) - return 0; + if (! TYPE_UNSIGNED (type) && unsc) + { + int prec = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (c))) - 1; + if (prec < HOST_BITS_PER_WIDE_INT) + { + if (((((unsigned HOST_WIDE_INT) 1) << prec) & dc.low) != 0) + return 0; + } + else if (((((unsigned HOST_WIDE_INT) 1) + << (prec - HOST_BITS_PER_WIDE_INT)) & dc.high) != 0) + return 0; + } /* If we haven't been able to decide at this point, there nothing more we can check ourselves here. Look at the base type if we have one and it @@ -6483,12 +6523,13 @@ int_fits_type_p (const_tree c, const_tree type) if (TREE_CODE (type) == INTEGER_TYPE && TREE_TYPE (type) != 0 && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (type))) - return int_fits_type_p (c, TREE_TYPE (type)); + { + type = TREE_TYPE (type); + goto retry; + } /* Or to fit_double_type, if nothing else. */ - low = TREE_INT_CST_LOW (c); - high = TREE_INT_CST_HIGH (c); - return !fit_double_type (low, high, &low, &high, type); + return !fit_double_type (dc.low, dc.high, &dc.low, &dc.high, type); } /* Stores bounds of an integer TYPE in MIN and MAX. If TYPE has non-constant