Commit 8140c065 by Jakub Jelinek Committed by Jakub Jelinek

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
parent 78d432da
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.
......
...@@ -7326,7 +7326,8 @@ make_extraction (enum machine_mode mode, rtx inner, HOST_WIDE_INT pos, ...@@ -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, ...@@ -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. */
......
...@@ -10474,6 +10474,39 @@ ...@@ -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"
......
...@@ -1470,6 +1470,29 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op) ...@@ -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
......
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.
......
/* 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\]" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment