@@ -973,21 +973,35 @@
[(set_attr "type" "simd_fdiv")
(set_attr "mode" "<MODE>")])
-(define_insn "fma<mode>4"
+(define_expand "fma<mode>4"
[(set (match_operand:FMSA 0 "msa_reg_operand" "=f")
(fma:FMSA (match_operand:FMSA 1 "msa_reg_operand" "f")
(match_operand:FMSA 2 "msa_reg_operand" "f")
(match_operand:FMSA 3 "msa_reg_operand" "0")))]
- "ISA_HAS_MSA"
- "fmadd.<msafmt>\t%w0,%w1,%w2"
- [(set_attr "type" "simd_fmadd")
- (set_attr "mode" "<MODE>")])
+ "ISA_HAS_MSA && ISA_HAS_FUSED_MADDF")
-(define_insn "fnma<mode>4"
+(define_expand "fnma<mode>4"
[(set (match_operand:FMSA 0 "msa_reg_operand" "=f")
(fma:FMSA (neg:FMSA (match_operand:FMSA 1 "msa_reg_operand" "f"))
(match_operand:FMSA 2 "msa_reg_operand" "f")
(match_operand:FMSA 3 "msa_reg_operand" "0")))]
+ "ISA_HAS_MSA && ISA_HAS_FUSED_MADDF")
+
+(define_insn "msa_fmadd_<msafmt>"
+ [(set (match_operand:FMSA 0 "msa_reg_operand" "=f")
+ (fma:FMSA (match_operand:FMSA 1 "msa_reg_operand" "f")
+ (match_operand:FMSA 2 "msa_reg_operand" "f")
+ (match_operand:FMSA 3 "msa_reg_operand" "0")))]
+ "ISA_HAS_MSA"
+ "fmadd.<msafmt>\t%w0,%w1,%w2"
+ [(set_attr "type" "simd_fmadd")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "msa_fmsub_<msafmt>"
+ [(set (match_operand:FMSA 0 "msa_reg_operand" "=f")
+ (fma:FMSA (neg:FMSA (match_operand:FMSA 1 "msa_reg_operand" "f"))
+ (match_operand:FMSA 2 "msa_reg_operand" "f")
+ (match_operand:FMSA 3 "msa_reg_operand" "0")))]
"ISA_HAS_MSA"
"fmsub.<msafmt>\t%w0,%w1,%w2"
[(set_attr "type" "simd_fmadd")
@@ -17752,10 +17752,6 @@ AVAIL_NON_MIPS16 (msa, TARGET_MSA)
#define CODE_FOR_msa_ffint_u_d CODE_FOR_floatunsv2div2df2
#define CODE_FOR_msa_fsub_w CODE_FOR_subv4sf3
#define CODE_FOR_msa_fsub_d CODE_FOR_subv2df3
-#define CODE_FOR_msa_fmadd_w CODE_FOR_fmav4sf4
-#define CODE_FOR_msa_fmadd_d CODE_FOR_fmav2df4
-#define CODE_FOR_msa_fmsub_w CODE_FOR_fnmav4sf4
-#define CODE_FOR_msa_fmsub_d CODE_FOR_fnmav2df4
#define CODE_FOR_msa_fmul_w CODE_FOR_mulv4sf3
#define CODE_FOR_msa_fmul_d CODE_FOR_mulv2df3
#define CODE_FOR_msa_fdiv_w CODE_FOR_divv4sf3
new file mode 100644
@@ -0,0 +1,52 @@
+/* { dg-do run } */
+/* { dg-options "-mhard-float -mmsa" } */
+/* { dg-additional-options "-ffp-contract=fast" } */
+
+#define VSIZE 8
+
+typedef union
+{ double d; long long unsigned i; } double_ull_u;
+
+struct test_vec {
+ double_ull_u a;
+ double_ull_u b;
+ double_ull_u c;
+} test_bench[VSIZE] = {
+ {{.i=0x2c27173b4c9b0904ull}, {.i=0x6aa7b75c1df029d3ull}, {.i=0x5675ff363dd15094ull}},
+ {{.i=0x3a6f0e78379a5b56ull}, {.i=0x53b735d529784870ull}, {.i=0x4cdced4c10a30d9cull}},
+ {{.i=0x12d2eee56cc2b66aull}, {.i=0x60cd438558be66cdull}, {.i=0x335e9e8d425c189bull}},
+ {{.i=0x680d29830daea0c2ull}, {.i=0x4c5977b52c0d49efull}, {.i=0x7305e21c2165c647ull}},
+ {{.i=0x4e4add4115ecbebull}, {.i=0x401d6aed0c821feeull}, {.i=0x300832736663b62ull}},
+ {{.i=0x1f6f475265504cc9ull}, {.i=0x4e5785aa042408acull}, {.i=0x2ab32c6b25521f4aull}},
+ {{.i=0xd09c440443b602dull}, {.i=0x5f618fbb1fe650a2ull}, {.i=0x295aa9221841d645ull}},
+ {{.i=0x732612c95a91b01full}, {.i=0x268678105b8f78b5ull}, {.i=0x5973c32a350e1c23ull}},
+};
+
+int main (void)
+{
+ int i;
+ double __attribute__((aligned(16))) av [VSIZE];
+ double __attribute__((aligned(16))) bv[VSIZE];
+ double __attribute__((aligned(16))) cv[VSIZE];
+ double __attribute__((aligned(16))) res1[VSIZE];
+ double __attribute__((aligned(16))) res2[VSIZE - 1];
+
+ for (i = 0; i < VSIZE; i++)
+ {
+ av[i] = test_bench[i].a.d;
+ bv[i] = test_bench[i].b.d;
+ cv[i] = test_bench[i].c.d;
+ }
+
+ for (i = 0; i < VSIZE; i++)
+ res1[i] = av[i] * bv[i] + cv[i];
+
+ for (i = 0; i < VSIZE - 1; i++)
+ res2[i] = av[i] * bv[i] + cv[i];
+
+ for (i = 0; i < VSIZE - 1; i++)
+ if (res2[i] != res1[i])
+ return 1;
+
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,51 @@
+/* { dg-do run } */
+/* { dg-options "-mhard-float -mmsa" } */
+/* { dg-additional-options "-ffp-contract=fast" } */
+
+#define VSIZE 8
+
+typedef union { float f; unsigned long i; } float_ul_u;
+
+struct test_vec {
+ float_ul_u a;
+ float_ul_u b;
+ float_ul_u c;
+} test_bench[VSIZE] = {
+ {{.i=0x42963e5aul}, {.i=0xa0382c5ul}, {.i=0x8f2b15eul}},
+ {{.i=0x1c695decul}, {.i=0x3fcfaed9ul}, {.i=0xf856867ul}},
+ {{.i=0x116ae494ul}, {.i=0x3494b2fbul}, {.i=0xb13a31ul}},
+ {{.i=0x683caad3ul}, {.i=0x313c7c99ul}, {.i=0x519eb94cul}},
+ {{.i=0x4a9554feul}, {.i=0x392edbe4ul}, {.i=0x3d1a2dd9ul}},
+ {{.i=0x4c4fff5bul}, {.i=0x51b76675ul}, {.i=0x59a4ba71ul}},
+ {{.i=0x17cfc87dul}, {.i=0x5d66dc65ul}, {.i=0x30bb2b99ul}},
+ {{.i=0x61c66e3ul}, {.i=0x69321f16ul}, {.i=0x2d96b714ul}},
+};
+
+int main (void)
+{
+ int i;
+ float __attribute__((aligned(16))) av [VSIZE];
+ float __attribute__((aligned(16))) bv[VSIZE];
+ float __attribute__((aligned(16))) cv[VSIZE];
+ float __attribute__((aligned(16))) res1[VSIZE];
+ float __attribute__((aligned(16))) res2[VSIZE - 1];
+
+ for (i = 0; i < VSIZE; i++)
+ {
+ av[i] = test_bench[i].a.f;
+ bv[i] = test_bench[i].b.f;
+ cv[i] = test_bench[i].c.f;
+ }
+
+ for (i = 0; i < VSIZE; i++)
+ res1[i] = av[i] * bv[i] + cv[i];
+
+ for (i = 0; i < VSIZE - 1; i++)
+ res2[i] = av[i] * bv[i] + cv[i];
+
+ for (i = 0; i < VSIZE - 1; i++)
+ if (res2[i] != res1[i])
+ return 1;
+
+ return 0;
+}
@@ -362,8 +362,11 @@
/* { dg-final { scan-assembler-times "test37_v8u16:.*maddv.h.*test37_v8u16" 1 } } */
/* { dg-final { scan-assembler-times "test37_v4u32:.*maddv.w.*test37_v4u32" 1 } } */
/* { dg-final { scan-assembler-times "test37_v2u64:.*maddv.d.*test37_v2u64" 1 } } */
-/* { dg-final { scan-assembler-times "test37_v4f32:.*fmadd.w.*test37_v4f32" 1 } } */
-/* { dg-final { scan-assembler-times "test37_v2f64:.*fmadd.d.*test37_v2f64" 1 } } */
+/* Note: We chose not to emit fmadd.* on pre-r6 targets that lack scalar fma. */
+/* { dg-final { scan-assembler-times "test37_v4f32:.*fmadd.w.*test37_v4f32" 1 { target mipsisar6 } } } */
+/* { dg-final { scan-assembler-times "test37_v2f64:.*fmadd.d.*test37_v2f64" 1 { target mipsisar6 } } } */
+/* { dg-final { scan-assembler-times "test37_v4f32:.*fmul.w.*fadd.w.*test37_v4f32" 1 { target {! mipsisar6 } } } } */
+/* { dg-final { scan-assembler-times "test37_v2f64:.*fmul.d.*fadd.d.*test37_v2f64" 1 { target {! mipsisar6 } } } } */
/* { dg-final { scan-assembler-times "test38_v16i8:.*msubv.b.*test38_v16i8" 1 } } */
/* { dg-final { scan-assembler-times "test38_v8i16:.*msubv.h.*test38_v8i16" 1 } } */
/* { dg-final { scan-assembler-times "test38_v4i32:.*msubv.w.*test38_v4i32" 1 } } */
@@ -372,8 +375,11 @@
/* { dg-final { scan-assembler-times "test38_v8u16:.*msubv.h.*test38_v8u16" 1 } } */
/* { dg-final { scan-assembler-times "test38_v4u32:.*msubv.w.*test38_v4u32" 1 } } */
/* { dg-final { scan-assembler-times "test38_v2u64:.*msubv.d.*test38_v2u64" 1 } } */
-/* { dg-final { scan-assembler-times "test38_v4f32:.*fmsub.w.*test38_v4f32" 1 } } */
-/* { dg-final { scan-assembler-times "test38_v2f64:.*fmsub.d.*test38_v2f64" 1 } } */
+/* Note: We chose not to emit fmsub.* on pre-r6 targets that lack scalar fma. */
+/* { dg-final { scan-assembler-times "test38_v4f32:.*fmsub.w.*test38_v4f32" 1 { target mipsisar6 } } } */
+/* { dg-final { scan-assembler-times "test38_v2f64:.*fmsub.d.*test38_v2f64" 1 { target mipsisar6 } } } */
+/* { dg-final { scan-assembler-times "test38_v4f32:.*fmul.w.*fsub.w.*test38_v4f32" 1 { target {! mipsisar6 } } } } */
+/* { dg-final { scan-assembler-times "test38_v2f64:.*fmul.d.*fsub.d.*test38_v2f64" 1 { target {! mipsisar6 } } } } */
/* { dg-final { scan-assembler-times "test39_v16i8:.*ld.b.*test39_v16i8" 1 } } */
/* { dg-final { scan-assembler-times "test39_v8i16:.*ld.h.*test39_v8i16" 1 } } */
/* { dg-final { scan-assembler-times "test39_v4i32:.*ld.w.*test39_v4i32" 1 } } */
@@ -1514,6 +1514,16 @@ proc check_effective_target_mips64 { } {
}]
}
+# Return true if the target is a MIPS rev 6 target.
+
+proc check_effective_target_mipsisar6 { } {
+ return [check_no_compiler_messages mipsisar6 assembly {
+ #if __mips_isa_rev < 6
+ #error !__mips_isa_rev
+ #endif
+ }]
+}
+
# Return true if the target is using a compressed MIPS ISA.
proc check_effective_target_mips_compressed { } {