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]

PATCH: incorrect optimization of ((i < 0) && (i >= 0))


Hi,
attached is a patch and test case for the above problem.

range_binop is used inside merge_ranges to compare two range ends, each of
which might be unbounded. (have an infinite end value) Where at least one of
the ends is unbounded, a reduction is made using the algebraic rules of
unbounded values and a yes/no result is returned.

This is incorrect on two counts.
1) If both values are unbounded, we sometimes have to give a `maybe' result,
rather than a definite yes/no answer.
2) but we're not in the domain of infinite integers, we're in the domain of
fixed length comupter arithmetic. It is therefore legitimate to replace any
unbounded range (infinite value), with the specific value Z, larger than any
representable value. Doing the comparisons against Z leads to consistent
results where we can always give a yes/no result.

This patch does that. When one of the values is unbounded, we replace the
comparision with that of -Z, not Z, +Z.

Running the existing test suite with this patch gives no changes in the passes
and failures on a sparc solars 2.6 box.

The provided test case, causes the current snapshot to abort at -O1 and
greater, without this patch.

nathan

-- 
Dr Nathan Sidwell :: Computer Science Department :: Bristol University
      You can up the bandwidth, but you can't up the speed of light      
nathan@acm.org  http://www.cs.bris.ac.uk/~nathan/  nathan@cs.bris.ac.uk
Thu Feb  4 15:02:22 GMT 1999  Nathan Sidwell  <nathan@acm.org>

	* fold-const.c (range_binop): Take account of the bounded nature
	of fixed length arithmetic when comparing unbounded ranges.

Index: egcs/gcc/fold-const.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/fold-const.c,v
retrieving revision 1.54
diff -c -3 -p -r1.54 fold-const.c
*** fold-const.c	1999/01/27 07:28:14	1.54
--- fold-const.c	1999/02/04 12:26:41
*************** range_binop (code, type, arg0, upper0_p,
*** 3009,3028 ****
      return 0;
  
    /* Set SGN[01] to -1 if ARG[01] is a lower bound, 1 for upper, and 0
!      for neither.  Then compute our result treating them as never equal
!      and comparing bounds to non-bounds as above.  */
    sgn0 = arg0 != 0 ? 0 : (upper0_p ? 1 : -1);
    sgn1 = arg1 != 0 ? 0 : (upper1_p ? 1 : -1);
    switch (code)
      {
!     case EQ_EXPR:  case NE_EXPR:
!       result = (code == NE_EXPR);
        break;
!     case LT_EXPR:  case LE_EXPR:
        result = sgn0 < sgn1;
        break;
!     case GT_EXPR:  case GE_EXPR:
        result = sgn0 > sgn1;
        break;
      default:
        abort ();
--- 3009,3040 ----
      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 ();
/* Copyright (C) 1999 Free Software Foundation, Inc.
  Contributed by Nathan Sidwell 20 Jan 1999 <nathan@acm.org> */

/* check range combining boolean operations work */

extern void abort();

#define N 77

void func(int i)
{
  /* fold-const does some clever things with range tests. Make sure
     we get (some of) them right */
  
  /* these must fail, regardless of the value of i */
  if ((i < 0) && (i >= 0))
    abort();
  if ((i > 0) && (i <= 0))
    abort();
  if ((i >= 0) && (i < 0))
    abort();
  if ((i <= 0) && (i > 0))
    abort();

  if ((i < N) && (i >= N))
    abort();
  if ((i > N) && (i <= N))
    abort();
  if ((i >= N) && (i < N))
    abort();
  if ((i <= N) && (i > N))
    abort();
    
  /* these must pass, regardless of the value of i */
  if (! ((i < 0) || (i >= 0)))
    abort();
  if (! ((i > 0) || (i <= 0)))
    abort();
  if (! ((i >= 0) || (i < 0)))
    abort();
  if (! ((i <= 0) || (i > 0)))
    abort();

  if (! ((i < N) || (i >= N)))
    abort();
  if (! ((i > N) || (i <= N)))
    abort();
  if (! ((i >= N) || (i < N)))
    abort();
  if (! ((i <= N) || (i > N)))
    abort();
  
  return;
}

int main()
{
  func(0);
  func(1);
  return 0;
}

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