https://github.com/xiongzile updated https://github.com/llvm/llvm-project/pull/191845
>From fbf1680afd585b361ab490edfe648473ef2e9190 Mon Sep 17 00:00:00 2001 From: Zile Xiong <[email protected]> Date: Mon, 13 Apr 2026 23:36:36 +0800 Subject: [PATCH] [clang][clangir] add vpaddl and vpaddlq support --- .../lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp | 43 ++- clang/test/CodeGen/AArch64/neon/vpaddlorq.c | 250 ++++++++++++++++++ 2 files changed, 292 insertions(+), 1 deletion(-) create mode 100644 clang/test/CodeGen/AArch64/neon/vpaddlorq.c diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp index 75dd19d880444..5e4eff3b31af0 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp @@ -196,6 +196,42 @@ static mlir::Value emitNeonCall(CIRGenModule &cgm, CIRGenBuilderTy &builder, isConstrainedFPIntrinsic, shift, rightshift); } +static cir::VectorType getVPaddlInputVectorType(cir::VectorType resType) { + auto elemTy = resType.getElementType(); + auto lanes = resType.getSize(); + if (auto intTy = mlir::dyn_cast<cir::IntType>(elemTy)) { + unsigned resWidth = intTy.getWidth(); + assert((resWidth == 16 || resWidth == 32 || resWidth == 64) && + "unexpected vpaddl result element width"); + + unsigned argWidth = resWidth / 2; + unsigned argLanes = lanes * 2; + bool isSigned = intTy.isSigned(); + mlir::Type argElemTy = + cir::IntType::get(resType.getContext(), argWidth, isSigned); + cir::VectorType result = cir::VectorType::get(argElemTy, argLanes); + return result; + } + + llvm_unreachable("vpaddl result type must be an integer vector"); +} + +static mlir::Value emitNeonVPaddlCall(CIRGenFunction &cgf, + llvm::SmallVectorImpl<mlir::Value> &args, + cir::VectorType vTy, mlir::Location loc, + unsigned unsignedIntrinsicID, + unsigned signedIntrinsicID, + bool isUnsigned) { + llvm::StringRef llvmIntrName = + getLLVMIntrNameNoPrefix(static_cast<llvm::Intrinsic::ID>( + isUnsigned ? unsignedIntrinsicID : signedIntrinsicID)); + args[0] = + cgf.getBuilder().createBitcast(args[0], getVPaddlInputVectorType(vTy)); + return emitNeonCall(cgf.getCIRGenModule(), cgf.getBuilder(), + /*argTypes=*/{args[0].getType()}, args, llvmIntrName, + /*funcResTy=*/vTy, loc); +} + static mlir::Value emitCommonNeonSISDBuiltinExpr( CIRGenFunction &cgf, const ARMVectorIntrinsicInfo &info, llvm::SmallVectorImpl<mlir::Value> &ops, const CallExpr *expr) { @@ -414,7 +450,6 @@ static mlir::Value emitCommonNeonBuiltinExpr( CIRGenFunction &cgf, unsigned builtinID, unsigned llvmIntrinsic, unsigned altLLVMIntrinsic, const char *nameHint, unsigned modifier, const CallExpr *expr, llvm::SmallVectorImpl<mlir::Value> &ops) { - mlir::Location loc = cgf.getLoc(expr->getExprLoc()); clang::ASTContext &ctx = cgf.getContext(); @@ -638,8 +673,14 @@ static mlir::Value emitCommonNeonBuiltinExpr( case NEON::BI__builtin_neon_vmull_v: case NEON::BI__builtin_neon_vpadal_v: case NEON::BI__builtin_neon_vpadalq_v: + cgf.cgm.errorNYI(expr->getSourceRange(), + std::string("unimplemented AArch64 builtin call: ") + + ctx.BuiltinInfo.getName(builtinID)); + return mlir::Value{}; case NEON::BI__builtin_neon_vpaddl_v: case NEON::BI__builtin_neon_vpaddlq_v: + return emitNeonVPaddlCall(cgf, ops, vTy, loc, llvmIntrinsic, + altLLVMIntrinsic, usgn); case NEON::BI__builtin_neon_vqdmlal_v: case NEON::BI__builtin_neon_vqdmlsl_v: case NEON::BI__builtin_neon_vqdmulhq_lane_v: diff --git a/clang/test/CodeGen/AArch64/neon/vpaddlorq.c b/clang/test/CodeGen/AArch64/neon/vpaddlorq.c new file mode 100644 index 0000000000000..d5b9f1abe4c4b --- /dev/null +++ b/clang/test/CodeGen/AArch64/neon/vpaddlorq.c @@ -0,0 +1,250 @@ +// REQUIRES: aarch64-registered-target + +// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -disable-O0-optnone -fclangir -emit-llvm -o - %s | opt -S -passes=mem2reg | FileCheck %s --check-prefixes=CIR-LLVM +// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -disable-O0-optnone -emit-llvm -o - %s | opt -S -passes=mem2reg | FileCheck %s --check-prefixes=LLVM + +#include <arm_neon.h> + +// CIR-LLVM-LABEL: define dso_local <4 x i16> @test_vpaddl_s8( +// CIR-LLVM-SAME: <8 x i8> noundef [[TMP0:%.*]]) #[[ATTR0:[0-9]+]] { +// CIR-LLVM-NEXT: [[TMP2:%.*]] = call <4 x i16> @llvm.aarch64.neon.saddlp.v4i16.v8i8(<8 x i8> [[TMP0]]) +// CIR-LLVM-NEXT: ret <4 x i16> [[TMP2]] +// +// LLVM-LABEL: define dso_local <4 x i16> @test_vpaddl_s8( +// LLVM-SAME: <8 x i8> noundef [[A:%.*]]) #[[ATTR0:[0-9]+]] { +// LLVM-NEXT: [[ENTRY:.*:]] +// LLVM-NEXT: [[VPADDL_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.saddlp.v4i16.v8i8(<8 x i8> [[A]]) +// LLVM-NEXT: ret <4 x i16> [[VPADDL_I]] +// +int16x4_t test_vpaddl_s8(int8x8_t a) { + return vpaddl_s8(a); +} + +// CIR-LLVM-LABEL: define dso_local <8 x i16> @test_vpaddlq_s8( +// CIR-LLVM-SAME: <16 x i8> noundef [[TMP0:%.*]]) #[[ATTR0]] { +// CIR-LLVM-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.aarch64.neon.saddlp.v8i16.v16i8(<16 x i8> [[TMP0]]) +// CIR-LLVM-NEXT: ret <8 x i16> [[TMP2]] +// +// LLVM-LABEL: define dso_local <8 x i16> @test_vpaddlq_s8( +// LLVM-SAME: <16 x i8> noundef [[A:%.*]]) #[[ATTR0]] { +// LLVM-NEXT: [[ENTRY:.*:]] +// LLVM-NEXT: [[VPADDL_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.saddlp.v8i16.v16i8(<16 x i8> [[A]]) +// LLVM-NEXT: ret <8 x i16> [[VPADDL_I]] +// +int16x8_t test_vpaddlq_s8(int8x16_t a) { + return vpaddlq_s8(a); +} + +// CIR-LLVM-LABEL: define dso_local <2 x i32> @test_vpaddl_s16( +// CIR-LLVM-SAME: <4 x i16> noundef [[TMP0:%.*]]) #[[ATTR0]] { +// CIR-LLVM-NEXT: [[TMP2:%.*]] = alloca <4 x i16>, i64 1, align 8 +// CIR-LLVM-NEXT: store <4 x i16> [[TMP0]], ptr [[TMP2]], align 8 +// CIR-LLVM-NEXT: [[TMP3:%.*]] = load <8 x i8>, ptr [[TMP2]], align 8 +// CIR-LLVM-NEXT: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <4 x i16> +// CIR-LLVM-NEXT: [[TMP5:%.*]] = call <2 x i32> @llvm.aarch64.neon.saddlp.v2i32.v4i16(<4 x i16> [[TMP4]]) +// CIR-LLVM-NEXT: ret <2 x i32> [[TMP5]] +// +// LLVM-LABEL: define dso_local <2 x i32> @test_vpaddl_s16( +// LLVM-SAME: <4 x i16> noundef [[A:%.*]]) #[[ATTR0]] { +// LLVM-NEXT: [[ENTRY:.*:]] +// LLVM-NEXT: [[__P0_ADDR_I:%.*]] = alloca <4 x i16>, align 8 +// LLVM-NEXT: store <4 x i16> [[A]], ptr [[__P0_ADDR_I]], align 8 +// LLVM-NEXT: [[TMP0:%.*]] = load <8 x i8>, ptr [[__P0_ADDR_I]], align 8 +// LLVM-NEXT: [[VPADDL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16> +// LLVM-NEXT: [[VPADDL1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.saddlp.v2i32.v4i16(<4 x i16> [[VPADDL_I]]) +// LLVM-NEXT: ret <2 x i32> [[VPADDL1_I]] +// +int32x2_t test_vpaddl_s16(int16x4_t a) { + return vpaddl_s16(a); +} + +// CIR-LLVM-LABEL: define dso_local <4 x i32> @test_vpaddlq_s16( +// CIR-LLVM-SAME: <8 x i16> noundef [[TMP0:%.*]]) #[[ATTR0]] { +// CIR-LLVM-NEXT: [[TMP2:%.*]] = alloca <8 x i16>, i64 1, align 16 +// CIR-LLVM-NEXT: store <8 x i16> [[TMP0]], ptr [[TMP2]], align 16 +// CIR-LLVM-NEXT: [[TMP3:%.*]] = load <16 x i8>, ptr [[TMP2]], align 16 +// CIR-LLVM-NEXT: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP3]] to <8 x i16> +// CIR-LLVM-NEXT: [[TMP5:%.*]] = call <4 x i32> @llvm.aarch64.neon.saddlp.v4i32.v8i16(<8 x i16> [[TMP4]]) +// CIR-LLVM-NEXT: ret <4 x i32> [[TMP5]] +// +// LLVM-LABEL: define dso_local <4 x i32> @test_vpaddlq_s16( +// LLVM-SAME: <8 x i16> noundef [[A:%.*]]) #[[ATTR0]] { +// LLVM-NEXT: [[ENTRY:.*:]] +// LLVM-NEXT: [[__P0_ADDR_I:%.*]] = alloca <8 x i16>, align 16 +// LLVM-NEXT: store <8 x i16> [[A]], ptr [[__P0_ADDR_I]], align 16 +// LLVM-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[__P0_ADDR_I]], align 16 +// LLVM-NEXT: [[VPADDL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16> +// LLVM-NEXT: [[VPADDL1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.saddlp.v4i32.v8i16(<8 x i16> [[VPADDL_I]]) +// LLVM-NEXT: ret <4 x i32> [[VPADDL1_I]] +// +int32x4_t test_vpaddlq_s16(int16x8_t a) { + return vpaddlq_s16(a); +} + +// CIR-LLVM-LABEL: define dso_local <1 x i64> @test_vpaddl_s32( +// CIR-LLVM-SAME: <2 x i32> noundef [[TMP0:%.*]]) #[[ATTR0]] { +// CIR-LLVM-NEXT: [[TMP2:%.*]] = alloca <2 x i32>, i64 1, align 8 +// CIR-LLVM-NEXT: store <2 x i32> [[TMP0]], ptr [[TMP2]], align 8 +// CIR-LLVM-NEXT: [[TMP3:%.*]] = load <8 x i8>, ptr [[TMP2]], align 8 +// CIR-LLVM-NEXT: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <2 x i32> +// CIR-LLVM-NEXT: [[TMP5:%.*]] = call <1 x i64> @llvm.aarch64.neon.saddlp.v1i64.v2i32(<2 x i32> [[TMP4]]) +// CIR-LLVM-NEXT: ret <1 x i64> [[TMP5]] +// +// LLVM-LABEL: define dso_local <1 x i64> @test_vpaddl_s32( +// LLVM-SAME: <2 x i32> noundef [[A:%.*]]) #[[ATTR0]] { +// LLVM-NEXT: [[ENTRY:.*:]] +// LLVM-NEXT: [[__P0_ADDR_I:%.*]] = alloca <2 x i32>, align 8 +// LLVM-NEXT: store <2 x i32> [[A]], ptr [[__P0_ADDR_I]], align 8 +// LLVM-NEXT: [[TMP0:%.*]] = load <8 x i8>, ptr [[__P0_ADDR_I]], align 8 +// LLVM-NEXT: [[VPADDL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32> +// LLVM-NEXT: [[VPADDL1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.saddlp.v1i64.v2i32(<2 x i32> [[VPADDL_I]]) +// LLVM-NEXT: ret <1 x i64> [[VPADDL1_I]] +// +int64x1_t test_vpaddl_s32(int32x2_t a) { + return vpaddl_s32(a); +} + +// CIR-LLVM-LABEL: define dso_local <2 x i64> @test_vpaddlq_s32( +// CIR-LLVM-SAME: <4 x i32> noundef [[TMP0:%.*]]) #[[ATTR0]] { +// CIR-LLVM-NEXT: [[TMP2:%.*]] = alloca <4 x i32>, i64 1, align 16 +// CIR-LLVM-NEXT: store <4 x i32> [[TMP0]], ptr [[TMP2]], align 16 +// CIR-LLVM-NEXT: [[TMP3:%.*]] = load <16 x i8>, ptr [[TMP2]], align 16 +// CIR-LLVM-NEXT: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP3]] to <4 x i32> +// CIR-LLVM-NEXT: [[TMP5:%.*]] = call <2 x i64> @llvm.aarch64.neon.saddlp.v2i64.v4i32(<4 x i32> [[TMP4]]) +// CIR-LLVM-NEXT: ret <2 x i64> [[TMP5]] +// +// LLVM-LABEL: define dso_local <2 x i64> @test_vpaddlq_s32( +// LLVM-SAME: <4 x i32> noundef [[A:%.*]]) #[[ATTR0]] { +// LLVM-NEXT: [[ENTRY:.*:]] +// LLVM-NEXT: [[__P0_ADDR_I:%.*]] = alloca <4 x i32>, align 16 +// LLVM-NEXT: store <4 x i32> [[A]], ptr [[__P0_ADDR_I]], align 16 +// LLVM-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[__P0_ADDR_I]], align 16 +// LLVM-NEXT: [[VPADDL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32> +// LLVM-NEXT: [[VPADDL1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.saddlp.v2i64.v4i32(<4 x i32> [[VPADDL_I]]) +// LLVM-NEXT: ret <2 x i64> [[VPADDL1_I]] +// +int64x2_t test_vpaddlq_s32(int32x4_t a) { + return vpaddlq_s32(a); +} + +// CIR-LLVM-LABEL: define dso_local <4 x i16> @test_vpaddl_u8( +// CIR-LLVM-SAME: <8 x i8> noundef [[TMP0:%.*]]) #[[ATTR0]] { +// CIR-LLVM-NEXT: [[TMP2:%.*]] = call <4 x i16> @llvm.aarch64.neon.uaddlp.v4i16.v8i8(<8 x i8> [[TMP0]]) +// CIR-LLVM-NEXT: ret <4 x i16> [[TMP2]] +// +// LLVM-LABEL: define dso_local <4 x i16> @test_vpaddl_u8( +// LLVM-SAME: <8 x i8> noundef [[A:%.*]]) #[[ATTR0]] { +// LLVM-NEXT: [[ENTRY:.*:]] +// LLVM-NEXT: [[VPADDL_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uaddlp.v4i16.v8i8(<8 x i8> [[A]]) +// LLVM-NEXT: ret <4 x i16> [[VPADDL_I]] +// +uint16x4_t test_vpaddl_u8(uint8x8_t a) { + return vpaddl_u8(a); +} + +// CIR-LLVM-LABEL: define dso_local <8 x i16> @test_vpaddlq_u8( +// CIR-LLVM-SAME: <16 x i8> noundef [[TMP0:%.*]]) #[[ATTR0]] { +// CIR-LLVM-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.aarch64.neon.uaddlp.v8i16.v16i8(<16 x i8> [[TMP0]]) +// CIR-LLVM-NEXT: ret <8 x i16> [[TMP2]] +// +// LLVM-LABEL: define dso_local <8 x i16> @test_vpaddlq_u8( +// LLVM-SAME: <16 x i8> noundef [[A:%.*]]) #[[ATTR0]] { +// LLVM-NEXT: [[ENTRY:.*:]] +// LLVM-NEXT: [[VPADDL_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.uaddlp.v8i16.v16i8(<16 x i8> [[A]]) +// LLVM-NEXT: ret <8 x i16> [[VPADDL_I]] +// +uint16x8_t test_vpaddlq_u8(uint8x16_t a) { + return vpaddlq_u8(a); +} + +// CIR-LLVM-LABEL: define dso_local <2 x i32> @test_vpaddl_u16( +// CIR-LLVM-SAME: <4 x i16> noundef [[TMP0:%.*]]) #[[ATTR0]] { +// CIR-LLVM-NEXT: [[TMP2:%.*]] = alloca <4 x i16>, i64 1, align 8 +// CIR-LLVM-NEXT: store <4 x i16> [[TMP0]], ptr [[TMP2]], align 8 +// CIR-LLVM-NEXT: [[TMP3:%.*]] = load <8 x i8>, ptr [[TMP2]], align 8 +// CIR-LLVM-NEXT: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <4 x i16> +// CIR-LLVM-NEXT: [[TMP5:%.*]] = call <2 x i32> @llvm.aarch64.neon.uaddlp.v2i32.v4i16(<4 x i16> [[TMP4]]) +// CIR-LLVM-NEXT: ret <2 x i32> [[TMP5]] +// +// LLVM-LABEL: define dso_local <2 x i32> @test_vpaddl_u16( +// LLVM-SAME: <4 x i16> noundef [[A:%.*]]) #[[ATTR0]] { +// LLVM-NEXT: [[ENTRY:.*:]] +// LLVM-NEXT: [[__P0_ADDR_I:%.*]] = alloca <4 x i16>, align 8 +// LLVM-NEXT: store <4 x i16> [[A]], ptr [[__P0_ADDR_I]], align 8 +// LLVM-NEXT: [[TMP0:%.*]] = load <8 x i8>, ptr [[__P0_ADDR_I]], align 8 +// LLVM-NEXT: [[VPADDL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16> +// LLVM-NEXT: [[VPADDL1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uaddlp.v2i32.v4i16(<4 x i16> [[VPADDL_I]]) +// LLVM-NEXT: ret <2 x i32> [[VPADDL1_I]] +// +uint32x2_t test_vpaddl_u16(uint16x4_t a) { + return vpaddl_u16(a); +} + +// CIR-LLVM-LABEL: define dso_local <4 x i32> @test_vpaddlq_u16( +// CIR-LLVM-SAME: <8 x i16> noundef [[TMP0:%.*]]) #[[ATTR0]] { +// CIR-LLVM-NEXT: [[TMP2:%.*]] = alloca <8 x i16>, i64 1, align 16 +// CIR-LLVM-NEXT: store <8 x i16> [[TMP0]], ptr [[TMP2]], align 16 +// CIR-LLVM-NEXT: [[TMP3:%.*]] = load <16 x i8>, ptr [[TMP2]], align 16 +// CIR-LLVM-NEXT: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP3]] to <8 x i16> +// CIR-LLVM-NEXT: [[TMP5:%.*]] = call <4 x i32> @llvm.aarch64.neon.uaddlp.v4i32.v8i16(<8 x i16> [[TMP4]]) +// CIR-LLVM-NEXT: ret <4 x i32> [[TMP5]] +// +// LLVM-LABEL: define dso_local <4 x i32> @test_vpaddlq_u16( +// LLVM-SAME: <8 x i16> noundef [[A:%.*]]) #[[ATTR0]] { +// LLVM-NEXT: [[ENTRY:.*:]] +// LLVM-NEXT: [[__P0_ADDR_I:%.*]] = alloca <8 x i16>, align 16 +// LLVM-NEXT: store <8 x i16> [[A]], ptr [[__P0_ADDR_I]], align 16 +// LLVM-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[__P0_ADDR_I]], align 16 +// LLVM-NEXT: [[VPADDL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16> +// LLVM-NEXT: [[VPADDL1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.uaddlp.v4i32.v8i16(<8 x i16> [[VPADDL_I]]) +// LLVM-NEXT: ret <4 x i32> [[VPADDL1_I]] +// +uint32x4_t test_vpaddlq_u16(uint16x8_t a) { + return vpaddlq_u16(a); +} + +// CIR-LLVM-LABEL: define dso_local <1 x i64> @test_vpaddl_u32( +// CIR-LLVM-SAME: <2 x i32> noundef [[TMP0:%.*]]) #[[ATTR0]] { +// CIR-LLVM-NEXT: [[TMP2:%.*]] = alloca <2 x i32>, i64 1, align 8 +// CIR-LLVM-NEXT: store <2 x i32> [[TMP0]], ptr [[TMP2]], align 8 +// CIR-LLVM-NEXT: [[TMP3:%.*]] = load <8 x i8>, ptr [[TMP2]], align 8 +// CIR-LLVM-NEXT: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <2 x i32> +// CIR-LLVM-NEXT: [[TMP5:%.*]] = call <1 x i64> @llvm.aarch64.neon.uaddlp.v1i64.v2i32(<2 x i32> [[TMP4]]) +// CIR-LLVM-NEXT: ret <1 x i64> [[TMP5]] +// +// LLVM-LABEL: define dso_local <1 x i64> @test_vpaddl_u32( +// LLVM-SAME: <2 x i32> noundef [[A:%.*]]) #[[ATTR0]] { +// LLVM-NEXT: [[ENTRY:.*:]] +// LLVM-NEXT: [[__P0_ADDR_I:%.*]] = alloca <2 x i32>, align 8 +// LLVM-NEXT: store <2 x i32> [[A]], ptr [[__P0_ADDR_I]], align 8 +// LLVM-NEXT: [[TMP0:%.*]] = load <8 x i8>, ptr [[__P0_ADDR_I]], align 8 +// LLVM-NEXT: [[VPADDL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32> +// LLVM-NEXT: [[VPADDL1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.uaddlp.v1i64.v2i32(<2 x i32> [[VPADDL_I]]) +// LLVM-NEXT: ret <1 x i64> [[VPADDL1_I]] +// +uint64x1_t test_vpaddl_u32(uint32x2_t a) { + return vpaddl_u32(a); +} + +// CIR-LLVM-LABEL: define dso_local <2 x i64> @test_vpaddlq_u32( +// CIR-LLVM-SAME: <4 x i32> noundef [[TMP0:%.*]]) #[[ATTR0]] { +// CIR-LLVM-NEXT: [[TMP2:%.*]] = alloca <4 x i32>, i64 1, align 16 +// CIR-LLVM-NEXT: store <4 x i32> [[TMP0]], ptr [[TMP2]], align 16 +// CIR-LLVM-NEXT: [[TMP3:%.*]] = load <16 x i8>, ptr [[TMP2]], align 16 +// CIR-LLVM-NEXT: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP3]] to <4 x i32> +// CIR-LLVM-NEXT: [[TMP5:%.*]] = call <2 x i64> @llvm.aarch64.neon.uaddlp.v2i64.v4i32(<4 x i32> [[TMP4]]) +// CIR-LLVM-NEXT: ret <2 x i64> [[TMP5]] +// +// LLVM-LABEL: define dso_local <2 x i64> @test_vpaddlq_u32( +// LLVM-SAME: <4 x i32> noundef [[A:%.*]]) #[[ATTR0]] { +// LLVM-NEXT: [[ENTRY:.*:]] +// LLVM-NEXT: [[__P0_ADDR_I:%.*]] = alloca <4 x i32>, align 16 +// LLVM-NEXT: store <4 x i32> [[A]], ptr [[__P0_ADDR_I]], align 16 +// LLVM-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[__P0_ADDR_I]], align 16 +// LLVM-NEXT: [[VPADDL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32> +// LLVM-NEXT: [[VPADDL1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.uaddlp.v2i64.v4i32(<4 x i32> [[VPADDL_I]]) +// LLVM-NEXT: ret <2 x i64> [[VPADDL1_I]] +// +uint64x2_t test_vpaddlq_u32(uint32x4_t a) { + return vpaddlq_u32(a); +} \ No newline at end of file _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
