Author: Andrzej WarzyĆski Date: 2026-07-10T09:24:58+01:00 New Revision: 445d6c31c829fd01adf837ea50f19dbe4f7bd9ed
URL: https://github.com/llvm/llvm-project/commit/445d6c31c829fd01adf837ea50f19dbe4f7bd9ed DIFF: https://github.com/llvm/llvm-project/commit/445d6c31c829fd01adf837ea50f19dbe4f7bd9ed.diff LOG: [CIR][AArc64] Add lowering for fp16 intrinsics (sqrt + max + min) (#207786) This PR adds lowering for the following intrinsic groups: * https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#markdown-toc-square-root-1 * https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#maximum-1O * https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#markdown-toc-minimum-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. Added: Modified: clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp clang/test/CodeGen/AArch64/neon/fullfp16.c clang/test/CodeGen/AArch64/v8.2a-fp16-intrinsics.c Removed: ################################################################################ diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp index dfb5ace82bb06..2608aaf780591 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp @@ -2869,22 +2869,20 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, if (cir::isFPOrVectorOfFPType(ty)) intrName = "aarch64.neon.fmax"; return emitNeonCall(cgm, builder, {ty, ty}, ops, intrName, ty, loc); - case NEON::BI__builtin_neon_vmaxh_f16: - cgm.errorNYI(expr->getSourceRange(), - std::string("unimplemented AArch64 builtin call: ") + - getContext().BuiltinInfo.getName(builtinID)); - return mlir::Value{}; + case NEON::BI__builtin_neon_vmaxh_f16: { + auto halfTy = builder.getFp16Ty(); + return builder.emitIntrinsicCallOp(loc, "aarch64.neon.fmax", halfTy, ops); + } case NEON::BI__builtin_neon_vmin_v: case NEON::BI__builtin_neon_vminq_v: intrName = usgn ? "aarch64.neon.umin" : "aarch64.neon.smin"; if (cir::isFPOrVectorOfFPType(ty)) intrName = "aarch64.neon.fmin"; return emitNeonCall(cgm, builder, {ty, ty}, ops, intrName, ty, loc); - case NEON::BI__builtin_neon_vminh_f16: - cgm.errorNYI(expr->getSourceRange(), - std::string("unimplemented AArch64 builtin call: ") + - getContext().BuiltinInfo.getName(builtinID)); - return mlir::Value{}; + case NEON::BI__builtin_neon_vminh_f16: { + auto halfTy = builder.getFp16Ty(); + return builder.emitIntrinsicCallOp(loc, "aarch64.neon.fmin", halfTy, ops); + } case NEON::BI__builtin_neon_vabd_v: case NEON::BI__builtin_neon_vabdq_v: intrName = usgn ? "aarch64.neon.uabd" : "aarch64.neon.sabd"; @@ -2917,16 +2915,18 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, case NEON::BI__builtin_neon_vminnmq_v: intrName = "aarch64.neon.fminnm"; return emitNeonCall(cgm, builder, {ty, ty}, ops, intrName, ty, loc); - case NEON::BI__builtin_neon_vminnmh_f16: - cgm.errorNYI(expr->getSourceRange(), - std::string("unimplemented AArch64 builtin call: ") + - getContext().BuiltinInfo.getName(builtinID)); - return mlir::Value{}; + case NEON::BI__builtin_neon_vminnmh_f16: { + auto halfTy = builder.getFp16Ty(); + return builder.emitIntrinsicCallOp(loc, "aarch64.neon.fminnm", halfTy, ops); + } case NEON::BI__builtin_neon_vmaxnm_v: case NEON::BI__builtin_neon_vmaxnmq_v: intrName = "aarch64.neon.fmaxnm"; return emitNeonCall(cgm, builder, {ty, ty}, ops, intrName, ty, loc); - case NEON::BI__builtin_neon_vmaxnmh_f16: + case NEON::BI__builtin_neon_vmaxnmh_f16: { + auto halfTy = builder.getFp16Ty(); + return builder.emitIntrinsicCallOp(loc, "aarch64.neon.fmaxnm", halfTy, ops); + } case NEON::BI__builtin_neon_vrecpss_f32: case NEON::BI__builtin_neon_vrecpsd_f64: cgm.errorNYI(expr->getSourceRange(), @@ -3106,11 +3106,10 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, case NEON::BI__builtin_neon_vpminnmq_v: intrName = "aarch64.neon.fminnmp"; return emitNeonCall(cgm, builder, {ty, ty}, ops, intrName, ty, loc); - case NEON::BI__builtin_neon_vsqrth_f16: - cgm.errorNYI(expr->getSourceRange(), - std::string("unimplemented AArch64 builtin call: ") + - getContext().BuiltinInfo.getName(builtinID)); - return mlir::Value{}; + case NEON::BI__builtin_neon_vsqrth_f16: { + auto halfTy = builder.getFp16Ty(); + return emitCallMaybeConstrainedBuiltin(builder, loc, "sqrt", {halfTy}, ops); + } case NEON::BI__builtin_neon_vsqrt_v: case NEON::BI__builtin_neon_vsqrtq_v: assert(!cir::MissingFeatures::emitConstrainedFPCall()); diff --git a/clang/test/CodeGen/AArch64/neon/fullfp16.c b/clang/test/CodeGen/AArch64/neon/fullfp16.c index cd93d30e7d2ae..71a5a7d98eb83 100644 --- a/clang/test/CodeGen/AArch64/neon/fullfp16.c +++ b/clang/test/CodeGen/AArch64/neon/fullfp16.c @@ -34,7 +34,7 @@ #include <arm_fp16.h> //===------------------------------------------------------===// -// 2.5.1.1. Addition +// 2.5.1.5. Addition //===------------------------------------------------------===// // ALL-LABEL: @test_vaddh_f16( float16_t test_vaddh_f16(float16_t a, float16_t b) { @@ -85,6 +85,52 @@ float16_t test_vdivh_f16(float16_t a, float16_t b) { return vdivh_f16(a, b); } +//===------------------------------------------------------===// +// 2.5.1.7. Maximum +//===------------------------------------------------------===// +// ALL-LABEL: test_vmaxh_f16 +float16_t test_vmaxh_f16(float16_t a, float16_t b) { +// CIR: {{%.*}} = cir.call_llvm_intrinsic "aarch64.neon.fmax" + +// LLVM-SAME: half {{.*}} [[A:%.]], half {{.*}} [[B:%.]]) {{.*}} { +// LLVM: [[MAX:%.*]] = call half @llvm.aarch64.neon.fmax.f16(half [[A]], half [[B]]) +// LLVM: ret half [[MAX]] + return vmaxh_f16(a, b); +} + +// ALL-LABEL: test_vmaxnmh_f16 +float16_t test_vmaxnmh_f16(float16_t a, float16_t b) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.fmaxnm" + +// LLVM-SAME: half {{.*}} [[A:%.]], half {{.*}} [[B:%.]]) {{.*}} { +// LLVM: [[MAX:%.*]] = call half @llvm.aarch64.neon.fmaxnm.f16(half [[A]], half [[B]]) +// LLVM: ret half [[MAX]] + return vmaxnmh_f16(a, b); +} + +//===------------------------------------------------------===// +// 2.5.1.8. Mimimum +//===------------------------------------------------------===// +// ALL-LABEL: test_vminh_f16 +float16_t test_vminh_f16(float16_t a, float16_t b) { +// CIR: {{%.*}} = cir.call_llvm_intrinsic "aarch64.neon.fmin" + +// LLVM-SAME: half {{.*}} [[A:%.]], half {{.*}} [[B:%.]]) {{.*}} { +// LLVM: [[MIN:%.*]] = call half @llvm.aarch64.neon.fmin.f16(half [[A]], half [[B]]) +// LLVM: ret half [[MIN]] + return vminh_f16(a, b); +} + +// ALL-LABEL: test_vminnmh_f16 +float16_t test_vminnmh_f16(float16_t a, float16_t b) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.fminnm" + +// LLVM-SAME: half {{.*}} [[A:%.]], half {{.*}} [[B:%.]]) {{.*}} { +// LLVM: [[MIN:%.*]] = call half @llvm.aarch64.neon.fminnm.f16(half [[A]], half [[B]]) +// LLVM: ret half [[MIN]] + return vminnmh_f16(a, b); +} + //===------------------------------------------------------===// // 2.5.2.1. Bitwise equal to zero //===------------------------------------------------------===// @@ -260,6 +306,19 @@ float16_t test_vrndxh_f16(float16_t a) { return vrndxh_f16(a); } +//===------------------------------------------------------===// +// 2.5.1.4. Square root +//===------------------------------------------------------===// +// ALL-LABEL: test_vsqrth_f16 +float16_t test_vsqrth_f16(float16_t a) { +// CIR: cir.call_llvm_intrinsic "sqrt" + +// LLVM-SAME: half{{.*}} [[A:%.*]]) +// LLVM: [[SQR:%.*]] = call half @llvm.sqrt.f16(half [[A]]) +// LLVM: ret half [[SQR]] + return vsqrth_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 ad4a0e5eb7275..d519e4138adbf 100644 --- a/clang/test/CodeGen/AArch64/v8.2a-fp16-intrinsics.c +++ b/clang/test/CodeGen/AArch64/v8.2a-fp16-intrinsics.c @@ -291,13 +291,6 @@ uint64_t test_vcvtph_u64_f16 (float16_t a) { return vcvtph_u64_f16(a); } -// CHECK-LABEL: test_vsqrth_f16 -// CHECK: [[SQR:%.*]] = call half @llvm.sqrt.f16(half %a) -// CHECK: ret half [[SQR]] -float16_t test_vsqrth_f16(float16_t a) { - return vsqrth_f16(a); -} - // CHECK-LABEL: test_vcageh_f16 // CHECK: [[FACG:%.*]] = call i32 @llvm.aarch64.neon.facge.i32.f16(half %a, half %b) // CHECK: [[RET:%.*]] = trunc i32 [[FACG]] to i16 @@ -458,34 +451,6 @@ int64_t test_vcvth_n_u64_f16(float16_t a) { return vcvth_n_u64_f16(a, 1); } -// CHECK-LABEL: test_vmaxh_f16 -// CHECK: [[MAX:%.*]] = call half @llvm.aarch64.neon.fmax.f16(half %a, half %b) -// CHECK: ret half [[MAX]] -float16_t test_vmaxh_f16(float16_t a, float16_t b) { - return vmaxh_f16(a, b); -} - -// CHECK-LABEL: test_vmaxnmh_f16 -// CHECK: [[MAX:%.*]] = call half @llvm.aarch64.neon.fmaxnm.f16(half %a, half %b) -// CHECK: ret half [[MAX]] -float16_t test_vmaxnmh_f16(float16_t a, float16_t b) { - return vmaxnmh_f16(a, b); -} - -// CHECK-LABEL: test_vminh_f16 -// CHECK: [[MIN:%.*]] = call half @llvm.aarch64.neon.fmin.f16(half %a, half %b) -// CHECK: ret half [[MIN]] -float16_t test_vminh_f16(float16_t a, float16_t b) { - return vminh_f16(a, b); -} - -// CHECK-LABEL: test_vminnmh_f16 -// CHECK: [[MIN:%.*]] = call half @llvm.aarch64.neon.fminnm.f16(half %a, half %b) -// CHECK: ret half [[MIN]] -float16_t test_vminnmh_f16(float16_t a, float16_t b) { - return vminnmh_f16(a, b); -} - // CHECK-LABEL: test_vmulxh_f16 // CHECK: [[MUL:%.*]] = call half @llvm.aarch64.neon.fmulx.f16(half %a, half %b) // CHECK: ret half [[MUL]] _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
