[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
Fri Sep 4 23:43:05 PDT 2026
https://github.com/tgross35 updated https://github.com/llvm/llvm-project/pull/220167
>From aa030fc5f8d6ce89611c922a415686dbdafc71ea 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] [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 | 12 ++++++++----
compiler-rt/lib/builtins/fp_extend.h | 18 +++++++++++++++++-
compiler-rt/lib/builtins/fp_trunc.h | 18 +++++++++++++++++-
compiler-rt/lib/builtins/truncsfhf2.c | 12 ++++++++----
llvm/include/llvm/IR/RuntimeLibcalls.td | 4 ++++
5 files changed, 54 insertions(+), 10 deletions(-)
diff --git a/compiler-rt/lib/builtins/extendhfsf2.c b/compiler-rt/lib/builtins/extendhfsf2.c
index c0f25cdadcd4f..6aea27a1e7a36 100644
--- a/compiler-rt/lib/builtins/extendhfsf2.c
+++ b/compiler-rt/lib/builtins/extendhfsf2.c
@@ -16,14 +16,18 @@ 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) {
+ // Call the __inline version to avoid an extra indirection, since
+ // __extendhfsf2 won't be linked if this is used.
+ return dstToRep(__extendXfYf2__(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..8cf0036fe943b 100644
--- a/compiler-rt/lib/builtins/truncsfhf2.c
+++ b/compiler-rt/lib/builtins/truncsfhf2.c
@@ -16,14 +16,18 @@ 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) {
+ // Call the __inline version to avoid an extra indirection, since
+ // __truncsfhf2 won't be linked if this is used.
+ return dstToRep(__truncXfYf2__(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> {
More information about the llvm-commits
mailing list