From: Claudiu Zissulescu <claz...@gmail.com>

The compiler can match mpyd.eq r0,r1,r0 as a predicated instruction,
which is incorrect. The mpyd(u) instruction takes as input two 32-bit
registers, returning into a double 64-bit even-odd register pair.  For
the predicated case, the ARC instruction decoder expects the
destination register to be the same as the first input register. In
the big-endian case the result is swaped in the destination register
pair, however, the instruction encoding remains the same.  Refurbish
the mpyd(u) patterns to take into account the above observation.

Permission to apply this patch to master, gcc10 and gcc9 branches.

Cheers,
Claudiu

xxxx-xx-xx  Claudiu Zissulescu  <claz...@synopsys.com>

        * testsuite/gcc.target/arc/pmpyd.c: New test.
        * testsuite/gcc.target/arc/tmac-1.c: Update.
        * config/arc/arc.md (mpyd<su_optab>_arcv2hs): New template
        pattern.
        (*pmpyd<su_optab>_arcv2hs): Likewise.
        (*pmpyd<su_optab>_imm_arcv2hs): Likewise.
        (mpyd_arcv2hs): Moved into above template.
        (mpyd_imm_arcv2hs): Moved into above template.
        (mpydu_arcv2hs): Likewise.
        (mpydu_imm_arcv2hs): Likewise.
        (su_optab): New optab prefix for sign/zero-extending operations.

Signed-off-by: Claudiu Zissulescu <claz...@gmail.com>
---
 gcc/config/arc/arc.md                 | 101 +++++++++++++-------------
 gcc/testsuite/gcc.target/arc/pmpyd.c  |  15 ++++
 gcc/testsuite/gcc.target/arc/tmac-1.c |   2 +-
 3 files changed, 67 insertions(+), 51 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/arc/pmpyd.c

diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index 1720e8cd2f6f..d4d9f59a3eac 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -894,6 +894,8 @@ archs4x, archs4xd"
 
 (define_code_iterator SEZ [sign_extend zero_extend])
 (define_code_attr SEZ_prefix [(sign_extend "sex") (zero_extend "ext")])
+; Optab prefix for sign/zero-extending operations
+(define_code_attr su_optab [(sign_extend "") (zero_extend "u")])
 
 (define_insn "*<SEZ_prefix>xt<SQH_postfix>_cmp0_noout"
   [(set (match_operand 0 "cc_set_register" "")
@@ -6436,66 +6438,65 @@ archs4x, archs4xd"
    (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"))))
+(define_insn "mpyd<su_optab>_arcv2hs"
+  [(set (match_operand:DI 0 "even_register_operand"           "=r")
+       (mult:DI (SEZ:DI (match_operand:SI 1 "register_operand" "r"))
+                (SEZ:DI (match_operand:SI 2 "register_operand" "r"))))
    (set (reg:DI ARCV2_ACC)
        (mult:DI
-         (sign_extend:DI (match_dup 1))
-         (sign_extend:DI (match_dup 2))))]
+         (SEZ:DI (match_dup 1))
+         (SEZ: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")))
+  "mpyd<su_optab>%?\\t%0,%1,%2"
+  [(set_attr "length" "4")
+   (set_attr "iscompact" "false")
+   (set_attr "type" "multi")
+   (set_attr "predicable" "no")])
+
+(define_insn "*pmpyd<su_optab>_arcv2hs"
+  [(set (match_operand:DI 0 "even_register_operand"         "=r")
+       (mult:DI
+        (SEZ:DI (match_operand:SI 1 "even_register_operand" "%0"))
+        (SEZ:DI (match_operand:SI 2 "register_operand"      "r"))))
    (set (reg:DI ARCV2_ACC)
-       (mult:DI (sign_extend:DI (match_dup 1))
-                (match_dup 2)))]
+       (mult:DI
+         (SEZ:DI (match_dup 1))
+         (SEZ:DI (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"))))
+  "mpyd<su_optab>%?\\t%0,%1,%2"
+  [(set_attr "length" "4")
+   (set_attr "iscompact" "false")
+   (set_attr "type" "multi")
+   (set_attr "predicable" "yes")])
+
+(define_insn "mpyd<su_optab>_imm_arcv2hs"
+  [(set (match_operand:DI 0 "even_register_operand"            "=r,r,  r")
+       (mult:DI (SEZ:DI (match_operand:SI 1 "register_operand"  "r,0,  r"))
+                (match_operand 2            "immediate_operand" "L,I,Cal")))
    (set (reg:DI ARCV2_ACC)
-       (mult:DI (zero_extend:DI (match_dup 1))
-                (zero_extend:DI (match_dup 2))))]
+       (mult:DI (SEZ:DI (match_dup 1))
+                (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")))
+  "mpyd<su_optab>%?\\t%0,%1,%2"
+  [(set_attr "length" "4,4,8")
+   (set_attr "iscompact" "false")
+   (set_attr "type" "multi")
+   (set_attr "predicable" "no")])
+
+(define_insn "*pmpyd<su_optab>_imm_arcv2hs"
+  [(set (match_operand:DI 0 "even_register_operand"        "=r,r")
+       (mult:DI
+        (SEZ:DI (match_operand:SI 1 "even_register_operand" "0,0"))
+        (match_operand 2            "immediate_operand"     "L,Cal")))
    (set (reg:DI ARCV2_ACC)
-       (mult:DI (zero_extend:DI (match_dup 1))
+       (mult:DI (SEZ: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")])
+  "mpyd<su_optab>%?\\t%0,%1,%2"
+  [(set_attr "length" "4,8")
+   (set_attr "iscompact" "false")
+   (set_attr "type" "multi")
+   (set_attr "predicable" "yes")])
 
 (define_insn "*add_shift"
   [(set (match_operand:SI 0 "register_operand" "=q,r,r")
diff --git a/gcc/testsuite/gcc.target/arc/pmpyd.c 
b/gcc/testsuite/gcc.target/arc/pmpyd.c
new file mode 100644
index 000000000000..0eb0ff7f11b6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/pmpyd.c
@@ -0,0 +1,15 @@
+/* { dg-do assemble } */
+/* { dg-skip-if "" { ! { clmcpu } } } */
+/* { dg-options "-mcpu=hs38 -Os -EB" } */
+
+/* This example is found during big-endian build.  The compiler is
+   matching mpydu.hi r12,r13,r3 as a predicated instruction, which is
+   incorrect.  The error is due to different predicates between the
+   output operand and the first operand of the instruction.  */
+unsigned int test(unsigned int x, unsigned long long y)
+{
+  y /= 0x20000000;
+  if (x > 1)
+    y *= x;
+  return y;
+}
diff --git a/gcc/testsuite/gcc.target/arc/tmac-1.c 
b/gcc/testsuite/gcc.target/arc/tmac-1.c
index 3fcabf5fff2d..5b302cad4a4a 100644
--- a/gcc/testsuite/gcc.target/arc/tmac-1.c
+++ b/gcc/testsuite/gcc.target/arc/tmac-1.c
@@ -7,5 +7,5 @@
 
 /* { dg-final { scan-assembler "macd " } } */
 /* { dg-final { scan-assembler "macdu" } } */
-/* { dg-final { scan-assembler "mpyd " } } */
+/* { dg-final { scan-assembler "mpyd\\t" } } */
 /* { dg-final { scan-assembler "mpydu" } } */
-- 
2.26.2

  • [PATCH] arc: Use separate pr... Claudiu Zissulescu via Gcc-patches

Reply via email to