From 1bf020d9b399127094474cf802aee4026dd7e54b Mon Sep 17 00:00:00 2001 From: jakub Date: Mon, 8 Jul 2013 08:48:40 +0000 Subject: [PATCH] PR target/57819 * simplify-rtx.c (simplify_unary_operation_1) : Simplify (zero_extend:SI (subreg:QI (and:SI (reg:SI) (const_int 63)) 0)). * combine.c (make_extraction): Create ZERO_EXTEND or SIGN_EXTEND using simplify_gen_unary instead of gen_rtx_*_EXTEND. * config/i386/i386.md (*jcc_bt_1): New define_insn_and_split. * gcc.target/i386/pr57819.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@200775 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 8 +++++++ gcc/combine.c | 6 ++++-- gcc/config/i386/i386.md | 33 ++++++++++++++++++++++++++++ gcc/simplify-rtx.c | 23 ++++++++++++++++++++ gcc/testsuite/ChangeLog | 3 +++ gcc/testsuite/gcc.target/i386/pr57819.c | 38 +++++++++++++++++++++++++++++++++ 6 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr57819.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e4fc901..4fc4e50 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,13 @@ 2013-07-08 Jakub Jelinek + PR target/57819 + * simplify-rtx.c (simplify_unary_operation_1) : + Simplify (zero_extend:SI (subreg:QI (and:SI (reg:SI) + (const_int 63)) 0)). + * combine.c (make_extraction): Create ZERO_EXTEND or SIGN_EXTEND + using simplify_gen_unary instead of gen_rtx_*_EXTEND. + * config/i386/i386.md (*jcc_bt_1): New define_insn_and_split. + PR rtl-optimization/57829 * simplify-rtx.c (simplify_binary_operation_1) : Ensure that mask bits outside of mode are just sign-extension from mode to HWI. diff --git a/gcc/combine.c b/gcc/combine.c index b737bc5..ca311ff 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -7326,7 +7326,8 @@ make_extraction (enum machine_mode mode, rtx inner, HOST_WIDE_INT pos, if (pos_rtx != 0 && GET_MODE_SIZE (pos_mode) > GET_MODE_SIZE (GET_MODE (pos_rtx))) { - rtx temp = gen_rtx_ZERO_EXTEND (pos_mode, pos_rtx); + rtx temp = simplify_gen_unary (ZERO_EXTEND, pos_mode, pos_rtx, + GET_MODE (pos_rtx)); /* If we know that no extraneous bits are set, and that the high bit is not set, convert extraction to cheaper one - either @@ -7340,7 +7341,8 @@ make_extraction (enum machine_mode mode, rtx inner, HOST_WIDE_INT pos, >> 1)) == 0))) { - rtx temp1 = gen_rtx_SIGN_EXTEND (pos_mode, pos_rtx); + rtx temp1 = simplify_gen_unary (SIGN_EXTEND, pos_mode, pos_rtx, + GET_MODE (pos_rtx)); /* Prefer ZERO_EXTENSION, since it gives more information to backends. */ diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index a6e2946..2777e9c 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -10474,6 +10474,39 @@ PUT_CODE (operands[0], reverse_condition (GET_CODE (operands[0]))); }) +;; Like *jcc_bt, but expect a SImode operand 2 instead of QImode +;; zero extended to SImode. +(define_insn_and_split "*jcc_bt_1" + [(set (pc) + (if_then_else (match_operator 0 "bt_comparison_operator" + [(zero_extract:SWI48 + (match_operand:SWI48 1 "register_operand" "r") + (const_int 1) + (match_operand:SI 2 "register_operand" "r")) + (const_int 0)]) + (label_ref (match_operand 3)) + (pc))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_USE_BT || optimize_function_for_size_p (cfun)" + "#" + "&& 1" + [(set (reg:CCC FLAGS_REG) + (compare:CCC + (zero_extract:SWI48 + (match_dup 1) + (const_int 1) + (match_dup 2)) + (const_int 0))) + (set (pc) + (if_then_else (match_op_dup 0 [(reg:CCC FLAGS_REG) (const_int 0)]) + (label_ref (match_dup 3)) + (pc)))] +{ + operands[2] = simplify_gen_subreg (mode, operands[2], SImode, 0); + + PUT_CODE (operands[0], reverse_condition (GET_CODE (operands[0]))); +}) + ;; Avoid useless masking of bit offset operand. "and" in SImode is correct ;; also for DImode, this is what combine produces. (define_insn_and_split "*jcc_bt_mask" diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index be54db8..17a3d12 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -1470,6 +1470,29 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op) } } + /* (zero_extend:M (subreg:N )) is (for M == O) or + (zero_extend:M ), if X doesn't have any non-zero bits outside + of mode N. E.g. + (zero_extend:SI (subreg:QI (and:SI (reg:SI) (const_int 63)) 0)) is + (and:SI (reg:SI) (const_int 63)). */ + if (GET_CODE (op) == SUBREG + && GET_MODE_PRECISION (GET_MODE (op)) + < GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op))) + && GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op))) + <= HOST_BITS_PER_WIDE_INT + && GET_MODE_PRECISION (mode) + >= GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op))) + && subreg_lowpart_p (op) + && (nonzero_bits (SUBREG_REG (op), GET_MODE (SUBREG_REG (op))) + & ~GET_MODE_MASK (GET_MODE (op))) == 0) + { + if (GET_MODE_PRECISION (mode) + == GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op)))) + return SUBREG_REG (op); + return simplify_gen_unary (ZERO_EXTEND, mode, SUBREG_REG (op), + GET_MODE (SUBREG_REG (op))); + } + #if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend) /* As we do not know which address space the pointer is referring to, we can do this only if the target does not support different pointer diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f4d0b6f..8de216f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2013-07-08 Jakub Jelinek + PR target/57819 + * gcc.target/i386/pr57819.c: New test. + PR rtl-optimization/57829 * gcc.c-torture/execute/pr57829.c: New test. diff --git a/gcc/testsuite/gcc.target/i386/pr57819.c b/gcc/testsuite/gcc.target/i386/pr57819.c new file mode 100644 index 0000000..b086a40 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr57819.c @@ -0,0 +1,38 @@ +/* PR target/57819 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -mtune=core2" } */ + +void foo (void); + +__extension__ typedef __INTPTR_TYPE__ intptr_t; + +int +test1 (intptr_t x, intptr_t n) +{ + n &= sizeof (intptr_t) * __CHAR_BIT__ - 1; + + if (x & ((intptr_t) 1 << n)) + foo (); + + return 0; +} + +int +test2 (intptr_t x, intptr_t n) +{ + if (x & ((intptr_t) 1 << ((int) n & (sizeof (intptr_t) * __CHAR_BIT__ - 1)))) + foo (); + + return 0; +} + +int +test3 (intptr_t x, intptr_t n) +{ + if (x & ((intptr_t) 1 << ((int) n & ((int) sizeof (intptr_t) * __CHAR_BIT__ - 1)))) + foo (); + + return 0; +} + +/* { dg-final { scan-assembler-not "and\[lq\]\[ \t\]" } } */ -- 2.7.4