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>
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
* simplify-rtx.c (simplify_binary_operation_1) <case IOR>: Ensure that
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,
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. */
......
......@@ -10474,6 +10474,39 @@
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
;; also for DImode, this is what combine produces.
(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)
}
}
/* (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)
/* 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
......
2013-07-08 Jakub Jelinek <jakub@redhat.com>
PR target/57819
* gcc.target/i386/pr57819.c: New test.
PR rtl-optimization/57829
* 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