[clang] [clang][CIR] Add lowering for fp16 intrinsics (PR #194865)
Andrzej WarzyĆski via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 29 07:00:00 PDT 2026
https://github.com/banach-space created https://github.com/llvm/llvm-project/pull/194865
This PR adds lowering for the following intrinsic groups:
* https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#absolute-difference-1
* https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#reciprocal-estimate-1
* https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#reciprocal-estimate-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.
>From f77f2f930d91074a1fdce877c1de4254eea323bf Mon Sep 17 00:00:00 2001
From: Andrzej Warzynski <andrzej.warzynski at arm.com>
Date: Wed, 29 Apr 2026 13:52:46 +0000
Subject: [PATCH] [clang][CIR] Add lowering for fp16 intrinsics
This PR adds lowering for the following intrinsic groups:
* https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#absolute-difference-1
* https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#reciprocal-estimate-1
* https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#reciprocal-estimate-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 | 5 ++
clang/test/CodeGen/AArch64/neon/fullfp16.c | 68 +++++++++++++++++++
.../CodeGen/AArch64/v8.2a-fp16-intrinsics.c | 35 ----------
3 files changed, 73 insertions(+), 35 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
index cac5f8eced8a7..602a310384a34 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
@@ -317,6 +317,11 @@ static mlir::Value emitCommonNeonSISDBuiltinExpr(
case NEON::BI__builtin_neon_vcvtd_n_f64_u64:
case NEON::BI__builtin_neon_vcvtd_n_s64_f64:
case NEON::BI__builtin_neon_vcvtd_n_u64_f64:
+ case NEON::BI__builtin_neon_vabdh_f16:
+ case NEON::BI__builtin_neon_vrecpeh_f16:
+ case NEON::BI__builtin_neon_vrecpxh_f16:
+ case NEON::BI__builtin_neon_vrsqrteh_f16:
+ case NEON::BI__builtin_neon_vrsqrtsh_f16:
return emitNeonCall(cgf.cgm, cgf.getBuilder(),
{cgf.convertType(expr->getArg(0)->getType())}, ops,
llvmIntrName, cgf.convertType(expr->getType()), loc);
diff --git a/clang/test/CodeGen/AArch64/neon/fullfp16.c b/clang/test/CodeGen/AArch64/neon/fullfp16.c
index db0b20fe62799..056b0df253e48 100644
--- a/clang/test/CodeGen/AArch64/neon/fullfp16.c
+++ b/clang/test/CodeGen/AArch64/neon/fullfp16.c
@@ -102,6 +102,9 @@ uint16_t test_vceqzh_f16(float16_t a) {
return vceqzh_f16(a);
}
+//===------------------------------------------------------===//
+// 2.5.1.1.1. Absolute value
+//===------------------------------------------------------===//
// ALL-LABEL: @test_vabsh_f16
float16_t test_vabsh_f16(float16_t a) {
// CIR: {{%.*}} = cir.fabs {{%.*}} : !cir.f16
@@ -112,6 +115,68 @@ float16_t test_vabsh_f16(float16_t a) {
return vabsh_f16(a);
}
+//===------------------------------------------------------===//
+// 2.5.1.1.2. Absolute difference
+//===------------------------------------------------------===//
+// ALL-LABEL: test_vabdh_f16
+float16_t test_vabdh_f16(float16_t a, float16_t b) {
+// CIR: cir.call_llvm_intrinsic "aarch64.sisd.fabd" {{.*}} -> !cir.f16
+
+// LLVM-SAME: half {{.*}} [[A:%.*]], half {{.*}} [[B:%.*]])
+// LLVM: [[ABD:%.*]] = call half @llvm.aarch64.sisd.fabd.f16(half [[A]], half [[B]])
+// LLVM: ret half [[ABD]]
+ return vabdh_f16(a, b);
+}
+
+//===------------------------------------------------------===//
+// 2.5.1.2.1. Reciprocal estimate
+//===------------------------------------------------------===//
+// ALL-LABEL: test_vrecpeh_f16
+float16_t test_vrecpeh_f16(float16_t a) {
+// CIR: cir.call_llvm_intrinsic "aarch64.neon.frecpe" {{.*}} -> !cir.f16
+
+// LLVM-SAME: half {{.*}} [[A:%.*]])
+// LLVM: [[VREC:%.*]] = call half @llvm.aarch64.neon.frecpe.f16(half [[A]])
+// LLVM: ret half [[VREC]]
+ return vrecpeh_f16(a);
+}
+
+// ALL-LABEL: test_vrecpxh_f16
+float16_t test_vrecpxh_f16(float16_t a) {
+// CIR: cir.call_llvm_intrinsic "aarch64.neon.frecpx" {{.*}} -> !cir.f16
+
+// LLVM-SAME: half {{.*}} [[A:%.*]])
+// LLVM: [[VREC:%.*]] = call half @llvm.aarch64.neon.frecpx.f16(half [[A]])
+// LLVM: ret half [[VREC]]
+ return vrecpxh_f16(a);
+}
+
+//===------------------------------------------------------===//
+// 2.5.1.2.2. Reciprocal square-root estimate
+//===------------------------------------------------------===//
+// ALL-LABEL: test_vrsqrteh_f16
+float16_t test_vrsqrteh_f16(float16_t a) {
+// CIR: cir.call_llvm_intrinsic "aarch64.neon.frsqrte" {{.*}} -> !cir.f16
+
+// LLVM-SAME: half {{.*}} [[A:%.*]])
+// LLVM: [[RND:%.*]] = call half @llvm.aarch64.neon.frsqrte.f16(half [[A]])
+// LLVM: ret half [[RND]]
+ return vrsqrteh_f16(a);
+}
+
+// ALL-LABEL: test_vrsqrtsh_f16
+float16_t test_vrsqrtsh_f16(float16_t a, float16_t b) {
+// CIR: cir.call_llvm_intrinsic "aarch64.neon.frsqrts" {{.*}} -> !cir.f16
+
+// LLVM-SAME: half {{.*}} [[A:%.*]], half {{.*}} [[B:%.*]])
+// LLVM: [[RSQRTS:%.*]] = call half @llvm.aarch64.neon.frsqrts.f16(half [[A]], half [[B]])
+// LLVM: ret half [[RSQRTS]]
+ return vrsqrtsh_f16(a, b);
+}
+
+//===------------------------------------------------------===//
+// 2.5.4.1. Negate
+//===------------------------------------------------------===//
// ALL-LABEL: @test_vnegh_f16
float16_t test_vnegh_f16(float16_t a) {
// CIR: cir.minus {{.*}} : !cir.f16
@@ -122,6 +187,9 @@ float16_t test_vnegh_f16(float16_t a) {
return vnegh_f16(a);
}
+//===------------------------------------------------------===//
+// 2.5.1.9.3 Fused multiply-accumulate
+//===------------------------------------------------------===//
// ALL-LABEL: test_vfmah_f16
float16_t test_vfmah_f16(float16_t a, float16_t b, float16_t c) {
// CIR: cir.call_llvm_intrinsic "fma" {{.*}} : (!cir.f16, !cir.f16, !cir.f16) -> !cir.f16
diff --git a/clang/test/CodeGen/AArch64/v8.2a-fp16-intrinsics.c b/clang/test/CodeGen/AArch64/v8.2a-fp16-intrinsics.c
index a6f830fd48ee3..0fad0e1c79fec 100644
--- a/clang/test/CodeGen/AArch64/v8.2a-fp16-intrinsics.c
+++ b/clang/test/CodeGen/AArch64/v8.2a-fp16-intrinsics.c
@@ -291,20 +291,6 @@ uint64_t test_vcvtph_u64_f16 (float16_t a) {
return vcvtph_u64_f16(a);
}
-// CHECK-LABEL: test_vrecpeh_f16
-// CHECK: [[VREC:%.*]] = call half @llvm.aarch64.neon.frecpe.f16(half %a)
-// CHECK: ret half [[VREC]]
-float16_t test_vrecpeh_f16(float16_t a) {
- return vrecpeh_f16(a);
-}
-
-// CHECK-LABEL: test_vrecpxh_f16
-// CHECK: [[VREC:%.*]] = call half @llvm.aarch64.neon.frecpx.f16(half %a)
-// CHECK: ret half [[VREC]]
-float16_t test_vrecpxh_f16(float16_t a) {
- return vrecpxh_f16(a);
-}
-
// CHECK-LABEL: test_vrndh_f16
// CHECK: [[RND:%.*]] = call half @llvm.trunc.f16(half %a)
// CHECK: ret half [[RND]]
@@ -354,13 +340,6 @@ float16_t test_vrndxh_f16(float16_t a) {
return vrndxh_f16(a);
}
-// CHECK-LABEL: test_vrsqrteh_f16
-// CHECK: [[RND:%.*]] = call half @llvm.aarch64.neon.frsqrte.f16(half %a)
-// CHECK: ret half [[RND]]
-float16_t test_vrsqrteh_f16(float16_t a) {
- return vrsqrteh_f16(a);
-}
-
// CHECK-LABEL: test_vsqrth_f16
// CHECK: [[SQR:%.*]] = call half @llvm.sqrt.f16(half %a)
// CHECK: ret half [[SQR]]
@@ -368,13 +347,6 @@ float16_t test_vsqrth_f16(float16_t a) {
return vsqrth_f16(a);
}
-// CHECK-LABEL: test_vabdh_f16
-// CHECK: [[ABD:%.*]] = call half @llvm.aarch64.sisd.fabd.f16(half %a, half %b)
-// CHECK: ret half [[ABD]]
-float16_t test_vabdh_f16(float16_t a, float16_t b) {
- return vabdh_f16(a, b);
-}
-
// 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
@@ -576,10 +548,3 @@ float16_t test_vmulxh_f16(float16_t a, float16_t b) {
float16_t test_vrecpsh_f16(float16_t a, float16_t b) {
return vrecpsh_f16(a, b);
}
-
-// CHECK-LABEL: test_vrsqrtsh_f16
-// CHECK: [[RSQRTS:%.*]] = call half @llvm.aarch64.neon.frsqrts.f16(half %a, half %b)
-// CHECK: ret half [[RSQRTS]]
-float16_t test_vrsqrtsh_f16(float16_t a, float16_t b) {
- return vrsqrtsh_f16(a, b);
-}
More information about the cfe-commits
mailing list