aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorLulu Cheng <chenglulu@loongson.cn>2023-09-05 11:09:03 +0800
committerLulu Cheng <chenglulu@loongson.cn>2023-09-09 15:06:20 +0800
commitf83d6fc222040febf510af81eeeb87670a2fc4d8 (patch)
treeda4d0f875d13afe81dc4efd7c5dc0c32965d1bd3 /gcc
parentc0bb7a6f39e58717d34c9459586c0b1d5db16d89 (diff)
downloadgcc-f83d6fc222040febf510af81eeeb87670a2fc4d8.zip
gcc-f83d6fc222040febf510af81eeeb87670a2fc4d8.tar.gz
gcc-f83d6fc222040febf510af81eeeb87670a2fc4d8.tar.bz2
LoongArch: Optimized multiply instruction generation.
1. Can generate mulh.w[u] instruction. 2. Can generate mulw.d.wu instruction. gcc/ChangeLog: * config/loongarch/loongarch.md (mulsidi3_64bit): Field unsigned extension support. (<u>muldi3_highpart): Modify template name. (<u>mulsi3_highpart): Likewise. (<u>mulsidi3_64bit): Field unsigned extension support. (<su>muldi3_highpart): Modify muldi3_highpart to smuldi3_highpart. (<su>mulsi3_highpart): Modify mulsi3_highpart to smulsi3_highpart. gcc/testsuite/ChangeLog: * gcc.target/loongarch/mulw_d_wu.c: New test. * gcc.target/loongarch/smuldi3_highpart.c: New test. * gcc.target/loongarch/smulsi3_highpart.c: New test. * gcc.target/loongarch/umulsi3_highpart.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/loongarch/loongarch.md66
-rw-r--r--gcc/testsuite/gcc.target/loongarch/mulw_d_wu.c9
-rw-r--r--gcc/testsuite/gcc.target/loongarch/smuldi3_highpart.c13
-rw-r--r--gcc/testsuite/gcc.target/loongarch/smulsi3_highpart.c15
-rw-r--r--gcc/testsuite/gcc.target/loongarch/umulsi3_highpart.c14
5 files changed, 94 insertions, 23 deletions
diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md
index 75f641b..1dc6b52 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -750,15 +750,6 @@
[(set_attr "type" "imul")
(set_attr "mode" "<MODE>")])
-(define_insn "mulsidi3_64bit"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
- (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
- "TARGET_64BIT"
- "mulw.d.w\t%0,%1,%2"
- [(set_attr "type" "imul")
- (set_attr "mode" "DI")])
-
(define_insn "*mulsi3_extended"
[(set (match_operand:DI 0 "register_operand" "=r")
(sign_extend:DI
@@ -787,14 +778,14 @@
emit_insn (gen_muldi3 (low, operands[1], operands[2]));
rtx high = gen_reg_rtx (DImode);
- emit_insn (gen_<u>muldi3_highpart (high, operands[1], operands[2]));
+ emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
emit_move_insn (gen_lowpart (DImode, operands[0]), low);
emit_move_insn (gen_highpart (DImode, operands[0]), high);
DONE;
})
-(define_insn "<u>muldi3_highpart"
+(define_insn "<su>muldi3_highpart"
[(set (match_operand:DI 0 "register_operand" "=r")
(truncate:DI
(lshiftrt:TI
@@ -809,22 +800,34 @@
(set_attr "mode" "DI")])
(define_expand "<u>mulsidi3"
- [(set (match_operand:DI 0 "register_operand" "=r")
+ [(set (match_operand:DI 0 "register_operand")
(mult:DI (any_extend:DI
- (match_operand:SI 1 "register_operand" " r"))
+ (match_operand:SI 1 "register_operand"))
(any_extend:DI
- (match_operand:SI 2 "register_operand" " r"))))]
- "!TARGET_64BIT"
+ (match_operand:SI 2 "register_operand"))))]
+ ""
{
- rtx temp = gen_reg_rtx (SImode);
- emit_insn (gen_mulsi3 (temp, operands[1], operands[2]));
- emit_insn (gen_<u>mulsi3_highpart (loongarch_subword (operands[0], true),
- operands[1], operands[2]));
- emit_insn (gen_movsi (loongarch_subword (operands[0], false), temp));
- DONE;
+ if (!TARGET_64BIT)
+ {
+ rtx temp = gen_reg_rtx (SImode);
+ emit_insn (gen_mulsi3 (temp, operands[1], operands[2]));
+ emit_insn (gen_<su>mulsi3_highpart (loongarch_subword (operands[0], true),
+ operands[1], operands[2]));
+ emit_insn (gen_movsi (loongarch_subword (operands[0], false), temp));
+ DONE;
+ }
})
-(define_insn "<u>mulsi3_highpart"
+(define_insn "<u>mulsidi3_64bit"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "r"))
+ (any_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
+ "TARGET_64BIT"
+ "mulw.d.w<u>\t%0,%1,%2"
+ [(set_attr "type" "imul")
+ (set_attr "mode" "DI")])
+
+(define_insn "<su>mulsi3_highpart"
[(set (match_operand:SI 0 "register_operand" "=r")
(truncate:SI
(lshiftrt:DI
@@ -833,11 +836,28 @@
(any_extend:DI
(match_operand:SI 2 "register_operand" " r")))
(const_int 32))))]
- "!TARGET_64BIT"
+ ""
"mulh.w<u>\t%0,%1,%2"
[(set_attr "type" "imul")
(set_attr "mode" "SI")])
+;; Under the LoongArch architecture, the mulh.w[u] instruction performs
+;; sign extension by default, so the sign extension instruction can be
+;; eliminated.
+(define_peephole
+ [(set (match_operand:SI 0 "register_operand")
+ (truncate:SI
+ (lshiftrt:DI
+ (mult:DI (any_extend:DI
+ (match_operand:SI 1 "register_operand"))
+ (any_extend:DI
+ (match_operand:SI 2 "register_operand")))
+ (const_int 32))))
+ (set (match_operand:DI 3 "register_operand")
+ (sign_extend:DI (match_dup 0)))]
+ "TARGET_64BIT && REGNO (operands[0]) == REGNO (operands[3])"
+ "mulh.w<u>\t%0,%1,%2")
+
;;
;; ....................
;;
diff --git a/gcc/testsuite/gcc.target/loongarch/mulw_d_wu.c b/gcc/testsuite/gcc.target/loongarch/mulw_d_wu.c
new file mode 100644
index 0000000..16163d6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/mulw_d_wu.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mabi=lp64d" } */
+/* { dg-final { scan-assembler "mulw.d.wu" } } */
+
+__attribute__((noipa, noinline)) unsigned long
+f(unsigned long a, unsigned long b)
+{
+ return (unsigned long)(unsigned int)a * (unsigned long)(unsigned int)b;
+}
diff --git a/gcc/testsuite/gcc.target/loongarch/smuldi3_highpart.c b/gcc/testsuite/gcc.target/loongarch/smuldi3_highpart.c
new file mode 100644
index 0000000..6f5c686
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/smuldi3_highpart.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O2 -fdump-rtl-expand-all" } */
+
+typedef int TI __attribute ((mode(TI)));
+typedef int DI __attribute__((mode(DI)));
+
+DI
+test (DI x, DI y)
+{
+ return ((TI)x * y) >> 64;
+}
+
+/* { dg-final { scan-rtl-dump "highparttmp" "expand" } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/smulsi3_highpart.c b/gcc/testsuite/gcc.target/loongarch/smulsi3_highpart.c
new file mode 100644
index 0000000..c4dbf8af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/smulsi3_highpart.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-rtl-expand-all" } */
+
+typedef unsigned int DI __attribute__((mode(DI)));
+typedef unsigned int SI __attribute__((mode(SI)));
+
+SI
+f (SI x, SI y)
+{
+ return ((DI) x * y) >> 32;
+}
+
+/* { dg-final { scan-rtl-dump "highparttmp" "expand" } } */
+/* { dg-final { scan-assembler "mulh\\.w" } } */
+/* { dg-final { scan-assembler-not "slli\\.w" } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/umulsi3_highpart.c b/gcc/testsuite/gcc.target/loongarch/umulsi3_highpart.c
new file mode 100644
index 0000000..e208803
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/umulsi3_highpart.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+typedef unsigned int DI __attribute__((mode(DI)));
+typedef unsigned int SI __attribute__((mode(SI)));
+
+SI
+f (SI x, SI y)
+{
+ return ((DI) x * y) >> 32;
+}
+
+/* { dg-final { scan-assembler "mulh\\.wu" } } */
+/* { dg-final { scan-assembler-not "slli\\.w" } } */