From: Claudiu Zissulescu Date: Tue, 28 Jul 2020 10:15:48 +0000 (+0300) Subject: arc: Use separate predicated patterns for mpyd(u) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f7ad4446274831234e5acd3506fd2e01c7594c6a;p=gcc.git 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 * config/arc/arc.md (mpyd_arcv2hs): New template pattern. (*pmpyd_arcv2hs): Likewise. (*pmpyd_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 * gcc.target/arc/pmpyd.c: New test. * gcc.target/arc/tmac-1.c: Update. Signed-off-by: Claudiu Zissulescu --- diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md index 266b7ce7666..2b46e265538 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 "*xt_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_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%?\\t%0,%1,%2" + [(set_attr "length" "4") + (set_attr "iscompact" "false") + (set_attr "type" "multi") + (set_attr "predicable" "no")]) + +(define_insn "*pmpyd_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%?\\t%0,%1,%2" + [(set_attr "length" "4") + (set_attr "iscompact" "false") + (set_attr "type" "multi") + (set_attr "predicable" "yes")]) + +(define_insn "mpyd_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%?\\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_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%?\\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 00000000000..0eb0ff7f11b --- /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 3fcabf5fff2..5b302cad4a4 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" } } */