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:
parent
d95eb49f76
commit
fa4a5557dd
2 changed files with 144 additions and 140 deletions
|
@ -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.
|
||||
|
|
279
gcc/fold-const.c
279
gcc/fold-const.c
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue