https://github.com/banach-space created https://github.com/llvm/llvm-project/pull/217263
This PR adds lowering for intrinsic from the following groups: * https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#conversions It continues the work started in #190961, #193273, #199990, #209252, , #211609, #216757 and #217017. This PR implements the conversions for the following: 1) "int to float" intrinsics: * vcvt_f32_s32 * vcvtq_f32_s32 * vcvt_f32_u32 * vcvtq_f32_u32 * vcvts_f32_s32 * vcvts_f32_u32 * vcvt_f64_s64 * vcvtq_f64_s64 * vcvt_f64_u64 * vcvtq_f64_u64 * vcvtd_f64_s64 * vcvtd_f64_u64 2) "float width conversion" intrnsics: * vcvt_f16_f32 * vcvt_high_f16_f32 * vcvt_f32_f64 * vcvt_high_f32_f64 * vcvt_f32_f16 * vcvt_high_f32_f16 * vcvt_f64_f32 * vcvt_high_f64_f32 * vcvtx_f32_f64 * vcvtxd_f32_f64 * vcvtx_high_f32_f64 The corresponding tests are moved from: * clang/test/CodeGen/AArch64/ to: * clang/test/CodeGen/AArch64/neon/ The lowering follows the existing implementation in CodeGen/TargetBuiltins/ARM.cpp. From 37f338eebbeaf2bd685164dc508131d95a95a98c Mon Sep 17 00:00:00 2001 From: Andrzej Warzynski <[email protected]> Date: Wed, 19 Aug 2026 10:04:55 +0000 Subject: [PATCH] [clang][CIR][AArch64] Add lowering for conversion intrinsics This PR adds lowering for intrinsic from the following groups: * https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#conversions It continues the work started in #190961, #193273, #199990, #209252, , #211609, #216757 and #217017. This PR implements the conversions for the following: 1) "int to float" intrinsics: * vcvt_f32_s32 * vcvtq_f32_s32 * vcvt_f32_u32 * vcvtq_f32_u32 * vcvts_f32_s32 * vcvts_f32_u32 * vcvt_f64_s64 * vcvtq_f64_s64 * vcvt_f64_u64 * vcvtq_f64_u64 * vcvtd_f64_s64 * vcvtd_f64_u64 2) "float width conversion" intrnsics: * vcvt_f16_f32 * vcvt_high_f16_f32 * vcvt_f32_f64 * vcvt_high_f32_f64 * vcvt_f32_f16 * vcvt_high_f32_f16 * vcvt_f64_f32 * vcvt_high_f64_f32 * vcvtx_f32_f64 * vcvtxd_f32_f64 * vcvtx_high_f32_f64 The corresponding tests are moved from: * clang/test/CodeGen/AArch64/ to: * clang/test/CodeGen/AArch64/neon/ The lowering follows the existing implementation in CodeGen/TargetBuiltins/ARM.cpp. --- .../lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp | 64 +++- .../CodeGen/AArch64/neon-fcvt-intrinsics.c | 17 - clang/test/CodeGen/AArch64/neon-intrinsics.c | 64 ---- clang/test/CodeGen/AArch64/neon-misc.c | 194 ----------- clang/test/CodeGen/AArch64/neon/intrinsics.c | 317 ++++++++++++++++++ 5 files changed, 374 insertions(+), 282 deletions(-) delete mode 100644 clang/test/CodeGen/AArch64/neon-fcvt-intrinsics.c diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp index f2bc4141f433e..47237d57b2760 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp @@ -483,6 +483,7 @@ emitCommonNeonSISDBuiltinExpr(CIRGenFunction &cgf, case NEON::BI__builtin_neon_vcvtad_u32_f64: case NEON::BI__builtin_neon_vcvtad_s64_f64: case NEON::BI__builtin_neon_vcvtad_u64_f64: + case NEON::BI__builtin_neon_vcvtxd_f32_f64: case NEON::BI__builtin_neon_vaddlv_s32: case NEON::BI__builtin_neon_vaddlv_u32: case NEON::BI__builtin_neon_vaddlvq_s32: @@ -789,6 +790,7 @@ static mlir::Value emitCommonNeonBuiltinExpr( const bool isUnsigned = neonType.isUnsigned(); const bool hasLegalHalfType = cgf.getTarget().hasFastHalfType(); const bool usgn = neonType.isUnsigned(); + const bool isQuad = neonType.isQuad(); // The value of allowBFloatArgsAndRet is true for AArch64, but it should // come from ABI info. @@ -908,8 +910,17 @@ static mlir::Value emitCommonNeonBuiltinExpr( case NEON::BI__builtin_neon_vcltzq_v: case NEON::BI__builtin_neon_vclz_v: case NEON::BI__builtin_neon_vclzq_v: + cgf.cgm.errorNYI(expr->getSourceRange(), + std::string("unimplemented AArch64 builtin call: ") + + ctx.BuiltinInfo.getName(builtinID)); + return mlir::Value{}; case NEON::BI__builtin_neon_vcvt_f32_v: - case NEON::BI__builtin_neon_vcvtq_f32_v: + case NEON::BI__builtin_neon_vcvtq_f32_v: { + ops[0] = cgf.getBuilder().createBitcast(ops[0], ty); + ty = getNeonType(&cgf, NeonTypeFlags(NeonTypeFlags::Float32, false, isQuad), + hasLegalHalfType); + return cgf.getBuilder().createCast(cir::CastKind::int_to_float, ops[0], ty); + } case NEON::BI__builtin_neon_vcvt_f16_s16: case NEON::BI__builtin_neon_vcvt_f16_u16: case NEON::BI__builtin_neon_vcvtq_f16_s16: @@ -1030,7 +1041,19 @@ static mlir::Value emitCommonNeonBuiltinExpr( case NEON::BI__builtin_neon_vcvtmq_u16_f16: case NEON::BI__builtin_neon_vcvtmq_u32_v: case NEON::BI__builtin_neon_vcvtmq_u64_v: - case NEON::BI__builtin_neon_vcvtx_f32_v: + cgf.cgm.errorNYI(expr->getSourceRange(), + std::string("unimplemented AArch64 builtin call: ") + + ctx.BuiltinInfo.getName(builtinID)); + return mlir::Value{}; + case NEON::BI__builtin_neon_vcvtx_f32_v: { + llvm::StringRef llvmIntrName = getLLVMIntrNameNoPrefix( + static_cast<llvm::Intrinsic::ID>(llvmIntrinsic)); + auto v2f64 = cir::VectorType::get(cgf.cgm.doubleTy, 2); + auto v2f32 = cir::VectorType::get(cgf.cgm.floatTy, 2); + return emitNeonCall(cgf.getCIRGenModule(), cgf.getBuilder(), + /*argTypes=*/{v2f64}, ops, llvmIntrName, + /*funcResTy=*/v2f32, loc); + } case NEON::BI__builtin_neon_vext_v: case NEON::BI__builtin_neon_vextq_v: cgf.cgm.errorNYI(expr->getSourceRange(), @@ -2628,7 +2651,10 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, case NEON::BI__builtin_neon_vcvts_f32_u32: case NEON::BI__builtin_neon_vcvtd_f64_u64: case NEON::BI__builtin_neon_vcvts_f32_s32: - case NEON::BI__builtin_neon_vcvtd_f64_s64: + case NEON::BI__builtin_neon_vcvtd_f64_s64: { + return builder.createCast(loc, cir::CastKind::int_to_float, ops[0], + convertType(expr->getType())); + } case NEON::BI__builtin_neon_vcvth_f16_u16: case NEON::BI__builtin_neon_vcvth_f16_u32: case NEON::BI__builtin_neon_vcvth_f16_u64: @@ -2934,8 +2960,22 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, case NEON::BI__builtin_neon_vcvt_bf16_f32: case NEON::BI__builtin_neon_vcvtq_low_bf16_f32: case NEON::BI__builtin_neon_vcvtq_high_bf16_f32: - case NEON::BI__builtin_neon_vcvt_f16_f32: - case NEON::BI__builtin_neon_vcvt_f32_f16: + cgm.errorNYI(expr->getSourceRange(), + std::string("unimplemented AArch64 builtin call: ") + + getContext().BuiltinInfo.getName(builtinID)); + return mlir::Value{}; + case NEON::BI__builtin_neon_vcvt_f16_f32: { + auto v4f32 = cir::VectorType::get(cgm.floatTy, 4); + auto v4f16 = cir::VectorType::get(cgm.fP16Ty, 4); + return builder.createFloatingCast(builder.createBitcast(ops[0], v4f32), + v4f16); + } + case NEON::BI__builtin_neon_vcvt_f32_f16: { + auto v4f32 = cir::VectorType::get(cgm.floatTy, 4); + auto v4f16 = cir::VectorType::get(cgm.fP16Ty, 4); + return builder.createFloatingCast(builder.createBitcast(ops[0], v4f16), + v4f32); + } case clang::AArch64::BI_InterlockedAdd: case clang::AArch64::BI_InterlockedAdd_acq: case clang::AArch64::BI_InterlockedAdd_rel: @@ -3259,8 +3299,18 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, ty = getNeonType( this, NeonTypeFlags(NeonTypeFlags::Float64, false, type.isQuad())); return builder.createCast(loc, cir::CastKind::int_to_float, ops[0], ty); - case NEON::BI__builtin_neon_vcvt_f64_f32: - case NEON::BI__builtin_neon_vcvt_f32_f64: + case NEON::BI__builtin_neon_vcvt_f64_f32: { + auto v2f32 = cir::VectorType::get(cgm.floatTy, 2); + auto v2f64 = cir::VectorType::get(cgm.doubleTy, 2); + return builder.createFloatingCast(builder.createBitcast(ops[0], v2f32), + v2f64); + } + case NEON::BI__builtin_neon_vcvt_f32_f64: { + auto v2f32 = cir::VectorType::get(cgm.floatTy, 2); + auto v2f64 = cir::VectorType::get(cgm.doubleTy, 2); + return builder.createFloatingCast(builder.createBitcast(ops[0], v2f64), + v2f32); + } case NEON::BI__builtin_neon_vcvt_s32_v: case NEON::BI__builtin_neon_vcvt_u32_v: case NEON::BI__builtin_neon_vcvt_s64_v: diff --git a/clang/test/CodeGen/AArch64/neon-fcvt-intrinsics.c b/clang/test/CodeGen/AArch64/neon-fcvt-intrinsics.c deleted file mode 100644 index f460065112444..0000000000000 --- a/clang/test/CodeGen/AArch64/neon-fcvt-intrinsics.c +++ /dev/null @@ -1,17 +0,0 @@ -// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature -// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon \ -// RUN: -disable-O0-optnone -emit-llvm -o - %s | opt -S -passes=mem2reg | FileCheck %s - -// REQUIRES: aarch64-registered-target || arm-registered-target - -#include <arm_neon.h> - -// CHECK-LABEL: define {{[^@]+}}@test_vcvtxd_f32_f64 -// CHECK-SAME: (double noundef [[A:%.*]]) #[[ATTR0:[0-9]+]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: [[VCVTXD_F32_F64_I:%.*]] = call float @llvm.aarch64.sisd.fcvtxn(double [[A]]) -// CHECK-NEXT: ret float [[VCVTXD_F32_F64_I]] -// -float32_t test_vcvtxd_f32_f64(float64_t a) { - return (float32_t)vcvtxd_f32_f64(a); -} diff --git a/clang/test/CodeGen/AArch64/neon-intrinsics.c b/clang/test/CodeGen/AArch64/neon-intrinsics.c index 79cb1c42cd5af..8515754922834 100644 --- a/clang/test/CodeGen/AArch64/neon-intrinsics.c +++ b/clang/test/CodeGen/AArch64/neon-intrinsics.c @@ -5264,46 +5264,6 @@ float64_t test_vrsqrtsd_f64(float64_t a, float64_t b) { return vrsqrtsd_f64(a, b); } -// CHECK-LABEL: define dso_local float @test_vcvts_f32_s32( -// CHECK-SAME: i32 noundef [[A:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = sitofp i32 [[A]] to float -// CHECK-NEXT: ret float [[TMP0]] -// -float32_t test_vcvts_f32_s32(int32_t a) { - return vcvts_f32_s32(a); -} - -// CHECK-LABEL: define dso_local double @test_vcvtd_f64_s64( -// CHECK-SAME: i64 noundef [[A:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = sitofp i64 [[A]] to double -// CHECK-NEXT: ret double [[TMP0]] -// -float64_t test_vcvtd_f64_s64(int64_t a) { - return vcvtd_f64_s64(a); -} - -// CHECK-LABEL: define dso_local float @test_vcvts_f32_u32( -// CHECK-SAME: i32 noundef [[A:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = uitofp i32 [[A]] to float -// CHECK-NEXT: ret float [[TMP0]] -// -float32_t test_vcvts_f32_u32(uint32_t a) { - return vcvts_f32_u32(a); -} - -// CHECK-LABEL: define dso_local double @test_vcvtd_f64_u64( -// CHECK-SAME: i64 noundef [[A:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = uitofp i64 [[A]] to double -// CHECK-NEXT: ret double [[TMP0]] -// -float64_t test_vcvtd_f64_u64(uint64_t a) { - return vcvtd_f64_u64(a); -} - // CHECK-LABEL: define dso_local float @test_vrecpes_f32( // CHECK-SAME: float noundef [[A:%.*]]) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] @@ -12440,30 +12400,6 @@ float64x1_t test_vneg_f64(float64x1_t a) { return vneg_f64(a); } -// CHECK-LABEL: define dso_local <1 x double> @test_vcvt_f64_s64( -// CHECK-SAME: <1 x i64> noundef [[A:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <1 x i64> [[A]] to <8 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64> -// CHECK-NEXT: [[VCVT_I:%.*]] = sitofp <1 x i64> [[TMP1]] to <1 x double> -// CHECK-NEXT: ret <1 x double> [[VCVT_I]] -// -float64x1_t test_vcvt_f64_s64(int64x1_t a) { - return vcvt_f64_s64(a); -} - -// CHECK-LABEL: define dso_local <1 x double> @test_vcvt_f64_u64( -// CHECK-SAME: <1 x i64> noundef [[A:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <1 x i64> [[A]] to <8 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64> -// CHECK-NEXT: [[VCVT_I:%.*]] = uitofp <1 x i64> [[TMP1]] to <1 x double> -// CHECK-NEXT: ret <1 x double> [[VCVT_I]] -// -float64x1_t test_vcvt_f64_u64(uint64x1_t a) { - return vcvt_f64_u64(a); -} - // CHECK-LABEL: define dso_local <1 x double> @test_vrsqrte_f64( // CHECK-SAME: <1 x double> noundef [[A:%.*]]) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] diff --git a/clang/test/CodeGen/AArch64/neon-misc.c b/clang/test/CodeGen/AArch64/neon-misc.c index cfc85c7bd3c52..253c4eb7a1316 100644 --- a/clang/test/CodeGen/AArch64/neon-misc.c +++ b/clang/test/CodeGen/AArch64/neon-misc.c @@ -2614,128 +2614,6 @@ float16x4_t test_vcvt_f16_f32(float32x4_t a) { return vcvt_f16_f32(a); } -// CHECK-LABEL: define dso_local <8 x half> @test_vcvt_high_f16_f32( -// CHECK-SAME: <4 x half> noundef [[A:%.*]], <4 x float> noundef [[B:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x float> [[B]] to <4 x i32> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[TMP0]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float> -// CHECK-NEXT: [[TMP3:%.*]] = fptrunc <4 x float> [[TMP2]] to <4 x half> -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[TMP3]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> -// CHECK-NEXT: ret <8 x half> [[SHUFFLE_I]] -// -float16x8_t test_vcvt_high_f16_f32(float16x4_t a, float32x4_t b) { - return vcvt_high_f16_f32(a, b); -} - -// CHECK-LABEL: define dso_local <2 x float> @test_vcvt_f32_f64( -// CHECK-SAME: <2 x double> noundef [[A:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x double> [[A]] to <2 x i64> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i64> [[TMP0]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double> -// CHECK-NEXT: [[VCVT_I:%.*]] = fptrunc <2 x double> [[TMP2]] to <2 x float> -// CHECK-NEXT: ret <2 x float> [[VCVT_I]] -// -float32x2_t test_vcvt_f32_f64(float64x2_t a) { - return vcvt_f32_f64(a); -} - -// CHECK-LABEL: define dso_local <4 x float> @test_vcvt_high_f32_f64( -// CHECK-SAME: <2 x float> noundef [[A:%.*]], <2 x double> noundef [[B:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x double> [[B]] to <2 x i64> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i64> [[TMP0]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double> -// CHECK-NEXT: [[VCVT_I_I:%.*]] = fptrunc <2 x double> [[TMP2]] to <2 x float> -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <2 x float> [[A]], <2 x float> [[VCVT_I_I]], <4 x i32> <i32 0, i32 1, i32 2, i32 3> -// CHECK-NEXT: ret <4 x float> [[SHUFFLE_I]] -// -float32x4_t test_vcvt_high_f32_f64(float32x2_t a, float64x2_t b) { - return vcvt_high_f32_f64(a, b); -} - -// CHECK-LABEL: define dso_local <2 x float> @test_vcvtx_f32_f64( -// CHECK-SAME: <2 x double> noundef [[A:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x double> [[A]] to <2 x i64> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i64> [[TMP0]] to <16 x i8> -// CHECK-NEXT: [[VCVTX_F32_V_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double> -// CHECK-NEXT: [[VCVTX_F32_V1_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fcvtxn.v2f32.v2f64(<2 x double> [[VCVTX_F32_V_I]]) -// CHECK-NEXT: ret <2 x float> [[VCVTX_F32_V1_I]] -// -float32x2_t test_vcvtx_f32_f64(float64x2_t a) { - return vcvtx_f32_f64(a); -} - -// CHECK-LABEL: define dso_local <4 x float> @test_vcvtx_high_f32_f64( -// CHECK-SAME: <2 x float> noundef [[A:%.*]], <2 x double> noundef [[B:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x double> [[B]] to <2 x i64> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i64> [[TMP0]] to <16 x i8> -// CHECK-NEXT: [[VCVTX_F32_V_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double> -// CHECK-NEXT: [[VCVTX_F32_V1_I_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fcvtxn.v2f32.v2f64(<2 x double> [[VCVTX_F32_V_I_I]]) -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <2 x float> [[A]], <2 x float> [[VCVTX_F32_V1_I_I]], <4 x i32> <i32 0, i32 1, i32 2, i32 3> -// CHECK-NEXT: ret <4 x float> [[SHUFFLE_I]] -// -float32x4_t test_vcvtx_high_f32_f64(float32x2_t a, float64x2_t b) { - return vcvtx_high_f32_f64(a, b); -} - -// CHECK-LABEL: define dso_local <4 x float> @test_vcvt_f32_f16( -// CHECK-SAME: <4 x half> noundef [[A:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x half> [[A]] to <4 x i16> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i16> [[TMP0]] to <8 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x half> -// CHECK-NEXT: [[TMP3:%.*]] = fpext <4 x half> [[TMP2]] to <4 x float> -// CHECK-NEXT: ret <4 x float> [[TMP3]] -// -float32x4_t test_vcvt_f32_f16(float16x4_t a) { - return vcvt_f32_f16(a); -} - -// CHECK-LABEL: define dso_local <4 x float> @test_vcvt_high_f32_f16( -// CHECK-SAME: <8 x half> noundef [[A:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[A]], <4 x i32> <i32 4, i32 5, i32 6, i32 7> -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x half> [[SHUFFLE_I]] to <4 x i16> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i16> [[TMP0]] to <8 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x half> -// CHECK-NEXT: [[TMP3:%.*]] = fpext <4 x half> [[TMP2]] to <4 x float> -// CHECK-NEXT: ret <4 x float> [[TMP3]] -// -float32x4_t test_vcvt_high_f32_f16(float16x8_t a) { - return vcvt_high_f32_f16(a); -} - -// CHECK-LABEL: define dso_local <2 x double> @test_vcvt_f64_f32( -// CHECK-SAME: <2 x float> noundef [[A:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x float> [[A]] to <2 x i32> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i32> [[TMP0]] to <8 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float> -// CHECK-NEXT: [[VCVT_I:%.*]] = fpext <2 x float> [[TMP2]] to <2 x double> -// CHECK-NEXT: ret <2 x double> [[VCVT_I]] -// -float64x2_t test_vcvt_f64_f32(float32x2_t a) { - return vcvt_f64_f32(a); -} - -// CHECK-LABEL: define dso_local <2 x double> @test_vcvt_high_f64_f32( -// CHECK-SAME: <4 x float> noundef [[A:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x float> [[A]], <4 x float> [[A]], <2 x i32> <i32 2, i32 3> -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x float> [[SHUFFLE_I]] to <2 x i32> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i32> [[TMP0]] to <8 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float> -// CHECK-NEXT: [[VCVT_I_I:%.*]] = fpext <2 x float> [[TMP2]] to <2 x double> -// CHECK-NEXT: ret <2 x double> [[VCVT_I_I]] -// -float64x2_t test_vcvt_high_f64_f32(float32x4_t a) { - return vcvt_high_f64_f32(a); -} - // CHECK-LABEL: define dso_local <2 x double> @test_vrndnq_f64( // CHECK-SAME: <2 x double> noundef [[A:%.*]]) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] @@ -2928,75 +2806,3 @@ uint32x2_t test_vrecpe_u32(uint32x2_t a) { uint32x4_t test_vrecpeq_u32(uint32x4_t a) { return vrecpeq_u32(a); } - -// CHECK-LABEL: define dso_local <2 x float> @test_vcvt_f32_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: [[VCVT_I:%.*]] = sitofp <2 x i32> [[TMP1]] to <2 x float> -// CHECK-NEXT: ret <2 x float> [[VCVT_I]] -// -float32x2_t test_vcvt_f32_s32(int32x2_t a) { - return vcvt_f32_s32(a); -} - -// CHECK-LABEL: define dso_local <2 x float> @test_vcvt_f32_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: [[VCVT_I:%.*]] = uitofp <2 x i32> [[TMP1]] to <2 x float> -// CHECK-NEXT: ret <2 x float> [[VCVT_I]] -// -float32x2_t test_vcvt_f32_u32(uint32x2_t a) { - return vcvt_f32_u32(a); -} - -// CHECK-LABEL: define dso_local <4 x float> @test_vcvtq_f32_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: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32> -// CHECK-NEXT: [[VCVT_I:%.*]] = sitofp <4 x i32> [[TMP1]] to <4 x float> -// CHECK-NEXT: ret <4 x float> [[VCVT_I]] -// -float32x4_t test_vcvtq_f32_s32(int32x4_t a) { - return vcvtq_f32_s32(a); -} - -// CHECK-LABEL: define dso_local <4 x float> @test_vcvtq_f32_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: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32> -// CHECK-NEXT: [[VCVT_I:%.*]] = uitofp <4 x i32> [[TMP1]] to <4 x float> -// CHECK-NEXT: ret <4 x float> [[VCVT_I]] -// -float32x4_t test_vcvtq_f32_u32(uint32x4_t a) { - return vcvtq_f32_u32(a); -} - -// CHECK-LABEL: define dso_local <2 x double> @test_vcvtq_f64_s64( -// CHECK-SAME: <2 x i64> noundef [[A:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x i64> [[A]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64> -// CHECK-NEXT: [[VCVT_I:%.*]] = sitofp <2 x i64> [[TMP1]] to <2 x double> -// CHECK-NEXT: ret <2 x double> [[VCVT_I]] -// -float64x2_t test_vcvtq_f64_s64(int64x2_t a) { - return vcvtq_f64_s64(a); -} - -// CHECK-LABEL: define dso_local <2 x double> @test_vcvtq_f64_u64( -// CHECK-SAME: <2 x i64> noundef [[A:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x i64> [[A]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64> -// CHECK-NEXT: [[VCVT_I:%.*]] = uitofp <2 x i64> [[TMP1]] to <2 x double> -// CHECK-NEXT: ret <2 x double> [[VCVT_I]] -// -float64x2_t test_vcvtq_f64_u64(uint64x2_t a) { - return vcvtq_f64_u64(a); -} diff --git a/clang/test/CodeGen/AArch64/neon/intrinsics.c b/clang/test/CodeGen/AArch64/neon/intrinsics.c index 12b181a4ee917..ece2da21557c7 100644 --- a/clang/test/CodeGen/AArch64/neon/intrinsics.c +++ b/clang/test/CodeGen/AArch64/neon/intrinsics.c @@ -5452,6 +5452,323 @@ uint32_t test_vcvtad_u32_f64(float64_t a) { return (uint32_t)vcvtad_u32_f64(a); } +//===------------------------------------------------------===// +// 2.1.4.1 Convearions (int to float) +// https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#conversions +//===------------------------------------------------------===// +// LLVM-LABEL: @test_vcvt_f32_s32( +// CIR-LABEL: @vcvt_f32_s32( +float32x2_t test_vcvt_f32_s32(int32x2_t a) { +// CIR: cir.cast int_to_float + +// LLVM-SAME: <2 x i32> {{.*}} [[A:%.*]]) +// LLVM: [[TMP0:%.*]] = bitcast <2 x i32> [[A]] to <8 x i8> +// LLVM: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32> +// LLVM: [[VCVT_I:%.*]] = sitofp <2 x i32> [[TMP1]] to <2 x float> +// LLVM: ret <2 x float> [[VCVT_I]] + return vcvt_f32_s32(a); +} + +// LLVM-LABEL: @test_vcvtq_f32_s32( +// CIR-LABEL: @vcvtq_f32_s32( +float32x4_t test_vcvtq_f32_s32(int32x4_t a) { +// CIR: cir.cast int_to_float + +// LLVM-SAME: <4 x i32> {{.*}} [[A:%.*]]) +// LLVM: [[TMP0:%.*]] = bitcast <4 x i32> [[A]] to <16 x i8> +// LLVM: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32> +// LLVM: [[VCVT_I:%.*]] = sitofp <4 x i32> [[TMP1]] to <4 x float> +// LLVM: ret <4 x float> [[VCVT_I]] + return vcvtq_f32_s32(a); +} + +// LLVM-LABEL: @test_vcvt_f32_u32( +// CIR-LABEL: @vcvt_f32_u32( +float32x2_t test_vcvt_f32_u32(uint32x2_t a) { +// CIR: cir.cast int_to_float + +// LLVM-SAME: <2 x i32> {{.*}} [[A:%.*]]) #[[ATTR0]] { +// LLVM: [[TMP0:%.*]] = bitcast <2 x i32> [[A]] to <8 x i8> +// LLVM: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32> +// LLVM: [[VCVT_I:%.*]] = uitofp <2 x i32> [[TMP1]] to <2 x float> +// LLVM: ret <2 x float> [[VCVT_I]] + return vcvt_f32_u32(a); +} + +// LLVM-LABEL: @test_vcvtq_f32_u32( +// CIR-LABEL: @vcvtq_f32_u32( +float32x4_t test_vcvtq_f32_u32(uint32x4_t a) { +// CIR: cir.cast int_to_float + +// LLVM-SAME: <4 x i32> {{.*}} [[A:%.*]]) #[[ATTR0]] { +// LLVM: [[TMP0:%.*]] = bitcast <4 x i32> [[A]] to <16 x i8> +// LLVM: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32> +// LLVM: [[VCVT_I:%.*]] = uitofp <4 x i32> [[TMP1]] to <4 x float> +// LLVM: ret <4 x float> [[VCVT_I]] + return vcvtq_f32_u32(a); +} + +// LLVM-LABEL: @test_vcvts_f32_s32( +// CIR-LABEL: @vcvts_f32_s32( +float32_t test_vcvts_f32_s32(int32_t a) { +// CIR: cir.cast int_to_float + +// LLVM-SAME: i32 {{.*}} [[A:%.*]]) +// LLVM: [[TMP0:%.*]] = sitofp i32 [[A]] to float +// LLVM: ret float [[TMP0]] + return vcvts_f32_s32(a); +} + +// LLVM-LABEL: @test_vcvts_f32_u32( +// CIR-LABEL: @vcvts_f32_u32( +float32_t test_vcvts_f32_u32(uint32_t a) { +// CIR: cir.cast int_to_float + +// LLVM-SAME: i32 {{.*}} [[A:%.*]]) #[[ATTR0]] { +// LLVM: [[TMP0:%.*]] = uitofp i32 [[A]] to float +// LLVM: ret float [[TMP0]] + return vcvts_f32_u32(a); +} + +// LLVM-LABEL: @test_vcvt_f64_s64( +// CIR-LABEL: @vcvt_f64_s64( +float64x1_t test_vcvt_f64_s64(int64x1_t a) { +// CIR: cir.cast int_to_float + +// LLVM-SAME: <1 x i64> {{.*}} [[A:%.*]]) #[[ATTR0]] { +// LLVM: [[TMP0:%.*]] = bitcast <1 x i64> [[A]] to <8 x i8> +// LLVM: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64> +// LLVM: [[VCVT_I:%.*]] = sitofp <1 x i64> [[TMP1]] to <1 x double> +// LLVM: ret <1 x double> [[VCVT_I]] + return vcvt_f64_s64(a); +} + +// LLVM-LABEL: @test_vcvtq_f64_s64( +// CIR-LABEL: @vcvtq_f64_s64( +float64x2_t test_vcvtq_f64_s64(int64x2_t a) { +// CIR: cir.cast int_to_float + +// LLVM-SAME: <2 x i64> {{.*}} [[A:%.*]]) #[[ATTR0]] { +// LLVM: [[TMP0:%.*]] = bitcast <2 x i64> [[A]] to <16 x i8> +// LLVM: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64> +// LLVM: [[VCVT_I:%.*]] = sitofp <2 x i64> [[TMP1]] to <2 x double> +// LLVM: ret <2 x double> [[VCVT_I]] + return vcvtq_f64_s64(a); +} + +// LLVM-LABEL: @test_vcvt_f64_u64( +// CIR-LABEL: @vcvt_f64_u64( +float64x1_t test_vcvt_f64_u64(uint64x1_t a) { +// CIR: cir.cast int_to_float + +// LLVM-SAME: <1 x i64> {{.*}} [[A:%.*]]) #[[ATTR0]] { +// LLVM: [[TMP0:%.*]] = bitcast <1 x i64> [[A]] to <8 x i8> +// LLVM: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64> +// LLVM: [[VCVT_I:%.*]] = uitofp <1 x i64> [[TMP1]] to <1 x double> +// LLVM: ret <1 x double> [[VCVT_I]] + return vcvt_f64_u64(a); +} + +// LLVM-LABEL: @test_vcvtq_f64_u64( +// CIR-LABEL: @vcvtq_f64_u64( +float64x2_t test_vcvtq_f64_u64(uint64x2_t a) { +// CIR: cir.cast int_to_float + +// LLVM-SAME: <2 x i64> {{.*}} [[A:%.*]]) #[[ATTR0]] { +// LLVM: [[TMP0:%.*]] = bitcast <2 x i64> [[A]] to <16 x i8> +// LLVM: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64> +// LLVM: [[VCVT_I:%.*]] = uitofp <2 x i64> [[TMP1]] to <2 x double> +// LLVM: ret <2 x double> [[VCVT_I]] + return vcvtq_f64_u64(a); +} + +// LLVM-LABEL: @test_vcvtd_f64_s64( +// CIR-LABEL: @vcvtd_f64_s64( +float64_t test_vcvtd_f64_s64(int64_t a) { +// CIR: cir.cast int_to_float + +// LLVM-SAME: i64 {{.*}} [[A:%.*]]) +// LLVM: [[TMP0:%.*]] = sitofp i64 [[A]] to double +// LLVM: ret double [[TMP0]] + return vcvtd_f64_s64(a); +} + +// LLVM-LABEL: @test_vcvtd_f64_u64( +// CIR-LABEL: @vcvtd_f64_u64( +float64_t test_vcvtd_f64_u64(uint64_t a) { +// CIR: cir.cast int_to_float + +// LLVM-SAME: i64 {{.*}} [[A:%.*]]) #[[ATTR0]] { +// LLVM: [[TMP0:%.*]] = uitofp i64 [[A]] to double +// LLVM: ret double [[TMP0]] + return vcvtd_f64_u64(a); +} + +//===------------------------------------------------------===// +// 2.1.4.1 Convearions (float width conversion) +// https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#conversions +//===------------------------------------------------------===// +// LLVM-LABEL: @test_vcvt_f16_f32( +// CIR-LABEL: @vcvt_f16_f32( +float16x4_t test_vcvt_f16_f32(float32x4_t a) { +// CIR: cir.cast floating + +// LLVM-SAME: <4 x float> {{.*}} [[A:%.*]]) #[[ATTR0]] { +// LLVM: [[TMP0:%.*]] = bitcast <4 x float> [[A]] to <4 x i32> +// LLVM: [[TMP1:%.*]] = bitcast <4 x i32> [[TMP0]] to <16 x i8> +// LLVM: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float> +// LLVM: [[TMP3:%.*]] = fptrunc <4 x float> [[TMP2]] to <4 x half> +// LLVM: ret <4 x half> [[TMP3]] + return vcvt_f16_f32(a); +} + +// LLVM-LABEL: @test_vcvt_high_f16_f32( +// CIR-LABEL: @vcvt_f16_f32( +float16x8_t test_vcvt_high_f16_f32(float16x4_t a, float32x4_t b) { +// CIR: cir.call @vcvt_f16_f32 +// CIR: cir.call @vcombine_f16 + +// LLVM-SAME: <4 x half> {{.*}} [[A:%.*]], <4 x float> {{.*}} [[B:%.*]]) #[[ATTR0]] { +// LLVM: [[TMP0:%.*]] = bitcast <4 x float> [[B]] to <4 x i32> +// LLVM: [[TMP1:%.*]] = bitcast <4 x i32> [[TMP0]] to <16 x i8> +// LLVM: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float> +// LLVM: [[TMP3:%.*]] = fptrunc <4 x float> [[TMP2]] to <4 x half> +// LLVM: [[SHUFFLE_I:%.*]] = shufflevector <4 x half> [[A]], <4 x half> [[TMP3]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> +// LLVM: ret <8 x half> [[SHUFFLE_I]] + return vcvt_high_f16_f32(a, b); +} + +// LLVM-LABEL: @test_vcvt_f32_f64( +// CIR-LABEL: @vcvt_f32_f64( +float32x2_t test_vcvt_f32_f64(float64x2_t a) { +// CIR: cir.cast floating + +// LLVM-SAME: <2 x double> {{.*}} [[A:%.*]]) #[[ATTR0]] { +// LLVM: [[TMP0:%.*]] = bitcast <2 x double> [[A]] to <2 x i64> +// LLVM: [[TMP1:%.*]] = bitcast <2 x i64> [[TMP0]] to <16 x i8> +// LLVM: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double> +// LLVM: [[VCVT_I:%.*]] = fptrunc <2 x double> [[TMP2]] to <2 x float> +// LLVM: ret <2 x float> [[VCVT_I]] + return vcvt_f32_f64(a); +} + +// LLVM-LABEL: @test_vcvt_high_f32_f64( +// CIR-LABEL: @vcvt_high_f32_f64( +float32x4_t test_vcvt_high_f32_f64(float32x2_t a, float64x2_t b) { +// CIR: cir.call @vcvt_f32_f64 +// CIR: cir.call @vcombine_f32 + +// LLVM-SAME: <2 x float> {{.*}} [[A:%.*]], <2 x double> {{.*}} [[B:%.*]]) +// LLVM: [[TMP0:%.*]] = bitcast <2 x double> [[B]] to <2 x i64> +// LLVM: [[TMP1:%.*]] = bitcast <2 x i64> [[TMP0]] to <16 x i8> +// LLVM: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double> +// LLVM: [[VCVT_I_I:%.*]] = fptrunc <2 x double> [[TMP2]] to <2 x float> +// LLVM: [[SHUFFLE_I:%.*]] = shufflevector <2 x float> [[A]], <2 x float> [[VCVT_I_I]], <4 x i32> <i32 0, i32 1, i32 2, i32 3> +// LLVM: ret <4 x float> [[SHUFFLE_I]] + return vcvt_high_f32_f64(a, b); +} + +// LLVM-LABEL: @test_vcvt_f32_f16( +// CIR-LABEL: @vcvt_f32_f16( +float32x4_t test_vcvt_f32_f16(float16x4_t a) { +// CIR: cir.cast floating + +// LLVM-SAME: <4 x half> {{.*}} [[A:%.*]]) +// LLVM: [[TMP0:%.*]] = bitcast <4 x half> [[A]] to <4 x i16> +// LLVM: [[TMP1:%.*]] = bitcast <4 x i16> [[TMP0]] to <8 x i8> +// LLVM: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x half> +// LLVM: [[TMP3:%.*]] = fpext <4 x half> [[TMP2]] to <4 x float> +// LLVM: ret <4 x float> [[TMP3]] + return vcvt_f32_f16(a); +} + +// LLVM-LABEL: @test_vcvt_high_f32_f16( +// CIR-LABEL: @vcvt_high_f32_f16( +float32x4_t test_vcvt_high_f32_f16(float16x8_t a) { +// CIR: cir.call @vget_high_f16 +// CIR: cir.call @vcvt_f32_f16 + +// LLVM-SAME: <8 x half> {{.*}} [[A:%.*]]) +// LLVM: [[SHUFFLE_I:%.*]] = shufflevector <8 x half> [[A]], <8 x half> [[A]], <4 x i32> <i32 4, i32 5, i32 6, i32 7> +// LLVM: [[TMP0:%.*]] = bitcast <4 x half> [[SHUFFLE_I]] to <4 x i16> +// LLVM: [[TMP1:%.*]] = bitcast <4 x i16> [[TMP0]] to <8 x i8> +// LLVM: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x half> +// LLVM: [[TMP3:%.*]] = fpext <4 x half> [[TMP2]] to <4 x float> +// LLVM: ret <4 x float> [[TMP3]] + return vcvt_high_f32_f16(a); +} + +// LLVM-LABEL: @test_vcvt_f64_f32( +// CIR-LABEL: @vcvt_f64_f32( +float64x2_t test_vcvt_f64_f32(float32x2_t a) { +// CIR: cir.cast floating + +// LLVM-SAME: <2 x float> {{.*}} [[A:%.*]]) +// LLVM: [[TMP0:%.*]] = bitcast <2 x float> [[A]] to <2 x i32> +// LLVM: [[TMP1:%.*]] = bitcast <2 x i32> [[TMP0]] to <8 x i8> +// LLVM: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float> +// LLVM: [[VCVT_I:%.*]] = fpext <2 x float> [[TMP2]] to <2 x double> +// LLVM: ret <2 x double> [[VCVT_I]] + return vcvt_f64_f32(a); +} + +// LLVM-LABEL: @test_vcvt_high_f64_f32( +// CIR-LABEL: @vcvt_high_f64_f32( +float64x2_t test_vcvt_high_f64_f32(float32x4_t a) { +// CIR: cir.call @vget_high_f32 +// CIR: cir.call @vcvt_f64_f32 + +// LLVM-SAME: <4 x float> {{.*}} [[A:%.*]]) +// LLVM: [[SHUFFLE_I:%.*]] = shufflevector <4 x float> [[A]], <4 x float> [[A]], <2 x i32> <i32 2, i32 3> +// LLVM: [[TMP0:%.*]] = bitcast <2 x float> [[SHUFFLE_I]] to <2 x i32> +// LLVM: [[TMP1:%.*]] = bitcast <2 x i32> [[TMP0]] to <8 x i8> +// LLVM: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float> +// LLVM: [[VCVT_I_I:%.*]] = fpext <2 x float> [[TMP2]] to <2 x double> +// LLVM: ret <2 x double> [[VCVT_I_I]] + return vcvt_high_f64_f32(a); +} + +// LLVM-LABEL: @test_vcvtx_f32_f64( +// CIR-LABEL: @vcvtx_f32_f64( +float32x2_t test_vcvtx_f32_f64(float64x2_t a) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.fcvtxn" + +// LLVM-SAME: <2 x double> {{.*}} [[A:%.*]]) +// LLVM: [[TMP0:%.*]] = bitcast <2 x double> [[A]] to <2 x i64> +// LLVM: [[TMP1:%.*]] = bitcast <2 x i64> [[TMP0]] to <16 x i8> +// LLVM: [[VCVTX_F32_V_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double> +// LLVM: [[VCVTX_F32_V1_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fcvtxn.v2f32.v2f64(<2 x double> [[VCVTX_F32_V_I]]) +// LLVM: ret <2 x float> [[VCVTX_F32_V1_I]] + return vcvtx_f32_f64(a); +} + +// LLVM-LABEL: @test_vcvtxd_f32_f64 +// CIR-LABEL: @vcvtxd_f32_f64 +float32_t test_vcvtxd_f32_f64(float64_t a) { +// CIR: cir.call_llvm_intrinsic "aarch64.sisd.fcvtxn" + +// LLVM-SAME: (double {{.*}} [[A:%.*]]) +// LLVM: [[VCVTXD_F32_F64_I:%.*]] = call float @llvm.aarch64.sisd.fcvtxn(double [[A]]) +// LLVM: ret float [[VCVTXD_F32_F64_I]] + return (float32_t)vcvtxd_f32_f64(a); +} + +// LLVM-LABEL: @test_vcvtx_high_f32_f64( +// CIR-LABEL: @vcvtx_high_f32_f64( +float32x4_t test_vcvtx_high_f32_f64(float32x2_t a, float64x2_t b) { +// CIR: cir.call @vcvtx_f32_f64 +// CIR: cir.call @vcombine_f32 + +// LLVM-SAME: <2 x float> {{.*}} [[A:%.*]], <2 x double> {{.*}} [[B:%.*]]) +// LLVM: [[TMP0:%.*]] = bitcast <2 x double> [[B]] to <2 x i64> +// LLVM: [[TMP1:%.*]] = bitcast <2 x i64> [[TMP0]] to <16 x i8> +// LLVM: [[VCVTX_F32_V_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double> +// LLVM: [[VCVTX_F32_V1_I_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fcvtxn.v2f32.v2f64(<2 x double> [[VCVTX_F32_V_I_I]]) +// LLVM: [[SHUFFLE_I:%.*]] = shufflevector <2 x float> [[A]], <2 x float> [[VCVTX_F32_V1_I_I]], <4 x i32> <i32 0, i32 1, i32 2, i32 3> +// LLVM: ret <4 x float> [[SHUFFLE_I]] + return vcvtx_high_f32_f64(a, b); +} + //===------------------------------------------------------===// // 2.1.3.2.3 Vector shift right and accumulate // https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#vector-shift-right-and-accumulate _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
