https://github.com/banach-space updated https://github.com/llvm/llvm-project/pull/207511
From 53bccc12a6d50522e1780ce779837fa7d893e939 Mon Sep 17 00:00:00 2001 From: Andrzej Warzynski <[email protected]> Date: Sat, 4 Jul 2026 16:29:04 +0000 Subject: [PATCH] [CIR][AArc64] Add lowering for fp16 intrinsics (FP16 step + rounding) This PR adds lowering for the following intrinsic groups: * https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#markdown-toc-reciprocal-step * https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#markdown-toc-rounding-1 It also moves the corresponding tests from: * clang/test/CodeGen/AArch64/v8.2a-fp16-intrinsics.c to: * clang/test/CodeGen/AArch64/neon/fullfp16.c The lowering follows the existing implementation in CodeGen/TargetBuiltins/ARM.cpp. --- .../lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp | 76 +++++++++++++--- clang/test/CodeGen/AArch64/neon/fullfp16.c | 86 +++++++++++++++++++ .../CodeGen/AArch64/v8.2a-fp16-intrinsics.c | 55 ------------ 3 files changed, 152 insertions(+), 65 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp index e3418d561df34..dbbcd8ae8890a 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp @@ -657,8 +657,8 @@ static mlir::Value emitCommonNeonBuiltinExpr( // FIXME // getTargetHooks().getABIInfo().allowBFloatArgsAndRet(); - cir::VectorType vTy = getNeonType(&cgf, neonType, hasLegalHalfType, false, - allowBFloatArgsAndRet); + cir::VectorType vTy = getNeonType(&cgf, neonType, hasLegalHalfType, + /*v1Ty=*/false, allowBFloatArgsAndRet); cir::VectorType ty = vTy; if (!ty) return nullptr; @@ -2876,7 +2876,15 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, case NEON::BI__builtin_neon_vmaxnmh_f16: case NEON::BI__builtin_neon_vrecpss_f32: case NEON::BI__builtin_neon_vrecpsd_f64: - case NEON::BI__builtin_neon_vrecpsh_f16: + cgm.errorNYI(expr->getSourceRange(), + std::string("unimplemented AArch64 builtin call: ") + + getContext().BuiltinInfo.getName(builtinID)); + return mlir::Value{}; + case NEON::BI__builtin_neon_vrecpsh_f16: { + auto halfTy = builder.getFp16Ty(); + return emitNeonCall(cgm, builder, {halfTy, halfTy}, ops, + "aarch64.neon.frecps", halfTy, loc); + } case NEON::BI__builtin_neon_vqshrun_n_v: cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + @@ -2906,24 +2914,72 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, return emitNeonCall(cgm, builder, {argTy, sInt32Ty}, ops, intrName, ty, loc); } - case NEON::BI__builtin_neon_vrndah_f16: + case NEON::BI__builtin_neon_vrndah_f16: { + assert(!cir::MissingFeatures::emitConstrainedFPCall()); + auto halfTy = builder.getFp16Ty(); + return emitNeonCall(cgm, builder, {halfTy}, ops, "round", halfTy, loc); + } case NEON::BI__builtin_neon_vrnda_v: case NEON::BI__builtin_neon_vrndaq_v: - case NEON::BI__builtin_neon_vrndih_f16: - case NEON::BI__builtin_neon_vrndmh_f16: + cgm.errorNYI(expr->getSourceRange(), + std::string("unimplemented AArch64 builtin call: ") + + getContext().BuiltinInfo.getName(builtinID)); + return mlir::Value{}; + case NEON::BI__builtin_neon_vrndih_f16: { + assert(!cir::MissingFeatures::emitConstrainedFPCall()); + auto halfTy = builder.getFp16Ty(); + return emitNeonCall(cgm, builder, {halfTy}, ops, "nearbyint", halfTy, loc); + } + case NEON::BI__builtin_neon_vrndmh_f16: { + assert(!cir::MissingFeatures::emitConstrainedFPCall()); + auto halfTy = builder.getFp16Ty(); + return emitNeonCall(cgm, builder, {halfTy}, ops, "floor", halfTy, loc); + } case NEON::BI__builtin_neon_vrndm_v: case NEON::BI__builtin_neon_vrndmq_v: - case NEON::BI__builtin_neon_vrndnh_f16: + cgm.errorNYI(expr->getSourceRange(), + std::string("unimplemented AArch64 builtin call: ") + + getContext().BuiltinInfo.getName(builtinID)); + return mlir::Value{}; + case NEON::BI__builtin_neon_vrndnh_f16: { + assert(!cir::MissingFeatures::emitConstrainedFPCall()); + auto halfTy = builder.getFp16Ty(); + return emitNeonCall(cgm, builder, {halfTy}, ops, "roundeven", halfTy, loc); + } case NEON::BI__builtin_neon_vrndn_v: case NEON::BI__builtin_neon_vrndnq_v: case NEON::BI__builtin_neon_vrndns_f32: - case NEON::BI__builtin_neon_vrndph_f16: + cgm.errorNYI(expr->getSourceRange(), + std::string("unimplemented AArch64 builtin call: ") + + getContext().BuiltinInfo.getName(builtinID)); + return mlir::Value{}; + case NEON::BI__builtin_neon_vrndph_f16: { + assert(!cir::MissingFeatures::emitConstrainedFPCall()); + auto halfTy = builder.getFp16Ty(); + return emitNeonCall(cgm, builder, {halfTy}, ops, "ceil", halfTy, loc); + } case NEON::BI__builtin_neon_vrndp_v: case NEON::BI__builtin_neon_vrndpq_v: - case NEON::BI__builtin_neon_vrndxh_f16: + cgm.errorNYI(expr->getSourceRange(), + std::string("unimplemented AArch64 builtin call: ") + + getContext().BuiltinInfo.getName(builtinID)); + return mlir::Value{}; + case NEON::BI__builtin_neon_vrndxh_f16: { + assert(!cir::MissingFeatures::emitConstrainedFPCall()); + auto halfTy = builder.getFp16Ty(); + return emitNeonCall(cgm, builder, {halfTy}, ops, "rint", halfTy, loc); + } case NEON::BI__builtin_neon_vrndx_v: case NEON::BI__builtin_neon_vrndxq_v: - case NEON::BI__builtin_neon_vrndh_f16: + cgm.errorNYI(expr->getSourceRange(), + std::string("unimplemented AArch64 builtin call: ") + + getContext().BuiltinInfo.getName(builtinID)); + return mlir::Value{}; + case NEON::BI__builtin_neon_vrndh_f16: { + assert(!cir::MissingFeatures::emitConstrainedFPCall()); + auto halfTy = builder.getFp16Ty(); + return emitNeonCall(cgm, builder, {halfTy}, ops, "trunc", halfTy, loc); + } case NEON::BI__builtin_neon_vrnd32x_f32: case NEON::BI__builtin_neon_vrnd32xq_f32: case NEON::BI__builtin_neon_vrnd32x_f64: diff --git a/clang/test/CodeGen/AArch64/neon/fullfp16.c b/clang/test/CodeGen/AArch64/neon/fullfp16.c index ba65f76e924c4..b9f6269ed836c 100644 --- a/clang/test/CodeGen/AArch64/neon/fullfp16.c +++ b/clang/test/CodeGen/AArch64/neon/fullfp16.c @@ -174,6 +174,92 @@ float16_t test_vrsqrtsh_f16(float16_t a, float16_t b) { return vrsqrtsh_f16(a, b); } +//===------------------------------------------------------===// +// 2.5.1.2.3. Reciprocal step +//===------------------------------------------------------===// +// ALL-LABEL: test_vrecpsh_f16 +float16_t test_vrecpsh_f16(float16_t a, float16_t b) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.frecps" + +// LLVM-SAME: half {{.*}} [[A:%.*]], half {{.*}} [[B:%.*]]) +// LLVM: [[RECPS:%.*]] = call half @llvm.aarch64.neon.frecps.f16(half [[A]], half [[B]]) +// LLVM: ret half [[RECPS]] + return vrecpsh_f16(a, b); +} + +//===------------------------------------------------------===// +// 2.5.1.3. Rounding +//===------------------------------------------------------===// +// ALL-LABEL: test_vrndh_f16 +float16_t test_vrndh_f16(float16_t a) { +// CIR: cir.call_llvm_intrinsic "trunc" + +// LLVM-SAME: half {{.*}} [[A:%.*]]) +// LLVM: [[RND:%.*]] = call half @llvm.trunc.f16(half [[A]]) +// LLVM: ret half [[RND]] + return vrndh_f16(a); +} + +// ALL-LABEL: test_vrndah_f16 +float16_t test_vrndah_f16(float16_t a) { +// CIR: cir.call_llvm_intrinsic "round" + +// LLVM-SAME: half {{.*}} [[A:%.*]]) +// LLVM: [[RND:%.*]] = call half @llvm.round.f16(half [[A]]) +// LLVM: ret half [[RND]] + return vrndah_f16(a); +} + +// ALL-LABEL: test_vrndih_f16 +float16_t test_vrndih_f16(float16_t a) { +// CIR: cir.call_llvm_intrinsic "nearbyint" + +// LLVM-SAME: half {{.*}} [[A:%.*]]) +// LLVM: [[RND:%.*]] = call half @llvm.nearbyint.f16(half [[A]]) +// LLVM: ret half [[RND]] + return vrndih_f16(a); +} + +// ALL-LABEL: test_vrndmh_f16 +float16_t test_vrndmh_f16(float16_t a) { +// CIR: cir.call_llvm_intrinsic "floor" + +// LLVM-SAME: half {{.*}} [[A:%.*]]) +// LLVM: [[RND:%.*]] = call half @llvm.floor.f16(half [[A]]) +// LLVM: ret half [[RND]] + return vrndmh_f16(a); +} + +// ALL-LABEL: test_vrndnh_f16 +float16_t test_vrndnh_f16(float16_t a) { +// CIR: cir.call_llvm_intrinsic "roundeven" + +// LLVM-SAME: half {{.*}} [[A:%.*]]) +// LLVM: [[RND:%.*]] = call half @llvm.roundeven.f16(half [[A]]) +// LLVM: ret half [[RND]] + return vrndnh_f16(a); +} + +// ALL-LABEL: test_vrndph_f16 +float16_t test_vrndph_f16(float16_t a) { +// CIR: cir.call_llvm_intrinsic "ceil" + +// LLVM-SAME: half {{.*}} [[A:%.*]]) +// LLVM: [[RND:%.*]] = call half @llvm.ceil.f16(half [[A]]) +// LLVM: ret half [[RND]] + return vrndph_f16(a); +} + +// ALL-LABEL: test_vrndxh_f16 +float16_t test_vrndxh_f16(float16_t a) { +// CIR: cir.call_llvm_intrinsic "rint" + +// LLVm-SAME: half {{.*}} [[A:%.*]]) +// LLVM: [[RND:%.*]] = call half @llvm.rint.f16(half [[A]]) +// LLVM: ret half [[RND]] + return vrndxh_f16(a); +} + //===------------------------------------------------------===// // 2.5.4.1. Negate //===------------------------------------------------------===// diff --git a/clang/test/CodeGen/AArch64/v8.2a-fp16-intrinsics.c b/clang/test/CodeGen/AArch64/v8.2a-fp16-intrinsics.c index ed6246238bf8e..41021d7d21f7d 100644 --- a/clang/test/CodeGen/AArch64/v8.2a-fp16-intrinsics.c +++ b/clang/test/CodeGen/AArch64/v8.2a-fp16-intrinsics.c @@ -291,54 +291,6 @@ uint64_t test_vcvtph_u64_f16 (float16_t a) { return vcvtph_u64_f16(a); } -// CHECK-LABEL: test_vrndh_f16 -// CHECK: [[RND:%.*]] = call half @llvm.trunc.f16(half %a) -// CHECK: ret half [[RND]] -float16_t test_vrndh_f16(float16_t a) { - return vrndh_f16(a); -} - -// CHECK-LABEL: test_vrndah_f16 -// CHECK: [[RND:%.*]] = call half @llvm.round.f16(half %a) -// CHECK: ret half [[RND]] -float16_t test_vrndah_f16(float16_t a) { - return vrndah_f16(a); -} - -// CHECK-LABEL: test_vrndih_f16 -// CHECK: [[RND:%.*]] = call half @llvm.nearbyint.f16(half %a) -// CHECK: ret half [[RND]] -float16_t test_vrndih_f16(float16_t a) { - return vrndih_f16(a); -} - -// CHECK-LABEL: test_vrndmh_f16 -// CHECK: [[RND:%.*]] = call half @llvm.floor.f16(half %a) -// CHECK: ret half [[RND]] -float16_t test_vrndmh_f16(float16_t a) { - return vrndmh_f16(a); -} - -// CHECK-LABEL: test_vrndnh_f16 -// CHECK: [[RND:%.*]] = call half @llvm.roundeven.f16(half %a) -// CHECK: ret half [[RND]] -float16_t test_vrndnh_f16(float16_t a) { - return vrndnh_f16(a); -} - -// CHECK-LABEL: test_vrndph_f16 -// CHECK: [[RND:%.*]] = call half @llvm.ceil.f16(half %a) -// CHECK: ret half [[RND]] -float16_t test_vrndph_f16(float16_t a) { - return vrndph_f16(a); -} - -// CHECK-LABEL: test_vrndxh_f16 -// CHECK: [[RND:%.*]] = call half @llvm.rint.f16(half %a) -// CHECK: ret half [[RND]] -float16_t test_vrndxh_f16(float16_t a) { - return vrndxh_f16(a); -} // CHECK-LABEL: test_vsqrth_f16 // CHECK: [[SQR:%.*]] = call half @llvm.sqrt.f16(half %a) @@ -541,10 +493,3 @@ float16_t test_vminnmh_f16(float16_t a, float16_t b) { float16_t test_vmulxh_f16(float16_t a, float16_t b) { return vmulxh_f16(a, b); } - -// CHECK-LABEL: test_vrecpsh_f16 -// CHECK: [[RECPS:%.*]] = call half @llvm.aarch64.neon.frecps.f16(half %a, half %b) -// CHECK: ret half [[RECPS]] -float16_t test_vrecpsh_f16(float16_t a, float16_t b) { - return vrecpsh_f16(a, b); -} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
