From 47bac44b58d233131d21f747fbef69bd389c8387 Mon Sep 17 00:00:00 2001
From: rsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Sat, 17 Apr 2004 07:02:32 +0000
Subject: [PATCH] 	* config/mips/mips.h (PREDICATE_CODES): Add
 macc_msac_operand. 	* config/mips/mips.c (macc_msac_operand): New
 function. 	* config/mips/mips.md (*msac): Move after *macc. 
 (*msac2): New.  Generalize macc-related peepholes so that they apply 	to
 msac too.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@80790 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/ChangeLog                    |   8 ++
 gcc/config/mips/mips.c           |  16 ++++
 gcc/config/mips/mips.h           |   1 +
 gcc/config/mips/mips.md          | 155 +++++++++++++++++--------------
 gcc/testsuite/ChangeLog          |   4 +
 gcc/testsuite/gcc.dg/vr-mult-1.c |  10 ++
 gcc/testsuite/gcc.dg/vr-mult-2.c |  10 ++
 7 files changed, 132 insertions(+), 72 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/vr-mult-1.c
 create mode 100644 gcc/testsuite/gcc.dg/vr-mult-2.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0a29202d65b8..e8f9213e7c05 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2004-04-17  Richard Sandiford  <rsandifo@redhat.com>
+
+	* config/mips/mips.h (PREDICATE_CODES): Add macc_msac_operand.
+	* config/mips/mips.c (macc_msac_operand): New function.
+	* config/mips/mips.md (*msac): Move after *macc.
+	(*msac2): New.  Generalize macc-related peepholes so that they apply
+	to msac too.
+
 2004-04-17  Paolo Bonzini  <bonzini@gnu.org>
 
 	* opts.c (decode_options): Do not enable flag_rename_registers
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index b8d27a3c39f4..16a1ab252986 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -1449,6 +1449,22 @@ extend_operator (rtx op, enum machine_mode mode)
 	  && (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND));
 }
 
+/* Return true if X is the right hand side of a "macc" or "msac" instruction.
+   This predicate is intended for use in peephole optimizations.  */
+
+int
+macc_msac_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  if (ISA_HAS_MACC && GET_CODE (x) == PLUS && REG_P (XEXP (x, 1)))
+    x = XEXP (x, 0);
+  else if (ISA_HAS_MSAC && GET_CODE (x) == MINUS && REG_P (XEXP (x, 0)))
+    x = XEXP (x, 1);
+  else
+    return false;
+
+  return GET_CODE (x) == MULT && REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 1));
+}
+
 /* Return nonzero if the code of this rtx pattern is EQ or NE.  */
 
 int
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index c4b7769db515..8bd9fb710de6 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -2742,6 +2742,7 @@ typedef struct mips_args {
 				  CONST_DOUBLE, CONST }},		\
   {"fcc_register_operand",	{ REG, SUBREG }},			\
   {"hilo_operand",		{ REG }},				\
+  {"macc_msac_operand",		{ PLUS, MINUS }},			\
   {"extend_operator",		{ ZERO_EXTEND, SIGN_EXTEND }},
 
 /* A list of predicates that do special things with modes, and so
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index fdf3f96fef06..0ac944419ec4 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -1678,7 +1678,27 @@
   [(set_attr "type" "imadd")
    (set_attr "mode" "SI")])
 
-;; Pattern generated by define_peephole2 below
+(define_insn "*msac"
+  [(set (match_operand:SI 0 "register_operand" "=l,d")
+        (minus:SI (match_operand:SI 1 "register_operand" "0,l")
+                  (mult:SI (match_operand:SI 2 "register_operand" "d,d")
+                           (match_operand:SI 3 "register_operand" "d,d"))))
+   (clobber (match_scratch:SI 4 "=h,h"))
+   (clobber (match_scratch:SI 5 "=X,1"))]
+  "ISA_HAS_MSAC"
+{
+  if (which_alternative == 1)
+    return "msac\t%0,%2,%3";
+  else if (TARGET_MIPS5500)
+    return "msub\t%2,%3";
+  else
+    return "msac\t$0,%2,%3";
+}
+  [(set_attr "type"     "imadd")
+   (set_attr "mode"     "SI")])
+
+;; Patterns generated by the define_peephole2 below.
+
 (define_insn "*macc2"
   [(set (match_operand:SI 0 "register_operand" "=l")
 	(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d")
@@ -1694,35 +1714,43 @@
   [(set_attr "type"	"imadd")
    (set_attr "mode"	"SI")])
 
+(define_insn "*msac2"
+  [(set (match_operand:SI 0 "register_operand" "=l")
+	(minus:SI (match_dup 0)
+		  (mult:SI (match_operand:SI 1 "register_operand" "d")
+			   (match_operand:SI 2 "register_operand" "d"))))
+   (set (match_operand:SI 3 "register_operand" "=d")
+	(minus:SI (match_dup 0)
+		  (mult:SI (match_dup 1)
+			   (match_dup 2))))
+   (clobber (match_scratch:SI 4 "=h"))]
+  "ISA_HAS_MSAC && reload_completed"
+  "msac\t%3,%1,%2"
+  [(set_attr "type"	"imadd")
+   (set_attr "mode"	"SI")])
+
 ;; Convert macc $0,<r1>,<r2> & mflo <r3> into macc <r3>,<r1>,<r2>
+;; Similarly msac.
 ;;
 ;; Operand 0: LO
-;; Operand 1: GPR (1st multiplication operand)
-;; Operand 2: GPR (2nd multiplication operand)
-;; Operand 3: HI
-;; Operand 4: GPR (destination)
+;; Operand 1: macc/msac
+;; Operand 2: HI
+;; Operand 3: GPR (destination)
 (define_peephole2
   [(parallel
        [(set (match_operand:SI 0 "register_operand" "")
-	     (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "")
-			       (match_operand:SI 2 "register_operand" ""))
-		      (match_dup 0)))
-	(clobber (match_operand:SI 3 "register_operand" ""))
+	     (match_operand:SI 1 "macc_msac_operand" ""))
+	(clobber (match_operand:SI 2 "register_operand" ""))
 	(clobber (scratch:SI))])
-   (set (match_operand:SI 4 "register_operand" "")
+   (set (match_operand:SI 3 "register_operand" "")
 	(match_dup 0))]
-  "ISA_HAS_MACC
-   && true_regnum (operands[0]) == LO_REGNUM
-   && GP_REG_P (true_regnum (operands[4]))"
+  "true_regnum (operands[0]) == LO_REGNUM
+   && GP_REG_P (true_regnum (operands[3]))"
   [(parallel [(set (match_dup 0)
-		   (plus:SI (mult:SI (match_dup 1)
-				     (match_dup 2))
-			    (match_dup 0)))
-	      (set (match_dup 4)
-		   (plus:SI (mult:SI (match_dup 1)
-				     (match_dup 2))
-			    (match_dup 0)))
-	      (clobber (match_dup 3))])]
+		   (match_dup 1))
+	      (set (match_dup 3)
+		   (match_dup 1))
+	      (clobber (match_dup 2))])]
   "")
 
 ;; When we have a three-address multiplication instruction, it should
@@ -1736,9 +1764,10 @@
 ;; Operand 1: LO
 ;; Operand 2: GPR (addend)
 ;; Operand 3: GPR (destination)
-;; Operand 4: GPR (1st multiplication operand)
-;; Operand 5: GPR (2nd multiplication operand)
-;; Operand 6: HI
+;; Operand 4: macc/msac
+;; Operand 5: HI
+;; Operand 6: new multiplication
+;; Operand 7: new addition/subtraction
 (define_peephole2
   [(match_scratch:SI 0 "d")
    (set (match_operand:SI 1 "register_operand" "")
@@ -1746,34 +1775,35 @@
    (match_dup 0)
    (parallel
        [(set (match_operand:SI 3 "register_operand" "")
-	     (plus:SI (mult:SI (match_operand:SI 4 "register_operand" "")
-			       (match_operand:SI 5 "register_operand" ""))
-		      (match_dup 1)))
-	(clobber (match_operand:SI 6 "register_operand" ""))
+	     (match_operand:SI 4 "macc_msac_operand" ""))
+	(clobber (match_operand:SI 5 "register_operand" ""))
 	(clobber (match_dup 1))])]
-  "ISA_HAS_MACC && GENERATE_MULT3_SI
+  "GENERATE_MULT3_SI
    && true_regnum (operands[1]) == LO_REGNUM
    && peep2_reg_dead_p (2, operands[1])
    && GP_REG_P (true_regnum (operands[3]))"
   [(parallel [(set (match_dup 0)
-		   (mult:SI (match_dup 4)
-			    (match_dup 5)))
-	      (clobber (match_dup 6))
+		   (match_dup 6))
+	      (clobber (match_dup 5))
 	      (clobber (match_dup 1))])
    (set (match_dup 3)
-	(plus:SI (match_dup 0)
-		 (match_dup 2)))]
-  "")
+	(match_dup 7))]
+{
+  operands[6] = XEXP (operands[4], GET_CODE (operands[4]) == PLUS ? 0 : 1);
+  operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode,
+				operands[2], operands[0]);
+})
 
 ;; Same as above, except LO is the initial target of the macc.
 ;;
 ;; Operand 0: GPR (scratch)
 ;; Operand 1: LO
 ;; Operand 2: GPR (addend)
-;; Operand 3: GPR (1st multiplication operand)
-;; Operand 4: GPR (2nd multiplication operand)
-;; Operand 5: HI
-;; Operand 6: GPR (destination)
+;; Operand 3: macc/msac
+;; Operand 4: HI
+;; Operand 5: GPR (destination)
+;; Operand 6: new multiplication
+;; Operand 7: new addition/subtraction
 (define_peephole2
   [(match_scratch:SI 0 "d")
    (set (match_operand:SI 1 "register_operand" "")
@@ -1781,27 +1811,27 @@
    (match_dup 0)
    (parallel
        [(set (match_dup 1)
-	     (plus:SI (mult:SI (match_operand:SI 3 "register_operand" "")
-			       (match_operand:SI 4 "register_operand" ""))
-		      (match_dup 1)))
-	(clobber (match_operand:SI 5 "register_operand" ""))
+	     (match_operand:SI 3 "macc_msac_operand" ""))
+	(clobber (match_operand:SI 4 "register_operand" ""))
 	(clobber (scratch:SI))])
    (match_dup 0)
-   (set (match_operand:SI 6 "register_operand" "")
+   (set (match_operand:SI 5 "register_operand" "")
 	(match_dup 1))]
-  "ISA_HAS_MACC && GENERATE_MULT3_SI
+  "GENERATE_MULT3_SI
    && true_regnum (operands[1]) == LO_REGNUM
    && peep2_reg_dead_p (3, operands[1])
-   && GP_REG_P (true_regnum (operands[6]))"
+   && GP_REG_P (true_regnum (operands[5]))"
   [(parallel [(set (match_dup 0)
-		   (mult:SI (match_dup 3)
-			    (match_dup 4)))
-	      (clobber (match_dup 5))
+		   (match_dup 6))
+	      (clobber (match_dup 4))
 	      (clobber (match_dup 1))])
-   (set (match_dup 6)
-	(plus:SI (match_dup 0)
-		 (match_dup 2)))]
-  "")
+   (set (match_dup 5)
+	(match_dup 7))]
+{
+  operands[6] = XEXP (operands[4], GET_CODE (operands[4]) == PLUS ? 0 : 1);
+  operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode,
+				operands[2], operands[0]);
+})
 
 (define_insn "*mul_sub_si"
   [(set (match_operand:SI 0 "register_operand" "=l,*d,*d")
@@ -1873,25 +1903,6 @@
   [(set_attr "type"     "imul")
    (set_attr "mode"     "SI")])
 
-(define_insn "*msac"
-  [(set (match_operand:SI 0 "register_operand" "=l,d")
-        (minus:SI (match_operand:SI 1 "register_operand" "0,l")
-                  (mult:SI (match_operand:SI 2 "register_operand" "d,d")
-                           (match_operand:SI 3 "register_operand" "d,d"))))
-   (clobber (match_scratch:SI 4 "=h,h"))
-   (clobber (match_scratch:SI 5 "=X,1"))]
-  "ISA_HAS_MSAC"
-{
-  if (which_alternative == 1)
-    return "msac\t%0,%2,%3";
-  else if (TARGET_MIPS5500)
-    return "msub\t%2,%3";
-  else
-    return "msac\t$0,%2,%3";
-}
-  [(set_attr "type"     "imadd")
-   (set_attr "mode"     "SI")])
-
 (define_expand "muldi3"
   [(set (match_operand:DI 0 "register_operand" "")
 	(mult:DI (match_operand:DI 1 "register_operand" "")
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index e3fd06ac1b4a..a8a7364ad26c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2004-04-17  Richard Sandiford  <rsandifo@redhat.com>
+
+	* gcc.dg/vr-mult-[12].c: New tests.
+
 2004-04-16  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
 
 	* gcc.dg/funcorder.c: xfail hppa*64*-*-*.
diff --git a/gcc/testsuite/gcc.dg/vr-mult-1.c b/gcc/testsuite/gcc.dg/vr-mult-1.c
new file mode 100644
index 000000000000..a208067fb7db
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vr-mult-1.c
@@ -0,0 +1,10 @@
+/* Make sure that mul/addu is preferred over mtlo/macc on targets that
+   support both.  */
+/* { dg-do compile { target mips*-*-* } } */
+/* { dg-options "-O2" } */
+#if defined (_MIPS_ARCH_VR5400) || defined (_MIPS_ARCH_VR5500)
+int f (int a, int b, int c) { return a + b * c; }
+#else
+void f () { asm volatile ("mul/addu"); }
+#endif
+/* { dg-final { scan-assembler "mul.*addu" } } */
diff --git a/gcc/testsuite/gcc.dg/vr-mult-2.c b/gcc/testsuite/gcc.dg/vr-mult-2.c
new file mode 100644
index 000000000000..4a3ad98cc2a9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vr-mult-2.c
@@ -0,0 +1,10 @@
+/* Make sure that mul/subu is preferred over mtlo/msac on targets that
+   support both.  */
+/* { dg-do compile { target mips*-*-* } } */
+/* { dg-options "-O2" } */
+#if defined (_MIPS_ARCH_VR5400) || defined (_MIPS_ARCH_VR5500)
+int f (int a, int b, int c) { return a - b * c; }
+#else
+void f () { asm volatile ("mul/subu"); }
+#endif
+/* { dg-final { scan-assembler "mul.*subu" } } */
-- 
GitLab