re PR middle-end/54685 ([SH] Improve unsigned int comparison with 0x7FFFFFFF)

PR target/54685
	* config/sh/sh.md (one_cmplsi2): Make insn_and_split.  Add manual
	combine matching for an insn sequence where a ge:SI pattern can be used.

	PR target/54685
	* gcc.target/sh/pr54685.c: New.

From-SVN: r192200
This commit is contained in:
Oleg Endo 2012-10-08 10:09:28 +00:00
parent e28d52cffb
commit f429813df1
4 changed files with 120 additions and 1 deletions

View file

@ -1,3 +1,9 @@
2012-10-08 Oleg Endo <olegendo@gcc.gnu.org>
PR target/54685
* config/sh/sh.md (one_cmplsi2): Make insn_and_split. Add manual
combine matching for an insn sequence where a ge:SI pattern can be used.
2012-10-08 Dodji Seketeli <dodji@redhat.com>
PR c++/53528 C++11 attribute support

View file

@ -5189,11 +5189,61 @@ label:
"neg %1,%0"
[(set_attr "type" "arith")])
(define_insn "one_cmplsi2"
(define_insn_and_split "one_cmplsi2"
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
(not:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
"TARGET_SH1"
"not %1,%0"
"&& can_create_pseudo_p ()"
[(set (reg:SI T_REG) (ge:SI (match_dup 1) (const_int 0)))
(set (match_dup 0) (reg:SI T_REG))]
{
/* PR 54685
If the result of 'unsigned int <= 0x7FFFFFFF' ends up as the following
sequence:
(set (reg0) (not:SI (reg0) (reg1)))
(parallel [(set (reg2) (lshiftrt:SI (reg0) (const_int 31)))
(clobber (reg:SI T_REG))])
... match and combine the sequence manually in the split pass after the
combine pass. Notice that combine does try the target pattern of this
split, but if the pattern is added it interferes with other patterns, in
particular with the div0s comparisons.
This could also be done with a peephole but doing it here before register
allocation can save one temporary.
When we're here, the not:SI pattern obviously has been matched already
and we only have to see whether the following insn is the left shift. */
rtx i = next_nonnote_insn_bb (curr_insn);
if (i == NULL_RTX || !NONJUMP_INSN_P (i))
FAIL;
rtx p = PATTERN (i);
if (GET_CODE (p) != PARALLEL || XVECLEN (p, 0) != 2)
FAIL;
rtx p0 = XVECEXP (p, 0, 0);
rtx p1 = XVECEXP (p, 0, 1);
if (/* (set (reg2) (lshiftrt:SI (reg0) (const_int 31))) */
GET_CODE (p0) == SET
&& GET_CODE (XEXP (p0, 1)) == LSHIFTRT
&& REG_P (XEXP (XEXP (p0, 1), 0))
&& REGNO (XEXP (XEXP (p0, 1), 0)) == REGNO (operands[0])
&& CONST_INT_P (XEXP (XEXP (p0, 1), 1))
&& INTVAL (XEXP (XEXP (p0, 1), 1)) == 31
/* (clobber (reg:SI T_REG)) */
&& GET_CODE (p1) == CLOBBER && REG_P (XEXP (p1, 0))
&& REGNO (XEXP (p1, 0)) == T_REG)
{
operands[0] = XEXP (p0, 0);
set_insn_deleted (i);
}
else
FAIL;
}
[(set_attr "type" "arith")])
(define_expand "one_cmpldi2"

View file

@ -1,3 +1,8 @@
2012-10-08 Oleg Endo <olegendo@gcc.gnu.org>
PR target/54685
* gcc.target/sh/pr54685.c: New.
2012-10-08 Dodji Seketeli <dodji@redhat.com>
PR c++/53528 C++11 attribute support

View file

@ -0,0 +1,58 @@
/* Check that a comparison 'unsigned int <= 0x7FFFFFFF' results in code
utilizing the cmp/pz instruction. */
/* { dg-do compile { target "sh*-*-*" } } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler-not "not" } } */
/* { dg-final { scan-assembler-times "cmp/pz" 7 } } */
/* { dg-final { scan-assembler-times "shll" 1 } } */
/* { dg-final { scan-assembler-times "movt" 4 } } */
int
test_00 (unsigned int a)
{
return !(a > 0x7FFFFFFF);
}
int
test_01 (unsigned int a)
{
return !(a > 0x7FFFFFFF) ? -5 : 10;
}
int
test_02 (unsigned int a)
{
/* 1x shll, 1x movt */
return a >= 0x80000000;
}
int
test_03 (unsigned int a)
{
return a >= 0x80000000 ? -5 : 10;
}
int
test_04 (unsigned int a)
{
return a <= 0x7FFFFFFF;
}
int
test_05 (unsigned int a)
{
return a <= 0x7FFFFFFF ? -5 : 10;
}
int
test_06 (unsigned int a)
{
return a < 0x80000000;
}
int
test_07 (unsigned int a)
{
return a < 0x80000000 ? -5 : 10;
}