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]

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


execute/991221-1.c fails for SH when optimizing.
The first problem occurs when make_range knows about the value being
outside the range of (, UINT_MAX) and tries to merge knowledge that
it cannot be smaller than 0.

          /* If this is an unsigned comparison, we also know that EXP is
             greater than or equal to zero.  We base the range tests we make
             on that fact, so we record it here so we can parse existing
             range tests.  */
          if (TREE_UNSIGNED (type) && (low == 0 || high == 0))
            {
              if (! merge_ranges (&n_in_p, &n_low, &n_high, in_p, low, high,
                                  1, convert (type, integer_zero_node),
                                  NULL_TREE))
                break;

merge_ranges uses range_binop to determine if (0, ) is a subset of
(, UINT_MAX) .

  /* 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, integer_type_node,
                                      high1, 1, high0, 1));

range_binop says it is not.  It is passed the wrong type - signed integer
instead of unsigned integer - but even when this is fixed, it still needs
to actually look at its bounds to realize that UNIT_MAX is the largest
value of TYPE, and hence (, UINT_MAX) is effeectively unbounded.

The second problem is a minor one: make range wants to reverse an unsigned
range if there is no upper bound, and it even tries that when there is
no lower bound.

I'm currently running tests for this patch:

Fri Dec 24 05:28:29 1999  J"orn Rennecke <amylaar@cygnus.co.uk>

	* fold-const.c (range_binop): Recognize when a bound is the same
	as the corresponding bound of its 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/24 05:13:02
*************** range_binop (code, type, arg0, upper0_p,
*** 3180,3187 ****
       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:
--- 3180,3199 ----
       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 = (upper0_p
! 	  ? ((! arg0
! 	      || operand_equal_p (arg0, TYPE_MAX_VALUE (TREE_TYPE (arg0)), 1))
! 	     ? 1 : 0)
! 	  : ((! arg0
! 	      || operand_equal_p (arg0, TYPE_MIN_VALUE (TREE_TYPE (arg0)), 1))
! 	     ? -1 : 0));
!   sgn1 = (upper1_p
! 	  ? ((! arg1
! 	      || operand_equal_p (arg1, TYPE_MAX_VALUE (TREE_TYPE (arg1)), 1))
! 	     ? 1 : 0)
! 	  : ((! arg1
! 	      || operand_equal_p (arg1, TYPE_MIN_VALUE (TREE_TYPE (arg1)), 1))
! 	     ? -1 : 0));
    switch (code)
      {
      case EQ_EXPR:
*************** 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,
--- 3327,3336 ----
  
  	      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;
--- 3545,3568 ----
    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
--- 3573,3581 ----
    /* 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),
--- 3651,3657 ----
  	 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]