[committed] Extend MIPS macc optimisations to msac

Richard Sandiford rsandifo@redhat.com
Sat Apr 17 07:03:00 GMT 2004


The MIPS port has two sets of peephole optimisations for VR-style macc
instructions.  The first tries to use both the LO and GPR destinations
of the macc if possible, so something like "macc $0,$4,$5;mflo $6" will
become "macc $6,$4,$5".  If 3-operand multiplications are supported,
the second set tries to replace single maccs with a separate multiplication
and addition.  This is usually better since the multiplications can then
be pipelined.

The same optimisations are useful for msac too, so this patch
generalises them to cover both macc and msac.

I also added a couple of test cases to check the second set
of peepholes.  It's harder to check the first since everything
depends to a great extent on register allocation.

Unfortunately, adding -march=vr5400 to dg-options will break tests
for multilibs like -mips3.  The tests therefore don't try to force
a particular architecture.

Tested on mips64vrel-elf.  Also bootstrapped & regression tested on
mips64{,el}-linux-gnu.  Applied to HEAD.

Richard


	* 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.

gcc/testsuite
	* gcc.dg/vr-mult-[12].c: New tests.

Index: config/mips/mips.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.h,v
retrieving revision 1.331
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.331 mips.h
*** config/mips/mips.h	14 Apr 2004 08:36:58 -0000	1.331
--- config/mips/mips.h	17 Apr 2004 06:42:09 -0000
*************** #define PREDICATE_CODES							\
*** 2742,2747 ****
--- 2742,2748 ----
  				  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
Index: config/mips/mips.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.c,v
retrieving revision 1.401
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.401 mips.c
*** config/mips/mips.c	14 Apr 2004 08:36:57 -0000	1.401
--- config/mips/mips.c	17 Apr 2004 06:42:07 -0000
*************** extend_operator (rtx op, enum machine_mo
*** 1449,1454 ****
--- 1449,1470 ----
  	  && (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
Index: config/mips/mips.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.md,v
retrieving revision 1.230
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.230 mips.md
*** config/mips/mips.md	14 Apr 2004 08:36:58 -0000	1.230
--- config/mips/mips.md	17 Apr 2004 06:42:10 -0000
*************** (define_insn "*macc"
*** 1678,1684 ****
    [(set_attr "type" "imadd")
     (set_attr "mode" "SI")])
  
! ;; Pattern generated by 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")
--- 1678,1704 ----
    [(set_attr "type" "imadd")
     (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")])
! 
! ;; 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")
*************** (define_insn "*macc2"
*** 1694,1728 ****
    [(set_attr "type"	"imadd")
     (set_attr "mode"	"SI")])
  
  ;; Convert macc $0,<r1>,<r2> & mflo <r3> into macc <r3>,<r1>,<r2>
  ;;
  ;; Operand 0: LO
! ;; Operand 1: GPR (1st multiplication operand)
! ;; Operand 2: GPR (2nd multiplication operand)
! ;; Operand 3: HI
! ;; Operand 4: 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" ""))
  	(clobber (scratch:SI))])
!    (set (match_operand:SI 4 "register_operand" "")
  	(match_dup 0))]
!   "ISA_HAS_MACC
!    && true_regnum (operands[0]) == LO_REGNUM
!    && GP_REG_P (true_regnum (operands[4]))"
    [(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))])]
    "")
  
  ;; When we have a three-address multiplication instruction, it should
--- 1714,1756 ----
    [(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: macc/msac
! ;; Operand 2: HI
! ;; Operand 3: GPR (destination)
  (define_peephole2
    [(parallel
         [(set (match_operand:SI 0 "register_operand" "")
! 	     (match_operand:SI 1 "macc_msac_operand" ""))
! 	(clobber (match_operand:SI 2 "register_operand" ""))
  	(clobber (scratch:SI))])
!    (set (match_operand:SI 3 "register_operand" "")
  	(match_dup 0))]
!   "true_regnum (operands[0]) == LO_REGNUM
!    && GP_REG_P (true_regnum (operands[3]))"
    [(parallel [(set (match_dup 0)
! 		   (match_dup 1))
! 	      (set (match_dup 3)
! 		   (match_dup 1))
! 	      (clobber (match_dup 2))])]
    "")
  
  ;; When we have a three-address multiplication instruction, it should
*************** (define_peephole2
*** 1736,1744 ****
  ;; 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
  (define_peephole2
    [(match_scratch:SI 0 "d")
     (set (match_operand:SI 1 "register_operand" "")
--- 1764,1773 ----
  ;; Operand 1: LO
  ;; Operand 2: GPR (addend)
  ;; Operand 3: GPR (destination)
! ;; 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" "")
*************** (define_peephole2
*** 1746,1779 ****
     (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" ""))
  	(clobber (match_dup 1))])]
!   "ISA_HAS_MACC && 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))
  	      (clobber (match_dup 1))])
     (set (match_dup 3)
! 	(plus:SI (match_dup 0)
! 		 (match_dup 2)))]
!   "")
  
  ;; 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)
  (define_peephole2
    [(match_scratch:SI 0 "d")
     (set (match_operand:SI 1 "register_operand" "")
--- 1775,1809 ----
     (match_dup 0)
     (parallel
         [(set (match_operand:SI 3 "register_operand" "")
! 	     (match_operand:SI 4 "macc_msac_operand" ""))
! 	(clobber (match_operand:SI 5 "register_operand" ""))
  	(clobber (match_dup 1))])]
!   "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)
! 		   (match_dup 6))
! 	      (clobber (match_dup 5))
  	      (clobber (match_dup 1))])
     (set (match_dup 3)
! 	(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: 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" "")
*************** (define_peephole2
*** 1781,1807 ****
     (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" ""))
  	(clobber (scratch:SI))])
     (match_dup 0)
!    (set (match_operand:SI 6 "register_operand" "")
  	(match_dup 1))]
!   "ISA_HAS_MACC && GENERATE_MULT3_SI
     && true_regnum (operands[1]) == LO_REGNUM
     && peep2_reg_dead_p (3, operands[1])
!    && GP_REG_P (true_regnum (operands[6]))"
    [(parallel [(set (match_dup 0)
! 		   (mult:SI (match_dup 3)
! 			    (match_dup 4)))
! 	      (clobber (match_dup 5))
  	      (clobber (match_dup 1))])
!    (set (match_dup 6)
! 	(plus:SI (match_dup 0)
! 		 (match_dup 2)))]
!   "")
  
  (define_insn "*mul_sub_si"
    [(set (match_operand:SI 0 "register_operand" "=l,*d,*d")
--- 1811,1837 ----
     (match_dup 0)
     (parallel
         [(set (match_dup 1)
! 	     (match_operand:SI 3 "macc_msac_operand" ""))
! 	(clobber (match_operand:SI 4 "register_operand" ""))
  	(clobber (scratch:SI))])
     (match_dup 0)
!    (set (match_operand:SI 5 "register_operand" "")
  	(match_dup 1))]
!   "GENERATE_MULT3_SI
     && true_regnum (operands[1]) == LO_REGNUM
     && peep2_reg_dead_p (3, operands[1])
!    && GP_REG_P (true_regnum (operands[5]))"
    [(parallel [(set (match_dup 0)
! 		   (match_dup 6))
! 	      (clobber (match_dup 4))
  	      (clobber (match_dup 1))])
!    (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")
*************** (define_insn "*muls"
*** 1871,1895 ****
     muls\t$0,%1,%2
     muls\t%0,%1,%2"
    [(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"
--- 1901,1906 ----
*** /dev/null	Tue Jun 17 23:06:41 2003
--- testsuite/gcc.dg/vr-mult-1.c	Sat Apr 17 07:27:11 2004
***************
*** 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" } } */
*** /dev/null	Tue Jun 17 23:06:41 2003
--- testsuite/gcc.dg/vr-mult-2.c	Sat Apr 17 07:25:31 2004
***************
*** 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" } } */



More information about the Gcc-patches mailing list