re PR target/57819 (Suboptimal shift patterns)

PR target/57819
	* simplify-rtx.c (simplify_unary_operation_1) <case ZERO_EXTEND>:
	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<mode>_1): New define_insn_and_split.

	* gcc.target/i386/pr57819.c: New test.

From-SVN: r200775
This commit is contained in:
Jakub Jelinek 2013-07-08 10:48:40 +02:00 committed by Jakub Jelinek
parent 78d432da45
commit 8140c06592
6 changed files with 109 additions and 2 deletions

View File

@ -1,5 +1,13 @@
2013-07-08 Jakub Jelinek <jakub@redhat.com> 2013-07-08 Jakub Jelinek <jakub@redhat.com>
PR target/57819
* simplify-rtx.c (simplify_unary_operation_1) <case ZERO_EXTEND>:
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<mode>_1): New define_insn_and_split.
PR rtl-optimization/57829 PR rtl-optimization/57829
* simplify-rtx.c (simplify_binary_operation_1) <case IOR>: Ensure that * simplify-rtx.c (simplify_binary_operation_1) <case IOR>: Ensure that
mask bits outside of mode are just sign-extension from mode to HWI. mask bits outside of mode are just sign-extension from mode to HWI.

View File

@ -7326,7 +7326,8 @@ make_extraction (enum machine_mode mode, rtx inner, HOST_WIDE_INT pos,
if (pos_rtx != 0 if (pos_rtx != 0
&& GET_MODE_SIZE (pos_mode) > GET_MODE_SIZE (GET_MODE (pos_rtx))) && 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 /* If we know that no extraneous bits are set, and that the high
bit is not set, convert extraction to cheaper one - either 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)) >> 1))
== 0))) == 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 /* Prefer ZERO_EXTENSION, since it gives more information to
backends. */ backends. */

View File

@ -10474,6 +10474,39 @@
PUT_CODE (operands[0], reverse_condition (GET_CODE (operands[0]))); PUT_CODE (operands[0], reverse_condition (GET_CODE (operands[0])));
}) })
;; Like *jcc_bt<mode>, but expect a SImode operand 2 instead of QImode
;; zero extended to SImode.
(define_insn_and_split "*jcc_bt<mode>_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>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 ;; Avoid useless masking of bit offset operand. "and" in SImode is correct
;; also for DImode, this is what combine produces. ;; also for DImode, this is what combine produces.
(define_insn_and_split "*jcc_bt<mode>_mask" (define_insn_and_split "*jcc_bt<mode>_mask"

View File

@ -1470,6 +1470,29 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op)
} }
} }
/* (zero_extend:M (subreg:N <X:O>)) is <X:O> (for M == O) or
(zero_extend:M <X:O>), 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) #if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
/* As we do not know which address space the pointer is referring to, /* 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 we can do this only if the target does not support different pointer

View File

@ -1,5 +1,8 @@
2013-07-08 Jakub Jelinek <jakub@redhat.com> 2013-07-08 Jakub Jelinek <jakub@redhat.com>
PR target/57819
* gcc.target/i386/pr57819.c: New test.
PR rtl-optimization/57829 PR rtl-optimization/57829
* gcc.c-torture/execute/pr57829.c: New test. * gcc.c-torture/execute/pr57829.c: New test.

View File

@ -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\]" } } */