https://github.com/iamvickynguyen created https://github.com/llvm/llvm-project/pull/204285
Related to https://github.com/llvm/llvm-project/issues/185382 CIR lowering for - widening-addition intrinsics (https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#widening-addition) Port tests: - `clang/test/CodeGen/AArch64/neon_intrinsics.c` to `clang/test/CodeGen/AArch64/neon/add.c` >From d5299dd6ad9c6c4a51596049a5a38671df486517 Mon Sep 17 00:00:00 2001 From: Vicky Nguyen <[email protected]> Date: Thu, 11 Jun 2026 20:04:29 -0700 Subject: [PATCH] [CIR][AArch64] Upstream widening-addition NEON builtins --- .../lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp | 26 +- clang/test/CodeGen/AArch64/neon-intrinsics.c | 342 ---------------- clang/test/CodeGen/AArch64/neon/add.c | 370 ++++++++++++++++++ 3 files changed, 394 insertions(+), 344 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp index 0e35aff9f2370..d883b12c39b3b 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp @@ -882,7 +882,16 @@ static mlir::Value emitCommonNeonBuiltinExpr( case NEON::BI__builtin_neon_vld3q_lane_v: case NEON::BI__builtin_neon_vld4_lane_v: case NEON::BI__builtin_neon_vld4q_lane_v: - case NEON::BI__builtin_neon_vmovl_v: + case NEON::BI__builtin_neon_vmovl_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); + return builder.createIntCast(src, vTy); + } case NEON::BI__builtin_neon_vmovn_v: case NEON::BI__builtin_neon_vmull_v: case NEON::BI__builtin_neon_vpadal_v: @@ -949,7 +958,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 84cfeab2c7c0e..ee0271d55b021 100644 --- a/clang/test/CodeGen/AArch64/neon-intrinsics.c +++ b/clang/test/CodeGen/AArch64/neon-intrinsics.c @@ -5630,348 +5630,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_s8( // CHECK-SAME: <8 x i8> noundef [[A:%.*]], <8 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 916f4af59363e..4c286aba40f72 100644 --- a/clang/test/CodeGen/AArch64/neon/add.c +++ b/clang/test/CodeGen/AArch64/neon/add.c @@ -103,3 +103,373 @@ poly128_t test_vaddq_p128(poly128_t a, poly128_t b) { return vaddq_p128(a, b); } +//===----------------------------------------------------------------------===// +// 2.2.2.3. 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); +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
