aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/mips/mips.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/mips/mips.md')
-rw-r--r--gcc/config/mips/mips.md344
1 files changed, 234 insertions, 110 deletions
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 3855cb99c76..90bccf420ed 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -1812,6 +1812,38 @@
[(set_attr "type" "imul")
(set_attr "mode" "SI")])
+;; If a register gets allocated to LO, and we spill to memory, the reload
+;; will include a move from LO to a GPR. Merge it into the multiplication
+;; if it can set the GPR directly.
+;;
+;; Operand 0: LO
+;; Operand 1: GPR (1st multiplication operand)
+;; Operand 2: GPR (2nd multiplication operand)
+;; Operand 3: HI
+;; Operand 4: HILO
+;; Operand 5: GPR (destination)
+(define_peephole2
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "")
+ (mult:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "register_operand" "")))
+ (clobber (match_operand:SI 3 "register_operand" ""))
+ (clobber (scratch:SI))
+ (clobber (match_operand:SI 4 "register_operand" ""))])
+ (set (match_operand:SI 5 "register_operand" "")
+ (match_dup 0))]
+ "GENERATE_MULT3_SI
+ && true_regnum (operands[0]) == LO_REGNUM
+ && GP_REG_P (true_regnum (operands[5]))
+ && peep2_reg_dead_p (2, operands[0])"
+ [(parallel
+ [(set (match_dup 5)
+ (mult:SI (match_dup 1)
+ (match_dup 2)))
+ (clobber (match_dup 3))
+ (clobber (match_dup 0))
+ (clobber (match_dup 4))])])
+
(define_insn "mulsi3_internal"
[(set (match_operand:SI 0 "register_operand" "=l")
(mult:SI (match_operand:SI 1 "register_operand" "d")
@@ -1868,30 +1900,15 @@
(clobber (match_scratch:SI 6 "=a,a,a"))
(clobber (match_scratch:SI 7 "=X,X,d"))]
"(TARGET_MIPS3900
- || TARGET_MIPS5400
- || TARGET_MIPS5500
|| ISA_HAS_MADD_MSUB)
&& !TARGET_MIPS16"
"*
{
static const char *const madd[] = { \"madd\\t%1,%2\", \"madd\\t%0,%1,%2\" };
- static const char *const macc[] = { \"macc\\t$0,%1,%2\", \"macc\\t%0,%1,%2\" };
if (which_alternative == 2)
return \"#\";
if (ISA_HAS_MADD_MSUB && which_alternative != 0)
return \"#\";
-
- if (TARGET_MIPS5400)
- return macc[which_alternative];
-
- if (TARGET_MIPS5500)
- {
- if (which_alternative == 0)
- return madd[0];
- else
- return macc[which_alternative];
- }
-
return madd[which_alternative];
}"
[(set_attr "type" "imadd,imadd,multi")
@@ -1942,13 +1959,169 @@
(set (match_dup 0) (match_dup 3))]
"")
+(define_insn "*macc"
+ [(set (match_operand:SI 0 "register_operand" "=l,d")
+ (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d")
+ (match_operand:SI 2 "register_operand" "d,d"))
+ (match_operand:SI 3 "register_operand" "0,l")))
+ (clobber (match_scratch:SI 4 "=h,h"))
+ (clobber (match_scratch:SI 5 "=X,3"))
+ (clobber (match_scratch:SI 6 "=a,a"))]
+ "ISA_HAS_MACC"
+ "*
+{
+ if (which_alternative == 1)
+ return \"macc\\t%0,%1,%2\";
+ else if (TARGET_MIPS5500)
+ return \"madd\\t%1,%2\";
+ else
+ return \"macc\\t%.,%1,%2\";
+}"
+ [(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")
+ (match_operand:SI 2 "register_operand" "d"))
+ (match_dup 0)))
+ (set (match_operand:SI 3 "register_operand" "=d")
+ (plus:SI (mult:SI (match_dup 1)
+ (match_dup 2))
+ (match_dup 0)))
+ (clobber (match_scratch:SI 4 "=h"))
+ (clobber (match_scratch:SI 5 "=a"))]
+ "ISA_HAS_MACC && reload_completed"
+ "macc\\t%3,%1,%2"
+ [(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: HILO
+;; Operand 5: 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))
+ (clobber (match_operand:SI 4 "register_operand" ""))])
+ (set (match_operand:SI 5 "register_operand" "")
+ (match_dup 0))]
+ "ISA_HAS_MACC
+ && true_regnum (operands[0]) == LO_REGNUM
+ && GP_REG_P (true_regnum (operands[5]))"
+ [(parallel [(set (match_dup 0)
+ (plus:SI (mult:SI (match_dup 1)
+ (match_dup 2))
+ (match_dup 0)))
+ (set (match_dup 5)
+ (plus:SI (mult:SI (match_dup 1)
+ (match_dup 2))
+ (match_dup 0)))
+ (clobber (match_dup 3))
+ (clobber (match_dup 4))])]
+ "")
+
+;; When we have a three-address multiplication instruction, it should
+;; be faster to do a separate multiply and add, rather than moving
+;; something into LO in order to use a macc instruction.
+;;
+;; This peephole needs a scratch register to cater for the case when one
+;; of the multiplication operands is the same as the destination.
+;;
+;; Operand 0: GPR (scratch)
+;; 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 7: HILO
+(define_peephole2
+ [(match_scratch:SI 0 "d")
+ (set (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "register_operand" ""))
+ (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))
+ (clobber (match_operand:SI 7 "register_operand" ""))])]
+ "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))
+ (clobber (match_dup 7))])
+ (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: HILO
+;; Operand 7: GPR (destination)
+(define_peephole2
+ [(match_scratch:SI 0 "d")
+ (set (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "register_operand" ""))
+ (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))
+ (clobber (match_operand:SI 6 "register_operand" ""))])
+ (match_dup 0)
+ (set (match_operand:SI 7 "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[7]))"
+ [(parallel [(set (match_dup 0)
+ (mult:SI (match_dup 3)
+ (match_dup 4)))
+ (clobber (match_dup 5))
+ (clobber (match_dup 1))
+ (clobber (match_dup 6))])
+ (set (match_dup 7)
+ (plus:SI (match_dup 0)
+ (match_dup 2)))]
+ "")
+
(define_insn "*mul_sub_si"
[(set (match_operand:SI 0 "register_operand" "=l,*d,*d")
(minus:SI (match_operand:SI 1 "register_operand" "0,l,*d")
(mult:SI (match_operand:SI 2 "register_operand" "d,d,d")
(match_operand:SI 3 "register_operand" "d,d,d"))))
(clobber (match_scratch:SI 4 "=h,h,h"))
- (clobber (match_scratch:SI 5 "=X,3,l"))
+ (clobber (match_scratch:SI 5 "=X,1,l"))
(clobber (match_scratch:SI 6 "=a,a,a"))
(clobber (match_scratch:SI 7 "=X,X,d"))]
"ISA_HAS_MADD_MSUB"
@@ -2013,7 +2186,7 @@
(clobber (match_scratch:SI 3 "=h,h"))
(clobber (match_scratch:SI 4 "=a,a"))
(clobber (match_scratch:SI 5 "=X,l"))]
- "ISA_HAS_MULS && TARGET_64BIT"
+ "ISA_HAS_MULS"
"@
muls\\t$0,%1,%2
muls\\t%0,%1,%2"
@@ -2030,35 +2203,20 @@
(clobber (match_scratch:SI 5 "=X,1,l"))
(clobber (match_scratch:SI 6 "=a,a,a"))
(clobber (match_scratch:SI 7 "=X,X,d"))]
- "ISA_HAS_MSAC && TARGET_64BIT"
- "@
- msac\\t$0,%2,%3
- msac\\t%0,%2,%3
- #"
+ "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,imadd,multi")
(set_attr "mode" "SI")
(set_attr "length" "4,4,8")])
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (minus:SI (match_operand:SI 1 "register_operand" "")
- (mult:SI (match_operand:SI 2 "register_operand" "")
- (match_operand:SI 3 "register_operand" ""))))
- (clobber (match_scratch:SI 4 ""))
- (clobber (match_scratch:SI 5 ""))
- (clobber (match_scratch:SI 6 ""))
- (clobber (match_scratch:SI 7 ""))]
- "reload_completed && !TARGET_DEBUG_D_MODE
- && GP_REG_P (true_regnum (operands[0]))
- && GP_REG_P (true_regnum (operands[1]))"
- [(parallel [(set (match_dup 7)
- (mult:SI (match_dup 2) (match_dup 3)))
- (clobber (match_dup 4))
- (clobber (match_dup 5))
- (clobber (match_dup 6))])
- (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 7)))]
- "")
-
(define_expand "muldi3"
[(set (match_operand:DI 0 "register_operand" "=l")
(mult:DI (match_operand:DI 1 "se_register_operand" "d")
@@ -2194,22 +2352,17 @@
[(set_attr "type" "imul")
(set_attr "mode" "SI")])
-;; widening multiply with accumulator and/or negation
-;; These don't match yet for zero-extending; too complex for combine?
-;; Possible additions we should have:
-;; "=x" variants for when !TARGET_64BIT ?
-;; all-d alternatives with splits like pure SImode versions
+;; Widening multiply with negation. It isn't worth using this pattern
+;; for 64-bit code since the reload sequence for HILO_REGNUM is so long.
(define_insn "*muls_di"
- [(set (match_operand:DI 0 "register_operand" "=a")
+ [(set (match_operand:DI 0 "register_operand" "=x")
(neg:DI
(mult:DI (match_operator:DI 3 "extend_operator"
[(match_operand:SI 1 "register_operand" "d")])
(match_operator:DI 4 "extend_operator"
[(match_operand:SI 2 "register_operand" "d")]))))
- (clobber (match_scratch:SI 5 "=h"))
- (clobber (match_scratch:SI 6 "=l"))]
- "TARGET_64BIT
- && ISA_HAS_MULS
+ (clobber (match_scratch:SI 5 "=a"))]
+ "!TARGET_64BIT && ISA_HAS_MULS
&& GET_CODE (operands[3]) == GET_CODE (operands[4])"
"*
{
@@ -2222,33 +2375,32 @@
(set_attr "length" "4")
(set_attr "mode" "SI")])
+;; Not used for 64-bit code: see comment for *muls_di.
(define_insn "*msac_di"
- [(set (match_operand:DI 0 "register_operand" "=a")
+ [(set (match_operand:DI 0 "register_operand" "=x")
(minus:DI (match_operand:DI 3 "register_operand" "0")
(mult:DI (match_operator:DI 4 "extend_operator"
[(match_operand:SI 1 "register_operand" "d")])
(match_operator:DI 5 "extend_operator"
[(match_operand:SI 2 "register_operand" "d")]))))
- (clobber (match_scratch:SI 6 "=h"))
- (clobber (match_scratch:SI 7 "=l"))]
- "TARGET_64BIT
- && ISA_HAS_MSAC
+ (clobber (match_scratch:SI 6 "=a"))]
+ "!TARGET_64BIT && ISA_HAS_MSAC
&& GET_CODE (operands[4]) == GET_CODE (operands[5])"
"*
{
if (GET_CODE (operands[4]) == SIGN_EXTEND)
- {
- if (TARGET_MIPS5500)
- return \"msub\\t%1,%2\";
- else
- return \"msac\\t$0,%1,%2\";
+ {
+ if (TARGET_MIPS5500)
+ return \"msub\\t%1,%2\";
+ else
+ return \"msac\\t$0,%1,%2\";
}
else
- {
- if (TARGET_MIPS5500)
- return \"msubu\\t%1,%2\";
- else
- return \"msacu\\t$0,%1,%2\";
+ {
+ if (TARGET_MIPS5500)
+ return \"msubu\\t%1,%2\";
+ else
+ return \"msacu\\t$0,%1,%2\";
}
}"
[(set_attr "type" "imadd")
@@ -2272,9 +2424,9 @@
#else
rtx (*genfn) ();
#endif
- if (ISA_HAS_MULHI && TARGET_64BIT)
+ if (ISA_HAS_MULHI)
genfn = gen_xmulsi3_highpart_mulhi;
- else
+ else
genfn = gen_xmulsi3_highpart_internal;
emit_insn ((*genfn) (operands[0], operands[1], operands[2], dummy,
dummy, dummy2));
@@ -2297,7 +2449,7 @@
#else
rtx (*genfn) ();
#endif
- if (ISA_HAS_MULHI && TARGET_64BIT)
+ if (ISA_HAS_MULHI)
genfn = gen_xmulsi3_highpart_mulhi;
else
genfn = gen_xmulsi3_highpart_internal;
@@ -2317,7 +2469,7 @@
(const_int 32)])))
(clobber (match_scratch:SI 6 "=l"))
(clobber (match_scratch:SI 7 "=a"))]
- "GET_CODE (operands[3]) == GET_CODE (operands[4])"
+ "!ISA_HAS_MULHI && GET_CODE (operands[3]) == GET_CODE (operands[4])"
"*
{
if (GET_CODE (operands[3]) == SIGN_EXTEND)
@@ -2340,9 +2492,7 @@
(clobber (match_scratch:SI 6 "=l,l"))
(clobber (match_scratch:SI 7 "=a,a"))
(clobber (match_scratch:SI 8 "=X,h"))]
- "ISA_HAS_MULHI
- && TARGET_64BIT
- && GET_CODE (operands[3]) == GET_CODE (operands[4])"
+ "ISA_HAS_MULHI && GET_CODE (operands[3]) == GET_CODE (operands[4])"
"*
{
static char const *const sign[] = { \"mult\\t%1,%2\", \"mulhi\\t%0,%1,%2\" };
@@ -2369,9 +2519,7 @@
(clobber (match_scratch:SI 6 "=l,l"))
(clobber (match_scratch:SI 7 "=a,a"))
(clobber (match_scratch:SI 8 "=X,h"))]
- "ISA_HAS_MULHI
- && TARGET_64BIT
- && GET_CODE (operands[3]) == GET_CODE (operands[4])"
+ "ISA_HAS_MULHI && GET_CODE (operands[3]) == GET_CODE (operands[4])"
"*
{
static char const *const sign[] = { \"mulshi\\t$0,%1,%2\", \"mulshi\\t%0,%1,%2\" };
@@ -2427,38 +2575,17 @@
[(set_attr "type" "imadd")
(set_attr "mode" "SI")])
+;; Only use this pattern in 32-bit code: see *muls_di.
(define_insn "*mul_acc_di"
- [(set (match_operand:DI 0 "register_operand" "+x")
- (plus:DI (mult:DI (match_operator:DI 3 "extend_operator"
- [(match_operand:SI 1 "register_operand" "d")])
- (match_operator:DI 4 "extend_operator"
- [(match_operand:SI 2 "register_operand" "d")]))
- (match_dup 0)))
- (clobber (match_scratch:SI 5 "=a"))]
- "TARGET_MAD
- && ! TARGET_64BIT
- && GET_CODE (operands[3]) == GET_CODE (operands[4])"
- "*
-{
- if (GET_CODE (operands[3]) == SIGN_EXTEND)
- return \"mad\\t%1,%2\";
- else
- return \"madu\\t%1,%2\";
-}"
- [(set_attr "type" "imadd")
- (set_attr "mode" "SI")])
-
-(define_insn "*mul_acc_64bit_di"
- [(set (match_operand:DI 0 "register_operand" "+a")
+ [(set (match_operand:DI 0 "register_operand" "=x")
(plus:DI (mult:DI (match_operator:DI 3 "extend_operator"
[(match_operand:SI 1 "register_operand" "d")])
(match_operator:DI 4 "extend_operator"
[(match_operand:SI 2 "register_operand" "d")]))
- (match_dup 0)))
- (clobber (match_scratch:SI 5 "=h"))
- (clobber (match_scratch:SI 6 "=l"))]
- "TARGET_MAD
- && TARGET_64BIT
+ (match_operand:DI 5 "register_operand" "0")))
+ (clobber (match_scratch:SI 6 "=a"))]
+ "(TARGET_MAD || ISA_HAS_MACC)
+ && !TARGET_64BIT
&& GET_CODE (operands[3]) == GET_CODE (operands[4])"
"*
{
@@ -2469,26 +2596,23 @@
else
return \"madu\\t%1,%2\";
}
- else if (ISA_HAS_MACC)
+ else
{
if (GET_CODE (operands[3]) == SIGN_EXTEND)
{
if (TARGET_MIPS5500)
return \"madd\\t%1,%2\";
else
- return \"macc\\t$0,%1,%2\";
+ return \"macc\\t$0,%1,%2\";
}
else
{
if (TARGET_MIPS5500)
return \"maddu\\t%1,%2\";
else
- return \"maccu\\t$0,%1,%2\";
+ return \"maccu\\t$0,%1,%2\";
}
}
- else
- abort ();
-
}"
[(set_attr "type" "imadd")
(set_attr "mode" "SI")])