[clang] 378b411 - [clang][AArch64][SVE2p3][SME2p3] Add intrinsics for v9.7a shift operations (#186087)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 28 05:48:56 PDT 2026
Author: Amilendra Kodithuwakku
Date: 2026-04-28T13:48:48+01:00
New Revision: 378b411cf20051e3c3b654eab4347523f7da603f
URL: https://github.com/llvm/llvm-project/commit/378b411cf20051e3c3b654eab4347523f7da603f
DIFF: https://github.com/llvm/llvm-project/commit/378b411cf20051e3c3b654eab4347523f7da603f.diff
LOG: [clang][AArch64][SVE2p3][SME2p3] Add intrinsics for v9.7a shift operations (#186087)
Add the following new clang intrinsics based on the ACLE specification
https://github.com/ARM-software/acle/pull/428 (Add alpha support for 9.7
data processing intrinsics)
Multi-vector saturating rounding shift right narrow and interleave
instructions
- SQRSHRN
- svint8_t svqrshrn_s8(svint16x2_t, uint64_t) / svint8_t
svqrshrn_n_s8_s16_x2(svint16x2_t, uint64_t)
- UQRSHRN
- svuint8_t svqrshrn_u8(svuint16x2_t, uint64_t) / svuint8_t
svqrshrn_n_u8_u16_x2(svuint16x2_t, uint64_t)
- SQRSHRUN
- svuint8_t svqrshrun_u8(svint16x2_t, uint64_t) / svuint8_t
svqrshrun_n_u8_s16_x2(svint16x2_t, uint64_t)
Multi-vector saturating shift right narrow and interleave
- SQSHRN
- svint8_t svqshrn_s8(svint16x2_t, uint64_t) / svint8_t
svqshrn_n_s8_s16_x2(svint16x2_t, uint64_t)
- svint16_t svqshrn_s16(svint32x2_t, uint64_t) / svint16_t
svqshrn_n_s16_s32_x2(svint32x2_t, uint64_t)
- UQSHRN
- svuint8_t svqshrn_u8(svuint16x2_t, uint64_t) / svuint8_t
svqshrn_n_u8_u16_x2(svuint16x2_t, uint64_t)
- svuint16_t svqshrn_u16(svuint32x2_t, uint64_t) / svuint16_t
svqshrn_n_u16_u32_x2(svuint32x2_t, uint64_t)
- SQSHRUN
- svuint8_t svqshrun_u8(svint16x2_t, uint64_t) / svuint8_t
svqshrun_n_u8_s16_x2(svint16x2_t, uint64_t)
- svuint16_t svqshrun_u16(svint32x2_t, uint64_t) / svuint16_t
svqshrun_n_u16_s32_x2(svint32x2_t, uint64_t)
Added:
clang/test/CodeGen/AArch64/sve2p3-intrinsics/acle_sve2p3_qrshr.c
clang/test/CodeGen/AArch64/sve2p3-intrinsics/acle_sve2p3_qshr.c
clang/test/Sema/aarch64-sve2p3-intrinsics/acle_sve2p3_imm.cpp
clang/test/Sema/aarch64-sve2p3-intrinsics/acle_sve2p3_qshrn.cpp
llvm/test/CodeGen/AArch64/sve2p3-intrinsics/sve2p3-intrinsics-qrshr.ll
llvm/test/CodeGen/AArch64/sve2p3-intrinsics/sve2p3-intrinsics-qshr.ll
Modified:
clang/include/clang/Basic/arm_sve.td
clang/test/Sema/AArch64/arm_sve_feature_dependent_sve_AND_LP_sve2p3_OR_sme2p3_RP___sme_AND_LP_sve2p3_OR_sme2p3_RP.c
llvm/include/llvm/IR/IntrinsicsAArch64.td
llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
llvm/lib/Target/AArch64/SVEInstrFormats.td
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/arm_sve.td b/clang/include/clang/Basic/arm_sve.td
index 59424f400098b..242ac7bed6e10 100644
--- a/clang/include/clang/Basic/arm_sve.td
+++ b/clang/include/clang/Basic/arm_sve.td
@@ -2253,6 +2253,15 @@ let SVETargetGuard = "sve2p1|sme2", SMETargetGuard = "sve2p1|sme2" in {
def SVSQRSHRUN_X2 : SInst<"svqrshrun[_n]_{0}[_{d}_x2]", "e2i", "i", MergeNone, "aarch64_sve_sqrshrun_x2", [VerifyRuntimeMode], [ImmCheck<1, ImmCheck1_16>]>;
}
+//
+// Multi-vector saturating rounding shift right narrow and interleave
+//
+let SVETargetGuard = "sve2p3|sme2p3", SMETargetGuard = "sve2p3|sme2p3" in {
+ def SVSQRSHRN_X2_S8 : SInst<"svqrshrn[_n]_{0}[_{d}_x2]", "h2i", "s", MergeNone, "aarch64_sve_sqrshrn_x2", [VerifyRuntimeMode], [ImmCheck<1, ImmCheckShiftRightNarrow, 0>]>;
+ def SVUQRSHRN_X2_U8 : SInst<"svqrshrn[_n]_{0}[_{d}_x2]", "e2i", "Us", MergeNone, "aarch64_sve_uqrshrn_x2", [VerifyRuntimeMode], [ImmCheck<1, ImmCheckShiftRightNarrow, 0>]>;
+ def SVSQRSHRUN_X2_S8 : SInst<"svqrshrun[_n]_{0}[_{d}_x2]", "e2i", "s", MergeNone, "aarch64_sve_sqrshrun_x2", [VerifyRuntimeMode], [ImmCheck<1, ImmCheckShiftRightNarrow, 0>]>;
+}
+
let SVETargetGuard = "sve2p1|sme2p1", SMETargetGuard = "sve2p1|sme2p1" in {
def SVZIPQ1 : SInst<"svzipq1[_{d}]", "ddd", "cUcsUsiUilUlbhfdm", MergeNone, "aarch64_sve_zipq1", [VerifyRuntimeMode], []>;
def SVZIPQ2 : SInst<"svzipq2[_{d}]", "ddd", "cUcsUsiUilUlbhfdm", MergeNone, "aarch64_sve_zipq2", [VerifyRuntimeMode], []>;
@@ -2332,6 +2341,15 @@ let SVETargetGuard = InvalidMode, SMETargetGuard = "sme-f16f16" in {
def SVCVTL_F32_X2 : SInst<"svcvtl_f32[_f16_x2]", "2h", "f", MergeNone, "aarch64_sve_fcvtl_widen_x2", [ IsStreaming],[]>;
}
+//
+// Multi-vector saturating shift right narrow and interleave
+//
+let SVETargetGuard = "sve2p3|sme2p3", SMETargetGuard = "sve2p3|sme2p3" in {
+ def SVSQSHRN_X2 : SInst<"svqshrn[_n]_{0}[_{d}_x2]", "h2i", "is", MergeNone, "aarch64_sve_sqshrn_x2", [VerifyRuntimeMode], [ImmCheck<1, ImmCheckShiftRightNarrow, 0>]>;
+ def SVUQSHRN_X2 : SInst<"svqshrn[_n]_{0}[_{d}_x2]", "e2i", "UiUs", MergeNone, "aarch64_sve_uqshrn_x2", [VerifyRuntimeMode], [ImmCheck<1, ImmCheckShiftRightNarrow, 0>]>;
+ def SVSQSHRUN_X2 : SInst<"svqshrun[_n]_{0}[_{d}_x2]", "e2i", "is", MergeNone, "aarch64_sve_sqshrun_x2", [VerifyRuntimeMode], [ImmCheck<1, ImmCheckShiftRightNarrow, 0>]>;
+}
+
//
// Multi-vector saturating extract narrow
//
diff --git a/clang/test/CodeGen/AArch64/sve2p3-intrinsics/acle_sve2p3_qrshr.c b/clang/test/CodeGen/AArch64/sve2p3-intrinsics/acle_sve2p3_qrshr.c
new file mode 100644
index 0000000000000..1e76ab8defac8
--- /dev/null
+++ b/clang/test/CodeGen/AArch64/sve2p3-intrinsics/acle_sve2p3_qrshr.c
@@ -0,0 +1,144 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sve -target-feature +sve2p3 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sve -target-feature +sve2p3 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sme -target-feature +sme2p3 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sve -target-feature +sme2p3 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sme -target-feature +sve2p3 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2p3 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2p3 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK
+// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme -target-feature +sme2p3 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sme2p3 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme -target-feature +sve2p3 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sve -target-feature +sve2p3 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sme -target-feature +sme2p3 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s
+
+// REQUIRES: aarch64-registered-target
+
+#include <arm_sve.h>
+
+#if defined(__ARM_FEATURE_SME) && defined(__ARM_FEATURE_SVE)
+#define ATTR __arm_streaming_compatible
+#elif defined(__ARM_FEATURE_SME)
+#define ATTR __arm_streaming
+#else
+#define ATTR
+#endif
+
+#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
+
+// CHECK-LABEL: define dso_local <vscale x 16 x i8> @test_svqrshrn_n_s8_s16_x2(
+// CHECK-SAME: <vscale x 8 x i16> [[ZN_COERCE0:%.*]], <vscale x 8 x i16> [[ZN_COERCE1:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[ZN:%.*]] = alloca { <vscale x 8 x i16>, <vscale x 8 x i16> }, align 16
+// CHECK-NEXT: [[ZN_ADDR:%.*]] = alloca { <vscale x 8 x i16>, <vscale x 8 x i16> }, align 16
+// CHECK-NEXT: [[TMP0:%.*]] = insertvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } poison, <vscale x 8 x i16> [[ZN_COERCE0]], 0
+// CHECK-NEXT: [[TMP1:%.*]] = insertvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP0]], <vscale x 8 x i16> [[ZN_COERCE1]], 1
+// CHECK-NEXT: store { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP1]], ptr [[ZN]], align 16
+// CHECK-NEXT: [[ZN1:%.*]] = load { <vscale x 8 x i16>, <vscale x 8 x i16> }, ptr [[ZN]], align 16
+// CHECK-NEXT: store { <vscale x 8 x i16>, <vscale x 8 x i16> } [[ZN1]], ptr [[ZN_ADDR]], align 16
+// CHECK-NEXT: [[TMP2:%.*]] = load { <vscale x 8 x i16>, <vscale x 8 x i16> }, ptr [[ZN_ADDR]], align 16
+// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP2]], 0
+// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP2]], 1
+// CHECK-NEXT: [[TMP5:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.sqrshrn.x2.nxv8i16(<vscale x 8 x i16> [[TMP3]], <vscale x 8 x i16> [[TMP4]], i32 8)
+// CHECK-NEXT: ret <vscale x 16 x i8> [[TMP5]]
+//
+// CPP-CHECK-LABEL: define dso_local <vscale x 16 x i8> @_Z25test_svqrshrn_n_s8_s16_x211svint16x2_t(
+// CPP-CHECK-SAME: <vscale x 8 x i16> [[ZN_COERCE0:%.*]], <vscale x 8 x i16> [[ZN_COERCE1:%.*]]) #[[ATTR0:[0-9]+]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: [[ZN:%.*]] = alloca { <vscale x 8 x i16>, <vscale x 8 x i16> }, align 16
+// CPP-CHECK-NEXT: [[ZN_ADDR:%.*]] = alloca { <vscale x 8 x i16>, <vscale x 8 x i16> }, align 16
+// CPP-CHECK-NEXT: [[TMP0:%.*]] = insertvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } poison, <vscale x 8 x i16> [[ZN_COERCE0]], 0
+// CPP-CHECK-NEXT: [[TMP1:%.*]] = insertvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP0]], <vscale x 8 x i16> [[ZN_COERCE1]], 1
+// CPP-CHECK-NEXT: store { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP1]], ptr [[ZN]], align 16
+// CPP-CHECK-NEXT: [[ZN1:%.*]] = load { <vscale x 8 x i16>, <vscale x 8 x i16> }, ptr [[ZN]], align 16
+// CPP-CHECK-NEXT: store { <vscale x 8 x i16>, <vscale x 8 x i16> } [[ZN1]], ptr [[ZN_ADDR]], align 16
+// CPP-CHECK-NEXT: [[TMP2:%.*]] = load { <vscale x 8 x i16>, <vscale x 8 x i16> }, ptr [[ZN_ADDR]], align 16
+// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP2]], 0
+// CPP-CHECK-NEXT: [[TMP4:%.*]] = extractvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP2]], 1
+// CPP-CHECK-NEXT: [[TMP5:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.sqrshrn.x2.nxv8i16(<vscale x 8 x i16> [[TMP3]], <vscale x 8 x i16> [[TMP4]], i32 8)
+// CPP-CHECK-NEXT: ret <vscale x 16 x i8> [[TMP5]]
+//
+svint8_t test_svqrshrn_n_s8_s16_x2(svint16x2_t zn) ATTR
+{
+ return SVE_ACLE_FUNC(svqrshrn,_n,_s8,_s16_x2)(zn, 8);
+}
+
+// CHECK-LABEL: define dso_local <vscale x 16 x i8> @test_svqrshrn_n_u8_u16_x2(
+// CHECK-SAME: <vscale x 8 x i16> [[ZN_COERCE0:%.*]], <vscale x 8 x i16> [[ZN_COERCE1:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[ZN:%.*]] = alloca { <vscale x 8 x i16>, <vscale x 8 x i16> }, align 16
+// CHECK-NEXT: [[ZN_ADDR:%.*]] = alloca { <vscale x 8 x i16>, <vscale x 8 x i16> }, align 16
+// CHECK-NEXT: [[TMP0:%.*]] = insertvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } poison, <vscale x 8 x i16> [[ZN_COERCE0]], 0
+// CHECK-NEXT: [[TMP1:%.*]] = insertvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP0]], <vscale x 8 x i16> [[ZN_COERCE1]], 1
+// CHECK-NEXT: store { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP1]], ptr [[ZN]], align 16
+// CHECK-NEXT: [[ZN1:%.*]] = load { <vscale x 8 x i16>, <vscale x 8 x i16> }, ptr [[ZN]], align 16
+// CHECK-NEXT: store { <vscale x 8 x i16>, <vscale x 8 x i16> } [[ZN1]], ptr [[ZN_ADDR]], align 16
+// CHECK-NEXT: [[TMP2:%.*]] = load { <vscale x 8 x i16>, <vscale x 8 x i16> }, ptr [[ZN_ADDR]], align 16
+// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP2]], 0
+// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP2]], 1
+// CHECK-NEXT: [[TMP5:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.uqrshrn.x2.nxv8i16(<vscale x 8 x i16> [[TMP3]], <vscale x 8 x i16> [[TMP4]], i32 8)
+// CHECK-NEXT: ret <vscale x 16 x i8> [[TMP5]]
+//
+// CPP-CHECK-LABEL: define dso_local <vscale x 16 x i8> @_Z25test_svqrshrn_n_u8_u16_x212svuint16x2_t(
+// CPP-CHECK-SAME: <vscale x 8 x i16> [[ZN_COERCE0:%.*]], <vscale x 8 x i16> [[ZN_COERCE1:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: [[ZN:%.*]] = alloca { <vscale x 8 x i16>, <vscale x 8 x i16> }, align 16
+// CPP-CHECK-NEXT: [[ZN_ADDR:%.*]] = alloca { <vscale x 8 x i16>, <vscale x 8 x i16> }, align 16
+// CPP-CHECK-NEXT: [[TMP0:%.*]] = insertvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } poison, <vscale x 8 x i16> [[ZN_COERCE0]], 0
+// CPP-CHECK-NEXT: [[TMP1:%.*]] = insertvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP0]], <vscale x 8 x i16> [[ZN_COERCE1]], 1
+// CPP-CHECK-NEXT: store { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP1]], ptr [[ZN]], align 16
+// CPP-CHECK-NEXT: [[ZN1:%.*]] = load { <vscale x 8 x i16>, <vscale x 8 x i16> }, ptr [[ZN]], align 16
+// CPP-CHECK-NEXT: store { <vscale x 8 x i16>, <vscale x 8 x i16> } [[ZN1]], ptr [[ZN_ADDR]], align 16
+// CPP-CHECK-NEXT: [[TMP2:%.*]] = load { <vscale x 8 x i16>, <vscale x 8 x i16> }, ptr [[ZN_ADDR]], align 16
+// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP2]], 0
+// CPP-CHECK-NEXT: [[TMP4:%.*]] = extractvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP2]], 1
+// CPP-CHECK-NEXT: [[TMP5:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.uqrshrn.x2.nxv8i16(<vscale x 8 x i16> [[TMP3]], <vscale x 8 x i16> [[TMP4]], i32 8)
+// CPP-CHECK-NEXT: ret <vscale x 16 x i8> [[TMP5]]
+//
+svuint8_t test_svqrshrn_n_u8_u16_x2(svuint16x2_t zn) ATTR
+{
+ return SVE_ACLE_FUNC(svqrshrn,_n,_u8,_u16_x2)(zn, 8);
+}
+
+// CHECK-LABEL: define dso_local <vscale x 16 x i8> @test_svqrshrun_n_u8_s16_x2(
+// CHECK-SAME: <vscale x 8 x i16> [[ZN_COERCE0:%.*]], <vscale x 8 x i16> [[ZN_COERCE1:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[ZN:%.*]] = alloca { <vscale x 8 x i16>, <vscale x 8 x i16> }, align 16
+// CHECK-NEXT: [[ZN_ADDR:%.*]] = alloca { <vscale x 8 x i16>, <vscale x 8 x i16> }, align 16
+// CHECK-NEXT: [[TMP0:%.*]] = insertvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } poison, <vscale x 8 x i16> [[ZN_COERCE0]], 0
+// CHECK-NEXT: [[TMP1:%.*]] = insertvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP0]], <vscale x 8 x i16> [[ZN_COERCE1]], 1
+// CHECK-NEXT: store { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP1]], ptr [[ZN]], align 16
+// CHECK-NEXT: [[ZN1:%.*]] = load { <vscale x 8 x i16>, <vscale x 8 x i16> }, ptr [[ZN]], align 16
+// CHECK-NEXT: store { <vscale x 8 x i16>, <vscale x 8 x i16> } [[ZN1]], ptr [[ZN_ADDR]], align 16
+// CHECK-NEXT: [[TMP2:%.*]] = load { <vscale x 8 x i16>, <vscale x 8 x i16> }, ptr [[ZN_ADDR]], align 16
+// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP2]], 0
+// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP2]], 1
+// CHECK-NEXT: [[TMP5:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.sqrshrun.x2.nxv8i16(<vscale x 8 x i16> [[TMP3]], <vscale x 8 x i16> [[TMP4]], i32 8)
+// CHECK-NEXT: ret <vscale x 16 x i8> [[TMP5]]
+//
+// CPP-CHECK-LABEL: define dso_local <vscale x 16 x i8> @_Z26test_svqrshrun_n_u8_s16_x211svint16x2_t(
+// CPP-CHECK-SAME: <vscale x 8 x i16> [[ZN_COERCE0:%.*]], <vscale x 8 x i16> [[ZN_COERCE1:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: [[ZN:%.*]] = alloca { <vscale x 8 x i16>, <vscale x 8 x i16> }, align 16
+// CPP-CHECK-NEXT: [[ZN_ADDR:%.*]] = alloca { <vscale x 8 x i16>, <vscale x 8 x i16> }, align 16
+// CPP-CHECK-NEXT: [[TMP0:%.*]] = insertvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } poison, <vscale x 8 x i16> [[ZN_COERCE0]], 0
+// CPP-CHECK-NEXT: [[TMP1:%.*]] = insertvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP0]], <vscale x 8 x i16> [[ZN_COERCE1]], 1
+// CPP-CHECK-NEXT: store { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP1]], ptr [[ZN]], align 16
+// CPP-CHECK-NEXT: [[ZN1:%.*]] = load { <vscale x 8 x i16>, <vscale x 8 x i16> }, ptr [[ZN]], align 16
+// CPP-CHECK-NEXT: store { <vscale x 8 x i16>, <vscale x 8 x i16> } [[ZN1]], ptr [[ZN_ADDR]], align 16
+// CPP-CHECK-NEXT: [[TMP2:%.*]] = load { <vscale x 8 x i16>, <vscale x 8 x i16> }, ptr [[ZN_ADDR]], align 16
+// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP2]], 0
+// CPP-CHECK-NEXT: [[TMP4:%.*]] = extractvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP2]], 1
+// CPP-CHECK-NEXT: [[TMP5:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.sqrshrun.x2.nxv8i16(<vscale x 8 x i16> [[TMP3]], <vscale x 8 x i16> [[TMP4]], i32 8)
+// CPP-CHECK-NEXT: ret <vscale x 16 x i8> [[TMP5]]
+//
+svuint8_t test_svqrshrun_n_u8_s16_x2(svint16x2_t zn) ATTR
+{
+ return SVE_ACLE_FUNC(svqrshrun,_n,_u8,_s16_x2)(zn, 8);
+}
diff --git a/clang/test/CodeGen/AArch64/sve2p3-intrinsics/acle_sve2p3_qshr.c b/clang/test/CodeGen/AArch64/sve2p3-intrinsics/acle_sve2p3_qshr.c
new file mode 100644
index 0000000000000..bf65771c58708
--- /dev/null
+++ b/clang/test/CodeGen/AArch64/sve2p3-intrinsics/acle_sve2p3_qshr.c
@@ -0,0 +1,255 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sve -target-feature +sve2p3 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sve -target-feature +sve2p3 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sme -target-feature +sme2p3 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sve -target-feature +sme2p3 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sme -target-feature +sve2p3 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2p3 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2p3 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK
+// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme -target-feature +sme2p3 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sme2p3 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme -target-feature +sve2p3 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sve -target-feature +sve2p3 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sme -target-feature +sme2p3 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s
+
+// REQUIRES: aarch64-registered-target
+
+#include <arm_sve.h>
+
+#if defined(__ARM_FEATURE_SME) && defined(__ARM_FEATURE_SVE)
+#define ATTR __arm_streaming_compatible
+#elif defined(__ARM_FEATURE_SME)
+#define ATTR __arm_streaming
+#else
+#define ATTR
+#endif
+
+#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
+
+// CHECK-LABEL: define dso_local <vscale x 16 x i8> @test_svqshrn_n_s8_s16_x2(
+// CHECK-SAME: <vscale x 8 x i16> [[ZN_COERCE0:%.*]], <vscale x 8 x i16> [[ZN_COERCE1:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[ZN:%.*]] = alloca { <vscale x 8 x i16>, <vscale x 8 x i16> }, align 16
+// CHECK-NEXT: [[ZN_ADDR:%.*]] = alloca { <vscale x 8 x i16>, <vscale x 8 x i16> }, align 16
+// CHECK-NEXT: [[TMP0:%.*]] = insertvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } poison, <vscale x 8 x i16> [[ZN_COERCE0]], 0
+// CHECK-NEXT: [[TMP1:%.*]] = insertvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP0]], <vscale x 8 x i16> [[ZN_COERCE1]], 1
+// CHECK-NEXT: store { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP1]], ptr [[ZN]], align 16
+// CHECK-NEXT: [[ZN1:%.*]] = load { <vscale x 8 x i16>, <vscale x 8 x i16> }, ptr [[ZN]], align 16
+// CHECK-NEXT: store { <vscale x 8 x i16>, <vscale x 8 x i16> } [[ZN1]], ptr [[ZN_ADDR]], align 16
+// CHECK-NEXT: [[TMP2:%.*]] = load { <vscale x 8 x i16>, <vscale x 8 x i16> }, ptr [[ZN_ADDR]], align 16
+// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP2]], 0
+// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP2]], 1
+// CHECK-NEXT: [[TMP5:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.sqshrn.x2.nxv8i16(<vscale x 8 x i16> [[TMP3]], <vscale x 8 x i16> [[TMP4]], i32 8)
+// CHECK-NEXT: ret <vscale x 16 x i8> [[TMP5]]
+//
+// CPP-CHECK-LABEL: define dso_local <vscale x 16 x i8> @_Z24test_svqshrn_n_s8_s16_x211svint16x2_t(
+// CPP-CHECK-SAME: <vscale x 8 x i16> [[ZN_COERCE0:%.*]], <vscale x 8 x i16> [[ZN_COERCE1:%.*]]) #[[ATTR0:[0-9]+]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: [[ZN:%.*]] = alloca { <vscale x 8 x i16>, <vscale x 8 x i16> }, align 16
+// CPP-CHECK-NEXT: [[ZN_ADDR:%.*]] = alloca { <vscale x 8 x i16>, <vscale x 8 x i16> }, align 16
+// CPP-CHECK-NEXT: [[TMP0:%.*]] = insertvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } poison, <vscale x 8 x i16> [[ZN_COERCE0]], 0
+// CPP-CHECK-NEXT: [[TMP1:%.*]] = insertvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP0]], <vscale x 8 x i16> [[ZN_COERCE1]], 1
+// CPP-CHECK-NEXT: store { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP1]], ptr [[ZN]], align 16
+// CPP-CHECK-NEXT: [[ZN1:%.*]] = load { <vscale x 8 x i16>, <vscale x 8 x i16> }, ptr [[ZN]], align 16
+// CPP-CHECK-NEXT: store { <vscale x 8 x i16>, <vscale x 8 x i16> } [[ZN1]], ptr [[ZN_ADDR]], align 16
+// CPP-CHECK-NEXT: [[TMP2:%.*]] = load { <vscale x 8 x i16>, <vscale x 8 x i16> }, ptr [[ZN_ADDR]], align 16
+// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP2]], 0
+// CPP-CHECK-NEXT: [[TMP4:%.*]] = extractvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP2]], 1
+// CPP-CHECK-NEXT: [[TMP5:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.sqshrn.x2.nxv8i16(<vscale x 8 x i16> [[TMP3]], <vscale x 8 x i16> [[TMP4]], i32 8)
+// CPP-CHECK-NEXT: ret <vscale x 16 x i8> [[TMP5]]
+//
+svint8_t test_svqshrn_n_s8_s16_x2(svint16x2_t zn) ATTR
+{
+ return SVE_ACLE_FUNC(svqshrn,_n,_s8,_s16_x2)(zn, 8);
+}
+
+// CHECK-LABEL: define dso_local <vscale x 8 x i16> @test_svqshrn_n_s16_s32_x2(
+// CHECK-SAME: <vscale x 4 x i32> [[ZN_COERCE0:%.*]], <vscale x 4 x i32> [[ZN_COERCE1:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[ZN:%.*]] = alloca { <vscale x 4 x i32>, <vscale x 4 x i32> }, align 16
+// CHECK-NEXT: [[ZN_ADDR:%.*]] = alloca { <vscale x 4 x i32>, <vscale x 4 x i32> }, align 16
+// CHECK-NEXT: [[TMP0:%.*]] = insertvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } poison, <vscale x 4 x i32> [[ZN_COERCE0]], 0
+// CHECK-NEXT: [[TMP1:%.*]] = insertvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[TMP0]], <vscale x 4 x i32> [[ZN_COERCE1]], 1
+// CHECK-NEXT: store { <vscale x 4 x i32>, <vscale x 4 x i32> } [[TMP1]], ptr [[ZN]], align 16
+// CHECK-NEXT: [[ZN1:%.*]] = load { <vscale x 4 x i32>, <vscale x 4 x i32> }, ptr [[ZN]], align 16
+// CHECK-NEXT: store { <vscale x 4 x i32>, <vscale x 4 x i32> } [[ZN1]], ptr [[ZN_ADDR]], align 16
+// CHECK-NEXT: [[TMP2:%.*]] = load { <vscale x 4 x i32>, <vscale x 4 x i32> }, ptr [[ZN_ADDR]], align 16
+// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[TMP2]], 0
+// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[TMP2]], 1
+// CHECK-NEXT: [[TMP5:%.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.sqshrn.x2.nxv4i32(<vscale x 4 x i32> [[TMP3]], <vscale x 4 x i32> [[TMP4]], i32 16)
+// CHECK-NEXT: ret <vscale x 8 x i16> [[TMP5]]
+//
+// CPP-CHECK-LABEL: define dso_local <vscale x 8 x i16> @_Z25test_svqshrn_n_s16_s32_x211svint32x2_t(
+// CPP-CHECK-SAME: <vscale x 4 x i32> [[ZN_COERCE0:%.*]], <vscale x 4 x i32> [[ZN_COERCE1:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: [[ZN:%.*]] = alloca { <vscale x 4 x i32>, <vscale x 4 x i32> }, align 16
+// CPP-CHECK-NEXT: [[ZN_ADDR:%.*]] = alloca { <vscale x 4 x i32>, <vscale x 4 x i32> }, align 16
+// CPP-CHECK-NEXT: [[TMP0:%.*]] = insertvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } poison, <vscale x 4 x i32> [[ZN_COERCE0]], 0
+// CPP-CHECK-NEXT: [[TMP1:%.*]] = insertvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[TMP0]], <vscale x 4 x i32> [[ZN_COERCE1]], 1
+// CPP-CHECK-NEXT: store { <vscale x 4 x i32>, <vscale x 4 x i32> } [[TMP1]], ptr [[ZN]], align 16
+// CPP-CHECK-NEXT: [[ZN1:%.*]] = load { <vscale x 4 x i32>, <vscale x 4 x i32> }, ptr [[ZN]], align 16
+// CPP-CHECK-NEXT: store { <vscale x 4 x i32>, <vscale x 4 x i32> } [[ZN1]], ptr [[ZN_ADDR]], align 16
+// CPP-CHECK-NEXT: [[TMP2:%.*]] = load { <vscale x 4 x i32>, <vscale x 4 x i32> }, ptr [[ZN_ADDR]], align 16
+// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[TMP2]], 0
+// CPP-CHECK-NEXT: [[TMP4:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[TMP2]], 1
+// CPP-CHECK-NEXT: [[TMP5:%.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.sqshrn.x2.nxv4i32(<vscale x 4 x i32> [[TMP3]], <vscale x 4 x i32> [[TMP4]], i32 16)
+// CPP-CHECK-NEXT: ret <vscale x 8 x i16> [[TMP5]]
+//
+svint16_t test_svqshrn_n_s16_s32_x2(svint32x2_t zn) ATTR
+{
+ return SVE_ACLE_FUNC(svqshrn,_n,_s16,_s32_x2)(zn, 16);
+}
+
+// CHECK-LABEL: define dso_local <vscale x 16 x i8> @test_svqshrn_n_u8_u16_x2(
+// CHECK-SAME: <vscale x 8 x i16> [[ZN_COERCE0:%.*]], <vscale x 8 x i16> [[ZN_COERCE1:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[ZN:%.*]] = alloca { <vscale x 8 x i16>, <vscale x 8 x i16> }, align 16
+// CHECK-NEXT: [[ZN_ADDR:%.*]] = alloca { <vscale x 8 x i16>, <vscale x 8 x i16> }, align 16
+// CHECK-NEXT: [[TMP0:%.*]] = insertvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } poison, <vscale x 8 x i16> [[ZN_COERCE0]], 0
+// CHECK-NEXT: [[TMP1:%.*]] = insertvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP0]], <vscale x 8 x i16> [[ZN_COERCE1]], 1
+// CHECK-NEXT: store { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP1]], ptr [[ZN]], align 16
+// CHECK-NEXT: [[ZN1:%.*]] = load { <vscale x 8 x i16>, <vscale x 8 x i16> }, ptr [[ZN]], align 16
+// CHECK-NEXT: store { <vscale x 8 x i16>, <vscale x 8 x i16> } [[ZN1]], ptr [[ZN_ADDR]], align 16
+// CHECK-NEXT: [[TMP2:%.*]] = load { <vscale x 8 x i16>, <vscale x 8 x i16> }, ptr [[ZN_ADDR]], align 16
+// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP2]], 0
+// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP2]], 1
+// CHECK-NEXT: [[TMP5:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.uqshrn.x2.nxv8i16(<vscale x 8 x i16> [[TMP3]], <vscale x 8 x i16> [[TMP4]], i32 8)
+// CHECK-NEXT: ret <vscale x 16 x i8> [[TMP5]]
+//
+// CPP-CHECK-LABEL: define dso_local <vscale x 16 x i8> @_Z24test_svqshrn_n_u8_u16_x212svuint16x2_t(
+// CPP-CHECK-SAME: <vscale x 8 x i16> [[ZN_COERCE0:%.*]], <vscale x 8 x i16> [[ZN_COERCE1:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: [[ZN:%.*]] = alloca { <vscale x 8 x i16>, <vscale x 8 x i16> }, align 16
+// CPP-CHECK-NEXT: [[ZN_ADDR:%.*]] = alloca { <vscale x 8 x i16>, <vscale x 8 x i16> }, align 16
+// CPP-CHECK-NEXT: [[TMP0:%.*]] = insertvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } poison, <vscale x 8 x i16> [[ZN_COERCE0]], 0
+// CPP-CHECK-NEXT: [[TMP1:%.*]] = insertvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP0]], <vscale x 8 x i16> [[ZN_COERCE1]], 1
+// CPP-CHECK-NEXT: store { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP1]], ptr [[ZN]], align 16
+// CPP-CHECK-NEXT: [[ZN1:%.*]] = load { <vscale x 8 x i16>, <vscale x 8 x i16> }, ptr [[ZN]], align 16
+// CPP-CHECK-NEXT: store { <vscale x 8 x i16>, <vscale x 8 x i16> } [[ZN1]], ptr [[ZN_ADDR]], align 16
+// CPP-CHECK-NEXT: [[TMP2:%.*]] = load { <vscale x 8 x i16>, <vscale x 8 x i16> }, ptr [[ZN_ADDR]], align 16
+// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP2]], 0
+// CPP-CHECK-NEXT: [[TMP4:%.*]] = extractvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP2]], 1
+// CPP-CHECK-NEXT: [[TMP5:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.uqshrn.x2.nxv8i16(<vscale x 8 x i16> [[TMP3]], <vscale x 8 x i16> [[TMP4]], i32 8)
+// CPP-CHECK-NEXT: ret <vscale x 16 x i8> [[TMP5]]
+//
+svuint8_t test_svqshrn_n_u8_u16_x2(svuint16x2_t zn) ATTR
+{
+ return SVE_ACLE_FUNC(svqshrn,_n,_u8,_u16_x2)(zn, 8);
+}
+
+// CHECK-LABEL: define dso_local <vscale x 8 x i16> @test_svqshrn_n_u16_u32_x2(
+// CHECK-SAME: <vscale x 4 x i32> [[ZN_COERCE0:%.*]], <vscale x 4 x i32> [[ZN_COERCE1:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[ZN:%.*]] = alloca { <vscale x 4 x i32>, <vscale x 4 x i32> }, align 16
+// CHECK-NEXT: [[ZN_ADDR:%.*]] = alloca { <vscale x 4 x i32>, <vscale x 4 x i32> }, align 16
+// CHECK-NEXT: [[TMP0:%.*]] = insertvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } poison, <vscale x 4 x i32> [[ZN_COERCE0]], 0
+// CHECK-NEXT: [[TMP1:%.*]] = insertvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[TMP0]], <vscale x 4 x i32> [[ZN_COERCE1]], 1
+// CHECK-NEXT: store { <vscale x 4 x i32>, <vscale x 4 x i32> } [[TMP1]], ptr [[ZN]], align 16
+// CHECK-NEXT: [[ZN1:%.*]] = load { <vscale x 4 x i32>, <vscale x 4 x i32> }, ptr [[ZN]], align 16
+// CHECK-NEXT: store { <vscale x 4 x i32>, <vscale x 4 x i32> } [[ZN1]], ptr [[ZN_ADDR]], align 16
+// CHECK-NEXT: [[TMP2:%.*]] = load { <vscale x 4 x i32>, <vscale x 4 x i32> }, ptr [[ZN_ADDR]], align 16
+// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[TMP2]], 0
+// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[TMP2]], 1
+// CHECK-NEXT: [[TMP5:%.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.uqshrn.x2.nxv4i32(<vscale x 4 x i32> [[TMP3]], <vscale x 4 x i32> [[TMP4]], i32 16)
+// CHECK-NEXT: ret <vscale x 8 x i16> [[TMP5]]
+//
+// CPP-CHECK-LABEL: define dso_local <vscale x 8 x i16> @_Z25test_svqshrn_n_u16_u32_x212svuint32x2_t(
+// CPP-CHECK-SAME: <vscale x 4 x i32> [[ZN_COERCE0:%.*]], <vscale x 4 x i32> [[ZN_COERCE1:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: [[ZN:%.*]] = alloca { <vscale x 4 x i32>, <vscale x 4 x i32> }, align 16
+// CPP-CHECK-NEXT: [[ZN_ADDR:%.*]] = alloca { <vscale x 4 x i32>, <vscale x 4 x i32> }, align 16
+// CPP-CHECK-NEXT: [[TMP0:%.*]] = insertvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } poison, <vscale x 4 x i32> [[ZN_COERCE0]], 0
+// CPP-CHECK-NEXT: [[TMP1:%.*]] = insertvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[TMP0]], <vscale x 4 x i32> [[ZN_COERCE1]], 1
+// CPP-CHECK-NEXT: store { <vscale x 4 x i32>, <vscale x 4 x i32> } [[TMP1]], ptr [[ZN]], align 16
+// CPP-CHECK-NEXT: [[ZN1:%.*]] = load { <vscale x 4 x i32>, <vscale x 4 x i32> }, ptr [[ZN]], align 16
+// CPP-CHECK-NEXT: store { <vscale x 4 x i32>, <vscale x 4 x i32> } [[ZN1]], ptr [[ZN_ADDR]], align 16
+// CPP-CHECK-NEXT: [[TMP2:%.*]] = load { <vscale x 4 x i32>, <vscale x 4 x i32> }, ptr [[ZN_ADDR]], align 16
+// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[TMP2]], 0
+// CPP-CHECK-NEXT: [[TMP4:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[TMP2]], 1
+// CPP-CHECK-NEXT: [[TMP5:%.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.uqshrn.x2.nxv4i32(<vscale x 4 x i32> [[TMP3]], <vscale x 4 x i32> [[TMP4]], i32 16)
+// CPP-CHECK-NEXT: ret <vscale x 8 x i16> [[TMP5]]
+//
+svuint16_t test_svqshrn_n_u16_u32_x2(svuint32x2_t zn) ATTR
+{
+ return SVE_ACLE_FUNC(svqshrn,_n,_u16,_u32_x2)(zn, 16);
+}
+
+// CHECK-LABEL: define dso_local <vscale x 8 x i16> @test_svqshrun_n_u16_s32_x2(
+// CHECK-SAME: <vscale x 4 x i32> [[ZN_COERCE0:%.*]], <vscale x 4 x i32> [[ZN_COERCE1:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[ZN:%.*]] = alloca { <vscale x 4 x i32>, <vscale x 4 x i32> }, align 16
+// CHECK-NEXT: [[ZN_ADDR:%.*]] = alloca { <vscale x 4 x i32>, <vscale x 4 x i32> }, align 16
+// CHECK-NEXT: [[TMP0:%.*]] = insertvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } poison, <vscale x 4 x i32> [[ZN_COERCE0]], 0
+// CHECK-NEXT: [[TMP1:%.*]] = insertvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[TMP0]], <vscale x 4 x i32> [[ZN_COERCE1]], 1
+// CHECK-NEXT: store { <vscale x 4 x i32>, <vscale x 4 x i32> } [[TMP1]], ptr [[ZN]], align 16
+// CHECK-NEXT: [[ZN1:%.*]] = load { <vscale x 4 x i32>, <vscale x 4 x i32> }, ptr [[ZN]], align 16
+// CHECK-NEXT: store { <vscale x 4 x i32>, <vscale x 4 x i32> } [[ZN1]], ptr [[ZN_ADDR]], align 16
+// CHECK-NEXT: [[TMP2:%.*]] = load { <vscale x 4 x i32>, <vscale x 4 x i32> }, ptr [[ZN_ADDR]], align 16
+// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[TMP2]], 0
+// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[TMP2]], 1
+// CHECK-NEXT: [[TMP5:%.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.sqshrun.x2.nxv4i32(<vscale x 4 x i32> [[TMP3]], <vscale x 4 x i32> [[TMP4]], i32 16)
+// CHECK-NEXT: ret <vscale x 8 x i16> [[TMP5]]
+//
+// CPP-CHECK-LABEL: define dso_local <vscale x 8 x i16> @_Z26test_svqshrun_n_u16_s32_x211svint32x2_t(
+// CPP-CHECK-SAME: <vscale x 4 x i32> [[ZN_COERCE0:%.*]], <vscale x 4 x i32> [[ZN_COERCE1:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: [[ZN:%.*]] = alloca { <vscale x 4 x i32>, <vscale x 4 x i32> }, align 16
+// CPP-CHECK-NEXT: [[ZN_ADDR:%.*]] = alloca { <vscale x 4 x i32>, <vscale x 4 x i32> }, align 16
+// CPP-CHECK-NEXT: [[TMP0:%.*]] = insertvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } poison, <vscale x 4 x i32> [[ZN_COERCE0]], 0
+// CPP-CHECK-NEXT: [[TMP1:%.*]] = insertvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[TMP0]], <vscale x 4 x i32> [[ZN_COERCE1]], 1
+// CPP-CHECK-NEXT: store { <vscale x 4 x i32>, <vscale x 4 x i32> } [[TMP1]], ptr [[ZN]], align 16
+// CPP-CHECK-NEXT: [[ZN1:%.*]] = load { <vscale x 4 x i32>, <vscale x 4 x i32> }, ptr [[ZN]], align 16
+// CPP-CHECK-NEXT: store { <vscale x 4 x i32>, <vscale x 4 x i32> } [[ZN1]], ptr [[ZN_ADDR]], align 16
+// CPP-CHECK-NEXT: [[TMP2:%.*]] = load { <vscale x 4 x i32>, <vscale x 4 x i32> }, ptr [[ZN_ADDR]], align 16
+// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[TMP2]], 0
+// CPP-CHECK-NEXT: [[TMP4:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[TMP2]], 1
+// CPP-CHECK-NEXT: [[TMP5:%.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.sqshrun.x2.nxv4i32(<vscale x 4 x i32> [[TMP3]], <vscale x 4 x i32> [[TMP4]], i32 16)
+// CPP-CHECK-NEXT: ret <vscale x 8 x i16> [[TMP5]]
+//
+svuint16_t test_svqshrun_n_u16_s32_x2(svint32x2_t zn) ATTR
+{
+ return SVE_ACLE_FUNC(svqshrun,_n,_u16,_s32_x2)(zn, 16);
+}
+
+// CHECK-LABEL: define dso_local <vscale x 16 x i8> @test_svqshrun_n_u8_s16_x2(
+// CHECK-SAME: <vscale x 8 x i16> [[ZN_COERCE0:%.*]], <vscale x 8 x i16> [[ZN_COERCE1:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[ZN:%.*]] = alloca { <vscale x 8 x i16>, <vscale x 8 x i16> }, align 16
+// CHECK-NEXT: [[ZN_ADDR:%.*]] = alloca { <vscale x 8 x i16>, <vscale x 8 x i16> }, align 16
+// CHECK-NEXT: [[TMP0:%.*]] = insertvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } poison, <vscale x 8 x i16> [[ZN_COERCE0]], 0
+// CHECK-NEXT: [[TMP1:%.*]] = insertvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP0]], <vscale x 8 x i16> [[ZN_COERCE1]], 1
+// CHECK-NEXT: store { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP1]], ptr [[ZN]], align 16
+// CHECK-NEXT: [[ZN1:%.*]] = load { <vscale x 8 x i16>, <vscale x 8 x i16> }, ptr [[ZN]], align 16
+// CHECK-NEXT: store { <vscale x 8 x i16>, <vscale x 8 x i16> } [[ZN1]], ptr [[ZN_ADDR]], align 16
+// CHECK-NEXT: [[TMP2:%.*]] = load { <vscale x 8 x i16>, <vscale x 8 x i16> }, ptr [[ZN_ADDR]], align 16
+// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP2]], 0
+// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP2]], 1
+// CHECK-NEXT: [[TMP5:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.sqshrun.x2.nxv8i16(<vscale x 8 x i16> [[TMP3]], <vscale x 8 x i16> [[TMP4]], i32 8)
+// CHECK-NEXT: ret <vscale x 16 x i8> [[TMP5]]
+//
+// CPP-CHECK-LABEL: define dso_local <vscale x 16 x i8> @_Z25test_svqshrun_n_u8_s16_x211svint16x2_t(
+// CPP-CHECK-SAME: <vscale x 8 x i16> [[ZN_COERCE0:%.*]], <vscale x 8 x i16> [[ZN_COERCE1:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: [[ZN:%.*]] = alloca { <vscale x 8 x i16>, <vscale x 8 x i16> }, align 16
+// CPP-CHECK-NEXT: [[ZN_ADDR:%.*]] = alloca { <vscale x 8 x i16>, <vscale x 8 x i16> }, align 16
+// CPP-CHECK-NEXT: [[TMP0:%.*]] = insertvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } poison, <vscale x 8 x i16> [[ZN_COERCE0]], 0
+// CPP-CHECK-NEXT: [[TMP1:%.*]] = insertvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP0]], <vscale x 8 x i16> [[ZN_COERCE1]], 1
+// CPP-CHECK-NEXT: store { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP1]], ptr [[ZN]], align 16
+// CPP-CHECK-NEXT: [[ZN1:%.*]] = load { <vscale x 8 x i16>, <vscale x 8 x i16> }, ptr [[ZN]], align 16
+// CPP-CHECK-NEXT: store { <vscale x 8 x i16>, <vscale x 8 x i16> } [[ZN1]], ptr [[ZN_ADDR]], align 16
+// CPP-CHECK-NEXT: [[TMP2:%.*]] = load { <vscale x 8 x i16>, <vscale x 8 x i16> }, ptr [[ZN_ADDR]], align 16
+// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP2]], 0
+// CPP-CHECK-NEXT: [[TMP4:%.*]] = extractvalue { <vscale x 8 x i16>, <vscale x 8 x i16> } [[TMP2]], 1
+// CPP-CHECK-NEXT: [[TMP5:%.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.sqshrun.x2.nxv8i16(<vscale x 8 x i16> [[TMP3]], <vscale x 8 x i16> [[TMP4]], i32 8)
+// CPP-CHECK-NEXT: ret <vscale x 16 x i8> [[TMP5]]
+//
+svuint8_t test_svqshrun_n_u8_s16_x2(svint16x2_t zn) ATTR
+{
+ return SVE_ACLE_FUNC(svqshrun,_n,_u8,_s16_x2)(zn, 8);
+}
diff --git a/clang/test/Sema/AArch64/arm_sve_feature_dependent_sve_AND_LP_sve2p3_OR_sme2p3_RP___sme_AND_LP_sve2p3_OR_sme2p3_RP.c b/clang/test/Sema/AArch64/arm_sve_feature_dependent_sve_AND_LP_sve2p3_OR_sme2p3_RP___sme_AND_LP_sve2p3_OR_sme2p3_RP.c
index 00f6001bdb29e..b93db8f017cf0 100644
--- a/clang/test/Sema/AArch64/arm_sve_feature_dependent_sve_AND_LP_sve2p3_OR_sme2p3_RP___sme_AND_LP_sve2p3_OR_sme2p3_RP.c
+++ b/clang/test/Sema/AArch64/arm_sve_feature_dependent_sve_AND_LP_sve2p3_OR_sme2p3_RP___sme_AND_LP_sve2p3_OR_sme2p3_RP.c
@@ -16,11 +16,15 @@ void test(void) {
svbool_t svbool_t_val;
svint8_t svint8_t_val;
svint16_t svint16_t_val;
+ svint16x2_t svint16x2_t_val;
svint32_t svint32_t_val;
+ svint32x2_t svint32x2_t_val;
svint64_t svint64_t_val;
svuint8_t svuint8_t_val;
svuint16_t svuint16_t_val;
+ svuint16x2_t svuint16x2_t_val;
svuint32_t svuint32_t_val;
+ svuint32x2_t svuint32x2_t_val;
svuint64_t svuint64_t_val;
uint8_t uint8_t_val;
uint16_t uint16_t_val;
@@ -82,6 +86,24 @@ void test(void) {
svaddsubp_u16(svuint16_t_val, svuint16_t_val);
svaddsubp_u32(svuint32_t_val, svuint32_t_val);
svaddsubp_u64(svuint64_t_val, svuint64_t_val);
+ svqrshrn_n_s8_s16_x2(svint16x2_t_val, 2);
+ svqrshrn_n_u8_u16_x2(svuint16x2_t_val, 2);
+ svqrshrn_s8(svint16x2_t_val, 2);
+ svqrshrn_u8(svuint16x2_t_val, 2);
+ svqrshrun_n_u8_s16_x2(svint16x2_t_val, 2);
+ svqrshrun_u8(svint16x2_t_val, 2);
+ svqshrn_n_s8_s16_x2(svint16x2_t_val, 2);
+ svqshrn_n_s16_s32_x2(svint32x2_t_val, 2);
+ svqshrn_n_u8_u16_x2(svuint16x2_t_val, 2);
+ svqshrn_n_u16_u32_x2(svuint32x2_t_val, 2);
+ svqshrn_s8(svint16x2_t_val, 2);
+ svqshrn_s16(svint32x2_t_val, 2);
+ svqshrn_u8(svuint16x2_t_val, 2);
+ svqshrn_u16(svuint32x2_t_val, 2);
+ svqshrun_n_u8_s16_x2(svint16x2_t_val, 2);
+ svqshrun_n_u16_s32_x2(svint32x2_t_val, 2);
+ svqshrun_u8(svint16x2_t_val, 2);
+ svqshrun_u16(svint32x2_t_val, 2);
svsubp_m(svbool_t_val, svint8_t_val, svint8_t_val);
svsubp_m(svbool_t_val, svint16_t_val, svint16_t_val);
svsubp_m(svbool_t_val, svint32_t_val, svint32_t_val);
@@ -139,11 +161,15 @@ void test_streaming(void) __arm_streaming{
svbool_t svbool_t_val;
svint8_t svint8_t_val;
svint16_t svint16_t_val;
+ svint16x2_t svint16x2_t_val;
svint32_t svint32_t_val;
+ svint32x2_t svint32x2_t_val;
svint64_t svint64_t_val;
svuint8_t svuint8_t_val;
svuint16_t svuint16_t_val;
+ svuint16x2_t svuint16x2_t_val;
svuint32_t svuint32_t_val;
+ svuint32x2_t svuint32x2_t_val;
svuint64_t svuint64_t_val;
uint8_t uint8_t_val;
uint16_t uint16_t_val;
@@ -205,6 +231,24 @@ void test_streaming(void) __arm_streaming{
svaddsubp_u16(svuint16_t_val, svuint16_t_val);
svaddsubp_u32(svuint32_t_val, svuint32_t_val);
svaddsubp_u64(svuint64_t_val, svuint64_t_val);
+ svqrshrn_n_s8_s16_x2(svint16x2_t_val, 2);
+ svqrshrn_n_u8_u16_x2(svuint16x2_t_val, 2);
+ svqrshrn_s8(svint16x2_t_val, 2);
+ svqrshrn_u8(svuint16x2_t_val, 2);
+ svqrshrun_n_u8_s16_x2(svint16x2_t_val, 2);
+ svqrshrun_u8(svint16x2_t_val, 2);
+ svqshrn_n_s8_s16_x2(svint16x2_t_val, 2);
+ svqshrn_n_s16_s32_x2(svint32x2_t_val, 2);
+ svqshrn_n_u8_u16_x2(svuint16x2_t_val, 2);
+ svqshrn_n_u16_u32_x2(svuint32x2_t_val, 2);
+ svqshrn_s8(svint16x2_t_val, 2);
+ svqshrn_s16(svint32x2_t_val, 2);
+ svqshrn_u8(svuint16x2_t_val, 2);
+ svqshrn_u16(svuint32x2_t_val, 2);
+ svqshrun_n_u8_s16_x2(svint16x2_t_val, 2);
+ svqshrun_n_u16_s32_x2(svint32x2_t_val, 2);
+ svqshrun_u8(svint16x2_t_val, 2);
+ svqshrun_u16(svint32x2_t_val, 2);
svsubp_m(svbool_t_val, svint8_t_val, svint8_t_val);
svsubp_m(svbool_t_val, svint16_t_val, svint16_t_val);
svsubp_m(svbool_t_val, svint32_t_val, svint32_t_val);
@@ -262,11 +306,15 @@ void test_streaming_compatible(void) __arm_streaming_compatible{
svbool_t svbool_t_val;
svint8_t svint8_t_val;
svint16_t svint16_t_val;
+ svint16x2_t svint16x2_t_val;
svint32_t svint32_t_val;
+ svint32x2_t svint32x2_t_val;
svint64_t svint64_t_val;
svuint8_t svuint8_t_val;
svuint16_t svuint16_t_val;
+ svuint16x2_t svuint16x2_t_val;
svuint32_t svuint32_t_val;
+ svuint32x2_t svuint32x2_t_val;
svuint64_t svuint64_t_val;
uint8_t uint8_t_val;
uint16_t uint16_t_val;
@@ -328,6 +376,24 @@ void test_streaming_compatible(void) __arm_streaming_compatible{
svaddsubp_u16(svuint16_t_val, svuint16_t_val);
svaddsubp_u32(svuint32_t_val, svuint32_t_val);
svaddsubp_u64(svuint64_t_val, svuint64_t_val);
+ svqrshrn_n_s8_s16_x2(svint16x2_t_val, 2);
+ svqrshrn_n_u8_u16_x2(svuint16x2_t_val, 2);
+ svqrshrn_s8(svint16x2_t_val, 2);
+ svqrshrn_u8(svuint16x2_t_val, 2);
+ svqrshrun_n_u8_s16_x2(svint16x2_t_val, 2);
+ svqrshrun_u8(svint16x2_t_val, 2);
+ svqshrn_n_s8_s16_x2(svint16x2_t_val, 2);
+ svqshrn_n_s16_s32_x2(svint32x2_t_val, 2);
+ svqshrn_n_u8_u16_x2(svuint16x2_t_val, 2);
+ svqshrn_n_u16_u32_x2(svuint32x2_t_val, 2);
+ svqshrn_s8(svint16x2_t_val, 2);
+ svqshrn_s16(svint32x2_t_val, 2);
+ svqshrn_u8(svuint16x2_t_val, 2);
+ svqshrn_u16(svuint32x2_t_val, 2);
+ svqshrun_n_u8_s16_x2(svint16x2_t_val, 2);
+ svqshrun_n_u16_s32_x2(svint32x2_t_val, 2);
+ svqshrun_u8(svint16x2_t_val, 2);
+ svqshrun_u16(svint32x2_t_val, 2);
svsubp_m(svbool_t_val, svint8_t_val, svint8_t_val);
svsubp_m(svbool_t_val, svint16_t_val, svint16_t_val);
svsubp_m(svbool_t_val, svint32_t_val, svint32_t_val);
diff --git a/clang/test/Sema/aarch64-sve2p3-intrinsics/acle_sve2p3_imm.cpp b/clang/test/Sema/aarch64-sve2p3-intrinsics/acle_sve2p3_imm.cpp
new file mode 100644
index 0000000000000..e0d21aed716d2
--- /dev/null
+++ b/clang/test/Sema/aarch64-sve2p3-intrinsics/acle_sve2p3_imm.cpp
@@ -0,0 +1,87 @@
+// REQUIRES: aarch64-registered-target
+
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sve2 -target-feature +sve2p3 -fsyntax-only -verify %s
+
+#include <arm_sve.h>
+
+
+
+svint8_t test_svqshrn_n_s8_s16_x2(svint16x2_t zn, uint64_t imm)
+{
+ svqshrn_n_s8_s16_x2(zn, 0); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [1, 8]}}
+ svqshrn_n_s8_s16_x2(zn, 9); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [1, 8]}}
+ svqshrn_n_s8_s16_x2(zn, -1); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [1, 8]}}
+
+ svqshrn_n_s8_s16_x2(zn, imm); // expected-error-re {{argument to {{.+}} must be a constant integer}}}}
+}
+
+svint16_t test_svqshrn_n_s16_s32_x2(svint32x2_t zn, uint64_t imm)
+{
+ svqshrn_n_s16_s32_x2(zn, 0); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [1, 16]}}
+ svqshrn_n_s16_s32_x2(zn, 17); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [1, 16]}}
+ svqshrn_n_s16_s32_x2(zn, -1); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [1, 16]}}
+
+ svqshrn_n_s16_s32_x2(zn, imm); // expected-error-re {{argument to {{.+}} must be a constant integer}}}}
+}
+
+svuint8_t test_svqshrn_n_u8_u16_x2(svuint16x2_t zn, uint64_t imm)
+{
+ svqshrn_n_u8_u16_x2(zn, 0); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [1, 8]}}
+ svqshrn_n_u8_u16_x2(zn, 9); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [1, 8]}}
+ svqshrn_n_u8_u16_x2(zn, -1); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [1, 8]}}
+
+ svqshrn_n_u8_u16_x2(zn, imm); // expected-error-re {{argument to {{.+}} must be a constant integer}}}}
+}
+
+svuint16_t test_svqshrn_n_u16_u32_x2(svuint32x2_t zn, uint64_t imm)
+{
+ svqshrn_n_u16_u32_x2(zn, 0); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [1, 16]}}
+ svqshrn_n_u16_u32_x2(zn, 17); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [1, 16]}}
+ svqshrn_n_u16_u32_x2(zn, -1); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [1, 16]}}
+
+ svqshrn_n_u16_u32_x2(zn, imm); // expected-error-re {{argument to {{.+}} must be a constant integer}}}}
+}
+
+svuint16_t test_svqshrun_n_u16_s32_x2(svint32x2_t zn, uint64_t imm)
+{
+ svqshrun_n_u16_s32_x2(zn, 0); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [1, 16]}}
+ svqshrun_n_u16_s32_x2(zn, 17); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [1, 16]}}
+ svqshrun_n_u16_s32_x2(zn, -1); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [1, 16]}}
+
+ svqshrun_n_u16_s32_x2(zn, imm); // expected-error-re {{argument to {{.+}} must be a constant integer}}}}
+}
+
+svuint8_t test_svqshrun_n_u8_s16_x2(svint16x2_t zn, uint64_t imm)
+{
+ svqshrun_n_u8_s16_x2(zn, 0); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [1, 8]}}
+ svqshrun_n_u8_s16_x2(zn, 9); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [1, 8]}}
+ svqshrun_n_u8_s16_x2(zn, -1); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [1, 8]}}
+
+ svqshrun_n_u8_s16_x2(zn, imm); // expected-error-re {{argument to {{.+}} must be a constant integer}}}}
+}
+
+void test_svqrshrn_n_s8_s16_x2(svint16x2_t zn, uint64_t imm) {
+ svqrshrn_n_s8_s16_x2(zn, 0); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [1, 8]}}
+ svqrshrn_n_s8_s16_x2(zn, 9); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [1, 8]}}
+ svqrshrn_n_s8_s16_x2(zn, -1); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [1, 8]}}
+
+ svqrshrn_n_s8_s16_x2(zn, imm); // expected-error-re {{argument to {{.+}} must be a constant integer}}}}
+}
+
+svuint8_t test_svqrshrn_n_u8_u16_x2(svuint16x2_t zn, uint64_t imm)
+{
+ svqrshrn_n_u8_u16_x2(zn, 0); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [1, 8]}}
+ svqrshrn_n_u8_u16_x2(zn, 9); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [1, 8]}}
+ svqrshrn_n_u8_u16_x2(zn, -1); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [1, 8]}}
+
+ svqrshrn_n_u8_u16_x2(zn, imm); // expected-error-re {{argument to {{.+}} must be a constant integer}}}}
+}
+
+svuint8_t test_svqrshrun_n_u8_s16_x2(svint16x2_t zn, uint64_t imm)
+{
+ svqrshrun_n_u8_s16_x2(zn, 0); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [1, 8]}}
+ svqrshrun_n_u8_s16_x2(zn, 9); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [1, 8]}}
+ svqrshrun_n_u8_s16_x2(zn, -1); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [1, 8]}}
+
+ svqrshrun_n_u8_s16_x2(zn, imm); // expected-error-re {{argument to {{.+}} must be a constant integer}}}}
+}
diff --git a/clang/test/Sema/aarch64-sve2p3-intrinsics/acle_sve2p3_qshrn.cpp b/clang/test/Sema/aarch64-sve2p3-intrinsics/acle_sve2p3_qshrn.cpp
new file mode 100644
index 0000000000000..0909a46158942
--- /dev/null
+++ b/clang/test/Sema/aarch64-sve2p3-intrinsics/acle_sve2p3_qshrn.cpp
@@ -0,0 +1,51 @@
+// REQUIRES: aarch64-registered-target
+
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -verify -verify-ignore-unexpected=error,note -emit-llvm -o - %s
+// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -verify=overload -verify-ignore-unexpected=error,note -emit-llvm -o - %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
+
+void test(svint32x2_t s32x2, svint16x2_t s16x2, svint8x2_t s8x2, svuint32x2_t u32x2, svuint16x2_t u16x2, svuint8x2_t u8x2)
+{
+ // expected-error at +2 {{'svqshrn_n_s8_s16_x2' needs target feature (sve,(sve2p3|sme2p3))|(sme,(sve2p3|sme2p3))}}
+ // overload-error at +1 {{'svqshrn_s8' needs target feature (sve,(sve2p3|sme2p3))|(sme,(sve2p3|sme2p3))}}
+ SVE_ACLE_FUNC(svqshrn,_n,_s8,_s16_x2)(s16x2, 8);
+
+ // expected-error at +2 {{'svqshrn_n_s16_s32_x2' needs target feature (sve,(sve2p3|sme2p3))|(sme,(sve2p3|sme2p3))}}
+ // overload-error at +1 {{'svqshrn_s16' needs target feature (sve,(sve2p3|sme2p3))|(sme,(sve2p3|sme2p3))}}
+ SVE_ACLE_FUNC(svqshrn,_n,_s16,_s32_x2)(s32x2, 16);
+
+ // expected-error at +2 {{'svqshrn_n_u8_u16_x2' needs target feature (sve,(sve2p3|sme2p3))|(sme,(sve2p3|sme2p3))}}
+ // overload-error at +1 {{'svqshrn_u8' needs target feature (sve,(sve2p3|sme2p3))|(sme,(sve2p3|sme2p3))}}
+ SVE_ACLE_FUNC(svqshrn,_n,_u8,_u16_x2)(u16x2, 8);
+
+ // expected-error at +2 {{'svqshrn_n_u16_u32_x2' needs target feature (sve,(sve2p3|sme2p3))|(sme,(sve2p3|sme2p3))}}
+ // overload-error at +1 {{'svqshrn_u16' needs target feature (sve,(sve2p3|sme2p3))|(sme,(sve2p3|sme2p3))}}
+ SVE_ACLE_FUNC(svqshrn,_n,_u16,_u32_x2)(u32x2, 16);
+
+ // expected-error at +2 {{'svqshrun_n_u16_s32_x2' needs target feature (sve,(sve2p3|sme2p3))|(sme,(sve2p3|sme2p3))}}
+ // overload-error at +1 {{'svqshrun_u16' needs target feature (sve,(sve2p3|sme2p3))|(sme,(sve2p3|sme2p3))}}
+ SVE_ACLE_FUNC(svqshrun,_n,_u16,_s32_x2)(s32x2, 16);
+
+ // expected-error at +2 {{'svqshrun_n_u8_s16_x2' needs target feature (sve,(sve2p3|sme2p3))|(sme,(sve2p3|sme2p3))}}
+ // overload-error at +1 {{'svqshrun_u8' needs target feature (sve,(sve2p3|sme2p3))|(sme,(sve2p3|sme2p3))}}
+ SVE_ACLE_FUNC(svqshrun,_n,_u8,_s16_x2)(s16x2, 8);
+
+ // expected-error at +2 {{'svqrshrn_n_s8_s16_x2' needs target feature (sve,(sve2p3|sme2p3))|(sme,(sve2p3|sme2p3))}}
+ // overload-error at +1 {{'svqrshrn_s8' needs target feature (sve,(sve2p3|sme2p3))|(sme,(sve2p3|sme2p3))}}
+ SVE_ACLE_FUNC(svqrshrn,_n,_s8,_s16_x2)(s16x2, 8);
+
+ // expected-error at +2 {{'svqrshrn_n_u8_u16_x2' needs target feature (sve,(sve2p3|sme2p3))|(sme,(sve2p3|sme2p3))}}
+ // overload-error at +1 {{'svqrshrn_u8' needs target feature (sve,(sve2p3|sme2p3))|(sme,(sve2p3|sme2p3))}}
+ SVE_ACLE_FUNC(svqrshrn,_n,_u8,_u16_x2)(u16x2, 8);
+
+ // expected-error at +2 {{'svqrshrun_n_u8_s16_x2' needs target feature (sve,(sve2p3|sme2p3))|(sme,(sve2p3|sme2p3))}}
+ // overload-error at +1 {{'svqrshrun_u8' needs target feature (sve,(sve2p3|sme2p3))|(sme,(sve2p3|sme2p3))}}
+ SVE_ACLE_FUNC(svqrshrun,_n,_u8,_s16_x2)(s16x2, 8);
+}
diff --git a/llvm/include/llvm/IR/IntrinsicsAArch64.td b/llvm/include/llvm/IR/IntrinsicsAArch64.td
index 2204c05860693..ccc2fe06ec0d2 100644
--- a/llvm/include/llvm/IR/IntrinsicsAArch64.td
+++ b/llvm/include/llvm/IR/IntrinsicsAArch64.td
@@ -3781,6 +3781,13 @@ let TargetPrefix = "aarch64" in {
def int_aarch64_sve_uqcvtn_x4 : SVE2_CVT_VG4_SINGLE_Intrinsic;
def int_aarch64_sve_sqcvtun_x4 : SVE2_CVT_VG4_SINGLE_Intrinsic;
+ //
+ // Multi-vector saturating shift right narrow and interleave
+ //
+ def int_aarch64_sve_sqshrn_x2 : SVE2_VG2_Multi_Imm_Intrinsic;
+ def int_aarch64_sve_uqshrn_x2 : SVE2_VG2_Multi_Imm_Intrinsic;
+ def int_aarch64_sve_sqshrun_x2 : SVE2_VG2_Multi_Imm_Intrinsic;
+
//
// Multi-Single add/sub
//
@@ -4296,4 +4303,3 @@ let TargetPrefix = "aarch64" in {
def int_aarch64_sve_pmlal_pair_x2 : DefaultAttrsIntrinsic<[llvm_nxv2i64_ty, llvm_nxv2i64_ty],
[llvm_nxv2i64_ty, llvm_nxv2i64_ty, llvm_nxv2i64_ty, llvm_nxv2i64_ty], [IntrNoMem]>;
}
-
diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
index 08639ebf22b91..09e464d8f7d9e 100644
--- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
@@ -4868,15 +4868,15 @@ let Predicates = [HasSVE2p3_or_SME2p3] in {
defm UCVTFLT_ZZ : sve2_int_to_fp_upcvt<"ucvtflt", 0b11>;
// SVE2 saturating shift right narrow by immediate and interleave
- defm SQRSHRN_Z2ZI_HtoB : sve_multi_vec_round_shift_narrow<"sqrshrn", 0b101>;
- defm SQRSHRUN_Z2ZI_HtoB : sve_multi_vec_round_shift_narrow<"sqrshrun", 0b001>;
- defm SQSHRN_Z2ZI_HtoB : sve_multi_vec_round_shift_narrow<"sqshrn", 0b000>;
- defm SQSHRUN_Z2ZI_HtoB : sve_multi_vec_round_shift_narrow<"sqshrun", 0b100>;
- defm UQRSHRN_Z2ZI_HtoB : sve_multi_vec_round_shift_narrow<"uqrshrn", 0b111>;
- defm UQSHRN_Z2ZI_HtoB : sve_multi_vec_round_shift_narrow<"uqshrn", 0b010>;
- defm SQSHRUN_Z2ZI_StoH : sve_multi_vec_shift_narrow<"sqshrun", 0b100, null_frag>;
- defm SQSHRN_Z2ZI_StoH : sve_multi_vec_shift_narrow<"sqshrn", 0b000, null_frag>;
- defm UQSHRN_Z2ZI_StoH : sve_multi_vec_shift_narrow<"uqshrn", 0b010, null_frag>;
+ defm SQRSHRN_Z2ZI_HtoB : sve_multi_vec_round_shift_narrow<"sqrshrn", 0b101, int_aarch64_sve_sqrshrn_x2>;
+ defm SQRSHRUN_Z2ZI_HtoB : sve_multi_vec_round_shift_narrow<"sqrshrun", 0b001, int_aarch64_sve_sqrshrun_x2>;
+ defm SQSHRN_Z2ZI_HtoB : sve_multi_vec_round_shift_narrow<"sqshrn", 0b000, int_aarch64_sve_sqshrn_x2>;
+ defm SQSHRUN_Z2ZI_HtoB : sve_multi_vec_round_shift_narrow<"sqshrun", 0b100, int_aarch64_sve_sqshrun_x2>;
+ defm UQRSHRN_Z2ZI_HtoB : sve_multi_vec_round_shift_narrow<"uqrshrn", 0b111, int_aarch64_sve_uqrshrn_x2>;
+ defm UQSHRN_Z2ZI_HtoB : sve_multi_vec_round_shift_narrow<"uqshrn", 0b010, int_aarch64_sve_uqshrn_x2>;
+ defm SQSHRUN_Z2ZI_StoH : sve_multi_vec_shift_narrow<"sqshrun", 0b100, int_aarch64_sve_sqshrun_x2>;
+ defm SQSHRN_Z2ZI_StoH : sve_multi_vec_shift_narrow<"sqshrn", 0b000, int_aarch64_sve_sqshrn_x2>;
+ defm UQSHRN_Z2ZI_StoH : sve_multi_vec_shift_narrow<"uqshrn", 0b010, int_aarch64_sve_uqshrn_x2>;
defm LUTI6_Z2ZZI : sve2_luti6_vector_index<"luti6">;
} // End HasSME2p3orSVE2p3
diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td
index 0e6eb52a7a6c8..2818abbe6df59 100644
--- a/llvm/lib/Target/AArch64/SVEInstrFormats.td
+++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td
@@ -720,7 +720,7 @@ class SVE_Shift_Add_All_Active_Pat<ValueType vtd, SDPatternOperator op, ValueTyp
: Pat<(vtd (add vt1:$Op1, (op (pt (SVEAllActive)), vt2:$Op2, vt3:$Op3))),
(inst $Op1, $Op2, $Op3)>;
-class SVE2p1_Sat_Shift_VG2_Pat<string name, SDPatternOperator intrinsic, ValueType out_vt, ValueType in_vt, Operand imm_ty>
+class SVE_Sat_Shift_VG2_Pat<string name, SDPatternOperator intrinsic, ValueType out_vt, ValueType in_vt, Operand imm_ty>
: Pat<(out_vt (intrinsic in_vt:$Zn1, in_vt:$Zn2, (i32 imm_ty:$i))),
(!cast<Instruction>(name) (REG_SEQUENCE ZPR2Mul2, in_vt:$Zn1, zsub0, in_vt:$Zn2, zsub1), imm_ty:$i)>;
@@ -10166,7 +10166,7 @@ multiclass sve2p1_multi_vec_extract_narrow<string mnemonic, bits<2> opc, SDPatte
}
// SVE2 multi-vec shift narrow
-class sve2p1_multi_vec_shift_narrow<string mnemonic, ZPRRegOp ZdRC, RegisterOperand ZSrcOp,
+class sve_multi_vec_shift_narrow<string mnemonic, ZPRRegOp ZdRC, RegisterOperand ZSrcOp,
Operand immtype, bits<3> opc, bits<2> tsz>
: I<(outs ZdRC:$Zd), (ins ZSrcOp:$Zn, immtype:$imm),
mnemonic, "\t$Zd, $Zn, $imm",
@@ -10190,17 +10190,19 @@ class sve2p1_multi_vec_shift_narrow<string mnemonic, ZPRRegOp ZdRC, RegisterOper
}
multiclass sve_multi_vec_shift_narrow<string mnemonic, bits<3> opc, SDPatternOperator intrinsic> {
- def NAME : sve2p1_multi_vec_shift_narrow<mnemonic, ZPR16, ZZ_s_mul_r, vecshiftR16, opc, 0b01> {
+ def NAME : sve_multi_vec_shift_narrow<mnemonic, ZPR16, ZZ_s_mul_r, vecshiftR16, opc, 0b01> {
let Inst{19} = imm{3}; // imm4
}
- def : SVE2p1_Sat_Shift_VG2_Pat<NAME, intrinsic, nxv8i16, nxv4i32, vecshiftR16>;
+ def : SVE_Sat_Shift_VG2_Pat<NAME, intrinsic, nxv8i16, nxv4i32, vecshiftR16>;
}
-multiclass sve_multi_vec_round_shift_narrow<string mnemonic, bits<3> opc> {
- def NAME : sve2p1_multi_vec_shift_narrow<mnemonic, ZPR8, ZZ_h_mul_r, vecshiftR8, opc, 0b00> {
+multiclass sve_multi_vec_round_shift_narrow<string mnemonic, bits<3> opc, SDPatternOperator intrinsic> {
+ def NAME : sve_multi_vec_shift_narrow<mnemonic, ZPR8, ZZ_h_mul_r, vecshiftR8, opc, 0b00> {
let Inst{19} = 0b1; // always 1 for imm3 version
}
+
+ def : SVE_Sat_Shift_VG2_Pat<NAME, intrinsic, nxv16i8, nxv8i16, vecshiftR8>;
}
// SME2 multi-vec contiguous load (scalar plus scalar, two registers)
diff --git a/llvm/test/CodeGen/AArch64/sve2p3-intrinsics/sve2p3-intrinsics-qrshr.ll b/llvm/test/CodeGen/AArch64/sve2p3-intrinsics/sve2p3-intrinsics-qrshr.ll
new file mode 100644
index 0000000000000..9b8f06e78762b
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/sve2p3-intrinsics/sve2p3-intrinsics-qrshr.ll
@@ -0,0 +1,31 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sve2p3 -enable-subreg-liveness -verify-machineinstrs < %s | FileCheck %s
+; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sme2p3 -force-streaming -verify-machineinstrs < %s | FileCheck %s
+; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sme,+sve2p3 -force-streaming -verify-machineinstrs < %s | FileCheck %s
+
+define <vscale x 16 x i8> @test_svqrshrn_n_s8_s16_x2(<vscale x 8 x i16> %zn, <vscale x 8 x i16> %zm) {
+; CHECK-LABEL: test_svqrshrn_n_s8_s16_x2:
+; CHECK: // %bb.0:
+; CHECK-NEXT: sqrshrn z0.b, { z0.h, z1.h }, #8
+; CHECK-NEXT: ret
+ %res = call <vscale x 16 x i8> @llvm.aarch64.sve.sqrshrn.x2.nxv8i16(<vscale x 8 x i16> %zn, <vscale x 8 x i16> %zm, i32 8)
+ ret <vscale x 16 x i8> %res
+}
+
+define <vscale x 16 x i8> @test_svqrshrn_n_u8_u16_x2(<vscale x 8 x i16> %zn, <vscale x 8 x i16> %zm) {
+; CHECK-LABEL: test_svqrshrn_n_u8_u16_x2:
+; CHECK: // %bb.0:
+; CHECK-NEXT: uqrshrn z0.b, { z0.h, z1.h }, #8
+; CHECK-NEXT: ret
+ %res = call <vscale x 16 x i8> @llvm.aarch64.sve.uqrshrn.x2.nxv8i16(<vscale x 8 x i16> %zn, <vscale x 8 x i16> %zm, i32 8)
+ ret <vscale x 16 x i8> %res
+}
+
+define <vscale x 16 x i8> @test_svqrshrun_n_u8_s16_x2(<vscale x 8 x i16> %zn, <vscale x 8 x i16> %zm) {
+; CHECK-LABEL: test_svqrshrun_n_u8_s16_x2:
+; CHECK: // %bb.0:
+; CHECK-NEXT: sqrshrun z0.b, { z0.h, z1.h }, #8
+; CHECK-NEXT: ret
+ %res = call <vscale x 16 x i8> @llvm.aarch64.sve.sqrshrun.x2.nxv8i16(<vscale x 8 x i16> %zn, <vscale x 8 x i16> %zm, i32 8)
+ ret <vscale x 16 x i8> %res
+}
diff --git a/llvm/test/CodeGen/AArch64/sve2p3-intrinsics/sve2p3-intrinsics-qshr.ll b/llvm/test/CodeGen/AArch64/sve2p3-intrinsics/sve2p3-intrinsics-qshr.ll
new file mode 100644
index 0000000000000..de466588d116b
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/sve2p3-intrinsics/sve2p3-intrinsics-qshr.ll
@@ -0,0 +1,58 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sve2p3 -enable-subreg-liveness -verify-machineinstrs < %s | FileCheck %s
+; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sme2p3 -force-streaming -verify-machineinstrs < %s | FileCheck %s
+; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sme,+sve2p3 -force-streaming -verify-machineinstrs < %s | FileCheck %s
+
+define <vscale x 16 x i8> @test_svqshrn_n_s8_s16_x2(<vscale x 8 x i16> %zn, <vscale x 8 x i16> %zm) {
+; CHECK-LABEL: test_svqshrn_n_s8_s16_x2:
+; CHECK: // %bb.0:
+; CHECK-NEXT: sqshrn z0.b, { z0.h, z1.h }, #8
+; CHECK-NEXT: ret
+ %res = call <vscale x 16 x i8> @llvm.aarch64.sve.sqshrn.x2.nxv8i16(<vscale x 8 x i16> %zn, <vscale x 8 x i16> %zm, i32 8)
+ ret <vscale x 16 x i8> %res
+}
+
+define <vscale x 8 x i16> @test_svqshrn_n_s16_s32_x2(<vscale x 4 x i32> %zn, <vscale x 4 x i32> %zm) {
+; CHECK-LABEL: test_svqshrn_n_s16_s32_x2:
+; CHECK: // %bb.0:
+; CHECK-NEXT: sqshrn z0.h, { z0.s, z1.s }, #16
+; CHECK-NEXT: ret
+ %res = call <vscale x 8 x i16> @llvm.aarch64.sve.sqshrn.x2.nxv4i32(<vscale x 4 x i32> %zn, <vscale x 4 x i32> %zm, i32 16)
+ ret <vscale x 8 x i16> %res
+}
+
+define <vscale x 16 x i8> @test_svqshrn_n_u8_u16_x2(<vscale x 8 x i16> %zn, <vscale x 8 x i16> %zm) {
+; CHECK-LABEL: test_svqshrn_n_u8_u16_x2:
+; CHECK: // %bb.0:
+; CHECK-NEXT: uqshrn z0.b, { z0.h, z1.h }, #8
+; CHECK-NEXT: ret
+ %res = call <vscale x 16 x i8> @llvm.aarch64.sve.uqshrn.x2.nxv8i16(<vscale x 8 x i16> %zn, <vscale x 8 x i16> %zm, i32 8)
+ ret <vscale x 16 x i8> %res
+}
+
+define <vscale x 8 x i16> @test_svqshrn_n_u16_u32_x2(<vscale x 4 x i32> %zn, <vscale x 4 x i32> %zm) {
+; CHECK-LABEL: test_svqshrn_n_u16_u32_x2:
+; CHECK: // %bb.0:
+; CHECK-NEXT: uqshrn z0.h, { z0.s, z1.s }, #16
+; CHECK-NEXT: ret
+ %res = call <vscale x 8 x i16> @llvm.aarch64.sve.uqshrn.x2.nxv4i32(<vscale x 4 x i32> %zn, <vscale x 4 x i32> %zm, i32 16)
+ ret <vscale x 8 x i16> %res
+}
+
+define <vscale x 8 x i16> @test_svqshrun_n_u16_s32_x2(<vscale x 4 x i32> %zn, <vscale x 4 x i32> %zm) {
+; CHECK-LABEL: test_svqshrun_n_u16_s32_x2:
+; CHECK: // %bb.0:
+; CHECK-NEXT: sqshrun z0.h, { z0.s, z1.s }, #16
+; CHECK-NEXT: ret
+ %res = call <vscale x 8 x i16> @llvm.aarch64.sve.sqshrun.x2.nxv4i32(<vscale x 4 x i32> %zn, <vscale x 4 x i32> %zm, i32 16)
+ ret <vscale x 8 x i16> %res
+}
+
+define <vscale x 16 x i8> @test_svqshrun_n_u8_s16_x2(<vscale x 8 x i16> %zn, <vscale x 8 x i16> %zm) {
+; CHECK-LABEL: test_svqshrun_n_u8_s16_x2:
+; CHECK: // %bb.0:
+; CHECK-NEXT: sqshrun z0.b, { z0.h, z1.h }, #8
+; CHECK-NEXT: ret
+ %res = call <vscale x 16 x i8> @llvm.aarch64.sve.sqshrun.x2.nxv8i16(<vscale x 8 x i16> %zn, <vscale x 8 x i16> %zm, i32 8)
+ ret <vscale x 16 x i8> %res
+}
More information about the cfe-commits
mailing list