This is the mail archive of the
`gcc-patches@gcc.gnu.org`
mailing list for the GCC project.

Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|

Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |

Other format: | [Raw text] |

*From*: Roger Sayle <roger at eyesopen dot com>*To*: gcc-patches at gcc dot gnu dot org*Date*: Wed, 10 Sep 2003 20:53:29 -0600 (MDT)*Subject*: [PATCH] Move NEG/NOT opts from combine.c to simplify-rtx.c

The following patch moves a bunch of RTL simplification optimizations for NEG and NOT from combine.c's combine_simplify_rtx to simplify-rtx.c's simplify_unary_operation. The former already calls the latter [on line 3705 of combine.c], so there should be no change in the behaviour of combine. Placing them in simplify_unary_operation, however, makes these same transformations available to the rest of the compiler (expand, CSE, GCSE, etc...); Another small step towards unification. Apart from the move, this patch also makes sure that we consistently recursively simplify the result after each optimization gets applied. This is done by calling either simplify_gen_unary or simplify_gen_binary rather than constructing RTL directly. Apart from that both the transformations and the conditions under which they fire should be unchanged and no new optimizations have been introduced. The following patch has been tested on i686-pc-linux-gnu with a complete "make bootstrap", all languages except treelang, and regression tested with a top-level "make -k check" with no new failures. Ok for mainline? 2003-09-10 Roger Sayle <roger@eyesopen.com> * combine.c (combine_simplify_rtx): Move several NOT and NEG optimizations from here... * simplify-rtx.c (simplify_unary_operation): to here. Recursively simplify expressions using simplify_gen_*ary instead of gen_rtx_*. Index: combine.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/combine.c,v retrieving revision 1.384 diff -c -3 -p -r1.384 combine.c *** combine.c 7 Sep 2003 20:32:16 -0000 1.384 --- combine.c 10 Sep 2003 22:05:43 -0000 *************** combine_simplify_rtx (rtx x, enum machin *** 3847,3879 **** break; case NOT: - /* (not (plus X -1)) can become (neg X). */ - if (GET_CODE (XEXP (x, 0)) == PLUS - && XEXP (XEXP (x, 0), 1) == constm1_rtx) - return gen_rtx_NEG (mode, XEXP (XEXP (x, 0), 0)); - - /* Similarly, (not (neg X)) is (plus X -1). */ - if (GET_CODE (XEXP (x, 0)) == NEG) - return gen_rtx_PLUS (mode, XEXP (XEXP (x, 0), 0), constm1_rtx); - - /* (not (xor X C)) for C constant is (xor X D) with D = ~C. */ - if (GET_CODE (XEXP (x, 0)) == XOR - && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT - && (temp = simplify_unary_operation (NOT, mode, - XEXP (XEXP (x, 0), 1), - mode)) != 0) - return gen_binary (XOR, mode, XEXP (XEXP (x, 0), 0), temp); - - /* (not (ashift 1 X)) is (rotate ~1 X). We used to do this for operands - other than 1, but that is not valid. We could do a similar - simplification for (not (lshiftrt C X)) where C is just the sign bit, - but this doesn't seem common enough to bother with. */ - if (GET_CODE (XEXP (x, 0)) == ASHIFT - && XEXP (XEXP (x, 0), 0) == const1_rtx) - return gen_rtx_ROTATE (mode, simplify_gen_unary (NOT, mode, - const1_rtx, mode), - XEXP (XEXP (x, 0), 1)); - if (GET_CODE (XEXP (x, 0)) == SUBREG && subreg_lowpart_p (XEXP (x, 0)) && (GET_MODE_SIZE (GET_MODE (XEXP (x, 0))) --- 3847,3852 ---- *************** combine_simplify_rtx (rtx x, enum machin *** 3890,3913 **** return gen_lowpart_for_combine (mode, x); } - /* If STORE_FLAG_VALUE is -1, (not (comparison foo bar)) can be done by - reversing the comparison code if valid. */ - if (STORE_FLAG_VALUE == -1 - && GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<' - && (reversed = reversed_comparison (x, mode, XEXP (XEXP (x, 0), 0), - XEXP (XEXP (x, 0), 1)))) - return reversed; - - /* (not (ashiftrt foo C)) where C is the number of bits in FOO minus 1 - is (ge foo (const_int 0)) if STORE_FLAG_VALUE is -1, so we can - perform the above simplification. */ - - if (STORE_FLAG_VALUE == -1 - && GET_CODE (XEXP (x, 0)) == ASHIFTRT - && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT - && INTVAL (XEXP (XEXP (x, 0), 1)) == GET_MODE_BITSIZE (mode) - 1) - return gen_rtx_GE (mode, XEXP (XEXP (x, 0), 0), const0_rtx); - /* Apply De Morgan's laws to reduce number of patterns for machines with negating logical insns (and-not, nand, etc.). If result has only one NOT, put it first, since that is how the patterns are --- 3863,3868 ---- *************** combine_simplify_rtx (rtx x, enum machin *** 3938,3999 **** break; case NEG: - /* (neg (plus X 1)) can become (not X). */ - if (GET_CODE (XEXP (x, 0)) == PLUS - && XEXP (XEXP (x, 0), 1) == const1_rtx) - return gen_rtx_NOT (mode, XEXP (XEXP (x, 0), 0)); - - /* Similarly, (neg (not X)) is (plus X 1). */ - if (GET_CODE (XEXP (x, 0)) == NOT) - return plus_constant (XEXP (XEXP (x, 0), 0), 1); - - /* (neg (minus X Y)) can become (minus Y X). This transformation - isn't safe for modes with signed zeros, since if X and Y are - both +0, (minus Y X) is the same as (minus X Y). If the rounding - mode is towards +infinity (or -infinity) then the two expressions - will be rounded differently. */ - if (GET_CODE (XEXP (x, 0)) == MINUS - && !HONOR_SIGNED_ZEROS (mode) - && !HONOR_SIGN_DEPENDENT_ROUNDING (mode)) - return gen_binary (MINUS, mode, XEXP (XEXP (x, 0), 1), - XEXP (XEXP (x, 0), 0)); - - /* (neg (plus A B)) is canonicalized to (minus (neg A) B). */ - if (GET_CODE (XEXP (x, 0)) == PLUS - && !HONOR_SIGNED_ZEROS (mode) - && !HONOR_SIGN_DEPENDENT_ROUNDING (mode)) - { - temp = simplify_gen_unary (NEG, mode, XEXP (XEXP (x, 0), 0), mode); - temp = combine_simplify_rtx (temp, mode, last, in_dest); - return gen_binary (MINUS, mode, temp, XEXP (XEXP (x, 0), 1)); - } - - /* (neg (mult A B)) becomes (mult (neg A) B). - This works even for floating-point values. */ - if (GET_CODE (XEXP (x, 0)) == MULT - && !HONOR_SIGN_DEPENDENT_ROUNDING (mode)) - { - temp = simplify_gen_unary (NEG, mode, XEXP (XEXP (x, 0), 0), mode); - return gen_binary (MULT, mode, temp, XEXP (XEXP (x, 0), 1)); - } - /* (neg (xor A 1)) is (plus A -1) if A is known to be either 0 or 1. */ if (GET_CODE (XEXP (x, 0)) == XOR && XEXP (XEXP (x, 0), 1) == const1_rtx && nonzero_bits (XEXP (XEXP (x, 0), 0), mode) == 1) return gen_binary (PLUS, mode, XEXP (XEXP (x, 0), 0), constm1_rtx); - - /* NEG commutes with ASHIFT since it is multiplication. Only do this - if we can then eliminate the NEG (e.g., - if the operand is a constant). */ - - if (GET_CODE (XEXP (x, 0)) == ASHIFT) - { - temp = simplify_unary_operation (NEG, mode, - XEXP (XEXP (x, 0), 0), mode); - if (temp) - return gen_binary (ASHIFT, mode, temp, XEXP (XEXP (x, 0), 1)); - } temp = expand_compound_operation (XEXP (x, 0)); --- 3893,3903 ---- Index: simplify-rtx.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/simplify-rtx.c,v retrieving revision 1.157 diff -c -3 -p -r1.157 simplify-rtx.c *** simplify-rtx.c 4 Sep 2003 01:52:59 -0000 1.157 --- simplify-rtx.c 10 Sep 2003 22:05:46 -0000 *************** simplify_unary_operation (enum rtx_code *** 788,793 **** --- 788,795 ---- else { enum rtx_code reversed; + rtx temp; + /* There are some simplifications we can do even if the operands aren't constant. */ switch (code) *************** simplify_unary_operation (enum rtx_code *** 801,814 **** if (mode == BImode && GET_RTX_CLASS (GET_CODE (op)) == '<' && ((reversed = reversed_comparison_code (op, NULL_RTX)) != UNKNOWN)) ! return gen_rtx_fmt_ee (reversed, ! op_mode, XEXP (op, 0), XEXP (op, 1)); break; case NEG: /* (neg (neg X)) == X. */ if (GET_CODE (op) == NEG) return XEXP (op, 0); break; case SIGN_EXTEND: --- 803,918 ---- if (mode == BImode && GET_RTX_CLASS (GET_CODE (op)) == '<' && ((reversed = reversed_comparison_code (op, NULL_RTX)) != UNKNOWN)) ! return simplify_gen_relational (reversed, op_mode, op_mode, ! XEXP (op, 0), XEXP (op, 1)); ! ! /* (not (plus X -1)) can become (neg X). */ ! if (GET_CODE (op) == PLUS ! && XEXP (op, 1) == constm1_rtx) ! return simplify_gen_unary (NEG, mode, XEXP (op, 0), mode); ! ! /* Similarly, (not (neg X)) is (plus X -1). */ ! if (GET_CODE (op) == NEG) ! return plus_constant (XEXP (op, 0), -1); ! ! /* (not (xor X C)) for C constant is (xor X D) with D = ~C. */ ! if (GET_CODE (op) == XOR ! && GET_CODE (XEXP (op, 1)) == CONST_INT ! && (temp = simplify_unary_operation (NOT, mode, ! XEXP (op, 1), ! mode)) != 0) ! return simplify_gen_binary (XOR, mode, XEXP (op, 0), temp); ! ! ! /* (not (ashift 1 X)) is (rotate ~1 X). We used to do this for ! operands other than 1, but that is not valid. We could do a ! similar simplification for (not (lshiftrt C X)) where C is ! just the sign bit, but this doesn't seem common enough to ! bother with. */ ! if (GET_CODE (op) == ASHIFT ! && XEXP (op, 0) == const1_rtx) ! { ! temp = simplify_gen_unary (NOT, mode, const1_rtx, mode); ! return simplify_gen_binary (ROTATE, mode, temp, XEXP (op, 1)); ! } ! ! /* If STORE_FLAG_VALUE is -1, (not (comparison X Y)) can be done ! by reversing the comparison code if valid. */ ! if (STORE_FLAG_VALUE == -1 ! && GET_RTX_CLASS (GET_CODE (op)) == '<' ! && (reversed = reversed_comparison_code (op, NULL_RTX)) ! != UNKNOWN) ! return simplify_gen_relational (reversed, op_mode, op_mode, ! XEXP (op, 0), XEXP (op, 1)); ! ! /* (not (ashiftrt foo C)) where C is the number of bits in FOO ! minus 1 is (ge foo (const_int 0)) if STORE_FLAG_VALUE is -1, ! so we can perform the above simplification. */ ! ! if (STORE_FLAG_VALUE == -1 ! && GET_CODE (op) == ASHIFTRT ! && GET_CODE (XEXP (op, 1)) == CONST_INT ! && INTVAL (XEXP (op, 1)) == GET_MODE_BITSIZE (mode) - 1) ! return simplify_gen_relational (GE, mode, mode, XEXP (op, 0), ! const0_rtx); ! break; case NEG: /* (neg (neg X)) == X. */ if (GET_CODE (op) == NEG) return XEXP (op, 0); + + /* (neg (plus X 1)) can become (not X). */ + if (GET_CODE (op) == PLUS + && XEXP (op, 1) == const1_rtx) + return simplify_gen_unary (NOT, mode, XEXP (op, 0), mode); + + /* Similarly, (neg (not X)) is (plus X 1). */ + if (GET_CODE (op) == NOT) + return plus_constant (XEXP (op, 0), 1); + + /* (neg (minus X Y)) can become (minus Y X). This transformation + isn't safe for modes with signed zeros, since if X and Y are + both +0, (minus Y X) is the same as (minus X Y). If the + rounding mode is towards +infinity (or -infinity) then the two + expressions will be rounded differently. */ + if (GET_CODE (op) == MINUS + && !HONOR_SIGNED_ZEROS (mode) + && !HONOR_SIGN_DEPENDENT_ROUNDING (mode)) + return simplify_gen_binary (MINUS, mode, XEXP (op, 1), + XEXP (op, 0)); + + /* (neg (plus A B)) is canonicalized to (minus (neg A) B). */ + if (GET_CODE (op) == PLUS + && !HONOR_SIGNED_ZEROS (mode) + && !HONOR_SIGN_DEPENDENT_ROUNDING (mode)) + { + temp = simplify_gen_unary (NEG, mode, XEXP (op, 0), mode); + return simplify_gen_binary (MINUS, mode, temp, XEXP (op, 1)); + } + + /* (neg (mult A B)) becomes (mult (neg A) B). + This works even for floating-point values. */ + if (GET_CODE (op) == MULT + && !HONOR_SIGN_DEPENDENT_ROUNDING (mode)) + { + temp = simplify_gen_unary (NEG, mode, XEXP (op, 0), mode); + return simplify_gen_binary (MULT, mode, temp, XEXP (op, 1)); + } + + /* NEG commutes with ASHIFT since it is multiplication. Only do + this if we can then eliminate the NEG (e.g., if the operand + is a constant). */ + if (GET_CODE (op) == ASHIFT) + { + temp = simplify_unary_operation (NEG, mode, XEXP (op, 0), + mode); + if (temp) + return simplify_gen_binary (ASHIFT, mode, temp, + XEXP (op, 1)); + } + break; case SIGN_EXTEND: Roger -- Roger Sayle, E-mail: roger@eyesopen.com OpenEye Scientific Software, WWW: http://www.eyesopen.com/ Suite 1107, 3600 Cerrillos Road, Tel: (+1) 505-473-7385 Santa Fe, New Mexico, 87507. Fax: (+1) 505-473-0833

**Follow-Ups**:**Re: [PATCH] Move NEG/NOT opts from combine.c to simplify-rtx.c***From:*Zack Weinberg

Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|

Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |