https://github.com/xiongzile updated https://github.com/llvm/llvm-project/pull/191845
>From 07ef59ce3f0c6ef0b0b5d62a9d1efa7b4ccf25ce 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-misc.c | 136 --------------- clang/test/CodeGen/AArch64/neon/vpaddl.c | 155 ++++++++++++++++++ 3 files changed, 197 insertions(+), 137 deletions(-) create mode 100644 clang/test/CodeGen/AArch64/neon/vpaddl.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-misc.c b/clang/test/CodeGen/AArch64/neon-misc.c index ac2c83aa03ccf..9b49774dc60e7 100644 --- a/clang/test/CodeGen/AArch64/neon-misc.c +++ b/clang/test/CodeGen/AArch64/neon-misc.c @@ -995,142 +995,6 @@ float32x4_t test_vrev64q_f32(float32x4_t a) { return vrev64q_f32(a); } -// CHECK-LABEL: define dso_local <4 x i16> @test_vpaddl_s8( -// CHECK-SAME: <8 x i8> noundef [[A:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[VPADDL_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.saddlp.v4i16.v8i8(<8 x i8> [[A]]) -// CHECK-NEXT: ret <4 x i16> [[VPADDL_I]] -// -int16x4_t test_vpaddl_s8(int8x8_t a) { - return vpaddl_s8(a); -} - -// CHECK-LABEL: define dso_local <2 x i32> @test_vpaddl_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: [[VPADDL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16> -// CHECK-NEXT: [[VPADDL1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.saddlp.v2i32.v4i16(<4 x i16> [[VPADDL_I]]) -// CHECK-NEXT: ret <2 x i32> [[VPADDL1_I]] -// -int32x2_t test_vpaddl_s16(int16x4_t a) { - return vpaddl_s16(a); -} - -// CHECK-LABEL: define dso_local <1 x i64> @test_vpaddl_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: [[VPADDL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32> -// CHECK-NEXT: [[VPADDL1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.saddlp.v1i64.v2i32(<2 x i32> [[VPADDL_I]]) -// CHECK-NEXT: ret <1 x i64> [[VPADDL1_I]] -// -int64x1_t test_vpaddl_s32(int32x2_t a) { - return vpaddl_s32(a); -} - -// CHECK-LABEL: define dso_local <4 x i16> @test_vpaddl_u8( -// CHECK-SAME: <8 x i8> noundef [[A:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[VPADDL_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uaddlp.v4i16.v8i8(<8 x i8> [[A]]) -// CHECK-NEXT: ret <4 x i16> [[VPADDL_I]] -// -uint16x4_t test_vpaddl_u8(uint8x8_t a) { - return vpaddl_u8(a); -} - -// CHECK-LABEL: define dso_local <2 x i32> @test_vpaddl_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: [[VPADDL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16> -// CHECK-NEXT: [[VPADDL1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uaddlp.v2i32.v4i16(<4 x i16> [[VPADDL_I]]) -// CHECK-NEXT: ret <2 x i32> [[VPADDL1_I]] -// -uint32x2_t test_vpaddl_u16(uint16x4_t a) { - return vpaddl_u16(a); -} - -// CHECK-LABEL: define dso_local <1 x i64> @test_vpaddl_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: [[VPADDL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32> -// CHECK-NEXT: [[VPADDL1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.uaddlp.v1i64.v2i32(<2 x i32> [[VPADDL_I]]) -// CHECK-NEXT: ret <1 x i64> [[VPADDL1_I]] -// -uint64x1_t test_vpaddl_u32(uint32x2_t a) { - return vpaddl_u32(a); -} - -// CHECK-LABEL: define dso_local <8 x i16> @test_vpaddlq_s8( -// CHECK-SAME: <16 x i8> noundef [[A:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[VPADDL_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.saddlp.v8i16.v16i8(<16 x i8> [[A]]) -// CHECK-NEXT: ret <8 x i16> [[VPADDL_I]] -// -int16x8_t test_vpaddlq_s8(int8x16_t a) { - return vpaddlq_s8(a); -} - -// CHECK-LABEL: define dso_local <4 x i32> @test_vpaddlq_s16( -// CHECK-SAME: <8 x i16> noundef [[A:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x i16> [[A]] to <16 x i8> -// CHECK-NEXT: [[VPADDL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16> -// CHECK-NEXT: [[VPADDL1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.saddlp.v4i32.v8i16(<8 x i16> [[VPADDL_I]]) -// CHECK-NEXT: ret <4 x i32> [[VPADDL1_I]] -// -int32x4_t test_vpaddlq_s16(int16x8_t a) { - return vpaddlq_s16(a); -} - -// CHECK-LABEL: define dso_local <2 x i64> @test_vpaddlq_s32( -// CHECK-SAME: <4 x i32> noundef [[A:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A]] to <16 x i8> -// CHECK-NEXT: [[VPADDL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32> -// CHECK-NEXT: [[VPADDL1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.saddlp.v2i64.v4i32(<4 x i32> [[VPADDL_I]]) -// CHECK-NEXT: ret <2 x i64> [[VPADDL1_I]] -// -int64x2_t test_vpaddlq_s32(int32x4_t a) { - return vpaddlq_s32(a); -} - -// CHECK-LABEL: define dso_local <8 x i16> @test_vpaddlq_u8( -// CHECK-SAME: <16 x i8> noundef [[A:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[VPADDL_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.uaddlp.v8i16.v16i8(<16 x i8> [[A]]) -// CHECK-NEXT: ret <8 x i16> [[VPADDL_I]] -// -uint16x8_t test_vpaddlq_u8(uint8x16_t a) { - return vpaddlq_u8(a); -} - -// CHECK-LABEL: define dso_local <4 x i32> @test_vpaddlq_u16( -// CHECK-SAME: <8 x i16> noundef [[A:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x i16> [[A]] to <16 x i8> -// CHECK-NEXT: [[VPADDL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16> -// CHECK-NEXT: [[VPADDL1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.uaddlp.v4i32.v8i16(<8 x i16> [[VPADDL_I]]) -// CHECK-NEXT: ret <4 x i32> [[VPADDL1_I]] -// -uint32x4_t test_vpaddlq_u16(uint16x8_t a) { - return vpaddlq_u16(a); -} - -// CHECK-LABEL: define dso_local <2 x i64> @test_vpaddlq_u32( -// CHECK-SAME: <4 x i32> noundef [[A:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A]] to <16 x i8> -// CHECK-NEXT: [[VPADDL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32> -// CHECK-NEXT: [[VPADDL1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.uaddlp.v2i64.v4i32(<4 x i32> [[VPADDL_I]]) -// CHECK-NEXT: ret <2 x i64> [[VPADDL1_I]] -// -uint64x2_t test_vpaddlq_u32(uint32x4_t a) { - return vpaddlq_u32(a); -} - // CHECK-LABEL: define dso_local <4 x i16> @test_vpadal_s8( // CHECK-SAME: <4 x i16> noundef [[A:%.*]], <8 x i8> noundef [[B:%.*]]) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] diff --git a/clang/test/CodeGen/AArch64/neon/vpaddl.c b/clang/test/CodeGen/AArch64/neon/vpaddl.c new file mode 100644 index 0000000000000..f307c88c6ef5c --- /dev/null +++ b/clang/test/CodeGen/AArch64/neon/vpaddl.c @@ -0,0 +1,155 @@ +// REQUIRES: aarch64-registered-target || arm-registered-target + +// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -disable-O0-optnone -flax-vector-conversions=none -emit-llvm -o - %s | opt -S -passes=mem2reg,sroa | FileCheck %s --check-prefixes=LLVM +// RUN: %if cir-enabled %{%clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -disable-O0-optnone -flax-vector-conversions=none -fclangir -emit-llvm -o - %s | opt -S -passes=mem2reg,sroa | FileCheck %s --check-prefixes=LLVM %} +// RUN: %if cir-enabled %{%clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -disable-O0-optnone -flax-vector-conversions=none -fclangir -emit-cir -o - %s | FileCheck %s --check-prefixes=CIR %} + +#include <arm_neon.h> + +// LLVM-LABEL: @test_vpaddl_s8( +// CIR-LABEL: @vpaddl_s8( +int16x4_t test_vpaddl_s8(int8x8_t a) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.saddlp" %{{.*}} : (!cir.vector<8 x !s8i>) -> !cir.vector<4 x !s16i> + +// LLVM-SAME: <8 x i8> {{.*}} [[A:%.*]]) #[[ATTR0:[0-9]+]] { +// LLVM: [[VPADDL_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.saddlp.v4i16.v8i8(<8 x i8> [[A]]) +// LLVM-NEXT: ret <4 x i16> [[VPADDL_I]] + return vpaddl_s8(a); +} + +// LLVM-LABEL: @test_vpaddlq_s8( +// CIR-LABEL: @vpaddlq_s8( +int16x8_t test_vpaddlq_s8(int8x16_t a) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.saddlp" %{{.*}} : (!cir.vector<16 x !s8i>) -> !cir.vector<8 x !s16i> + +// LLVM-SAME: <16 x i8> {{.*}} [[A:%.*]]) #[[ATTR0]] { +// LLVM: [[VPADDL_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.saddlp.v8i16.v16i8(<16 x i8> [[A]]) +// LLVM-NEXT: ret <8 x i16> [[VPADDL_I]] + return vpaddlq_s8(a); +} + +// LLVM-LABEL: @test_vpaddl_s16( +// CIR-LABEL: @vpaddl_s16( +int32x2_t test_vpaddl_s16(int16x4_t a) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.saddlp" %{{.*}} : (!cir.vector<4 x !s16i>) -> !cir.vector<2 x !s32i> + +// LLVM-SAME: <4 x i16> {{.*}} [[A:%.*]]) #[[ATTR0]] { +// LLVM: [[TMP0:%.*]] = bitcast <4 x i16> [[A]] to <8 x i8> +// 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]] + return vpaddl_s16(a); +} + +// LLVM-LABEL: @test_vpaddlq_s16( +// CIR-LABEL: @vpaddlq_s16( +int32x4_t test_vpaddlq_s16(int16x8_t a) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.saddlp" %{{.*}} : (!cir.vector<8 x !s16i>) -> !cir.vector<4 x !s32i> + +// LLVM-SAME: <8 x i16> {{.*}} [[A:%.*]]) #[[ATTR0]] { +// LLVM: [[TMP0:%.*]] = bitcast <8 x i16> [[A]] to <16 x i8> +// 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]] + return vpaddlq_s16(a); +} + +// LLVM-LABEL: @test_vpaddl_s32( +// CIR-LABEL: @vpaddl_s32( +int64x1_t test_vpaddl_s32(int32x2_t a) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.saddlp" %{{.*}} : (!cir.vector<2 x !s32i>) -> !cir.vector<1 x !s64i> + +// LLVM-SAME: <2 x i32> {{.*}} [[A:%.*]]) #[[ATTR0]] { +// LLVM: [[TMP0:%.*]] = bitcast <2 x i32> [[A]] to <8 x i8> +// 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]] + return vpaddl_s32(a); +} + +// LLVM-LABEL: @test_vpaddlq_s32( +// CIR-LABEL: @vpaddlq_s32( +int64x2_t test_vpaddlq_s32(int32x4_t a) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.saddlp" %{{.*}} : (!cir.vector<4 x !s32i>) -> !cir.vector<2 x !s64i> + +// LLVM-SAME: <4 x i32> {{.*}} [[A:%.*]]) #[[ATTR0]] { +// LLVM: [[TMP0:%.*]] = bitcast <4 x i32> [[A]] to <16 x i8> +// 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]] + return vpaddlq_s32(a); +} + +// LLVM-LABEL: @test_vpaddl_u8( +// CIR-LABEL: @vpaddl_u8( +uint16x4_t test_vpaddl_u8(uint8x8_t a) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.uaddlp" %{{.*}} : (!cir.vector<8 x !u8i>) -> !cir.vector<4 x !u16i> + +// LLVM-SAME: <8 x i8> {{.*}} [[A:%.*]]) #[[ATTR0]] { +// LLVM: [[VPADDL_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uaddlp.v4i16.v8i8(<8 x i8> [[A]]) +// LLVM-NEXT: ret <4 x i16> [[VPADDL_I]] + return vpaddl_u8(a); +} + +// LLVM-LABEL: @test_vpaddlq_u8( +// CIR-LABEL: @vpaddlq_u8( +uint16x8_t test_vpaddlq_u8(uint8x16_t a) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.uaddlp" %{{.*}} : (!cir.vector<16 x !u8i>) -> !cir.vector<8 x !u16i> + +// LLVM-SAME: <16 x i8> {{.*}} [[A:%.*]]) #[[ATTR0]] { +// LLVM: [[VPADDL_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.uaddlp.v8i16.v16i8(<16 x i8> [[A]]) +// LLVM-NEXT: ret <8 x i16> [[VPADDL_I]] + return vpaddlq_u8(a); +} + +// LLVM-LABEL: @test_vpaddl_u16( +// CIR-LABEL: @vpaddl_u16( +uint32x2_t test_vpaddl_u16(uint16x4_t a) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.uaddlp" %{{.*}} : (!cir.vector<4 x !u16i>) -> !cir.vector<2 x !u32i> + +// LLVM-SAME: <4 x i16> {{.*}} [[A:%.*]]) #[[ATTR0]] { +// LLVM: [[TMP0:%.*]] = bitcast <4 x i16> [[A]] to <8 x i8> +// 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]] + return vpaddl_u16(a); +} + +// LLVM-LABEL: @test_vpaddlq_u16( +// CIR-LABEL: @vpaddlq_u16( +uint32x4_t test_vpaddlq_u16(uint16x8_t a) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.uaddlp" %{{.*}} : (!cir.vector<8 x !u16i>) -> !cir.vector<4 x !u32i> + +// LLVM-SAME: <8 x i16> {{.*}} [[A:%.*]]) #[[ATTR0]] { +// LLVM: [[TMP0:%.*]] = bitcast <8 x i16> [[A]] to <16 x i8> +// 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]] + return vpaddlq_u16(a); +} + +// LLVM-LABEL: @test_vpaddl_u32( +// CIR-LABEL: @vpaddl_u32( +uint64x1_t test_vpaddl_u32(uint32x2_t a) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.uaddlp" %{{.*}} : (!cir.vector<2 x !u32i>) -> !cir.vector<1 x !u64i> + +// LLVM-SAME: <2 x i32> {{.*}} [[A:%.*]]) #[[ATTR0]] { +// LLVM: [[TMP0:%.*]] = bitcast <2 x i32> [[A]] to <8 x i8> +// 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]] + return vpaddl_u32(a); +} + +// LLVM-LABEL: @test_vpaddlq_u32( +// CIR-LABEL: @vpaddlq_u32( +uint64x2_t test_vpaddlq_u32(uint32x4_t a) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.uaddlp" %{{.*}} : (!cir.vector<4 x !u32i>) -> !cir.vector<2 x !u64i> + +// LLVM-SAME: <4 x i32> {{.*}} [[A:%.*]]) #[[ATTR0]] { +// LLVM: [[TMP0:%.*]] = bitcast <4 x i32> [[A]] to <16 x i8> +// 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]] + 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
