[clang] 445d6c3 - [CIR][AArc64] Add lowering for fp16 intrinsics (sqrt + max + min) (#207786)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 10 01:25:03 PDT 2026
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]]
More information about the cfe-commits
mailing list