aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2008-10-16 08:50:30 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2008-10-16 08:50:30 +0200
commit5b429886c5e390a0d7ae27311f859d2ae1d4b2c1 (patch)
tree9fa058951dd970add438b293d8a95bfcf27b9c5a /gcc
parentc39a4ad7a8e2e494432980bdaff5d4b378b50bb2 (diff)
downloadgcc-5b429886c5e390a0d7ae27311f859d2ae1d4b2c1.zip
gcc-5b429886c5e390a0d7ae27311f859d2ae1d4b2c1.tar.gz
gcc-5b429886c5e390a0d7ae27311f859d2ae1d4b2c1.tar.bz2
re PR tree-optimization/37525 (IVOPTS difference causing 20% degradation in 173.applu benchmark)
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. From-SVN: r141164
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/tree.c105
2 files changed, 79 insertions, 32 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c3d2d9f..057069d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2008-10-16 Jakub Jelinek <jakub@redhat.com>
+
+ 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 <jh@suse.cz>
* ira-emit.c (change_regs): Return false when replacing reg by
diff --git a/gcc/tree.c b/gcc/tree.c
index b131a20..7064e06 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