From d89c0abc0724945e3181f3aaef023b292e53baad Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Fri, 22 Aug 2014 21:59:26 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@216294 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/MachineFrameInfo.h | 8 ++++++++ lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp | 8 ++++++++ lib/Target/ARM/ARMISelLowering.cpp | 4 ++-- lib/Target/X86/X86ISelLowering.cpp | 5 +++-- test/CodeGen/ARM/fold-stack-adjust.ll | 3 +++ test/CodeGen/ARM/thumb1_return_sequence.ll | 7 ++++++- test/CodeGen/ARM/vararg_no_start.ll | 10 ++++++++++ test/CodeGen/ARM/vargs_align.ll | 3 +++ test/CodeGen/Thumb/pop.ll | 6 ++++-- test/CodeGen/Thumb2/2009-08-06-SpDecBug.ll | 3 +++ test/CodeGen/X86/vararg_no_start.ll | 9 +++++++++ test/CodeGen/X86/vastart-defs-eflags.ll | 2 ++ 12 files changed, 61 insertions(+), 7 deletions(-) create mode 100644 test/CodeGen/ARM/vararg_no_start.ll create mode 100644 test/CodeGen/X86/vararg_no_start.ll diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h index 79a82497661..dca809177d4 100644 --- a/include/llvm/CodeGen/MachineFrameInfo.h +++ b/include/llvm/CodeGen/MachineFrameInfo.h @@ -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 diff --git a/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp index 1c85248eb84..c9da6fd83ee 100644 --- a/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +++ b/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -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(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)) diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 42c8f202e0f..f5355833a34 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -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); diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index afcabdcda7e..a685fdb6c7e 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -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)); diff --git a/test/CodeGen/ARM/fold-stack-adjust.ll b/test/CodeGen/ARM/fold-stack-adjust.ll index 1d10464017c..514d4a9fccb 100644 --- a/test/CodeGen/ARM/fold-stack-adjust.ll +++ b/test/CodeGen/ARM/fold-stack-adjust.ll @@ -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 diff --git a/test/CodeGen/ARM/thumb1_return_sequence.ll b/test/CodeGen/ARM/thumb1_return_sequence.ll index ab08379a248..318e6e40237 100644 --- a/test/CodeGen/ARM/thumb1_return_sequence.ll +++ b/test/CodeGen/ARM/thumb1_return_sequence.ll @@ -46,6 +46,7 @@ entry: store <4 x i32> , <4 x i32>* %b, align 16 store <4 x i32> , <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 diff --git a/test/CodeGen/ARM/vararg_no_start.ll b/test/CodeGen/ARM/vararg_no_start.ll new file mode 100644 index 00000000000..f9c8c1b7546 --- /dev/null +++ b/test/CodeGen/ARM/vararg_no_start.ll @@ -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 diff --git a/test/CodeGen/ARM/vargs_align.ll b/test/CodeGen/ARM/vargs_align.ll index e390cf05144..3abb57ee51f 100644 --- a/test/CodeGen/ARM/vargs_align.ll +++ b/test/CodeGen/ARM/vargs_align.ll @@ -10,6 +10,7 @@ entry: store i32 0, i32* %tmp %tmp1 = load i32* %tmp ; [#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 diff --git a/test/CodeGen/Thumb/pop.ll b/test/CodeGen/Thumb/pop.ll index 1e45c7f37bc..3c539c69017 100644 --- a/test/CodeGen/Thumb/pop.ll +++ b/test/CodeGen/Thumb/pop.ll @@ -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 diff --git a/test/CodeGen/Thumb2/2009-08-06-SpDecBug.ll b/test/CodeGen/Thumb2/2009-08-06-SpDecBug.ll index c8eac8d4d09..59c23673211 100644 --- a/test/CodeGen/Thumb2/2009-08-06-SpDecBug.ll +++ b/test/CodeGen/Thumb2/2009-08-06-SpDecBug.ll @@ -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 diff --git a/test/CodeGen/X86/vararg_no_start.ll b/test/CodeGen/X86/vararg_no_start.ll new file mode 100644 index 00000000000..ab5c6fc58aa --- /dev/null +++ b/test/CodeGen/X86/vararg_no_start.ll @@ -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 diff --git a/test/CodeGen/X86/vastart-defs-eflags.ll b/test/CodeGen/X86/vastart-defs-eflags.ll index 6017753fc8f..d0c515089f4 100644 --- a/test/CodeGen/X86/vastart-defs-eflags.ll +++ b/test/CodeGen/X86/vastart-defs-eflags.ll @@ -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 -- 2.40.0