[multiple changes]

2002-05-15  Jakub Jelinek  <jakub@redhat.com>

        * fold-const.c (fold): Fix a typo.

2002-05-15  Eric Botcazou  <ebotcazou@multimania.com>

        * fold-const.c (fold) [LT_EXPR]: Move the transformation of a
        comparison against the highest or lowest integer value before
        the 'X >= CST to X > (CST - 1)' and 'X < CST to X <= (CST - 1)'
        transformation and that of an unsigned comparison against 0
        right after.

From-SVN: r53493
This commit is contained in:
Richard Henderson 2002-05-15 13:39:55 -07:00
parent 14285ace88
commit 033afd1106
2 changed files with 152 additions and 140 deletions

View File

@ -1,3 +1,15 @@
2002-05-15 Jakub Jelinek <jakub@redhat.com>
* fold-const.c (fold): Fix a typo.
2002-05-15 Eric Botcazou <ebotcazou@multimania.com>
* fold-const.c (fold) [LT_EXPR]: Move the transformation of a
comparison against the highest or lowest integer value before
the 'X >= CST to X > (CST - 1)' and 'X < CST to X <= (CST - 1)'
transformation and that of an unsigned comparison against 0
right after.
2002-05-15 Richard Henderson <rth@redhat.com>
* varasm.c (merge_weak): Error for any weakening after definition.

View File

@ -5962,7 +5962,117 @@ fold (expr)
}
}
/* Change X >= CST to X > (CST - 1) if CST is positive. */
/* 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. */
if (TREE_CODE (arg1) == INTEGER_CST
&& TREE_CODE (arg0) != INTEGER_CST
&& tree_int_cst_sgn (arg1) > 0)
@ -5986,6 +6096,35 @@ 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;
}
}
/* 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
a revised constant as long as no overflow occurs. */
@ -6191,145 +6330,6 @@ 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 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;
}
}
}
/* If we are comparing an expression that just has comparisons
of two integer values, arithmetic expressions of those comparisons,
and constants, we can simplify it. There are only three cases