* Claudiu Zissulescu <claudiu.zissule...@synopsys.com> [2017-04-25 15:03:44 +0200]:
> Add support for MAC and DMPY instructions. ARCv2 Only. > > gcc/ > 2016-12-08 Claudiu Zissulescu <claz...@synopsys.com> > > * config/arc/arc.c (arc_conditional_register_usage): Handle ACCL, > ACCH registers. > * config/arc/arc.md (mulsidi3): Use advanced mpy instructions when > available. > (umulsidi3): Likewise. > (mulsidi3_700): Disable this pattern when we have advanced mpy > instructions. > (umulsidi3_700): Likewise. > (maddsidi4): New pattern. > (macd, mac, mac_r, umaddsidi4, macdu, macu, macu_r): Likewise. > (mpyd_arcv2hs, mpyd_imm_arcv2hs, mpydu_arcv2hs): Likewise. > (mpydu_imm_arcv2hs): Likewise. > * config/arc/predicates.md (accl_operand): New predicate. Looks good, but is it not possible to write some tests? Thanks, Andrew > --- > gcc/config/arc/arc.c | 5 +- > gcc/config/arc/arc.md | 266 > ++++++++++++++++++++++++++++++++++++++++++- > gcc/config/arc/predicates.md | 5 + > 3 files changed, 272 insertions(+), 4 deletions(-) > > diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c > index 170b8dd..238244b 100644 > --- a/gcc/config/arc/arc.c > +++ b/gcc/config/arc/arc.c > @@ -1789,8 +1789,9 @@ arc_conditional_register_usage (void) > arc_regno_reg_class[PROGRAM_COUNTER_REGNO] = GENERAL_REGS; > > /*ARCV2 Accumulator. */ > - if (TARGET_V2 > - && (TARGET_FP_DP_FUSED || TARGET_FP_SP_FUSED)) > + if ((TARGET_V2 > + && (TARGET_FP_DP_FUSED || TARGET_FP_SP_FUSED)) > + || TARGET_PLUS_DMPY) > { > arc_regno_reg_class[ACCL_REGNO] = WRITABLE_CORE_REGS; > arc_regno_reg_class[ACCH_REGNO] = WRITABLE_CORE_REGS; > diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md > index ffab390..db5867c 100644 > --- a/gcc/config/arc/arc.md > +++ b/gcc/config/arc/arc.md > @@ -2157,6 +2157,18 @@ > "TARGET_ANY_MPY" > " > { > + if (TARGET_PLUS_MACD) > + { > + if (CONST_INT_P (operands[2])) > + { > + emit_insn (gen_mpyd_imm_arcv2hs (operands[0], operands[1], > operands[2])); > + } > + else > + { > + emit_insn (gen_mpyd_arcv2hs (operands[0], operands[1], operands[2])); > + } > + DONE; > + } > if (TARGET_MPY) > { > operands[2] = force_reg (SImode, operands[2]); > @@ -2237,7 +2249,7 @@ > [(set (match_operand:DI 0 "register_operand" "=&r") > (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%c")) > (sign_extend:DI (match_operand:SI 2 "extend_operand" "cL"))))] > - "TARGET_MPY" > + "TARGET_MPY && !TARGET_PLUS_MACD" > "#" > "&& reload_completed" > [(const_int 0)] > @@ -2390,6 +2402,18 @@ > (zero_extend:DI (match_operand:SI 2 "nonmemory_operand" ""))))] > "" > { > + if (TARGET_PLUS_MACD) > + { > + if (CONST_INT_P (operands[2])) > + { > + emit_insn (gen_mpydu_imm_arcv2hs (operands[0], operands[1], > operands[2])); > + } > + else > + { > + emit_insn (gen_mpydu_arcv2hs (operands[0], operands[1], operands[2])); > + } > + DONE; > + } > if (TARGET_MPY) > { > operands[2] = force_reg (SImode, operands[2]); > @@ -2480,7 +2504,7 @@ > [(set (match_operand:DI 0 "dest_reg_operand" "=&r") > (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%c")) > (zero_extend:DI (match_operand:SI 2 "extend_operand" "cL"))))] > - "TARGET_MPY" > + "TARGET_MPY && !TARGET_PLUS_MACD" > "#" > "reload_completed" > [(const_int 0)] > @@ -6215,6 +6239,244 @@ > "" > [(set_attr "length" "0")]) > > +;; MAC and DMPY instructions > +(define_insn_and_split "maddsidi4" > + [(set (match_operand:DI 0 "register_operand" "=r") > + (plus:DI > + (mult:DI > + (sign_extend:DI (match_operand:SI 1 "register_operand" "%r")) > + (sign_extend:DI (match_operand:SI 2 "extend_operand" "ri"))) > + (match_operand:DI 3 "register_operand" "r")))] > + "TARGET_PLUS_DMPY" > + "#" > + "TARGET_PLUS_DMPY && reload_completed" > + [(const_int 0)] > + "{ > + rtx acc_reg = gen_rtx_REG (DImode, ACC_REG_FIRST); > + emit_move_insn (acc_reg, operands[3]); > + if (TARGET_PLUS_MACD) > + emit_insn (gen_macd (operands[0], operands[1], operands[2])); > + else > + { > + emit_insn (gen_mac (operands[1], operands[2])); > + emit_move_insn (operands[0], acc_reg); > + } > + DONE; > + }" > + [(set_attr "type" "multi") > + (set_attr "length" "36")]) > + > +(define_insn "macd" > + [(set (match_operand:DI 0 "even_register_operand" "=Rcr,r,r") > + (plus:DI > + (mult:DI > + (sign_extend:DI (match_operand:SI 1 "register_operand" "%0,c,c")) > + (sign_extend:DI (match_operand:SI 2 "extend_operand" " c,cI,Cal"))) > + (reg:DI ARCV2_ACC))) > + (set (reg:DI ARCV2_ACC) > + (plus:DI > + (mult:DI (sign_extend:DI (match_dup 1)) > + (sign_extend:DI (match_dup 2))) > + (reg:DI ARCV2_ACC)))] > + "TARGET_PLUS_MACD" > + "macd %0,%1,%2" > + [(set_attr "length" "4,4,8") > + (set_attr "type" "multi") > + (set_attr "predicable" "yes,no,no") > + (set_attr "cond" "canuse,nocond,nocond")]) > + > +(define_insn "mac" > + [(set (reg:DI ARCV2_ACC) > + (plus:DI > + (mult:DI (sign_extend:DI (match_operand:SI 0 "register_operand" > "%r,r")) > + (sign_extend:DI (match_operand:SI 1 "extend_operand" "rI,i"))) > + (reg:DI ARCV2_ACC)))] > + "TARGET_PLUS_DMPY" > + "mac 0,%0,%1" > + [(set_attr "length" "4,8") > + (set_attr "type" "multi") > + (set_attr "predicable" "no") > + (set_attr "cond" "nocond")]) > + > +(define_peephole2 > + [(set (reg:DI ARCV2_ACC) > + (plus:DI > + (mult:DI (sign_extend:DI (match_operand:SI 0 "register_operand" "")) > + (sign_extend:DI (match_operand:SI 1 "extend_operand" ""))) > + (reg:DI ARCV2_ACC))) > + (set (match_operand:SI 2 "register_operand" "") > + (match_operand:SI 3 "accl_operand" ""))] > + "TARGET_PLUS_DMPY" > + [(const_int 0)] > + { > + emit_insn (gen_mac_r (operands[2], operands[0], operands[1])); > + DONE; > + }) > + > +(define_insn "mac_r" > + [(set (match_operand:SI 0 "register_operand" "=r,r") > + (truncate:SI > + (plus:DI > + (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" > "%r,r")) > + (sign_extend:DI (match_operand:SI 2 "extend_operand" > "rI,i"))) > + (reg:DI ARCV2_ACC)))) > + (clobber (reg:DI ARCV2_ACC))] > + "TARGET_PLUS_DMPY" > + "mac %0,%1,%2" > + [(set_attr "length" "4,8") > + (set_attr "type" "multi") > + (set_attr "predicable" "no") > + (set_attr "cond" "nocond")]) > + > +(define_insn_and_split "umaddsidi4" > + [(set (match_operand:DI 0 "register_operand" "=r") > + (plus:DI > + (mult:DI > + (zero_extend:DI (match_operand:SI 1 "register_operand" "%r")) > + (zero_extend:DI (match_operand:SI 2 "extend_operand" "ri"))) > + (match_operand:DI 3 "register_operand" "r")))] > + "TARGET_PLUS_DMPY" > + "#" > + "TARGET_PLUS_DMPY && reload_completed" > + [(const_int 0)] > + "{ > + rtx acc_reg = gen_rtx_REG (DImode, ACC_REG_FIRST); > + emit_move_insn (acc_reg, operands[3]); > + if (TARGET_PLUS_MACD) > + emit_insn (gen_macdu (operands[0], operands[1], operands[2])); > + else > + { > + emit_insn (gen_macu (operands[1], operands[2])); > + emit_move_insn (operands[0], acc_reg); > + } > + DONE; > + }" > + [(set_attr "type" "multi") > + (set_attr "length" "36")]) > + > +(define_insn "macdu" > + [(set (match_operand:DI 0 "even_register_operand" "=Rcr,r,r") > + (plus:DI > + (mult:DI > + (zero_extend:DI (match_operand:SI 1 "register_operand" "%0,c,c")) > + (zero_extend:DI (match_operand:SI 2 "extend_operand" " c,cI,i"))) > + (reg:DI ARCV2_ACC))) > + (set (reg:DI ARCV2_ACC) > + (plus:DI > + (mult:DI (zero_extend:DI (match_dup 1)) > + (zero_extend:DI (match_dup 2))) > + (reg:DI ARCV2_ACC)))] > + "TARGET_PLUS_MACD" > + "macdu %0,%1,%2" > + [(set_attr "length" "4,4,8") > + (set_attr "type" "multi") > + (set_attr "predicable" "yes,no,no") > + (set_attr "cond" "canuse,nocond,nocond")]) > + > +(define_insn "macu" > + [(set (reg:DI ARCV2_ACC) > + (plus:DI > + (mult:DI (zero_extend:DI (match_operand:SI 0 "register_operand" > "%r,r")) > + (zero_extend:DI (match_operand:SI 1 "extend_operand" "rI,i"))) > + (reg:DI ARCV2_ACC)))] > + "TARGET_PLUS_DMPY" > + "macu 0,%0,%1" > + [(set_attr "length" "4,8") > + (set_attr "type" "multi") > + (set_attr "predicable" "no") > + (set_attr "cond" "nocond")]) > + > +(define_peephole2 > + [(set (reg:DI ARCV2_ACC) > + (plus:DI > + (mult:DI (zero_extend:DI (match_operand:SI 0 "register_operand" "")) > + (zero_extend:DI (match_operand:SI 1 "extend_operand" ""))) > + (reg:DI ARCV2_ACC))) > + (set (match_operand:SI 2 "register_operand" "") > + (match_operand:SI 3 "accl_operand" ""))] > + "TARGET_PLUS_DMPY" > + [(const_int 0)] > + { > + emit_insn (gen_macu_r (operands[2], operands[0], operands[1])); > + DONE; > + }) > + > +(define_insn "macu_r" > + [(set (match_operand:SI 0 "register_operand" "=r,r") > + (truncate:SI > + (plus:DI > + (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" > "%r,r")) > + (zero_extend:DI (match_operand:SI 2 "extend_operand" > "rI,i"))) > + (reg:DI ARCV2_ACC)))) > + (clobber (reg:DI ARCV2_ACC))] > + "TARGET_PLUS_DMPY" > + "macu %0,%1,%2" > + [(set_attr "length" "4,8") > + (set_attr "type" "multi") > + (set_attr "predicable" "no") > + (set_attr "cond" "nocond")]) > + > +(define_insn "mpyd_arcv2hs" > + [(set (match_operand:DI 0 "even_register_operand" "=Rcr, > r") > + (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" " 0, > c")) > + (sign_extend:DI (match_operand:SI 2 "register_operand" " c, > c")))) > + (set (reg:DI ARCV2_ACC) > + (mult:DI > + (sign_extend:DI (match_dup 1)) > + (sign_extend:DI (match_dup 2))))] > + "TARGET_PLUS_MACD" > + "mpyd%? %0,%1,%2" > + [(set_attr "length" "4,4") > + (set_attr "iscompact" "false") > + (set_attr "type" "multi") > + (set_attr "predicable" "yes,no") > + (set_attr "cond" "canuse,nocond")]) > + > +(define_insn "mpyd_imm_arcv2hs" > + [(set (match_operand:DI 0 "even_register_operand" "=Rcr, > r,r,Rcr, r") > + (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" " 0, > c,0, 0, c")) > + (match_operand 2 "immediate_operand" " L, > L,I,Cal,Cal"))) > + (set (reg:DI ARCV2_ACC) > + (mult:DI (sign_extend:DI (match_dup 1)) > + (match_dup 2)))] > + "TARGET_PLUS_MACD" > + "mpyd%? %0,%1,%2" > + [(set_attr "length" "4,4,4,8,8") > + (set_attr "iscompact" "false") > + (set_attr "type" "multi") > + (set_attr "predicable" "yes,no,no,yes,no") > + (set_attr "cond" "canuse,nocond,nocond,canuse_limm,nocond")]) > + > +(define_insn "mpydu_arcv2hs" > + [(set (match_operand:DI 0 "even_register_operand" "=Rcr, > r") > + (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" " 0, > c")) > + (zero_extend:DI (match_operand:SI 2 "register_operand" " c, > c")))) > + (set (reg:DI ARCV2_ACC) > + (mult:DI (zero_extend:DI (match_dup 1)) > + (zero_extend:DI (match_dup 2))))] > + "TARGET_PLUS_MACD" > + "mpydu%? %0,%1,%2" > + [(set_attr "length" "4,4") > + (set_attr "iscompact" "false") > + (set_attr "type" "multi") > + (set_attr "predicable" "yes,no") > + (set_attr "cond" "canuse,nocond")]) > + > +(define_insn "mpydu_imm_arcv2hs" > + [(set (match_operand:DI 0 "even_register_operand" "=Rcr, > r,r,Rcr, r") > + (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" " 0, > c,0, 0, c")) > + (match_operand 2 "immediate_operand" " L, > L,I,Cal,Cal"))) > + (set (reg:DI ARCV2_ACC) > + (mult:DI (zero_extend:DI (match_dup 1)) > + (match_dup 2)))] > + "TARGET_PLUS_MACD" > + "mpydu%? %0,%1,%2" > + [(set_attr "length" "4,4,4,8,8") > + (set_attr "iscompact" "false") > + (set_attr "type" "multi") > + (set_attr "predicable" "yes,no,no,yes,no") > + (set_attr "cond" "canuse,nocond,nocond,canuse_limm,nocond")]) > + > ;; include the arc-FPX instructions > (include "fpx.md") > > diff --git a/gcc/config/arc/predicates.md b/gcc/config/arc/predicates.md > index f4c2a80..7ddec91 100644 > --- a/gcc/config/arc/predicates.md > +++ b/gcc/config/arc/predicates.md > @@ -697,6 +697,11 @@ > (and (match_code "reg") > (match_test "REGNO (op) == (TARGET_BIG_ENDIAN ? 58 : 59)"))) > > +(define_predicate "accl_operand" > + (and (match_code "reg") > + (match_test "REGNO (op) == (TARGET_BIG_ENDIAN ? 59 : 58)") > + (match_test "TARGET_V2"))) > + > ; Unfortunately, we can not allow a const_int_operand before reload, because > ; reload needs a non-void mode to guide it how to reload the inside of a > ; {sign_}extend. > -- > 1.9.1 >