aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-10-26 23:55:23 +0000
committerDavid S. Miller <davem@gcc.gnu.org>2011-10-26 16:55:23 -0700
commit9aa6a9b5def1d499cf2948775b3941a093f80c95 (patch)
treee5135fa3732ec8fc08302acc0fa5e5b316c4c863 /gcc
parent28c2f60e96a3dd100a85b32a91f7a1c0c408fd39 (diff)
downloadgcc-9aa6a9b5def1d499cf2948775b3941a093f80c95.zip
gcc-9aa6a9b5def1d499cf2948775b3941a093f80c95.tar.gz
gcc-9aa6a9b5def1d499cf2948775b3941a093f80c95.tar.bz2
Improve sparc setcc generation and add testcases.
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. From-SVN: r180550
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/sparc/sparc.c14
-rw-r--r--gcc/config/sparc/sparc.md59
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/sparc/setcc-1.c39
-rw-r--r--gcc/testsuite/gcc.target/sparc/setcc-2.c39
6 files changed, 156 insertions, 8 deletions
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 <davem@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 <davem@davemloft.net>
+
+ * gcc.target/sparc/setcc-1.c: New test.
+ * gcc.target/sparc/setcc-2.c: New test.
+
2011-10-26 Joseph Myers <joseph@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 } } } */