ARM / x86_64 varargs: Don't save regparms in prologue without va_start
authorReid Kleckner <reid@kleckner.net>
Fri, 22 Aug 2014 21:59:26 +0000 (21:59 +0000)
committerReid Kleckner <reid@kleckner.net>
Fri, 22 Aug 2014 21:59:26 +0000 (21:59 +0000)
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

12 files changed:
include/llvm/CodeGen/MachineFrameInfo.h
lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
lib/Target/ARM/ARMISelLowering.cpp
lib/Target/X86/X86ISelLowering.cpp
test/CodeGen/ARM/fold-stack-adjust.ll
test/CodeGen/ARM/thumb1_return_sequence.ll
test/CodeGen/ARM/vararg_no_start.ll [new file with mode: 0644]
test/CodeGen/ARM/vargs_align.ll
test/CodeGen/Thumb/pop.ll
test/CodeGen/Thumb2/2009-08-06-SpDecBug.ll
test/CodeGen/X86/vararg_no_start.ll [new file with mode: 0644]
test/CodeGen/X86/vastart-defs-eflags.ll

index 79a82497661e47555ba185d1f2f5305583db4e96..dca809177d4b07a2b62cb8614a64b144bd9e7235 100644 (file)
@@ -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
index 1c85248eb846602b01f68a2df7f9c1597cf6c038..c9da6fd83eed2b08766640785865198df591ad28 100644 (file)
@@ -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))
index 42c8f202e0faf1e60530754c39538fe6e40d4b3d..f5355833a34c26c27b13bec5497ae7cdeb0c2f4b 100644 (file)
@@ -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);
index afcabdcda7eb87555e92478f18d8114879606f30..a685fdb6c7ee285582b2659b5390f2afacfbd5a0 100644 (file)
@@ -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));
index 1d10464017cee398a1e7f82312c41350b30659c9..514d4a9fccb9d543270a43d2f75a062e4eddfab8 100644 (file)
@@ -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
index ab08379a24831de739e70693068bc25122395109..318e6e4023702636b992b848b2872f8bf2d06e41 100644 (file)
@@ -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
diff --git a/test/CodeGen/ARM/vararg_no_start.ll b/test/CodeGen/ARM/vararg_no_start.ll
new file mode 100644 (file)
index 0000000..f9c8c1b
--- /dev/null
@@ -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
index e390cf051443387400ff45274deb14cec10822ad..3abb57ee51f8ee3d09ed0521e815bde83417abc2 100644 (file)
@@ -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
index 1e45c7f37bcbfb71b2e9056246a2f10b29f8f6b8..3c539c69017089bbf7e6ccdd85ab12a28943eba5 100644 (file)
@@ -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
index c8eac8d4d0941ed3189c875e69d02950aec07466..59c236732118d3c85cb612efb8308d1bfa25906a 100644 (file)
@@ -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 (file)
index 0000000..ab5c6fc
--- /dev/null
@@ -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
index 6017753fc8fde0cac0dea87290026edbdef7e75e..d0c515089f48dd434744ec5627698c338056367d 100644 (file)
@@ -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