Skip to content

Conversation

@arsenm
Copy link
Contributor

@arsenm arsenm commented Aug 13, 2025

The __truncdfhf2 handling is kind of convoluted, but reproduces
the existing, likely wrong, handling.

@llvmbot
Copy link
Member

llvmbot commented Aug 13, 2025

@llvm/pr-subscribers-backend-arm

@llvm/pr-subscribers-llvm-ir

Author: Matt Arsenault (arsenm)

Changes

The __truncdfhf2 handling is kind of convoluted, but reproduces
the existing, likely wrong, handling.


Full diff: https://github.com/llvm/llvm-project/pull/153408.diff

2 Files Affected:

  • (modified) llvm/include/llvm/IR/RuntimeLibcalls.td (+23-5)
  • (modified) llvm/lib/IR/RuntimeLibcalls.cpp (-19)
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td
index 89bb0be4d26e9..a98e94455dd21 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.td
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.td
@@ -1532,10 +1532,17 @@ def ARMHalfConvertLibcallCallingConv : LibcallCallingConv<
     (isAAPCS_ABI(TT, ABIName) ? CallingConv::ARM_AAPCS : CallingConv::ARM_APCS)}]
 >;
 
-def GNUEABIHalfConvertCalls :
-  LibcallImpls<(add __gnu_f2h_ieee, __gnu_h2f_ieee),
-    RuntimeLibcallPredicate<[{!TT.isOSBinFormatMachO() &&
-                              !TT.isTargetAEABI()}]>> {
+def ARMLibgccHalfConvertCalls :
+  LibcallImpls<(add __truncsfhf2, __extendhfsf2),
+    RuntimeLibcallPredicate<[{!TT.isTargetAEABI() && TT.isOSBinFormatMachO()}]>> {
+  let CallingConv = ARMHalfConvertLibcallCallingConv;
+}
+
+// FIXME: These conditions are probably bugged. We're using the
+// default libgcc call when the other cases are replaced.
+def ARMDoubleToHalfCalls :
+  LibcallImpls<(add __truncdfhf2),
+    RuntimeLibcallPredicate<[{!TT.isTargetAEABI()}]>> {
   let CallingConv = ARMHalfConvertLibcallCallingConv;
 }
 
@@ -1546,6 +1553,13 @@ def EABIHalfConvertCalls : LibcallImpls<(add __aeabi_f2h, __aeabi_h2f),
   let CallingConv = ARM_AAPCS;
 }
 
+def GNUEABIHalfConvertCalls :
+  LibcallImpls<(add __gnu_f2h_ieee, __gnu_h2f_ieee),
+    RuntimeLibcallPredicate<[{!TT.isOSBinFormatMachO() &&
+                              !TT.isTargetAEABI()}]>> {
+  let CallingConv = ARMHalfConvertLibcallCallingConv;
+}
+
 def WindowARMDivRemCalls : LibcallImpls<
   (add __rt_sdiv, __rt_sdiv64, __rt_udiv, __rt_udiv64),
   isOSWindows> {
@@ -1665,7 +1679,9 @@ def isARMOrThumb : RuntimeLibcallPredicate<"TT.isARM() || TT.isThumb()">;
 
 def ARMSystemLibrary
     : SystemRuntimeLibrary<isARMOrThumb,
-      (add WinDefaultLibcallImpls,
+      (add (sub WinDefaultLibcallImpls, ARMLibgccHalfConvertCalls,
+                                        GNUEABIHalfConvertCalls,
+                                        ARMDoubleToHalfCalls),
            LibcallImpls<(add __powisf2, __powidf2), isNotOSMSVCRT>,
            LibmHasFrexpF32, LibmHasLdexpF32,
            LibmHasFrexpF128, LibmHasLdexpF128,
@@ -1679,8 +1695,10 @@ def ARMSystemLibrary
 
            AEABICalls,
            AEABI45MemCalls,
+           ARMLibgccHalfConvertCalls,
            EABIHalfConvertCalls,
            GNUEABIHalfConvertCalls,
+           ARMDoubleToHalfCalls,
 
            // Use divmod compiler-rt calls for iOS 5.0 and later.
            LibcallImpls<(add __divmodsi4, __udivmodsi4),
diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp
index ac845c4998783..83f7df5e9f587 100644
--- a/llvm/lib/IR/RuntimeLibcalls.cpp
+++ b/llvm/lib/IR/RuntimeLibcalls.cpp
@@ -33,25 +33,6 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
   if (ExceptionModel == ExceptionHandling::SjLj)
     setLibcallImpl(RTLIB::UNWIND_RESUME, RTLIB::_Unwind_SjLj_Resume);
 
-  if (TT.isARM() || TT.isThumb()) {
-    // The half <-> float conversion functions are always soft-float on
-    // non-watchos platforms, but are needed for some targets which use a
-    // hard-float calling convention by default.
-    if (!TT.isWatchABI()) {
-      if (isAAPCS_ABI(TT, ABIName)) {
-        setLibcallImplCallingConv(RTLIB::__truncsfhf2, CallingConv::ARM_AAPCS);
-        setLibcallImplCallingConv(RTLIB::__truncdfhf2, CallingConv::ARM_AAPCS);
-        setLibcallImplCallingConv(RTLIB::__extendhfsf2, CallingConv::ARM_AAPCS);
-      } else {
-        setLibcallImplCallingConv(RTLIB::__truncsfhf2, CallingConv::ARM_APCS);
-        setLibcallImplCallingConv(RTLIB::__truncdfhf2, CallingConv::ARM_APCS);
-        setLibcallImplCallingConv(RTLIB::__extendhfsf2, CallingConv::ARM_APCS);
-      }
-    }
-
-    return;
-  }
-
   if (TT.getArch() == Triple::ArchType::msp430) {
     setLibcallImplCallingConv(RTLIB::__mspabi_mpyll,
                               CallingConv::MSP430_BUILTIN);

@llvmbot
Copy link
Member

llvmbot commented Aug 13, 2025

@llvm/pr-subscribers-tablegen

Author: Matt Arsenault (arsenm)

Changes

The __truncdfhf2 handling is kind of convoluted, but reproduces
the existing, likely wrong, handling.


Full diff: https://github.com/llvm/llvm-project/pull/153408.diff

2 Files Affected:

  • (modified) llvm/include/llvm/IR/RuntimeLibcalls.td (+23-5)
  • (modified) llvm/lib/IR/RuntimeLibcalls.cpp (-19)
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td
index 89bb0be4d26e9..a98e94455dd21 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.td
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.td
@@ -1532,10 +1532,17 @@ def ARMHalfConvertLibcallCallingConv : LibcallCallingConv<
     (isAAPCS_ABI(TT, ABIName) ? CallingConv::ARM_AAPCS : CallingConv::ARM_APCS)}]
 >;
 
-def GNUEABIHalfConvertCalls :
-  LibcallImpls<(add __gnu_f2h_ieee, __gnu_h2f_ieee),
-    RuntimeLibcallPredicate<[{!TT.isOSBinFormatMachO() &&
-                              !TT.isTargetAEABI()}]>> {
+def ARMLibgccHalfConvertCalls :
+  LibcallImpls<(add __truncsfhf2, __extendhfsf2),
+    RuntimeLibcallPredicate<[{!TT.isTargetAEABI() && TT.isOSBinFormatMachO()}]>> {
+  let CallingConv = ARMHalfConvertLibcallCallingConv;
+}
+
+// FIXME: These conditions are probably bugged. We're using the
+// default libgcc call when the other cases are replaced.
+def ARMDoubleToHalfCalls :
+  LibcallImpls<(add __truncdfhf2),
+    RuntimeLibcallPredicate<[{!TT.isTargetAEABI()}]>> {
   let CallingConv = ARMHalfConvertLibcallCallingConv;
 }
 
@@ -1546,6 +1553,13 @@ def EABIHalfConvertCalls : LibcallImpls<(add __aeabi_f2h, __aeabi_h2f),
   let CallingConv = ARM_AAPCS;
 }
 
+def GNUEABIHalfConvertCalls :
+  LibcallImpls<(add __gnu_f2h_ieee, __gnu_h2f_ieee),
+    RuntimeLibcallPredicate<[{!TT.isOSBinFormatMachO() &&
+                              !TT.isTargetAEABI()}]>> {
+  let CallingConv = ARMHalfConvertLibcallCallingConv;
+}
+
 def WindowARMDivRemCalls : LibcallImpls<
   (add __rt_sdiv, __rt_sdiv64, __rt_udiv, __rt_udiv64),
   isOSWindows> {
@@ -1665,7 +1679,9 @@ def isARMOrThumb : RuntimeLibcallPredicate<"TT.isARM() || TT.isThumb()">;
 
 def ARMSystemLibrary
     : SystemRuntimeLibrary<isARMOrThumb,
-      (add WinDefaultLibcallImpls,
+      (add (sub WinDefaultLibcallImpls, ARMLibgccHalfConvertCalls,
+                                        GNUEABIHalfConvertCalls,
+                                        ARMDoubleToHalfCalls),
            LibcallImpls<(add __powisf2, __powidf2), isNotOSMSVCRT>,
            LibmHasFrexpF32, LibmHasLdexpF32,
            LibmHasFrexpF128, LibmHasLdexpF128,
@@ -1679,8 +1695,10 @@ def ARMSystemLibrary
 
            AEABICalls,
            AEABI45MemCalls,
+           ARMLibgccHalfConvertCalls,
            EABIHalfConvertCalls,
            GNUEABIHalfConvertCalls,
+           ARMDoubleToHalfCalls,
 
            // Use divmod compiler-rt calls for iOS 5.0 and later.
            LibcallImpls<(add __divmodsi4, __udivmodsi4),
diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp
index ac845c4998783..83f7df5e9f587 100644
--- a/llvm/lib/IR/RuntimeLibcalls.cpp
+++ b/llvm/lib/IR/RuntimeLibcalls.cpp
@@ -33,25 +33,6 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
   if (ExceptionModel == ExceptionHandling::SjLj)
     setLibcallImpl(RTLIB::UNWIND_RESUME, RTLIB::_Unwind_SjLj_Resume);
 
-  if (TT.isARM() || TT.isThumb()) {
-    // The half <-> float conversion functions are always soft-float on
-    // non-watchos platforms, but are needed for some targets which use a
-    // hard-float calling convention by default.
-    if (!TT.isWatchABI()) {
-      if (isAAPCS_ABI(TT, ABIName)) {
-        setLibcallImplCallingConv(RTLIB::__truncsfhf2, CallingConv::ARM_AAPCS);
-        setLibcallImplCallingConv(RTLIB::__truncdfhf2, CallingConv::ARM_AAPCS);
-        setLibcallImplCallingConv(RTLIB::__extendhfsf2, CallingConv::ARM_AAPCS);
-      } else {
-        setLibcallImplCallingConv(RTLIB::__truncsfhf2, CallingConv::ARM_APCS);
-        setLibcallImplCallingConv(RTLIB::__truncdfhf2, CallingConv::ARM_APCS);
-        setLibcallImplCallingConv(RTLIB::__extendhfsf2, CallingConv::ARM_APCS);
-      }
-    }
-
-    return;
-  }
-
   if (TT.getArch() == Triple::ArchType::msp430) {
     setLibcallImplCallingConv(RTLIB::__mspabi_mpyll,
                               CallingConv::MSP430_BUILTIN);

@arsenm arsenm force-pushed the users/arsenm/arm/move-gnu-half-convert-libcall-calling-conv-config-tablegen branch from 283d03d to 83b3bab Compare August 13, 2025 23:38
@arsenm arsenm force-pushed the users/arsenm/arm/move-remaining-half-convert-calling-conv-config-tablegen branch from da9d432 to 333abd7 Compare August 13, 2025 23:38
@arsenm arsenm force-pushed the users/arsenm/arm/move-gnu-half-convert-libcall-calling-conv-config-tablegen branch from 83b3bab to 2b09c7b Compare August 14, 2025 07:08
@arsenm arsenm force-pushed the users/arsenm/arm/move-remaining-half-convert-calling-conv-config-tablegen branch from 333abd7 to e77db15 Compare August 14, 2025 07:08
Base automatically changed from users/arsenm/arm/move-gnu-half-convert-libcall-calling-conv-config-tablegen to main August 14, 2025 08:36
@arsenm arsenm force-pushed the users/arsenm/arm/move-remaining-half-convert-calling-conv-config-tablegen branch from e77db15 to bf4e8a6 Compare August 14, 2025 14:14

def ARMLibgccHalfConvertCalls :
LibcallImpls<(add __truncsfhf2, __extendhfsf2),
RuntimeLibcallPredicate<[{!TT.isTargetAEABI() && TT.isOSBinFormatMachO()}]>> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I follow this - the old code would add these on !Watch ABI as either AAPCS or APCS.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are the default values, and !WatchABI is not mutually exclusive. This needs to be expressed as the positive set of cases where it is used

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, but what I mean to say is that this feels like it applies to far more cases than previously.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sadly that test coverage is missing the cases for MachO/WatchABI. Would you mind adding a few cases to ensure that that the WatchOS ABI targets are properly handled?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to do this before, but update_llc_test_checks for some reason breaks on the watchOS triples. I do see no difference with and without this, but those triples also do not use the libcalls in the first place.

Part of the problem I'm trying to solve here is the conflation of does-this-call-exist and will this call be used

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hacked the triple into update_llc_test_checks

// default libgcc call when the other cases are replaced.
def ARMDoubleToHalfCalls :
LibcallImpls<(add __truncdfhf2),
RuntimeLibcallPredicate<[{!TT.isTargetAEABI()}]>> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likewise

@arsenm arsenm changed the title ARM: Remove remaining half convert libcall config into tablegen ARM: Move remaining half convert libcall config into tablegen Aug 19, 2025
@arsenm arsenm force-pushed the users/arsenm/arm/move-remaining-half-convert-calling-conv-config-tablegen branch from bf4e8a6 to 67eb146 Compare August 19, 2025 06:17
The __truncdfhf2 handling is kind of convoluted, but reproduces
the existing, likely wrong, handling.
@arsenm arsenm force-pushed the users/arsenm/arm/move-remaining-half-convert-calling-conv-config-tablegen branch from 67eb146 to 3128daa Compare September 3, 2025 00:47
@arsenm
Copy link
Contributor Author

arsenm commented Sep 10, 2025

ping

@arsenm arsenm merged commit fc0f1fc into main Sep 11, 2025
9 checks passed
@arsenm arsenm deleted the users/arsenm/arm/move-remaining-half-convert-calling-conv-config-tablegen branch September 11, 2025 03:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants