[6/6] aarch64: Port NEON min/max intrinsics to the pragma-based framework

Message ID 20260902083828.45767-7-dhruvc@nvidia.com
State New
Delegated to: Kyrill Tkachov
Headers
Series aarch64: Port NEON intrinsics to pragma-based framework using IFNs |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_simplebootstrap_build--master-arm-bootstrap success Build passed

Commit Message

Dhruv Chawla Sept. 2, 2026, 8:38 a.m. UTC
  From: Dhruv Chawla <dhruvc@nvidia.com>

Port the following intrinsics to the pragma-based framework:
* vmax
* vmin
* vmaxnm
* vminnm

The faminmax-no-codegen.c test now ends up folding to a single
instruction (famax / famin) in a few cases.

The following are not ported in this patch as they cannot be directly
lowered from an IFN through an existing instruction pattern:
* vmax_f16
* vmax_f32
* vmax_f64
* vmaxq_f16
* vmaxq_f32
* vmaxq_f64
* vmin_f16
* vmin_f32
* vmin_f64
* vminq_f16
* vminq_f32
* vminq_f64

  This is due to the NaN semantics of these intrinsics which require
  lowering to <optab>_nan variants.

* vmaxnm_f64
* vminnm_f64

  This is due to the iterator used in the pattern (VHSDF) not covering
  the mode (V1DF) for these intrinsics.

Bootstrapped and regtested on aarch64-linux-gnu.

Signed-off-by: Dhruv Chawla <dhruvc@nvidia.com>

gcc/ChangeLog:

	* config/aarch64/aarch64-neon-builtins-base.cc (vmax, vmaxq, vmin,
	vminq, vmaxnm, vmaxnmq, vminnm, vminnmq): New function bases.
	* config/aarch64/aarch64-neon-builtins-base.def (vmax, vmaxq, vmin,
	vminq, vmaxnm, vmaxnmq, vminnm, vminnmq): New function groups.
	* config/aarch64/arm_neon.h (vmax_s8, vmax_s16, vmax_s32, vmax_u8,
	vmax_u16, vmax_u32, vmaxq_s8, vmaxq_s16, vmaxq_s32, vmaxq_u8,
	vmaxq_u16, vmaxq_u32, vmaxnm_f32, vmaxnmq_f32, vmaxnmq_f64, vmin_s8,
	vmin_s16, vmin_s32, vmin_u8, vmin_u16, vmin_u32, vminq_s8, vminq_s16,
	vminq_s32, vminq_u8, vminq_u16, vminq_u32, vminnm_f32, vminnmq_f32,
	vminnmq_f64, vmaxnm_f16, vmaxnmq_f16, vminnm_f16, vminnmq_f16):
	Delete functions.

gcc/testsuite/ChangeLog:

	* gcc.target/aarch64/simd/faminmax-no-codegen.c: Update
	check-function-bodies checks.
	* gcc.target/aarch64/neon/vmax.c: New test.
	* gcc.target/aarch64/neon/vmaxnm.c: Likewise.
	* gcc.target/aarch64/neon/vmin.c: Likewise.
	* gcc.target/aarch64/neon/vminnm.c: Likewise.
---
 .../aarch64/aarch64-neon-builtins-base.cc     |  10 +
 .../aarch64/aarch64-neon-builtins-base.def    |  20 ++
 gcc/config/aarch64/arm_neon.h                 | 249 ------------------
 gcc/testsuite/gcc.target/aarch64/neon/vmax.c  | 130 +++++++++
 .../gcc.target/aarch64/neon/vmaxnm.c          |  46 ++++
 gcc/testsuite/gcc.target/aarch64/neon/vmin.c  | 130 +++++++++
 .../gcc.target/aarch64/neon/vminnm.c          |  46 ++++
 .../aarch64/simd/faminmax-no-codegen.c        |  40 +--
 8 files changed, 392 insertions(+), 279 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/neon/vmax.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/neon/vmaxnm.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/neon/vmin.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/neon/vminnm.c
  

Patch

diff --git a/gcc/config/aarch64/aarch64-neon-builtins-base.cc b/gcc/config/aarch64/aarch64-neon-builtins-base.cc
index b8bb324f7de..487c5dac302 100644
--- a/gcc/config/aarch64/aarch64-neon-builtins-base.cc
+++ b/gcc/config/aarch64/aarch64-neon-builtins-base.cc
@@ -767,6 +767,16 @@  NEON_FUNCTION (vqsubd, gimple_ifn, (IFN_SAT_SUB))
 NEON_FUNCTION (vqsub,  gimple_ifn, (IFN_SAT_SUB))
 NEON_FUNCTION (vqsubq, gimple_ifn, (IFN_SAT_SUB))
 
+// Max/min
+NEON_FUNCTION (vmax,    gimple_expr, (MAX_EXPR))
+NEON_FUNCTION (vmaxq,   gimple_expr, (MAX_EXPR))
+NEON_FUNCTION (vmin,    gimple_expr, (MIN_EXPR))
+NEON_FUNCTION (vminq,   gimple_expr, (MIN_EXPR))
+NEON_FUNCTION (vmaxnm,  gimple_ifn,  (IFN_FMAX))
+NEON_FUNCTION (vmaxnmq, gimple_ifn,  (IFN_FMAX))
+NEON_FUNCTION (vminnm,  gimple_ifn,  (IFN_FMIN))
+NEON_FUNCTION (vminnmq, gimple_ifn,  (IFN_FMIN))
+
 // Reductions
 NEON_FUNCTION (vaddv,    gimple_ifn, (IFN_REDUC_PLUS))
 NEON_FUNCTION (vaddvq,   gimple_ifn, (IFN_REDUC_PLUS))
diff --git a/gcc/config/aarch64/aarch64-neon-builtins-base.def b/gcc/config/aarch64/aarch64-neon-builtins-base.def
index 70f14c46f0a..21181aacc9b 100644
--- a/gcc/config/aarch64/aarch64-neon-builtins-base.def
+++ b/gcc/config/aarch64/aarch64-neon-builtins-base.def
@@ -92,6 +92,26 @@  DEF_NEON_FUNCTION (vqsub,  bhs_integer, ("D0,D0,D0"))
 DEF_NEON_FUNCTION (vqsubq, all_integer, ("Q0,Q0,Q0"))
 #undef REQUIRED_EXTENSIONS
 
+// Max/min
+#define REQUIRED_EXTENSIONS nonstreaming_only (AARCH64_FL_SIMD)
+DEF_NEON_FUNCTION (vmax,    bhs_integer, ("D0,D0,D0"))
+DEF_NEON_FUNCTION (vmaxq,   bhs_integer, ("Q0,Q0,Q0"))
+DEF_NEON_FUNCTION (vmin,    bhs_integer, ("D0,D0,D0"))
+DEF_NEON_FUNCTION (vminq,   bhs_integer, ("Q0,Q0,Q0"))
+DEF_NEON_FUNCTION (vmaxnm,  s_float,     ("D0,D0,D0"))
+DEF_NEON_FUNCTION (vmaxnmq, sd_float,    ("Q0,Q0,Q0"))
+DEF_NEON_FUNCTION (vminnm,  s_float,     ("D0,D0,D0"))
+DEF_NEON_FUNCTION (vminnmq, sd_float,    ("Q0,Q0,Q0"))
+#undef REQUIRED_EXTENSIONS
+
+// Max/min (FP16)
+#define REQUIRED_EXTENSIONS nonstreaming_only (AARCH64_FL_SIMD | AARCH64_FL_F16)
+DEF_NEON_FUNCTION (vmaxnm,  h_float, ("D0,D0,D0"))
+DEF_NEON_FUNCTION (vmaxnmq, h_float, ("Q0,Q0,Q0"))
+DEF_NEON_FUNCTION (vminnm,  h_float, ("D0,D0,D0"))
+DEF_NEON_FUNCTION (vminnmq, h_float, ("Q0,Q0,Q0"))
+#undef REQUIRED_EXTENSIONS
+
 // Reductions
 #define REQUIRED_EXTENSIONS nonstreaming_only (AARCH64_FL_SIMD)
 DEF_NEON_FUNCTION (vaddv,    s_float_bhs_integer,  ("s0,D0"))
diff --git a/gcc/config/aarch64/arm_neon.h b/gcc/config/aarch64/arm_neon.h
index 59eba4c70ed..ea82a7ed719 100644
--- a/gcc/config/aarch64/arm_neon.h
+++ b/gcc/config/aarch64/arm_neon.h
@@ -11504,51 +11504,6 @@  vmax_f64 (float64x1_t __a, float64x1_t __b)
 				      vget_lane_f64 (__b, 0)) };
 }
 
-__extension__ extern __inline int8x8_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vmax_s8 (int8x8_t __a, int8x8_t __b)
-{
-  return __builtin_aarch64_smaxv8qi (__a, __b);
-}
-
-__extension__ extern __inline int16x4_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vmax_s16 (int16x4_t __a, int16x4_t __b)
-{
-  return __builtin_aarch64_smaxv4hi (__a, __b);
-}
-
-__extension__ extern __inline int32x2_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vmax_s32 (int32x2_t __a, int32x2_t __b)
-{
-  return __builtin_aarch64_smaxv2si (__a, __b);
-}
-
-__extension__ extern __inline uint8x8_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vmax_u8 (uint8x8_t __a, uint8x8_t __b)
-{
-  return (uint8x8_t) __builtin_aarch64_umaxv8qi ((int8x8_t) __a,
-						 (int8x8_t) __b);
-}
-
-__extension__ extern __inline uint16x4_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vmax_u16 (uint16x4_t __a, uint16x4_t __b)
-{
-  return (uint16x4_t) __builtin_aarch64_umaxv4hi ((int16x4_t) __a,
-						  (int16x4_t) __b);
-}
-
-__extension__ extern __inline uint32x2_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vmax_u32 (uint32x2_t __a, uint32x2_t __b)
-{
-  return (uint32x2_t) __builtin_aarch64_umaxv2si ((int32x2_t) __a,
-						  (int32x2_t) __b);
-}
-
 __extension__ extern __inline float32x4_t
 __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
 vmaxq_f32 (float32x4_t __a, float32x4_t __b)
@@ -11563,50 +11518,6 @@  vmaxq_f64 (float64x2_t __a, float64x2_t __b)
   return __builtin_aarch64_fmax_nanv2df (__a, __b);
 }
 
-__extension__ extern __inline int8x16_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vmaxq_s8 (int8x16_t __a, int8x16_t __b)
-{
-  return __builtin_aarch64_smaxv16qi (__a, __b);
-}
-
-__extension__ extern __inline int16x8_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vmaxq_s16 (int16x8_t __a, int16x8_t __b)
-{
-  return __builtin_aarch64_smaxv8hi (__a, __b);
-}
-
-__extension__ extern __inline int32x4_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vmaxq_s32 (int32x4_t __a, int32x4_t __b)
-{
-  return __builtin_aarch64_smaxv4si (__a, __b);
-}
-
-__extension__ extern __inline uint8x16_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vmaxq_u8 (uint8x16_t __a, uint8x16_t __b)
-{
-  return (uint8x16_t) __builtin_aarch64_umaxv16qi ((int8x16_t) __a,
-						   (int8x16_t) __b);
-}
-
-__extension__ extern __inline uint16x8_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vmaxq_u16 (uint16x8_t __a, uint16x8_t __b)
-{
-  return (uint16x8_t) __builtin_aarch64_umaxv8hi ((int16x8_t) __a,
-						  (int16x8_t) __b);
-}
-
-__extension__ extern __inline uint32x4_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vmaxq_u32 (uint32x4_t __a, uint32x4_t __b)
-{
-  return (uint32x4_t) __builtin_aarch64_umaxv4si ((int32x4_t) __a,
-						  (int32x4_t) __b);
-}
 /* vmulx */
 
 __extension__ extern __inline float32x2_t
@@ -12065,13 +11976,6 @@  vpminnms_f32 (float32x2_t __a)
 
 /* vmaxnm  */
 
-__extension__ extern __inline float32x2_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vmaxnm_f32 (float32x2_t __a, float32x2_t __b)
-{
-  return __builtin_aarch64_fmaxv2sf (__a, __b);
-}
-
 __extension__ extern __inline float64x1_t
 __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
 vmaxnm_f64 (float64x1_t __a, float64x1_t __b)
@@ -12081,20 +11985,6 @@  vmaxnm_f64 (float64x1_t __a, float64x1_t __b)
 				vget_lane_f64 (__b, 0)) };
 }
 
-__extension__ extern __inline float32x4_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vmaxnmq_f32 (float32x4_t __a, float32x4_t __b)
-{
-  return __builtin_aarch64_fmaxv4sf (__a, __b);
-}
-
-__extension__ extern __inline float64x2_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vmaxnmq_f64 (float64x2_t __a, float64x2_t __b)
-{
-  return __builtin_aarch64_fmaxv2df (__a, __b);
-}
-
 /* vmaxv  */
 
 __extension__ extern __inline float32_t
@@ -12136,51 +12026,6 @@  vmin_f64 (float64x1_t __a, float64x1_t __b)
 					  vget_lane_f64 (__b, 0)) };
 }
 
-__extension__ extern __inline int8x8_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vmin_s8 (int8x8_t __a, int8x8_t __b)
-{
-  return __builtin_aarch64_sminv8qi (__a, __b);
-}
-
-__extension__ extern __inline int16x4_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vmin_s16 (int16x4_t __a, int16x4_t __b)
-{
-  return __builtin_aarch64_sminv4hi (__a, __b);
-}
-
-__extension__ extern __inline int32x2_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vmin_s32 (int32x2_t __a, int32x2_t __b)
-{
-  return __builtin_aarch64_sminv2si (__a, __b);
-}
-
-__extension__ extern __inline uint8x8_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vmin_u8 (uint8x8_t __a, uint8x8_t __b)
-{
-  return (uint8x8_t) __builtin_aarch64_uminv8qi ((int8x8_t) __a,
-						 (int8x8_t) __b);
-}
-
-__extension__ extern __inline uint16x4_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vmin_u16 (uint16x4_t __a, uint16x4_t __b)
-{
-  return (uint16x4_t) __builtin_aarch64_uminv4hi ((int16x4_t) __a,
-						  (int16x4_t) __b);
-}
-
-__extension__ extern __inline uint32x2_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vmin_u32 (uint32x2_t __a, uint32x2_t __b)
-{
-  return (uint32x2_t) __builtin_aarch64_uminv2si ((int32x2_t) __a,
-						  (int32x2_t) __b);
-}
-
 __extension__ extern __inline float32x4_t
 __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
 vminq_f32 (float32x4_t __a, float32x4_t __b)
@@ -12195,60 +12040,8 @@  vminq_f64 (float64x2_t __a, float64x2_t __b)
   return __builtin_aarch64_fmin_nanv2df (__a, __b);
 }
 
-__extension__ extern __inline int8x16_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vminq_s8 (int8x16_t __a, int8x16_t __b)
-{
-  return __builtin_aarch64_sminv16qi (__a, __b);
-}
-
-__extension__ extern __inline int16x8_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vminq_s16 (int16x8_t __a, int16x8_t __b)
-{
-  return __builtin_aarch64_sminv8hi (__a, __b);
-}
-
-__extension__ extern __inline int32x4_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vminq_s32 (int32x4_t __a, int32x4_t __b)
-{
-  return __builtin_aarch64_sminv4si (__a, __b);
-}
-
-__extension__ extern __inline uint8x16_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vminq_u8 (uint8x16_t __a, uint8x16_t __b)
-{
-  return (uint8x16_t) __builtin_aarch64_uminv16qi ((int8x16_t) __a,
-						   (int8x16_t) __b);
-}
-
-__extension__ extern __inline uint16x8_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vminq_u16 (uint16x8_t __a, uint16x8_t __b)
-{
-  return (uint16x8_t) __builtin_aarch64_uminv8hi ((int16x8_t) __a,
-						  (int16x8_t) __b);
-}
-
-__extension__ extern __inline uint32x4_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vminq_u32 (uint32x4_t __a, uint32x4_t __b)
-{
-  return (uint32x4_t) __builtin_aarch64_uminv4si ((int32x4_t) __a,
-						  (int32x4_t) __b);
-}
-
 /* vminnm  */
 
-__extension__ extern __inline float32x2_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vminnm_f32 (float32x2_t __a, float32x2_t __b)
-{
-  return __builtin_aarch64_fminv2sf (__a, __b);
-}
-
 __extension__ extern __inline float64x1_t
 __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
 vminnm_f64 (float64x1_t __a, float64x1_t __b)
@@ -12258,20 +12051,6 @@  vminnm_f64 (float64x1_t __a, float64x1_t __b)
 				vget_lane_f64 (__b, 0)) };
 }
 
-__extension__ extern __inline float32x4_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vminnmq_f32 (float32x4_t __a, float32x4_t __b)
-{
-  return __builtin_aarch64_fminv4sf (__a, __b);
-}
-
-__extension__ extern __inline float64x2_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vminnmq_f64 (float64x2_t __a, float64x2_t __b)
-{
-  return __builtin_aarch64_fminv2df (__a, __b);
-}
-
 /* vminv  */
 
 __extension__ extern __inline float32_t
@@ -19272,20 +19051,6 @@  vmaxq_f16 (float16x8_t __a, float16x8_t __b)
   return __builtin_aarch64_fmax_nanv8hf (__a, __b);
 }
 
-__extension__ extern __inline float16x4_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vmaxnm_f16 (float16x4_t __a, float16x4_t __b)
-{
-  return __builtin_aarch64_fmaxv4hf (__a, __b);
-}
-
-__extension__ extern __inline float16x8_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vmaxnmq_f16 (float16x8_t __a, float16x8_t __b)
-{
-  return __builtin_aarch64_fmaxv8hf (__a, __b);
-}
-
 __extension__ extern __inline float16x4_t
 __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
 vmin_f16 (float16x4_t __a, float16x4_t __b)
@@ -19300,20 +19065,6 @@  vminq_f16 (float16x8_t __a, float16x8_t __b)
   return __builtin_aarch64_fmin_nanv8hf (__a, __b);
 }
 
-__extension__ extern __inline float16x4_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vminnm_f16 (float16x4_t __a, float16x4_t __b)
-{
-  return __builtin_aarch64_fminv4hf (__a, __b);
-}
-
-__extension__ extern __inline float16x8_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vminnmq_f16 (float16x8_t __a, float16x8_t __b)
-{
-  return __builtin_aarch64_fminv8hf (__a, __b);
-}
-
 __extension__ extern __inline float16x4_t
 __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
 vmul_f16 (float16x4_t __a, float16x4_t __b)
diff --git a/gcc/testsuite/gcc.target/aarch64/neon/vmax.c b/gcc/testsuite/gcc.target/aarch64/neon/vmax.c
new file mode 100644
index 00000000000..ac22958f096
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/neon/vmax.c
@@ -0,0 +1,130 @@ 
+/* { dg-do compile } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "arm_neon_test.h"
+
+/*
+** test_vmax_u8:
+** umax	v0\.8b, (v0\.8b, v1\.8b|v1\.8b, v0\.8b)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmax_u8, uint8x8_t)
+
+/*
+** test_vmax_s8:
+** smax	v0\.8b, (v0\.8b, v1\.8b|v1\.8b, v0\.8b)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmax_s8, int8x8_t)
+
+/*
+** test_vmax_u16:
+** umax	v0\.4h, (v0\.4h, v1\.4h|v1\.4h, v0\.4h)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmax_u16, uint16x4_t)
+
+/*
+** test_vmax_s16:
+** smax	v0\.4h, (v0\.4h, v1\.4h|v1\.4h, v0\.4h)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmax_s16, int16x4_t)
+
+/*
+** test_vmax_f16:
+** fmax	v0\.4h, (v0\.4h, v1\.4h|v1\.4h, v0\.4h)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmax_f16, float16x4_t)
+
+/*
+** test_vmax_u32:
+** umax	v0\.2s, (v0\.2s, v1\.2s|v1\.2s, v0\.2s)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmax_u32, uint32x2_t)
+
+/*
+** test_vmax_s32:
+** smax	v0\.2s, (v0\.2s, v1\.2s|v1\.2s, v0\.2s)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmax_s32, int32x2_t)
+
+/*
+** test_vmax_f32:
+** fmax	v0\.2s, (v0\.2s, v1\.2s|v1\.2s, v0\.2s)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmax_f32, float32x2_t)
+
+/*
+** test_vmax_f64:
+** fmax	d0, (d0, d1|d1, d0)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmax_f64, float64x1_t)
+
+/*
+** test_vmaxq_u8:
+** umax	v0\.16b, (v0\.16b, v1\.16b|v1\.16b, v0\.16b)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmaxq_u8, uint8x16_t)
+
+/*
+** test_vmaxq_s8:
+** smax	v0\.16b, (v0\.16b, v1\.16b|v1\.16b, v0\.16b)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmaxq_s8, int8x16_t)
+
+/*
+** test_vmaxq_u16:
+** umax	v0\.8h, (v0\.8h, v1\.8h|v1\.8h, v0\.8h)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmaxq_u16, uint16x8_t)
+
+/*
+** test_vmaxq_s16:
+** smax	v0\.8h, (v0\.8h, v1\.8h|v1\.8h, v0\.8h)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmaxq_s16, int16x8_t)
+
+/*
+** test_vmaxq_f16:
+** fmax	v0\.8h, (v0\.8h, v1\.8h|v1\.8h, v0\.8h)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmaxq_f16, float16x8_t)
+
+/*
+** test_vmaxq_u32:
+** umax	v0\.4s, (v0\.4s, v1\.4s|v1\.4s, v0\.4s)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmaxq_u32, uint32x4_t)
+
+/*
+** test_vmaxq_s32:
+** smax	v0\.4s, (v0\.4s, v1\.4s|v1\.4s, v0\.4s)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmaxq_s32, int32x4_t)
+
+/*
+** test_vmaxq_f32:
+** fmax	v0\.4s, (v0\.4s, v1\.4s|v1\.4s, v0\.4s)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmaxq_f32, float32x4_t)
+
+/*
+** test_vmaxq_f64:
+** fmax	v0\.2d, (v0\.2d, v1\.2d|v1\.2d, v0\.2d)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmaxq_f64, float64x2_t)
diff --git a/gcc/testsuite/gcc.target/aarch64/neon/vmaxnm.c b/gcc/testsuite/gcc.target/aarch64/neon/vmaxnm.c
new file mode 100644
index 00000000000..e2bee718811
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/neon/vmaxnm.c
@@ -0,0 +1,46 @@ 
+/* { dg-do compile } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "arm_neon_test.h"
+
+/*
+** test_vmaxnm_f16:
+** fmaxnm	v0\.4h, (v0\.4h, v1\.4h|v1\.4h, v0\.4h)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmaxnm_f16, float16x4_t)
+
+/*
+** test_vmaxnm_f32:
+** fmaxnm	v0\.2s, (v0\.2s, v1\.2s|v1\.2s, v0\.2s)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmaxnm_f32, float32x2_t)
+
+/*
+** test_vmaxnm_f64:
+** fmaxnm	d0, (d0, d1|d1, d0)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmaxnm_f64, float64x1_t)
+
+/*
+** test_vmaxnmq_f16:
+** fmaxnm	v0\.8h, (v0\.8h, v1\.8h|v1\.8h, v0\.8h)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmaxnmq_f16, float16x8_t)
+
+/*
+** test_vmaxnmq_f32:
+** fmaxnm	v0\.4s, (v0\.4s, v1\.4s|v1\.4s, v0\.4s)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmaxnmq_f32, float32x4_t)
+
+/*
+** test_vmaxnmq_f64:
+** fmaxnm	v0\.2d, (v0\.2d, v1\.2d|v1\.2d, v0\.2d)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmaxnmq_f64, float64x2_t)
diff --git a/gcc/testsuite/gcc.target/aarch64/neon/vmin.c b/gcc/testsuite/gcc.target/aarch64/neon/vmin.c
new file mode 100644
index 00000000000..13b582c0449
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/neon/vmin.c
@@ -0,0 +1,130 @@ 
+/* { dg-do compile } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "arm_neon_test.h"
+
+/*
+** test_vmin_u8:
+** umin	v0\.8b, (v0\.8b, v1\.8b|v1\.8b, v0\.8b)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmin_u8, uint8x8_t)
+
+/*
+** test_vmin_s8:
+** smin	v0\.8b, (v0\.8b, v1\.8b|v1\.8b, v0\.8b)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmin_s8, int8x8_t)
+
+/*
+** test_vmin_u16:
+** umin	v0\.4h, (v0\.4h, v1\.4h|v1\.4h, v0\.4h)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmin_u16, uint16x4_t)
+
+/*
+** test_vmin_s16:
+** smin	v0\.4h, (v0\.4h, v1\.4h|v1\.4h, v0\.4h)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmin_s16, int16x4_t)
+
+/*
+** test_vmin_f16:
+** fmin	v0\.4h, (v0\.4h, v1\.4h|v1\.4h, v0\.4h)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmin_f16, float16x4_t)
+
+/*
+** test_vmin_u32:
+** umin	v0\.2s, (v0\.2s, v1\.2s|v1\.2s, v0\.2s)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmin_u32, uint32x2_t)
+
+/*
+** test_vmin_s32:
+** smin	v0\.2s, (v0\.2s, v1\.2s|v1\.2s, v0\.2s)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmin_s32, int32x2_t)
+
+/*
+** test_vmin_f32:
+** fmin	v0\.2s, (v0\.2s, v1\.2s|v1\.2s, v0\.2s)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmin_f32, float32x2_t)
+
+/*
+** test_vmin_f64:
+** fmin	d0, (d0, d1|d1, d0)
+** ret
+*/
+TEST_UNIFORM_BINARY (vmin_f64, float64x1_t)
+
+/*
+** test_vminq_u8:
+** umin	v0\.16b, (v0\.16b, v1\.16b|v1\.16b, v0\.16b)
+** ret
+*/
+TEST_UNIFORM_BINARY (vminq_u8, uint8x16_t)
+
+/*
+** test_vminq_s8:
+** smin	v0\.16b, (v0\.16b, v1\.16b|v1\.16b, v0\.16b)
+** ret
+*/
+TEST_UNIFORM_BINARY (vminq_s8, int8x16_t)
+
+/*
+** test_vminq_u16:
+** umin	v0\.8h, (v0\.8h, v1\.8h|v1\.8h, v0\.8h)
+** ret
+*/
+TEST_UNIFORM_BINARY (vminq_u16, uint16x8_t)
+
+/*
+** test_vminq_s16:
+** smin	v0\.8h, (v0\.8h, v1\.8h|v1\.8h, v0\.8h)
+** ret
+*/
+TEST_UNIFORM_BINARY (vminq_s16, int16x8_t)
+
+/*
+** test_vminq_f16:
+** fmin	v0\.8h, (v0\.8h, v1\.8h|v1\.8h, v0\.8h)
+** ret
+*/
+TEST_UNIFORM_BINARY (vminq_f16, float16x8_t)
+
+/*
+** test_vminq_u32:
+** umin	v0\.4s, (v0\.4s, v1\.4s|v1\.4s, v0\.4s)
+** ret
+*/
+TEST_UNIFORM_BINARY (vminq_u32, uint32x4_t)
+
+/*
+** test_vminq_s32:
+** smin	v0\.4s, (v0\.4s, v1\.4s|v1\.4s, v0\.4s)
+** ret
+*/
+TEST_UNIFORM_BINARY (vminq_s32, int32x4_t)
+
+/*
+** test_vminq_f32:
+** fmin	v0\.4s, (v0\.4s, v1\.4s|v1\.4s, v0\.4s)
+** ret
+*/
+TEST_UNIFORM_BINARY (vminq_f32, float32x4_t)
+
+/*
+** test_vminq_f64:
+** fmin	v0\.2d, (v0\.2d, v1\.2d|v1\.2d, v0\.2d)
+** ret
+*/
+TEST_UNIFORM_BINARY (vminq_f64, float64x2_t)
diff --git a/gcc/testsuite/gcc.target/aarch64/neon/vminnm.c b/gcc/testsuite/gcc.target/aarch64/neon/vminnm.c
new file mode 100644
index 00000000000..316bba1a5a4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/neon/vminnm.c
@@ -0,0 +1,46 @@ 
+/* { dg-do compile } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "arm_neon_test.h"
+
+/*
+** test_vminnm_f16:
+** fminnm	v0\.4h, (v0\.4h, v1\.4h|v1\.4h, v0\.4h)
+** ret
+*/
+TEST_UNIFORM_BINARY (vminnm_f16, float16x4_t)
+
+/*
+** test_vminnm_f32:
+** fminnm	v0\.2s, (v0\.2s, v1\.2s|v1\.2s, v0\.2s)
+** ret
+*/
+TEST_UNIFORM_BINARY (vminnm_f32, float32x2_t)
+
+/*
+** test_vminnm_f64:
+** fminnm	d0, (d0, d1|d1, d0)
+** ret
+*/
+TEST_UNIFORM_BINARY (vminnm_f64, float64x1_t)
+
+/*
+** test_vminnmq_f16:
+** fminnm	v0\.8h, (v0\.8h, v1\.8h|v1\.8h, v0\.8h)
+** ret
+*/
+TEST_UNIFORM_BINARY (vminnmq_f16, float16x8_t)
+
+/*
+** test_vminnmq_f32:
+** fminnm	v0\.4s, (v0\.4s, v1\.4s|v1\.4s, v0\.4s)
+** ret
+*/
+TEST_UNIFORM_BINARY (vminnmq_f32, float32x4_t)
+
+/*
+** test_vminnmq_f64:
+** fminnm	v0\.2d, (v0\.2d, v1\.2d|v1\.2d, v0\.2d)
+** ret
+*/
+TEST_UNIFORM_BINARY (vminnmq_f64, float64x2_t)
diff --git a/gcc/testsuite/gcc.target/aarch64/simd/faminmax-no-codegen.c b/gcc/testsuite/gcc.target/aarch64/simd/faminmax-no-codegen.c
index 3ec0a52b522..4bbd81f5a0d 100644
--- a/gcc/testsuite/gcc.target/aarch64/simd/faminmax-no-codegen.c
+++ b/gcc/testsuite/gcc.target/aarch64/simd/faminmax-no-codegen.c
@@ -21,9 +21,7 @@  test_abs_max_f16 (float16x4_t a, float16x4_t b)
 
 /*
 ** test_abs_maxnm_f16:
-**	fabs	v1.4h, v1.4h
-**	fabs	v0.4h, v0.4h
-**	fmaxnm	v0.4h, v0.4h, v1.4h
+**	famax	v0.4h, (v0.4h, v1.4h|v1.4h, v0.4h)
 **	ret
 */
 float16x4_t
@@ -47,9 +45,7 @@  test_abs_maxq_f16 (float16x8_t a, float16x8_t b)
 
 /*
 ** test_abs_maxnmq_f16:
-**	fabs	v1.8h, v1.8h
-**	fabs	v0.8h, v0.8h
-**	fmaxnm	v0.8h, v0.8h, v1.8h
+**	famax	v0.8h, (v0.8h, v1.8h|v1.8h, v0.8h)
 **	ret
 */
 float16x8_t
@@ -73,9 +69,7 @@  test_abs_max_f32 (float32x2_t a, float32x2_t b)
 
 /*
 ** test_abs_maxnm_f32:
-**	fabs	v1.2s, v1.2s
-**	fabs	v0.2s, v0.2s
-**	fmaxnm	v0.2s, v0.2s, v1.2s
+**	famax	v0.2s, (v0.2s, v1.2s|v1.2s, v0.2s)
 **	ret
 */
 float32x2_t
@@ -99,9 +93,7 @@  test_abs_maxq_f32 (float32x4_t a, float32x4_t b)
 
 /*
 ** test_abs_maxnmq_f32:
-**	fabs	v1.4s, v1.4s
-**	fabs	v0.4s, v0.4s
-**	fmaxnm	v0.4s, v0.4s, v1.4s
+**	famax	v0.4s, (v0.4s, v1.4s|v1.4s, v0.4s)
 **	ret
 */
 float32x4_t
@@ -125,9 +117,7 @@  test_abs_maxq_f64 (float64x2_t a, float64x2_t b)
 
 /*
 ** test_abs_maxnmq_f64:
-**	fabs	v1.2d, v1.2d
-**	fabs	v0.2d, v0.2d
-**	fmaxnm	v0.2d, v0.2d, v1.2d
+**	famax	v0.2d, (v0.2d, v1.2d|v1.2d, v0.2d)
 **	ret
 */
 float64x2_t
@@ -151,9 +141,7 @@  test_abs_min_f16 (float16x4_t a, float16x4_t b)
 
 /*
 ** test_abs_minnm_f16:
-**	fabs	v1.4h, v1.4h
-**	fabs	v0.4h, v0.4h
-**	fminnm	v0.4h, v0.4h, v1.4h
+**	famin	v0.4h, (v0.4h, v1.4h|v1.4h, v0.4h)
 **	ret
 */
 float16x4_t
@@ -177,9 +165,7 @@  test_abs_minq_f16 (float16x8_t a, float16x8_t b)
 
 /*
 ** test_abs_minnmq_f16:
-**	fabs	v1.8h, v1.8h
-**	fabs	v0.8h, v0.8h
-**	fminnm	v0.8h, v0.8h, v1.8h
+**	famin	v0.8h, (v0.8h, v1.8h|v1.8h, v0.8h)
 **	ret
 */
 float16x8_t
@@ -203,9 +189,7 @@  test_abs_min_f32 (float32x2_t a, float32x2_t b)
 
 /*
 ** test_abs_minnm_f32:
-**	fabs	v1.2s, v1.2s
-**	fabs	v0.2s, v0.2s
-**	fminnm	v0.2s, v0.2s, v1.2s
+**	famin	v0.2s, (v0.2s, v1.2s|v1.2s, v0.2s)
 **	ret
 */
 float32x2_t
@@ -229,9 +213,7 @@  test_abs_minq_f32 (float32x4_t a, float32x4_t b)
 
 /*
 ** test_abs_minnmq_f32:
-**	fabs	v1.4s, v1.4s
-**	fabs	v0.4s, v0.4s
-**	fminnm	v0.4s, v0.4s, v1.4s
+**	famin	v0.4s, (v0.4s, v1.4s|v1.4s, v0.4s)
 **	ret
 */
 float32x4_t
@@ -255,9 +237,7 @@  test_abs_minq_f64 (float64x2_t a, float64x2_t b)
 
 /*
 ** test_abs_minnmq_f64:
-**	fabs	v1.2d, v1.2d
-**	fabs	v0.2d, v0.2d
-**	fminnm	v0.2d, v0.2d, v1.2d
+**	famin	v0.2d, (v0.2d, v1.2d|v1.2d, v0.2d)
 **	ret
 */
 float64x2_t