tree.c (int_fits_type_p): Extract generic checks from the case of constant type bounds.
authorOlivier Hainque <hainque@act-europe.fr>
Mon, 14 Apr 2003 21:59:54 +0000 (23:59 +0200)
committerRichard Kenner <kenner@gcc.gnu.org>
Mon, 14 Apr 2003 21:59:54 +0000 (17:59 -0400)
* tree.c (int_fits_type_p): Extract generic checks from the case
of constant type bounds. Refine the checks against constant type
bounds to allow for possible decisions against each of these bounds
without requiring both bounds to be constant.
(tree_int_cst_msb): Put back.
* tree.h (tree_int_cst_msb): Likewise.

From-SVN: r65598

gcc/ChangeLog
gcc/tree.c
gcc/tree.h

index 93af039800d6fe3c40ea537ef560f8c9543e6b26..41451aa9c4aa0e601812b9d5e0735738b7a1fcdd 100644 (file)
 
 2003-04-14  Olivier Hainque <hainque@act-europe.fr>
 
+       * tree.c (int_fits_type_p): Extract generic checks from the case
+       of constant type bounds. Refine the checks against constant type
+       bounds to allow for possible decisions against each of these bounds
+       without requiring both bounds to be constant.
+       (tree_int_cst_msb): Put back.
+       * tree.h (tree_int_cst_msb): Likewise.
+
        * global.c (global_conflicts): Prevent allocation of call clobbered
        hard regs to pseudos live across abnormal edges, as later passes are
        not ready to handle them.
index 0570261d60d1045dee1fa158d4478df244c921b4..2d8e12a8674cd6d4efef1f14dd1c14fd6ba198d8 100644 (file)
@@ -3245,6 +3245,24 @@ tree_low_cst (t, pos)
     abort ();
 }
 
+/* Return the most significant bit of the integer constant T.  */
+
+int
+tree_int_cst_msb (t)
+     tree t;
+{
+  int prec;
+  HOST_WIDE_INT h;
+  unsigned HOST_WIDE_INT l;
+
+  /* Note that using TYPE_PRECISION here is wrong.  We care about the
+     actual bits, not the (arbitrary) range of the type.  */
+  prec = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (t))) - 1;
+  rshift_double (TREE_INT_CST_LOW (t), TREE_INT_CST_HIGH (t), prec,
+                2 * HOST_BITS_PER_WIDE_INT, &l, &h, 0);
+  return (l & 1) == 1;
+}
+
 /* Return an indication of the sign of the integer constant T.
    The return value is -1 if T < 0, 0 if T == 0, and 1 if T > 0.
    Note that -1 will never be returned it T's type is unsigned.  */
@@ -4069,29 +4087,58 @@ int
 int_fits_type_p (c, type)
      tree c, type;
 {
-  /* If the bounds of the type are integers, we can check ourselves.
-     If not, but this type is a subtype, try checking against that.
-     Otherwise, use force_fit_type, which checks against the precision.  */
-  if (TYPE_MAX_VALUE (type) != NULL_TREE
-      && TYPE_MIN_VALUE (type) != NULL_TREE
-      && TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST
-      && TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST)
+  tree type_low_bound = TYPE_MIN_VALUE (type);
+  tree type_high_bound = TYPE_MAX_VALUE (type);
+  int ok_for_low_bound, ok_for_high_bound;
+    
+  /* Perform some generic filtering first, which may allow making a decision
+     even if the bounds are not constant.  First, negative integers never fit
+     in unsigned types, */
+  if ((TREE_UNSIGNED (type) && tree_int_cst_sgn (c) < 0)
+      /* Also, unsigned integers with top bit set never fit signed types.  */
+      || (! TREE_UNSIGNED (type) 
+         && TREE_UNSIGNED (TREE_TYPE (c)) && tree_int_cst_msb (c)))
+    return 0;
+
+  /* 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
+     this type is a subtype, try checking against that.  Otherwise, use
+     force_fit_type, which checks against the precision.
+
+     Compute the status for each possibly constant bound, and return if we see
+     one does not match. Use ok_for_xxx_bound for this purpose, assigning -1
+     for "unknown if constant fits", 0 for "constant known *not* to fit" and 1
+     for "constant known to fit".  */
+
+  ok_for_low_bound = -1;
+  ok_for_high_bound = -1;
+    
+  /* Check if C >= type_low_bound.  */
+  if (type_low_bound && TREE_CODE (type_low_bound) == INTEGER_CST)
     {
-      if (TREE_UNSIGNED (type))
-       return (! INT_CST_LT_UNSIGNED (TYPE_MAX_VALUE (type), c)
-               && ! INT_CST_LT_UNSIGNED (c, TYPE_MIN_VALUE (type))
-               /* Negative ints never fit unsigned types.  */
-               && ! (TREE_INT_CST_HIGH (c) < 0
-                     && ! TREE_UNSIGNED (TREE_TYPE (c))));
-      else
-       return (! INT_CST_LT (TYPE_MAX_VALUE (type), c)
-               && ! INT_CST_LT (c, TYPE_MIN_VALUE (type))
-               /* Unsigned ints with top bit set never fit signed types.  */
-               && ! (TREE_INT_CST_HIGH (c) < 0
-                     && TREE_UNSIGNED (TREE_TYPE (c))));
+      ok_for_low_bound = ! tree_int_cst_lt (c, type_low_bound);
+      if (! ok_for_low_bound)
+       return 0;
     }
+
+  /* Check if c <= type_high_bound.  */
+  if (type_high_bound && TREE_CODE (type_high_bound) == INTEGER_CST)
+    {
+      ok_for_high_bound = ! tree_int_cst_lt (type_high_bound, c);
+      if (! ok_for_high_bound)
+       return 0;
+    }
+
+  /* If the constant fits both bounds, the result is known.  */
+  if (ok_for_low_bound == 1 && ok_for_high_bound == 1)
+    return 1;
+
+  /* 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.  */
   else if (TREE_CODE (type) == INTEGER_TYPE && TREE_TYPE (type) != 0)
     return int_fits_type_p (c, TREE_TYPE (type));
+  
+  /* Or to force_fit_type, if nothing else.  */
   else
     {
       c = copy_node (c);
index c72e3d022c611f72b3e8dec4c014ef38a264e4c2..95f2ad4ac03b8806c85f20fa5e2af04a5b00e8be 100644 (file)
@@ -2300,6 +2300,7 @@ extern int tree_int_cst_lt                PARAMS ((tree, tree));
 extern int tree_int_cst_compare         PARAMS ((tree, tree));
 extern int host_integerp               PARAMS ((tree, int));
 extern HOST_WIDE_INT tree_low_cst      PARAMS ((tree, int));
+extern int tree_int_cst_msb            PARAMS ((tree));
 extern int tree_int_cst_sgn            PARAMS ((tree));
 extern int tree_expr_nonnegative_p     PARAMS ((tree));
 extern int rtl_expr_nonnegative_p      PARAMS ((rtx));