This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH: incorrect optimization of ((i < 0) && (i >= 0))
- To: egcs-patches at egcs dot cygnus dot com
- Subject: PATCH: incorrect optimization of ((i < 0) && (i >= 0))
- From: Nathan Sidwell <nathan at acm dot org>
- Date: Thu, 04 Feb 1999 15:30:36 +0000
- CC: yergeau at gloworm dot stanford dot edu
- Organization: University of Bristol
- Reply-To: nathan at compsci dot bristol dot ac dot uk
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;
}