Improve sparc setcc generation and add testcases.
authorDavid S. Miller <davem@davemloft.net>
Wed, 26 Oct 2011 23:55:23 +0000 (23:55 +0000)
committerDavid S. Miller <davem@gcc.gnu.org>
Wed, 26 Oct 2011 23:55:23 +0000 (16:55 -0700)
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

gcc/ChangeLog
gcc/config/sparc/sparc.c
gcc/config/sparc/sparc.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/sparc/setcc-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/sparc/setcc-2.c [new file with mode: 0644]

index d6d1382..3a51510 100644 (file)
@@ -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.
index 964bcaf..80e05a6 100644 (file)
@@ -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;
 }
index 2bae28e..2b4b2bb 100644 (file)
   ""
   [(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")
   ""
   [(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")
   "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))))]
   "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")
   "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))))]
   "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.
index 1a60d74..2879dfe 100644 (file)
@@ -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 (file)
index 0000000..6065bbb
--- /dev/null
@@ -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 (file)
index 0000000..cc17c65
--- /dev/null
@@ -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 } } } */