[PATCH] Improve sparc setcc generation and add testcases.

David Miller davem@davemloft.net
Thu Oct 27 04:08:00 GMT 2011


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  <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 } } } */
-- 
1.7.6.401.g6a319



More information about the Gcc-patches mailing list