[clang] 515020c - [SveEmitter] Add more immediate operand checks.

Sander de Smalen via cfe-commits cfe-commits at lists.llvm.org
Mon Apr 20 06:55:21 PDT 2020


Author: Sander de Smalen
Date: 2020-04-20T14:41:58+01:00
New Revision: 515020c091e74723ee0876229890d71a8aa79702

URL: https://github.com/llvm/llvm-project/commit/515020c091e74723ee0876229890d71a8aa79702
DIFF: https://github.com/llvm/llvm-project/commit/515020c091e74723ee0876229890d71a8aa79702.diff

LOG: [SveEmitter] Add more immediate operand checks.

This patch adds a number of intrinsics that take immediates with
varying ranges based on the element size one of the operands.

    svext:   immediate ranging 0 to (2048/sizeinbits(elt) - 1)
    svasrd:  immediate ranging 1..sizeinbits(elt)
    svqshlu: immediate ranging 1..sizeinbits(elt)/2
    ftmad:   immediate ranging 0..(sizeinbits(elt) - 1)

Reviewers: efriedma, SjoerdMeijer, rovka, rengolin

Reviewed By: SjoerdMeijer

Tags: #clang

Differential Revision: https://reviews.llvm.org/D76679

Added: 
    clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_asrd.c
    clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ext.c
    clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_tmad.c
    clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_asrd.c
    clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_ext.c
    clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_tmad.c
    clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qshlu.c
    clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_shrnb.c
    clang/test/CodeGen/aarch64-sve2-intrinsics/negative/acle_sve2_qshlu.c
    clang/test/CodeGen/aarch64-sve2-intrinsics/negative/acle_sve2_shrnb.c

Modified: 
    clang/include/clang/Basic/arm_sve.td
    clang/lib/CodeGen/CGBuiltin.cpp
    clang/lib/Sema/SemaChecking.cpp
    clang/utils/TableGen/SveEmitter.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/arm_sve.td b/clang/include/clang/Basic/arm_sve.td
index 75fd3ca499d0..9fe4715e4ea1 100644
--- a/clang/include/clang/Basic/arm_sve.td
+++ b/clang/include/clang/Basic/arm_sve.td
@@ -58,9 +58,11 @@
 // -------------------
 // prototype: return (arg, arg, ...)
 //
+// u: vector of unsigned integers
 // d: default
 // c: const pointer type
 // P: predicate type
+// h: 1/2 width elements, 2x element count
 //
 // i: constant uint64_t
 //
@@ -157,14 +159,18 @@ class ImmCheckType<int val> {
 }
 def ImmCheck0_31                : ImmCheckType<0>;  // 0..31 (used for e.g. predicate patterns)
 def ImmCheck1_16                : ImmCheckType<1>;  // 1..16
+def ImmCheckExtract             : ImmCheckType<2>;  // 0..(2048/sizeinbits(elt) - 1)
+def ImmCheckShiftRight          : ImmCheckType<3>;  // 1..sizeinbits(elt)
+def ImmCheckShiftRightNarrow    : ImmCheckType<4>;  // 1..sizeinbits(elt)/2
+def ImmCheckShiftLeft           : ImmCheckType<5>;  // 0..(sizeinbits(elt) - 1)
+def ImmCheck0_7                 : ImmCheckType<6>;  // 0..7
 
 class ImmCheck<int arg, ImmCheckType kind, int eltSizeArg = -1> {
   int Arg = arg;
-	int EltSizeArg = eltSizeArg;
+  int EltSizeArg = eltSizeArg;
   ImmCheckType Kind = kind;
 }
 
-// Every intrinsic subclasses Inst.
 class Inst<string n, string p, string t, MergeType mt, string i,
            list<FlagType> ft, list<ImmCheck> ch, MemEltType met> {
   string Name = n;
@@ -282,6 +288,30 @@ def SVSTNT1 : MInst<"svstnt1[_{d}]", "vPpd", "csilUcUsUiUlhfd", [IsStore], MemEl
 // Store one vector, with no truncation, non-temporal (scalar base, VL displacement)
 def SVSTNT1_VNUM : MInst<"svstnt1_vnum[_{d}]", "vPpld", "csilUcUsUiUlhfd", [IsStore], MemEltTyDefault, "aarch64_sve_stnt1">;
 
+////////////////////////////////////////////////////////////////////////////////
+// Permutations and selection
+def SVEXT        : SInst<"svext[_{d}]",       "dddi", "csilUcUsUiUlhfd", MergeNone, "aarch64_sve_ext", [], [ImmCheck<2, ImmCheckExtract, 1>]>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Shifts
+def SVASRD_M : SInst<"svasrd[_n_{d}]", "dPdi", "csil",            MergeOp1,  "aarch64_sve_asrd", [], [ImmCheck<2, ImmCheckShiftRight, 1>]>;
+
+////////////////////////////////////////////////////////////////////////////////
+// SVE2 - Narrowing DSP operations
+let ArchGuard = "defined(__ARM_FEATURE_SVE2)" in {
+def SVSHRNB      : SInst<"svshrnb[_n_{d}]",    "hdi",  "silUsUiUl", MergeNone, "aarch64_sve_shrnb",     [], [ImmCheck<1, ImmCheckShiftRightNarrow, 0>]>;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// SVE2 - Uniform DSP operations
+let ArchGuard = "defined(__ARM_FEATURE_SVE2)" in {
+def SVQSHLU_M  : SInst<"svqshlu[_n_{d}]", "uPdi", "csil",         MergeOp1,  "aarch64_sve_sqshlu", [], [ImmCheck<2, ImmCheckShiftLeft,  1>]>;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Floating-point arithmetic
+def SVTMAD  : SInst<"svtmad[_{d}]",  "dddi", "hfd", MergeNone, "aarch64_sve_ftmad_x", [], [ImmCheck<2, ImmCheck0_7>]>;
+
 ////////////////////////////////////////////////////////////////////////////////
 // Saturating scalar arithmetic
 def SVQDECH_S : SInst<"svqdech_pat[_{d}]",   "ddIi", "s", MergeNone, "aarch64_sve_sqdech", [], [ImmCheck<2, ImmCheck1_16>]>;

diff  --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 8ee69740f15c..96c7c9ed2d7b 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -7630,6 +7630,15 @@ Value *CodeGenFunction::EmitAArch64SVEBuiltinExpr(unsigned BuiltinID,
   else if (Builtin->LLVMIntrinsic != 0) {
     llvm::Type* OverloadedTy = getSVEType(TypeFlags);
 
+    // Predicates must match the main datatype.
+    for (unsigned i = 0, e = Ops.size(); i != e; ++i) {
+      if (auto PredTy = dyn_cast<llvm::VectorType>(Ops[i]->getType()))
+        if (PredTy->getScalarType()->isIntegerTy(1)) {
+          auto NewPredTy = cast<llvm::VectorType>(OverloadedTy);
+          Ops[i] = EmitSVEPredicateCast(Ops[i], NewPredTy);
+        }
+    }
+
     Function *F = CGM.getIntrinsic(Builtin->LLVMIntrinsic, OverloadedTy);
     Value *Call = Builder.CreateCall(F, Ops);
 		return Call;

diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 037e9c332412..c13d5fc5c3e2 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2025,6 +2025,29 @@ bool Sema::CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
       if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 1, 16))
         HasError = true;
       break;
+    case SVETypeFlags::ImmCheck0_7:
+      if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, 7))
+        HasError = true;
+      break;
+    case SVETypeFlags::ImmCheckExtract:
+      if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0,
+                                      (2048 / ElementSizeInBits) - 1))
+        HasError = true;
+      break;
+    case SVETypeFlags::ImmCheckShiftRight:
+      if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 1, ElementSizeInBits))
+        HasError = true;
+      break;
+    case SVETypeFlags::ImmCheckShiftRightNarrow:
+      if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 1,
+                                      ElementSizeInBits / 2))
+        HasError = true;
+      break;
+    case SVETypeFlags::ImmCheckShiftLeft:
+      if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0,
+                                      ElementSizeInBits - 1))
+        HasError = true;
+      break;
     }
   }
 

diff  --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_asrd.c b/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_asrd.c
new file mode 100644
index 000000000000..bd0261f26189
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_asrd.c
@@ -0,0 +1,81 @@
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+
+#include <arm_sve.h>
+
+#ifdef SVE_OVERLOADED_FORMS
+// A simple used,unused... macro, long enough to represent any SVE builtin.
+#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3
+#else
+#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4
+#endif
+
+svint8_t test_svasrd_n_s8_m(svbool_t pg, svint8_t op1)
+{
+  // CHECK-LABEL: test_svasrd_n_s8_m
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.asrd.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %op1, i32 1)
+  // CHECK: ret <vscale x 16 x i8> %[[INTRINSIC]]
+  return SVE_ACLE_FUNC(svasrd,_n_s8,_m,)(pg, op1, 1);
+}
+
+svint16_t test_svasrd_n_s16_m(svbool_t pg, svint16_t op1)
+{
+  // CHECK-LABEL: test_svasrd_n_s16_m
+  // CHECK: %[[P0:.*]] = call <vscale x 8 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.asrd.nxv8i16(<vscale x 8 x i1> %[[P0]], <vscale x 8 x i16> %op1, i32 1)
+  // CHECK: ret <vscale x 8 x i16> %[[INTRINSIC]]
+  return SVE_ACLE_FUNC(svasrd,_n_s16,_m,)(pg, op1, 1);
+}
+
+svint32_t test_svasrd_n_s32_m(svbool_t pg, svint32_t op1)
+{
+  // CHECK-LABEL: test_svasrd_n_s32_m
+  // CHECK: %[[P0:.*]] = call <vscale x 4 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.asrd.nxv4i32(<vscale x 4 x i1> %[[P0]], <vscale x 4 x i32> %op1, i32 1)
+  // CHECK: ret <vscale x 4 x i32> %[[INTRINSIC]]
+  return SVE_ACLE_FUNC(svasrd,_n_s32,_m,)(pg, op1, 1);
+}
+
+svint64_t test_svasrd_n_s64_m(svbool_t pg, svint64_t op1)
+{
+  // CHECK-LABEL: test_svasrd_n_s64_m
+  // CHECK: %[[P0:.*]] = call <vscale x 2 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x i64> @llvm.aarch64.sve.asrd.nxv2i64(<vscale x 2 x i1> %[[P0]], <vscale x 2 x i64> %op1, i32 1)
+  // CHECK: ret <vscale x 2 x i64> %[[INTRINSIC]]
+  return SVE_ACLE_FUNC(svasrd,_n_s64,_m,)(pg, op1, 1);
+}
+
+svint8_t test_svasrd_n_s8_max_m(svbool_t pg, svint8_t op1)
+{
+  // CHECK-LABEL: test_svasrd_n_s8_max_m
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.asrd.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %op1, i32 8)
+  // CHECK: ret <vscale x 16 x i8> %[[INTRINSIC]]
+  return SVE_ACLE_FUNC(svasrd,_n_s8,_m,)(pg, op1, 8);
+}
+
+svint16_t test_svasrd_n_s16_max_m(svbool_t pg, svint16_t op1)
+{
+  // CHECK-LABEL: test_svasrd_n_s16_max_m
+  // CHECK: %[[P0:.*]] = call <vscale x 8 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.asrd.nxv8i16(<vscale x 8 x i1> %[[P0]], <vscale x 8 x i16> %op1, i32 16)
+  // CHECK: ret <vscale x 8 x i16> %[[INTRINSIC]]
+  return SVE_ACLE_FUNC(svasrd,_n_s16,_m,)(pg, op1, 16);
+}
+
+svint32_t test_svasrd_n_s32_max_m(svbool_t pg, svint32_t op1)
+{
+  // CHECK-LABEL: test_svasrd_n_s32_max_m
+  // CHECK: %[[P0:.*]] = call <vscale x 4 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.asrd.nxv4i32(<vscale x 4 x i1> %[[P0]], <vscale x 4 x i32> %op1, i32 32)
+  // CHECK: ret <vscale x 4 x i32> %[[INTRINSIC]]
+  return SVE_ACLE_FUNC(svasrd,_n_s32,_m,)(pg, op1, 32);
+}
+
+svint64_t test_svasrd_n_s64_max_m(svbool_t pg, svint64_t op1)
+{
+  // CHECK-LABEL: test_svasrd_n_s64_max_m
+  // CHECK: %[[P0:.*]] = call <vscale x 2 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x i64> @llvm.aarch64.sve.asrd.nxv2i64(<vscale x 2 x i1> %[[P0]], <vscale x 2 x i64> %op1, i32 64)
+  // CHECK: ret <vscale x 2 x i64> %[[INTRINSIC]]
+  return SVE_ACLE_FUNC(svasrd,_n_s64,_m,)(pg, op1, 64);
+}

diff  --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ext.c b/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ext.c
new file mode 100644
index 000000000000..fb3a10f29440
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ext.c
@@ -0,0 +1,131 @@
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+
+#include <arm_sve.h>
+
+#ifdef SVE_OVERLOADED_FORMS
+// A simple used,unused... macro, long enough to represent any SVE builtin.
+#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3
+#else
+#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4
+#endif
+
+svint8_t test_svext_s8(svint8_t op1, svint8_t op2)
+{
+  // CHECK-LABEL: test_svext_s8
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.ext.nxv16i8(<vscale x 16 x i8> %op1, <vscale x 16 x i8> %op2, i32 0)
+  // CHECK: ret <vscale x 16 x i8> %[[INTRINSIC]]
+  return SVE_ACLE_FUNC(svext,_s8,,)(op1, op2, 0);
+}
+
+svint8_t test_svext_s8_1(svint8_t op1, svint8_t op2)
+{
+  // CHECK-LABEL: test_svext_s8_1
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.ext.nxv16i8(<vscale x 16 x i8> %op1, <vscale x 16 x i8> %op2, i32 255)
+  // CHECK: ret <vscale x 16 x i8> %[[INTRINSIC]]
+  return SVE_ACLE_FUNC(svext,_s8,,)(op1, op2, 255);
+}
+
+svint16_t test_svext_s16(svint16_t op1, svint16_t op2)
+{
+  // CHECK-LABEL: test_svext_s16
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.ext.nxv8i16(<vscale x 8 x i16> %op1, <vscale x 8 x i16> %op2, i32 0)
+  // CHECK: ret <vscale x 8 x i16> %[[INTRINSIC]]
+  return SVE_ACLE_FUNC(svext,_s16,,)(op1, op2, 0);
+}
+
+svint16_t test_svext_s16_1(svint16_t op1, svint16_t op2)
+{
+  // CHECK-LABEL: test_svext_s16_1
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.ext.nxv8i16(<vscale x 8 x i16> %op1, <vscale x 8 x i16> %op2, i32 127)
+  // CHECK: ret <vscale x 8 x i16> %[[INTRINSIC]]
+  return SVE_ACLE_FUNC(svext,_s16,,)(op1, op2, 127);
+}
+
+svint32_t test_svext_s32(svint32_t op1, svint32_t op2)
+{
+  // CHECK-LABEL: test_svext_s32
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.ext.nxv4i32(<vscale x 4 x i32> %op1, <vscale x 4 x i32> %op2, i32 0)
+  // CHECK: ret <vscale x 4 x i32> %[[INTRINSIC]]
+  return SVE_ACLE_FUNC(svext,_s32,,)(op1, op2, 0);
+}
+
+svint32_t test_svext_s32_1(svint32_t op1, svint32_t op2)
+{
+  // CHECK-LABEL: test_svext_s32_1
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.ext.nxv4i32(<vscale x 4 x i32> %op1, <vscale x 4 x i32> %op2, i32 63)
+  // CHECK: ret <vscale x 4 x i32> %[[INTRINSIC]]
+  return SVE_ACLE_FUNC(svext,_s32,,)(op1, op2, 63);
+}
+
+svint64_t test_svext_s64(svint64_t op1, svint64_t op2)
+{
+  // CHECK-LABEL: test_svext_s64
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x i64> @llvm.aarch64.sve.ext.nxv2i64(<vscale x 2 x i64> %op1, <vscale x 2 x i64> %op2, i32 0)
+  // CHECK: ret <vscale x 2 x i64> %[[INTRINSIC]]
+  return SVE_ACLE_FUNC(svext,_s64,,)(op1, op2, 0);
+}
+
+svint64_t test_svext_s64_1(svint64_t op1, svint64_t op2)
+{
+  // CHECK-LABEL: test_svext_s64_1
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x i64> @llvm.aarch64.sve.ext.nxv2i64(<vscale x 2 x i64> %op1, <vscale x 2 x i64> %op2, i32 31)
+  // CHECK: ret <vscale x 2 x i64> %[[INTRINSIC]]
+  return SVE_ACLE_FUNC(svext,_s64,,)(op1, op2, 31);
+}
+
+svuint8_t test_svext_u8(svuint8_t op1, svuint8_t op2)
+{
+  // CHECK-LABEL: test_svext_u8
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.ext.nxv16i8(<vscale x 16 x i8> %op1, <vscale x 16 x i8> %op2, i32 255)
+  // CHECK: ret <vscale x 16 x i8> %[[INTRINSIC]]
+  return SVE_ACLE_FUNC(svext,_u8,,)(op1, op2, 255);
+}
+
+svuint16_t test_svext_u16(svuint16_t op1, svuint16_t op2)
+{
+  // CHECK-LABEL: test_svext_u16
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.ext.nxv8i16(<vscale x 8 x i16> %op1, <vscale x 8 x i16> %op2, i32 127)
+  // CHECK: ret <vscale x 8 x i16> %[[INTRINSIC]]
+  return SVE_ACLE_FUNC(svext,_u16,,)(op1, op2, 127);
+}
+
+svuint32_t test_svext_u32(svuint32_t op1, svuint32_t op2)
+{
+  // CHECK-LABEL: test_svext_u32
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.ext.nxv4i32(<vscale x 4 x i32> %op1, <vscale x 4 x i32> %op2, i32 63)
+  // CHECK: ret <vscale x 4 x i32> %[[INTRINSIC]]
+  return SVE_ACLE_FUNC(svext,_u32,,)(op1, op2, 63);
+}
+
+svuint64_t test_svext_u64(svuint64_t op1, svuint64_t op2)
+{
+  // CHECK-LABEL: test_svext_u64
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x i64> @llvm.aarch64.sve.ext.nxv2i64(<vscale x 2 x i64> %op1, <vscale x 2 x i64> %op2, i32 31)
+  // CHECK: ret <vscale x 2 x i64> %[[INTRINSIC]]
+  return SVE_ACLE_FUNC(svext,_u64,,)(op1, op2, 31);
+}
+
+svfloat16_t test_svext_f16(svfloat16_t op1, svfloat16_t op2)
+{
+  // CHECK-LABEL: test_svext_f16
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x half> @llvm.aarch64.sve.ext.nxv8f16(<vscale x 8 x half> %op1, <vscale x 8 x half> %op2, i32 127)
+  // CHECK: ret <vscale x 8 x half> %[[INTRINSIC]]
+  return SVE_ACLE_FUNC(svext,_f16,,)(op1, op2, 127);
+}
+
+svfloat32_t test_svext_f32(svfloat32_t op1, svfloat32_t op2)
+{
+  // CHECK-LABEL: test_svext_f32
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x float> @llvm.aarch64.sve.ext.nxv4f32(<vscale x 4 x float> %op1, <vscale x 4 x float> %op2, i32 63)
+  // CHECK: ret <vscale x 4 x float> %[[INTRINSIC]]
+  return SVE_ACLE_FUNC(svext,_f32,,)(op1, op2, 63);
+}
+
+svfloat64_t test_svext_f64(svfloat64_t op1, svfloat64_t op2)
+{
+  // CHECK-LABEL: test_svext_f64
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x double> @llvm.aarch64.sve.ext.nxv2f64(<vscale x 2 x double> %op1, <vscale x 2 x double> %op2, i32 31)
+  // CHECK: ret <vscale x 2 x double> %[[INTRINSIC]]
+  return SVE_ACLE_FUNC(svext,_f64,,)(op1, op2, 31);
+}

diff  --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_tmad.c b/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_tmad.c
new file mode 100644
index 000000000000..c9383857d45b
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_tmad.c
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+
+#include <arm_sve.h>
+
+#ifdef SVE_OVERLOADED_FORMS
+// A simple used,unused... macro, long enough to represent any SVE builtin.
+#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3
+#else
+#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4
+#endif
+
+svfloat16_t test_svtmad_f16(svfloat16_t op1, svfloat16_t op2)
+{
+  // CHECK-LABEL: test_svtmad_f16
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x half> @llvm.aarch64.sve.ftmad.x.nxv8f16(<vscale x 8 x half> %op1, <vscale x 8 x half> %op2, i32 0)
+  // CHECK: ret <vscale x 8 x half> %[[INTRINSIC]]
+  return SVE_ACLE_FUNC(svtmad,_f16,,)(op1, op2, 0);
+}
+
+svfloat16_t test_svtmad_f16_1(svfloat16_t op1, svfloat16_t op2)
+{
+  // CHECK-LABEL: test_svtmad_f16_1
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x half> @llvm.aarch64.sve.ftmad.x.nxv8f16(<vscale x 8 x half> %op1, <vscale x 8 x half> %op2, i32 7)
+  // CHECK: ret <vscale x 8 x half> %[[INTRINSIC]]
+  return SVE_ACLE_FUNC(svtmad,_f16,,)(op1, op2, 7);
+}
+
+svfloat32_t test_svtmad_f32(svfloat32_t op1, svfloat32_t op2)
+{
+  // CHECK-LABEL: test_svtmad_f32
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x float> @llvm.aarch64.sve.ftmad.x.nxv4f32(<vscale x 4 x float> %op1, <vscale x 4 x float> %op2, i32 0)
+  // CHECK: ret <vscale x 4 x float> %[[INTRINSIC]]
+  return SVE_ACLE_FUNC(svtmad,_f32,,)(op1, op2, 0);
+}
+
+svfloat64_t test_svtmad_f64(svfloat64_t op1, svfloat64_t op2)
+{
+  // CHECK-LABEL: test_svtmad_f64
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x double> @llvm.aarch64.sve.ftmad.x.nxv2f64(<vscale x 2 x double> %op1, <vscale x 2 x double> %op2, i32 0)
+  // CHECK: ret <vscale x 2 x double> %[[INTRINSIC]]
+  return SVE_ACLE_FUNC(svtmad,_f64,,)(op1, op2, 0);
+}

diff  --git a/clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_asrd.c b/clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_asrd.c
new file mode 100644
index 000000000000..62547c3f98a2
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_asrd.c
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify %s
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify %s
+
+#ifdef SVE_OVERLOADED_FORMS
+// A simple used,unused... macro, long enough to represent any SVE builtin.
+#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3
+#else
+#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4
+#endif
+
+#include <arm_sve.h>
+
+svint8_t test_svasrd_n_s8_m(svbool_t pg, svint8_t op1)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [1, 8]}}
+  return SVE_ACLE_FUNC(svasrd,_n_s8,_m,)(pg, op1, 0);
+}
+
+svint16_t test_svasrd_n_s16_m(svbool_t pg, svint16_t op1)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [1, 16]}}
+  return SVE_ACLE_FUNC(svasrd,_n_s16,_m,)(pg, op1, 17);
+}
+
+svint32_t test_svasrd_n_s32_m(svbool_t pg, svint32_t op1)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [1, 32]}}
+  return SVE_ACLE_FUNC(svasrd,_n_s32,_m,)(pg, op1, 0);
+}
+
+svint64_t test_svasrd_n_s64_m(svbool_t pg, svint64_t op1)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [1, 64]}}
+  return SVE_ACLE_FUNC(svasrd,_n_s64,_m,)(pg, op1, 65);
+}

diff  --git a/clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_ext.c b/clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_ext.c
new file mode 100644
index 000000000000..f8706d4e7590
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_ext.c
@@ -0,0 +1,101 @@
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify %s
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify %s
+
+#ifdef SVE_OVERLOADED_FORMS
+// A simple used,unused... macro, long enough to represent any SVE builtin.
+#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3
+#else
+#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4
+#endif
+
+#include <arm_sve.h>
+
+svint8_t test_svext_s8(svint8_t op1, svint8_t op2)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [0, 255]}}
+  return SVE_ACLE_FUNC(svext,_s8,,)(op1, op2, -1);
+}
+
+svint8_t test_svext_s8_1(svint8_t op1, svint8_t op2)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [0, 255]}}
+  return SVE_ACLE_FUNC(svext,_s8,,)(op1, op2, 256);
+}
+
+svint16_t test_svext_s16(svint16_t op1, svint16_t op2)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [0, 127]}}
+  return SVE_ACLE_FUNC(svext,_s16,,)(op1, op2, -1);
+}
+
+svint16_t test_svext_s16_1(svint16_t op1, svint16_t op2)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [0, 127]}}
+  return SVE_ACLE_FUNC(svext,_s16,,)(op1, op2, 128);
+}
+
+svint32_t test_svext_s32(svint32_t op1, svint32_t op2)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [0, 63]}}
+  return SVE_ACLE_FUNC(svext,_s32,,)(op1, op2, -1);
+}
+
+svint32_t test_svext_s32_1(svint32_t op1, svint32_t op2)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [0, 63]}}
+  return SVE_ACLE_FUNC(svext,_s32,,)(op1, op2, 64);
+}
+
+svint64_t test_svext_s64(svint64_t op1, svint64_t op2)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [0, 31]}}
+  return SVE_ACLE_FUNC(svext,_s64,,)(op1, op2, -1);
+}
+
+svint64_t test_svext_s64_1(svint64_t op1, svint64_t op2)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [0, 31]}}
+  return SVE_ACLE_FUNC(svext,_s64,,)(op1, op2, 32);
+}
+
+svuint8_t test_svext_u8(svuint8_t op1, svuint8_t op2)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [0, 255]}}
+  return SVE_ACLE_FUNC(svext,_u8,,)(op1, op2, -1);
+}
+
+svuint16_t test_svext_u16(svuint16_t op1, svuint16_t op2)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [0, 127]}}
+  return SVE_ACLE_FUNC(svext,_u16,,)(op1, op2, 128);
+}
+
+svuint32_t test_svext_u32(svuint32_t op1, svuint32_t op2)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [0, 63]}}
+  return SVE_ACLE_FUNC(svext,_u32,,)(op1, op2, -1);
+}
+
+svuint64_t test_svext_u64(svuint64_t op1, svuint64_t op2)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [0, 31]}}
+  return SVE_ACLE_FUNC(svext,_u64,,)(op1, op2, 32);
+}
+
+svfloat16_t test_svext_f16(svfloat16_t op1, svfloat16_t op2)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [0, 127]}}
+  return SVE_ACLE_FUNC(svext,_f16,,)(op1, op2, -1);
+}
+
+svfloat32_t test_svext_f32(svfloat32_t op1, svfloat32_t op2)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [0, 63]}}
+  return SVE_ACLE_FUNC(svext,_f32,,)(op1, op2, 64);
+}
+
+svfloat64_t test_svext_f64(svfloat64_t op1, svfloat64_t op2)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [0, 31]}}
+  return SVE_ACLE_FUNC(svext,_f64,,)(op1, op2, -1);
+}

diff  --git a/clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_tmad.c b/clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_tmad.c
new file mode 100644
index 000000000000..da85cb726257
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_tmad.c
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify %s
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify %s
+
+#ifdef SVE_OVERLOADED_FORMS
+// A simple used,unused... macro, long enough to represent any SVE builtin.
+#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3
+#else
+#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4
+#endif
+
+#include <arm_sve.h>
+
+svfloat16_t test_svtmad_f16(svfloat16_t op1, svfloat16_t op2)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [0, 7]}}
+  return SVE_ACLE_FUNC(svtmad,_f16,,)(op1, op2, -1);
+}
+
+svfloat16_t test_svtmad_f16_1(svfloat16_t op1, svfloat16_t op2)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [0, 7]}}
+  return SVE_ACLE_FUNC(svtmad,_f16,,)(op1, op2, 8);
+}
+
+svfloat32_t test_svtmad_f32(svfloat32_t op1, svfloat32_t op2)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [0, 7]}}
+  return SVE_ACLE_FUNC(svtmad,_f32,,)(op1, op2, -1);
+}
+
+svfloat32_t test_svtmad_f32_1(svfloat32_t op1, svfloat32_t op2)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [0, 7]}}
+  return SVE_ACLE_FUNC(svtmad,_f32,,)(op1, op2, 8);
+}
+
+svfloat64_t test_svtmad_f64(svfloat64_t op1, svfloat64_t op2)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [0, 7]}}
+  return SVE_ACLE_FUNC(svtmad,_f64,,)(op1, op2, -1);
+}
+
+svfloat64_t test_svtmad_f64_1(svfloat64_t op1, svfloat64_t op2)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [0, 7]}}
+  return SVE_ACLE_FUNC(svtmad,_f64,,)(op1, op2, 8);
+}

diff  --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qshlu.c b/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qshlu.c
new file mode 100644
index 000000000000..69a260764d39
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qshlu.c
@@ -0,0 +1,99 @@
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -D__ARM_FEATURE_SVE2 -triple aarch64-none-linux-gnu -target-feature +sve2 -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -D__ARM_FEATURE_SVE2 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2 -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify -verify-ignore-unexpected=error %s
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify=overload -verify-ignore-unexpected=error %s
+
+#include <arm_sve.h>
+
+#ifdef SVE_OVERLOADED_FORMS
+// A simple used,unused... macro, long enough to represent any SVE builtin.
+#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3
+#else
+#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4
+#endif
+
+svuint8_t test_svqshlu_n_s8_m(svbool_t pg, svint8_t op1)
+{
+  // CHECK-LABEL: test_svqshlu_n_s8_m
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.sqshlu.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %op1, i32 0)
+  // CHECK: ret <vscale x 16 x i8> %[[INTRINSIC]]
+  // overload-warning at +2 {{implicit declaration of function 'svqshlu_m'}}
+  // expected-warning at +1 {{implicit declaration of function 'svqshlu_n_s8_m'}}
+  return SVE_ACLE_FUNC(svqshlu,_n_s8,_m,)(pg, op1, 0);
+}
+
+svuint8_t test_svqshlu_n_s8_m_1(svbool_t pg, svint8_t op1)
+{
+  // CHECK-LABEL: test_svqshlu_n_s8_m_1
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.sqshlu.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %op1, i32 7)
+  // CHECK: ret <vscale x 16 x i8> %[[INTRINSIC]]
+  // overload-warning at +2 {{implicit declaration of function 'svqshlu_m'}}
+  // expected-warning at +1 {{implicit declaration of function 'svqshlu_n_s8_m'}}
+  return SVE_ACLE_FUNC(svqshlu,_n_s8,_m,)(pg, op1, 7);
+}
+
+svuint16_t test_svqshlu_n_s16_m(svbool_t pg, svint16_t op1)
+{
+  // CHECK-LABEL: test_svqshlu_n_s16_m
+  // CHECK: %[[PG:.*]] = call <vscale x 8 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.sqshlu.nxv8i16(<vscale x 8 x i1> %[[PG]], <vscale x 8 x i16> %op1, i32 0)
+  // CHECK: ret <vscale x 8 x i16> %[[INTRINSIC]]
+  // overload-warning at +2 {{implicit declaration of function 'svqshlu_m'}}
+  // expected-warning at +1 {{implicit declaration of function 'svqshlu_n_s16_m'}}
+  return SVE_ACLE_FUNC(svqshlu,_n_s16,_m,)(pg, op1, 0);
+}
+
+svuint16_t test_svqshlu_n_s16_m_1(svbool_t pg, svint16_t op1)
+{
+  // CHECK-LABEL: test_svqshlu_n_s16_m_1
+  // CHECK: %[[PG:.*]] = call <vscale x 8 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.sqshlu.nxv8i16(<vscale x 8 x i1> %[[PG]], <vscale x 8 x i16> %op1, i32 15)
+  // CHECK: ret <vscale x 8 x i16> %[[INTRINSIC]]
+  // overload-warning at +2 {{implicit declaration of function 'svqshlu_m'}}
+  // expected-warning at +1 {{implicit declaration of function 'svqshlu_n_s16_m'}}
+  return SVE_ACLE_FUNC(svqshlu,_n_s16,_m,)(pg, op1, 15);
+}
+
+svuint32_t test_svqshlu_n_s32_m(svbool_t pg, svint32_t op1)
+{
+  // CHECK-LABEL: test_svqshlu_n_s32_m
+  // CHECK: %[[PG:.*]] = call <vscale x 4 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.sqshlu.nxv4i32(<vscale x 4 x i1> %[[PG]], <vscale x 4 x i32> %op1, i32 0)
+  // CHECK: ret <vscale x 4 x i32> %[[INTRINSIC]]
+  // overload-warning at +2 {{implicit declaration of function 'svqshlu_m'}}
+  // expected-warning at +1 {{implicit declaration of function 'svqshlu_n_s32_m'}}
+  return SVE_ACLE_FUNC(svqshlu,_n_s32,_m,)(pg, op1, 0);
+}
+
+svuint32_t test_svqshlu_n_s32_m_1(svbool_t pg, svint32_t op1)
+{
+  // CHECK-LABEL: test_svqshlu_n_s32_m_1
+  // CHECK: %[[PG:.*]] = call <vscale x 4 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.sqshlu.nxv4i32(<vscale x 4 x i1> %[[PG]], <vscale x 4 x i32> %op1, i32 31)
+  // CHECK: ret <vscale x 4 x i32> %[[INTRINSIC]]
+  // overload-warning at +2 {{implicit declaration of function 'svqshlu_m'}}
+  // expected-warning at +1 {{implicit declaration of function 'svqshlu_n_s32_m'}}
+  return SVE_ACLE_FUNC(svqshlu,_n_s32,_m,)(pg, op1, 31);
+}
+
+svuint64_t test_svqshlu_n_s64_m(svbool_t pg, svint64_t op1)
+{
+  // CHECK-LABEL: test_svqshlu_n_s64_m
+  // CHECK: %[[PG:.*]] = call <vscale x 2 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x i64> @llvm.aarch64.sve.sqshlu.nxv2i64(<vscale x 2 x i1> %[[PG]], <vscale x 2 x i64> %op1, i32 0)
+  // CHECK: ret <vscale x 2 x i64> %[[INTRINSIC]]
+  // overload-warning at +2 {{implicit declaration of function 'svqshlu_m'}}
+  // expected-warning at +1 {{implicit declaration of function 'svqshlu_n_s64_m'}}
+  return SVE_ACLE_FUNC(svqshlu,_n_s64,_m,)(pg, op1, 0);
+}
+
+svuint64_t test_svqshlu_n_s64_m_1(svbool_t pg, svint64_t op1)
+{
+  // CHECK-LABEL: test_svqshlu_n_s64_m_1
+  // CHECK: %[[PG:.*]] = call <vscale x 2 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x i64> @llvm.aarch64.sve.sqshlu.nxv2i64(<vscale x 2 x i1> %[[PG]], <vscale x 2 x i64> %op1, i32 63)
+  // CHECK: ret <vscale x 2 x i64> %[[INTRINSIC]]
+  // overload-warning at +2 {{implicit declaration of function 'svqshlu_m'}}
+  // expected-warning at +1 {{implicit declaration of function 'svqshlu_n_s64_m'}}
+  return SVE_ACLE_FUNC(svqshlu,_n_s64,_m,)(pg, op1, 63);
+}

diff  --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_shrnb.c b/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_shrnb.c
new file mode 100644
index 000000000000..88403c5ede58
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_shrnb.c
@@ -0,0 +1,133 @@
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -D__ARM_FEATURE_SVE2 -triple aarch64-none-linux-gnu -target-feature +sve2 -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -D__ARM_FEATURE_SVE2 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2 -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify -verify-ignore-unexpected=error %s
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify=overload -verify-ignore-unexpected=error %s
+
+#include <arm_sve.h>
+
+#ifdef SVE_OVERLOADED_FORMS
+// A simple used,unused... macro, long enough to represent any SVE builtin.
+#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3
+#else
+#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4
+#endif
+
+svint8_t test_svshrnb_n_s16(svint16_t op1)
+{
+  // CHECK-LABEL: test_svshrnb_n_s16
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.shrnb.nxv8i16(<vscale x 8 x i16> %op1, i32 1)
+  // CHECK: ret <vscale x 16 x i8> %[[INTRINSIC]]
+  // overload-warning at +2 {{implicit declaration of function 'svshrnb'}}
+  // expected-warning at +1 {{implicit declaration of function 'svshrnb_n_s16'}}
+  return SVE_ACLE_FUNC(svshrnb,_n_s16,,)(op1, 1);
+}
+
+svint8_t test_svshrnb_n_s16_1(svint16_t op1)
+{
+  // CHECK-LABEL: test_svshrnb_n_s16_1
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.shrnb.nxv8i16(<vscale x 8 x i16> %op1, i32 8)
+  // CHECK: ret <vscale x 16 x i8> %[[INTRINSIC]]
+  // overload-warning at +2 {{implicit declaration of function 'svshrnb'}}
+  // expected-warning at +1 {{implicit declaration of function 'svshrnb_n_s16'}}
+  return SVE_ACLE_FUNC(svshrnb,_n_s16,,)(op1, 8);
+}
+
+svint16_t test_svshrnb_n_s32(svint32_t op1)
+{
+  // CHECK-LABEL: test_svshrnb_n_s32
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.shrnb.nxv4i32(<vscale x 4 x i32> %op1, i32 1)
+  // CHECK: ret <vscale x 8 x i16> %[[INTRINSIC]]
+  // overload-warning at +2 {{implicit declaration of function 'svshrnb'}}
+  // expected-warning at +1 {{implicit declaration of function 'svshrnb_n_s32'}}
+  return SVE_ACLE_FUNC(svshrnb,_n_s32,,)(op1, 1);
+}
+
+svint16_t test_svshrnb_n_s32_1(svint32_t op1)
+{
+  // CHECK-LABEL: test_svshrnb_n_s32_1
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.shrnb.nxv4i32(<vscale x 4 x i32> %op1, i32 16)
+  // CHECK: ret <vscale x 8 x i16> %[[INTRINSIC]]
+  // overload-warning at +2 {{implicit declaration of function 'svshrnb'}}
+  // expected-warning at +1 {{implicit declaration of function 'svshrnb_n_s32'}}
+  return SVE_ACLE_FUNC(svshrnb,_n_s32,,)(op1, 16);
+}
+
+svint32_t test_svshrnb_n_s64(svint64_t op1)
+{
+  // CHECK-LABEL: test_svshrnb_n_s64
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.shrnb.nxv2i64(<vscale x 2 x i64> %op1, i32 1)
+  // CHECK: ret <vscale x 4 x i32> %[[INTRINSIC]]
+  // overload-warning at +2 {{implicit declaration of function 'svshrnb'}}
+  // expected-warning at +1 {{implicit declaration of function 'svshrnb_n_s64'}}
+  return SVE_ACLE_FUNC(svshrnb,_n_s64,,)(op1, 1);
+}
+
+svint32_t test_svshrnb_n_s64_1(svint64_t op1)
+{
+  // CHECK-LABEL: test_svshrnb_n_s64_1
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.shrnb.nxv2i64(<vscale x 2 x i64> %op1, i32 32)
+  // CHECK: ret <vscale x 4 x i32> %[[INTRINSIC]]
+  // overload-warning at +2 {{implicit declaration of function 'svshrnb'}}
+  // expected-warning at +1 {{implicit declaration of function 'svshrnb_n_s64'}}
+  return SVE_ACLE_FUNC(svshrnb,_n_s64,,)(op1, 32);
+}
+
+svuint8_t test_svshrnb_n_u16(svuint16_t op1)
+{
+  // CHECK-LABEL: test_svshrnb_n_u16
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.shrnb.nxv8i16(<vscale x 8 x i16> %op1, i32 1)
+  // CHECK: ret <vscale x 16 x i8> %[[INTRINSIC]]
+  // overload-warning at +2 {{implicit declaration of function 'svshrnb'}}
+  // expected-warning at +1 {{implicit declaration of function 'svshrnb_n_u16'}}
+  return SVE_ACLE_FUNC(svshrnb,_n_u16,,)(op1, 1);
+}
+
+svuint8_t test_svshrnb_n_u16_1(svuint16_t op1)
+{
+  // CHECK-LABEL: test_svshrnb_n_u16_1
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.shrnb.nxv8i16(<vscale x 8 x i16> %op1, i32 8)
+  // CHECK: ret <vscale x 16 x i8> %[[INTRINSIC]]
+  // overload-warning at +2 {{implicit declaration of function 'svshrnb'}}
+  // expected-warning at +1 {{implicit declaration of function 'svshrnb_n_u16'}}
+  return SVE_ACLE_FUNC(svshrnb,_n_u16,,)(op1, 8);
+}
+
+svuint16_t test_svshrnb_n_u32(svuint32_t op1)
+{
+  // CHECK-LABEL: test_svshrnb_n_u32
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.shrnb.nxv4i32(<vscale x 4 x i32> %op1, i32 1)
+  // CHECK: ret <vscale x 8 x i16> %[[INTRINSIC]]
+  // overload-warning at +2 {{implicit declaration of function 'svshrnb'}}
+  // expected-warning at +1 {{implicit declaration of function 'svshrnb_n_u32'}}
+  return SVE_ACLE_FUNC(svshrnb,_n_u32,,)(op1, 1);
+}
+
+svuint16_t test_svshrnb_n_u32_1(svuint32_t op1)
+{
+  // CHECK-LABEL: test_svshrnb_n_u32_1
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.shrnb.nxv4i32(<vscale x 4 x i32> %op1, i32 16)
+  // CHECK: ret <vscale x 8 x i16> %[[INTRINSIC]]
+  // overload-warning at +2 {{implicit declaration of function 'svshrnb'}}
+  // expected-warning at +1 {{implicit declaration of function 'svshrnb_n_u32'}}
+  return SVE_ACLE_FUNC(svshrnb,_n_u32,,)(op1, 16);
+}
+
+svuint32_t test_svshrnb_n_u64(svuint64_t op1)
+{
+  // CHECK-LABEL: test_svshrnb_n_u64
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.shrnb.nxv2i64(<vscale x 2 x i64> %op1, i32 1)
+  // CHECK: ret <vscale x 4 x i32> %[[INTRINSIC]]
+  // overload-warning at +2 {{implicit declaration of function 'svshrnb'}}
+  // expected-warning at +1 {{implicit declaration of function 'svshrnb_n_u64'}}
+  return SVE_ACLE_FUNC(svshrnb,_n_u64,,)(op1, 1);
+}
+
+svuint32_t test_svshrnb_n_u64_1(svuint64_t op1)
+{
+  // CHECK-LABEL: test_svshrnb_n_u64_1
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.shrnb.nxv2i64(<vscale x 2 x i64> %op1, i32 32)
+  // CHECK: ret <vscale x 4 x i32> %[[INTRINSIC]]
+  // overload-warning at +2 {{implicit declaration of function 'svshrnb'}}
+  // expected-warning at +1 {{implicit declaration of function 'svshrnb_n_u64'}}
+  return SVE_ACLE_FUNC(svshrnb,_n_u64,,)(op1, 32);
+}

diff  --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/negative/acle_sve2_qshlu.c b/clang/test/CodeGen/aarch64-sve2-intrinsics/negative/acle_sve2_qshlu.c
new file mode 100644
index 000000000000..022cf804b007
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sve2-intrinsics/negative/acle_sve2_qshlu.c
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -D__ARM_FEATURE_SVE2 -triple aarch64-none-linux-gnu -target-feature +sve2 -fallow-half-arguments-and-returns -fsyntax-only -verify %s
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -D__ARM_FEATURE_SVE2 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2 -fallow-half-arguments-and-returns -fsyntax-only -verify %s
+
+#ifdef SVE_OVERLOADED_FORMS
+// A simple used,unused... macro, long enough to represent any SVE builtin.
+#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3
+#else
+#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4
+#endif
+
+#include <arm_sve.h>
+
+svuint8_t test_svqshlu_n_s8_m(svbool_t pg, svint8_t op1)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [0, 7]}}
+  return SVE_ACLE_FUNC(svqshlu,_n_s8,_m,)(pg, op1, -1);
+}
+
+svuint16_t test_svqshlu_n_s16_m(svbool_t pg, svint16_t op1)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [0, 15]}}
+  return SVE_ACLE_FUNC(svqshlu,_n_s16,_m,)(pg, op1, -1);
+}
+
+svuint32_t test_svqshlu_n_s32_m(svbool_t pg, svint32_t op1)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [0, 31]}}
+  return SVE_ACLE_FUNC(svqshlu,_n_s32,_m,)(pg, op1, -1);
+}
+
+svuint64_t test_svqshlu_n_s64_m(svbool_t pg, svint64_t op1)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [0, 63]}}
+  return SVE_ACLE_FUNC(svqshlu,_n_s64,_m,)(pg, op1, -1);
+}

diff  --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/negative/acle_sve2_shrnb.c b/clang/test/CodeGen/aarch64-sve2-intrinsics/negative/acle_sve2_shrnb.c
new file mode 100644
index 000000000000..60cf3a1154ed
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sve2-intrinsics/negative/acle_sve2_shrnb.c
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -D__ARM_FEATURE_SVE2 -triple aarch64-none-linux-gnu -target-feature +sve2 -fallow-half-arguments-and-returns -fsyntax-only -verify %s
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -D__ARM_FEATURE_SVE2 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2 -fallow-half-arguments-and-returns -fsyntax-only -verify %s
+
+#ifdef SVE_OVERLOADED_FORMS
+// A simple used,unused... macro, long enough to represent any SVE builtin.
+#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3
+#else
+#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4
+#endif
+
+#include <arm_sve.h>
+
+svint8_t test_svshrnb_n_s16(svint16_t op1)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [1, 8]}}
+  return SVE_ACLE_FUNC(svshrnb,_n_s16,,)(op1, 0);
+}
+
+svint16_t test_svshrnb_n_s32(svint32_t op1)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [1, 16]}}
+  return SVE_ACLE_FUNC(svshrnb,_n_s32,,)(op1, 0);
+}
+
+svint32_t test_svshrnb_n_s64(svint64_t op1)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [1, 32]}}
+  return SVE_ACLE_FUNC(svshrnb,_n_s64,,)(op1, 0);
+}
+
+svuint8_t test_svshrnb_n_u16(svuint16_t op1)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [1, 8]}}
+  return SVE_ACLE_FUNC(svshrnb,_n_u16,,)(op1, 0);
+}
+
+svuint16_t test_svshrnb_n_u32(svuint32_t op1)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [1, 16]}}
+  return SVE_ACLE_FUNC(svshrnb,_n_u32,,)(op1, 0);
+}
+
+svuint32_t test_svshrnb_n_u64(svuint64_t op1)
+{
+  // expected-error-re at +1 {{argument value {{[0-9]+}} is outside the valid range [1, 32]}}
+  return SVE_ACLE_FUNC(svshrnb,_n_u64,,)(op1, 0);
+}

diff  --git a/clang/utils/TableGen/SveEmitter.cpp b/clang/utils/TableGen/SveEmitter.cpp
index 8ef65612a243..03fe8228dd86 100644
--- a/clang/utils/TableGen/SveEmitter.cpp
+++ b/clang/utils/TableGen/SveEmitter.cpp
@@ -456,6 +456,9 @@ void SVEType::applyModifier(char Mod) {
     Bitwidth = ElementBitwidth;
     NumVectors = 0;
     break;
+  case 'h':
+    ElementBitwidth /= 2;
+    break;
   case 'P':
     Signed = true;
     Float = false;
@@ -463,6 +466,11 @@ void SVEType::applyModifier(char Mod) {
     Bitwidth = 16;
     ElementBitwidth = 1;
     break;
+  case 'u':
+    Predicate = false;
+    Signed = false;
+    Float = false;
+    break;
   case 'i':
     Predicate = false;
     Float = false;


        


More information about the cfe-commits mailing list