diff options
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/dojump.c | 60 |
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; + } } } |