fix for execute/991221-1.c -O1 failure

Joern Rennecke amylaar@cygnus.co.uk
Thu Dec 30 13:10:00 GMT 1999


I thought a bit more about the problem in range_binop and came to the
conlusion that we really need to check both minimum and maximum for arg0,
and independent of upper0_p - because we really compare this value to arg1.
So arg0 being equal to a bound matters iff arg1 is 0, i.e. to be assumed to
be a bound.  And vice versa.
Once we calculate upper and lower bounds, there is really no good reason
to do this messy calculation by hand.  We can just use the values of the
bounds in the ordinary comparisons.

I handle pointers types by calling type_for_size to get the matching
integer type.

Thu Dec 30 21:06:16 1999  J"orn Rennecke <amylaar@cygnus.co.uk>

	* fold-const.c (range_binop): For suprenum / infimum comparisons,
	use the actual minimum / maximum value of the type.
	(make_range): Don't try to reverse an unbounded range.
	(merge_ranges): Perform operations in the appropriate type.

Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/fold-const.c,v
retrieving revision 1.93
diff -p -r1.93 fold-const.c
*** fold-const.c	1999/12/21 06:02:59	1.93
--- fold-const.c	1999/12/30 21:00:26
*************** range_binop (code, type, arg0, upper0_p,
*** 3155,3212 ****
       int upper0_p, upper1_p;
  {
    tree tem;
-   int result;
-   int sgn0, sgn1;
  
!   /* If neither arg represents infinity, do the normal operation.
!      Else, if not a comparison, return infinity.  Else handle the special
!      comparison rules. Note that most of the cases below won't occur, but
!      are handled for consistency.  */
! 
!   if (arg0 != 0 && arg1 != 0)
      {
!       tem = fold (build (code, type != 0 ? type : TREE_TYPE (arg0),
! 			 arg0, convert (TREE_TYPE (arg0), arg1)));
!       STRIP_NOPS (tem);
!       return TREE_CODE (tem) == INTEGER_CST ? tem : 0;
!     }
  
!   if (TREE_CODE_CLASS (code) != '<')
!     return 0;
  
!   /* Set SGN[01] to -1 if ARG[01] is a lower bound, 1 for upper, and 0
!      for neither.  In real maths, we cannot assume open ended ranges are
!      the same. But, this is computer arithmetic, where numbers are finite.
!      We can therefore make the transformation of any unbounded range with
!      the value Z, Z being greater than any representable number. This permits
!      us to treat unbounded ranges as equal. */
!   sgn0 = arg0 != 0 ? 0 : (upper0_p ? 1 : -1);
!   sgn1 = arg1 != 0 ? 0 : (upper1_p ? 1 : -1);
!   switch (code)
!     {
!     case EQ_EXPR:
!       result = sgn0 == sgn1;
!       break;
!     case NE_EXPR:
!       result = sgn0 != sgn1;
!       break;
!     case LT_EXPR:
!       result = sgn0 < sgn1;
!       break;
!     case LE_EXPR:
!       result = sgn0 <= sgn1;
!       break;
!     case GT_EXPR:
!       result = sgn0 > sgn1;
!       break;
!     case GE_EXPR:
!       result = sgn0 >= sgn1;
!       break;
!     default:
!       abort ();
      }
  
!   return convert (type, result ? integer_one_node : integer_zero_node);
  }
        
  /* Given EXP, a logical expression, set the range it is testing into
--- 3155,3187 ----
       int upper0_p, upper1_p;
  {
    tree tem;
  
!   /* If either of the values represents a supremum / infimum, get the 
!      appropriate bound from the type.  This way, we won't get confused
!      when we compare a bound represented as 0 with its actual value.  */
!   if (arg0 == NULL_PTR || arg1 == NULL_PTR)
      {
!       tree btype;
  
!       /* If this is not a comparison, we can't compute the result.  */
!       if (TREE_CODE_CLASS (code) != '<')
! 	return 0;
  
!       /* Pointer types have no explicit
! 	 bounds, so get an integer type instead.  */
!       btype = (TREE_CODE (type) == POINTER_TYPE
! 	       ? type_for_size (TYPE_PRECISION (type), TREE_UNSIGNED (type))
! 	       : type);
!       if (arg0 == NULL_PTR)
! 	arg0 = upper0_p ? TYPE_MAX_VALUE (btype) : TYPE_MIN_VALUE (btype);
!       if (arg1 == NULL_PTR)
! 	arg1 = upper1_p ? TYPE_MAX_VALUE (btype) : TYPE_MIN_VALUE (btype);
      }
  
!   tem = fold (build (code, type != 0 ? type : TREE_TYPE (arg0),
! 		     arg0, convert (TREE_TYPE (arg0), arg1)));
!   STRIP_NOPS (tem);
!   return TREE_CODE (tem) == INTEGER_CST ? tem : 0;
  }
        
  /* Given EXP, a logical expression, set the range it is testing into
*************** make_range (exp, pin_p, plow, phigh)
*** 3315,3323 ****
  
  	      in_p = n_in_p, low = n_low, high = n_high;
  
! 	      /* If the high bound is missing, reverse the range so it
! 		 goes from zero to the low bound minus 1.  */
! 	      if (high == 0)
  		{
  		  in_p = ! in_p;
  		  high = range_binop (MINUS_EXPR, NULL_TREE, low, 0,
--- 3290,3299 ----
  
  	      in_p = n_in_p, low = n_low, high = n_high;
  
! 	      /* If the high bound is missing, but we
! 		 have a low bound, reverse the range so
! 		 it goes from zero to the low bound minus 1.  */
! 	      if (high == 0 && low)
  		{
  		  in_p = ! in_p;
  		  high = range_binop (MINUS_EXPR, NULL_TREE, low, 0,
*************** merge_ranges (pin_p, plow, phigh, in0_p,
*** 3532,3550 ****
    tree tem;
    int in_p;
    tree low, high;
    int lowequal = ((low0 == 0 && low1 == 0)
! 		  || integer_onep (range_binop (EQ_EXPR, integer_type_node,
  						low0, 0, low1, 0)));
    int highequal = ((high0 == 0 && high1 == 0)
! 		   || integer_onep (range_binop (EQ_EXPR, integer_type_node,
  						 high0, 1, high1, 1)));
  
    /* Make range 0 be the range that starts first, or ends last if they
       start at the same value.  Swap them if it isn't.  */
!   if (integer_onep (range_binop (GT_EXPR, integer_type_node, 
  				 low0, 0, low1, 0))
        || (lowequal
! 	  && integer_onep (range_binop (GT_EXPR, integer_type_node,
  					high1, 1, high0, 1))))
      {
        temp = in0_p, in0_p = in1_p, in1_p = temp;
--- 3508,3531 ----
    tree tem;
    int in_p;
    tree low, high;
+   tree type = (low0 ? TREE_TYPE (low0)
+ 	       : high0 ? TREE_TYPE (high0)
+ 	       : low1 ? TREE_TYPE (low1)
+ 	       : high1 ? TREE_TYPE (high1)
+ 	       : integer_type_node);
    int lowequal = ((low0 == 0 && low1 == 0)
! 		  || integer_onep (range_binop (EQ_EXPR, type,
  						low0, 0, low1, 0)));
    int highequal = ((high0 == 0 && high1 == 0)
! 		   || integer_onep (range_binop (EQ_EXPR, type,
  						 high0, 1, high1, 1)));
  
    /* Make range 0 be the range that starts first, or ends last if they
       start at the same value.  Swap them if it isn't.  */
!   if (integer_onep (range_binop (GT_EXPR, type,
  				 low0, 0, low1, 0))
        || (lowequal
! 	  && integer_onep (range_binop (GT_EXPR, type,
  					high1, 1, high0, 1))))
      {
        temp = in0_p, in0_p = in1_p, in1_p = temp;
*************** merge_ranges (pin_p, plow, phigh, in0_p,
*** 3555,3563 ****
    /* Now flag two cases, whether the ranges are disjoint or whether the
       second range is totally subsumed in the first.  Note that the tests
       below are simplified by the ones above.  */
!   no_overlap = integer_onep (range_binop (LT_EXPR, integer_type_node,
  					  high0, 1, low1, 0));
!   subset = integer_onep (range_binop (LE_EXPR, integer_type_node,
  				      high1, 1, high0, 1));
  
    /* We now have four cases, depending on whether we are including or
--- 3536,3544 ----
    /* Now flag two cases, whether the ranges are disjoint or whether the
       second range is totally subsumed in the first.  Note that the tests
       below are simplified by the ones above.  */
!   no_overlap = integer_onep (range_binop (LT_EXPR, type,
  					  high0, 1, low1, 0));
!   subset = integer_onep (range_binop (LE_EXPR, type,
  				      high1, 1, high0, 1));
  
    /* We now have four cases, depending on whether we are including or
*************** merge_ranges (pin_p, plow, phigh, in0_p,
*** 3633,3639 ****
  	 second.  */
        if (no_overlap)
  	{
! 	  if (integer_onep (range_binop (EQ_EXPR, integer_type_node,
  					 range_binop (PLUS_EXPR, NULL_TREE,
  						      high0, 1,
  						      integer_one_node, 1),
--- 3614,3620 ----
  	 second.  */
        if (no_overlap)
  	{
! 	  if (integer_onep (range_binop (EQ_EXPR, type,
  					 range_binop (PLUS_EXPR, NULL_TREE,
  						      high0, 1,
  						      integer_one_node, 1),


More information about the Gcc-patches mailing list