diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index 45311e92f9866..cbd43cde78548 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -715,10 +715,14 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM_, setLibcallImplCallingConv(RTLIB::__truncsfhf2, CallingConv::ARM_AAPCS); setLibcallImplCallingConv(RTLIB::__truncdfhf2, CallingConv::ARM_AAPCS); setLibcallImplCallingConv(RTLIB::__extendhfsf2, CallingConv::ARM_AAPCS); + setLibcallImplCallingConv(RTLIB::__gnu_h2f_ieee, CallingConv::ARM_AAPCS); + setLibcallImplCallingConv(RTLIB::__gnu_f2h_ieee, CallingConv::ARM_AAPCS); } else { setLibcallImplCallingConv(RTLIB::__truncsfhf2, CallingConv::ARM_APCS); setLibcallImplCallingConv(RTLIB::__truncdfhf2, CallingConv::ARM_APCS); setLibcallImplCallingConv(RTLIB::__extendhfsf2, CallingConv::ARM_APCS); + setLibcallImplCallingConv(RTLIB::__gnu_h2f_ieee, CallingConv::ARM_APCS); + setLibcallImplCallingConv(RTLIB::__gnu_f2h_ieee, CallingConv::ARM_APCS); } } diff --git a/llvm/test/CodeGen/ARM/issue147935-half-convert-libcall-abi.ll b/llvm/test/CodeGen/ARM/issue147935-half-convert-libcall-abi.ll new file mode 100644 index 0000000000000..33f3efccd039e --- /dev/null +++ b/llvm/test/CodeGen/ARM/issue147935-half-convert-libcall-abi.ll @@ -0,0 +1,277 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=arm-unknown-linux-gnueabihf -mattr=+vfp2 < %s | FileCheck -check-prefixes=AAPCS-HARD,GNU-AAPCS-HARD %s +; RUN: llc -mtriple=arm-unknown-linux-gnueabi -mattr=+vfp2 < %s | FileCheck -check-prefixes=AAPCS-SOFT,GNU-AAPCS-SOFT %s +; RUN: llc -mtriple=arm-unknown-linux-eabihf -mattr=+vfp2 < %s | FileCheck -check-prefixes=AAPCS-HARD,EABI-HARD %s +; 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 + +define i1 @test(half %self) #0 { +; GNU-AAPCS-HARD-LABEL: test: +; GNU-AAPCS-HARD: @ %bb.0: +; GNU-AAPCS-HARD-NEXT: .save {r11, lr} +; GNU-AAPCS-HARD-NEXT: push {r11, lr} +; GNU-AAPCS-HARD-NEXT: vmov r0, s0 +; GNU-AAPCS-HARD-NEXT: bl __gnu_h2f_ieee +; GNU-AAPCS-HARD-NEXT: vmov s0, r0 +; GNU-AAPCS-HARD-NEXT: mov r0, #0 +; GNU-AAPCS-HARD-NEXT: vcmp.f32 s0, s0 +; GNU-AAPCS-HARD-NEXT: vmrs APSR_nzcv, fpscr +; GNU-AAPCS-HARD-NEXT: movvs r0, #1 +; GNU-AAPCS-HARD-NEXT: pop {r11, lr} +; GNU-AAPCS-HARD-NEXT: mov pc, lr +; +; GNU-AAPCS-SOFT-LABEL: test: +; GNU-AAPCS-SOFT: @ %bb.0: +; GNU-AAPCS-SOFT-NEXT: .save {r11, lr} +; GNU-AAPCS-SOFT-NEXT: push {r11, lr} +; GNU-AAPCS-SOFT-NEXT: bl __gnu_h2f_ieee +; GNU-AAPCS-SOFT-NEXT: vmov s0, r0 +; GNU-AAPCS-SOFT-NEXT: mov r0, #0 +; GNU-AAPCS-SOFT-NEXT: vcmp.f32 s0, s0 +; GNU-AAPCS-SOFT-NEXT: vmrs APSR_nzcv, fpscr +; GNU-AAPCS-SOFT-NEXT: movvs r0, #1 +; GNU-AAPCS-SOFT-NEXT: pop {r11, lr} +; GNU-AAPCS-SOFT-NEXT: mov pc, lr +; +; EABI-HARD-LABEL: test: +; EABI-HARD: @ %bb.0: +; EABI-HARD-NEXT: .save {r11, lr} +; EABI-HARD-NEXT: push {r11, lr} +; EABI-HARD-NEXT: vmov r0, s0 +; EABI-HARD-NEXT: bl __aeabi_h2f +; EABI-HARD-NEXT: vmov s0, r0 +; EABI-HARD-NEXT: mov r0, #0 +; EABI-HARD-NEXT: vcmp.f32 s0, s0 +; EABI-HARD-NEXT: vmrs APSR_nzcv, fpscr +; EABI-HARD-NEXT: movvs r0, #1 +; EABI-HARD-NEXT: pop {r11, lr} +; EABI-HARD-NEXT: mov pc, lr +; +; EABI-SOFT-LABEL: test: +; EABI-SOFT: @ %bb.0: +; EABI-SOFT-NEXT: .save {r11, lr} +; EABI-SOFT-NEXT: push {r11, lr} +; EABI-SOFT-NEXT: bl __aeabi_h2f +; EABI-SOFT-NEXT: vmov s0, r0 +; EABI-SOFT-NEXT: mov r0, #0 +; EABI-SOFT-NEXT: vcmp.f32 s0, s0 +; EABI-SOFT-NEXT: vmrs APSR_nzcv, fpscr +; EABI-SOFT-NEXT: movvs r0, #1 +; EABI-SOFT-NEXT: pop {r11, lr} +; EABI-SOFT-NEXT: mov pc, lr +; +; APCS-LABEL: test: +; APCS: @ %bb.0: +; APCS-NEXT: push {lr} +; APCS-NEXT: bl __gnu_h2f_ieee +; APCS-NEXT: vmov s0, r0 +; APCS-NEXT: mov r0, #0 +; APCS-NEXT: vcmp.f32 s0, s0 +; APCS-NEXT: vmrs APSR_nzcv, fpscr +; APCS-NEXT: movwvs r0, #1 +; APCS-NEXT: pop {lr} +; APCS-NEXT: bx lr + %_0 = fcmp une half %self, %self + ret i1 %_0 +} + +define float @f16_to_f32(ptr %p) #0 { +; GNU-AAPCS-HARD-LABEL: f16_to_f32: +; GNU-AAPCS-HARD: @ %bb.0: +; GNU-AAPCS-HARD-NEXT: .save {r11, lr} +; GNU-AAPCS-HARD-NEXT: push {r11, lr} +; GNU-AAPCS-HARD-NEXT: ldrh r0, [r0] +; GNU-AAPCS-HARD-NEXT: bl __gnu_h2f_ieee +; GNU-AAPCS-HARD-NEXT: vmov s0, r0 +; GNU-AAPCS-HARD-NEXT: pop {r11, lr} +; GNU-AAPCS-HARD-NEXT: mov pc, lr +; +; GNU-AAPCS-SOFT-LABEL: f16_to_f32: +; GNU-AAPCS-SOFT: @ %bb.0: +; GNU-AAPCS-SOFT-NEXT: ldrh r0, [r0] +; GNU-AAPCS-SOFT-NEXT: b __gnu_h2f_ieee +; +; EABI-HARD-LABEL: f16_to_f32: +; EABI-HARD: @ %bb.0: +; EABI-HARD-NEXT: .save {r11, lr} +; EABI-HARD-NEXT: push {r11, lr} +; EABI-HARD-NEXT: ldrh r0, [r0] +; EABI-HARD-NEXT: bl __aeabi_h2f +; EABI-HARD-NEXT: vmov s0, r0 +; EABI-HARD-NEXT: pop {r11, lr} +; EABI-HARD-NEXT: mov pc, lr +; +; EABI-SOFT-LABEL: f16_to_f32: +; EABI-SOFT: @ %bb.0: +; EABI-SOFT-NEXT: ldrh r0, [r0] +; EABI-SOFT-NEXT: b __aeabi_h2f +; +; APCS-LABEL: f16_to_f32: +; APCS: @ %bb.0: +; APCS-NEXT: ldrh r0, [r0] +; APCS-NEXT: b __gnu_h2f_ieee + %load = load half, ptr %p + %cvt = fpext half %load to float + ret float %cvt +} + +define void @f32_to_f16(ptr %p, float %arg) #0 { +; GNU-AAPCS-HARD-LABEL: f32_to_f16: +; GNU-AAPCS-HARD: @ %bb.0: +; GNU-AAPCS-HARD-NEXT: .save {r4, lr} +; GNU-AAPCS-HARD-NEXT: push {r4, lr} +; GNU-AAPCS-HARD-NEXT: mov r4, r0 +; GNU-AAPCS-HARD-NEXT: vmov r0, s0 +; GNU-AAPCS-HARD-NEXT: bl __gnu_f2h_ieee +; GNU-AAPCS-HARD-NEXT: strh r0, [r4] +; GNU-AAPCS-HARD-NEXT: pop {r4, lr} +; GNU-AAPCS-HARD-NEXT: mov pc, lr +; +; GNU-AAPCS-SOFT-LABEL: f32_to_f16: +; GNU-AAPCS-SOFT: @ %bb.0: +; GNU-AAPCS-SOFT-NEXT: .save {r4, lr} +; GNU-AAPCS-SOFT-NEXT: push {r4, lr} +; GNU-AAPCS-SOFT-NEXT: mov r4, r0 +; GNU-AAPCS-SOFT-NEXT: mov r0, r1 +; GNU-AAPCS-SOFT-NEXT: bl __gnu_f2h_ieee +; GNU-AAPCS-SOFT-NEXT: strh r0, [r4] +; GNU-AAPCS-SOFT-NEXT: pop {r4, lr} +; GNU-AAPCS-SOFT-NEXT: mov pc, lr +; +; EABI-HARD-LABEL: f32_to_f16: +; EABI-HARD: @ %bb.0: +; EABI-HARD-NEXT: .save {r4, lr} +; EABI-HARD-NEXT: push {r4, lr} +; EABI-HARD-NEXT: mov r4, r0 +; EABI-HARD-NEXT: vmov r0, s0 +; EABI-HARD-NEXT: bl __aeabi_f2h +; EABI-HARD-NEXT: strh r0, [r4] +; EABI-HARD-NEXT: pop {r4, lr} +; EABI-HARD-NEXT: mov pc, lr +; +; EABI-SOFT-LABEL: f32_to_f16: +; EABI-SOFT: @ %bb.0: +; EABI-SOFT-NEXT: .save {r4, lr} +; EABI-SOFT-NEXT: push {r4, lr} +; EABI-SOFT-NEXT: mov r4, r0 +; EABI-SOFT-NEXT: mov r0, r1 +; EABI-SOFT-NEXT: bl __aeabi_f2h +; EABI-SOFT-NEXT: strh r0, [r4] +; EABI-SOFT-NEXT: pop {r4, lr} +; EABI-SOFT-NEXT: mov pc, lr +; +; APCS-LABEL: f32_to_f16: +; APCS: @ %bb.0: +; APCS-NEXT: push {r4, lr} +; APCS-NEXT: mov r4, r0 +; APCS-NEXT: mov r0, r1 +; APCS-NEXT: bl __gnu_f2h_ieee +; APCS-NEXT: strh r0, [r4] +; APCS-NEXT: pop {r4, pc} + %cvt = fptrunc float %arg to half + store half %cvt, ptr %p + ret void +} + +define double @f16_to_f64(ptr %p) #0 { +; GNU-AAPCS-HARD-LABEL: f16_to_f64: +; GNU-AAPCS-HARD: @ %bb.0: +; GNU-AAPCS-HARD-NEXT: .save {r11, lr} +; GNU-AAPCS-HARD-NEXT: push {r11, lr} +; GNU-AAPCS-HARD-NEXT: ldrh r0, [r0] +; GNU-AAPCS-HARD-NEXT: bl __gnu_h2f_ieee +; GNU-AAPCS-HARD-NEXT: vmov s0, r0 +; GNU-AAPCS-HARD-NEXT: vcvt.f64.f32 d0, s0 +; GNU-AAPCS-HARD-NEXT: pop {r11, lr} +; GNU-AAPCS-HARD-NEXT: mov pc, lr +; +; GNU-AAPCS-SOFT-LABEL: f16_to_f64: +; GNU-AAPCS-SOFT: @ %bb.0: +; GNU-AAPCS-SOFT-NEXT: .save {r11, lr} +; GNU-AAPCS-SOFT-NEXT: push {r11, lr} +; GNU-AAPCS-SOFT-NEXT: ldrh r0, [r0] +; GNU-AAPCS-SOFT-NEXT: bl __gnu_h2f_ieee +; GNU-AAPCS-SOFT-NEXT: vmov s0, r0 +; GNU-AAPCS-SOFT-NEXT: vcvt.f64.f32 d0, s0 +; GNU-AAPCS-SOFT-NEXT: vmov r0, r1, d0 +; GNU-AAPCS-SOFT-NEXT: pop {r11, lr} +; GNU-AAPCS-SOFT-NEXT: mov pc, lr +; +; EABI-HARD-LABEL: f16_to_f64: +; EABI-HARD: @ %bb.0: +; EABI-HARD-NEXT: .save {r11, lr} +; EABI-HARD-NEXT: push {r11, lr} +; EABI-HARD-NEXT: ldrh r0, [r0] +; EABI-HARD-NEXT: bl __aeabi_h2f +; EABI-HARD-NEXT: vmov s0, r0 +; EABI-HARD-NEXT: vcvt.f64.f32 d0, s0 +; EABI-HARD-NEXT: pop {r11, lr} +; EABI-HARD-NEXT: mov pc, lr +; +; EABI-SOFT-LABEL: f16_to_f64: +; EABI-SOFT: @ %bb.0: +; EABI-SOFT-NEXT: .save {r11, lr} +; EABI-SOFT-NEXT: push {r11, lr} +; EABI-SOFT-NEXT: ldrh r0, [r0] +; EABI-SOFT-NEXT: bl __aeabi_h2f +; EABI-SOFT-NEXT: vmov s0, r0 +; EABI-SOFT-NEXT: vcvt.f64.f32 d0, s0 +; EABI-SOFT-NEXT: vmov r0, r1, d0 +; EABI-SOFT-NEXT: pop {r11, lr} +; EABI-SOFT-NEXT: mov pc, lr +; +; APCS-LABEL: f16_to_f64: +; APCS: @ %bb.0: +; APCS-NEXT: push {lr} +; APCS-NEXT: ldrh r0, [r0] +; APCS-NEXT: bl __gnu_h2f_ieee +; APCS-NEXT: vmov s0, r0 +; APCS-NEXT: vcvt.f64.f32 d16, s0 +; APCS-NEXT: vmov r0, r1, d16 +; APCS-NEXT: pop {lr} +; APCS-NEXT: bx lr + %load = load half, ptr %p + %cvt = fpext half %load to double + ret double %cvt +} + +define void @f64_to_f16(ptr %p, double %arg) #0 { +; AAPCS-HARD-LABEL: f64_to_f16: +; AAPCS-HARD: @ %bb.0: +; AAPCS-HARD-NEXT: .save {r4, lr} +; AAPCS-HARD-NEXT: push {r4, lr} +; AAPCS-HARD-NEXT: mov r4, r0 +; AAPCS-HARD-NEXT: vmov r0, r1, d0 +; AAPCS-HARD-NEXT: bl __aeabi_d2h +; AAPCS-HARD-NEXT: strh r0, [r4] +; AAPCS-HARD-NEXT: pop {r4, lr} +; AAPCS-HARD-NEXT: mov pc, lr +; +; AAPCS-SOFT-LABEL: f64_to_f16: +; AAPCS-SOFT: @ %bb.0: +; AAPCS-SOFT-NEXT: .save {r4, lr} +; AAPCS-SOFT-NEXT: push {r4, lr} +; AAPCS-SOFT-NEXT: mov r4, r0 +; AAPCS-SOFT-NEXT: mov r1, r3 +; AAPCS-SOFT-NEXT: mov r0, r2 +; AAPCS-SOFT-NEXT: bl __aeabi_d2h +; AAPCS-SOFT-NEXT: strh r0, [r4] +; AAPCS-SOFT-NEXT: pop {r4, lr} +; AAPCS-SOFT-NEXT: mov pc, lr +; +; APCS-LABEL: f64_to_f16: +; APCS: @ %bb.0: +; APCS-NEXT: push {r4, lr} +; APCS-NEXT: mov r4, r0 +; APCS-NEXT: mov r0, r1 +; APCS-NEXT: mov r1, r2 +; APCS-NEXT: bl __truncdfhf2 +; APCS-NEXT: strh r0, [r4] +; APCS-NEXT: pop {r4, pc} + %cvt = fptrunc double %arg to half + store half %cvt, ptr %p + ret void +} + +attributes #0 = { nounwind }