fold-const.c (fold): Move X>=C / X<C transfomation earlier.

* fold-const.c (fold) [compare ops]: Move X>=C / X<C transfomation
        earlier.  Re-factor comparisons vs extrema.

From-SVN: r54626
This commit is contained in:
Richard Henderson 2002-06-14 17:06:18 -07:00 committed by Richard Henderson
parent d95eb49f76
commit fa4a5557dd
2 changed files with 144 additions and 140 deletions

View File

@ -1,3 +1,8 @@
2002-06-14 Richard Henderson <rth@redhat.com>
* fold-const.c (fold) [compare ops]: Move X>=C / X<C transfomation
earlier. Re-factor comparisons vs extrema.
2002-06-14 Richard Henderson <rth@redhat.com>
* config/alpha/alpha.md (builtin_zapnot): Fix op2 mode.

View File

@ -6013,122 +6013,14 @@ fold (expr)
}
}
/* Comparisons with the highest or lowest possible integer of
the specified size will have known values and an unsigned
<= 0x7fffffff can be simplified. */
{
int width = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (arg1)));
if (TREE_CODE (arg1) == INTEGER_CST
&& ! TREE_CONSTANT_OVERFLOW (arg1)
&& width <= HOST_BITS_PER_WIDE_INT
&& (INTEGRAL_TYPE_P (TREE_TYPE (arg1))
|| POINTER_TYPE_P (TREE_TYPE (arg1))))
{
if (TREE_INT_CST_HIGH (arg1) == 0
&& (TREE_INT_CST_LOW (arg1)
== ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1)
&& ! TREE_UNSIGNED (TREE_TYPE (arg1)))
switch (TREE_CODE (t))
{
case GT_EXPR:
return omit_one_operand (type,
convert (type, integer_zero_node),
arg0);
case GE_EXPR:
TREE_SET_CODE (t, EQ_EXPR);
break;
case LE_EXPR:
return omit_one_operand (type,
convert (type, integer_one_node),
arg0);
case LT_EXPR:
TREE_SET_CODE (t, NE_EXPR);
break;
default:
break;
}
else if (TREE_INT_CST_HIGH (arg1) == -1
&& (TREE_INT_CST_LOW (arg1)
== ((unsigned HOST_WIDE_INT) -1 << (width - 1)))
&& ! TREE_UNSIGNED (TREE_TYPE (arg1)))
switch (TREE_CODE (t))
{
case LT_EXPR:
return omit_one_operand (type,
convert (type, integer_zero_node),
arg0);
case LE_EXPR:
TREE_SET_CODE (t, EQ_EXPR);
break;
case GE_EXPR:
return omit_one_operand (type,
convert (type, integer_one_node),
arg0);
case GT_EXPR:
TREE_SET_CODE (t, NE_EXPR);
break;
default:
break;
}
else if (TREE_INT_CST_HIGH (arg1) == 0
&& (TREE_INT_CST_LOW (arg1)
== ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1)
&& TREE_UNSIGNED (TREE_TYPE (arg1))
/* signed_type does not work on pointer types. */
&& INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
{
if (TREE_CODE (t) == LE_EXPR || TREE_CODE (t) == GT_EXPR)
{
tree st0, st1;
st0 = (*lang_hooks.types.signed_type) (TREE_TYPE (arg0));
st1 = (*lang_hooks.types.signed_type) (TREE_TYPE (arg1));
return fold
(build (TREE_CODE (t) == LE_EXPR ? GE_EXPR: LT_EXPR,
type, convert (st0, arg0),
convert (st1, integer_zero_node)));
}
}
else if (TREE_INT_CST_HIGH (arg1) == 0
&& (TREE_INT_CST_LOW (arg1)
== ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1)
&& TREE_UNSIGNED (TREE_TYPE (arg1)))
switch (TREE_CODE (t))
{
case GT_EXPR:
return omit_one_operand (type,
convert (type, integer_zero_node),
arg0);
case GE_EXPR:
TREE_SET_CODE (t, EQ_EXPR);
break;
case LE_EXPR:
return omit_one_operand (type,
convert (type, integer_one_node),
arg0);
case LT_EXPR:
TREE_SET_CODE (t, NE_EXPR);
break;
default:
break;
}
}
}
/* Change X >= C to X > C-1 and X < C to X <= C-1 if C is positive. */
/* Change X >= C to X > (C - 1) and X < C to X <= (C - 1) if C > 0.
This transformation affects the cases which are handled in later
optimizations involving comparisons with non-negative constants. */
if (TREE_CODE (arg1) == INTEGER_CST
&& TREE_CODE (arg0) != INTEGER_CST
&& tree_int_cst_sgn (arg1) > 0)
{
switch (TREE_CODE (t))
switch (code)
{
case GE_EXPR:
code = GT_EXPR;
@ -6147,34 +6039,141 @@ fold (expr)
}
}
/* An unsigned comparison against 0 can be simplified. */
if (integer_zerop (arg1)
&& (INTEGRAL_TYPE_P (TREE_TYPE (arg1))
|| POINTER_TYPE_P (TREE_TYPE (arg1)))
&& TREE_UNSIGNED (TREE_TYPE (arg1)))
{
switch (TREE_CODE (t))
{
case GT_EXPR:
code = NE_EXPR;
TREE_SET_CODE (t, NE_EXPR);
break;
case LE_EXPR:
code = EQ_EXPR;
TREE_SET_CODE (t, EQ_EXPR);
break;
case GE_EXPR:
return omit_one_operand (type,
convert (type, integer_one_node),
arg0);
case LT_EXPR:
return omit_one_operand (type,
convert (type, integer_zero_node),
arg0);
default:
break;
}
}
/* Comparisons with the highest or lowest possible integer of
the specified size will have known values. */
{
int width = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (arg1)));
if (TREE_CODE (arg1) == INTEGER_CST
&& ! TREE_CONSTANT_OVERFLOW (arg1)
&& width <= HOST_BITS_PER_WIDE_INT
&& (INTEGRAL_TYPE_P (TREE_TYPE (arg1))
|| POINTER_TYPE_P (TREE_TYPE (arg1))))
{
unsigned HOST_WIDE_INT signed_max;
unsigned HOST_WIDE_INT max, min;
signed_max = ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1;
if (TREE_UNSIGNED (TREE_TYPE (arg1)))
{
max = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1;
min = 0;
}
else
{
max = signed_max;
min = ((unsigned HOST_WIDE_INT) -1 << (width - 1));
}
if (TREE_INT_CST_HIGH (arg1) == 0
&& TREE_INT_CST_LOW (arg1) == max)
switch (code)
{
case GT_EXPR:
return omit_one_operand (type,
convert (type, integer_zero_node),
arg0);
case GE_EXPR:
code = EQ_EXPR;
TREE_SET_CODE (t, EQ_EXPR);
break;
case LE_EXPR:
return omit_one_operand (type,
convert (type, integer_one_node),
arg0);
case LT_EXPR:
code = NE_EXPR;
TREE_SET_CODE (t, NE_EXPR);
break;
/* The GE_EXPR and LT_EXPR cases above are not normally
reached because of previous transformations. */
default:
break;
}
else if (TREE_INT_CST_HIGH (arg1) == 0
&& TREE_INT_CST_LOW (arg1) == max - 1)
switch (code)
{
case GT_EXPR:
code = EQ_EXPR;
arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0);
t = build (code, type, TREE_OPERAND (t, 0), arg1);
break;
case LE_EXPR:
code = NE_EXPR;
arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0);
t = build (code, type, TREE_OPERAND (t, 0), arg1);
break;
default:
break;
}
else if (TREE_INT_CST_HIGH (arg1) == (min ? -1 : 0)
&& TREE_INT_CST_LOW (arg1) == min)
switch (code)
{
case LT_EXPR:
return omit_one_operand (type,
convert (type, integer_zero_node),
arg0);
case LE_EXPR:
code = EQ_EXPR;
TREE_SET_CODE (t, EQ_EXPR);
break;
case GE_EXPR:
return omit_one_operand (type,
convert (type, integer_one_node),
arg0);
case GT_EXPR:
code = NE_EXPR;
TREE_SET_CODE (t, NE_EXPR);
break;
default:
break;
}
else if (TREE_INT_CST_HIGH (arg1) == (min ? -1 : 0)
&& TREE_INT_CST_LOW (arg1) == min + 1)
switch (code)
{
case GE_EXPR:
code = NE_EXPR;
arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
t = build (code, type, TREE_OPERAND (t, 0), arg1);
break;
case LT_EXPR:
code = EQ_EXPR;
arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
t = build (code, type, TREE_OPERAND (t, 0), arg1);
break;
default:
break;
}
else if (TREE_INT_CST_HIGH (arg1) == 0
&& TREE_INT_CST_LOW (arg1) == signed_max
&& TREE_UNSIGNED (TREE_TYPE (arg1))
/* signed_type does not work on pointer types. */
&& INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
{
/* The following case also applies to X < signed_max+1
and X >= signed_max+1 because previous transformations. */
if (code == LE_EXPR || code == GT_EXPR)
{
tree st0, st1;
st0 = (*lang_hooks.types.signed_type) (TREE_TYPE (arg0));
st1 = (*lang_hooks.types.signed_type) (TREE_TYPE (arg1));
return fold
(build (code == LE_EXPR ? GE_EXPR: LT_EXPR,
type, convert (st0, arg0),
convert (st1, integer_zero_node)));
}
}
}
}
/* If this is an EQ or NE comparison of a constant with a PLUS_EXPR or
a MINUS_EXPR of a constant, we can convert it into a comparison with