diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp index 0722f5ba76b6..a4958276dc88 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp @@ -2319,6 +2319,7 @@ mlir::Value CIRGenFunction::emitCommonNeonBuiltinExpr( // Determine the type of this overloaded NEON intrinsic. NeonTypeFlags neonType(neonTypeConst->getZExtValue()); bool isUnsigned = neonType.isUnsigned(); + bool isQuad = neonType.isQuad(); const bool hasLegalHalfType = getTarget().hasLegalHalfType(); // The value of allowBFloatArgsAndRet is true for AArch64, but it should // come from ABI info. @@ -2380,6 +2381,13 @@ mlir::Value CIRGenFunction::emitCommonNeonBuiltinExpr( : "aarch64.neon.sqsub", vTy, getLoc(e->getExprLoc())); } + case NEON::BI__builtin_neon_vcvt_f32_v: + case NEON::BI__builtin_neon_vcvtq_f32_v: { + ops[0] = builder.createBitcast(ops[0], ty); + ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float32, false, isQuad), + hasLegalHalfType); + return builder.createCast(cir::CastKind::int_to_float, ops[0], ty); + } case NEON::BI__builtin_neon_vext_v: case NEON::BI__builtin_neon_vextq_v: { int cv = getIntValueFromConstOp(ops[2]); diff --git a/clang/test/CIR/CodeGen/AArch64/neon-misc.c b/clang/test/CIR/CodeGen/AArch64/neon-misc.c index 2869a95fe884..a798139de55f 100644 --- a/clang/test/CIR/CodeGen/AArch64/neon-misc.c +++ b/clang/test/CIR/CodeGen/AArch64/neon-misc.c @@ -860,3 +860,50 @@ uint32x2_t test_vqmovn_u64(uint64x2_t a) { // LLVM: [[VQMOVN_V1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uqxtn.v2i32(<2 x i64> [[A]]) // LLVM: ret <2 x i32> [[VQMOVN_V1_I]] } +float32x2_t test_vcvt_f32_s32(int32x2_t a) { + return vcvt_f32_s32(a); + + // CIR-LABEL: vcvt_f32_s32 + // {{%.*}} = cir.cast(int_to_float, {{%.*}} : !cir.vector), !cir.vector + + // LLVM: {{.*}}test_vcvt_f32_s32(<2 x i32>{{.*}}[[a:%.*]]) + // LLVM: [[TMP0:%.*]] = bitcast <2 x i32> [[a]] to <8 x i8> + // LLVM: [[VCVT_I:%.*]] = sitofp <2 x i32> [[a]] to <2 x float> + // LLVM: ret <2 x float> [[VCVT_I]] +} + +float32x2_t test_vcvt_f32_u32(uint32x2_t a) { + return vcvt_f32_u32(a); + + // CIR-LABEL: vcvt_f32_u32 + // {{%.*}} = cir.cast(int_to_float, {{%.*}} : !cir.vector), !cir.vector + + // LLVM: {{.*}}test_vcvt_f32_u32(<2 x i32>{{.*}}[[a:%.*]]) + // LLVM: [[TMP0:%.*]] = bitcast <2 x i32> [[a]] to <8 x i8> + // LLVM: [[VCVT_I:%.*]] = uitofp <2 x i32> [[a]] to <2 x float> + // LLVM: ret <2 x float> [[VCVT_I]] +} + +float32x4_t test_vcvtq_f32_s32(int32x4_t a) { + return vcvtq_f32_s32(a); + + // CIR-LABEL: vcvtq_f32_s32 + // {{%.*}} = cir.cast(int_to_float, {{%.*}} : !cir.vector), !cir.vector + + // LLVM: {{.*}}test_vcvtq_f32_s32(<4 x i32>{{.*}}[[a:%.*]]) + // LLVM: [[TMP0:%.*]] = bitcast <4 x i32> [[a]] to <16 x i8> + // LLVM: [[VCVT_I:%.*]] = sitofp <4 x i32> [[a]] to <4 x float> + // LLVM: ret <4 x float> [[VCVT_I]] +} + +float32x4_t test_vcvtq_f32_u32(uint32x4_t a) { + return vcvtq_f32_u32(a); + + // CIR-LABEL: vcvtq_f32_u32 + // {{%.*}} = cir.cast(int_to_float, {{%.*}} : !cir.vector), !cir.vector + + // LLVM: {{.*}}test_vcvtq_f32_u32(<4 x i32>{{.*}}[[a:%.*]]) + // LLVM: [[TMP0:%.*]] = bitcast <4 x i32> [[a]] to <16 x i8> + // LLVM: [[VCVT_I:%.*]] = uitofp <4 x i32> [[a]] to <4 x float> + // LLVM: ret <4 x float> [[VCVT_I]] +}