[1/6] aarch64: Port NEON saturating add/sub intrinsics to pragma-based framework

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

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:
* vqadd
* vqsub

Plus their scalar variants: vq{add,sub}{b,h,s,d}.

The following are not ported in this patch as they cannot be directly
lowered from an IFN through an existing instruction pattern:
* vqadd_s64
* vqadd_u64
* vqsub_s64
* vqsub_u64

This is because the pattern does not iterate through the modes (V1DI) required
to lower them (it uses the VSDQ_I_QI_HI iterator).

Bootstrapped and regtested on aarch64-linux-gnu.

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

gcc/ChangeLog:

	* config/aarch64/aarch64-neon-builtins-base.cc (vqaddb, vqaddh,
	vqadds, vqaddd, vqadd, vqaddq, vqsubb, vqsubh, vqsubs, vqsubd, vqsub,
	vqsubq): New function bases.
	* config/aarch64/aarch64-neon-builtins-base.def (vqaddb, vqaddh,
	vqadds, vqaddd, vqadd, vqaddq, vqsubb, vqsubh, vqsubs, vqsubd, vqsub,
	vqsubq): New function groups.
	* config/aarch64/arm_neon.h (vqadd_s8, vqadd_s16, vqadd_s32,
	vqadd_u8, vqadd_u16, vqadd_u32, vqaddq_s8, vqaddq_s16, vqaddq_s32,
	vqaddq_s64, vqaddq_u8, vqaddq_u16, vqaddq_u32, vqaddq_u64, vqsub_s8,
	vqsub_s16, vqsub_s32, vqsub_u8, vqsub_u16, vqsub_u32, vqsubq_s8,
	vqsubq_s16, vqsubq_s32, vqsubq_s64, vqsubq_u8, vqsubq_u16, vqsubq_u32,
	vqsubq_u64, vqaddb_s8, vqaddh_s16, vqadds_s32, vqaddd_s64, vqaddb_u8,
	vqaddh_u16, vqadds_u32, vqaddd_u64, vqsubb_s8, vqsubh_s16, vqsubs_s32,
	vqsubd_s64, vqsubb_u8, vqsubh_u16, vqsubs_u32, vqsubd_u64): Delete
	functions.
	(vqadd_s64): Relocate to be grouped with the other {s,u}64
	functions.

gcc/testsuite/ChangeLog:

	* gcc.target/aarch64/neon/vqadd.c: New test.
	* gcc.target/aarch64/neon/vqsub.c: Likewise.
---
 .../aarch64/aarch64-neon-builtins-base.cc     |  14 +
 .../aarch64/aarch64-neon-builtins-base.def    |  16 +
 gcc/config/aarch64/arm_neon.h                 | 318 +-----------------
 gcc/testsuite/gcc.target/aarch64/neon/vqadd.c | 192 +++++++++++
 gcc/testsuite/gcc.target/aarch64/neon/vqsub.c | 192 +++++++++++
 5 files changed, 417 insertions(+), 315 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/neon/vqadd.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/neon/vqsub.c
  

Comments

Kyrylo Tkachov Sept. 2, 2026, 11:59 a.m. UTC | #1
Hi Dhruv,

> On 2 Sep 2026, at 10:38, Dhruv Chawla <dhruvc@nvidia.com> wrote:
> 
> From: Dhruv Chawla <dhruvc@nvidia.com>
> 
> Port the following intrinsics to the pragma-based framework:
> * vqadd
> * vqsub
> 
> Plus their scalar variants: vq{add,sub}{b,h,s,d}.
> 
> The following are not ported in this patch as they cannot be directly
> lowered from an IFN through an existing instruction pattern:
> * vqadd_s64
> * vqadd_u64
> * vqsub_s64
> * vqsub_u64
> 
> This is because the pattern does not iterate through the modes (V1DI) required
> to lower them (it uses the VSDQ_I_QI_HI iterator).
> 

I see this is an issue with many intrinsics groups. We’ll need to figure out a way to handle this, but in another patch.
This patch is ok.
Thanks,
Kyrill

> Bootstrapped and regtested on aarch64-linux-gnu.
> 
> Signed-off-by: Dhruv Chawla <dhruvc@nvidia.com>
> 
> gcc/ChangeLog:
> 
> * config/aarch64/aarch64-neon-builtins-base.cc (vqaddb, vqaddh,
> vqadds, vqaddd, vqadd, vqaddq, vqsubb, vqsubh, vqsubs, vqsubd, vqsub,
> vqsubq): New function bases.
> * config/aarch64/aarch64-neon-builtins-base.def (vqaddb, vqaddh,
> vqadds, vqaddd, vqadd, vqaddq, vqsubb, vqsubh, vqsubs, vqsubd, vqsub,
> vqsubq): New function groups.
> * config/aarch64/arm_neon.h (vqadd_s8, vqadd_s16, vqadd_s32,
> vqadd_u8, vqadd_u16, vqadd_u32, vqaddq_s8, vqaddq_s16, vqaddq_s32,
> vqaddq_s64, vqaddq_u8, vqaddq_u16, vqaddq_u32, vqaddq_u64, vqsub_s8,
> vqsub_s16, vqsub_s32, vqsub_u8, vqsub_u16, vqsub_u32, vqsubq_s8,
> vqsubq_s16, vqsubq_s32, vqsubq_s64, vqsubq_u8, vqsubq_u16, vqsubq_u32,
> vqsubq_u64, vqaddb_s8, vqaddh_s16, vqadds_s32, vqaddd_s64, vqaddb_u8,
> vqaddh_u16, vqadds_u32, vqaddd_u64, vqsubb_s8, vqsubh_s16, vqsubs_s32,
> vqsubd_s64, vqsubb_u8, vqsubh_u16, vqsubs_u32, vqsubd_u64): Delete
> functions.
> (vqadd_s64): Relocate to be grouped with the other {s,u}64
> functions.
> 
> gcc/testsuite/ChangeLog:
> 
> * gcc.target/aarch64/neon/vqadd.c: New test.
> * gcc.target/aarch64/neon/vqsub.c: Likewise.
> ---
> .../aarch64/aarch64-neon-builtins-base.cc     |  14 +
> .../aarch64/aarch64-neon-builtins-base.def    |  16 +
> gcc/config/aarch64/arm_neon.h                 | 318 +-----------------
> gcc/testsuite/gcc.target/aarch64/neon/vqadd.c | 192 +++++++++++
> gcc/testsuite/gcc.target/aarch64/neon/vqsub.c | 192 +++++++++++
> 5 files changed, 417 insertions(+), 315 deletions(-)
> create mode 100644 gcc/testsuite/gcc.target/aarch64/neon/vqadd.c
> create mode 100644 gcc/testsuite/gcc.target/aarch64/neon/vqsub.c
> 
> diff --git a/gcc/config/aarch64/aarch64-neon-builtins-base.cc b/gcc/config/aarch64/aarch64-neon-builtins-base.cc
> index d8fae81388e..5c886d32f42 100644
> --- a/gcc/config/aarch64/aarch64-neon-builtins-base.cc
> +++ b/gcc/config/aarch64/aarch64-neon-builtins-base.cc
> @@ -753,6 +753,20 @@ NEON_FUNCTION (vaddd, gimple_expr, (PLUS_EXPR))
> NEON_FUNCTION (vadd,  gimple_expr, (PLUS_EXPR, PLUS_EXPR, BIT_XOR_EXPR))
> NEON_FUNCTION (vaddq, gimple_expr, (PLUS_EXPR, PLUS_EXPR, BIT_XOR_EXPR))
> 
> +// Saturating arithmetic
> +NEON_FUNCTION (vqaddb, gimple_ifn, (IFN_SAT_ADD))
> +NEON_FUNCTION (vqaddh, gimple_ifn, (IFN_SAT_ADD))
> +NEON_FUNCTION (vqadds, gimple_ifn, (IFN_SAT_ADD))
> +NEON_FUNCTION (vqaddd, gimple_ifn, (IFN_SAT_ADD))
> +NEON_FUNCTION (vqadd,  gimple_ifn, (IFN_SAT_ADD))
> +NEON_FUNCTION (vqaddq, gimple_ifn, (IFN_SAT_ADD))
> +NEON_FUNCTION (vqsubb, gimple_ifn, (IFN_SAT_SUB))
> +NEON_FUNCTION (vqsubh, gimple_ifn, (IFN_SAT_SUB))
> +NEON_FUNCTION (vqsubs, gimple_ifn, (IFN_SAT_SUB))
> +NEON_FUNCTION (vqsubd, gimple_ifn, (IFN_SAT_SUB))
> +NEON_FUNCTION (vqsub,  gimple_ifn, (IFN_SAT_SUB))
> +NEON_FUNCTION (vqsubq, gimple_ifn, (IFN_SAT_SUB))
> +
> // Bitwise operations
> NEON_FUNCTION (vand,   gimple_expr,    (BIT_AND_EXPR))
> NEON_FUNCTION (vandq,  gimple_expr,    (BIT_AND_EXPR))
> diff --git a/gcc/config/aarch64/aarch64-neon-builtins-base.def b/gcc/config/aarch64/aarch64-neon-builtins-base.def
> index 7257f59bbc5..52e4746453b 100644
> --- a/gcc/config/aarch64/aarch64-neon-builtins-base.def
> +++ b/gcc/config/aarch64/aarch64-neon-builtins-base.def
> @@ -76,6 +76,22 @@ DEF_NEON_FUNCTION (vadd,  h_float, ("D0,D0,D0"))
> DEF_NEON_FUNCTION (vaddq, h_float, ("Q0,Q0,Q0"))
> #undef REQUIRED_EXTENSIONS
> 
> +// Saturating arithmetic
> +#define REQUIRED_EXTENSIONS nonstreaming_only (AARCH64_FL_SIMD)
> +DEF_NEON_FUNCTION (vqaddb, b_integer,   ("s0,s0,s0"))
> +DEF_NEON_FUNCTION (vqaddh, h_integer,   ("s0,s0,s0"))
> +DEF_NEON_FUNCTION (vqadds, s_integer,   ("s0,s0,s0"))
> +DEF_NEON_FUNCTION (vqaddd, d_integer,   ("s0,s0,s0"))
> +DEF_NEON_FUNCTION (vqadd,  bhs_integer, ("D0,D0,D0"))
> +DEF_NEON_FUNCTION (vqaddq, all_integer, ("Q0,Q0,Q0"))
> +DEF_NEON_FUNCTION (vqsubb, b_integer,   ("s0,s0,s0"))
> +DEF_NEON_FUNCTION (vqsubh, h_integer,   ("s0,s0,s0"))
> +DEF_NEON_FUNCTION (vqsubs, s_integer,   ("s0,s0,s0"))
> +DEF_NEON_FUNCTION (vqsubd, d_integer,   ("s0,s0,s0"))
> +DEF_NEON_FUNCTION (vqsub,  bhs_integer, ("D0,D0,D0"))
> +DEF_NEON_FUNCTION (vqsubq, all_integer, ("Q0,Q0,Q0"))
> +#undef REQUIRED_EXTENSIONS
> +
> // Bitwise operations
> #define REQUIRED_EXTENSIONS nonstreaming_only (AARCH64_FL_SIMD)
> DEF_NEON_FUNCTION (vand,   all_integer, ("D0,D0,D0"))
> diff --git a/gcc/config/aarch64/arm_neon.h b/gcc/config/aarch64/arm_neon.h
> index 873a1195d3e..985b4bdb6cc 100644
> --- a/gcc/config/aarch64/arm_neon.h
> +++ b/gcc/config/aarch64/arm_neon.h
> @@ -1071,41 +1071,6 @@ vsubw_high_u32 (uint64x2_t __a, uint32x4_t __b)
>   return __builtin_aarch64_usubw2v4si_uuu (__a, __b);
> }
> 
> -__extension__ extern __inline int8x8_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqadd_s8 (int8x8_t __a, int8x8_t __b)
> -{
> -  return (int8x8_t) __builtin_aarch64_ssaddv8qi (__a, __b);
> -}
> -
> -__extension__ extern __inline int16x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqadd_s16 (int16x4_t __a, int16x4_t __b)
> -{
> -  return (int16x4_t) __builtin_aarch64_ssaddv4hi (__a, __b);
> -}
> -
> -__extension__ extern __inline int32x2_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqadd_s32 (int32x2_t __a, int32x2_t __b)
> -{
> -  return (int32x2_t) __builtin_aarch64_ssaddv2si (__a, __b);
> -}
> -
> -__extension__ extern __inline int64x1_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqadd_s64 (int64x1_t __a, int64x1_t __b)
> -{
> -  return (int64x1_t) {__builtin_aarch64_ssadddi (__a[0], __b[0])};
> -}
> -
> -__extension__ extern __inline uint8x8_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqadd_u8 (uint8x8_t __a, uint8x8_t __b)
> -{
> -  return __builtin_aarch64_usaddv8qi_uuu (__a, __b);
> -}
> -
> __extension__ extern __inline int8x8_t
> __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> vhsub_s8 (int8x8_t __a, int8x8_t __b)
> @@ -1358,18 +1323,11 @@ vsubhn_high_u64 (uint32x2_t __a, uint64x2_t __b, uint64x2_t __c)
>   return __builtin_aarch64_subhn2v2di_uuuu (__a, __b, __c);
> }
> 
> -__extension__ extern __inline uint16x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqadd_u16 (uint16x4_t __a, uint16x4_t __b)
> -{
> -  return __builtin_aarch64_usaddv4hi_uuu (__a, __b);
> -}
> -
> -__extension__ extern __inline uint32x2_t
> +__extension__ extern __inline int64x1_t
> __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqadd_u32 (uint32x2_t __a, uint32x2_t __b)
> +vqadd_s64 (int64x1_t __a, int64x1_t __b)
> {
> -  return __builtin_aarch64_usaddv2si_uuu (__a, __b);
> +  return (int64x1_t) {__builtin_aarch64_ssadddi (__a[0], __b[0])};
> }
> 
> __extension__ extern __inline uint64x1_t
> @@ -1379,83 +1337,6 @@ vqadd_u64 (uint64x1_t __a, uint64x1_t __b)
>   return (uint64x1_t) {__builtin_aarch64_usadddi_uuu (__a[0], __b[0])};
> }
> 
> -__extension__ extern __inline int8x16_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqaddq_s8 (int8x16_t __a, int8x16_t __b)
> -{
> -  return (int8x16_t) __builtin_aarch64_ssaddv16qi (__a, __b);
> -}
> -
> -__extension__ extern __inline int16x8_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqaddq_s16 (int16x8_t __a, int16x8_t __b)
> -{
> -  return (int16x8_t) __builtin_aarch64_ssaddv8hi (__a, __b);
> -}
> -
> -__extension__ extern __inline int32x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqaddq_s32 (int32x4_t __a, int32x4_t __b)
> -{
> -  return (int32x4_t) __builtin_aarch64_ssaddv4si (__a, __b);
> -}
> -
> -__extension__ extern __inline int64x2_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqaddq_s64 (int64x2_t __a, int64x2_t __b)
> -{
> -  return (int64x2_t) __builtin_aarch64_ssaddv2di (__a, __b);
> -}
> -
> -__extension__ extern __inline uint8x16_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqaddq_u8 (uint8x16_t __a, uint8x16_t __b)
> -{
> -  return __builtin_aarch64_usaddv16qi_uuu (__a, __b);
> -}
> -
> -__extension__ extern __inline uint16x8_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqaddq_u16 (uint16x8_t __a, uint16x8_t __b)
> -{
> -  return __builtin_aarch64_usaddv8hi_uuu (__a, __b);
> -}
> -
> -__extension__ extern __inline uint32x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqaddq_u32 (uint32x4_t __a, uint32x4_t __b)
> -{
> -  return __builtin_aarch64_usaddv4si_uuu (__a, __b);
> -}
> -
> -__extension__ extern __inline uint64x2_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqaddq_u64 (uint64x2_t __a, uint64x2_t __b)
> -{
> -  return __builtin_aarch64_usaddv2di_uuu (__a, __b);
> -}
> -
> -__extension__ extern __inline int8x8_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqsub_s8 (int8x8_t __a, int8x8_t __b)
> -{
> -  return (int8x8_t) __builtin_aarch64_sssubv8qi (__a, __b);
> -}
> -
> -__extension__ extern __inline int16x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqsub_s16 (int16x4_t __a, int16x4_t __b)
> -{
> -  return (int16x4_t) __builtin_aarch64_sssubv4hi (__a, __b);
> -}
> -
> -__extension__ extern __inline int32x2_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqsub_s32 (int32x2_t __a, int32x2_t __b)
> -{
> -  return (int32x2_t) __builtin_aarch64_sssubv2si (__a, __b);
> -}
> -
> __extension__ extern __inline int64x1_t
> __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> vqsub_s64 (int64x1_t __a, int64x1_t __b)
> @@ -1463,27 +1344,6 @@ vqsub_s64 (int64x1_t __a, int64x1_t __b)
>   return (int64x1_t) {__builtin_aarch64_sssubdi (__a[0], __b[0])};
> }
> 
> -__extension__ extern __inline uint8x8_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqsub_u8 (uint8x8_t __a, uint8x8_t __b)
> -{
> -  return __builtin_aarch64_ussubv8qi_uuu (__a, __b);
> -}
> -
> -__extension__ extern __inline uint16x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqsub_u16 (uint16x4_t __a, uint16x4_t __b)
> -{
> -  return __builtin_aarch64_ussubv4hi_uuu (__a, __b);
> -}
> -
> -__extension__ extern __inline uint32x2_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqsub_u32 (uint32x2_t __a, uint32x2_t __b)
> -{
> -  return __builtin_aarch64_ussubv2si_uuu (__a, __b);
> -}
> -
> __extension__ extern __inline uint64x1_t
> __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> vqsub_u64 (uint64x1_t __a, uint64x1_t __b)
> @@ -1491,62 +1351,6 @@ vqsub_u64 (uint64x1_t __a, uint64x1_t __b)
>   return (uint64x1_t) {__builtin_aarch64_ussubdi_uuu (__a[0], __b[0])};
> }
> 
> -__extension__ extern __inline int8x16_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqsubq_s8 (int8x16_t __a, int8x16_t __b)
> -{
> -  return (int8x16_t) __builtin_aarch64_sssubv16qi (__a, __b);
> -}
> -
> -__extension__ extern __inline int16x8_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqsubq_s16 (int16x8_t __a, int16x8_t __b)
> -{
> -  return (int16x8_t) __builtin_aarch64_sssubv8hi (__a, __b);
> -}
> -
> -__extension__ extern __inline int32x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqsubq_s32 (int32x4_t __a, int32x4_t __b)
> -{
> -  return (int32x4_t) __builtin_aarch64_sssubv4si (__a, __b);
> -}
> -
> -__extension__ extern __inline int64x2_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqsubq_s64 (int64x2_t __a, int64x2_t __b)
> -{
> -  return (int64x2_t) __builtin_aarch64_sssubv2di (__a, __b);
> -}
> -
> -__extension__ extern __inline uint8x16_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqsubq_u8 (uint8x16_t __a, uint8x16_t __b)
> -{
> -  return __builtin_aarch64_ussubv16qi_uuu (__a, __b);
> -}
> -
> -__extension__ extern __inline uint16x8_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqsubq_u16 (uint16x8_t __a, uint16x8_t __b)
> -{
> -  return __builtin_aarch64_ussubv8hi_uuu (__a, __b);
> -}
> -
> -__extension__ extern __inline uint32x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqsubq_u32 (uint32x4_t __a, uint32x4_t __b)
> -{
> -  return __builtin_aarch64_ussubv4si_uuu (__a, __b);
> -}
> -
> -__extension__ extern __inline uint64x2_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqsubq_u64 (uint64x2_t __a, uint64x2_t __b)
> -{
> -  return __builtin_aarch64_ussubv2di_uuu (__a, __b);
> -}
> -
> __extension__ extern __inline int8x8_t
> __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> vqneg_s8 (int8x8_t __a)
> @@ -13921,64 +13725,6 @@ vqabsd_s64 (int64_t __a)
>   return __builtin_aarch64_sqabsdi (__a);
> }
> 
> -/* vqadd */
> -
> -__extension__ extern __inline int8_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqaddb_s8 (int8_t __a, int8_t __b)
> -{
> -  return (int8_t) __builtin_aarch64_ssaddqi (__a, __b);
> -}
> -
> -__extension__ extern __inline int16_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqaddh_s16 (int16_t __a, int16_t __b)
> -{
> -  return (int16_t) __builtin_aarch64_ssaddhi (__a, __b);
> -}
> -
> -__extension__ extern __inline int32_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqadds_s32 (int32_t __a, int32_t __b)
> -{
> -  return (int32_t) __builtin_aarch64_ssaddsi (__a, __b);
> -}
> -
> -__extension__ extern __inline int64_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqaddd_s64 (int64_t __a, int64_t __b)
> -{
> -  return __builtin_aarch64_ssadddi (__a, __b);
> -}
> -
> -__extension__ extern __inline uint8_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqaddb_u8 (uint8_t __a, uint8_t __b)
> -{
> -  return (uint8_t) __builtin_aarch64_usaddqi_uuu (__a, __b);
> -}
> -
> -__extension__ extern __inline uint16_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqaddh_u16 (uint16_t __a, uint16_t __b)
> -{
> -  return (uint16_t) __builtin_aarch64_usaddhi_uuu (__a, __b);
> -}
> -
> -__extension__ extern __inline uint32_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqadds_u32 (uint32_t __a, uint32_t __b)
> -{
> -  return (uint32_t) __builtin_aarch64_usaddsi_uuu (__a, __b);
> -}
> -
> -__extension__ extern __inline uint64_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqaddd_u64 (uint64_t __a, uint64_t __b)
> -{
> -  return __builtin_aarch64_usadddi_uuu (__a, __b);
> -}
> -
> /* vqdmlal */
> 
> __extension__ extern __inline int32x4_t
> @@ -15620,64 +15366,6 @@ vqshrund_n_s64 (int64_t __a, const int __b)
>   return (int32_t) __builtin_aarch64_sqshrun_ndi (__a, __b);
> }
> 
> -/* vqsub */
> -
> -__extension__ extern __inline int8_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqsubb_s8 (int8_t __a, int8_t __b)
> -{
> -  return (int8_t) __builtin_aarch64_sssubqi (__a, __b);
> -}
> -
> -__extension__ extern __inline int16_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqsubh_s16 (int16_t __a, int16_t __b)
> -{
> -  return (int16_t) __builtin_aarch64_sssubhi (__a, __b);
> -}
> -
> -__extension__ extern __inline int32_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqsubs_s32 (int32_t __a, int32_t __b)
> -{
> -  return (int32_t) __builtin_aarch64_sssubsi (__a, __b);
> -}
> -
> -__extension__ extern __inline int64_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqsubd_s64 (int64_t __a, int64_t __b)
> -{
> -  return __builtin_aarch64_sssubdi (__a, __b);
> -}
> -
> -__extension__ extern __inline uint8_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqsubb_u8 (uint8_t __a, uint8_t __b)
> -{
> -  return (uint8_t) __builtin_aarch64_ussubqi_uuu (__a, __b);
> -}
> -
> -__extension__ extern __inline uint16_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqsubh_u16 (uint16_t __a, uint16_t __b)
> -{
> -  return (uint16_t) __builtin_aarch64_ussubhi_uuu (__a, __b);
> -}
> -
> -__extension__ extern __inline uint32_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqsubs_u32 (uint32_t __a, uint32_t __b)
> -{
> -  return (uint32_t) __builtin_aarch64_ussubsi_uuu (__a, __b);
> -}
> -
> -__extension__ extern __inline uint64_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vqsubd_u64 (uint64_t __a, uint64_t __b)
> -{
> -  return __builtin_aarch64_ussubdi_uuu (__a, __b);
> -}
> -
> /* vqtbl2 */
> 
> __extension__ extern __inline int8x8_t
> diff --git a/gcc/testsuite/gcc.target/aarch64/neon/vqadd.c b/gcc/testsuite/gcc.target/aarch64/neon/vqadd.c
> new file mode 100644
> index 00000000000..322f54c5a42
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/neon/vqadd.c
> @@ -0,0 +1,192 @@
> +/* { dg-do compile } */
> +/* { dg-final { check-function-bodies "**" "" } } */
> +
> +#include "arm_neon_test.h"
> +
> +/*
> +** test_vqadd_u8:
> +** uqadd v0\.8b, (v0\.8b, v1\.8b|v1\.8b, v0\.8b)
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqadd_u8, uint8x8_t)
> +
> +/*
> +** test_vqadd_s8:
> +** sqadd v0\.8b, (v0\.8b, v1\.8b|v1\.8b, v0\.8b)
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqadd_s8, int8x8_t)
> +
> +/*
> +** test_vqadd_u16:
> +** uqadd v0\.4h, (v0\.4h, v1\.4h|v1\.4h, v0\.4h)
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqadd_u16, uint16x4_t)
> +
> +/*
> +** test_vqadd_s16:
> +** sqadd v0\.4h, (v0\.4h, v1\.4h|v1\.4h, v0\.4h)
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqadd_s16, int16x4_t)
> +
> +/*
> +** test_vqadd_u32:
> +** uqadd v0\.2s, (v0\.2s, v1\.2s|v1\.2s, v0\.2s)
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqadd_u32, uint32x2_t)
> +
> +/*
> +** test_vqadd_s32:
> +** sqadd v0\.2s, (v0\.2s, v1\.2s|v1\.2s, v0\.2s)
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqadd_s32, int32x2_t)
> +
> +/*
> +** test_vqadd_u64:
> +** uqadd d0, (d0, d1|d1, d0)
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqadd_u64, uint64x1_t)
> +
> +/*
> +** test_vqadd_s64:
> +** sqadd d0, (d0, d1|d1, d0)
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqadd_s64, int64x1_t)
> +
> +/*
> +** test_vqaddq_u8:
> +** uqadd v0\.16b, (v0\.16b, v1\.16b|v1\.16b, v0\.16b)
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqaddq_u8, uint8x16_t)
> +
> +/*
> +** test_vqaddq_s8:
> +** sqadd v0\.16b, (v0\.16b, v1\.16b|v1\.16b, v0\.16b)
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqaddq_s8, int8x16_t)
> +
> +/*
> +** test_vqaddq_u16:
> +** uqadd v0\.8h, (v0\.8h, v1\.8h|v1\.8h, v0\.8h)
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqaddq_u16, uint16x8_t)
> +
> +/*
> +** test_vqaddq_s16:
> +** sqadd v0\.8h, (v0\.8h, v1\.8h|v1\.8h, v0\.8h)
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqaddq_s16, int16x8_t)
> +
> +/*
> +** test_vqaddq_u32:
> +** uqadd v0\.4s, (v0\.4s, v1\.4s|v1\.4s, v0\.4s)
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqaddq_u32, uint32x4_t)
> +
> +/*
> +** test_vqaddq_s32:
> +** sqadd v0\.4s, (v0\.4s, v1\.4s|v1\.4s, v0\.4s)
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqaddq_s32, int32x4_t)
> +
> +/*
> +** test_vqaddq_u64:
> +** uqadd v0\.2d, (v0\.2d, v1\.2d|v1\.2d, v0\.2d)
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqaddq_u64, uint64x2_t)
> +
> +/*
> +** test_vqaddq_s64:
> +** sqadd v0\.2d, (v0\.2d, v1\.2d|v1\.2d, v0\.2d)
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqaddq_s64, int64x2_t)
> +
> +/*
> +** test_vqaddb_u8:
> +** dup v([0-9]+)\.8b, w[0-9]+
> +** dup v([0-9]+)\.8b, w[0-9]+
> +** uqadd b([0-9]+), (b\2, b\1|b\1, b\2)
> +** umov w0, v\3\.b\[0\]
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqaddb_u8, uint8_t)
> +
> +/*
> +** test_vqaddb_s8:
> +** dup v([0-9]+)\.8b, w[0-9]+
> +** dup v([0-9]+)\.8b, w[0-9]+
> +** sqadd b([0-9]+), (b\2, b\1|b\1, b\2)
> +** umov w0, v\3\.b\[0\]
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqaddb_s8, int8_t)
> +
> +/*
> +** test_vqaddh_u16:
> +** dup v([0-9]+)\.4h, w[0-9]+
> +** dup v([0-9]+)\.4h, w[0-9]+
> +** uqadd h([0-9]+), (h\2, h\1|h\1, h\2)
> +** umov w0, v\3\.h\[0\]
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqaddh_u16, uint16_t)
> +
> +/*
> +** test_vqaddh_s16:
> +** dup v([0-9]+)\.4h, w[0-9]+
> +** dup v([0-9]+)\.4h, w[0-9]+
> +** sqadd h([0-9]+), (h\2, h\1|h\1, h\2)
> +** umov w0, v\3\.h\[0\]
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqaddh_s16, int16_t)
> +
> +/*
> +** test_vqadds_u32:
> +** adds (w[0-9]+), (w0, w1|w1, w0)
> +** csinv w0, \1, wzr, cc
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqadds_u32, uint32_t)
> +
> +/*
> +** test_vqadds_s32:
> +** fmov (s[0-9]+), w[0-9]+
> +** fmov (s[0-9]+), w[0-9]+
> +** sqadd s([0-9]+), (\2, \1|\1, \2)
> +** fmov w0, s\3
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqadds_s32, int32_t)
> +
> +/*
> +** test_vqaddd_u64:
> +** adds (x[0-9]+), (x0, x1|x1, x0)
> +** csinv x0, \1, xzr, cc
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqaddd_u64, uint64_t)
> +
> +/*
> +** test_vqaddd_s64:
> +** fmov (d[0-9]+), x[0-9]+
> +** fmov (d[0-9]+), x[0-9]+
> +** sqadd d([0-9]+), (\2, \1|\1, \2)
> +** fmov x0, d\3
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqaddd_s64, int64_t)
> diff --git a/gcc/testsuite/gcc.target/aarch64/neon/vqsub.c b/gcc/testsuite/gcc.target/aarch64/neon/vqsub.c
> new file mode 100644
> index 00000000000..52ac2f102eb
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/neon/vqsub.c
> @@ -0,0 +1,192 @@
> +/* { dg-do compile } */
> +/* { dg-final { check-function-bodies "**" "" } } */
> +
> +#include "arm_neon_test.h"
> +
> +/*
> +** test_vqsub_u8:
> +** uqsub v0\.8b, v0\.8b, v1\.8b
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqsub_u8, uint8x8_t)
> +
> +/*
> +** test_vqsub_s8:
> +** sqsub v0\.8b, v0\.8b, v1\.8b
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqsub_s8, int8x8_t)
> +
> +/*
> +** test_vqsub_u16:
> +** uqsub v0\.4h, v0\.4h, v1\.4h
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqsub_u16, uint16x4_t)
> +
> +/*
> +** test_vqsub_s16:
> +** sqsub v0\.4h, v0\.4h, v1\.4h
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqsub_s16, int16x4_t)
> +
> +/*
> +** test_vqsub_u32:
> +** uqsub v0\.2s, v0\.2s, v1\.2s
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqsub_u32, uint32x2_t)
> +
> +/*
> +** test_vqsub_s32:
> +** sqsub v0\.2s, v0\.2s, v1\.2s
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqsub_s32, int32x2_t)
> +
> +/*
> +** test_vqsub_u64:
> +** uqsub d0, d0, d1
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqsub_u64, uint64x1_t)
> +
> +/*
> +** test_vqsub_s64:
> +** sqsub d0, d0, d1
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqsub_s64, int64x1_t)
> +
> +/*
> +** test_vqsubq_u8:
> +** uqsub v0\.16b, v0\.16b, v1\.16b
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqsubq_u8, uint8x16_t)
> +
> +/*
> +** test_vqsubq_s8:
> +** sqsub v0\.16b, v0\.16b, v1\.16b
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqsubq_s8, int8x16_t)
> +
> +/*
> +** test_vqsubq_u16:
> +** uqsub v0\.8h, v0\.8h, v1\.8h
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqsubq_u16, uint16x8_t)
> +
> +/*
> +** test_vqsubq_s16:
> +** sqsub v0\.8h, v0\.8h, v1\.8h
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqsubq_s16, int16x8_t)
> +
> +/*
> +** test_vqsubq_u32:
> +** uqsub v0\.4s, v0\.4s, v1\.4s
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqsubq_u32, uint32x4_t)
> +
> +/*
> +** test_vqsubq_s32:
> +** sqsub v0\.4s, v0\.4s, v1\.4s
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqsubq_s32, int32x4_t)
> +
> +/*
> +** test_vqsubq_u64:
> +** uqsub v0\.2d, v0\.2d, v1\.2d
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqsubq_u64, uint64x2_t)
> +
> +/*
> +** test_vqsubq_s64:
> +** sqsub v0\.2d, v0\.2d, v1\.2d
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqsubq_s64, int64x2_t)
> +
> +/*
> +** test_vqsubb_u8:
> +** dup v([0-9]+)\.8b, w0
> +** dup v([0-9]+)\.8b, w1
> +** uqsub b([0-9]+), b\1, b\2
> +** umov w0, v\3\.b\[0\]
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqsubb_u8, uint8_t)
> +
> +/*
> +** test_vqsubb_s8:
> +** dup v([0-9]+)\.8b, w0
> +** dup v([0-9]+)\.8b, w1
> +** sqsub b([0-9]+), b\1, b\2
> +** umov w0, v\3\.b\[0\]
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqsubb_s8, int8_t)
> +
> +/*
> +** test_vqsubh_u16:
> +** dup v([0-9]+)\.4h, w0
> +** dup v([0-9]+)\.4h, w1
> +** uqsub h([0-9]+), h\1, h\2
> +** umov w0, v\3\.h\[0\]
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqsubh_u16, uint16_t)
> +
> +/*
> +** test_vqsubh_s16:
> +** dup v([0-9]+)\.4h, w0
> +** dup v([0-9]+)\.4h, w1
> +** sqsub h([0-9]+), h\1, h\2
> +** umov w0, v\3\.h\[0\]
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqsubh_s16, int16_t)
> +
> +/*
> +** test_vqsubs_u32:
> +** subs (w[0-9]+), w0, w1
> +** csel w0, \1, wzr, cs
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqsubs_u32, uint32_t)
> +
> +/*
> +** test_vqsubs_s32:
> +** fmov (s[0-9]+), w0
> +** fmov (s[0-9]+), w1
> +** sqsub s([0-9]+), \1, \2
> +** fmov w0, s\3
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqsubs_s32, int32_t)
> +
> +/*
> +** test_vqsubd_u64:
> +** subs (x[0-9]+), x0, x1
> +** csel x0, \1, xzr, cs
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqsubd_u64, uint64_t)
> +
> +/*
> +** test_vqsubd_s64:
> +** fmov (d[0-9]+), x0
> +** fmov (d[0-9]+), x1
> +** sqsub d([0-9]+), \1, \2
> +** fmov x0, d\3
> +** ret
> +*/
> +TEST_UNIFORM_BINARY (vqsubd_s64, int64_t)
> -- 
> 2.43.0
>
  

Patch

diff --git a/gcc/config/aarch64/aarch64-neon-builtins-base.cc b/gcc/config/aarch64/aarch64-neon-builtins-base.cc
index d8fae81388e..5c886d32f42 100644
--- a/gcc/config/aarch64/aarch64-neon-builtins-base.cc
+++ b/gcc/config/aarch64/aarch64-neon-builtins-base.cc
@@ -753,6 +753,20 @@  NEON_FUNCTION (vaddd, gimple_expr, (PLUS_EXPR))
 NEON_FUNCTION (vadd,  gimple_expr, (PLUS_EXPR, PLUS_EXPR, BIT_XOR_EXPR))
 NEON_FUNCTION (vaddq, gimple_expr, (PLUS_EXPR, PLUS_EXPR, BIT_XOR_EXPR))
 
+// Saturating arithmetic
+NEON_FUNCTION (vqaddb, gimple_ifn, (IFN_SAT_ADD))
+NEON_FUNCTION (vqaddh, gimple_ifn, (IFN_SAT_ADD))
+NEON_FUNCTION (vqadds, gimple_ifn, (IFN_SAT_ADD))
+NEON_FUNCTION (vqaddd, gimple_ifn, (IFN_SAT_ADD))
+NEON_FUNCTION (vqadd,  gimple_ifn, (IFN_SAT_ADD))
+NEON_FUNCTION (vqaddq, gimple_ifn, (IFN_SAT_ADD))
+NEON_FUNCTION (vqsubb, gimple_ifn, (IFN_SAT_SUB))
+NEON_FUNCTION (vqsubh, gimple_ifn, (IFN_SAT_SUB))
+NEON_FUNCTION (vqsubs, gimple_ifn, (IFN_SAT_SUB))
+NEON_FUNCTION (vqsubd, gimple_ifn, (IFN_SAT_SUB))
+NEON_FUNCTION (vqsub,  gimple_ifn, (IFN_SAT_SUB))
+NEON_FUNCTION (vqsubq, gimple_ifn, (IFN_SAT_SUB))
+
 // Bitwise operations
 NEON_FUNCTION (vand,   gimple_expr,    (BIT_AND_EXPR))
 NEON_FUNCTION (vandq,  gimple_expr,    (BIT_AND_EXPR))
diff --git a/gcc/config/aarch64/aarch64-neon-builtins-base.def b/gcc/config/aarch64/aarch64-neon-builtins-base.def
index 7257f59bbc5..52e4746453b 100644
--- a/gcc/config/aarch64/aarch64-neon-builtins-base.def
+++ b/gcc/config/aarch64/aarch64-neon-builtins-base.def
@@ -76,6 +76,22 @@  DEF_NEON_FUNCTION (vadd,  h_float, ("D0,D0,D0"))
 DEF_NEON_FUNCTION (vaddq, h_float, ("Q0,Q0,Q0"))
 #undef REQUIRED_EXTENSIONS
 
+// Saturating arithmetic
+#define REQUIRED_EXTENSIONS nonstreaming_only (AARCH64_FL_SIMD)
+DEF_NEON_FUNCTION (vqaddb, b_integer,   ("s0,s0,s0"))
+DEF_NEON_FUNCTION (vqaddh, h_integer,   ("s0,s0,s0"))
+DEF_NEON_FUNCTION (vqadds, s_integer,   ("s0,s0,s0"))
+DEF_NEON_FUNCTION (vqaddd, d_integer,   ("s0,s0,s0"))
+DEF_NEON_FUNCTION (vqadd,  bhs_integer, ("D0,D0,D0"))
+DEF_NEON_FUNCTION (vqaddq, all_integer, ("Q0,Q0,Q0"))
+DEF_NEON_FUNCTION (vqsubb, b_integer,   ("s0,s0,s0"))
+DEF_NEON_FUNCTION (vqsubh, h_integer,   ("s0,s0,s0"))
+DEF_NEON_FUNCTION (vqsubs, s_integer,   ("s0,s0,s0"))
+DEF_NEON_FUNCTION (vqsubd, d_integer,   ("s0,s0,s0"))
+DEF_NEON_FUNCTION (vqsub,  bhs_integer, ("D0,D0,D0"))
+DEF_NEON_FUNCTION (vqsubq, all_integer, ("Q0,Q0,Q0"))
+#undef REQUIRED_EXTENSIONS
+
 // Bitwise operations
 #define REQUIRED_EXTENSIONS nonstreaming_only (AARCH64_FL_SIMD)
 DEF_NEON_FUNCTION (vand,   all_integer, ("D0,D0,D0"))
diff --git a/gcc/config/aarch64/arm_neon.h b/gcc/config/aarch64/arm_neon.h
index 873a1195d3e..985b4bdb6cc 100644
--- a/gcc/config/aarch64/arm_neon.h
+++ b/gcc/config/aarch64/arm_neon.h
@@ -1071,41 +1071,6 @@  vsubw_high_u32 (uint64x2_t __a, uint32x4_t __b)
   return __builtin_aarch64_usubw2v4si_uuu (__a, __b);
 }
 
-__extension__ extern __inline int8x8_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqadd_s8 (int8x8_t __a, int8x8_t __b)
-{
-  return (int8x8_t) __builtin_aarch64_ssaddv8qi (__a, __b);
-}
-
-__extension__ extern __inline int16x4_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqadd_s16 (int16x4_t __a, int16x4_t __b)
-{
-  return (int16x4_t) __builtin_aarch64_ssaddv4hi (__a, __b);
-}
-
-__extension__ extern __inline int32x2_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqadd_s32 (int32x2_t __a, int32x2_t __b)
-{
-  return (int32x2_t) __builtin_aarch64_ssaddv2si (__a, __b);
-}
-
-__extension__ extern __inline int64x1_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqadd_s64 (int64x1_t __a, int64x1_t __b)
-{
-  return (int64x1_t) {__builtin_aarch64_ssadddi (__a[0], __b[0])};
-}
-
-__extension__ extern __inline uint8x8_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqadd_u8 (uint8x8_t __a, uint8x8_t __b)
-{
-  return __builtin_aarch64_usaddv8qi_uuu (__a, __b);
-}
-
 __extension__ extern __inline int8x8_t
 __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
 vhsub_s8 (int8x8_t __a, int8x8_t __b)
@@ -1358,18 +1323,11 @@  vsubhn_high_u64 (uint32x2_t __a, uint64x2_t __b, uint64x2_t __c)
   return __builtin_aarch64_subhn2v2di_uuuu (__a, __b, __c);
 }
 
-__extension__ extern __inline uint16x4_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqadd_u16 (uint16x4_t __a, uint16x4_t __b)
-{
-  return __builtin_aarch64_usaddv4hi_uuu (__a, __b);
-}
-
-__extension__ extern __inline uint32x2_t
+__extension__ extern __inline int64x1_t
 __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqadd_u32 (uint32x2_t __a, uint32x2_t __b)
+vqadd_s64 (int64x1_t __a, int64x1_t __b)
 {
-  return __builtin_aarch64_usaddv2si_uuu (__a, __b);
+  return (int64x1_t) {__builtin_aarch64_ssadddi (__a[0], __b[0])};
 }
 
 __extension__ extern __inline uint64x1_t
@@ -1379,83 +1337,6 @@  vqadd_u64 (uint64x1_t __a, uint64x1_t __b)
   return (uint64x1_t) {__builtin_aarch64_usadddi_uuu (__a[0], __b[0])};
 }
 
-__extension__ extern __inline int8x16_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqaddq_s8 (int8x16_t __a, int8x16_t __b)
-{
-  return (int8x16_t) __builtin_aarch64_ssaddv16qi (__a, __b);
-}
-
-__extension__ extern __inline int16x8_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqaddq_s16 (int16x8_t __a, int16x8_t __b)
-{
-  return (int16x8_t) __builtin_aarch64_ssaddv8hi (__a, __b);
-}
-
-__extension__ extern __inline int32x4_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqaddq_s32 (int32x4_t __a, int32x4_t __b)
-{
-  return (int32x4_t) __builtin_aarch64_ssaddv4si (__a, __b);
-}
-
-__extension__ extern __inline int64x2_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqaddq_s64 (int64x2_t __a, int64x2_t __b)
-{
-  return (int64x2_t) __builtin_aarch64_ssaddv2di (__a, __b);
-}
-
-__extension__ extern __inline uint8x16_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqaddq_u8 (uint8x16_t __a, uint8x16_t __b)
-{
-  return __builtin_aarch64_usaddv16qi_uuu (__a, __b);
-}
-
-__extension__ extern __inline uint16x8_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqaddq_u16 (uint16x8_t __a, uint16x8_t __b)
-{
-  return __builtin_aarch64_usaddv8hi_uuu (__a, __b);
-}
-
-__extension__ extern __inline uint32x4_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqaddq_u32 (uint32x4_t __a, uint32x4_t __b)
-{
-  return __builtin_aarch64_usaddv4si_uuu (__a, __b);
-}
-
-__extension__ extern __inline uint64x2_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqaddq_u64 (uint64x2_t __a, uint64x2_t __b)
-{
-  return __builtin_aarch64_usaddv2di_uuu (__a, __b);
-}
-
-__extension__ extern __inline int8x8_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqsub_s8 (int8x8_t __a, int8x8_t __b)
-{
-  return (int8x8_t) __builtin_aarch64_sssubv8qi (__a, __b);
-}
-
-__extension__ extern __inline int16x4_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqsub_s16 (int16x4_t __a, int16x4_t __b)
-{
-  return (int16x4_t) __builtin_aarch64_sssubv4hi (__a, __b);
-}
-
-__extension__ extern __inline int32x2_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqsub_s32 (int32x2_t __a, int32x2_t __b)
-{
-  return (int32x2_t) __builtin_aarch64_sssubv2si (__a, __b);
-}
-
 __extension__ extern __inline int64x1_t
 __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
 vqsub_s64 (int64x1_t __a, int64x1_t __b)
@@ -1463,27 +1344,6 @@  vqsub_s64 (int64x1_t __a, int64x1_t __b)
   return (int64x1_t) {__builtin_aarch64_sssubdi (__a[0], __b[0])};
 }
 
-__extension__ extern __inline uint8x8_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqsub_u8 (uint8x8_t __a, uint8x8_t __b)
-{
-  return __builtin_aarch64_ussubv8qi_uuu (__a, __b);
-}
-
-__extension__ extern __inline uint16x4_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqsub_u16 (uint16x4_t __a, uint16x4_t __b)
-{
-  return __builtin_aarch64_ussubv4hi_uuu (__a, __b);
-}
-
-__extension__ extern __inline uint32x2_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqsub_u32 (uint32x2_t __a, uint32x2_t __b)
-{
-  return __builtin_aarch64_ussubv2si_uuu (__a, __b);
-}
-
 __extension__ extern __inline uint64x1_t
 __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
 vqsub_u64 (uint64x1_t __a, uint64x1_t __b)
@@ -1491,62 +1351,6 @@  vqsub_u64 (uint64x1_t __a, uint64x1_t __b)
   return (uint64x1_t) {__builtin_aarch64_ussubdi_uuu (__a[0], __b[0])};
 }
 
-__extension__ extern __inline int8x16_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqsubq_s8 (int8x16_t __a, int8x16_t __b)
-{
-  return (int8x16_t) __builtin_aarch64_sssubv16qi (__a, __b);
-}
-
-__extension__ extern __inline int16x8_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqsubq_s16 (int16x8_t __a, int16x8_t __b)
-{
-  return (int16x8_t) __builtin_aarch64_sssubv8hi (__a, __b);
-}
-
-__extension__ extern __inline int32x4_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqsubq_s32 (int32x4_t __a, int32x4_t __b)
-{
-  return (int32x4_t) __builtin_aarch64_sssubv4si (__a, __b);
-}
-
-__extension__ extern __inline int64x2_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqsubq_s64 (int64x2_t __a, int64x2_t __b)
-{
-  return (int64x2_t) __builtin_aarch64_sssubv2di (__a, __b);
-}
-
-__extension__ extern __inline uint8x16_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqsubq_u8 (uint8x16_t __a, uint8x16_t __b)
-{
-  return __builtin_aarch64_ussubv16qi_uuu (__a, __b);
-}
-
-__extension__ extern __inline uint16x8_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqsubq_u16 (uint16x8_t __a, uint16x8_t __b)
-{
-  return __builtin_aarch64_ussubv8hi_uuu (__a, __b);
-}
-
-__extension__ extern __inline uint32x4_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqsubq_u32 (uint32x4_t __a, uint32x4_t __b)
-{
-  return __builtin_aarch64_ussubv4si_uuu (__a, __b);
-}
-
-__extension__ extern __inline uint64x2_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqsubq_u64 (uint64x2_t __a, uint64x2_t __b)
-{
-  return __builtin_aarch64_ussubv2di_uuu (__a, __b);
-}
-
 __extension__ extern __inline int8x8_t
 __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
 vqneg_s8 (int8x8_t __a)
@@ -13921,64 +13725,6 @@  vqabsd_s64 (int64_t __a)
   return __builtin_aarch64_sqabsdi (__a);
 }
 
-/* vqadd */
-
-__extension__ extern __inline int8_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqaddb_s8 (int8_t __a, int8_t __b)
-{
-  return (int8_t) __builtin_aarch64_ssaddqi (__a, __b);
-}
-
-__extension__ extern __inline int16_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqaddh_s16 (int16_t __a, int16_t __b)
-{
-  return (int16_t) __builtin_aarch64_ssaddhi (__a, __b);
-}
-
-__extension__ extern __inline int32_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqadds_s32 (int32_t __a, int32_t __b)
-{
-  return (int32_t) __builtin_aarch64_ssaddsi (__a, __b);
-}
-
-__extension__ extern __inline int64_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqaddd_s64 (int64_t __a, int64_t __b)
-{
-  return __builtin_aarch64_ssadddi (__a, __b);
-}
-
-__extension__ extern __inline uint8_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqaddb_u8 (uint8_t __a, uint8_t __b)
-{
-  return (uint8_t) __builtin_aarch64_usaddqi_uuu (__a, __b);
-}
-
-__extension__ extern __inline uint16_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqaddh_u16 (uint16_t __a, uint16_t __b)
-{
-  return (uint16_t) __builtin_aarch64_usaddhi_uuu (__a, __b);
-}
-
-__extension__ extern __inline uint32_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqadds_u32 (uint32_t __a, uint32_t __b)
-{
-  return (uint32_t) __builtin_aarch64_usaddsi_uuu (__a, __b);
-}
-
-__extension__ extern __inline uint64_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqaddd_u64 (uint64_t __a, uint64_t __b)
-{
-  return __builtin_aarch64_usadddi_uuu (__a, __b);
-}
-
 /* vqdmlal */
 
 __extension__ extern __inline int32x4_t
@@ -15620,64 +15366,6 @@  vqshrund_n_s64 (int64_t __a, const int __b)
   return (int32_t) __builtin_aarch64_sqshrun_ndi (__a, __b);
 }
 
-/* vqsub */
-
-__extension__ extern __inline int8_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqsubb_s8 (int8_t __a, int8_t __b)
-{
-  return (int8_t) __builtin_aarch64_sssubqi (__a, __b);
-}
-
-__extension__ extern __inline int16_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqsubh_s16 (int16_t __a, int16_t __b)
-{
-  return (int16_t) __builtin_aarch64_sssubhi (__a, __b);
-}
-
-__extension__ extern __inline int32_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqsubs_s32 (int32_t __a, int32_t __b)
-{
-  return (int32_t) __builtin_aarch64_sssubsi (__a, __b);
-}
-
-__extension__ extern __inline int64_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqsubd_s64 (int64_t __a, int64_t __b)
-{
-  return __builtin_aarch64_sssubdi (__a, __b);
-}
-
-__extension__ extern __inline uint8_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqsubb_u8 (uint8_t __a, uint8_t __b)
-{
-  return (uint8_t) __builtin_aarch64_ussubqi_uuu (__a, __b);
-}
-
-__extension__ extern __inline uint16_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqsubh_u16 (uint16_t __a, uint16_t __b)
-{
-  return (uint16_t) __builtin_aarch64_ussubhi_uuu (__a, __b);
-}
-
-__extension__ extern __inline uint32_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqsubs_u32 (uint32_t __a, uint32_t __b)
-{
-  return (uint32_t) __builtin_aarch64_ussubsi_uuu (__a, __b);
-}
-
-__extension__ extern __inline uint64_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqsubd_u64 (uint64_t __a, uint64_t __b)
-{
-  return __builtin_aarch64_ussubdi_uuu (__a, __b);
-}
-
 /* vqtbl2 */
 
 __extension__ extern __inline int8x8_t
diff --git a/gcc/testsuite/gcc.target/aarch64/neon/vqadd.c b/gcc/testsuite/gcc.target/aarch64/neon/vqadd.c
new file mode 100644
index 00000000000..322f54c5a42
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/neon/vqadd.c
@@ -0,0 +1,192 @@ 
+/* { dg-do compile } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "arm_neon_test.h"
+
+/*
+** test_vqadd_u8:
+** uqadd	v0\.8b, (v0\.8b, v1\.8b|v1\.8b, v0\.8b)
+** ret
+*/
+TEST_UNIFORM_BINARY (vqadd_u8, uint8x8_t)
+
+/*
+** test_vqadd_s8:
+** sqadd	v0\.8b, (v0\.8b, v1\.8b|v1\.8b, v0\.8b)
+** ret
+*/
+TEST_UNIFORM_BINARY (vqadd_s8, int8x8_t)
+
+/*
+** test_vqadd_u16:
+** uqadd	v0\.4h, (v0\.4h, v1\.4h|v1\.4h, v0\.4h)
+** ret
+*/
+TEST_UNIFORM_BINARY (vqadd_u16, uint16x4_t)
+
+/*
+** test_vqadd_s16:
+** sqadd	v0\.4h, (v0\.4h, v1\.4h|v1\.4h, v0\.4h)
+** ret
+*/
+TEST_UNIFORM_BINARY (vqadd_s16, int16x4_t)
+
+/*
+** test_vqadd_u32:
+** uqadd	v0\.2s, (v0\.2s, v1\.2s|v1\.2s, v0\.2s)
+** ret
+*/
+TEST_UNIFORM_BINARY (vqadd_u32, uint32x2_t)
+
+/*
+** test_vqadd_s32:
+** sqadd	v0\.2s, (v0\.2s, v1\.2s|v1\.2s, v0\.2s)
+** ret
+*/
+TEST_UNIFORM_BINARY (vqadd_s32, int32x2_t)
+
+/*
+** test_vqadd_u64:
+** uqadd	d0, (d0, d1|d1, d0)
+** ret
+*/
+TEST_UNIFORM_BINARY (vqadd_u64, uint64x1_t)
+
+/*
+** test_vqadd_s64:
+** sqadd	d0, (d0, d1|d1, d0)
+** ret
+*/
+TEST_UNIFORM_BINARY (vqadd_s64, int64x1_t)
+
+/*
+** test_vqaddq_u8:
+** uqadd	v0\.16b, (v0\.16b, v1\.16b|v1\.16b, v0\.16b)
+** ret
+*/
+TEST_UNIFORM_BINARY (vqaddq_u8, uint8x16_t)
+
+/*
+** test_vqaddq_s8:
+** sqadd	v0\.16b, (v0\.16b, v1\.16b|v1\.16b, v0\.16b)
+** ret
+*/
+TEST_UNIFORM_BINARY (vqaddq_s8, int8x16_t)
+
+/*
+** test_vqaddq_u16:
+** uqadd	v0\.8h, (v0\.8h, v1\.8h|v1\.8h, v0\.8h)
+** ret
+*/
+TEST_UNIFORM_BINARY (vqaddq_u16, uint16x8_t)
+
+/*
+** test_vqaddq_s16:
+** sqadd	v0\.8h, (v0\.8h, v1\.8h|v1\.8h, v0\.8h)
+** ret
+*/
+TEST_UNIFORM_BINARY (vqaddq_s16, int16x8_t)
+
+/*
+** test_vqaddq_u32:
+** uqadd	v0\.4s, (v0\.4s, v1\.4s|v1\.4s, v0\.4s)
+** ret
+*/
+TEST_UNIFORM_BINARY (vqaddq_u32, uint32x4_t)
+
+/*
+** test_vqaddq_s32:
+** sqadd	v0\.4s, (v0\.4s, v1\.4s|v1\.4s, v0\.4s)
+** ret
+*/
+TEST_UNIFORM_BINARY (vqaddq_s32, int32x4_t)
+
+/*
+** test_vqaddq_u64:
+** uqadd	v0\.2d, (v0\.2d, v1\.2d|v1\.2d, v0\.2d)
+** ret
+*/
+TEST_UNIFORM_BINARY (vqaddq_u64, uint64x2_t)
+
+/*
+** test_vqaddq_s64:
+** sqadd	v0\.2d, (v0\.2d, v1\.2d|v1\.2d, v0\.2d)
+** ret
+*/
+TEST_UNIFORM_BINARY (vqaddq_s64, int64x2_t)
+
+/*
+** test_vqaddb_u8:
+** dup	v([0-9]+)\.8b, w[0-9]+
+** dup	v([0-9]+)\.8b, w[0-9]+
+** uqadd	b([0-9]+), (b\2, b\1|b\1, b\2)
+** umov	w0, v\3\.b\[0\]
+** ret
+*/
+TEST_UNIFORM_BINARY (vqaddb_u8, uint8_t)
+
+/*
+** test_vqaddb_s8:
+** dup	v([0-9]+)\.8b, w[0-9]+
+** dup	v([0-9]+)\.8b, w[0-9]+
+** sqadd	b([0-9]+), (b\2, b\1|b\1, b\2)
+** umov	w0, v\3\.b\[0\]
+** ret
+*/
+TEST_UNIFORM_BINARY (vqaddb_s8, int8_t)
+
+/*
+** test_vqaddh_u16:
+** dup	v([0-9]+)\.4h, w[0-9]+
+** dup	v([0-9]+)\.4h, w[0-9]+
+** uqadd	h([0-9]+), (h\2, h\1|h\1, h\2)
+** umov	w0, v\3\.h\[0\]
+** ret
+*/
+TEST_UNIFORM_BINARY (vqaddh_u16, uint16_t)
+
+/*
+** test_vqaddh_s16:
+** dup	v([0-9]+)\.4h, w[0-9]+
+** dup	v([0-9]+)\.4h, w[0-9]+
+** sqadd	h([0-9]+), (h\2, h\1|h\1, h\2)
+** umov	w0, v\3\.h\[0\]
+** ret
+*/
+TEST_UNIFORM_BINARY (vqaddh_s16, int16_t)
+
+/*
+** test_vqadds_u32:
+** adds	(w[0-9]+), (w0, w1|w1, w0)
+** csinv	w0, \1, wzr, cc
+** ret
+*/
+TEST_UNIFORM_BINARY (vqadds_u32, uint32_t)
+
+/*
+** test_vqadds_s32:
+** fmov	(s[0-9]+), w[0-9]+
+** fmov	(s[0-9]+), w[0-9]+
+** sqadd	s([0-9]+), (\2, \1|\1, \2)
+** fmov	w0, s\3
+** ret
+*/
+TEST_UNIFORM_BINARY (vqadds_s32, int32_t)
+
+/*
+** test_vqaddd_u64:
+** adds	(x[0-9]+), (x0, x1|x1, x0)
+** csinv	x0, \1, xzr, cc
+** ret
+*/
+TEST_UNIFORM_BINARY (vqaddd_u64, uint64_t)
+
+/*
+** test_vqaddd_s64:
+** fmov	(d[0-9]+), x[0-9]+
+** fmov	(d[0-9]+), x[0-9]+
+** sqadd	d([0-9]+), (\2, \1|\1, \2)
+** fmov	x0, d\3
+** ret
+*/
+TEST_UNIFORM_BINARY (vqaddd_s64, int64_t)
diff --git a/gcc/testsuite/gcc.target/aarch64/neon/vqsub.c b/gcc/testsuite/gcc.target/aarch64/neon/vqsub.c
new file mode 100644
index 00000000000..52ac2f102eb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/neon/vqsub.c
@@ -0,0 +1,192 @@ 
+/* { dg-do compile } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "arm_neon_test.h"
+
+/*
+** test_vqsub_u8:
+** uqsub	v0\.8b, v0\.8b, v1\.8b
+** ret
+*/
+TEST_UNIFORM_BINARY (vqsub_u8, uint8x8_t)
+
+/*
+** test_vqsub_s8:
+** sqsub	v0\.8b, v0\.8b, v1\.8b
+** ret
+*/
+TEST_UNIFORM_BINARY (vqsub_s8, int8x8_t)
+
+/*
+** test_vqsub_u16:
+** uqsub	v0\.4h, v0\.4h, v1\.4h
+** ret
+*/
+TEST_UNIFORM_BINARY (vqsub_u16, uint16x4_t)
+
+/*
+** test_vqsub_s16:
+** sqsub	v0\.4h, v0\.4h, v1\.4h
+** ret
+*/
+TEST_UNIFORM_BINARY (vqsub_s16, int16x4_t)
+
+/*
+** test_vqsub_u32:
+** uqsub	v0\.2s, v0\.2s, v1\.2s
+** ret
+*/
+TEST_UNIFORM_BINARY (vqsub_u32, uint32x2_t)
+
+/*
+** test_vqsub_s32:
+** sqsub	v0\.2s, v0\.2s, v1\.2s
+** ret
+*/
+TEST_UNIFORM_BINARY (vqsub_s32, int32x2_t)
+
+/*
+** test_vqsub_u64:
+** uqsub	d0, d0, d1
+** ret
+*/
+TEST_UNIFORM_BINARY (vqsub_u64, uint64x1_t)
+
+/*
+** test_vqsub_s64:
+** sqsub	d0, d0, d1
+** ret
+*/
+TEST_UNIFORM_BINARY (vqsub_s64, int64x1_t)
+
+/*
+** test_vqsubq_u8:
+** uqsub	v0\.16b, v0\.16b, v1\.16b
+** ret
+*/
+TEST_UNIFORM_BINARY (vqsubq_u8, uint8x16_t)
+
+/*
+** test_vqsubq_s8:
+** sqsub	v0\.16b, v0\.16b, v1\.16b
+** ret
+*/
+TEST_UNIFORM_BINARY (vqsubq_s8, int8x16_t)
+
+/*
+** test_vqsubq_u16:
+** uqsub	v0\.8h, v0\.8h, v1\.8h
+** ret
+*/
+TEST_UNIFORM_BINARY (vqsubq_u16, uint16x8_t)
+
+/*
+** test_vqsubq_s16:
+** sqsub	v0\.8h, v0\.8h, v1\.8h
+** ret
+*/
+TEST_UNIFORM_BINARY (vqsubq_s16, int16x8_t)
+
+/*
+** test_vqsubq_u32:
+** uqsub	v0\.4s, v0\.4s, v1\.4s
+** ret
+*/
+TEST_UNIFORM_BINARY (vqsubq_u32, uint32x4_t)
+
+/*
+** test_vqsubq_s32:
+** sqsub	v0\.4s, v0\.4s, v1\.4s
+** ret
+*/
+TEST_UNIFORM_BINARY (vqsubq_s32, int32x4_t)
+
+/*
+** test_vqsubq_u64:
+** uqsub	v0\.2d, v0\.2d, v1\.2d
+** ret
+*/
+TEST_UNIFORM_BINARY (vqsubq_u64, uint64x2_t)
+
+/*
+** test_vqsubq_s64:
+** sqsub	v0\.2d, v0\.2d, v1\.2d
+** ret
+*/
+TEST_UNIFORM_BINARY (vqsubq_s64, int64x2_t)
+
+/*
+** test_vqsubb_u8:
+** dup	v([0-9]+)\.8b, w0
+** dup	v([0-9]+)\.8b, w1
+** uqsub	b([0-9]+), b\1, b\2
+** umov	w0, v\3\.b\[0\]
+** ret
+*/
+TEST_UNIFORM_BINARY (vqsubb_u8, uint8_t)
+
+/*
+** test_vqsubb_s8:
+** dup	v([0-9]+)\.8b, w0
+** dup	v([0-9]+)\.8b, w1
+** sqsub	b([0-9]+), b\1, b\2
+** umov	w0, v\3\.b\[0\]
+** ret
+*/
+TEST_UNIFORM_BINARY (vqsubb_s8, int8_t)
+
+/*
+** test_vqsubh_u16:
+** dup	v([0-9]+)\.4h, w0
+** dup	v([0-9]+)\.4h, w1
+** uqsub	h([0-9]+), h\1, h\2
+** umov	w0, v\3\.h\[0\]
+** ret
+*/
+TEST_UNIFORM_BINARY (vqsubh_u16, uint16_t)
+
+/*
+** test_vqsubh_s16:
+** dup	v([0-9]+)\.4h, w0
+** dup	v([0-9]+)\.4h, w1
+** sqsub	h([0-9]+), h\1, h\2
+** umov	w0, v\3\.h\[0\]
+** ret
+*/
+TEST_UNIFORM_BINARY (vqsubh_s16, int16_t)
+
+/*
+** test_vqsubs_u32:
+** subs	(w[0-9]+), w0, w1
+** csel	w0, \1, wzr, cs
+** ret
+*/
+TEST_UNIFORM_BINARY (vqsubs_u32, uint32_t)
+
+/*
+** test_vqsubs_s32:
+** fmov	(s[0-9]+), w0
+** fmov	(s[0-9]+), w1
+** sqsub	s([0-9]+), \1, \2
+** fmov	w0, s\3
+** ret
+*/
+TEST_UNIFORM_BINARY (vqsubs_s32, int32_t)
+
+/*
+** test_vqsubd_u64:
+** subs	(x[0-9]+), x0, x1
+** csel	x0, \1, xzr, cs
+** ret
+*/
+TEST_UNIFORM_BINARY (vqsubd_u64, uint64_t)
+
+/*
+** test_vqsubd_s64:
+** fmov	(d[0-9]+), x0
+** fmov	(d[0-9]+), x1
+** sqsub	d([0-9]+), \1, \2
+** fmov	x0, d\3
+** ret
+*/
+TEST_UNIFORM_BINARY (vqsubd_s64, int64_t)