public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [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

* Re: [PATCH] Fix up int_fits_type_p (PR tree-optimization/37525, take  2)
  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
  0 siblings, 0 replies; 2+ messages in thread
From: Richard Henderson @ 2008-10-15 22:48 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches

Jakub Jelinek wrote:
> 	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.

OK.


r~

^ 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).