mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
ARM / x86_64 varargs: Don't save regparms in prologue without va_start
There's no need to do this if the user doesn't call va_start. In the future, we're going to have thunks that forward these register parameters with musttail calls, and they won't need these spills for handling va_start. Most of the test suite changes are adding va_start calls to existing tests to keep things working. llvm-svn: 216294
This commit is contained in:
parent
78ec7d3e35
commit
60c1740ad6
@ -236,6 +236,9 @@ class MachineFrameInfo {
|
||||
/// pointer.
|
||||
bool HasInlineAsmWithSPAdjust;
|
||||
|
||||
/// True if the function contains a call to the llvm.vastart intrinsic.
|
||||
bool HasVAStart;
|
||||
|
||||
const TargetFrameLowering *getFrameLowering() const;
|
||||
public:
|
||||
explicit MachineFrameInfo(const TargetMachine &TM, bool RealignOpt)
|
||||
@ -256,6 +259,7 @@ public:
|
||||
LocalFrameMaxAlign = 0;
|
||||
UseLocalStackAllocationBlock = false;
|
||||
HasInlineAsmWithSPAdjust = false;
|
||||
HasVAStart = false;
|
||||
}
|
||||
|
||||
/// hasStackObjects - Return true if there are any stack objects in this
|
||||
@ -475,6 +479,10 @@ public:
|
||||
bool hasInlineAsmWithSPAdjust() const { return HasInlineAsmWithSPAdjust; }
|
||||
void setHasInlineAsmWithSPAdjust(bool B) { HasInlineAsmWithSPAdjust = B; }
|
||||
|
||||
/// Returns true if the function calls the llvm.va_start intrinsic.
|
||||
bool hasVAStart() const { return HasVAStart; }
|
||||
void setHasVAStart(bool B) { HasVAStart = B; }
|
||||
|
||||
/// getMaxCallFrameSize - Return the maximum size of a call frame that must be
|
||||
/// allocated for an outgoing function call. This is only available if
|
||||
/// CallFrameSetup/Destroy pseudo instructions are used by the target, and
|
||||
|
@ -138,6 +138,14 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf,
|
||||
}
|
||||
}
|
||||
|
||||
// Look for calls to the @llvm.va_start intrinsic. We can omit some
|
||||
// prologue boilerplate for variadic functions that don't examine their
|
||||
// arguments.
|
||||
if (const auto *II = dyn_cast<IntrinsicInst>(I)) {
|
||||
if (II->getIntrinsicID() == Intrinsic::vastart)
|
||||
MF->getFrameInfo()->setHasVAStart(true);
|
||||
}
|
||||
|
||||
// Mark values used outside their block as exported, by allocating
|
||||
// a virtual register for them.
|
||||
if (isUsedOutsideOfDefiningBlock(I))
|
||||
|
@ -3080,7 +3080,7 @@ ARMTargetLowering::LowerFormalArguments(SDValue Chain,
|
||||
}
|
||||
CCInfo.rewindByValRegsInfo();
|
||||
lastInsIndex = -1;
|
||||
if (isVarArg) {
|
||||
if (isVarArg && MFI->hasVAStart()) {
|
||||
unsigned ExtraArgRegsSize;
|
||||
unsigned ExtraArgRegsSaveSize;
|
||||
computeRegArea(CCInfo, MF, CCInfo.getInRegsParamsCount(), 0,
|
||||
@ -3222,7 +3222,7 @@ ARMTargetLowering::LowerFormalArguments(SDValue Chain,
|
||||
}
|
||||
|
||||
// varargs
|
||||
if (isVarArg)
|
||||
if (isVarArg && MFI->hasVAStart())
|
||||
VarArgStyleRegisters(CCInfo, DAG, dl, Chain,
|
||||
CCInfo.getNextStackOffset(),
|
||||
TotalArgRegsSaveSize);
|
||||
|
@ -2405,8 +2405,9 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain,
|
||||
StackSize = GetAlignedArgumentStackSize(StackSize, DAG);
|
||||
|
||||
// If the function takes variable number of arguments, make a frame index for
|
||||
// the start of the first vararg value... for expansion of llvm.va_start.
|
||||
if (isVarArg) {
|
||||
// the start of the first vararg value... for expansion of llvm.va_start. We
|
||||
// can skip this if there are no va_start calls.
|
||||
if (isVarArg && MFI->hasVAStart()) {
|
||||
if (Is64Bit || (CallConv != CallingConv::X86_FastCall &&
|
||||
CallConv != CallingConv::X86_ThisCall)) {
|
||||
FuncInfo->setVarArgsFrameIndex(MFI->CreateFixedObject(1, StackSize,true));
|
||||
|
@ -183,6 +183,7 @@ define void @test_varsize(...) minsize {
|
||||
; CHECK: bx lr
|
||||
|
||||
%var = alloca i8, i32 8
|
||||
call void @llvm.va_start(i8* %var)
|
||||
call void @bar(i8* %var)
|
||||
ret void
|
||||
}
|
||||
@ -216,3 +217,5 @@ if.then: ; preds = %entry
|
||||
exit: ; preds = %if.then, %entry
|
||||
ret float %call1
|
||||
}
|
||||
|
||||
declare void @llvm.va_start(i8*) nounwind
|
||||
|
@ -46,6 +46,7 @@ entry:
|
||||
store <4 x i32> <i32 42, i32 42, i32 42, i32 42>, <4 x i32>* %b, align 16
|
||||
store <4 x i32> <i32 0, i32 1, i32 2, i32 3>, <4 x i32>* %a, align 16
|
||||
%0 = load <4 x i32>* %a, align 16
|
||||
call void @llvm.va_start(i8* null)
|
||||
ret <4 x i32> %0
|
||||
|
||||
; Epilogue
|
||||
@ -154,6 +155,7 @@ entry:
|
||||
%7 = load i32* %d, align 4
|
||||
%add5 = add nsw i32 %add4, %7
|
||||
%add6 = add nsw i32 %add5, %i
|
||||
call void @llvm.va_start(i8* null)
|
||||
ret i32 %add6
|
||||
|
||||
; Epilogue
|
||||
@ -198,7 +200,8 @@ entry:
|
||||
; CHECK-V5T: sub sp,
|
||||
; CHECK-V5T: push {[[SAVED:(r[4567](, )?)+]], lr}
|
||||
|
||||
ret i32 %i;
|
||||
call void @llvm.va_start(i8* null)
|
||||
ret i32 %i;
|
||||
; Epilogue
|
||||
; --------
|
||||
; CHECK-V4T: pop {[[SAVED]]}
|
||||
@ -210,3 +213,5 @@ entry:
|
||||
; CHECK-V5T-NEXT: add sp,
|
||||
; CHECK-V5T-NEXT: bx r3
|
||||
}
|
||||
|
||||
declare void @llvm.va_start(i8*) nounwind
|
||||
|
10
test/CodeGen/ARM/vararg_no_start.ll
Normal file
10
test/CodeGen/ARM/vararg_no_start.ll
Normal file
@ -0,0 +1,10 @@
|
||||
; RUN: llc -mtriple=arm-darwin < %s | FileCheck %s
|
||||
; RUN: llc -O0 -mtriple=arm-darwin < %s | FileCheck %s
|
||||
|
||||
define void @foo(i8*, ...) {
|
||||
ret void
|
||||
}
|
||||
; CHECK-LABEL: {{^_?}}foo:
|
||||
; CHECK-NOT: str
|
||||
; CHECK: {{bx lr|mov pc, lr}}
|
||||
declare void @llvm.va_start(i8*) nounwind
|
@ -10,6 +10,7 @@ entry:
|
||||
store i32 0, i32* %tmp
|
||||
%tmp1 = load i32* %tmp ; <i32> [#uses=1]
|
||||
store i32 %tmp1, i32* %retval
|
||||
call void @llvm.va_start(i8* null)
|
||||
br label %return
|
||||
|
||||
return: ; preds = %entry
|
||||
@ -20,3 +21,5 @@ return: ; preds = %entry
|
||||
; OABI: add sp, sp, #12
|
||||
; OABI: add sp, sp, #12
|
||||
}
|
||||
|
||||
declare void @llvm.va_start(i8*) nounwind
|
||||
|
@ -7,7 +7,9 @@ define void @t(i8* %a, ...) nounwind {
|
||||
; CHECK-NEXT: add sp, #12
|
||||
; CHECK-NEXT: bx r3
|
||||
entry:
|
||||
%a.addr = alloca i8*
|
||||
store i8* %a, i8** %a.addr
|
||||
%a.addr = alloca i8, i32 4
|
||||
call void @llvm.va_start(i8* %a.addr)
|
||||
ret void
|
||||
}
|
||||
|
||||
declare void @llvm.va_start(i8*) nounwind
|
||||
|
@ -13,6 +13,7 @@ entry:
|
||||
; CHECK-NOT: mov sp, r7
|
||||
; CHECK: add sp, #8
|
||||
call void @__gcov_flush() nounwind
|
||||
call void @llvm.va_start(i8* null)
|
||||
br i1 undef, label %bb5, label %bb
|
||||
|
||||
bb: ; preds = %bb, %entry
|
||||
@ -27,3 +28,5 @@ bb5: ; preds = %bb, %entry
|
||||
declare hidden void @__gcov_flush()
|
||||
|
||||
declare i32 @execvp(i8*, i8**) nounwind
|
||||
|
||||
declare void @llvm.va_start(i8*) nounwind
|
||||
|
9
test/CodeGen/X86/vararg_no_start.ll
Normal file
9
test/CodeGen/X86/vararg_no_start.ll
Normal file
@ -0,0 +1,9 @@
|
||||
; RUN: llc -mtriple=x86_64-linux < %s | FileCheck %s
|
||||
; RUN: llc -mtriple=x86_64-windows-msvc < %s | FileCheck %s
|
||||
|
||||
define void @foo(i8*, ...) {
|
||||
ret void
|
||||
}
|
||||
; CHECK-LABEL: {{^_?}}foo:
|
||||
; CHECK-NOT: movq
|
||||
; CHECK: retq
|
@ -14,6 +14,7 @@ entry:
|
||||
br i1 %tobool, label %if.end, label %if.then
|
||||
|
||||
if.then: ; preds = %entry
|
||||
call void @llvm.va_start(i8* null)
|
||||
br label %if.end
|
||||
|
||||
if.end: ; preds = %entry, %if.then
|
||||
@ -21,3 +22,4 @@ if.end: ; preds = %entry, %if.then
|
||||
ret i32 %hasflag
|
||||
}
|
||||
|
||||
declare void @llvm.va_start(i8*) nounwind
|
||||
|
Loading…
Reference in New Issue
Block a user