[ARC] Add support for advanced mpy/mac instructions.
gcc/ 2017-05-09 Claudiu Zissulescu <claziss@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. From-SVN: r247797
This commit is contained in:
parent
c7314bc17b
commit
79557baea8
8 changed files with 341 additions and 4 deletions
16
ChangeLog
16
ChangeLog
|
@ -1,3 +1,19 @@
|
|||
2017-05-09 Claudiu Zissulescu <claziss@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.
|
||||
|
||||
2017-05-09 Claudiu Zissulescu <claziss@synopsys.com>
|
||||
Andrew Burgess <andrew.burgess@embecosm.com>
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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,3 +1,9 @@
|
|||
2017-05-09 Claudiu Zissulescu <claziss@synopsys.com>
|
||||
|
||||
* 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 <claziss@synopsys.com>
|
||||
Andrew Burgess <andrew.burgess@embecosm.com>
|
||||
|
||||
|
|
12
gcc/testsuite/gcc.target/arc/tmac-1.c
Normal file
12
gcc/testsuite/gcc.target/arc/tmac-1.c
Normal file
|
@ -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" } } */
|
||||
|
11
gcc/testsuite/gcc.target/arc/tmac-2.c
Normal file
11
gcc/testsuite/gcc.target/arc/tmac-2.c
Normal file
|
@ -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" } } */
|
24
gcc/testsuite/gcc.target/arc/tmac.h
Normal file
24
gcc/testsuite/gcc.target/arc/tmac.h
Normal file
|
@ -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;
|
||||
}
|
||||
|
Loading…
Add table
Reference in a new issue