diff mbox series

[1/4,ARC] Update mlo/mhi handling when big-endian CPU.

Message ID 20200203113832.20270-1-claziss@gmail.com
State New
Headers show
Series [1/4,ARC] Update mlo/mhi handling when big-endian CPU. | expand

Commit Message

Claudiu Zissulescu Ianculescu Feb. 3, 2020, 11:38 a.m. UTC
The ARC 600 MUL64 instructions are using mlo/mhi registers to pass the
64-bit result. However, the mlo/mhi registers are not swapping
depending on endianess.  Update multiplication patterns to reflect
this fact.

gcc/
xxxx-xx-xx  Claudiu Zissulescu  <claziss@synopsys.com>

	* config/arc/arc.md (mulsidi_600): Correctly select mlo/mhi
	registers.
	(umulsidi_600): Likewise.

testsuite/
xxxx-xx-xx  Claudiu Zissulescu  <claziss@synopsys.com>
	Petro Karashchenko  <petro.karashchenko@ring.com>

	* estsuite/gcc.target/arc/mul64-1.c: New test.
---
 gcc/config/arc/arc.md                  | 50 ++++++++++++++++----------
 gcc/testsuite/gcc.target/arc/mul64-1.c | 23 ++++++++++++
 2 files changed, 55 insertions(+), 18 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/arc/mul64-1.c

Comments

Jeff Law Feb. 3, 2020, 4:34 p.m. UTC | #1
On Mon, 2020-02-03 at 12:38 +0100, Claudiu Zissulescu wrote:
> The ARC 600 MUL64 instructions are using mlo/mhi registers to pass the
> 64-bit result. However, the mlo/mhi registers are not swapping
> depending on endianess.  Update multiplication patterns to reflect
> this fact.
> 
> gcc/
> xxxx-xx-xx  Claudiu Zissulescu  <claziss@synopsys.com>
> 
> 	* config/arc/arc.md (mulsidi_600): Correctly select mlo/mhi
> 	registers.
> 	(umulsidi_600): Likewise.
> 
> testsuite/
> xxxx-xx-xx  Claudiu Zissulescu  <claziss@synopsys.com>
> 	Petro Karashchenko  <petro.karashchenko@ring.com>
> 
> 	* estsuite/gcc.target/arc/mul64-1.c: New test.
OK
jeff
>
diff mbox series

Patch

diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index 9a96440025f..f19f2c32641 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -2288,19 +2288,26 @@  archs4x, archs4xd"
    (set_attr "cond" "canuse,canuse,canuse_limm,canuse")])
 
 (define_insn_and_split "mulsidi_600"
-  [(set (match_operand:DI 0 "register_operand"                               "=c, c,c,  c")
-	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand"  "%Rcq#q, c,c,  c"))
-		 (sign_extend:DI (match_operand:SI 2 "nonmemory_operand"  "Rcq#q,cL,L,C32"))))
-   (clobber (reg:DI MUL64_OUT_REG))]
+  [(set (match_operand:DI 0 "register_operand"                           "=r,r,  r")
+	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand"  "%r,r,  r"))
+		 (sign_extend:DI (match_operand:SI 2 "nonmemory_operand" "rL,L,C32"))))
+   (clobber (reg:DI R58_REG))]
   "TARGET_MUL64_SET"
   "#"
-  "TARGET_MUL64_SET"
+  "TARGET_MUL64_SET && reload_completed"
   [(const_int 0)]
-  "emit_insn (gen_mul64 (operands[1], operands[2]));
-   emit_move_insn (operands[0], gen_rtx_REG (DImode, MUL64_OUT_REG));
-   DONE;"
+ {
+   int hi = !TARGET_BIG_ENDIAN;
+   int lo = !hi;
+   rtx lr = operand_subword (operands[0], lo, 0, DImode);
+   rtx hr = operand_subword (operands[0], hi, 0, DImode);
+   emit_insn (gen_mul64 (operands[1], operands[2]));
+   emit_move_insn (lr, gen_rtx_REG (SImode, R58_REG));
+   emit_move_insn (hr, gen_rtx_REG (SImode, R59_REG));
+   DONE;
+ }
   [(set_attr "type" "multi")
-   (set_attr "length" "8")])
+   (set_attr "length" "4,4,8")])
 
 (define_insn "mul64"
   [(set (reg:DI MUL64_OUT_REG)
@@ -2316,19 +2323,26 @@  archs4x, archs4xd"
    (set_attr "cond" "canuse,canuse,canuse_limm,canuse")])
 
 (define_insn_and_split "umulsidi_600"
-  [(set (match_operand:DI 0 "register_operand"                            "=c,c, c")
-	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand"   "%c,c, c"))
-		 (sign_extend:DI (match_operand:SI 2 "nonmemory_operand"  "cL,L,C32"))))
-   (clobber (reg:DI MUL64_OUT_REG))]
+  [(set (match_operand:DI 0 "register_operand"                            "=r,r, r")
+	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand"   "%r,r, r"))
+		 (zero_extend:DI (match_operand:SI 2 "nonmemory_operand"  "rL,L,C32"))))
+   (clobber (reg:DI R58_REG))]
   "TARGET_MUL64_SET"
   "#"
-  "TARGET_MUL64_SET"
+  "TARGET_MUL64_SET && reload_completed"
   [(const_int 0)]
-  "emit_insn (gen_mulu64 (operands[1], operands[2]));
-   emit_move_insn (operands[0], gen_rtx_REG (DImode, MUL64_OUT_REG));
-   DONE;"
+ {
+   int hi = !TARGET_BIG_ENDIAN;
+   int lo = !hi;
+   rtx lr = operand_subword (operands[0], lo, 0, DImode);
+   rtx hr = operand_subword (operands[0], hi, 0, DImode);
+   emit_insn (gen_mulu64 (operands[1], operands[2]));
+   emit_move_insn (lr, gen_rtx_REG (SImode, R58_REG));
+   emit_move_insn (hr, gen_rtx_REG (SImode, R59_REG));
+   DONE;
+ }
   [(set_attr "type" "umulti")
-   (set_attr "length" "8")])
+   (set_attr "length" "4,4,8")])
 
 (define_insn "mulu64"
   [(set (reg:DI MUL64_OUT_REG)
diff --git a/gcc/testsuite/gcc.target/arc/mul64-1.c b/gcc/testsuite/gcc.target/arc/mul64-1.c
new file mode 100644
index 00000000000..2543fc33d3f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mul64-1.c
@@ -0,0 +1,23 @@ 
+/* { dg-do compile } */
+/* { dg-skip-if "MUL64 is ARC600 extension." { ! { clmcpu } } } */
+/* { dg-options "-O2 -mmul64 -mbig-endian -mcpu=arc600" } */
+
+/* Check if mlo/mhi registers are correctly layout when we compile for
+   a big-endian CPU.  */
+
+#include <stdint.h>
+
+uint32_t foo (uint32_t x)
+{
+  return x % 1000;
+}
+
+int32_t bar (int32_t x)
+{
+  return x % 1000;
+}
+
+/* { dg-final { scan-assembler-times "\\s+mul64\\s+" 3 } } */
+/* { dg-final { scan-assembler-times "\\s+mulu64\\s+" 1 } } */
+/* { dg-final { scan-assembler-times "r\[0-9\]+,mhi" 2 } } */
+/* { dg-final { scan-assembler-times "r\[0-9\]+,mlo" 2 } } */