[PATCH] Missing fold simplifications. (Fix PR6909 on mainline)
Richard Henderson
rth@redhat.com
Fri Jun 14 17:05:00 GMT 2002
On Sun, Jun 02, 2002 at 03:58:26PM -1000, Glen Nakamura wrote:
> http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=6909
>
> 2002-06-02 Glen Nakamura <glen@imodulo.com>
>
> * fold-const.c (fold): Move transformation of X >= CST to X > (CST - 1)
> and X < CST to X <= (CST - 1) to expose the following simplifications:
> 1. unsigned int < 0x80000000 to signed int >= 0.
> 2. unsigned int >= 0x80000000 to signed int < 0.
> 3. unsigned int > 0xfffffffe to unsigned int == 0xffffffff.
> 4. unsigned int <= 0xfffffffe to unsigned int != 0xffffffff.
I'm applying the following, which is simpler, but catches
the same sets of simplifications.
r~
* fold-const.c (fold) [compare ops]: Move X>=C / X<C transfomation
earlier. Re-factor comparisons vs extrema.
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.210
diff -c -p -d -u -r1.210 fold-const.c
--- fold-const.c 11 Jun 2002 22:36:53 -0000 1.210
+++ fold-const.c 14 Jun 2002 21:58:26 -0000
@@ -6013,9 +6013,34 @@ fold (expr)
}
}
+ /* 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)));
@@ -6025,43 +6050,76 @@ fold (expr)
&& (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;
@@ -6070,111 +6128,52 @@ fold (expr)
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
More information about the Gcc-patches
mailing list