fold-const.c (make_range): Correctly handle cases of converting from unsigned to signed type.

* fold-const.c (make_range): Correctly handle cases of converting
        from unsigned to signed type.

        * fold-const.c (merge_ranges): Make sure that if one range is subset
        of another, it will always be the second range.  Correct (+,-) case to
        account for this.

Brought over from gcc2; fixes sparc bug.

From-SVN: r15678
This commit is contained in:
Jeff Law 1997-09-23 12:35:51 -06:00
parent 4bc8c3c116
commit ce2157a1a9
2 changed files with 91 additions and 22 deletions

View File

@ -1,3 +1,14 @@
Tue Sep 23 12:34:51 1997 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* fold-const.c (make_range): Correctly handle cases of converting
from unsigned to signed type.
Tue Sep 23 12:34:51 1997 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
* fold-const.c (merge_ranges): Make sure that if one range is subset
of another, it will always be the second range. Correct (+,-) case to
account for this.
Tue Sep 23 01:15:50 1997 David S. Miller <davem@tanya.rutgers.edu> Tue Sep 23 01:15:50 1997 David S. Miller <davem@tanya.rutgers.edu>
* expmed.c (expand_divmod): If compute_mode is not the same as * expmed.c (expand_divmod): If compute_mode is not the same as

View File

@ -2863,14 +2863,62 @@ make_range (exp, pin_p, plow, phigh)
|| (high != 0 && ! int_fits_type_p (high, type))) || (high != 0 && ! int_fits_type_p (high, type)))
break; break;
if (low != 0) n_low = low, n_high = high;
low = convert (type, low);
if (high != 0) if (n_low != 0)
high = convert (type, high); n_low = convert (type, n_low);
if (n_high != 0)
n_high = convert (type, n_high);
/* If we're converting from an unsigned to a signed type,
we will be doing the comparison as unsigned. The tests above
have already verified that LOW and HIGH are both positive.
So we have to make sure that the original unsigned value will
be interpreted as positive. */
if (TREE_UNSIGNED (type) && ! TREE_UNSIGNED (TREE_TYPE (exp)))
{
tree equiv_type = type_for_mode (TYPE_MODE (type), 1);
tree high_positive
= fold (build (RSHIFT_EXPR, type,
convert (type,
TYPE_MAX_VALUE (equiv_type)),
convert (type, integer_one_node)));
/* If the low bound is specified, "and" the range with the
range for which the original unsigned value will be
positive. */
if (low != 0)
{
if (! merge_ranges (&n_in_p, &n_low, &n_high,
1, n_low, n_high,
1, convert (type, integer_zero_node),
high_positive))
break;
in_p = (n_in_p == in_p);
}
else
{
/* Otherwise, "or" the range with the range of the input
that will be interpreted as negative. */
if (! merge_ranges (&n_in_p, &n_low, &n_high,
0, n_low, n_high,
1, convert (type, integer_zero_node),
high_positive))
break;
in_p = (in_p != n_in_p);
}
}
exp = arg0; exp = arg0;
low = n_low, high = n_high;
continue; continue;
default:
break;
} }
break; break;
@ -2956,15 +3004,20 @@ merge_ranges (pin_p, plow, phigh, in0_p, low0, high0, in1_p, low1, high1)
tree tem; tree tem;
int in_p; int in_p;
tree low, high; 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. Swap them if it isn't. */ /* 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, if (integer_onep (range_binop (GT_EXPR, integer_type_node,
low0, 0, low1, 0)) low0, 0, low1, 0))
|| (((low0 == 0 && low1 == 0) || (lowequal
|| integer_onep (range_binop (EQ_EXPR, integer_type_node,
low0, 0, low1, 0)))
&& integer_onep (range_binop (GT_EXPR, integer_type_node, && integer_onep (range_binop (GT_EXPR, integer_type_node,
high0, 1, high1, 1)))) high1, 1, high0, 1))))
{ {
temp = in0_p, in0_p = in1_p, in1_p = temp; temp = in0_p, in0_p = in1_p, in1_p = temp;
tem = low0, low0 = low1, low1 = tem; tem = low0, low0 = low1, low1 = tem;
@ -2996,27 +3049,32 @@ merge_ranges (pin_p, plow, phigh, in0_p, low0, high0, in1_p, low1, high1)
else if (in0_p && ! in1_p) else if (in0_p && ! in1_p)
{ {
/* If they don't overlap, the result is the first range. If the /* If they don't overlap, the result is the first range. If they are
second range is a subset of the first, we can't describe this as equal, the result is false. If the second range is a subset of the
a single range unless both ranges end at the same place. If both first, and the ranges begin at the same place, we go from just after
ranges start in the same place, then the result is false. the end of the first range to the end of the second. If the second
Otherwise, we go from the start of the first range to just before range is not a subset of the first, or if it is a subset and both
the start of the second. */ ranges end at the same place, the range starts at the start of the
first range and ends just before the second range.
Otherwise, we can't describe this as a single range. */
if (no_overlap) if (no_overlap)
in_p = 1, low = low0, high = high0; in_p = 1, low = low0, high = high0;
else if (subset else if (lowequal && highequal)
&& integer_zerop (range_binop (EQ_EXPR, integer_type_node,
high0, 1, high1, 0)))
return 0;
else if (integer_onep (range_binop (EQ_EXPR, integer_type_node,
low0, 0, low1, 0)))
in_p = 0, low = high = 0; in_p = 0, low = high = 0;
else else if (subset && lowequal)
{
in_p = 1, high = high0;
low = range_binop (PLUS_EXPR, NULL_TREE, high1, 0,
integer_one_node, 0);
}
else if (! subset || highequal)
{ {
in_p = 1, low = low0; in_p = 1, low = low0;
high = range_binop (MINUS_EXPR, NULL_TREE, low1, 0, high = range_binop (MINUS_EXPR, NULL_TREE, low1, 0,
integer_one_node, 0); integer_one_node, 0);
} }
else
return 0;
} }
else if (! in0_p && in1_p) else if (! in0_p && in1_p)