
The ARM backend was checking that the outgoing values for a tail-call matched the incoming argument values of the caller. This isn't necessary, because the caller can change the values in both registers and the stack before doing the tail-call. The actual limitation is that the callee can't need more stack space for it's arguments than the caller does. This is needed for code using the musttail attribute, as well as enabling tail calls as an optimisation in more cases.
214 lines
7.0 KiB
LLVM
214 lines
7.0 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc -mtriple=armv8a -mattr=+armv8.2-a,+fullfp16,+neon -target-abi=aapcs-gnu -float-abi=soft -o - %s | FileCheck %s --check-prefix=SOFT
|
|
; RUN: llc -mtriple=armv8a -mattr=+armv8.2-a,+fullfp16,+neon -target-abi=aapcs-gnu -float-abi=hard -o - %s | FileCheck %s --check-prefix=HARD
|
|
; RUN: llc -mtriple=armeb-eabi -mattr=+armv8.2-a,+fullfp16,+neon -target-abi=aapcs-gnu -float-abi=soft -o - %s | FileCheck %s --check-prefix=SOFTEB
|
|
; RUN: llc -mtriple=armeb-eabi -mattr=+armv8.2-a,+fullfp16,+neon -target-abi=aapcs-gnu -float-abi=hard -o - %s | FileCheck %s --check-prefix=HARDEB
|
|
|
|
declare <4 x half> @llvm.fabs.v4f16(<4 x half>)
|
|
declare <8 x half> @llvm.fabs.v8f16(<8 x half>)
|
|
declare void @use(double, float, <4 x half>, i16, <8 x half>)
|
|
define <4 x half> @test_vabs_f16(<4 x half> %a) {
|
|
; SOFT-LABEL: test_vabs_f16:
|
|
; SOFT: @ %bb.0: @ %entry
|
|
; SOFT-NEXT: vmov d16, r0, r1
|
|
; SOFT-NEXT: vabs.f16 d16, d16
|
|
; SOFT-NEXT: vmov r0, r1, d16
|
|
; SOFT-NEXT: bx lr
|
|
;
|
|
; HARD-LABEL: test_vabs_f16:
|
|
; HARD: @ %bb.0: @ %entry
|
|
; HARD-NEXT: vabs.f16 d0, d0
|
|
; HARD-NEXT: bx lr
|
|
;
|
|
; SOFTEB-LABEL: test_vabs_f16:
|
|
; SOFTEB: @ %bb.0: @ %entry
|
|
; SOFTEB-NEXT: vmov d16, r1, r0
|
|
; SOFTEB-NEXT: vrev64.16 d16, d16
|
|
; SOFTEB-NEXT: vabs.f16 d16, d16
|
|
; SOFTEB-NEXT: vrev64.16 d16, d16
|
|
; SOFTEB-NEXT: vmov r1, r0, d16
|
|
; SOFTEB-NEXT: bx lr
|
|
;
|
|
; HARDEB-LABEL: test_vabs_f16:
|
|
; HARDEB: @ %bb.0: @ %entry
|
|
; HARDEB-NEXT: vrev64.16 d16, d0
|
|
; HARDEB-NEXT: vabs.f16 d16, d16
|
|
; HARDEB-NEXT: vrev64.16 d0, d16
|
|
; HARDEB-NEXT: bx lr
|
|
entry:
|
|
%vabs1.i = tail call <4 x half> @llvm.fabs.v4f16(<4 x half> %a)
|
|
ret <4 x half> %vabs1.i
|
|
}
|
|
|
|
|
|
define <8 x half> @test2_vabs_f16(<8 x half> %a) {
|
|
; SOFT-LABEL: test2_vabs_f16:
|
|
; SOFT: @ %bb.0: @ %entry
|
|
; SOFT-NEXT: vmov d17, r2, r3
|
|
; SOFT-NEXT: vmov d16, r0, r1
|
|
; SOFT-NEXT: vabs.f16 q8, q8
|
|
; SOFT-NEXT: vmov r0, r1, d16
|
|
; SOFT-NEXT: vmov r2, r3, d17
|
|
; SOFT-NEXT: bx lr
|
|
;
|
|
; HARD-LABEL: test2_vabs_f16:
|
|
; HARD: @ %bb.0: @ %entry
|
|
; HARD-NEXT: vabs.f16 q0, q0
|
|
; HARD-NEXT: bx lr
|
|
;
|
|
; SOFTEB-LABEL: test2_vabs_f16:
|
|
; SOFTEB: @ %bb.0: @ %entry
|
|
; SOFTEB-NEXT: vmov d17, r3, r2
|
|
; SOFTEB-NEXT: vmov d16, r1, r0
|
|
; SOFTEB-NEXT: vrev64.16 q8, q8
|
|
; SOFTEB-NEXT: vabs.f16 q8, q8
|
|
; SOFTEB-NEXT: vrev64.16 q8, q8
|
|
; SOFTEB-NEXT: vmov r1, r0, d16
|
|
; SOFTEB-NEXT: vmov r3, r2, d17
|
|
; SOFTEB-NEXT: bx lr
|
|
;
|
|
; HARDEB-LABEL: test2_vabs_f16:
|
|
; HARDEB: @ %bb.0: @ %entry
|
|
; HARDEB-NEXT: vrev64.16 q8, q0
|
|
; HARDEB-NEXT: vabs.f16 q8, q8
|
|
; HARDEB-NEXT: vrev64.16 q0, q8
|
|
; HARDEB-NEXT: bx lr
|
|
entry:
|
|
%vabs1.i = tail call <8 x half> @llvm.fabs.v8f16(<8 x half> %a)
|
|
ret <8 x half> %vabs1.i
|
|
}
|
|
|
|
define void @test(double, float, i16, <4 x half>, <8 x half>) {
|
|
; SOFT-LABEL: test:
|
|
; SOFT: @ %bb.0: @ %entry
|
|
; SOFT-NEXT: push {r11, lr}
|
|
; SOFT-NEXT: sub sp, sp, #32
|
|
; SOFT-NEXT: add r12, sp, #48
|
|
; SOFT-NEXT: vld1.64 {d16, d17}, [r12]
|
|
; SOFT-NEXT: add r12, sp, #16
|
|
; SOFT-NEXT: vabs.f16 q8, q8
|
|
; SOFT-NEXT: vst1.64 {d16, d17}, [r12]
|
|
; SOFT-NEXT: mov r12, sp
|
|
; SOFT-NEXT: vldr d16, [sp, #40]
|
|
; SOFT-NEXT: vabs.f16 d16, d16
|
|
; SOFT-NEXT: vst1.16 {d16}, [r12:64]!
|
|
; SOFT-NEXT: str r3, [r12]
|
|
; SOFT-NEXT: bl use
|
|
; SOFT-NEXT: add sp, sp, #32
|
|
; SOFT-NEXT: pop {r11, pc}
|
|
;
|
|
; HARD-LABEL: test:
|
|
; HARD: @ %bb.0: @ %entry
|
|
; HARD-NEXT: vabs.f16 q2, q2
|
|
; HARD-NEXT: vabs.f16 d2, d2
|
|
; HARD-NEXT: b use
|
|
;
|
|
; SOFTEB-LABEL: test:
|
|
; SOFTEB: @ %bb.0: @ %entry
|
|
; SOFTEB-NEXT: .save {r4, lr}
|
|
; SOFTEB-NEXT: push {r4, lr}
|
|
; SOFTEB-NEXT: .pad #32
|
|
; SOFTEB-NEXT: sub sp, sp, #32
|
|
; SOFTEB-NEXT: vldr d16, [sp, #40]
|
|
; SOFTEB-NEXT: mov lr, sp
|
|
; SOFTEB-NEXT: add r4, sp, #48
|
|
; SOFTEB-NEXT: add r12, sp, #16
|
|
; SOFTEB-NEXT: vrev64.16 d16, d16
|
|
; SOFTEB-NEXT: vabs.f16 d16, d16
|
|
; SOFTEB-NEXT: vst1.16 {d16}, [lr:64]!
|
|
; SOFTEB-NEXT: vld1.64 {d16, d17}, [r4]
|
|
; SOFTEB-NEXT: vrev64.16 q8, q8
|
|
; SOFTEB-NEXT: str r3, [lr]
|
|
; SOFTEB-NEXT: vabs.f16 q8, q8
|
|
; SOFTEB-NEXT: vrev64.16 q8, q8
|
|
; SOFTEB-NEXT: vst1.64 {d16, d17}, [r12]
|
|
; SOFTEB-NEXT: bl use
|
|
; SOFTEB-NEXT: add sp, sp, #32
|
|
; SOFTEB-NEXT: pop {r4, pc}
|
|
;
|
|
; HARDEB-LABEL: test:
|
|
; HARDEB: @ %bb.0: @ %entry
|
|
; HARDEB-NEXT: vrev64.16 d16, d2
|
|
; HARDEB-NEXT: vabs.f16 d16, d16
|
|
; HARDEB-NEXT: vrev64.16 d2, d16
|
|
; HARDEB-NEXT: vrev64.16 q8, q2
|
|
; HARDEB-NEXT: vabs.f16 q8, q8
|
|
; HARDEB-NEXT: vrev64.16 q2, q8
|
|
; HARDEB-NEXT: b use
|
|
entry:
|
|
%5 = tail call <4 x half> @llvm.fabs.v4f16(<4 x half> %3)
|
|
%6 = tail call <8 x half> @llvm.fabs.v8f16(<8 x half> %4)
|
|
tail call void @use(double %0, float %1, <4 x half> %5, i16 %2, <8 x half> %6)
|
|
ret void
|
|
}
|
|
|
|
define void @many_args_test(double, float, i16, <4 x half>, <8 x half>, <8 x half>, <8 x half>) {
|
|
; SOFT-LABEL: many_args_test:
|
|
; SOFT: @ %bb.0: @ %entry
|
|
; SOFT-NEXT: add r12, sp, #40
|
|
; SOFT-NEXT: vld1.64 {d16, d17}, [r12]
|
|
; SOFT-NEXT: add r12, sp, #8
|
|
; SOFT-NEXT: vabs.f16 q8, q8
|
|
; SOFT-NEXT: vld1.64 {d18, d19}, [r12]
|
|
; SOFT-NEXT: add r12, sp, #24
|
|
; SOFT-NEXT: vadd.f16 q8, q8, q9
|
|
; SOFT-NEXT: vld1.64 {d18, d19}, [r12]
|
|
; SOFT-NEXT: add r12, sp, #16
|
|
; SOFT-NEXT: vmul.f16 q8, q9, q8
|
|
; SOFT-NEXT: vst1.64 {d16, d17}, [r12]
|
|
; SOFT-NEXT: vldr d16, [sp]
|
|
; SOFT-NEXT: vstr d16, [sp]
|
|
; SOFT-NEXT: str r3, [sp, #8]
|
|
; SOFT-NEXT: b use
|
|
;
|
|
; HARD-LABEL: many_args_test:
|
|
; HARD: @ %bb.0: @ %entry
|
|
; HARD-NEXT: mov r1, sp
|
|
; HARD-NEXT: vld1.64 {d16, d17}, [r1]
|
|
; HARD-NEXT: vabs.f16 q8, q8
|
|
; HARD-NEXT: vadd.f16 q8, q8, q2
|
|
; HARD-NEXT: vmul.f16 q2, q3, q8
|
|
; HARD-NEXT: b use
|
|
;
|
|
; SOFTEB-LABEL: many_args_test:
|
|
; SOFTEB: @ %bb.0: @ %entry
|
|
; SOFTEB-NEXT: add r12, sp, #40
|
|
; SOFTEB-NEXT: vld1.64 {d16, d17}, [r12]
|
|
; SOFTEB-NEXT: add r12, sp, #8
|
|
; SOFTEB-NEXT: vrev64.16 q8, q8
|
|
; SOFTEB-NEXT: vabs.f16 q8, q8
|
|
; SOFTEB-NEXT: vld1.64 {d18, d19}, [r12]
|
|
; SOFTEB-NEXT: add r12, sp, #24
|
|
; SOFTEB-NEXT: vrev64.16 q9, q9
|
|
; SOFTEB-NEXT: vadd.f16 q8, q8, q9
|
|
; SOFTEB-NEXT: vld1.64 {d18, d19}, [r12]
|
|
; SOFTEB-NEXT: add r12, sp, #16
|
|
; SOFTEB-NEXT: vrev64.16 q9, q9
|
|
; SOFTEB-NEXT: vmul.f16 q8, q9, q8
|
|
; SOFTEB-NEXT: vldr d18, [sp]
|
|
; SOFTEB-NEXT: vrev64.16 q8, q8
|
|
; SOFTEB-NEXT: vst1.64 {d16, d17}, [r12]
|
|
; SOFTEB-NEXT: vstr d18, [sp]
|
|
; SOFTEB-NEXT: str r3, [sp, #8]
|
|
; SOFTEB-NEXT: b use
|
|
;
|
|
; HARDEB-LABEL: many_args_test:
|
|
; HARDEB: @ %bb.0: @ %entry
|
|
; HARDEB-NEXT: mov r1, sp
|
|
; HARDEB-NEXT: vld1.64 {d16, d17}, [r1]
|
|
; HARDEB-NEXT: vrev64.16 q8, q8
|
|
; HARDEB-NEXT: vabs.f16 q8, q8
|
|
; HARDEB-NEXT: vrev64.16 q9, q2
|
|
; HARDEB-NEXT: vadd.f16 q8, q8, q9
|
|
; HARDEB-NEXT: vrev64.16 q9, q3
|
|
; HARDEB-NEXT: vmul.f16 q8, q9, q8
|
|
; HARDEB-NEXT: vrev64.16 q2, q8
|
|
; HARDEB-NEXT: b use
|
|
entry:
|
|
%7 = tail call <8 x half> @llvm.fabs.v8f16(<8 x half> %6)
|
|
%8 = fadd <8 x half> %7, %4
|
|
%9 = fmul <8 x half> %5, %8
|
|
tail call void @use(double %0, float %1, <4 x half> %3, i16 %2, <8 x half> %9)
|
|
ret void
|
|
}
|