]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
LoongArch: Optimized multiply instruction generation.
authorLulu Cheng <chenglulu@loongson.cn>
Tue, 5 Sep 2023 03:09:03 +0000 (11:09 +0800)
committerLulu Cheng <chenglulu@loongson.cn>
Sat, 9 Sep 2023 07:06:20 +0000 (15:06 +0800)
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.

gcc/config/loongarch/loongarch.md
gcc/testsuite/gcc.target/loongarch/mulw_d_wu.c [new file with mode: 0644]
gcc/testsuite/gcc.target/loongarch/smuldi3_highpart.c [new file with mode: 0644]
gcc/testsuite/gcc.target/loongarch/smulsi3_highpart.c [new file with mode: 0644]
gcc/testsuite/gcc.target/loongarch/umulsi3_highpart.c [new file with mode: 0644]

index 75f641b38ee7c741e2fdd17de67848ad185532e4..1dc6b5244167069f63c04bce1786414c85a2b164 100644 (file)
   [(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
   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
    (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
                     (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 (file)
index 0000000..16163d6
--- /dev/null
@@ -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 (file)
index 0000000..6f5c686
--- /dev/null
@@ -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 (file)
index 0000000..c4dbf8a
--- /dev/null
@@ -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 (file)
index 0000000..e208803
--- /dev/null
@@ -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" } } */