diff options
author | sayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-12-11 01:49:05 +0000 |
---|---|---|
committer | sayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-12-11 01:49:05 +0000 |
commit | 79716d2e9d61d6c8d4526cfbe888b03db30188f9 (patch) | |
tree | 3035ae03ea21d5c817d6d99c7d2021a89ac56159 /gcc/dojump.c | |
parent | 79c23c93750f8ce0da01917b46b38ec71610bb15 (diff) | |
download | gcc-79716d2e9d61d6c8d4526cfbe888b03db30188f9.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@92024 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/dojump.c')
-rw-r--r-- | gcc/dojump.c | 60 |
1 files changed, 44 insertions, 16 deletions
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; + } } } |