]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
MIPS: Add Allegrex support for madd/msub instructions.
authorDavid Guillen Fandos <david@davidgf.net>
Fri, 19 Sep 2025 16:48:11 +0000 (18:48 +0200)
committerYunQiang Su <yunqiang@isrc.iscas.ac.cn>
Tue, 2 Dec 2025 01:26:53 +0000 (09:26 +0800)
Tweaking mul_acc_si/mul_sub_si was necessary to fix the implicit
assumption that CPUs with madd/msub support also support MUL3
multiplication. This disables the non-existent alternative if the CPU
does not have proper MUL3 support. This issue exists also for other CPUs
(ie. using -march=mips1 with -mimadd fails).

gcc/ChangeLog:

* config/mips/mips.h (ISA_HAS_MADD_MSUB): Include allegrex.
* config/mips/mips.md: Tweak mul_acc_si/mul_sub_si to make it
work when MUL3 is not available.

gcc/testsuite/ChangeLog:

* gcc.target/mips/madd-10.c: New test.
* gcc.target/mips/maddu-5.c: New test.
* gcc.target/mips/msub-9.c: New test.
* gcc.target/mips/msubu-5.c: New test.

Signed-off-by: David Guillen Fandos <david@davidgf.net>
gcc/config/mips/mips.h
gcc/config/mips/mips.md
gcc/testsuite/gcc.target/mips/madd-10.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/maddu-5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/msub-9.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/msubu-5.c [new file with mode: 0644]

index 7d1fc6552d6fa244a5a02f0a0a63a891f7b97eec..4d65bbf447098428b93cbb40e5d4f4242110e325 100644 (file)
@@ -1149,8 +1149,9 @@ struct mips_cpu_info {
                                 && !TARGET_MIPS16)
 
 /* ISA has integer multiply-accumulate instructions, madd and msub.  */
-#define ISA_HAS_MADD_MSUB      (mips_isa_rev >= 1                      \
-                                && mips_isa_rev <= 5)
+#define ISA_HAS_MADD_MSUB      ((mips_isa_rev >= 1                     \
+                                && mips_isa_rev <= 5)                  \
+                                || TARGET_ALLEGREX)
 
 /* Integer multiply-accumulate instructions should be generated.  */
 #define GENERATE_MADD_MSUB     (TARGET_IMADD && !TARGET_MIPS16)
index 939e51719297befc1beca09909a6c15b6ceff64a..5117dfd5d442bb86a8ca1fc9c0ecca3032bc7568 100644 (file)
    (set_attr "mode"    "SI")
    (set_attr "insn_count" "1,1,2")
    (set (attr "enabled")
-        (cond [(eq_attr "alternative" "1,2")
-                  (const_string "yes")]
-              (const_string "no")))])
+       (cond [(eq_attr "alternative" "1")
+              (const_string "yes")
+              (and (eq_attr "alternative" "2")
+                   (match_test "ISA_HAS_MUL3"))
+              (const_string "yes")]
+           (const_string "no")))])
 
 ;; The same idea applies here.  The middle alternative needs one less
 ;; clobber than the final alternative, so we add "*?" as a counterweight.
    (set_attr "mode"     "SI")
    (set_attr "insn_count" "1,1,2")
    (set (attr "enabled")
-        (cond [(eq_attr "alternative" "1,2")
-                  (const_string "yes")]
-              (const_string "no")))])
+        (cond [(eq_attr "alternative" "1")
+               (const_string "yes")
+               (and (eq_attr "alternative" "2")
+                    (match_test "ISA_HAS_MUL3"))
+               (const_string "yes")]
+           (const_string "no")))])
 
 ;; Split *mul_sub_si if both the source and destination accumulator
 ;; values are GPRs.
diff --git a/gcc/testsuite/gcc.target/mips/madd-10.c b/gcc/testsuite/gcc.target/mips/madd-10.c
new file mode 100644 (file)
index 0000000..514b8d9
--- /dev/null
@@ -0,0 +1,15 @@
+/* { dg-options "-march=allegrex -fexpensive-optimizations" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+/* { dg-final { scan-assembler-not "\tmul\t" } } */
+/* { dg-final { scan-assembler "\tmadd\t" } } */
+
+NOMIPS16 int
+f1 (int *a, int *b, int n)
+{
+  int x, i;
+
+  x = 0;
+  for (i = 0; i < n; i++)
+    x += a[i] * b[i];
+  return x;
+}
diff --git a/gcc/testsuite/gcc.target/mips/maddu-5.c b/gcc/testsuite/gcc.target/mips/maddu-5.c
new file mode 100644 (file)
index 0000000..c316b2f
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-options "-march=allegrex -fexpensive-optimizations" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+/* { dg-final { scan-assembler-not "\tmul\t" } } */
+/* { dg-final { scan-assembler "\tmaddu\t" } } */
+
+typedef unsigned int ui;
+typedef unsigned long long ull;
+
+NOMIPS16 ull
+f1 (ui x, ui y, ull z)
+{
+  return (ull) x * y + z;
+}
+
+NOMIPS16 ull
+f2 (ui x, ui y, ull z)
+{
+  return z + (ull) y * x;
+}
+
diff --git a/gcc/testsuite/gcc.target/mips/msub-9.c b/gcc/testsuite/gcc.target/mips/msub-9.c
new file mode 100644 (file)
index 0000000..c6b94cb
--- /dev/null
@@ -0,0 +1,15 @@
+/* { dg-options "-march=allegrex -fexpensive-optimizations" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+/* { dg-final { scan-assembler-not "\tmul\t" } } */
+/* { dg-final { scan-assembler "\tmsub\t" } } */
+
+NOMIPS16 int
+f1 (int *a, int *b, int n)
+{
+  int x, i;
+
+  x = 100;
+  for (i = 0; i < n; i++)
+    x -= a[i] * b[i];
+  return x;
+}
diff --git a/gcc/testsuite/gcc.target/mips/msubu-5.c b/gcc/testsuite/gcc.target/mips/msubu-5.c
new file mode 100644 (file)
index 0000000..ba3a8e7
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-options "-march=allegrex -fexpensive-optimizations" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+/* { dg-final { scan-assembler-not "\tmul\t" } } */
+/* { dg-final { scan-assembler "\tmsubu\t" } } */
+
+typedef unsigned int ui;
+typedef unsigned long long ull;
+
+NOMIPS16 ull
+f2 (ui x, ui y, ull z)
+{
+  return z - (ull) y * x;
+}
+