}
}
+ /* 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 (code)
+ {
+ case GE_EXPR:
+ code = GT_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 = LE_EXPR;
+ arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
+ t = build (code, type, TREE_OPERAND (t, 0), arg1);
+ break;
+
+ 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. */
+ the specified size will have known values. */
{
int width = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (arg1)));
&& (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)
- == ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1)
- && ! TREE_UNSIGNED (TREE_TYPE (arg1)))
- switch (TREE_CODE (t))
+ && 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) == -1
- && (TREE_INT_CST_LOW (arg1)
- == ((unsigned HOST_WIDE_INT) -1 << (width - 1)))
- && ! TREE_UNSIGNED (TREE_TYPE (arg1)))
- switch (TREE_CODE (t))
+ 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;
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)
- == ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1)
+ && 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)))
{
- if (TREE_CODE (t) == LE_EXPR || TREE_CODE (t) == GT_EXPR)
+ /* 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 (TREE_CODE (t) == LE_EXPR ? GE_EXPR: LT_EXPR,
+ (build (code == 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)
- {
- switch (TREE_CODE (t))
- {
- case GE_EXPR:
- code = GT_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 = LE_EXPR;
- arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
- t = build (code, type, TREE_OPERAND (t, 0), arg1);
- break;
-
- default:
- break;
- }
- }
-
- /* 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. */