[clang] [CIR][AArch64] Upstream widening-addition NEON builtins (PR #204285)
Vicky Nguyen via cfe-commits
cfe-commits at lists.llvm.org
Wed Jun 17 22:06:26 PDT 2026
https://github.com/iamvickynguyen updated https://github.com/llvm/llvm-project/pull/204285
>From 48fbf1be7ee85b491ef08f9e1280700d42d45a13 Mon Sep 17 00:00:00 2001
From: Vicky Nguyen <vicky.trucviennguyen at gmail.com>
Date: Thu, 11 Jun 2026 20:04:29 -0700
Subject: [PATCH] [CIR][AArch64] Upstream widening-addition and
vector-shift-left-and-widen NEON builtins
---
.../lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp | 15 +-
clang/test/CodeGen/AArch64/neon-intrinsics.c | 495 ------------------
clang/test/CodeGen/AArch64/neon/add.c | 371 +++++++++++++
clang/test/CodeGen/AArch64/neon/intrinsics.c | 187 +++++++
4 files changed, 572 insertions(+), 496 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
index b52e978fa0f4d..66850771d5490 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
@@ -959,7 +959,20 @@ static mlir::Value emitCommonNeonBuiltinExpr(
case NEON::BI__builtin_neon_vshlq_n_v:
return emitCommonNeonShift(cgf.getBuilder(), loc, vTy, ops[0], ops[1],
/*shiftLeft=*/true);
- case NEON::BI__builtin_neon_vshll_n_v:
+ case NEON::BI__builtin_neon_vshll_n_v: {
+ CIRGenBuilderTy &builder = cgf.getBuilder();
+ auto wideEltTy = mlir::cast<cir::IntType>(vTy.getElementType());
+ cir::VectorType narrowVecTy = cir::VectorType::get(
+ cir::IntType::get(wideEltTy.getContext(), wideEltTy.getWidth() / 2,
+ wideEltTy.isSigned()),
+ vTy.getSize());
+ mlir::Value src = builder.createBitcast(ops[0], narrowVecTy);
+ mlir::Value extended = builder.createIntCast(src, vTy);
+ mlir::Value shiftAmt =
+ emitNeonShiftVector(builder, ops[1], vTy, loc, /*neg=*/false);
+ return cir::ShiftOp::create(builder, loc, vTy, extended, shiftAmt,
+ /*isShiftLeft=*/true);
+ }
case NEON::BI__builtin_neon_vshrn_n_v:
cgf.cgm.errorNYI(expr->getSourceRange(),
std::string("unimplemented AArch64 builtin call: ") +
diff --git a/clang/test/CodeGen/AArch64/neon-intrinsics.c b/clang/test/CodeGen/AArch64/neon-intrinsics.c
index 9fde7f37fc192..b37ed5aa29f10 100644
--- a/clang/test/CodeGen/AArch64/neon-intrinsics.c
+++ b/clang/test/CodeGen/AArch64/neon-intrinsics.c
@@ -5144,159 +5144,6 @@ uint32x4_t test_vqshrn_high_n_u64(uint32x2_t a, uint64x2_t b) {
return vqshrn_high_n_u64(a, b, 19);
}
-// CHECK-LABEL: define dso_local <8 x i16> @test_vshll_n_s8(
-// CHECK-SAME: <8 x i8> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[TMP0:%.*]] = sext <8 x i8> [[A]] to <8 x i16>
-// CHECK-NEXT: [[VSHLL_N:%.*]] = shl <8 x i16> [[TMP0]], splat (i16 3)
-// CHECK-NEXT: ret <8 x i16> [[VSHLL_N]]
-//
-int16x8_t test_vshll_n_s8(int8x8_t a) {
- return vshll_n_s8(a, 3);
-}
-
-// CHECK-LABEL: define dso_local <4 x i32> @test_vshll_n_s16(
-// CHECK-SAME: <4 x i16> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i16> [[A]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK-NEXT: [[TMP2:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK-NEXT: [[VSHLL_N:%.*]] = shl <4 x i32> [[TMP2]], splat (i32 9)
-// CHECK-NEXT: ret <4 x i32> [[VSHLL_N]]
-//
-int32x4_t test_vshll_n_s16(int16x4_t a) {
- return vshll_n_s16(a, 9);
-}
-
-// CHECK-LABEL: define dso_local <2 x i64> @test_vshll_n_s32(
-// CHECK-SAME: <2 x i32> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[A]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK-NEXT: [[TMP2:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK-NEXT: [[VSHLL_N:%.*]] = shl <2 x i64> [[TMP2]], splat (i64 19)
-// CHECK-NEXT: ret <2 x i64> [[VSHLL_N]]
-//
-int64x2_t test_vshll_n_s32(int32x2_t a) {
- return vshll_n_s32(a, 19);
-}
-
-// CHECK-LABEL: define dso_local <8 x i16> @test_vshll_n_u8(
-// CHECK-SAME: <8 x i8> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[TMP0:%.*]] = zext <8 x i8> [[A]] to <8 x i16>
-// CHECK-NEXT: [[VSHLL_N:%.*]] = shl <8 x i16> [[TMP0]], splat (i16 3)
-// CHECK-NEXT: ret <8 x i16> [[VSHLL_N]]
-//
-uint16x8_t test_vshll_n_u8(uint8x8_t a) {
- return vshll_n_u8(a, 3);
-}
-
-// CHECK-LABEL: define dso_local <4 x i32> @test_vshll_n_u16(
-// CHECK-SAME: <4 x i16> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i16> [[A]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK-NEXT: [[TMP2:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK-NEXT: [[VSHLL_N:%.*]] = shl <4 x i32> [[TMP2]], splat (i32 9)
-// CHECK-NEXT: ret <4 x i32> [[VSHLL_N]]
-//
-uint32x4_t test_vshll_n_u16(uint16x4_t a) {
- return vshll_n_u16(a, 9);
-}
-
-// CHECK-LABEL: define dso_local <2 x i64> @test_vshll_n_u32(
-// CHECK-SAME: <2 x i32> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[A]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK-NEXT: [[TMP2:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK-NEXT: [[VSHLL_N:%.*]] = shl <2 x i64> [[TMP2]], splat (i64 19)
-// CHECK-NEXT: ret <2 x i64> [[VSHLL_N]]
-//
-uint64x2_t test_vshll_n_u32(uint32x2_t a) {
- return vshll_n_u32(a, 19);
-}
-
-// CHECK-LABEL: define dso_local <8 x i16> @test_vshll_high_n_s8(
-// CHECK-SAME: <16 x i8> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> [[A]], <16 x i8> [[A]], <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK-NEXT: [[TMP0:%.*]] = sext <8 x i8> [[SHUFFLE_I]] to <8 x i16>
-// CHECK-NEXT: [[VSHLL_N:%.*]] = shl <8 x i16> [[TMP0]], splat (i16 3)
-// CHECK-NEXT: ret <8 x i16> [[VSHLL_N]]
-//
-int16x8_t test_vshll_high_n_s8(int8x16_t a) {
- return vshll_high_n_s8(a, 3);
-}
-
-// CHECK-LABEL: define dso_local <4 x i32> @test_vshll_high_n_s16(
-// CHECK-SAME: <8 x i16> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> [[A]], <4 x i32> <i32 4, i32 5, i32 6, i32 7>
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK-NEXT: [[TMP2:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK-NEXT: [[VSHLL_N:%.*]] = shl <4 x i32> [[TMP2]], splat (i32 9)
-// CHECK-NEXT: ret <4 x i32> [[VSHLL_N]]
-//
-int32x4_t test_vshll_high_n_s16(int16x8_t a) {
- return vshll_high_n_s16(a, 9);
-}
-
-// CHECK-LABEL: define dso_local <2 x i64> @test_vshll_high_n_s32(
-// CHECK-SAME: <4 x i32> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> [[A]], <4 x i32> [[A]], <2 x i32> <i32 2, i32 3>
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK-NEXT: [[TMP2:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK-NEXT: [[VSHLL_N:%.*]] = shl <2 x i64> [[TMP2]], splat (i64 19)
-// CHECK-NEXT: ret <2 x i64> [[VSHLL_N]]
-//
-int64x2_t test_vshll_high_n_s32(int32x4_t a) {
- return vshll_high_n_s32(a, 19);
-}
-
-// CHECK-LABEL: define dso_local <8 x i16> @test_vshll_high_n_u8(
-// CHECK-SAME: <16 x i8> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> [[A]], <16 x i8> [[A]], <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK-NEXT: [[TMP0:%.*]] = zext <8 x i8> [[SHUFFLE_I]] to <8 x i16>
-// CHECK-NEXT: [[VSHLL_N:%.*]] = shl <8 x i16> [[TMP0]], splat (i16 3)
-// CHECK-NEXT: ret <8 x i16> [[VSHLL_N]]
-//
-uint16x8_t test_vshll_high_n_u8(uint8x16_t a) {
- return vshll_high_n_u8(a, 3);
-}
-
-// CHECK-LABEL: define dso_local <4 x i32> @test_vshll_high_n_u16(
-// CHECK-SAME: <8 x i16> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> [[A]], <4 x i32> <i32 4, i32 5, i32 6, i32 7>
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK-NEXT: [[TMP2:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK-NEXT: [[VSHLL_N:%.*]] = shl <4 x i32> [[TMP2]], splat (i32 9)
-// CHECK-NEXT: ret <4 x i32> [[VSHLL_N]]
-//
-uint32x4_t test_vshll_high_n_u16(uint16x8_t a) {
- return vshll_high_n_u16(a, 9);
-}
-
-// CHECK-LABEL: define dso_local <2 x i64> @test_vshll_high_n_u32(
-// CHECK-SAME: <4 x i32> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> [[A]], <4 x i32> [[A]], <2 x i32> <i32 2, i32 3>
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK-NEXT: [[TMP2:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK-NEXT: [[VSHLL_N:%.*]] = shl <2 x i64> [[TMP2]], splat (i64 19)
-// CHECK-NEXT: ret <2 x i64> [[VSHLL_N]]
-//
-uint64x2_t test_vshll_high_n_u32(uint32x4_t a) {
- return vshll_high_n_u32(a, 19);
-}
// CHECK-LABEL: define dso_local <8 x i16> @test_vmovl_high_s8(
// CHECK-SAME: <16 x i8> noundef [[A:%.*]]) #[[ATTR0]] {
@@ -5372,348 +5219,6 @@ uint64x2_t test_vmovl_high_u32(uint32x4_t a) {
return vmovl_high_u32(a);
}
-// CHECK-LABEL: define dso_local <8 x i16> @test_vaddl_s8(
-// CHECK-SAME: <8 x i8> noundef [[A:%.*]], <8 x i8> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[VMOVL_I5_I:%.*]] = sext <8 x i8> [[A]] to <8 x i16>
-// CHECK-NEXT: [[VMOVL_I_I:%.*]] = sext <8 x i8> [[B]] to <8 x i16>
-// CHECK-NEXT: [[ADD_I:%.*]] = add <8 x i16> [[VMOVL_I5_I]], [[VMOVL_I_I]]
-// CHECK-NEXT: ret <8 x i16> [[ADD_I]]
-//
-int16x8_t test_vaddl_s8(int8x8_t a, int8x8_t b) {
- return vaddl_s8(a, b);
-}
-
-// CHECK-LABEL: define dso_local <4 x i32> @test_vaddl_s16(
-// CHECK-SAME: <4 x i16> noundef [[A:%.*]], <4 x i16> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i16> [[A]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK-NEXT: [[VMOVL_I5_I:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[B]] to <8 x i8>
-// CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK-NEXT: [[VMOVL_I_I:%.*]] = sext <4 x i16> [[TMP3]] to <4 x i32>
-// CHECK-NEXT: [[ADD_I:%.*]] = add <4 x i32> [[VMOVL_I5_I]], [[VMOVL_I_I]]
-// CHECK-NEXT: ret <4 x i32> [[ADD_I]]
-//
-int32x4_t test_vaddl_s16(int16x4_t a, int16x4_t b) {
- return vaddl_s16(a, b);
-}
-
-// CHECK-LABEL: define dso_local <2 x i64> @test_vaddl_s32(
-// CHECK-SAME: <2 x i32> noundef [[A:%.*]], <2 x i32> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[A]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK-NEXT: [[VMOVL_I5_I:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x i32> [[B]] to <8 x i8>
-// CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK-NEXT: [[VMOVL_I_I:%.*]] = sext <2 x i32> [[TMP3]] to <2 x i64>
-// CHECK-NEXT: [[ADD_I:%.*]] = add <2 x i64> [[VMOVL_I5_I]], [[VMOVL_I_I]]
-// CHECK-NEXT: ret <2 x i64> [[ADD_I]]
-//
-int64x2_t test_vaddl_s32(int32x2_t a, int32x2_t b) {
- return vaddl_s32(a, b);
-}
-
-// CHECK-LABEL: define dso_local <8 x i16> @test_vaddl_u8(
-// CHECK-SAME: <8 x i8> noundef [[A:%.*]], <8 x i8> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[VMOVL_I5_I:%.*]] = zext <8 x i8> [[A]] to <8 x i16>
-// CHECK-NEXT: [[VMOVL_I_I:%.*]] = zext <8 x i8> [[B]] to <8 x i16>
-// CHECK-NEXT: [[ADD_I:%.*]] = add <8 x i16> [[VMOVL_I5_I]], [[VMOVL_I_I]]
-// CHECK-NEXT: ret <8 x i16> [[ADD_I]]
-//
-uint16x8_t test_vaddl_u8(uint8x8_t a, uint8x8_t b) {
- return vaddl_u8(a, b);
-}
-
-// CHECK-LABEL: define dso_local <4 x i32> @test_vaddl_u16(
-// CHECK-SAME: <4 x i16> noundef [[A:%.*]], <4 x i16> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i16> [[A]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK-NEXT: [[VMOVL_I5_I:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[B]] to <8 x i8>
-// CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK-NEXT: [[VMOVL_I_I:%.*]] = zext <4 x i16> [[TMP3]] to <4 x i32>
-// CHECK-NEXT: [[ADD_I:%.*]] = add <4 x i32> [[VMOVL_I5_I]], [[VMOVL_I_I]]
-// CHECK-NEXT: ret <4 x i32> [[ADD_I]]
-//
-uint32x4_t test_vaddl_u16(uint16x4_t a, uint16x4_t b) {
- return vaddl_u16(a, b);
-}
-
-// CHECK-LABEL: define dso_local <2 x i64> @test_vaddl_u32(
-// CHECK-SAME: <2 x i32> noundef [[A:%.*]], <2 x i32> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[A]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK-NEXT: [[VMOVL_I5_I:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x i32> [[B]] to <8 x i8>
-// CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK-NEXT: [[VMOVL_I_I:%.*]] = zext <2 x i32> [[TMP3]] to <2 x i64>
-// CHECK-NEXT: [[ADD_I:%.*]] = add <2 x i64> [[VMOVL_I5_I]], [[VMOVL_I_I]]
-// CHECK-NEXT: ret <2 x i64> [[ADD_I]]
-//
-uint64x2_t test_vaddl_u32(uint32x2_t a, uint32x2_t b) {
- return vaddl_u32(a, b);
-}
-
-// CHECK-LABEL: define dso_local <8 x i16> @test_vaddl_high_s8(
-// CHECK-SAME: <16 x i8> noundef [[A:%.*]], <16 x i8> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[SHUFFLE_I_I12_I:%.*]] = shufflevector <16 x i8> [[A]], <16 x i8> [[A]], <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK-NEXT: [[TMP0:%.*]] = sext <8 x i8> [[SHUFFLE_I_I12_I]] to <8 x i16>
-// CHECK-NEXT: [[SHUFFLE_I_I_I:%.*]] = shufflevector <16 x i8> [[B]], <16 x i8> [[B]], <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK-NEXT: [[TMP1:%.*]] = sext <8 x i8> [[SHUFFLE_I_I_I]] to <8 x i16>
-// CHECK-NEXT: [[ADD_I:%.*]] = add <8 x i16> [[TMP0]], [[TMP1]]
-// CHECK-NEXT: ret <8 x i16> [[ADD_I]]
-//
-int16x8_t test_vaddl_high_s8(int8x16_t a, int8x16_t b) {
- return vaddl_high_s8(a, b);
-}
-
-// CHECK-LABEL: define dso_local <4 x i32> @test_vaddl_high_s16(
-// CHECK-SAME: <8 x i16> noundef [[A:%.*]], <8 x i16> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[SHUFFLE_I_I12_I:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> [[A]], <4 x i32> <i32 4, i32 5, i32 6, i32 7>
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I12_I]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK-NEXT: [[TMP2:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK-NEXT: [[SHUFFLE_I_I_I:%.*]] = shufflevector <8 x i16> [[B]], <8 x i16> [[B]], <4 x i32> <i32 4, i32 5, i32 6, i32 7>
-// CHECK-NEXT: [[TMP3:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I_I]] to <8 x i8>
-// CHECK-NEXT: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <4 x i16>
-// CHECK-NEXT: [[TMP5:%.*]] = sext <4 x i16> [[TMP4]] to <4 x i32>
-// CHECK-NEXT: [[ADD_I:%.*]] = add <4 x i32> [[TMP2]], [[TMP5]]
-// CHECK-NEXT: ret <4 x i32> [[ADD_I]]
-//
-int32x4_t test_vaddl_high_s16(int16x8_t a, int16x8_t b) {
- return vaddl_high_s16(a, b);
-}
-
-// CHECK-LABEL: define dso_local <2 x i64> @test_vaddl_high_s32(
-// CHECK-SAME: <4 x i32> noundef [[A:%.*]], <4 x i32> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[SHUFFLE_I_I12_I:%.*]] = shufflevector <4 x i32> [[A]], <4 x i32> [[A]], <2 x i32> <i32 2, i32 3>
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I12_I]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK-NEXT: [[TMP2:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK-NEXT: [[SHUFFLE_I_I_I:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[B]], <2 x i32> <i32 2, i32 3>
-// CHECK-NEXT: [[TMP3:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I_I]] to <8 x i8>
-// CHECK-NEXT: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <2 x i32>
-// CHECK-NEXT: [[TMP5:%.*]] = sext <2 x i32> [[TMP4]] to <2 x i64>
-// CHECK-NEXT: [[ADD_I:%.*]] = add <2 x i64> [[TMP2]], [[TMP5]]
-// CHECK-NEXT: ret <2 x i64> [[ADD_I]]
-//
-int64x2_t test_vaddl_high_s32(int32x4_t a, int32x4_t b) {
- return vaddl_high_s32(a, b);
-}
-
-// CHECK-LABEL: define dso_local <8 x i16> @test_vaddl_high_u8(
-// CHECK-SAME: <16 x i8> noundef [[A:%.*]], <16 x i8> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[SHUFFLE_I_I12_I:%.*]] = shufflevector <16 x i8> [[A]], <16 x i8> [[A]], <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK-NEXT: [[TMP0:%.*]] = zext <8 x i8> [[SHUFFLE_I_I12_I]] to <8 x i16>
-// CHECK-NEXT: [[SHUFFLE_I_I_I:%.*]] = shufflevector <16 x i8> [[B]], <16 x i8> [[B]], <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK-NEXT: [[TMP1:%.*]] = zext <8 x i8> [[SHUFFLE_I_I_I]] to <8 x i16>
-// CHECK-NEXT: [[ADD_I:%.*]] = add <8 x i16> [[TMP0]], [[TMP1]]
-// CHECK-NEXT: ret <8 x i16> [[ADD_I]]
-//
-uint16x8_t test_vaddl_high_u8(uint8x16_t a, uint8x16_t b) {
- return vaddl_high_u8(a, b);
-}
-
-// CHECK-LABEL: define dso_local <4 x i32> @test_vaddl_high_u16(
-// CHECK-SAME: <8 x i16> noundef [[A:%.*]], <8 x i16> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[SHUFFLE_I_I12_I:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> [[A]], <4 x i32> <i32 4, i32 5, i32 6, i32 7>
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I12_I]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK-NEXT: [[TMP2:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK-NEXT: [[SHUFFLE_I_I_I:%.*]] = shufflevector <8 x i16> [[B]], <8 x i16> [[B]], <4 x i32> <i32 4, i32 5, i32 6, i32 7>
-// CHECK-NEXT: [[TMP3:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I_I]] to <8 x i8>
-// CHECK-NEXT: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <4 x i16>
-// CHECK-NEXT: [[TMP5:%.*]] = zext <4 x i16> [[TMP4]] to <4 x i32>
-// CHECK-NEXT: [[ADD_I:%.*]] = add <4 x i32> [[TMP2]], [[TMP5]]
-// CHECK-NEXT: ret <4 x i32> [[ADD_I]]
-//
-uint32x4_t test_vaddl_high_u16(uint16x8_t a, uint16x8_t b) {
- return vaddl_high_u16(a, b);
-}
-
-// CHECK-LABEL: define dso_local <2 x i64> @test_vaddl_high_u32(
-// CHECK-SAME: <4 x i32> noundef [[A:%.*]], <4 x i32> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[SHUFFLE_I_I12_I:%.*]] = shufflevector <4 x i32> [[A]], <4 x i32> [[A]], <2 x i32> <i32 2, i32 3>
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I12_I]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK-NEXT: [[TMP2:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK-NEXT: [[SHUFFLE_I_I_I:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[B]], <2 x i32> <i32 2, i32 3>
-// CHECK-NEXT: [[TMP3:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I_I]] to <8 x i8>
-// CHECK-NEXT: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <2 x i32>
-// CHECK-NEXT: [[TMP5:%.*]] = zext <2 x i32> [[TMP4]] to <2 x i64>
-// CHECK-NEXT: [[ADD_I:%.*]] = add <2 x i64> [[TMP2]], [[TMP5]]
-// CHECK-NEXT: ret <2 x i64> [[ADD_I]]
-//
-uint64x2_t test_vaddl_high_u32(uint32x4_t a, uint32x4_t b) {
- return vaddl_high_u32(a, b);
-}
-
-// CHECK-LABEL: define dso_local <8 x i16> @test_vaddw_s8(
-// CHECK-SAME: <8 x i16> noundef [[A:%.*]], <8 x i8> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[VMOVL_I_I:%.*]] = sext <8 x i8> [[B]] to <8 x i16>
-// CHECK-NEXT: [[ADD_I:%.*]] = add <8 x i16> [[A]], [[VMOVL_I_I]]
-// CHECK-NEXT: ret <8 x i16> [[ADD_I]]
-//
-int16x8_t test_vaddw_s8(int16x8_t a, int8x8_t b) {
- return vaddw_s8(a, b);
-}
-
-// CHECK-LABEL: define dso_local <4 x i32> @test_vaddw_s16(
-// CHECK-SAME: <4 x i32> noundef [[A:%.*]], <4 x i16> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i16> [[B]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK-NEXT: [[VMOVL_I_I:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK-NEXT: [[ADD_I:%.*]] = add <4 x i32> [[A]], [[VMOVL_I_I]]
-// CHECK-NEXT: ret <4 x i32> [[ADD_I]]
-//
-int32x4_t test_vaddw_s16(int32x4_t a, int16x4_t b) {
- return vaddw_s16(a, b);
-}
-
-// CHECK-LABEL: define dso_local <2 x i64> @test_vaddw_s32(
-// CHECK-SAME: <2 x i64> noundef [[A:%.*]], <2 x i32> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[B]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK-NEXT: [[VMOVL_I_I:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK-NEXT: [[ADD_I:%.*]] = add <2 x i64> [[A]], [[VMOVL_I_I]]
-// CHECK-NEXT: ret <2 x i64> [[ADD_I]]
-//
-int64x2_t test_vaddw_s32(int64x2_t a, int32x2_t b) {
- return vaddw_s32(a, b);
-}
-
-// CHECK-LABEL: define dso_local <8 x i16> @test_vaddw_u8(
-// CHECK-SAME: <8 x i16> noundef [[A:%.*]], <8 x i8> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[VMOVL_I_I:%.*]] = zext <8 x i8> [[B]] to <8 x i16>
-// CHECK-NEXT: [[ADD_I:%.*]] = add <8 x i16> [[A]], [[VMOVL_I_I]]
-// CHECK-NEXT: ret <8 x i16> [[ADD_I]]
-//
-uint16x8_t test_vaddw_u8(uint16x8_t a, uint8x8_t b) {
- return vaddw_u8(a, b);
-}
-
-// CHECK-LABEL: define dso_local <4 x i32> @test_vaddw_u16(
-// CHECK-SAME: <4 x i32> noundef [[A:%.*]], <4 x i16> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i16> [[B]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK-NEXT: [[VMOVL_I_I:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK-NEXT: [[ADD_I:%.*]] = add <4 x i32> [[A]], [[VMOVL_I_I]]
-// CHECK-NEXT: ret <4 x i32> [[ADD_I]]
-//
-uint32x4_t test_vaddw_u16(uint32x4_t a, uint16x4_t b) {
- return vaddw_u16(a, b);
-}
-
-// CHECK-LABEL: define dso_local <2 x i64> @test_vaddw_u32(
-// CHECK-SAME: <2 x i64> noundef [[A:%.*]], <2 x i32> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[B]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK-NEXT: [[VMOVL_I_I:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK-NEXT: [[ADD_I:%.*]] = add <2 x i64> [[A]], [[VMOVL_I_I]]
-// CHECK-NEXT: ret <2 x i64> [[ADD_I]]
-//
-uint64x2_t test_vaddw_u32(uint64x2_t a, uint32x2_t b) {
- return vaddw_u32(a, b);
-}
-
-// CHECK-LABEL: define dso_local <8 x i16> @test_vaddw_high_s8(
-// CHECK-SAME: <8 x i16> noundef [[A:%.*]], <16 x i8> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[SHUFFLE_I_I_I:%.*]] = shufflevector <16 x i8> [[B]], <16 x i8> [[B]], <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK-NEXT: [[TMP0:%.*]] = sext <8 x i8> [[SHUFFLE_I_I_I]] to <8 x i16>
-// CHECK-NEXT: [[ADD_I:%.*]] = add <8 x i16> [[A]], [[TMP0]]
-// CHECK-NEXT: ret <8 x i16> [[ADD_I]]
-//
-int16x8_t test_vaddw_high_s8(int16x8_t a, int8x16_t b) {
- return vaddw_high_s8(a, b);
-}
-
-// CHECK-LABEL: define dso_local <4 x i32> @test_vaddw_high_s16(
-// CHECK-SAME: <4 x i32> noundef [[A:%.*]], <8 x i16> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[SHUFFLE_I_I_I:%.*]] = shufflevector <8 x i16> [[B]], <8 x i16> [[B]], <4 x i32> <i32 4, i32 5, i32 6, i32 7>
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I_I]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK-NEXT: [[TMP2:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK-NEXT: [[ADD_I:%.*]] = add <4 x i32> [[A]], [[TMP2]]
-// CHECK-NEXT: ret <4 x i32> [[ADD_I]]
-//
-int32x4_t test_vaddw_high_s16(int32x4_t a, int16x8_t b) {
- return vaddw_high_s16(a, b);
-}
-
-// CHECK-LABEL: define dso_local <2 x i64> @test_vaddw_high_s32(
-// CHECK-SAME: <2 x i64> noundef [[A:%.*]], <4 x i32> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[SHUFFLE_I_I_I:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[B]], <2 x i32> <i32 2, i32 3>
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I_I]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK-NEXT: [[TMP2:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK-NEXT: [[ADD_I:%.*]] = add <2 x i64> [[A]], [[TMP2]]
-// CHECK-NEXT: ret <2 x i64> [[ADD_I]]
-//
-int64x2_t test_vaddw_high_s32(int64x2_t a, int32x4_t b) {
- return vaddw_high_s32(a, b);
-}
-
-// CHECK-LABEL: define dso_local <8 x i16> @test_vaddw_high_u8(
-// CHECK-SAME: <8 x i16> noundef [[A:%.*]], <16 x i8> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[SHUFFLE_I_I_I:%.*]] = shufflevector <16 x i8> [[B]], <16 x i8> [[B]], <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK-NEXT: [[TMP0:%.*]] = zext <8 x i8> [[SHUFFLE_I_I_I]] to <8 x i16>
-// CHECK-NEXT: [[ADD_I:%.*]] = add <8 x i16> [[A]], [[TMP0]]
-// CHECK-NEXT: ret <8 x i16> [[ADD_I]]
-//
-uint16x8_t test_vaddw_high_u8(uint16x8_t a, uint8x16_t b) {
- return vaddw_high_u8(a, b);
-}
-
-// CHECK-LABEL: define dso_local <4 x i32> @test_vaddw_high_u16(
-// CHECK-SAME: <4 x i32> noundef [[A:%.*]], <8 x i16> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[SHUFFLE_I_I_I:%.*]] = shufflevector <8 x i16> [[B]], <8 x i16> [[B]], <4 x i32> <i32 4, i32 5, i32 6, i32 7>
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I_I]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK-NEXT: [[TMP2:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK-NEXT: [[ADD_I:%.*]] = add <4 x i32> [[A]], [[TMP2]]
-// CHECK-NEXT: ret <4 x i32> [[ADD_I]]
-//
-uint32x4_t test_vaddw_high_u16(uint32x4_t a, uint16x8_t b) {
- return vaddw_high_u16(a, b);
-}
-
-// CHECK-LABEL: define dso_local <2 x i64> @test_vaddw_high_u32(
-// CHECK-SAME: <2 x i64> noundef [[A:%.*]], <4 x i32> noundef [[B:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[SHUFFLE_I_I_I:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[B]], <2 x i32> <i32 2, i32 3>
-// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I_I]] to <8 x i8>
-// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK-NEXT: [[TMP2:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK-NEXT: [[ADD_I:%.*]] = add <2 x i64> [[A]], [[TMP2]]
-// CHECK-NEXT: ret <2 x i64> [[ADD_I]]
-//
-uint64x2_t test_vaddw_high_u32(uint64x2_t a, uint32x4_t b) {
- return vaddw_high_u32(a, b);
-}
-
// CHECK-LABEL: define dso_local <8 x i16> @test_vsubl_high_s8(
// CHECK-SAME: <16 x i8> noundef [[A:%.*]], <16 x i8> noundef [[B:%.*]]) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
diff --git a/clang/test/CodeGen/AArch64/neon/add.c b/clang/test/CodeGen/AArch64/neon/add.c
index ff2cb23c772dd..b1dc5c253e7d6 100644
--- a/clang/test/CodeGen/AArch64/neon/add.c
+++ b/clang/test/CodeGen/AArch64/neon/add.c
@@ -349,3 +349,374 @@ poly128_t test_vaddq_p128(poly128_t a, poly128_t b) {
// LLVM-NEXT: ret i128 [[TMP3]]
return vaddq_p128(a, b);
}
+
+//===----------------------------------------------------------------------===//
+// 2.1.1.1.2. Widening addition
+// https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#widening-addition
+//===----------------------------------------------------------------------===//
+
+// LLVM-LABEL: @test_vaddl_s8(
+// CIR-LABEL: @vaddl_s8(
+int16x8_t test_vaddl_s8(int8x8_t a, int8x8_t b) {
+ // CIR: cir.add {{.*}} : !cir.vector<8 x !s16i>
+
+ // LLVM-SAME: <8 x i8> {{.*}} [[A:%.*]], <8 x i8> {{.*}} [[B:%.*]])
+ // LLVM: [[VMOVL_I5_I:%.*]] = sext <8 x i8> [[A]] to <8 x i16>
+ // LLVM-NEXT: [[VMOVL_I_I:%.*]] = sext <8 x i8> [[B]] to <8 x i16>
+ // LLVM-NEXT: [[ADD_I:%.*]] = add <8 x i16> [[VMOVL_I5_I]], [[VMOVL_I_I]]
+ // LLVM-NEXT: ret <8 x i16> [[ADD_I]]
+ return vaddl_s8(a, b);
+}
+
+// LLVM-LABEL: @test_vaddl_s16(
+// CIR-LABEL: @vaddl_s16(
+int32x4_t test_vaddl_s16(int16x4_t a, int16x4_t b) {
+ // CIR: cir.add {{.*}} : !cir.vector<4 x !s32i>
+
+ // LLVM-SAME: <4 x i16> {{.*}} [[A:%.*]], <4 x i16> {{.*}} [[B:%.*]])
+ // LLVM: [[TMP0:%.*]] = bitcast <4 x i16> [[A]] to <8 x i8>
+ // LLVM-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
+ // LLVM-NEXT: [[VMOVL_I5_I:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
+ // LLVM-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[B]] to <8 x i8>
+ // LLVM-NEXT: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
+ // LLVM-NEXT: [[VMOVL_I_I:%.*]] = sext <4 x i16> [[TMP3]] to <4 x i32>
+ // LLVM-NEXT: [[ADD_I:%.*]] = add <4 x i32> [[VMOVL_I5_I]], [[VMOVL_I_I]]
+ // LLVM-NEXT: ret <4 x i32> [[ADD_I]]
+ return vaddl_s16(a, b);
+}
+
+// LLVM-LABEL: @test_vaddl_s32(
+// CIR-LABEL: @vaddl_s32(
+int64x2_t test_vaddl_s32(int32x2_t a, int32x2_t b) {
+ // CIR: cir.add {{.*}} : !cir.vector<2 x !s64i>
+
+ // LLVM-SAME: <2 x i32> {{.*}} [[A:%.*]], <2 x i32> {{.*}} [[B:%.*]])
+ // LLVM: [[TMP0:%.*]] = bitcast <2 x i32> [[A]] to <8 x i8>
+ // LLVM-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
+ // LLVM-NEXT: [[VMOVL_I5_I:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
+ // LLVM-NEXT: [[TMP2:%.*]] = bitcast <2 x i32> [[B]] to <8 x i8>
+ // LLVM-NEXT: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
+ // LLVM-NEXT: [[VMOVL_I_I:%.*]] = sext <2 x i32> [[TMP3]] to <2 x i64>
+ // LLVM-NEXT: [[ADD_I:%.*]] = add <2 x i64> [[VMOVL_I5_I]], [[VMOVL_I_I]]
+ // LLVM-NEXT: ret <2 x i64> [[ADD_I]]
+ return vaddl_s32(a, b);
+}
+
+// LLVM-LABEL: @test_vaddl_u8(
+// CIR-LABEL: @vaddl_u8(
+uint16x8_t test_vaddl_u8(uint8x8_t a, uint8x8_t b) {
+ // CIR: cir.add {{.*}} : !cir.vector<8 x !u16i>
+
+ // LLVM-SAME: <8 x i8> {{.*}} [[A:%.*]], <8 x i8> {{.*}} [[B:%.*]])
+ // LLVM: [[VMOVL_I5_I:%.*]] = zext <8 x i8> [[A]] to <8 x i16>
+ // LLVM-NEXT: [[VMOVL_I_I:%.*]] = zext <8 x i8> [[B]] to <8 x i16>
+ // LLVM-NEXT: [[ADD_I:%.*]] = add <8 x i16> [[VMOVL_I5_I]], [[VMOVL_I_I]]
+ // LLVM-NEXT: ret <8 x i16> [[ADD_I]]
+ return vaddl_u8(a, b);
+}
+
+// LLVM-LABEL: @test_vaddl_u16(
+// CIR-LABEL: @vaddl_u16(
+uint32x4_t test_vaddl_u16(uint16x4_t a, uint16x4_t b) {
+ // CIR: cir.add {{.*}} : !cir.vector<4 x !u32i>
+
+ // LLVM-SAME: <4 x i16> {{.*}} [[A:%.*]], <4 x i16> {{.*}} [[B:%.*]])
+ // LLVM: [[TMP0:%.*]] = bitcast <4 x i16> [[A]] to <8 x i8>
+ // LLVM-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
+ // LLVM-NEXT: [[VMOVL_I5_I:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
+ // LLVM-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[B]] to <8 x i8>
+ // LLVM-NEXT: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
+ // LLVM-NEXT: [[VMOVL_I_I:%.*]] = zext <4 x i16> [[TMP3]] to <4 x i32>
+ // LLVM-NEXT: [[ADD_I:%.*]] = add <4 x i32> [[VMOVL_I5_I]], [[VMOVL_I_I]]
+ // LLVM-NEXT: ret <4 x i32> [[ADD_I]]
+ return vaddl_u16(a, b);
+}
+
+// LLVM-LABEL: @test_vaddl_u32(
+// CIR-LABEL: @vaddl_u32(
+uint64x2_t test_vaddl_u32(uint32x2_t a, uint32x2_t b) {
+ // CIR: cir.add {{.*}} : !cir.vector<2 x !u64i>
+
+ // LLVM-SAME: <2 x i32> {{.*}} [[A:%.*]], <2 x i32> {{.*}} [[B:%.*]])
+ // LLVM: [[TMP0:%.*]] = bitcast <2 x i32> [[A]] to <8 x i8>
+ // LLVM-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
+ // LLVM-NEXT: [[VMOVL_I5_I:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
+ // LLVM-NEXT: [[TMP2:%.*]] = bitcast <2 x i32> [[B]] to <8 x i8>
+ // LLVM-NEXT: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
+ // LLVM-NEXT: [[VMOVL_I_I:%.*]] = zext <2 x i32> [[TMP3]] to <2 x i64>
+ // LLVM-NEXT: [[ADD_I:%.*]] = add <2 x i64> [[VMOVL_I5_I]], [[VMOVL_I_I]]
+ // LLVM-NEXT: ret <2 x i64> [[ADD_I]]
+ return vaddl_u32(a, b);
+}
+
+// LLVM-LABEL: @test_vaddl_high_s8(
+// CIR-LABEL: @vaddl_high_s8(
+int16x8_t test_vaddl_high_s8(int8x16_t a, int8x16_t b) {
+ // CIR: cir.add {{.*}} : !cir.vector<8 x !s16i>
+
+ // LLVM-SAME: <16 x i8> {{.*}} [[A:%.*]], <16 x i8> {{.*}} [[B:%.*]])
+ // LLVM: [[SHUFFLE_I_I12_I:%.*]] = shufflevector <16 x i8> [[A]], <16 x i8> [[A]], <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ // LLVM-NEXT: [[TMP0:%.*]] = sext <8 x i8> [[SHUFFLE_I_I12_I]] to <8 x i16>
+ // LLVM-NEXT: [[SHUFFLE_I_I_I:%.*]] = shufflevector <16 x i8> [[B]], <16 x i8> [[B]], <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ // LLVM-NEXT: [[TMP1:%.*]] = sext <8 x i8> [[SHUFFLE_I_I_I]] to <8 x i16>
+ // LLVM-NEXT: [[ADD_I:%.*]] = add <8 x i16> [[TMP0]], [[TMP1]]
+ // LLVM-NEXT: ret <8 x i16> [[ADD_I]]
+ return vaddl_high_s8(a, b);
+}
+
+// LLVM-LABEL: @test_vaddl_high_s16(
+// CIR-LABEL: @vaddl_high_s16(
+int32x4_t test_vaddl_high_s16(int16x8_t a, int16x8_t b) {
+ // CIR: cir.add {{.*}} : !cir.vector<4 x !s32i>
+
+ // LLVM-SAME: <8 x i16> {{.*}} [[A:%.*]], <8 x i16> {{.*}} [[B:%.*]])
+ // LLVM: [[SHUFFLE_I_I12_I:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> [[A]], <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ // LLVM-NEXT: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I12_I]] to <8 x i8>
+ // LLVM-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
+ // LLVM-NEXT: [[TMP2:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
+ // LLVM-NEXT: [[SHUFFLE_I_I_I:%.*]] = shufflevector <8 x i16> [[B]], <8 x i16> [[B]], <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ // LLVM-NEXT: [[TMP3:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I_I]] to <8 x i8>
+ // LLVM-NEXT: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <4 x i16>
+ // LLVM-NEXT: [[TMP5:%.*]] = sext <4 x i16> [[TMP4]] to <4 x i32>
+ // LLVM-NEXT: [[ADD_I:%.*]] = add <4 x i32> [[TMP2]], [[TMP5]]
+ // LLVM-NEXT: ret <4 x i32> [[ADD_I]]
+ return vaddl_high_s16(a, b);
+}
+
+// LLVM-LABEL: @test_vaddl_high_s32(
+// CIR-LABEL: @vaddl_high_s32(
+int64x2_t test_vaddl_high_s32(int32x4_t a, int32x4_t b) {
+ // CIR: cir.add {{.*}} : !cir.vector<2 x !s64i>
+
+ // LLVM-SAME: <4 x i32> {{.*}} [[A:%.*]], <4 x i32> {{.*}} [[B:%.*]])
+ // LLVM: [[SHUFFLE_I_I12_I:%.*]] = shufflevector <4 x i32> [[A]], <4 x i32> [[A]], <2 x i32> <i32 2, i32 3>
+ // LLVM-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I12_I]] to <8 x i8>
+ // LLVM-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
+ // LLVM-NEXT: [[TMP2:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
+ // LLVM-NEXT: [[SHUFFLE_I_I_I:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[B]], <2 x i32> <i32 2, i32 3>
+ // LLVM-NEXT: [[TMP3:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I_I]] to <8 x i8>
+ // LLVM-NEXT: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <2 x i32>
+ // LLVM-NEXT: [[TMP5:%.*]] = sext <2 x i32> [[TMP4]] to <2 x i64>
+ // LLVM-NEXT: [[ADD_I:%.*]] = add <2 x i64> [[TMP2]], [[TMP5]]
+ // LLVM-NEXT: ret <2 x i64> [[ADD_I]]
+ return vaddl_high_s32(a, b);
+}
+
+// LLVM-LABEL: @test_vaddl_high_u8(
+// CIR-LABEL: @vaddl_high_u8(
+uint16x8_t test_vaddl_high_u8(uint8x16_t a, uint8x16_t b) {
+ // CIR: cir.add {{.*}} : !cir.vector<8 x !u16i>
+
+ // LLVM-SAME: <16 x i8> {{.*}} [[A:%.*]], <16 x i8> {{.*}} [[B:%.*]])
+ // LLVM: [[SHUFFLE_I_I12_I:%.*]] = shufflevector <16 x i8> [[A]], <16 x i8> [[A]], <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ // LLVM-NEXT: [[TMP0:%.*]] = zext <8 x i8> [[SHUFFLE_I_I12_I]] to <8 x i16>
+ // LLVM-NEXT: [[SHUFFLE_I_I_I:%.*]] = shufflevector <16 x i8> [[B]], <16 x i8> [[B]], <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ // LLVM-NEXT: [[TMP1:%.*]] = zext <8 x i8> [[SHUFFLE_I_I_I]] to <8 x i16>
+ // LLVM-NEXT: [[ADD_I:%.*]] = add <8 x i16> [[TMP0]], [[TMP1]]
+ // LLVM-NEXT: ret <8 x i16> [[ADD_I]]
+ return vaddl_high_u8(a, b);
+}
+
+// LLVM-LABEL: @test_vaddl_high_u16(
+// CIR-LABEL: @vaddl_high_u16(
+uint32x4_t test_vaddl_high_u16(uint16x8_t a, uint16x8_t b) {
+ // CIR: cir.add {{.*}} : !cir.vector<4 x !u32i>
+
+ // LLVM-SAME: <8 x i16> {{.*}} [[A:%.*]], <8 x i16> {{.*}} [[B:%.*]])
+ // LLVM: [[SHUFFLE_I_I12_I:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> [[A]], <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ // LLVM-NEXT: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I12_I]] to <8 x i8>
+ // LLVM-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
+ // LLVM-NEXT: [[TMP2:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
+ // LLVM-NEXT: [[SHUFFLE_I_I_I:%.*]] = shufflevector <8 x i16> [[B]], <8 x i16> [[B]], <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ // LLVM-NEXT: [[TMP3:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I_I]] to <8 x i8>
+ // LLVM-NEXT: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <4 x i16>
+ // LLVM-NEXT: [[TMP5:%.*]] = zext <4 x i16> [[TMP4]] to <4 x i32>
+ // LLVM-NEXT: [[ADD_I:%.*]] = add <4 x i32> [[TMP2]], [[TMP5]]
+ // LLVM-NEXT: ret <4 x i32> [[ADD_I]]
+ return vaddl_high_u16(a, b);
+}
+
+// LLVM-LABEL: @test_vaddl_high_u32(
+// CIR-LABEL: @vaddl_high_u32(
+uint64x2_t test_vaddl_high_u32(uint32x4_t a, uint32x4_t b) {
+ // CIR: cir.add {{.*}} : !cir.vector<2 x !u64i>
+
+ // LLVM-SAME: <4 x i32> {{.*}} [[A:%.*]], <4 x i32> {{.*}} [[B:%.*]])
+ // LLVM: [[SHUFFLE_I_I12_I:%.*]] = shufflevector <4 x i32> [[A]], <4 x i32> [[A]], <2 x i32> <i32 2, i32 3>
+ // LLVM-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I12_I]] to <8 x i8>
+ // LLVM-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
+ // LLVM-NEXT: [[TMP2:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
+ // LLVM-NEXT: [[SHUFFLE_I_I_I:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[B]], <2 x i32> <i32 2, i32 3>
+ // LLVM-NEXT: [[TMP3:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I_I]] to <8 x i8>
+ // LLVM-NEXT: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <2 x i32>
+ // LLVM-NEXT: [[TMP5:%.*]] = zext <2 x i32> [[TMP4]] to <2 x i64>
+ // LLVM-NEXT: [[ADD_I:%.*]] = add <2 x i64> [[TMP2]], [[TMP5]]
+ // LLVM-NEXT: ret <2 x i64> [[ADD_I]]
+ return vaddl_high_u32(a, b);
+}
+
+// LLVM-LABEL: @test_vaddw_s8(
+// CIR-LABEL: @vaddw_s8(
+int16x8_t test_vaddw_s8(int16x8_t a, int8x8_t b) {
+ // CIR: cir.add {{.*}} : !cir.vector<8 x !s16i>
+
+ // LLVM-SAME: <8 x i16> {{.*}} [[A:%.*]], <8 x i8> {{.*}} [[B:%.*]])
+ // LLVM: [[VMOVL_I_I:%.*]] = sext <8 x i8> [[B]] to <8 x i16>
+ // LLVM-NEXT: [[ADD_I:%.*]] = add <8 x i16> [[A]], [[VMOVL_I_I]]
+ // LLVM-NEXT: ret <8 x i16> [[ADD_I]]
+ return vaddw_s8(a, b);
+}
+
+// LLVM-LABEL: @test_vaddw_s16(
+// CIR-LABEL: @vaddw_s16(
+int32x4_t test_vaddw_s16(int32x4_t a, int16x4_t b) {
+ // CIR: cir.add {{.*}} : !cir.vector<4 x !s32i>
+
+ // LLVM-SAME: <4 x i32> {{.*}} [[A:%.*]], <4 x i16> {{.*}} [[B:%.*]])
+ // LLVM: [[TMP0:%.*]] = bitcast <4 x i16> [[B]] to <8 x i8>
+ // LLVM-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
+ // LLVM-NEXT: [[VMOVL_I_I:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
+ // LLVM-NEXT: [[ADD_I:%.*]] = add <4 x i32> [[A]], [[VMOVL_I_I]]
+ // LLVM-NEXT: ret <4 x i32> [[ADD_I]]
+ return vaddw_s16(a, b);
+}
+
+// LLVM-LABEL: @test_vaddw_s32(
+// CIR-LABEL: @vaddw_s32(
+int64x2_t test_vaddw_s32(int64x2_t a, int32x2_t b) {
+ // CIR: cir.add {{.*}} : !cir.vector<2 x !s64i>
+
+ // LLVM-SAME: <2 x i64> {{.*}} [[A:%.*]], <2 x i32> {{.*}} [[B:%.*]])
+ // LLVM: [[TMP0:%.*]] = bitcast <2 x i32> [[B]] to <8 x i8>
+ // LLVM-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
+ // LLVM-NEXT: [[VMOVL_I_I:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
+ // LLVM-NEXT: [[ADD_I:%.*]] = add <2 x i64> [[A]], [[VMOVL_I_I]]
+ // LLVM-NEXT: ret <2 x i64> [[ADD_I]]
+ return vaddw_s32(a, b);
+}
+
+// LLVM-LABEL: @test_vaddw_u8(
+// CIR-LABEL: @vaddw_u8(
+uint16x8_t test_vaddw_u8(uint16x8_t a, uint8x8_t b) {
+ // CIR: cir.add {{.*}} : !cir.vector<8 x !u16i>
+
+ // LLVM-SAME: <8 x i16> {{.*}} [[A:%.*]], <8 x i8> {{.*}} [[B:%.*]])
+ // LLVM: [[VMOVL_I_I:%.*]] = zext <8 x i8> [[B]] to <8 x i16>
+ // LLVM-NEXT: [[ADD_I:%.*]] = add <8 x i16> [[A]], [[VMOVL_I_I]]
+ // LLVM-NEXT: ret <8 x i16> [[ADD_I]]
+ return vaddw_u8(a, b);
+}
+
+// LLVM-LABEL: @test_vaddw_u16(
+// CIR-LABEL: @vaddw_u16(
+uint32x4_t test_vaddw_u16(uint32x4_t a, uint16x4_t b) {
+ // CIR: cir.add {{.*}} : !cir.vector<4 x !u32i>
+
+ // LLVM-SAME: <4 x i32> {{.*}} [[A:%.*]], <4 x i16> {{.*}} [[B:%.*]])
+ // LLVM: [[TMP0:%.*]] = bitcast <4 x i16> [[B]] to <8 x i8>
+ // LLVM-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
+ // LLVM-NEXT: [[VMOVL_I_I:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
+ // LLVM-NEXT: [[ADD_I:%.*]] = add <4 x i32> [[A]], [[VMOVL_I_I]]
+ // LLVM-NEXT: ret <4 x i32> [[ADD_I]]
+ return vaddw_u16(a, b);
+}
+
+// LLVM-LABEL: @test_vaddw_u32(
+// CIR-LABEL: @vaddw_u32(
+uint64x2_t test_vaddw_u32(uint64x2_t a, uint32x2_t b) {
+ // CIR: cir.add {{.*}} : !cir.vector<2 x !u64i>
+
+ // LLVM-SAME: <2 x i64> {{.*}} [[A:%.*]], <2 x i32> {{.*}} [[B:%.*]])
+ // LLVM: [[TMP0:%.*]] = bitcast <2 x i32> [[B]] to <8 x i8>
+ // LLVM-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
+ // LLVM-NEXT: [[VMOVL_I_I:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
+ // LLVM-NEXT: [[ADD_I:%.*]] = add <2 x i64> [[A]], [[VMOVL_I_I]]
+ // LLVM-NEXT: ret <2 x i64> [[ADD_I]]
+ return vaddw_u32(a, b);
+}
+
+// LLVM-LABEL: @test_vaddw_high_s8(
+// CIR-LABEL: @vaddw_high_s8(
+int16x8_t test_vaddw_high_s8(int16x8_t a, int8x16_t b) {
+ // CIR: cir.add {{.*}} : !cir.vector<8 x !s16i>
+
+ // LLVM-SAME: <8 x i16> {{.*}} [[A:%.*]], <16 x i8> {{.*}} [[B:%.*]])
+ // LLVM: [[SHUFFLE_I_I_I:%.*]] = shufflevector <16 x i8> [[B]], <16 x i8> [[B]], <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ // LLVM-NEXT: [[TMP0:%.*]] = sext <8 x i8> [[SHUFFLE_I_I_I]] to <8 x i16>
+ // LLVM-NEXT: [[ADD_I:%.*]] = add <8 x i16> [[A]], [[TMP0]]
+ // LLVM-NEXT: ret <8 x i16> [[ADD_I]]
+ return vaddw_high_s8(a, b);
+}
+
+// LLVM-LABEL: @test_vaddw_high_s16(
+// CIR-LABEL: @vaddw_high_s16(
+int32x4_t test_vaddw_high_s16(int32x4_t a, int16x8_t b) {
+ // CIR: cir.add {{.*}} : !cir.vector<4 x !s32i>
+
+ // LLVM-SAME: <4 x i32> {{.*}} [[A:%.*]], <8 x i16> {{.*}} [[B:%.*]])
+ // LLVM: [[SHUFFLE_I_I_I:%.*]] = shufflevector <8 x i16> [[B]], <8 x i16> [[B]], <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ // LLVM-NEXT: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I_I]] to <8 x i8>
+ // LLVM-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
+ // LLVM-NEXT: [[TMP2:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
+ // LLVM-NEXT: [[ADD_I:%.*]] = add <4 x i32> [[A]], [[TMP2]]
+ // LLVM-NEXT: ret <4 x i32> [[ADD_I]]
+ return vaddw_high_s16(a, b);
+}
+
+// LLVM-LABEL: @test_vaddw_high_s32(
+// CIR-LABEL: @vaddw_high_s32(
+int64x2_t test_vaddw_high_s32(int64x2_t a, int32x4_t b) {
+ // CIR: cir.add {{.*}} : !cir.vector<2 x !s64i>
+
+ // LLVM-SAME: <2 x i64> {{.*}} [[A:%.*]], <4 x i32> {{.*}} [[B:%.*]])
+ // LLVM: [[SHUFFLE_I_I_I:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[B]], <2 x i32> <i32 2, i32 3>
+ // LLVM-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I_I]] to <8 x i8>
+ // LLVM-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
+ // LLVM-NEXT: [[TMP2:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
+ // LLVM-NEXT: [[ADD_I:%.*]] = add <2 x i64> [[A]], [[TMP2]]
+ // LLVM-NEXT: ret <2 x i64> [[ADD_I]]
+ return vaddw_high_s32(a, b);
+}
+
+// LLVM-LABEL: @test_vaddw_high_u8(
+// CIR-LABEL: @vaddw_high_u8(
+uint16x8_t test_vaddw_high_u8(uint16x8_t a, uint8x16_t b) {
+ // CIR: cir.add {{.*}} : !cir.vector<8 x !u16i>
+
+ // LLVM-SAME: <8 x i16> {{.*}} [[A:%.*]], <16 x i8> {{.*}} [[B:%.*]])
+ // LLVM: [[SHUFFLE_I_I_I:%.*]] = shufflevector <16 x i8> [[B]], <16 x i8> [[B]], <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ // LLVM-NEXT: [[TMP0:%.*]] = zext <8 x i8> [[SHUFFLE_I_I_I]] to <8 x i16>
+ // LLVM-NEXT: [[ADD_I:%.*]] = add <8 x i16> [[A]], [[TMP0]]
+ // LLVM-NEXT: ret <8 x i16> [[ADD_I]]
+ return vaddw_high_u8(a, b);
+}
+
+// LLVM-LABEL: @test_vaddw_high_u16(
+// CIR-LABEL: @vaddw_high_u16(
+uint32x4_t test_vaddw_high_u16(uint32x4_t a, uint16x8_t b) {
+ // CIR: cir.add {{.*}} : !cir.vector<4 x !u32i>
+
+ // LLVM-SAME: <4 x i32> {{.*}} [[A:%.*]], <8 x i16> {{.*}} [[B:%.*]])
+ // LLVM: [[SHUFFLE_I_I_I:%.*]] = shufflevector <8 x i16> [[B]], <8 x i16> [[B]], <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ // LLVM-NEXT: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I_I]] to <8 x i8>
+ // LLVM-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
+ // LLVM-NEXT: [[TMP2:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
+ // LLVM-NEXT: [[ADD_I:%.*]] = add <4 x i32> [[A]], [[TMP2]]
+ // LLVM-NEXT: ret <4 x i32> [[ADD_I]]
+ return vaddw_high_u16(a, b);
+}
+
+// LLVM-LABEL: @test_vaddw_high_u32(
+// CIR-LABEL: @vaddw_high_u32(
+uint64x2_t test_vaddw_high_u32(uint64x2_t a, uint32x4_t b) {
+ // CIR: cir.add {{.*}} : !cir.vector<2 x !u64i>
+
+ // LLVM-SAME: <2 x i64> {{.*}} [[A:%.*]], <4 x i32> {{.*}} [[B:%.*]])
+ // LLVM: [[SHUFFLE_I_I_I:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[B]], <2 x i32> <i32 2, i32 3>
+ // LLVM-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I_I]] to <8 x i8>
+ // LLVM-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
+ // LLVM-NEXT: [[TMP2:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
+ // LLVM-NEXT: [[ADD_I:%.*]] = add <2 x i64> [[A]], [[TMP2]]
+ // LLVM-NEXT: ret <2 x i64> [[ADD_I]]
+ return vaddw_high_u32(a, b);
+}
diff --git a/clang/test/CodeGen/AArch64/neon/intrinsics.c b/clang/test/CodeGen/AArch64/neon/intrinsics.c
index ca3ae478d6546..3f309f7359084 100644
--- a/clang/test/CodeGen/AArch64/neon/intrinsics.c
+++ b/clang/test/CodeGen/AArch64/neon/intrinsics.c
@@ -6881,3 +6881,190 @@ float64_t test_vpmaxnmqd_f64(float64x2_t a) {
// LLVM-NEXT: ret double [[VPMAXNMQD_F64_I]]
return vpmaxnmqd_f64(a);
}
+
+//===----------------------------------------------------------------------===//
+// 2.1.3.1.5. Vector shift left and widen
+// https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#vector-shift-left-and-widen
+//===----------------------------------------------------------------------===//
+
+// ALL-LABEL: @test_vshll_n_s8(
+int16x8_t test_vshll_n_s8(int8x8_t a) {
+// CIR: cir.cast integral %{{.*}} : !cir.vector<8 x !s8i> -> !cir.vector<8 x !s16i>
+// CIR: cir.shift(left, %{{.*}} : !cir.vector<8 x !s16i>, %{{.*}} : !cir.vector<8 x !s16i>) -> !cir.vector<8 x !s16i>
+
+// LLVM-SAME: <8 x i8> {{.*}} [[A:%.*]]) {{.*}} {
+// LLVM: [[TMP0:%.*]] = sext <8 x i8> [[A]] to <8 x i16>
+// LLVM-NEXT: [[VSHLL_N:%.*]] = shl <8 x i16> [[TMP0]], splat (i16 3)
+// LLVM: ret <8 x i16> [[VSHLL_N]]
+ return vshll_n_s8(a, 3);
+}
+
+// ALL-LABEL: @test_vshll_n_s16(
+int32x4_t test_vshll_n_s16(int16x4_t a) {
+// CIR: cir.cast bitcast %{{.*}} : !cir.vector<8 x !s8i> -> !cir.vector<4 x !s16i>
+// CIR: cir.cast integral %{{.*}} : !cir.vector<4 x !s16i> -> !cir.vector<4 x !s32i>
+// CIR: cir.shift(left, %{{.*}} : !cir.vector<4 x !s32i>, %{{.*}} : !cir.vector<4 x !s32i>) -> !cir.vector<4 x !s32i>
+
+// LLVM-SAME: <4 x i16> {{.*}} [[A:%.*]]) {{.*}} {
+// LLVM: [[TMP0:%.*]] = bitcast <4 x i16> [[A]] to <8 x i8>
+// LLVM-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
+// LLVM-NEXT: [[TMP2:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
+// LLVM-NEXT: [[VSHLL_N:%.*]] = shl <4 x i32> [[TMP2]], splat (i32 9)
+// LLVM: ret <4 x i32> [[VSHLL_N]]
+ return vshll_n_s16(a, 9);
+}
+
+// ALL-LABEL: @test_vshll_n_s32(
+int64x2_t test_vshll_n_s32(int32x2_t a) {
+// CIR: cir.cast bitcast %{{.*}} : !cir.vector<8 x !s8i> -> !cir.vector<2 x !s32i>
+// CIR: cir.cast integral %{{.*}} : !cir.vector<2 x !s32i> -> !cir.vector<2 x !s64i>
+// CIR: cir.shift(left, %{{.*}} : !cir.vector<2 x !s64i>, %{{.*}} : !cir.vector<2 x !s64i>) -> !cir.vector<2 x !s64i>
+
+// LLVM-SAME: <2 x i32> {{.*}} [[A:%.*]]) {{.*}} {
+// LLVM: [[TMP0:%.*]] = bitcast <2 x i32> [[A]] to <8 x i8>
+// LLVM-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
+// LLVM-NEXT: [[TMP2:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
+// LLVM-NEXT: [[VSHLL_N:%.*]] = shl <2 x i64> [[TMP2]], splat (i64 19)
+// LLVM: ret <2 x i64> [[VSHLL_N]]
+ return vshll_n_s32(a, 19);
+}
+
+// ALL-LABEL: @test_vshll_n_u8(
+uint16x8_t test_vshll_n_u8(uint8x8_t a) {
+// CIR: cir.cast bitcast %{{.*}} : !cir.vector<8 x !s8i> -> !cir.vector<8 x !u8i>
+// CIR: cir.cast integral %{{.*}} : !cir.vector<8 x !u8i> -> !cir.vector<8 x !u16i>
+// CIR: cir.shift(left, %{{.*}} : !cir.vector<8 x !u16i>, %{{.*}} : !cir.vector<8 x !u16i>) -> !cir.vector<8 x !u16i>
+
+// LLVM-SAME: <8 x i8> {{.*}} [[A:%.*]]) {{.*}} {
+// LLVM: [[TMP0:%.*]] = zext <8 x i8> [[A]] to <8 x i16>
+// LLVM-NEXT: [[VSHLL_N:%.*]] = shl <8 x i16> [[TMP0]], splat (i16 3)
+// LLVM: ret <8 x i16> [[VSHLL_N]]
+ return vshll_n_u8(a, 3);
+}
+
+// ALL-LABEL: @test_vshll_n_u16(
+uint32x4_t test_vshll_n_u16(uint16x4_t a) {
+// CIR: cir.cast bitcast %{{.*}} : !cir.vector<8 x !s8i> -> !cir.vector<4 x !u16i>
+// CIR: cir.cast integral %{{.*}} : !cir.vector<4 x !u16i> -> !cir.vector<4 x !u32i>
+// CIR: cir.shift(left, %{{.*}} : !cir.vector<4 x !u32i>, %{{.*}} : !cir.vector<4 x !u32i>) -> !cir.vector<4 x !u32i>
+
+// LLVM-SAME: <4 x i16> {{.*}} [[A:%.*]]) {{.*}} {
+// LLVM: [[TMP0:%.*]] = bitcast <4 x i16> [[A]] to <8 x i8>
+// LLVM-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
+// LLVM-NEXT: [[TMP2:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
+// LLVM-NEXT: [[VSHLL_N:%.*]] = shl <4 x i32> [[TMP2]], splat (i32 9)
+// LLVM: ret <4 x i32> [[VSHLL_N]]
+ return vshll_n_u16(a, 9);
+}
+
+// ALL-LABEL: @test_vshll_n_u32(
+uint64x2_t test_vshll_n_u32(uint32x2_t a) {
+// CIR: cir.cast bitcast %{{.*}} : !cir.vector<8 x !s8i> -> !cir.vector<2 x !u32i>
+// CIR: cir.cast integral %{{.*}} : !cir.vector<2 x !u32i> -> !cir.vector<2 x !u64i>
+// CIR: cir.shift(left, %{{.*}} : !cir.vector<2 x !u64i>, %{{.*}} : !cir.vector<2 x !u64i>) -> !cir.vector<2 x !u64i>
+
+// LLVM-SAME: <2 x i32> {{.*}} [[A:%.*]]) {{.*}} {
+// LLVM: [[TMP0:%.*]] = bitcast <2 x i32> [[A]] to <8 x i8>
+// LLVM-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
+// LLVM-NEXT: [[TMP2:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
+// LLVM-NEXT: [[VSHLL_N:%.*]] = shl <2 x i64> [[TMP2]], splat (i64 19)
+// LLVM: ret <2 x i64> [[VSHLL_N]]
+ return vshll_n_u32(a, 19);
+}
+
+// ALL-LABEL: @test_vshll_high_n_s8(
+int16x8_t test_vshll_high_n_s8(int8x16_t a) {
+// CIR: cir.call @vget_high_s8
+// CIR: cir.cast integral %{{.*}} : !cir.vector<8 x !s8i> -> !cir.vector<8 x !s16i>
+// CIR: cir.shift(left, %{{.*}} : !cir.vector<8 x !s16i>, %{{.*}} : !cir.vector<8 x !s16i>) -> !cir.vector<8 x !s16i>
+
+// LLVM-SAME: <16 x i8> {{.*}} [[A:%.*]]) {{.*}} {
+// LLVM: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> [[A]], <16 x i8> [[A]], <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+// LLVM-NEXT: [[TMP0:%.*]] = sext <8 x i8> [[SHUFFLE_I]] to <8 x i16>
+// LLVM-NEXT: [[VSHLL_N:%.*]] = shl <8 x i16> [[TMP0]], splat (i16 3)
+// LLVM: ret <8 x i16> [[VSHLL_N]]
+ return vshll_high_n_s8(a, 3);
+}
+
+// ALL-LABEL: @test_vshll_high_n_s16(
+int32x4_t test_vshll_high_n_s16(int16x8_t a) {
+// CIR: cir.call @vget_high_s16
+// CIR: cir.cast bitcast %{{.*}} : !cir.vector<8 x !s8i> -> !cir.vector<4 x !s16i>
+// CIR: cir.cast integral %{{.*}} : !cir.vector<4 x !s16i> -> !cir.vector<4 x !s32i>
+// CIR: cir.shift(left, %{{.*}} : !cir.vector<4 x !s32i>, %{{.*}} : !cir.vector<4 x !s32i>) -> !cir.vector<4 x !s32i>
+
+// LLVM-SAME: <8 x i16> {{.*}} [[A:%.*]]) {{.*}} {
+// LLVM: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> [[A]], <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// LLVM-NEXT: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
+// LLVM-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
+// LLVM-NEXT: [[TMP2:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
+// LLVM-NEXT: [[VSHLL_N:%.*]] = shl <4 x i32> [[TMP2]], splat (i32 9)
+// LLVM: ret <4 x i32> [[VSHLL_N]]
+ return vshll_high_n_s16(a, 9);
+}
+
+// ALL-LABEL: @test_vshll_high_n_s32(
+int64x2_t test_vshll_high_n_s32(int32x4_t a) {
+// CIR: cir.call @vget_high_s32
+// CIR: cir.cast bitcast %{{.*}} : !cir.vector<8 x !s8i> -> !cir.vector<2 x !s32i>
+// CIR: cir.cast integral %{{.*}} : !cir.vector<2 x !s32i> -> !cir.vector<2 x !s64i>
+// CIR: cir.shift(left, %{{.*}} : !cir.vector<2 x !s64i>, %{{.*}} : !cir.vector<2 x !s64i>) -> !cir.vector<2 x !s64i>
+
+// LLVM-SAME: <4 x i32> {{.*}} [[A:%.*]]) {{.*}} {
+// LLVM: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> [[A]], <4 x i32> [[A]], <2 x i32> <i32 2, i32 3>
+// LLVM-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
+// LLVM-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
+// LLVM-NEXT: [[TMP2:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
+// LLVM-NEXT: [[VSHLL_N:%.*]] = shl <2 x i64> [[TMP2]], splat (i64 19)
+// LLVM: ret <2 x i64> [[VSHLL_N]]
+ return vshll_high_n_s32(a, 19);
+}
+
+// ALL-LABEL: @test_vshll_high_n_u8(
+uint16x8_t test_vshll_high_n_u8(uint8x16_t a) {
+// CIR: cir.call @vget_high_u8
+// CIR: cir.cast bitcast %{{.*}} : !cir.vector<8 x !s8i> -> !cir.vector<8 x !u8i>
+// CIR: cir.cast integral %{{.*}} : !cir.vector<8 x !u8i> -> !cir.vector<8 x !u16i>
+// CIR: cir.shift(left, %{{.*}} : !cir.vector<8 x !u16i>, %{{.*}} : !cir.vector<8 x !u16i>) -> !cir.vector<8 x !u16i>
+
+// LLVM-SAME: <16 x i8> {{.*}} [[A:%.*]]) {{.*}} {
+// LLVM: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> [[A]], <16 x i8> [[A]], <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+// LLVM-NEXT: [[TMP0:%.*]] = zext <8 x i8> [[SHUFFLE_I]] to <8 x i16>
+// LLVM-NEXT: [[VSHLL_N:%.*]] = shl <8 x i16> [[TMP0]], splat (i16 3)
+// LLVM: ret <8 x i16> [[VSHLL_N]]
+ return vshll_high_n_u8(a, 3);
+}
+
+// ALL-LABEL: @test_vshll_high_n_u16(
+uint32x4_t test_vshll_high_n_u16(uint16x8_t a) {
+// CIR: cir.call @vget_high_u16
+// CIR: cir.cast bitcast %{{.*}} : !cir.vector<8 x !s8i> -> !cir.vector<4 x !u16i>
+// CIR: cir.cast integral %{{.*}} : !cir.vector<4 x !u16i> -> !cir.vector<4 x !u32i>
+// CIR: cir.shift(left, %{{.*}} : !cir.vector<4 x !u32i>, %{{.*}} : !cir.vector<4 x !u32i>) -> !cir.vector<4 x !u32i>
+
+// LLVM-SAME: <8 x i16> {{.*}} [[A:%.*]]) {{.*}} {
+// LLVM: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> [[A]], <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+// LLVM-NEXT: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
+// LLVM-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
+// LLVM-NEXT: [[TMP2:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
+// LLVM-NEXT: [[VSHLL_N:%.*]] = shl <4 x i32> [[TMP2]], splat (i32 9)
+// LLVM: ret <4 x i32> [[VSHLL_N]]
+ return vshll_high_n_u16(a, 9);
+}
+
+// ALL-LABEL: @test_vshll_high_n_u32(
+uint64x2_t test_vshll_high_n_u32(uint32x4_t a) {
+// CIR: cir.call @vget_high_u32
+// CIR: cir.cast bitcast %{{.*}} : !cir.vector<8 x !s8i> -> !cir.vector<2 x !u32i>
+// CIR: cir.cast integral %{{.*}} : !cir.vector<2 x !u32i> -> !cir.vector<2 x !u64i>
+// CIR: cir.shift(left, %{{.*}} : !cir.vector<2 x !u64i>, %{{.*}} : !cir.vector<2 x !u64i>) -> !cir.vector<2 x !u64i>
+
+// LLVM-SAME: <4 x i32> {{.*}} [[A:%.*]]) {{.*}} {
+// LLVM: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> [[A]], <4 x i32> [[A]], <2 x i32> <i32 2, i32 3>
+// LLVM-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
+// LLVM-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
+// LLVM-NEXT: [[TMP2:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
+// LLVM-NEXT: [[VSHLL_N:%.*]] = shl <2 x i64> [[TMP2]], splat (i64 19)
+// LLVM: ret <2 x i64> [[VSHLL_N]]
+ return vshll_high_n_u32(a, 19);
+}
More information about the cfe-commits
mailing list