From 79557baea826fb4493037e6ebbbb65ca0d359d9c Mon Sep 17 00:00:00 2001 From: Claudiu Zissulescu Date: Tue, 9 May 2017 16:19:47 +0200 Subject: [PATCH] [ARC] Add support for advanced mpy/mac instructions. gcc/ 2017-05-09 Claudiu Zissulescu * 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. From-SVN: r247797 --- ChangeLog | 16 ++ gcc/config/arc/arc.c | 5 +- gcc/config/arc/arc.md | 266 +++++++++++++++++++++++++- gcc/config/arc/predicates.md | 5 + gcc/testsuite/ChangeLog | 6 + gcc/testsuite/gcc.target/arc/tmac-1.c | 12 ++ gcc/testsuite/gcc.target/arc/tmac-2.c | 11 ++ gcc/testsuite/gcc.target/arc/tmac.h | 24 +++ 8 files changed, 341 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.target/arc/tmac-1.c create mode 100644 gcc/testsuite/gcc.target/arc/tmac-2.c create mode 100644 gcc/testsuite/gcc.target/arc/tmac.h diff --git a/ChangeLog b/ChangeLog index d8eb87e7b17..d8982068a01 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2017-05-09 Claudiu Zissulescu + + * 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. + 2017-05-09 Claudiu Zissulescu Andrew Burgess diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c index 46ad31e52e0..91c28e73554 100644 --- a/gcc/config/arc/arc.c +++ b/gcc/config/arc/arc.c @@ -1786,8 +1786,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 5c3766c4604..edb983f1b2d 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)] @@ -6248,6 +6272,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 f4c2a80f2be..7ddec9149d1 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. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 36d4d1dd958..1ec70b920d3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2017-05-09 Claudiu Zissulescu + + * gcc.target/arc/tmac-1.c: New file. + * gcc.target/arc/tmac-2.c: Likewise. + * gcc.target/arc/tmac.h: Likewise. + 2017-05-09 Claudiu Zissulescu Andrew Burgess diff --git a/gcc/testsuite/gcc.target/arc/tmac-1.c b/gcc/testsuite/gcc.target/arc/tmac-1.c new file mode 100644 index 00000000000..e59df5f6b59 --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/tmac-1.c @@ -0,0 +1,12 @@ +/* { dg-skip-if "" { ! { clmcpu } } } */ +/* { dg-do compile } */ +/* { dg-options "-O2 -mcpu=archs -mmpy-option=8" } */ + +/* Test MAC operation for MPY_OPTION = 8. */ +#include "tmac.h" + +/* { dg-final { scan-assembler "macd " } } */ +/* { dg-final { scan-assembler "macdu" } } */ +/* { dg-final { scan-assembler "mpyd " } } */ +/* { dg-final { scan-assembler "mpydu" } } */ + diff --git a/gcc/testsuite/gcc.target/arc/tmac-2.c b/gcc/testsuite/gcc.target/arc/tmac-2.c new file mode 100644 index 00000000000..f0136bac3e6 --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/tmac-2.c @@ -0,0 +1,11 @@ +/* { dg-skip-if "" { ! { clmcpu } } } */ +/* { dg-do compile } */ +/* { dg-options "-O2 -mcpu=archs -mmpy-option=7" } */ + +/* Test MAC operation for MPY_OPTION = 7. */ +#include "tmac.h" + +/* { dg-final { scan-assembler "mac " } } */ +/* { dg-final { scan-assembler "macu" } } */ +/* { dg-final { scan-assembler "mpym " } } */ +/* { dg-final { scan-assembler "mpymu" } } */ diff --git a/gcc/testsuite/gcc.target/arc/tmac.h b/gcc/testsuite/gcc.target/arc/tmac.h new file mode 100644 index 00000000000..86471e83796 --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/tmac.h @@ -0,0 +1,24 @@ +/* Test MAC operations. */ + +long long foo (long long a, int b, int c) +{ + a += (long long )c * (long long )b; + return a; +} + +long long foo1 (int b, int c) +{ + return (long long)c * (long long) b; +} + +long long foo3 (long long a, unsigned int b, unsigned int c) +{ + a += (unsigned long long )c * (unsigned long long )b; + return a; +} + +long long foo4 (unsigned int b, unsigned int c) +{ + return (unsigned long long)c * (unsigned long long) b; +} + -- 2.30.2