diff options
Diffstat (limited to 'gcc/config/mips/mips.md')
-rw-r--r-- | gcc/config/mips/mips.md | 344 |
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")]) |