From 3128daa0ac32bafffdde174cac1ec75d530e9bf2 Mon Sep 17 00:00:00 2001 From: Matt Arsenault 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; // CallingConv::ARM_AAPCS def __gnu_f2h_ieee : RuntimeLibcallImpl; def __gnu_h2f_ieee : RuntimeLibcallImpl; -// 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, 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 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),