From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 24301 invoked by alias); 3 Jun 2002 01:56:02 -0000 Mailing-List: contact gcc-prs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-prs-owner@gcc.gnu.org Received: (qmail 24287 invoked by uid 71); 3 Jun 2002 01:56:02 -0000 Date: Sun, 02 Jun 2002 18:56:00 -0000 Message-ID: <20020603015602.24286.qmail@sources.redhat.com> To: nobody@gcc.gnu.org Cc: gcc-prs@gcc.gnu.org, From: Glen Nakamura Subject: Re: optimization/6909: problem w/ -Os on modified loop-2c.c test case. Reply-To: Glen Nakamura X-SW-Source: 2002-06/txt/msg00050.txt.bz2 List-Id: The following reply was made to PR optimization/6909; it has been noted by GNATS. From: Glen Nakamura To: gcc-gnats@gcc.gnu.org, gcc-bugs@gcc.gnu.org Cc: Subject: Re: optimization/6909: problem w/ -Os on modified loop-2c.c test case. Date: Sun, 2 Jun 2002 15:51:32 -1000 --IS0zKkzwUGydFO0o Content-Type: text/plain; charset=us-ascii Content-Disposition: inline http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=6909 2002-06-02 Glen Nakamura * 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 --IS0zKkzwUGydFO0o Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="fold.diff" 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 --IS0zKkzwUGydFO0o--