* [PATCH] Fix up int_fits_type_p (PR tree-optimization/37525, take 2)
@ 2008-10-13 13:44 Jakub Jelinek
2008-10-15 22:48 ` Richard Henderson
0 siblings, 1 reply; 2+ messages in thread
From: Jakub Jelinek @ 2008-10-13 13:44 UTC (permalink / raw)
To: gcc-patches
Hi!
As discussed earlier on the mailing list and on IRC, int_fits_type_p
ATM relies on size_type_node being unsigned type with the same precision
as sizetype, which isn't the case e.g. in Fortran.
The patch below rewrites int_fits_type_p using double_int, so it doesn't
have to create new constants and type trees.
I've bootstrapped/regtested it on x86_64-linux, with additional
checking that old int_fits_type_p and this new int_fits_type_p give
identical answers except when sizetype is involved (and size_type_node
is signed) or when bitsizetype is involved.
Ok for trunk?
2008-10-13 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.
--- gcc/tree.c.jj 2008-10-06 07:59:03.000000000 +0200
+++ gcc/tree.c 2008-10-13 13:28:54.000000000 +0200
@@ -6405,11 +6405,28 @@ get_narrower (tree op, int *unsignedp_pt
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
@@ -6421,25 +6438,25 @@ int_fits_type_p (const_tree c, const_tre
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;
}
@@ -6449,7 +6466,22 @@ int_fits_type_p (const_tree c, const_tre
/* 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;
}
@@ -6463,7 +6495,7 @@ int_fits_type_p (const_tree c, const_tre
/* 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. */
@@ -6471,10 +6503,18 @@ int_fits_type_p (const_tree c, const_tre
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
@@ -6482,12 +6522,13 @@ int_fits_type_p (const_tree c, const_tre
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
Jakub
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2008-10-15 18:50 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-10-13 13:44 [PATCH] Fix up int_fits_type_p (PR tree-optimization/37525, take 2) Jakub Jelinek
2008-10-15 22:48 ` Richard Henderson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).