[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