https://gcc.gnu.org/g:4cb381957ca6240956cf07bcc8d53b9dfe125b13

commit r17-4912-g4cb381957ca6240956cf07bcc8d53b9dfe125b13
Author: Dhruv Chawla <[email protected]>
Date:   Mon Aug 24 06:26:00 2026 +0000

    aarch64: Port NEON saturating add/sub intrinsics to pragma-based framework
    
    Port the following intrinsics to the pragma-based framework:
    * vqadd
    * vqsub
    
    Plus their scalar variants: vq{add,sub}{b,h,s,d}.
    
    This patch also modifies the gimple_ifn handler class to automatically
    convert intrinsics for V1XX modes (like V1DI and V1DF) to and from XX
    (i.e. DI and DF) modes to reuse the existing scalar patterns. There
    is no impact on codegen quality. Note that this matches the existing
    behaviour in arm_neon.h where the scalar intrinsics are used and cast back
    to the single-element vector mode.
    
    Existing machine patterns are not updated to support the V1XX modes as
    they lack entries in the attributes used (like Vtype, Vetype, Vmtype et
    al.). They would also require special handling to emit the <insn> Dm, Dn 
forms.
    Widening the iterators to add scalar modes ends up colliding with the 
existing
    scalar patterns.
    
    Bootstrapped and regtested on aarch64-linux-gnu.
    
    Signed-off-by: Dhruv Chawla <[email protected]>
    
    gcc/ChangeLog:
    
            * config/aarch64/aarch64-neon-builtins-base.cc (vqaddb, vqaddh,
            vqadds, vqaddd, vqadd, vqaddq, vqsubb, vqsubh, vqsubs, vqsubd, 
vqsub,
            vqsubq): New function bases.
            (one_element_vector_type_p): New function.
            (gimple_ifn::fold): Automatically convert arguments with
            single-element vector modes to the corresponding XX modes and back.
            * 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_s64, vqadd_u8, vqadd_u16, vqadd_u32, vqadd_u64, vqaddq_s8,
            vqaddq_s16, vqaddq_s32, vqaddq_s64, vqaddq_u8, vqaddq_u16, 
vqaddq_u32,
            vqaddq_u64, vqsub_s8, vqsub_s16, vqsub_s32, vqsub_s64, vqsub_u8,
            vqsub_u16, vqsub_u32, vqsub_u64, 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.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/aarch64/neon/vqadd.c: New test.
            * gcc.target/aarch64/neon/vqsub.c: Likewise.

Diff:
---
 gcc/config/aarch64/aarch64-neon-builtins-base.cc  |  45 ++-
 gcc/config/aarch64/aarch64-neon-builtins-base.def |  16 +
 gcc/config/aarch64/arm_neon.h                     | 340 ----------------------
 gcc/testsuite/gcc.target/aarch64/neon/vqadd.c     | 192 ++++++++++++
 gcc/testsuite/gcc.target/aarch64/neon/vqsub.c     | 192 ++++++++++++
 5 files changed, 442 insertions(+), 343 deletions(-)

diff --git a/gcc/config/aarch64/aarch64-neon-builtins-base.cc 
b/gcc/config/aarch64/aarch64-neon-builtins-base.cc
index 05039cd73845..04112c47ea9c 100644
--- a/gcc/config/aarch64/aarch64-neon-builtins-base.cc
+++ b/gcc/config/aarch64/aarch64-neon-builtins-base.cc
@@ -150,6 +150,14 @@ build_tuple_set (gimple_folder &f, tree tuple, tree index, 
tree lane, tree elem)
   return build_tuple_set (f, tuple, index, vec);
 }
 
+/* Check if TYPE is a vector type having one element, like int64x1_t (i.e. V1DI
+   mode) or float64x1_t (i.e. V1DF mode).  */
+static bool
+one_element_vector_type_p (tree type)
+{
+  return VECTOR_TYPE_P (type) && known_eq (TYPE_VECTOR_SUBPARTS (type), 1U);
+}
+
 /* Base class for all function expanders.
    At least one of `expand` or `fold` must be overriden by derived classes.  */
 class gimple_function_base : public function_base
@@ -514,13 +522,40 @@ public:
 
   gimple *fold (gimple_folder &f) const override
   {
+    tree lhs_type = TREE_TYPE (f.lhs);
+    /* There are no instructions that handle V1DI or V1DF modes for these
+       operations.  They need to be specially handled by casting the vector to
+       its element type and using it to feed the scalar version of the
+       operation.  The scalar result is then cast back to a vector and 
returned.
+       This matches the prior implementation that arm_neon.h used for these
+       operations.  */
+    bool scalar_lhs = one_element_vector_type_p (lhs_type);
+
     vec<tree> args{};
     for (unsigned i = 0; i < gimple_call_num_args (f.call); i++)
-      args.safe_push (gimple_call_arg (f.call, i));
+      {
+       tree arg = gimple_call_arg (f.call, i);
+       /* Convert V1DI/V1DF arguments to corresponding scalar modes.  */
+       if (scalar_lhs && one_element_vector_type_p (TREE_TYPE (arg)))
+         arg = f.force_val (build_cast (TREE_TYPE (lhs_type), arg));
+       args.safe_push (arg);
+      }
 
     auto call = gimple_build_call_internal_vec (this->m_ifn, args);
-    gimple_call_set_lhs (call, f.lhs);
-    return call;
+    args.release ();
+
+    if (!scalar_lhs)
+      {
+       gimple_call_set_lhs (call, f.lhs);
+       return call;
+      }
+
+    /* Temporary scalar to hold the result.  */
+    tree res = create_tmp_var (TREE_TYPE (lhs_type));
+    gimple_call_set_lhs (call, res);
+    gsi_insert_before (f.gsi, call, GSI_SAME_STMT);
+    /* Build the actual vector that the call's result gets assigned to.  */
+    return gimple_build_assign (f.lhs, build_vec_dup (lhs_type, res));
   }
 };
 
@@ -747,6 +782,10 @@ 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, vqaddh, vqadds, vqaddd, vqadd, vqaddq, gimple_ifn, 
(IFN_SAT_ADD))
+NEON_FUNCTION (vqsubb, vqsubh, vqsubs, vqsubd, vqsub, vqsubq, gimple_ifn, 
(IFN_SAT_SUB))
+
 // Bitwise operations
 NEON_FUNCTION (vand,  vandq,  gimple_expr,    (BIT_AND_EXPR))
 NEON_FUNCTION (vbic,  vbicq,  gimple_not_rhs, (BIT_AND_EXPR))
diff --git a/gcc/config/aarch64/aarch64-neon-builtins-base.def 
b/gcc/config/aarch64/aarch64-neon-builtins-base.def
index 57ef9ce7e492..928ea5422e39 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,  all_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,  all_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 49fce2751ff4..7daaee84921d 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,195 +1323,6 @@ 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
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-vqadd_u32 (uint32x2_t __a, uint32x2_t __b)
-{
-  return __builtin_aarch64_usaddv2si_uuu (__a, __b);
-}
-
-__extension__ extern __inline uint64x1_t
-__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
-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)
-{
-  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)
-{
-  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)
@@ -13893,64 +13669,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
@@ -15592,64 +15310,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 000000000000..322f54c5a42f
--- /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 000000000000..52ac2f102ebc
--- /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)

Reply via email to