This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
fix for execute/991221-1.c -O1 failure
- To: gcc-patches at gcc dot gnu dot org
- Subject: fix for execute/991221-1.c -O1 failure
- From: Joern Rennecke <amylaar at cygnus dot co dot uk>
- Date: Fri, 24 Dec 1999 05:39:51 +0000 (GMT)
- CC: amylaar at pasanda dot cygnus dot co dot uk, kenner at vlsi1 dot ultra dot nyu dot edu
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),