summaryrefslogtreecommitdiff
path: root/gcc/dojump.c
diff options
context:
space:
mode:
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2004-03-20 07:13:38 +0000
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2004-03-20 07:13:38 +0000
commitd9e1941911d3bb1faccfc665db2f654ca42e2c91 (patch)
treee476fa61be9fd061a4ef69e7378ead1fe041dc34 /gcc/dojump.c
parent626bd0b8f11596688d7bdd3da24e7003e59cec99 (diff)
downloadgcc-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.c66
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"