aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorClaudiu Zissulescu <claziss@gmail.com>2020-07-28 13:15:48 +0300
committerClaudiu Zissulescu <claziss@synopsys.com>2020-12-11 18:13:53 +0200
commitf7ad4446274831234e5acd3506fd2e01c7594c6a (patch)
tree0c119c203adee9865e604e7b763e9bff5380f6a5 /gcc
parent078c7498908d9b74caff34d12099b5c85470e277 (diff)
downloadgcc-f7ad4446274831234e5acd3506fd2e01c7594c6a.zip
gcc-f7ad4446274831234e5acd3506fd2e01c7594c6a.tar.gz
gcc-f7ad4446274831234e5acd3506fd2e01c7594c6a.tar.bz2
arc: Use separate predicated patterns for mpyd(u)
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. gcc/ 2020-12-11 Claudiu Zissulescu <claziss@synopsys.com> * 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. gcc/testsuite/ 2020-12-11 Claudiu Zissulescu <claziss@synopsys.com> * gcc.target/arc/pmpyd.c: New test. * gcc.target/arc/tmac-1.c: Update. Signed-off-by: Claudiu Zissulescu <claziss@gmail.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/arc/arc.md101
-rw-r--r--gcc/testsuite/gcc.target/arc/pmpyd.c15
-rw-r--r--gcc/testsuite/gcc.target/arc/tmac-1.c2
3 files changed, 67 insertions, 51 deletions
diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index 266b7ce..2b46e26 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -871,6 +871,8 @@ core_3, archs4x, archs4xd, archs4xd_slow"
(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" "")
@@ -6385,66 +6387,65 @@ core_3, archs4x, archs4xd, archs4xd_slow"
(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 0000000..0eb0ff7
--- /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 3fcabf5..5b302ca 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" } } */