This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Refine test in int_fits_type_p


This fixes a run-time error of the following Ada testcase on HPUX.

Tested on i686-pc-linux-gnu.

procedure P is

  subtype Range_T is Integer range -1 .. 1;

  function
    Bound_Value
    return Integer
  is
  begin
    return 1;
  end;

  Limit : constant Integer := Bound_Value;
  X : Range_T;

begin
   for Value in 1 .. Limit  loop
      X := Integer (Value);
   end loop;
end;

Thu Oct 17 08:59:38 2002  Olivier Hainque <hainque at act-europe dot 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.

*** gcc/tree.c	11 Apr 2003 00:24:58 -0000	1.294
--- gcc/tree.c	11 Apr 2003 21:45:06 -0000
*************** tree_low_cst (t, pos)
*** 3223,3226 ****
--- 3223,3244 ----
  }
  
+ /* 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.
*************** int_fits_type_p (c, type)
*** 4047,4073 ****
       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)
!     {
!       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))));
      }
    else if (TREE_CODE (type) == INTEGER_TYPE && TREE_TYPE (type) != 0)
      return int_fits_type_p (c, TREE_TYPE (type));
    else
      {
--- 4065,4120 ----
       tree c, type;
  {
!   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)
!     {
!       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
      {
*** gcc/tree.h	11 Apr 2003 00:24:58 -0000	1.390
--- gcc/tree.h	11 Apr 2003 21:45:10 -0000
*************** extern int tree_int_cst_compare         
*** 2309,2312 ****
--- 2309,2313 ----
  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));


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]