[llvm] ARM: Move remaining half convert libcall config into tablegen (PR #153408)

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 2 17:59:20 PDT 2025


https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/153408

>From 3128daa0ac32bafffdde174cac1ec75d530e9bf2 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Wed, 13 Aug 2025 21:05:36 +0900
Subject: [PATCH 1/2] ARM: Remove remaining half convert libcall config into
 tablegen

The __truncdfhf2 handling is kind of convoluted, but reproduces
the existing, likely wrong, handling.
---
 llvm/include/llvm/IR/RuntimeLibcalls.td | 34 +++++++++++++++++++------
 llvm/lib/IR/RuntimeLibcalls.cpp         | 25 ------------------
 2 files changed, 26 insertions(+), 33 deletions(-)

diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td
index 24ea92cc6865d..c0c2781af6e69 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.td
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.td
@@ -1614,13 +1614,6 @@ def __aeabi_h2f : RuntimeLibcallImpl<FPEXT_F16_F32>; // CallingConv::ARM_AAPCS
 def __gnu_f2h_ieee : RuntimeLibcallImpl<FPROUND_F32_F16>;
 def __gnu_h2f_ieee : RuntimeLibcallImpl<FPEXT_F16_F32>;
 
-// In EABI, these functions have an __aeabi_ prefix, but in GNUEABI
-// they have a __gnu_ prefix (which is the default).
-def EABIHalfConvertCalls : LibcallImpls<(add __aeabi_f2h, __aeabi_h2f),
-                                        isTargetAEABIAndAAPCS_ABI> {
-  let CallingConv = ARM_AAPCS;
-}
-
 // 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.
@@ -1629,6 +1622,27 @@ def ARMHalfConvertLibcallCallingConv : LibcallCallingConv<
     (isAAPCS_ABI(TT, ABIName) ? CallingConv::ARM_AAPCS : CallingConv::ARM_APCS)}]
 >;
 
+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;
+}
+
+// In EABI, these functions have an __aeabi_ prefix, but in GNUEABI
+// they have a __gnu_ prefix (which is the default).
+def EABIHalfConvertCalls : LibcallImpls<(add __aeabi_f2h, __aeabi_h2f),
+                                        isTargetAEABIAndAAPCS_ABI> {
+  let CallingConv = ARM_AAPCS;
+}
+
 def GNUEABIHalfConvertCalls :
   LibcallImpls<(add __gnu_f2h_ieee, __gnu_h2f_ieee),
     RuntimeLibcallPredicate<[{!TT.isOSBinFormatMachO() &&
@@ -1755,7 +1769,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,
@@ -1769,8 +1785,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 4fe5714a74e3f..7ea2e46a54183 100644
--- a/llvm/lib/IR/RuntimeLibcalls.cpp
+++ b/llvm/lib/IR/RuntimeLibcalls.cpp
@@ -33,31 +33,6 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
                                        EABI EABIVersion, StringRef ABIName) {
   setTargetRuntimeLibcallSets(TT, ExceptionModel, FloatABI, EABIVersion,
                               ABIName);
-
-  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::impl___truncsfhf2,
-                                  CallingConv::ARM_AAPCS);
-        setLibcallImplCallingConv(RTLIB::impl___truncdfhf2,
-                                  CallingConv::ARM_AAPCS);
-        setLibcallImplCallingConv(RTLIB::impl___extendhfsf2,
-                                  CallingConv::ARM_AAPCS);
-      } else {
-        setLibcallImplCallingConv(RTLIB::impl___truncsfhf2,
-                                  CallingConv::ARM_APCS);
-        setLibcallImplCallingConv(RTLIB::impl___truncdfhf2,
-                                  CallingConv::ARM_APCS);
-        setLibcallImplCallingConv(RTLIB::impl___extendhfsf2,
-                                  CallingConv::ARM_APCS);
-      }
-    }
-
-    return;
-  }
 }
 
 LLVM_ATTRIBUTE_ALWAYS_INLINE

>From 25ec612677041c997ebe8789d82cf440ad5eabba Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Wed, 3 Sep 2025 09:58:59 +0900
Subject: [PATCH 2/2] test watchabi case, which doesn't use the calls

---
 .../issue147935-half-convert-libcall-abi.ll   | 91 +++++++++++++++++++
 llvm/utils/UpdateTestChecks/asm.py            |  1 +
 2 files changed, 92 insertions(+)

diff --git a/llvm/test/CodeGen/ARM/issue147935-half-convert-libcall-abi.ll b/llvm/test/CodeGen/ARM/issue147935-half-convert-libcall-abi.ll
index 33f3efccd039e..be18eb3a9aa22 100644
--- a/llvm/test/CodeGen/ARM/issue147935-half-convert-libcall-abi.ll
+++ b/llvm/test/CodeGen/ARM/issue147935-half-convert-libcall-abi.ll
@@ -5,6 +5,8 @@
 ; RUN: llc -mtriple=arm-unknown-linux-eabi -mattr=+vfp2 < %s | FileCheck -check-prefixes=AAPCS-SOFT,EABI-SOFT %s
 ; RUN: llc -mtriple=armv7-unknown-linux -target-abi=apcs -float-abi=soft < %s | FileCheck -check-prefix=APCS %s
 ; RUN: llc -mtriple=armv7-unknown-linux -target-abi=apcs -float-abi=hard < %s | FileCheck -check-prefix=APCS %s
+; RUN: llc -mtriple=armv7k-apple-watchos2.0 -mcpu=cortex-a7 < %s | FileCheck -check-prefix=WATCHABI-HARD %s
+; RUN: llc -mtriple=armv7k-apple-watchos2.0 -mcpu=cortex-a7 -float-abi=soft < %s | FileCheck -check-prefix=WATCHABI-SOFT %s
 
 define i1 @test(half %self) #0 {
 ; GNU-AAPCS-HARD-LABEL: test:
@@ -72,6 +74,26 @@ define i1 @test(half %self) #0 {
 ; APCS-NEXT:    movwvs r0, #1
 ; APCS-NEXT:    pop {lr}
 ; APCS-NEXT:    bx lr
+;
+; WATCHABI-HARD-LABEL: test:
+; WATCHABI-HARD:       @ %bb.0:
+; WATCHABI-HARD-NEXT:    vcvtb.f32.f16 s0, s0
+; WATCHABI-HARD-NEXT:    mov r0, #0
+; WATCHABI-HARD-NEXT:    vcmp.f32 s0, s0
+; WATCHABI-HARD-NEXT:    vmrs APSR_nzcv, fpscr
+; WATCHABI-HARD-NEXT:    movwvs r0, #1
+; WATCHABI-HARD-NEXT:    bx lr
+;
+; WATCHABI-SOFT-LABEL: test:
+; WATCHABI-SOFT:       @ %bb.0:
+; WATCHABI-SOFT-NEXT:    vmov s0, r0
+; WATCHABI-SOFT-NEXT:    mov r1, #0
+; WATCHABI-SOFT-NEXT:    vcvtb.f32.f16 s0, s0
+; WATCHABI-SOFT-NEXT:    vcmp.f32 s0, s0
+; WATCHABI-SOFT-NEXT:    vmrs APSR_nzcv, fpscr
+; WATCHABI-SOFT-NEXT:    movwvs r1, #1
+; WATCHABI-SOFT-NEXT:    mov r0, r1
+; WATCHABI-SOFT-NEXT:    bx lr
   %_0 = fcmp une half %self, %self
   ret i1 %_0
 }
@@ -111,6 +133,21 @@ define float @f16_to_f32(ptr %p) #0 {
 ; APCS:       @ %bb.0:
 ; APCS-NEXT:    ldrh r0, [r0]
 ; APCS-NEXT:    b __gnu_h2f_ieee
+;
+; WATCHABI-HARD-LABEL: f16_to_f32:
+; WATCHABI-HARD:       @ %bb.0:
+; WATCHABI-HARD-NEXT:    ldrh r0, [r0]
+; WATCHABI-HARD-NEXT:    vmov s0, r0
+; WATCHABI-HARD-NEXT:    vcvtb.f32.f16 s0, s0
+; WATCHABI-HARD-NEXT:    bx lr
+;
+; WATCHABI-SOFT-LABEL: f16_to_f32:
+; WATCHABI-SOFT:       @ %bb.0:
+; WATCHABI-SOFT-NEXT:    ldrh r0, [r0]
+; WATCHABI-SOFT-NEXT:    vmov s0, r0
+; WATCHABI-SOFT-NEXT:    vcvtb.f32.f16 s0, s0
+; WATCHABI-SOFT-NEXT:    vmov r0, s0
+; WATCHABI-SOFT-NEXT:    bx lr
   %load = load half, ptr %p
   %cvt = fpext half %load to float
   ret float %cvt
@@ -169,6 +206,21 @@ define void @f32_to_f16(ptr %p, float %arg) #0 {
 ; APCS-NEXT:    bl __gnu_f2h_ieee
 ; APCS-NEXT:    strh r0, [r4]
 ; APCS-NEXT:    pop {r4, pc}
+;
+; WATCHABI-HARD-LABEL: f32_to_f16:
+; WATCHABI-HARD:       @ %bb.0:
+; WATCHABI-HARD-NEXT:    vcvtb.f16.f32 s0, s0
+; WATCHABI-HARD-NEXT:    vmov r1, s0
+; WATCHABI-HARD-NEXT:    strh r1, [r0]
+; WATCHABI-HARD-NEXT:    bx lr
+;
+; WATCHABI-SOFT-LABEL: f32_to_f16:
+; WATCHABI-SOFT:       @ %bb.0:
+; WATCHABI-SOFT-NEXT:    vmov s0, r1
+; WATCHABI-SOFT-NEXT:    vcvtb.f16.f32 s0, s0
+; WATCHABI-SOFT-NEXT:    vmov r1, s0
+; WATCHABI-SOFT-NEXT:    strh r1, [r0]
+; WATCHABI-SOFT-NEXT:    bx lr
   %cvt = fptrunc float %arg to half
   store half %cvt, ptr %p
   ret void
@@ -231,6 +283,23 @@ define double @f16_to_f64(ptr %p) #0 {
 ; APCS-NEXT:    vmov r0, r1, d16
 ; APCS-NEXT:    pop {lr}
 ; APCS-NEXT:    bx lr
+;
+; WATCHABI-HARD-LABEL: f16_to_f64:
+; WATCHABI-HARD:       @ %bb.0:
+; WATCHABI-HARD-NEXT:    ldrh r0, [r0]
+; WATCHABI-HARD-NEXT:    vmov s0, r0
+; WATCHABI-HARD-NEXT:    vcvtb.f32.f16 s0, s0
+; WATCHABI-HARD-NEXT:    vcvt.f64.f32 d0, s0
+; WATCHABI-HARD-NEXT:    bx lr
+;
+; WATCHABI-SOFT-LABEL: f16_to_f64:
+; WATCHABI-SOFT:       @ %bb.0:
+; WATCHABI-SOFT-NEXT:    ldrh r0, [r0]
+; WATCHABI-SOFT-NEXT:    vmov s0, r0
+; WATCHABI-SOFT-NEXT:    vcvtb.f32.f16 s0, s0
+; WATCHABI-SOFT-NEXT:    vcvt.f64.f32 d16, s0
+; WATCHABI-SOFT-NEXT:    vmov r0, r1, d16
+; WATCHABI-SOFT-NEXT:    bx lr
   %load = load half, ptr %p
   %cvt = fpext half %load to double
   ret double %cvt
@@ -269,6 +338,28 @@ define void @f64_to_f16(ptr %p, double %arg) #0 {
 ; APCS-NEXT:    bl __truncdfhf2
 ; APCS-NEXT:    strh r0, [r4]
 ; APCS-NEXT:    pop {r4, pc}
+;
+; WATCHABI-HARD-LABEL: f64_to_f16:
+; WATCHABI-HARD:       @ %bb.0:
+; WATCHABI-HARD-NEXT:    push {r4, lr}
+; WATCHABI-HARD-NEXT:    sub sp, sp, #8
+; WATCHABI-HARD-NEXT:    mov r4, r0
+; WATCHABI-HARD-NEXT:    bl ___truncdfhf2
+; WATCHABI-HARD-NEXT:    strh r0, [r4]
+; WATCHABI-HARD-NEXT:    add sp, sp, #8
+; WATCHABI-HARD-NEXT:    pop {r4, pc}
+;
+; WATCHABI-SOFT-LABEL: f64_to_f16:
+; WATCHABI-SOFT:       @ %bb.0:
+; WATCHABI-SOFT-NEXT:    push {r4, lr}
+; WATCHABI-SOFT-NEXT:    sub sp, sp, #8
+; WATCHABI-SOFT-NEXT:    mov r4, r0
+; WATCHABI-SOFT-NEXT:    mov r1, r3
+; WATCHABI-SOFT-NEXT:    mov r0, r2
+; WATCHABI-SOFT-NEXT:    bl ___truncdfhf2
+; WATCHABI-SOFT-NEXT:    strh r0, [r4]
+; WATCHABI-SOFT-NEXT:    add sp, sp, #8
+; WATCHABI-SOFT-NEXT:    pop {r4, pc}
   %cvt = fptrunc double %arg to half
   store half %cvt, ptr %p
   ret void
diff --git a/llvm/utils/UpdateTestChecks/asm.py b/llvm/utils/UpdateTestChecks/asm.py
index 570dbd081eb79..457b23f4a5f59 100644
--- a/llvm/utils/UpdateTestChecks/asm.py
+++ b/llvm/utils/UpdateTestChecks/asm.py
@@ -574,6 +574,7 @@ def get_run_handler(triple):
         "arm64-apple-macosx": (scrub_asm_arm_eabi, ASM_FUNCTION_AARCH64_DARWIN_RE),
         "armv7-apple-ios": (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_IOS_RE),
         "armv7-apple-darwin": (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_DARWIN_RE),
+        "armv7k-apple-watchos": (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_DARWIN_RE),
         "thumb": (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
         "thumb-macho": (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_MACHO_RE),
         "thumbv5-macho": (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_MACHO_RE),



More information about the llvm-commits mailing list