aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorBilyan Borisov <bilyan.borisov@arm.com>2016-11-01 12:48:32 +0000
committerTamar Christina <tnfchris@gcc.gnu.org>2016-11-01 12:48:32 +0000
commit9fc158eb3496423579aebbed057819e7d142fb96 (patch)
tree8bcd370eddd2043a62fe4723fc771352bffbad2c /gcc
parentea4249cb24da2315a58105bc37004f14de12f349 (diff)
downloadgcc-9fc158eb3496423579aebbed057819e7d142fb96.zip
gcc-9fc158eb3496423579aebbed057819e7d142fb96.tar.gz
gcc-9fc158eb3496423579aebbed057819e7d142fb96.tar.bz2
arm-c.c (arm_cpu_builtins): New macro definition.
gcc/ 2016-09-30 Bilyan Borisov <bilyan.borisov@arm.com> Tamar Christina <tamar.christina@arm.com> * config/arm/arm-c.c (arm_cpu_builtins): New macro definition. * config/arm/arm_neon.h (vmaxnm_f32): New intrinsinc. (vmaxnmq_f32): Likewise. (vminnm_f32): Likewise. (vminnmq_f32): Likewise. * config/arm/arm_neon_builtins.def (vmaxnm): New builtin. (vminnm): Likewise. * config/arm/neon.md (neon_<fmaxmin_op><mode>, VCVTF): New expander. gcc/testsuite/ 2016-09-30 Bilyan Borisov <bilyan.borisov@arm.com> * gcc.target/arm/simd/vmaxnm_f32_1.c: New. * gcc.target/arm/simd/vmaxnmq_f32_1.c: Likewise. * gcc.target/arm/simd/vminnm_f32_1.c: Likewise. * gcc.target/arm/simd/vminnmq_f32_1.c: Likewise. Co-Authored-By: Tamar Christina <tamar.christina@arm.com> From-SVN: r241736
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/config/arm/arm-c.c3
-rw-r--r--gcc/config/arm/arm_neon.h28
-rw-r--r--gcc/config/arm/arm_neon_builtins.def4
-rw-r--r--gcc/config/arm/neon.md11
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vmaxnm_f32_1.c159
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vmaxnmq_f32_1.c160
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vminnm_f32_1.c159
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vminnmq_f32_1.c159
10 files changed, 701 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7dd239d..8c6331e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+2016-11-01 Bilyan Borisov <bilyan.borisov@arm.com>
+ Tamar Christina <tamar.christina@arm.com>
+
+ * config/arm/arm-c.c (arm_cpu_builtins): New macro definition.
+ * config/arm/arm_neon.h (vmaxnm_f32): New intrinsinc.
+ (vmaxnmq_f32): Likewise.
+ (vminnm_f32): Likewise.
+ (vminnmq_f32): Likewise.
+ * config/arm/arm_neon_builtins.def (vmaxnm): New builtin.
+ (vminnm): Likewise.
+ * config/arm/neon.md (neon_<fmaxmin_op><mode>, VCVTF): New
+ expander.
+
2016-10-31 Michael Meissner <meissner@linux.vnet.ibm.com>
* config/rs6000/vsx.md (VSX_EXTRACT_FL): New iterator for all
diff --git a/gcc/config/arm/arm-c.c b/gcc/config/arm/arm-c.c
index df930f4..74417a6 100644
--- a/gcc/config/arm/arm-c.c
+++ b/gcc/config/arm/arm-c.c
@@ -87,6 +87,9 @@ arm_cpu_builtins (struct cpp_reader* pfile)
((TARGET_ARM_ARCH >= 5 && !TARGET_THUMB)
|| TARGET_ARM_ARCH_ISA_THUMB >=2));
+ def_or_undef_macro (pfile, "__ARM_FEATURE_NUMERIC_MAXMIN",
+ TARGET_ARM_ARCH >= 8 && TARGET_NEON && TARGET_FPU_ARMV8);
+
def_or_undef_macro (pfile, "__ARM_FEATURE_SIMD32", TARGET_INT_SIMD);
builtin_define_with_int_value ("__ARM_SIZEOF_MINIMAL_ENUM",
diff --git a/gcc/config/arm/arm_neon.h b/gcc/config/arm/arm_neon.h
index 54bbc7d..3898ff7 100644
--- a/gcc/config/arm/arm_neon.h
+++ b/gcc/config/arm/arm_neon.h
@@ -2956,6 +2956,34 @@ vmaxq_f32 (float32x4_t __a, float32x4_t __b)
return (float32x4_t)__builtin_neon_vmaxfv4sf (__a, __b);
}
+#pragma GCC push_options
+#pragma GCC target ("fpu=neon-fp-armv8")
+__extension__ static __inline float32x2_t __attribute__ ((__always_inline__))
+vmaxnm_f32 (float32x2_t a, float32x2_t b)
+{
+ return (float32x2_t)__builtin_neon_vmaxnmv2sf (a, b);
+}
+
+__extension__ static __inline float32x4_t __attribute__ ((__always_inline__))
+vmaxnmq_f32 (float32x4_t a, float32x4_t b)
+{
+ return (float32x4_t)__builtin_neon_vmaxnmv4sf (a, b);
+}
+
+__extension__ static __inline float32x2_t __attribute__ ((__always_inline__))
+vminnm_f32 (float32x2_t a, float32x2_t b)
+{
+ return (float32x2_t)__builtin_neon_vminnmv2sf (a, b);
+}
+
+__extension__ static __inline float32x4_t __attribute__ ((__always_inline__))
+vminnmq_f32 (float32x4_t a, float32x4_t b)
+{
+ return (float32x4_t)__builtin_neon_vminnmv4sf (a, b);
+}
+#pragma GCC pop_options
+
+
__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
vmaxq_u8 (uint8x16_t __a, uint8x16_t __b)
{
diff --git a/gcc/config/arm/arm_neon_builtins.def b/gcc/config/arm/arm_neon_builtins.def
index b29aa91..58b1020 100644
--- a/gcc/config/arm/arm_neon_builtins.def
+++ b/gcc/config/arm/arm_neon_builtins.def
@@ -147,12 +147,12 @@ VAR6 (BINOP, vmaxs, v8qi, v4hi, v2si, v16qi, v8hi, v4si)
VAR6 (BINOP, vmaxu, v8qi, v4hi, v2si, v16qi, v8hi, v4si)
VAR2 (BINOP, vmaxf, v2sf, v4sf)
VAR2 (BINOP, vmaxf, v8hf, v4hf)
-VAR2 (BINOP, vmaxnm, v4hf, v8hf)
+VAR4 (BINOP, vmaxnm, v2sf, v4sf, v4hf, v8hf)
VAR6 (BINOP, vmins, v8qi, v4hi, v2si, v16qi, v8hi, v4si)
VAR6 (BINOP, vminu, v8qi, v4hi, v2si, v16qi, v8hi, v4si)
VAR2 (BINOP, vminf, v2sf, v4sf)
VAR2 (BINOP, vminf, v4hf, v8hf)
-VAR2 (BINOP, vminnm, v8hf, v4hf)
+VAR4 (BINOP, vminnm, v2sf, v4sf, v8hf, v4hf)
VAR3 (BINOP, vpmaxs, v8qi, v4hi, v2si)
VAR3 (BINOP, vpmaxu, v8qi, v4hi, v2si)
diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md
index 59316de..4297511 100644
--- a/gcc/config/arm/neon.md
+++ b/gcc/config/arm/neon.md
@@ -2845,6 +2845,17 @@
[(set_attr "type" "neon_fp_minmax_s<q>")]
)
+;; v<maxmin>nm intrinsics.
+(define_insn "neon_<fmaxmin_op><mode>"
+ [(set (match_operand:VCVTF 0 "s_register_operand" "=w")
+ (unspec:VCVTF [(match_operand:VCVTF 1 "s_register_operand" "w")
+ (match_operand:VCVTF 2 "s_register_operand" "w")]
+ VMAXMINFNM))]
+ "TARGET_NEON && TARGET_FPU_ARMV8"
+ "<fmaxmin_op>.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
+ [(set_attr "type" "neon_fp_minmax_s<q>")]
+)
+
;; Vector forms for the IEEE-754 fmax()/fmin() functions
(define_insn "<fmaxmin><mode>3"
[(set (match_operand:VCVTF 0 "s_register_operand" "=w")
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index e57678e..3d49662 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2016-11-01 Bilyan Borisov <bilyan.borisov@arm.com>
+
+ * gcc.target/arm/simd/vmaxnm_f32_1.c: New.
+ * gcc.target/arm/simd/vmaxnmq_f32_1.c: Likewise.
+ * gcc.target/arm/simd/vminnm_f32_1.c: Likewise.
+ * gcc.target/arm/simd/vminnmq_f32_1.c: Likewise.
+
2016-11-01 Uros Bizjak <ubizjak@gmail.com>
* lib/target-supports.exp: Normalize order of i?86 and x86_64 targets.
diff --git a/gcc/testsuite/gcc.target/arm/simd/vmaxnm_f32_1.c b/gcc/testsuite/gcc.target/arm/simd/vmaxnm_f32_1.c
new file mode 100644
index 0000000..c3a9f36
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vmaxnm_f32_1.c
@@ -0,0 +1,159 @@
+/* Test the `vmaxnmf32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_v8_neon_ok } */
+/* { dg-options "-save-temps -O3 -march=armv8-a" } */
+/* { dg-add-options arm_v8_neon } */
+
+#include "arm_neon.h"
+
+extern void abort ();
+
+void __attribute__ ((noinline))
+test_vmaxnm_f32__regular_input1 ()
+{
+ float32_t a1[] = {1,2};
+ float32_t b1[] = {3,4};
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vmaxnm_f32 (a, b);
+ float32_t actual[2];
+ vst1_f32 (actual, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (actual[i] != b1[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vmaxnm_f32__regular_input2 ()
+{
+ float32_t a1[] = {3,2};
+ float32_t b1[] = {1,4};
+ float32_t e[] = {3,4};
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vmaxnm_f32 (a, b);
+ float32_t actual[2];
+ vst1_f32 (actual, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (actual[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vmaxnm_f32__quiet_NaN_one_arg ()
+{
+ /* When given a quiet NaN, vmaxnm returns the other operand.
+ In this test case we have NaNs in only one operand. */
+ float32_t n = __builtin_nanf ("");
+ float32_t a1[] = {1,2};
+ float32_t b1[] = {n,n};
+ float32_t e[] = {1,2};
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vmaxnm_f32 (a, b);
+ float32_t actual[2];
+ vst1_f32 (actual, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (actual[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vmaxnm_f32__quiet_NaN_both_args ()
+{
+ /* When given a quiet NaN, vmaxnm returns the other operand.
+ In this test case we have NaNs in both operands. */
+ float32_t n = __builtin_nanf ("");
+ float32_t a1[] = {n,2};
+ float32_t b1[] = {1,n};
+ float32_t e[] = {1,2};
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vmaxnm_f32 (a, b);
+ float32_t actual[2];
+ vst1_f32 (actual, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (actual[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vmaxnm_f32__zero_both_args ()
+{
+ /* For 0 and -0, vmaxnm returns 0. Since 0 == -0, check sign bit. */
+ float32_t a1[] = {0.0, 0.0};
+ float32_t b1[] = {-0.0, -0.0};
+ float32_t e[] = {0.0, 0.0};
+
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vmaxnm_f32 (a, b);
+
+ float32_t actual1[2];
+ vst1_f32 (actual1, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (actual1[i] != e[i] || __builtin_signbit (actual1[i]) != 0)
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vmaxnm_f32__inf_both_args ()
+{
+ /* The max of inf and inf is inf. The max of -inf and -inf is -inf. */
+ float32_t inf = __builtin_huge_valf ();
+ float32_t a1[] = {inf, -inf};
+ float32_t b1[] = {inf, -inf};
+ float32_t e[] = {inf, -inf};
+
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vmaxnm_f32 (a, b);
+
+ float32_t actual1[2];
+ vst1_f32 (actual1, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (actual1[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vmaxnm_f32__two_quiet_NaNs_both_args ()
+{
+ /* When given 2 NaNs, return a NaN. Since a NaN is not equal to anything,
+ not even another NaN, use __builtin_isnan () to check. */
+ float32_t n = __builtin_nanf ("");
+ float32_t a1[] = {n,n};
+ float32_t b1[] = {n,n};
+ float32_t e[] = {n,n};
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vmaxnm_f32 (a, b);
+ float32_t actual[2];
+ vst1_f32 (actual, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (!__builtin_isnan (actual[i]))
+ abort ();
+}
+
+int
+main ()
+{
+ test_vmaxnm_f32__regular_input1 ();
+ test_vmaxnm_f32__regular_input2 ();
+ test_vmaxnm_f32__quiet_NaN_one_arg ();
+ test_vmaxnm_f32__quiet_NaN_both_args ();
+ test_vmaxnm_f32__zero_both_args ();
+ test_vmaxnm_f32__inf_both_args ();
+ test_vmaxnm_f32__two_quiet_NaNs_both_args ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "vmaxnm\.f32\t\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+\n" 7 } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vmaxnmq_f32_1.c b/gcc/testsuite/gcc.target/arm/simd/vmaxnmq_f32_1.c
new file mode 100644
index 0000000..80c4e9a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vmaxnmq_f32_1.c
@@ -0,0 +1,160 @@
+/* Test the `vmaxnmqf32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_v8_neon_ok } */
+/* { dg-options "-save-temps -O3 -march=armv8-a" } */
+/* { dg-add-options arm_v8_neon } */
+
+#include "arm_neon.h"
+
+extern void abort ();
+
+void __attribute__ ((noinline))
+test_vmaxnmq_f32__regular_input1 ()
+{
+ float32_t a1[] = {1,2,5,6};
+ float32_t b1[] = {3,4,7,8};
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vmaxnmq_f32 (a, b);
+ float32_t actual[4];
+ vst1q_f32 (actual, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (actual[i] != b1[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vmaxnmq_f32__regular_input2 ()
+{
+ float32_t a1[] = {3,2,7,6};
+ float32_t b1[] = {1,4,5,8};
+ float32_t e[] = {3,4,7,8};
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vmaxnmq_f32 (a, b);
+ float32_t actual[4];
+ vst1q_f32 (actual, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (actual[i] != e[i])
+ abort ();
+}
+
+
+void __attribute__ ((noinline))
+test_vmaxnmq_f32__quiet_NaN_one_arg ()
+{
+ /* When given a quiet NaN, vmaxnmq returns the other operand.
+ In this test case we have NaNs in only one operand. */
+ float32_t n = __builtin_nanf ("");
+ float32_t a1[] = {1,2,3,4};
+ float32_t b1[] = {n,n,n,n};
+ float32_t e[] = {1,2,3,4};
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vmaxnmq_f32 (a, b);
+ float32_t actual[4];
+ vst1q_f32 (actual, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (actual[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vmaxnmq_f32__quiet_NaN_both_args ()
+{
+ /* When given a quiet NaN, vmaxnmq returns the other operand.
+ In this test case we have NaNs in both operands. */
+ float32_t n = __builtin_nanf ("");
+ float32_t a1[] = {n,2,n,4};
+ float32_t b1[] = {1,n,3,n};
+ float32_t e[] = {1,2,3,4};
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vmaxnmq_f32 (a, b);
+ float32_t actual[4];
+ vst1q_f32 (actual, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (actual[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vmaxnmq_f32__zero_both_args ()
+{
+ /* For 0 and -0, vmaxnmq returns 0. Since 0 == -0, check sign bit. */
+ float32_t a1[] = {0.0, 0.0, -0.0, -0.0};
+ float32_t b1[] = {-0.0, -0.0, 0.0, 0.0};
+ float32_t e[] = {0.0, 0.0, 0.0, 0.0};
+
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vmaxnmq_f32 (a, b);
+
+ float32_t actual1[4];
+ vst1q_f32 (actual1, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (actual1[i] != e[i] || __builtin_signbit (actual1[i]) != 0)
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vmaxnmq_f32__inf_both_args ()
+{
+ /* The max of inf and inf is inf. The max of -inf and -inf is -inf. */
+ float32_t inf = __builtin_huge_valf ();
+ float32_t a1[] = {inf, -inf, inf, inf};
+ float32_t b1[] = {inf, -inf, -inf, -inf};
+ float32_t e[] = {inf, -inf, inf, inf};
+
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vmaxnmq_f32 (a, b);
+
+ float32_t actual1[4];
+ vst1q_f32 (actual1, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (actual1[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vmaxnmq_f32__two_quiet_NaNs_both_args ()
+{
+ /* When given 2 NaNs, return a NaN. Since a NaN is not equal to anything,
+ not even another NaN, use __builtin_isnan () to check. */
+ float32_t n = __builtin_nanf ("");
+ float32_t a1[] = {n,n,n,n};
+ float32_t b1[] = {n,n,n,n};
+ float32_t e[] = {n,n};
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vmaxnmq_f32 (a, b);
+ float32_t actual[4];
+ vst1q_f32 (actual, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (!__builtin_isnan (actual[i]))
+ abort ();
+}
+
+int
+main ()
+{
+ test_vmaxnmq_f32__regular_input1 ();
+ test_vmaxnmq_f32__regular_input2 ();
+ test_vmaxnmq_f32__quiet_NaN_one_arg ();
+ test_vmaxnmq_f32__quiet_NaN_both_args ();
+ test_vmaxnmq_f32__zero_both_args ();
+ test_vmaxnmq_f32__inf_both_args ();
+ test_vmaxnmq_f32__two_quiet_NaNs_both_args ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "vmaxnm\.f32\t\[qQ\]\[0-9\]+, ?\[qQ\]\[0-9\]+, ?\[qQ\]\[0-9\]+\n" 7 } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vminnm_f32_1.c b/gcc/testsuite/gcc.target/arm/simd/vminnm_f32_1.c
new file mode 100644
index 0000000..9a1d097
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vminnm_f32_1.c
@@ -0,0 +1,159 @@
+/* Test the `vminnmf32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_v8_neon_ok } */
+/* { dg-options "-save-temps -O3 -march=armv8-a" } */
+/* { dg-add-options arm_v8_neon } */
+
+#include "arm_neon.h"
+
+extern void abort ();
+
+void __attribute__ ((noinline))
+test_vminnm_f32__regular_input1 ()
+{
+ float32_t a1[] = {1,2};
+ float32_t b1[] = {3,4};
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vminnm_f32 (a, b);
+ float32_t actual[2];
+ vst1_f32 (actual, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (actual[i] != a1[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vminnm_f32__regular_input2 ()
+{
+ float32_t a1[] = {3,2};
+ float32_t b1[] = {1,4};
+ float32_t e[] = {1,2};
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vminnm_f32 (a, b);
+ float32_t actual[2];
+ vst1_f32 (actual, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (actual[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vminnm_f32__quiet_NaN_one_arg ()
+{
+ /* When given a quiet NaN, vminnm returns the other operand.
+ In this test case we have NaNs in only one operand. */
+ float32_t n = __builtin_nanf ("");
+ float32_t a1[] = {1,2};
+ float32_t b1[] = {n,n};
+ float32_t e[] = {1,2};
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vminnm_f32 (a, b);
+ float32_t actual[2];
+ vst1_f32 (actual, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (actual[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vminnm_f32__quiet_NaN_both_args ()
+{
+ /* When given a quiet NaN, vminnm returns the other operand.
+ In this test case we have NaNs in both operands. */
+ float32_t n = __builtin_nanf ("");
+ float32_t a1[] = {n,2};
+ float32_t b1[] = {1,n};
+ float32_t e[] = {1,2};
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vminnm_f32 (a, b);
+ float32_t actual[2];
+ vst1_f32 (actual, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (actual[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vminnm_f32__zero_both_args ()
+{
+ /* For 0 and -0, vminnm returns -0. Since 0 == -0, check sign bit. */
+ float32_t a1[] = {0.0,0.0};
+ float32_t b1[] = {-0.0, -0.0};
+ float32_t e[] = {-0.0, -0.0};
+
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vminnm_f32 (a, b);
+
+ float32_t actual1[2];
+ vst1_f32 (actual1, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (actual1[i] != e[i] || __builtin_signbit (actual1[i]) == 0)
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vminnm_f32__inf_both_args ()
+{
+ /* The min of inf and inf is inf. The min of -inf and -inf is -inf. */
+ float32_t inf = __builtin_huge_valf ();
+ float32_t a1[] = {inf, -inf};
+ float32_t b1[] = {inf, -inf};
+ float32_t e[] = {inf, -inf};
+
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vminnm_f32 (a, b);
+
+ float32_t actual1[2];
+ vst1_f32 (actual1, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (actual1[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vminnm_f32__two_quiet_NaNs_both_args ()
+{
+ /* When given 2 NaNs, return a NaN. Since a NaN is not equal to anything,
+ not even another NaN, use __builtin_isnan () to check. */
+ float32_t n = __builtin_nanf ("");
+ float32_t a1[] = {n,n};
+ float32_t b1[] = {n,n};
+ float32_t e[] = {n,n};
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vminnm_f32 (a, b);
+ float32_t actual[2];
+ vst1_f32 (actual, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (!__builtin_isnan (actual[i]))
+ abort ();
+}
+
+int
+main ()
+{
+ test_vminnm_f32__regular_input1 ();
+ test_vminnm_f32__regular_input2 ();
+ test_vminnm_f32__quiet_NaN_one_arg ();
+ test_vminnm_f32__quiet_NaN_both_args ();
+ test_vminnm_f32__zero_both_args ();
+ test_vminnm_f32__inf_both_args ();
+ test_vminnm_f32__two_quiet_NaNs_both_args ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "vminnm\.f32\t\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+\n" 7 } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vminnmq_f32_1.c b/gcc/testsuite/gcc.target/arm/simd/vminnmq_f32_1.c
new file mode 100644
index 0000000..a778abe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vminnmq_f32_1.c
@@ -0,0 +1,159 @@
+/* Test the `vminnmqf32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_v8_neon_ok } */
+/* { dg-options "-save-temps -O3 -march=armv8-a" } */
+/* { dg-add-options arm_v8_neon } */
+
+#include "arm_neon.h"
+
+extern void abort ();
+
+void __attribute__ ((noinline))
+test_vminnmq_f32__regular_input1 ()
+{
+ float32_t a1[] = {1,2,5,6};
+ float32_t b1[] = {3,4,7,8};
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vminnmq_f32 (a, b);
+ float32_t actual[4];
+ vst1q_f32 (actual, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (actual[i] != a1[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vminnmq_f32__regular_input2 ()
+{
+ float32_t a1[] = {3,2,7,6};
+ float32_t b1[] = {1,4,5,8};
+ float32_t e[] = {1,2,5,6};
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vminnmq_f32 (a, b);
+ float32_t actual[4];
+ vst1q_f32 (actual, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (actual[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vminnmq_f32__quiet_NaN_one_arg ()
+{
+ /* When given a quiet NaN, vminnmq returns the other operand.
+ In this test case we have NaNs in only one operand. */
+ float32_t n = __builtin_nanf ("");
+ float32_t a1[] = {1,2,3,4};
+ float32_t b1[] = {n,n,n,n};
+ float32_t e[] = {1,2,3,4};
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vminnmq_f32 (a, b);
+ float32_t actual[4];
+ vst1q_f32 (actual, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (actual[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vminnmq_f32__quiet_NaN_both_args ()
+{
+ /* When given a quiet NaN, vminnmq returns the other operand.
+ In this test case we have NaNs in both operands. */
+ float32_t n = __builtin_nanf ("");
+ float32_t a1[] = {n,2,n,4};
+ float32_t b1[] = {1,n,3,n};
+ float32_t e[] = {1,2,3,4};
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vminnmq_f32 (a, b);
+ float32_t actual[4];
+ vst1q_f32 (actual, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (actual[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vminnmq_f32__zero_both_args ()
+{
+ /* For 0 and -0, vminnmq returns -0. Since 0 == -0, check sign bit. */
+ float32_t a1[] = {0.0, 0.0, -0.0, -0.0};
+ float32_t b1[] = {-0.0, -0.0, 0.0, 0.0};
+ float32_t e[] = {-0.0, -0.0, -0.0, -0.0};
+
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vminnmq_f32 (a, b);
+
+ float32_t actual1[4];
+ vst1q_f32 (actual1, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (actual1[i] != e[i] || __builtin_signbit (actual1[i]) == 0)
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vminnmq_f32__inf_both_args ()
+{
+ /* The min of inf and inf is inf. The min of -inf and -inf is -inf. */
+ float32_t inf = __builtin_huge_valf ();
+ float32_t a1[] = {inf, -inf, inf, inf};
+ float32_t b1[] = {inf, -inf, -inf, -inf};
+ float32_t e[] = {inf, -inf, -inf, -inf};
+
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vminnmq_f32 (a, b);
+
+ float32_t actual1[4];
+ vst1q_f32 (actual1, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (actual1[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vminnmq_f32__two_quiet_NaNs_both_args ()
+{
+ /* When given 2 NaNs, return a NaN. Since a NaN is not equal to anything,
+ not even another NaN, use __builtin_isnan () to check. */
+ float32_t n = __builtin_nanf ("");
+ float32_t a1[] = {n,n,n,n};
+ float32_t b1[] = {n,n,n,n};
+ float32_t e[] = {n,n};
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vminnmq_f32 (a, b);
+ float32_t actual[4];
+ vst1q_f32 (actual, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (!__builtin_isnan (actual[i]))
+ abort ();
+}
+
+int
+main ()
+{
+ test_vminnmq_f32__regular_input1 ();
+ test_vminnmq_f32__regular_input2 ();
+ test_vminnmq_f32__quiet_NaN_one_arg ();
+ test_vminnmq_f32__quiet_NaN_both_args ();
+ test_vminnmq_f32__zero_both_args ();
+ test_vminnmq_f32__inf_both_args ();
+ test_vminnmq_f32__two_quiet_NaNs_both_args ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "vminnm\.f32\t\[qQ\]\[0-9\]+, ?\[qQ\]\[0-9\]+, ?\[qQ\]\[0-9\]+\n" 7 } } */