[compiler-rt] [llvm] [compiler-rt] Use integers for __gnu_h2f_ieee and __gnu_f2h_ieee (PR #220167)
Trevor Gross via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 8 17:04:39 PDT 2026
https://github.com/tgross35 updated https://github.com/llvm/llvm-project/pull/220167
>From 1064d0483fc34daf5ff360e4596cdf9ff639c759 Mon Sep 17 00:00:00 2001
From: Trevor Gross <tg at trevorgross.com>
Date: Tue, 1 Sep 2026 04:00:31 -0500
Subject: [PATCH 1/2] [compiler-rt] Use integers for __gnu_h2f_ieee and
__gnu_f2h_ieee
In libgcc, these conversion routines use integers in the signature. In
practice this has worked because the AAPCS calling convention passes and
returns floats the same as the same-sized integer, but this may not be
the case on all platforms. Thus, update the signatures to match GCC.
---
compiler-rt/lib/builtins/extendhfsf2.c | 10 ++++++----
compiler-rt/lib/builtins/fp_extend.h | 18 +++++++++++++++++-
compiler-rt/lib/builtins/fp_trunc.h | 18 +++++++++++++++++-
compiler-rt/lib/builtins/truncsfhf2.c | 10 ++++++----
llvm/include/llvm/IR/RuntimeLibcalls.td | 4 ++++
5 files changed, 50 insertions(+), 10 deletions(-)
diff --git a/compiler-rt/lib/builtins/extendhfsf2.c b/compiler-rt/lib/builtins/extendhfsf2.c
index c0f25cdadcd4f..376ca040f1b92 100644
--- a/compiler-rt/lib/builtins/extendhfsf2.c
+++ b/compiler-rt/lib/builtins/extendhfsf2.c
@@ -16,14 +16,16 @@ COMPILER_RT_ABI NOINLINE float __extendhfsf2(src_t a) {
return __extendXfYf2__(a);
}
+// arm32-gnueabi-only routine that uses integers in the signature. This should
+// be gnueabi-specific, but LLVM currently emits it on more eabi platforms.
+COMPILER_RT_ABI uint32_t __gnu_h2f_ieee(uint16_t a) {
+ return dstToRep(__extendhfsf2(srcFromRep(a)));
+}
+
#if defined(__ARM_EABI__)
#if defined(COMPILER_RT_ARMHF_TARGET)
-AEABI_RTABI float __gnu_h2f_ieee(src_t a) { return __extendhfsf2(a); }
AEABI_RTABI float __aeabi_h2f(src_t a) { return __extendhfsf2(a); }
#else
-COMPILER_RT_ALIAS(__extendhfsf2, __gnu_h2f_ieee)
COMPILER_RT_ALIAS(__extendhfsf2, __aeabi_h2f)
#endif
-#else
-COMPILER_RT_ABI float __gnu_h2f_ieee(src_t a) { return __extendhfsf2(a); }
#endif
diff --git a/compiler-rt/lib/builtins/fp_extend.h b/compiler-rt/lib/builtins/fp_extend.h
index 22bf2b2514e57..dab19e13054e2 100644
--- a/compiler-rt/lib/builtins/fp_extend.h
+++ b/compiler-rt/lib/builtins/fp_extend.h
@@ -157,7 +157,7 @@ static inline dst_rep_t construct_dst_rep(dst_rep_t sign, dst_rep_t exp, dst_rep
return (sign << (dstBits - 1)) | (exp << (dstBits - 1 - dstExpBits)) | sigFrac;
}
-// Two helper routines for conversion to and from the representation of
+// Helper routines for conversion to and from the representation of
// floating-point data as integer values follow.
static inline src_rep_t srcToRep(src_t x) {
@@ -168,6 +168,22 @@ static inline src_rep_t srcToRep(src_t x) {
return rep.i;
}
+static inline src_t srcFromRep(src_rep_t x) {
+ const union {
+ src_t f;
+ src_rep_t i;
+ } rep = {.i = x};
+ return rep.f;
+}
+
+static inline dst_rep_t dstToRep(dst_t x) {
+ const union {
+ dst_t f;
+ dst_rep_t i;
+ } rep = {.f = x};
+ return rep.i;
+}
+
static inline dst_t dstFromRep(dst_rep_t x) {
const union {
dst_t f;
diff --git a/compiler-rt/lib/builtins/fp_trunc.h b/compiler-rt/lib/builtins/fp_trunc.h
index a1bd881eb57c9..7010ed46fe9cd 100644
--- a/compiler-rt/lib/builtins/fp_trunc.h
+++ b/compiler-rt/lib/builtins/fp_trunc.h
@@ -148,7 +148,7 @@ static inline dst_rep_t construct_dst_rep(dst_rep_t sign, dst_rep_t exp, dst_rep
return result;
}
-// End of specialization parameters. Two helper routines for conversion to and
+// End of specialization parameters. Helper routines for conversion to and
// from the representation of floating-point data as integer values follow.
static inline src_rep_t srcToRep(src_t x) {
@@ -159,6 +159,22 @@ static inline src_rep_t srcToRep(src_t x) {
return rep.i;
}
+static inline src_t srcFromRep(src_rep_t x) {
+ const union {
+ src_t f;
+ src_rep_t i;
+ } rep = {.i = x};
+ return rep.f;
+}
+
+static inline dst_rep_t dstToRep(dst_t x) {
+ const union {
+ dst_t f;
+ dst_rep_t i;
+ } rep = {.f = x};
+ return rep.i;
+}
+
static inline dst_t dstFromRep(dst_rep_t x) {
const union {
dst_t f;
diff --git a/compiler-rt/lib/builtins/truncsfhf2.c b/compiler-rt/lib/builtins/truncsfhf2.c
index 6ad8621b8bb02..095fd504d2044 100644
--- a/compiler-rt/lib/builtins/truncsfhf2.c
+++ b/compiler-rt/lib/builtins/truncsfhf2.c
@@ -16,14 +16,16 @@ COMPILER_RT_ABI NOINLINE dst_t __truncsfhf2(float a) {
return __truncXfYf2__(a);
}
+// arm32-gnueabi-only routine that uses integers in the signature. This should
+// be gnueabi-specific, but LLVM currently emits it on more eabi platforms.
+COMPILER_RT_ABI uint16_t __gnu_f2h_ieee(uint32_t a) {
+ return dstToRep(__truncsfhf2(srcFromRep(a)));
+}
+
#if defined(__ARM_EABI__)
#if defined(COMPILER_RT_ARMHF_TARGET)
-AEABI_RTABI dst_t __gnu_f2h_ieee(float a) { return __truncsfhf2(a); }
AEABI_RTABI dst_t __aeabi_f2h(float a) { return __truncsfhf2(a); }
#else
-COMPILER_RT_ALIAS(__truncsfhf2, __gnu_f2h_ieee)
COMPILER_RT_ALIAS(__truncsfhf2, __aeabi_f2h)
#endif
-#else
-COMPILER_RT_ABI dst_t __gnu_f2h_ieee(float a) { return __truncsfhf2(a); }
#endif
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td
index 078a3a39146ad..0c23f0e761655 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.td
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.td
@@ -2608,6 +2608,10 @@ def isNotMachOAndNotTargetAEABI
: RuntimeLibcallAvailability<(all_of (not IsOSBinFormatMachO),
(not IsTargetAEABI))>;
+// Note that these actually pass and return int and short rather than float and
+// _Float16. This happens to work with the AAPCS calling convention where they
+// are treated equally, but may not work on other platforms. __extendhfsf2 and
+// __truncsfhf2 should be used anyway on non-GNUEABIHF targets.
def GNUEABIHalfConvertCalls :
LibcallImpls<(add __gnu_f2h_ieee, __gnu_h2f_ieee),
isNotMachOAndNotTargetAEABI> {
>From e5ec898efa3c8833dc482b627e6dfdc24b157f14 Mon Sep 17 00:00:00 2001
From: Trevor Gross <tg at trevorgross.com>
Date: Tue, 8 Sep 2026 20:04:30 -0400
Subject: [PATCH 2/2] Reword runtimelibcalls.td comment
---
llvm/include/llvm/IR/RuntimeLibcalls.td | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td
index 0c23f0e761655..9976587232cd1 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.td
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.td
@@ -2611,7 +2611,7 @@ def isNotMachOAndNotTargetAEABI
// Note that these actually pass and return int and short rather than float and
// _Float16. This happens to work with the AAPCS calling convention where they
// are treated equally, but may not work on other platforms. __extendhfsf2 and
-// __truncsfhf2 should be used anyway on non-GNUEABIHF targets.
+// __truncsfhf2 should be used instead on non-GNUEABIHF targets anyway.
def GNUEABIHalfConvertCalls :
LibcallImpls<(add __gnu_f2h_ieee, __gnu_h2f_ieee),
isNotMachOAndNotTargetAEABI> {
More information about the llvm-commits
mailing list