mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-27 13:40:30 +00:00
[ARM] Relax restriction on variadic functions for tailcall optimization
Summary: Variadic functions can be treated in the same way as normal functions with respect to the number and types of parameters. Reviewers: grosbach, olista01, t.p.northover, rengolin Subscribers: javed.absar, aemerson, llvm-commits Differential Revision: https://reviews.llvm.org/D26748 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@287219 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
92dbb1780d
commit
189d9909bf
@ -2314,11 +2314,6 @@ ARMTargetLowering::IsEligibleForTailCallOptimization(SDValue Callee,
|
||||
// Look for obvious safe cases to perform tail call optimization that do not
|
||||
// require ABI changes. This is what gcc calls sibcall.
|
||||
|
||||
// Do not sibcall optimize vararg calls unless the call site is not passing
|
||||
// any arguments.
|
||||
if (isVarArg && !Outs.empty())
|
||||
return false;
|
||||
|
||||
// Exception-handling functions need a special set of instructions to indicate
|
||||
// a return to the hardware. Tail-calling another function would probably
|
||||
// break this.
|
||||
|
49
test/CodeGen/ARM/tail-call-float.ll
Normal file
49
test/CodeGen/ARM/tail-call-float.ll
Normal file
@ -0,0 +1,49 @@
|
||||
; RUN: llc -mtriple armv7 -target-abi aapcs -float-abi soft -O0 -o - < %s \
|
||||
; RUN: | FileCheck %s -check-prefix CHECK-SOFT -check-prefix CHECK
|
||||
; RUN: llc -mtriple armv7 -target-abi aapcs -float-abi hard -O0 -o - < %s \
|
||||
; RUN: | FileCheck %s -check-prefix CHECK-HARD -check-prefix CHECK
|
||||
|
||||
; Tests for passing floating-point regs. Variadic functions will always use
|
||||
; general-purpose registers. Standard functions will use the floating-point
|
||||
; registers if there is hardware FP available.
|
||||
|
||||
declare i1 @non_variadic(float, float, float, float)
|
||||
declare i1 @non_variadic_big(float, float, float, float, float, float)
|
||||
declare i1 @variadic(float, ...)
|
||||
|
||||
define void @non_variadic_fp(float %x, float %y) {
|
||||
; CHECK-LABEL: non_variadic_fp:
|
||||
; CHECK: b non_variadic
|
||||
entry:
|
||||
%call = tail call i1 (float, float, float, float) @non_variadic(float %y, float %x, float %x, float %y)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @variadic_fp(float %x, float %y) {
|
||||
; CHECK-LABEL: variadic_fp:
|
||||
; CHECK: b variadic
|
||||
entry:
|
||||
%call = tail call i1 (float, ...) @variadic(float %y, float %x, float %x, float %y)
|
||||
ret void
|
||||
}
|
||||
|
||||
; With soft-float, general-purpose registers are used and there are not enough
|
||||
; of them to handle the 6 arguments. With hard-float, we have plenty of regs
|
||||
; (s0-s15) to pass FP arguments.
|
||||
define void @non_variadic_fp_big(float %x, float %y) {
|
||||
; CHECK-LABEL: non_variadic_fp_big:
|
||||
; CHECK-SOFT: bl non_variadic_big
|
||||
; CHECK-HARD: b non_variadic_big
|
||||
entry:
|
||||
%call = tail call i1 (float, float, float, float, float, float) @non_variadic_big(float %y, float %x, float %x, float %y, float %x, float %y)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Variadic functions cannot use FP regs to pass arguments; only GP regs.
|
||||
define void @variadic_fp_big(float %x, float %y) {
|
||||
; CHECK-LABEL: variadic_fp_big:
|
||||
; CHECK: bl variadic
|
||||
entry:
|
||||
%call = tail call i1 (float, ...) @variadic(float %y, float %x, float %x, float %y, float %x, float %y)
|
||||
ret void
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
; RUN: llc -mtriple armv7 -target-abi apcs -O0 -o - < %s \
|
||||
; RUN: | FileCheck %s -check-prefix CHECK-TAIL
|
||||
; RUN: | FileCheck %s -check-prefix CHECK-TAIL -check-prefix CHECK
|
||||
; RUN: llc -mtriple armv7 -target-abi apcs -O0 -disable-tail-calls -o - < %s \
|
||||
; RUN: | FileCheck %s -check-prefix CHECK-NO-TAIL
|
||||
; RUN: | FileCheck %s -check-prefix CHECK-NO-TAIL -check-prefix CHECK
|
||||
; RUN: llc -mtriple armv7 -target-abi aapcs -O0 -o - < %s \
|
||||
; RUN: | FileCheck %s -check-prefix CHECK-TAIL-AAPCS -check-prefix CHECK
|
||||
|
||||
declare i32 @callee(i32 %i)
|
||||
declare extern_weak fastcc void @callee_weak()
|
||||
@ -30,3 +32,69 @@ define fastcc void @caller_weak() {
|
||||
tail call void @callee_weak()
|
||||
ret void
|
||||
}
|
||||
|
||||
; A tail call can be optimized if all the arguments can be passed in registers
|
||||
; R0-R3, or the remaining arguments are already in the caller's parameter area
|
||||
; in the stack. Variadic functions are no different.
|
||||
declare i32 @variadic(i32, ...)
|
||||
|
||||
; e.g. four integers
|
||||
define void @v_caller_ints1(i32 %a, i32 %b) {
|
||||
; CHECK-LABEL: v_caller_ints1:
|
||||
; CHECK-TAIL: b variadic
|
||||
; CHECK-TAIL-AAPCS: b variadic
|
||||
; CHECK-NO-TAIL: bl variadic
|
||||
entry:
|
||||
%call = tail call i32 (i32, ...) @variadic(i32 %a, i32 %b, i32 %b, i32 %a)
|
||||
ret void
|
||||
}
|
||||
|
||||
; e.g. two 32-bit integers, one 64-bit integer (needs to span two regs)
|
||||
define void @v_caller_ints2(i32 %y, i64 %z) {
|
||||
; CHECK-LABEL: v_caller_ints2:
|
||||
; CHECK-TAIL: b variadic
|
||||
; CHECK-TAIL-AAPCS: b variadic
|
||||
; CHECK-NO-TAIL: bl variadic
|
||||
entry:
|
||||
%call = tail call i32 (i32, ...) @variadic(i32 %y, i32 %y, i64 %z)
|
||||
ret void
|
||||
}
|
||||
|
||||
; e.g. two 32-bit integers, one 64-bit integer (needs to span two regs). Notice
|
||||
; that %z is passed in r1-r2 if APCS is used, contrary to AAPCS where r2-r3
|
||||
; would be used (since double-word types must start at an even register). In the
|
||||
; latter case, the third argument needs to be passed through the stack.
|
||||
define void @v_caller_ints3(i32 %y, i64 %z) {
|
||||
; CHECK-LABEL: v_caller_ints3:
|
||||
; CHECK-TAIL: b variadic
|
||||
; CHECK-TAIL-AAPCS: bl variadic
|
||||
; CHECK-NO-TAIL: bl variadic
|
||||
entry:
|
||||
%call = tail call i32 (i32, ...) @variadic(i32 %y, i64 %z, i32 %y)
|
||||
ret void
|
||||
}
|
||||
|
||||
; e.g. two 32-bit integers, one 64-bit integer and another 64-bit integer that
|
||||
; doesn't fit in r0-r3 but comes from the caller argument list and is in the
|
||||
; same position.
|
||||
define void @v_caller_ints4(i64 %a, i32 %b, i32 %c, i64 %d) {
|
||||
; CHECK-LABEL: v_caller_ints4:
|
||||
; CHECK-TAIL: b variadic
|
||||
; CHECK-TAIL-AAPCS: b variadic
|
||||
; CHECK-NO-TAIL: bl variadic
|
||||
entry:
|
||||
%call = tail call i32 (i32, ...) @variadic(i32 %b, i32 %c, i64 %a, i64 %d)
|
||||
ret void
|
||||
}
|
||||
|
||||
; If the arguments do not fit in r0-r3 and the existing parameters cannot be
|
||||
; taken from the caller's parameter region, the optimization is not supported.
|
||||
|
||||
; e.g. one 32-bit integer, two 64-bit integers
|
||||
define void @v_caller_ints_fail(i32 %y, i64 %z) {
|
||||
; CHECK-LABEL: v_caller_ints_fail:
|
||||
; CHECK: bl variadic
|
||||
entry:
|
||||
%call = tail call i32 (i32, ...) @variadic(i32 %y, i64 %z, i64 %z)
|
||||
ret void
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user