summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/dojump.c60
2 files changed, 53 insertions, 16 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 971c24967ec..4656a74f36f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2004-12-10 Roger Sayle <roger@eyesopen.com>
+
+ PR target/18002
+ PR middle-end/18424
+ * dojump.c (do_jump): When attempting to reverse the effects of
+ fold_single_bit_test, we need to STRIP_NOPS and narrowing type
+ conversions, and handle BIT_XOR_EXPR that's used to invert the
+ sense of the single bit test.
+
2004-12-10 Devang Patel <dpatel@apple.com>
PR 18732
diff --git a/gcc/dojump.c b/gcc/dojump.c
index 27a3cd68cee..93bcb8be41a 100644
--- a/gcc/dojump.c
+++ b/gcc/dojump.c
@@ -218,24 +218,52 @@ do_jump (tree exp, rtx if_false_label, rtx if_true_label)
/* 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)))
+ if (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)))
+ tree exp0 = TREE_OPERAND (exp, 0);
+ rtx set_label, clr_label;
+
+ /* Strip narrowing integral type conversions. */
+ while ((TREE_CODE (exp0) == NOP_EXPR
+ || TREE_CODE (exp0) == CONVERT_EXPR
+ || TREE_CODE (exp0) == NON_LVALUE_EXPR)
+ && TREE_OPERAND (exp0, 0) != error_mark_node
+ && TYPE_PRECISION (TREE_TYPE (exp0))
+ <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp0, 0))))
+ exp0 = TREE_OPERAND (exp0, 0);
+
+ /* "exp0 ^ 1" inverts the sense of the single bit test. */
+ if (TREE_CODE (exp0) == BIT_XOR_EXPR
+ && integer_onep (TREE_OPERAND (exp0, 1)))
{
- do_jump (build2 (BIT_AND_EXPR, argtype, arg,
- fold (build2 (LSHIFT_EXPR, argtype,
- one, shift))),
- if_false_label, if_true_label);
- break;
+ exp0 = TREE_OPERAND (exp0, 0);
+ clr_label = if_true_label;
+ set_label = if_false_label;
+ }
+ else
+ {
+ clr_label = if_false_label;
+ set_label = if_true_label;
+ }
+
+ if (TREE_CODE (exp0) == RSHIFT_EXPR)
+ {
+ tree arg = TREE_OPERAND (exp0, 0);
+ tree shift = TREE_OPERAND (exp0, 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)))
+ {
+ HOST_WIDE_INT mask = (HOST_WIDE_INT) 1
+ << TREE_INT_CST_LOW (shift);
+ do_jump (build2 (BIT_AND_EXPR, argtype, arg,
+ build_int_cst_type (argtype, mask)),
+ clr_label, set_label);
+ break;
+ }
}
}