Patchwork Add support for the VIS3 addxc instruction.

login
register
mail settings
Submitter David Miller
Date Oct. 28, 2011, 5:56 a.m.
Message ID <20111028.015609.1017276483397053077.davem@davemloft.net>
Download mbox | patch
Permalink /patch/122347/
State New
Headers show

Comments

David Miller - Oct. 28, 2011, 5:56 a.m.
'addxc' is like 'addx', but it uses the 64-bit carry condition
as input instead of the 32-bit one.

This allows us to do ne/ltu/gtu setcc operations comparing 64-bit
integers without temporaries.

Unfortunately, VIS3 only has addxc (not subxc) and only the 3-register
opcode is provided (no immediate version).  addxc and addxccc (the latter
of which we have no real use for) were added to VIS3 to facilitate
the multiplying of large numbers when used in concert with umulxhi.

Hopefully a future chip will add subxc too so we can support all the
cases which addx/subx currently handle.

After this change, all VIS3 instructions the compiler can make use of
in some way are supported by GCC.

Committed to trunk.

gcc/

	* config/sparc/sparc.md (snedi_special): Only match when not VIS3.
	(*snedi_zero): Likewise.
	(*snedi_zero_trunc): Likewise.
	(snedi_special_vis3): New expander.
	(*snedi_zero_vis3): New insn.
	(*snedi_zero_trunc_vis3): Likewise.
	(*sltu_insn_vis3): Likewise.
	(*sltu_insn_vis3_trunc): Likewise.
	(addxc): Likewise.
	(*addxc_trunc_sp64_vis3): Likewise.
	* config/sparc/sparc.c (emit_scc_insn): When VIS3 use the
	gen_snedi_special_vis3 expander, and try GTU/LTU addx based
	sequences on DImode values.

gcc/testsuite/

	* gcc.target/sparc/setcc-3.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@180602 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/ChangeLog             |   14 ++++++++
 gcc/config/sparc/sparc.c  |   14 ++++++--
 gcc/config/sparc/sparc.md |   80 ++++++++++++++++++++++++++++++++++++++++++---
 gcc/testsuite/ChangeLog   |    4 ++
 gcc/testsuite/gcc.target/sparc/setcc-3.c |   24 ++++++++++++++++++++++++
 4 files changed, 104 insertions(+), 8 deletions(-)

Patch

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2d864d8..420e188 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,19 @@ 
 2011-10-27  David S. Miller  <davem@davemloft.net>
 
+	* config/sparc/sparc.md (snedi_special): Only match when not VIS3.
+	(*snedi_zero): Likewise.
+	(*snedi_zero_trunc): Likewise.
+	(snedi_special_vis3): New expander.
+	(*snedi_zero_vis3): New insn.
+	(*snedi_zero_trunc_vis3): Likewise.
+	(*sltu_insn_vis3): Likewise.
+	(*sltu_insn_vis3_trunc): Likewise.
+	(addxc): Likewise.
+	(*addxc_trunc_sp64_vis3): Likewise.
+	* config/sparc/sparc.c (emit_scc_insn): When VIS3 use the
+	gen_snedi_special_vis3 expander, and try GTU/LTU addx based
+	sequences on DImode values.
+
 	* config/sparc/sparc.md (64-bit vector moves): Use 'e' not 'f'
 	constraint.
 
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index ea9fdef..3883dbd 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -2519,7 +2519,7 @@  emit_scc_insn (rtx operands[])
         }
       else if (GET_MODE (x) == DImode)
         {
-          rtx pat = gen_seqdi_special (operands[0], x, y);
+	  rtx pat = gen_seqdi_special (operands[0], x, y);
           emit_insn (pat);
           return true;
         }
@@ -2535,14 +2535,21 @@  emit_scc_insn (rtx operands[])
         }
       else if (GET_MODE (x) == DImode)
         {
-          rtx pat = gen_snedi_special (operands[0], x, y);
+	  rtx pat;
+	  if (TARGET_VIS3)
+	    pat = gen_snedi_special_vis3 (operands[0], x, y);
+	  else
+	    pat = gen_snedi_special (operands[0], x, y);
           emit_insn (pat);
           return true;
         }
     }
 
   if (TARGET_V9
+      && TARGET_ARCH64
       && GET_MODE (x) == DImode
+      && !(TARGET_VIS3
+	   && (code == GTU || code == LTU))
       && gen_v9_scc (operands[0], code, x, y))
     return true;
 
@@ -2561,7 +2568,8 @@  emit_scc_insn (rtx operands[])
         }
     }
 
-  if (code == LTU || code == GEU)
+  if (code == LTU
+      || (!TARGET_VIS3 && code == GEU))
     {
       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
 			      gen_rtx_fmt_ee (code, SImode,
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index dcd23a1..6dd3909 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -656,7 +656,17 @@ 
 		(match_operand:DI 2 "register_operand" "")))
    (set (match_operand:SI 0 "register_operand" "")
 	(ne:SI (match_dup 3) (const_int 0)))]
-  "TARGET_ARCH64"
+  "TARGET_ARCH64 && ! TARGET_VIS3"
+  { operands[3] = gen_reg_rtx (DImode); })
+
+(define_expand "snedi_special_vis3"
+  [(set (match_dup 3)
+	(xor:DI (match_operand:DI 1 "register_operand" "")
+		(match_operand:DI 2 "register_operand" "")))
+   (parallel [(set (match_operand:SI 0 "register_operand" "")
+		   (ne:SI (match_dup 3) (const_int 0)))
+	      (clobber (reg:CCX CC_REG))])]
+  "TARGET_ARCH64 && TARGET_VIS3"
   { operands[3] = gen_reg_rtx (DImode); })
 
 
@@ -733,7 +743,7 @@ 
   [(set (match_operand:DI 0 "register_operand" "=&r")
         (ne:DI (match_operand:DI 1 "register_operand" "r")
                (const_int 0)))]
-  "TARGET_ARCH64"
+  "TARGET_ARCH64 && ! TARGET_VIS3"
   "#"
   "&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
   [(set (match_dup 0) (const_int 0))
@@ -744,6 +754,20 @@ 
   ""
   [(set_attr "length" "2")])
 
+(define_insn_and_split "*snedi_zero_vis3"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(ne:DI (match_operand:DI 1 "register_operand" "r")
+	       (const_int 0)))
+   (clobber (reg:CCX CC_REG))]
+  "TARGET_ARCH64 && TARGET_VIS3"
+  "#"
+  ""
+  [(set (reg:CCX_NOOV CC_REG) (compare:CCX_NOOV (neg:DI (match_dup 1))
+					        (const_int 0)))
+   (set (match_dup 0) (ltu:DI (reg:CCX CC_REG) (const_int 0)))]
+  ""
+  [(set_attr "length" "2")])
+
 (define_insn_and_split "*neg_snedi_zero"
   [(set (match_operand:DI 0 "register_operand" "=&r")
         (neg:DI (ne:DI (match_operand:DI 1 "register_operand" "r")
@@ -763,7 +787,7 @@ 
   [(set (match_operand:SI 0 "register_operand" "=&r")
         (ne:SI (match_operand:DI 1 "register_operand" "r")
                (const_int 0)))]
-  "TARGET_ARCH64"
+  "TARGET_ARCH64 && ! TARGET_VIS3"
   "#"
   "&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
   [(set (match_dup 0) (const_int 0))
@@ -774,6 +798,20 @@ 
   ""
   [(set_attr "length" "2")])
 
+(define_insn_and_split "*snedi_zero_trunc_vis3"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(ne:SI (match_operand:DI 1 "register_operand" "r")
+	       (const_int 0)))
+   (clobber (reg:CCX CC_REG))]
+  "TARGET_ARCH64 && TARGET_VIS3"
+  "#"
+  ""
+  [(set (reg:CCX_NOOV CC_REG) (compare:CCX_NOOV (neg:DI (match_dup 1))
+					        (const_int 0)))
+   (set (match_dup 0) (ltu:SI (reg:CCX CC_REG) (const_int 0)))]
+  ""
+  [(set_attr "length" "2")])
+
 (define_insn_and_split "*seqsi_zero"
   [(set (match_operand:SI 0 "register_operand" "=r")
 	(eq:SI (match_operand:SI 1 "register_operand" "r")
@@ -959,6 +997,20 @@ 
   "addx\t%%g0, 0, %0"
   [(set_attr "type" "ialuX")])
 
+(define_insn "*sltu_insn_vis3"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(ltu:DI (reg:CCX CC_REG) (const_int 0)))]
+  "TARGET_ARCH64 && TARGET_VIS3"
+  "addxc\t%%g0, %%g0, %0"
+  [(set_attr "type" "ialuX")])
+
+(define_insn "*sltu_insn_vis3_trunc"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(ltu:SI (reg:CCX CC_REG) (const_int 0)))]
+  "TARGET_ARCH64 && TARGET_VIS3"
+  "addxc\t%%g0, %%g0, %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)))]
@@ -3543,6 +3595,15 @@ 
   "addx\t%1, %2, %0"
   [(set_attr "type" "ialuX")])
 
+(define_insn "addxc"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(plus:DI (plus:DI (match_operand:DI 1 "register_or_zero_operand" "%rJ")
+			  (match_operand:DI 2 "register_or_zero_operand" "rJ"))
+		 (ltu:DI (reg:CCX_NOOV CC_REG) (const_int 0))))]
+  "TARGET_ARCH64 && TARGET_VIS3"
+  "addxc\t%r1, %r2, %0"
+  [(set_attr "type" "ialuX")])
+
 (define_insn_and_split "*addx_extend_sp32"
   [(set (match_operand:DI 0 "register_operand" "=r")
 	(zero_extend:DI (plus:SI (plus:SI
@@ -3562,10 +3623,19 @@ 
 (define_insn "*addx_extend_sp64"
   [(set (match_operand:DI 0 "register_operand" "=r")
 	(zero_extend:DI (plus:SI (plus:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ")
-                                          (match_operand:SI 2 "arith_operand" "rI"))
+                                          (match_operand:SI 2 "register_or_zero_operand" "rJ"))
                                  (ltu:SI (reg:CC_NOOV CC_REG) (const_int 0)))))]
   "TARGET_ARCH64"
-  "addx\t%r1, %2, %0"
+  "addx\t%r1, %r2, %0"
+  [(set_attr "type" "ialuX")])
+
+(define_insn "*addxc_trunc_sp64_vis3"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(plus:SI (plus:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ")
+                          (match_operand:SI 2 "register_or_zero_operand" "rJ"))
+                 (ltu:SI (reg:CCX_NOOV CC_REG) (const_int 0))))]
+  "TARGET_ARCH64 && TARGET_VIS3"
+  "addxc\t%r1, %r2, %0"
   [(set_attr "type" "ialuX")])
 
 (define_insn_and_split "*adddi3_extend_sp32"
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 1f1b77f..9ef38fc 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@ 
+2011-10-27  David S. Miller  <davem@davemloft.net>
+
+	* gcc.target/sparc/setcc-3.c: New test.
+
 2011-10-27  Roberto Agostino Vitillo  <ravitillo@lbl.gov>
 
 	PR c++/30066
diff --git a/gcc/testsuite/gcc.target/sparc/setcc-3.c b/gcc/testsuite/gcc.target/sparc/setcc-3.c
new file mode 100644
index 0000000..8a26b67
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/setcc-3.c
@@ -0,0 +1,24 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O1 -mvis3" } */
+
+int neq (long a, long b)
+{
+  return a != b;
+}
+
+int lt (unsigned long a, unsigned long b)
+{
+  return a < b;
+}
+
+int gt (unsigned long a, unsigned long b)
+{
+  return a > b;
+}
+
+/* { dg-final { scan-assembler "xor\t%" } } */
+/* { dg-final { scan-assembler "subcc\t%" } } */
+/* { dg-final { scan-assembler-times "addxc\t%" 3 } } */
+/* { dg-final { scan-assembler-times "cmp\t%" 2 } } */
+/* { dg-final { scan-assembler-not "sra\t%" } } */