optimization/6909: problem w/ -Os on modified loop-2c.c test case.
Glen Nakamura
glen@imodulo.com
Sun Jun 2 18:51:00 GMT 2002
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.
Notes: This patch is a variation of a similar one posted in regard to PR6822.
I added "code = ??_EXPR;" in a number of places to keep "code" and
"TREE_CODE (t)" in sync. I couldn't think of a specific test case to expose
the problem, but I think it's correct and other places that use TREE_SET_CODE
do the same thing.
- Glen Nakamura
-------------- next part --------------
Index: fold-const.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.207
diff -c -3 -p -u -r1.207 fold-const.c
--- fold-const.c 1 Jun 2002 16:56:07 -0000 1.207
+++ fold-const.c 2 Jun 2002 21:32:28 -0000
@@ -5994,6 +5994,70 @@ fold (expr)
}
}
+ /* Change X >= CST to X > (CST - 1) and X < CST to X <= (CST - 1)
+ if CST is positive. This transformation affects the cases which are
+ handled in later optimizations involving comparisons with non-negative
+ constants. Remember to handle the equivalent > and <= cases instead
+ of the >= and < cases. Refer to the optimizations involving unsigned
+ comparisons with 0 and comparisons with the highest possible integer
+ of a specified type below for details of how this transformation
+ affects them. */
+ 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.
+ This optimization also applies to X >= 1 and X < 1 since those cases
+ are converted to X > 0 and X <= 0 by a previous transformation
+ which changes X >= CST to X > (CST - 1) and X < CST to X <= (CST - 1)
+ if CST is positive. */
+ 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. */
@@ -6017,6 +6081,7 @@ fold (expr)
convert (type, integer_zero_node),
arg0);
case GE_EXPR:
+ code = EQ_EXPR;
TREE_SET_CODE (t, EQ_EXPR);
break;
@@ -6025,9 +6090,38 @@ fold (expr)
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 a previous transformation changes
+ X >= CST to X > (CST - 1) and X < CST to X <= (CST - 1)
+ if CST is positive. The two new cases are handled
+ in the next switch statement. */
+
+ default:
+ break;
+ }
+
+ else if (TREE_INT_CST_HIGH (arg1) == 0
+ && (TREE_INT_CST_LOW (arg1)
+ == ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 2)
+ && ! TREE_UNSIGNED (TREE_TYPE (arg1)))
+ switch (TREE_CODE (t))
+ {
+ 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;
}
@@ -6043,6 +6137,7 @@ fold (expr)
convert (type, integer_zero_node),
arg0);
case LE_EXPR:
+ code = EQ_EXPR;
TREE_SET_CODE (t, EQ_EXPR);
break;
@@ -6051,6 +6146,7 @@ fold (expr)
convert (type, integer_one_node),
arg0);
case GT_EXPR:
+ code = NE_EXPR;
TREE_SET_CODE (t, NE_EXPR);
break;
@@ -6065,6 +6161,10 @@ fold (expr)
/* signed_type does not work on pointer types. */
&& INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
{
+ /* The following case also applies to X < (1 << (width - 1))
+ and X >= (1 << (width - 1)) because a previous
+ transformation changes X < CST to X <= (CST - 1)
+ and X >= CST to X > (CST - 1) if CST is positive. */
if (TREE_CODE (t) == LE_EXPR || TREE_CODE (t) == GT_EXPR)
{
tree st0, st1;
@@ -6076,6 +6176,7 @@ fold (expr)
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)
@@ -6087,6 +6188,7 @@ fold (expr)
convert (type, integer_zero_node),
arg0);
case GE_EXPR:
+ code = EQ_EXPR;
TREE_SET_CODE (t, EQ_EXPR);
break;
@@ -6095,67 +6197,43 @@ fold (expr)
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 a previous transformation changes
+ X >= CST to X > (CST - 1) and X < CST to X <= (CST - 1)
+ if CST is positive. The two new cases are handled
+ in the next switch statement. */
+
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;
- }
- }
+ else if (TREE_INT_CST_HIGH (arg1) == 0
+ && (TREE_INT_CST_LOW (arg1)
+ == ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 2)
+ && TREE_UNSIGNED (TREE_TYPE (arg1)))
+ switch (TREE_CODE (t))
+ {
+ 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;
- /* 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;
- }
- }
+ 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-bugs
mailing list