ARM: Move remaining half convert libcall config into tablegen (#153408)

The __truncdfhf2 handling is kind of convoluted, but reproduces
the existing, likely wrong, handling.
This commit is contained in:
Matt Arsenault 2025-09-11 12:11:46 +09:00 committed by GitHub
parent 004231aaeb
commit fc0f1fc695
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 118 additions and 33 deletions

View File

@ -1615,13 +1615,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.
@ -1630,6 +1623,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() &&
@ -1756,7 +1770,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,
@ -1770,8 +1786,10 @@ def ARMSystemLibrary
AEABICalls,
AEABI45MemCalls,
ARMLibgccHalfConvertCalls,
EABIHalfConvertCalls,
GNUEABIHalfConvertCalls,
ARMDoubleToHalfCalls,
// Use divmod compiler-rt calls for iOS 5.0 and later.
LibcallImpls<(add __divmodsi4, __udivmodsi4),

View File

@ -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

View File

@ -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

View File

@ -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),