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]

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


There was still a bootstrap problem - ironically fold-const.c:fold got
miscompiled by (range) constant folding.
The code in make_range that was supposed to add a lower bound for unsigned
values was actually removing them - not that it makes any difference in
the type, but make_range doesn't look at the bounds, so if it doesn't
see any explicit bound it doesn't think there is any.
I don't want to spread code to extract the type bounds all over fold-const.c,
so instead I set out to avoid removing or failing to add explicit bounds
in merge_ranges.

The bootstrap went fine this time.
There are some c-torture failures.
I know the 991112-1.c are due to a bug in set_nonzero_bits_and_sign_copies;
I don't know about the others.
FAIL: gcc.c-torture/execute/991112-1.c execution,  -O3 -fomit-frame-pointer 
FAIL: gcc.c-torture/execute/991112-1.c execution,  -O3 -g 
FAIL: gcc.c-torture/execute/991202-3.c execution,  -O0 
FAIL: gcc.c-torture/execute/991202-3.c execution,  -O1 
FAIL: gcc.c-torture/execute/991202-3.c execution,  -O2 
FAIL: gcc.c-torture/execute/991202-3.c execution,  -O3 -fomit-frame-pointer 
FAIL: gcc.c-torture/execute/991202-3.c execution,  -O3 -g 
FAIL: gcc.c-torture/execute/991202-3.c execution,  -Os 
FAIL: gcc.c-torture/execute/complex-2.c execution,  -O1 
FAIL: gcc.c-torture/execute/conversion.c execution,  -O0 
FAIL: gcc.c-torture/execute/conversion.c execution,  -O1 
FAIL: gcc.c-torture/execute/cvt-1.c execution,  -O0 
FAIL: gcc.c-torture/execute/cvt-1.c execution,  -O1 
FAIL: gcc.c-torture/execute/ieee/mzero2.c execution,  -O0 
FAIL: gcc.c-torture/execute/ieee/mzero2.c execution,  -O1 

Fri Dec 31 01:55:08 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.
	(merge_ranges): When lowequal or highequal are set, make low/high
	values really equal.

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/31 01:53:48
*************** 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,3190 ----
       int upper0_p, upper1_p;
  {
    tree tem;
! /* com
!    men
!    t.  */
! 
!   /* 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,
--- 3293,3302 ----
  
  	      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;
--- 3511,3553 ----
    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)));
  
+   /* The caller sometimes expects to add an explicit bound, when one of the
+      ranges has one.  So if we found an equality of an implicit bound with
+      an explict one, standarize on the explicit one.  */
+   if (lowequal)
+     {
+       if (low0)
+ 	low1 = low0;
+       else
+ 	low0 = low1;
+     }
+ 
+   if (highequal)
+     {
+       if (high0)
+ 	high1 = high0;
+       else
+ 	high0 = high1;
+     }
+ 
    /* 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
--- 3558,3566 ----
    /* 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),
--- 3636,3642 ----
  	 second.  */
        if (no_overlap)
  	{
! 	  if (integer_onep (range_binop (EQ_EXPR, type,
  					 range_binop (PLUS_EXPR, NULL_TREE,
  						      high0, 1,
  						      integer_one_node, 1),


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