From: David Guillen Fandos Date: Fri, 19 Sep 2025 16:48:11 +0000 (+0200) Subject: MIPS: Add Allegrex support for madd/msub instructions. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=93754d984b500c5914c3d1a437b6561e031aa604;p=thirdparty%2Fgcc.git MIPS: Add Allegrex support for madd/msub instructions. 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 --- diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 7d1fc6552d6..4d65bbf4470 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -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) diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 939e5171929..5117dfd5d44 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -1795,9 +1795,12 @@ (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. @@ -2041,9 +2044,12 @@ (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 index 00000000000..514b8d97f2f --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/madd-10.c @@ -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 index 00000000000..c316b2f0860 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/maddu-5.c @@ -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 index 00000000000..c6b94cb512d --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/msub-9.c @@ -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 index 00000000000..ba3a8e77a75 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/msubu-5.c @@ -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; +} +