[ARC] Add support for advanced mpy/mac instructions.
authorClaudiu Zissulescu <claziss@synopsys.com>
Tue, 9 May 2017 14:19:47 +0000 (16:19 +0200)
committerClaudiu Zissulescu <claziss@gcc.gnu.org>
Tue, 9 May 2017 14:19:47 +0000 (16:19 +0200)
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

ChangeLog
gcc/config/arc/arc.c
gcc/config/arc/arc.md
gcc/config/arc/predicates.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/arc/tmac-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arc/tmac-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arc/tmac.h [new file with mode: 0644]

index d8eb87e7b1795db8af02b4bc4b0b32190d17d51c..d8982068a0194c2ed6c23fc1e20a0301b63c1cfa 100644 (file)
--- a/ChangeLog
+++ b/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>
 
index 46ad31e52e07de62f160e9ddc0d6bb0e5fd645f7..91c28e7355412b211c9141aa6d67d2e25ee79760 100644 (file)
@@ -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;
index 5c3766c4604679bb26b35c8b731f6f81899913b0..edb983f1b2d021981b4acc404e1606e8063e4d12 100644 (file)
   "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]);
   [(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)]
                 (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]);
   [(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)]
   ""
   [(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")
 
index f4c2a80f2be84080ad7ccc1bffee097c53a3cb78..7ddec9149d1340d3b70d89fe9e686c27dfd8e7c4 100644 (file)
   (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.
index 36d4d1dd9585f63a7ee465ceae6f8f9934be62b5..1ec70b920d33f9ae9d2be81ba652fdab30d95c89 100644 (file)
@@ -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>
 
diff --git a/gcc/testsuite/gcc.target/arc/tmac-1.c b/gcc/testsuite/gcc.target/arc/tmac-1.c
new file mode 100644 (file)
index 0000000..e59df5f
--- /dev/null
@@ -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 (file)
index 0000000..f0136ba
--- /dev/null
@@ -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 (file)
index 0000000..86471e8
--- /dev/null
@@ -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;
+}
+