diff options
author | rsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-03-20 07:13:38 +0000 |
---|---|---|
committer | rsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-03-20 07:13:38 +0000 |
commit | d9e1941911d3bb1faccfc665db2f654ca42e2c91 (patch) | |
tree | e476fa61be9fd061a4ef69e7378ead1fe041dc34 /gcc/dojump.c | |
parent | 626bd0b8f11596688d7bdd3da24e7003e59cec99 (diff) | |
download | gcc-d9e1941911d3bb1faccfc665db2f654ca42e2c91.tar.gz |
* Makefile.in (dojump.o): Depend on $(GGC_H) and dojump.h.
(GTFILES): Add $(srcdir)/dojump.h.
(gt-dojump.h): New dependency.
* dojump.c (and_reg, and_test, shift_test): New static variables.
(prefer_and_bit_test): New function.
(do_jump): Use it to choose between (X & (1 << C)) and (X >> C) & 1.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@79732 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/dojump.c')
-rw-r--r-- | gcc/dojump.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/gcc/dojump.c b/gcc/dojump.c index d0cc13c45f3..83af19bb7f3 100644 --- a/gcc/dojump.c +++ b/gcc/dojump.c @@ -33,7 +33,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "expr.h" #include "optabs.h" #include "langhooks.h" +#include "ggc.h" +static bool prefer_and_bit_test (enum machine_mode, int); static void do_jump_by_parts_greater (tree, int, rtx, rtx); static void do_jump_by_parts_equality (tree, rtx, rtx); static void do_compare_and_jump (tree, enum rtx_code, enum rtx_code, rtx, @@ -101,6 +103,45 @@ jumpif (tree exp, rtx label) do_jump (exp, NULL_RTX, label); } +/* Used internally by prefer_and_bit_test. */ + +static GTY(()) rtx and_reg; +static GTY(()) rtx and_test; +static GTY(()) rtx shift_test; + +/* Compare the relative costs of "(X & (1 << BITNUM))" and "(X >> BITNUM) & 1", + where X is an arbitrary register of mode MODE. Return true if the former + is preferred. */ + +static bool +prefer_and_bit_test (enum machine_mode mode, int bitnum) +{ + if (and_test == 0) + { + /* Set up rtxes for the two variations. Use NULL as a placeholder + for the BITNUM-based constants. */ + and_reg = gen_rtx_REG (mode, FIRST_PSEUDO_REGISTER); + and_test = gen_rtx_AND (mode, and_reg, NULL); + shift_test = gen_rtx_AND (mode, gen_rtx_ASHIFTRT (mode, and_reg, NULL), + const1_rtx); + } + else + { + /* Change the mode of the previously-created rtxes. */ + PUT_MODE (and_reg, mode); + PUT_MODE (and_test, mode); + PUT_MODE (shift_test, mode); + PUT_MODE (XEXP (shift_test, 0), mode); + } + + /* Fill in the integers. */ + XEXP (and_test, 0) = GEN_INT ((unsigned HOST_WIDE_INT) 1 << bitnum); + XEXP (XEXP (shift_test, 0), 1) = GEN_INT (bitnum); + + return (rtx_cost (and_test, IF_THEN_ELSE) + <= rtx_cost (shift_test, IF_THEN_ELSE)); +} + /* Generate code to evaluate EXP and jump to IF_FALSE_LABEL if the result is zero, or IF_TRUE_LABEL if the result is one. Either of IF_FALSE_LABEL and IF_TRUE_LABEL may be zero, @@ -206,6 +247,29 @@ do_jump (tree exp, rtx if_false_label, rtx if_true_label) break; case BIT_AND_EXPR: + /* fold_single_bit_test() converts (X & (1 << C)) into (X >> C) & 1. + See if the former is preferred for jump tests and restore it + if so. */ + if (TREE_CODE (TREE_OPERAND (exp, 0)) == RSHIFT_EXPR + && integer_onep (TREE_OPERAND (exp, 1))) + { + tree arg = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); + tree shift = TREE_OPERAND (TREE_OPERAND (exp, 0), 1); + tree one = TREE_OPERAND (exp, 1); + tree argtype = TREE_TYPE (arg); + if (TREE_CODE (shift) == INTEGER_CST + && compare_tree_int (shift, 0) > 0 + && compare_tree_int (shift, HOST_BITS_PER_WIDE_INT) < 0 + && prefer_and_bit_test (TYPE_MODE (argtype), + TREE_INT_CST_LOW (shift))) + { + do_jump (build (BIT_AND_EXPR, argtype, arg, + fold (build (LSHIFT_EXPR, argtype, one, shift))), + if_false_label, if_true_label); + break; + } + } + /* If we are AND'ing with a small constant, do this comparison in the smallest type that fits. If the machine doesn't have comparisons that small, it will be converted back to the wider comparison. @@ -999,3 +1063,5 @@ do_compare_and_jump (tree exp, enum rtx_code signed_code, ? expr_size (TREE_OPERAND (exp, 0)) : NULL_RTX), if_false_label, if_true_label); } + +#include "gt-dojump.h" |