This makes sure the addx/subx sequence is used even when v9 conditional moves are available.
It also shows the compiler that the setcc instructions emitting -1, 0, or 1 all extend to DImode. I left all the "*x_{plus,minus}_foo" and related patterns alone for now, I'll get to those and add appropriate test cases as I find time. Committed to trunk. gcc/ * config/sparc/sparc.c (emit_scc_insn): Do not try v9 sequences until LEU/LTU/GEU/GTU is attempted. * config/sparc/sparc.md (*neg_snesi_sign_extend): New 64-bit insn and split. (*neg_seqsi_sign_extend): Likewise. (*sltu_extend_sp64, *neg_sltu_extend_sp64, *sgeu_extend_sp64, *neg_sgeu_extend_sp64): New insns. gcc/testsuite/ * gcc.target/sparc/setcc-1.c: New test. * gcc.target/sparc/setcc-2.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@180550 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 8 ++++ gcc/config/sparc/sparc.c | 14 +++---- gcc/config/sparc/sparc.md | 59 ++++++++++++++++++++++++++++++ gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/gcc.target/sparc/setcc-1.c | 39 ++++++++++++++++++++ gcc/testsuite/gcc.target/sparc/setcc-2.c | 39 ++++++++++++++++++++ 6 files changed, 156 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/gcc.target/sparc/setcc-1.c create mode 100644 gcc/testsuite/gcc.target/sparc/setcc-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d6d1382..3a51510 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,13 @@ 2011-10-26 David S. Miller <da...@davemloft.net> + * config/sparc/sparc.c (emit_scc_insn): Do not try v9 sequences until + LEU/LTU/GEU/GTU is attempted. + * config/sparc/sparc.md (*neg_snesi_sign_extend): New 64-bit insn + and split. + (*neg_seqsi_sign_extend): Likewise. + (*sltu_extend_sp64, *neg_sltu_extend_sp64, *sgeu_extend_sp64, + *neg_sgeu_extend_sp64): New insns. + * config/sparc/sparc-protos.h (sparc_expand_conditional_move): Declare. * config/sparc/sparc.md (mov<I:mode>cc, mov<F:mode>cc): Call it. (*mov<I:mode>_cc_v9): Normalize to expect operand 0 always in operand 4. diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 964bcaf..80e05a6 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -2541,14 +2541,6 @@ emit_scc_insn (rtx operands[]) } } - /* For the rest, on v9 we can use conditional moves. */ - - if (TARGET_V9) - { - if (gen_v9_scc (operands[0], code, x, y)) - return true; - } - /* We can do LTU and GEU using the addx/subx instructions too. And for GTU/LEU, if both operands are registers swap them and fall back to the easy case. */ @@ -2573,6 +2565,12 @@ emit_scc_insn (rtx operands[]) return true; } + /* All the posibilities to use addx/subx based sequences has been + exhausted, try for a 3 instruction sequence using v9 conditional + moves. */ + if (TARGET_V9 && gen_v9_scc (operands[0], code, x, y)) + return true; + /* Nope, do branches. */ return false; } diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index 2bae28e..2b4b2bb 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -713,6 +713,22 @@ "" [(set_attr "length" "2")]) +(define_insn_and_split "*neg_snesi_sign_extend" + [(set (match_operand:DI 0 "register_operand" "=r") + (neg:DI (ne:DI (match_operand:SI 1 "register_operand" "r") + (const_int 0)))) + (clobber (reg:CC CC_REG))] + "TARGET_ARCH64" + "#" + "&& 1" + [(set (reg:CC_NOOV CC_REG) (compare:CC_NOOV (minus:SI (const_int 0) + (match_dup 1)) + (const_int 0))) + (set (match_dup 0) (sign_extend:DI (neg:SI (ltu:SI (reg:CC CC_REG) + (const_int 0)))))] + "" + [(set_attr "length" "2")]) + (define_insn_and_split "*snedi_zero" [(set (match_operand:DI 0 "register_operand" "=&r") (ne:DI (match_operand:DI 1 "register_operand" "r") @@ -804,6 +820,21 @@ "" [(set_attr "length" "2")]) +(define_insn_and_split "*neg_seqsi_sign_extend" + [(set (match_operand:DI 0 "register_operand" "=r") + (neg:DI (eq:DI (match_operand:SI 1 "register_operand" "r") + (const_int 0)))) + (clobber (reg:CC CC_REG))] + "TARGET_ARCH64" + "#" + "&& 1" + [(set (reg:CC_NOOV CC_REG) (compare:CC_NOOV (neg:SI (match_dup 1)) + (const_int 0))) + (set (match_dup 0) (sign_extend:DI (neg:SI (geu:SI (reg:CC CC_REG) + (const_int 0)))))] + "" + [(set_attr "length" "2")]) + (define_insn_and_split "*seqdi_zero" [(set (match_operand:DI 0 "register_operand" "=&r") (eq:DI (match_operand:DI 1 "register_operand" "r") @@ -928,6 +959,13 @@ "addx\t%%g0, 0, %0" [(set_attr "type" "ialuX")]) +(define_insn "*sltu_extend_sp64" + [(set (match_operand:DI 0 "register_operand" "=r") + (ltu:DI (reg:CC CC_REG) (const_int 0)))] + "TARGET_ARCH64" + "addx\t%%g0, 0, %0" + [(set_attr "type" "ialuX")]) + (define_insn "*neg_sltu_insn" [(set (match_operand:SI 0 "register_operand" "=r") (neg:SI (ltu:SI (reg:CC CC_REG) (const_int 0))))] @@ -935,6 +973,13 @@ "subx\t%%g0, 0, %0" [(set_attr "type" "ialuX")]) +(define_insn "*neg_sltu_extend_sp64" + [(set (match_operand:DI 0 "register_operand" "=r") + (sign_extend:DI (neg:SI (ltu:SI (reg:CC CC_REG) (const_int 0)))))] + "TARGET_ARCH64" + "subx\t%%g0, 0, %0" + [(set_attr "type" "ialuX")]) + ;; ??? Combine should canonicalize these next two to the same pattern. (define_insn "*neg_sltu_minus_x" [(set (match_operand:SI 0 "register_operand" "=r") @@ -959,6 +1004,13 @@ "subx\t%%g0, -1, %0" [(set_attr "type" "ialuX")]) +(define_insn "*sgeu_extend_sp64" + [(set (match_operand:DI 0 "register_operand" "=r") + (geu:DI (reg:CC CC_REG) (const_int 0)))] + "TARGET_ARCH64" + "subx\t%%g0, -1, %0" + [(set_attr "type" "ialuX")]) + (define_insn "*neg_sgeu_insn" [(set (match_operand:SI 0 "register_operand" "=r") (neg:SI (geu:SI (reg:CC CC_REG) (const_int 0))))] @@ -966,6 +1018,13 @@ "addx\t%%g0, -1, %0" [(set_attr "type" "ialuX")]) +(define_insn "*neg_sgeu_extend_sp64" + [(set (match_operand:DI 0 "register_operand" "=r") + (sign_extend:DI (neg:SI (geu:SI (reg:CC CC_REG) (const_int 0)))))] + "TARGET_ARCH64" + "addx\t%%g0, -1, %0" + [(set_attr "type" "ialuX")]) + ;; We can also do (x + ((unsigned) i >= 0)) and related, so put them in. ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode ;; versions for v9. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1a60d74..2879dfe 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-10-26 David S. Miller <da...@davemloft.net> + + * gcc.target/sparc/setcc-1.c: New test. + * gcc.target/sparc/setcc-2.c: New test. + 2011-10-26 Joseph Myers <jos...@codesourcery.com> * gcc.dg/tls/thr-cse-1.c: For i?86-*-mingw*, check for multiple diff --git a/gcc/testsuite/gcc.target/sparc/setcc-1.c b/gcc/testsuite/gcc.target/sparc/setcc-1.c new file mode 100644 index 0000000..6065bbb --- /dev/null +++ b/gcc/testsuite/gcc.target/sparc/setcc-1.c @@ -0,0 +1,39 @@ +/* { dg-do compile } */ +/* { dg-options "-O1" } */ + +int neq (int a, int b) +{ + return a != b; +} + +int eq (int a, int b) +{ + return a == b; +} + +int lt (unsigned int a, unsigned int b) +{ + return a < b; +} + +int leq (unsigned int a, unsigned int b) +{ + return a <= b; +} + +int geq (unsigned int a, unsigned int b) +{ + return a >= b; +} + +int gt (unsigned int a, unsigned int b) +{ + return a > b; +} + +/* { dg-final { scan-assembler-times "xor\t%" 2 } } */ +/* { dg-final { scan-assembler-times "subcc\t%" 2 } } */ +/* { dg-final { scan-assembler-times "addx\t%" 3 } } */ +/* { dg-final { scan-assembler-times "subx\t%" 3 } } */ +/* { dg-final { scan-assembler-times "cmp\t%" 4 } } */ +/* { dg-final { scan-assembler-not "sra\t%" { target lp64 } } } */ diff --git a/gcc/testsuite/gcc.target/sparc/setcc-2.c b/gcc/testsuite/gcc.target/sparc/setcc-2.c new file mode 100644 index 0000000..cc17c65 --- /dev/null +++ b/gcc/testsuite/gcc.target/sparc/setcc-2.c @@ -0,0 +1,39 @@ +/* { dg-do compile } */ +/* { dg-options "-O1" } */ + +int neq (int a, int b) +{ + return -(a != b); +} + +int eq (int a, int b) +{ + return -(a == b); +} + +int lt (unsigned int a, unsigned int b) +{ + return -(a < b); +} + +int leq (unsigned int a, unsigned int b) +{ + return -(a <= b); +} + +int geq (unsigned int a, unsigned int b) +{ + return -(a >= b); +} + +int gt (unsigned int a, unsigned int b) +{ + return -(a > b); +} + +/* { dg-final { scan-assembler-times "xor\t%" 2 } } */ +/* { dg-final { scan-assembler-times "subcc\t%" 2 } } */ +/* { dg-final { scan-assembler-times "addx\t%" 3 } } */ +/* { dg-final { scan-assembler-times "subx\t%" 3 } } */ +/* { dg-final { scan-assembler-times "cmp\t%" 4 } } */ +/* { dg-final { scan-assembler-not "sra\t%" { target lp64 } } } */ -- 1.7.6.401.g6a319