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

Reply via email to