Index: llvm/lib/Target/X86/X86ISelLowering.h =================================================================== --- llvm/lib/Target/X86/X86ISelLowering.h +++ llvm/lib/Target/X86/X86ISelLowering.h @@ -1436,7 +1436,7 @@ SDValue LowerMemOpCallTo(SDValue Chain, SDValue StackPtr, SDValue Arg, const SDLoc &dl, SelectionDAG &DAG, const CCValAssign &VA, - ISD::ArgFlagsTy Flags) const; + ISD::ArgFlagsTy Flags, bool hasCopy) const; // Call lowering helpers. Index: llvm/lib/Target/X86/X86ISelLowering.cpp =================================================================== --- llvm/lib/Target/X86/X86ISelLowering.cpp +++ llvm/lib/Target/X86/X86ISelLowering.cpp @@ -3763,12 +3763,15 @@ SDValue Arg, const SDLoc &dl, SelectionDAG &DAG, const CCValAssign &VA, - ISD::ArgFlagsTy Flags) const { + ISD::ArgFlagsTy Flags, + bool hasCopy) const { unsigned LocMemOffset = VA.getLocMemOffset(); SDValue PtrOff = DAG.getIntPtrConstant(LocMemOffset, dl); PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(DAG.getDataLayout()), StackPtr, PtrOff); - if (Flags.isByVal()) + // If the argument already has a copy on the stack, we do not need to + // creating a temporary stack slot, again. + if (Flags.isByVal() && !hasCopy) return CreateCopyOfByValArgument(Arg, PtrOff, Chain, Flags, DAG, dl); return DAG.getStore( @@ -4080,7 +4083,7 @@ StackPtr = DAG.getCopyFromReg(Chain, dl, RegInfo->getStackRegister(), getPointerTy(DAG.getDataLayout())); MemOpChains.push_back(LowerMemOpCallTo(Chain, StackPtr, Arg, - dl, DAG, VA, Flags)); + dl, DAG, VA, Flags, !isByVal)); } } Index: llvm/test/CodeGen/X86/win64-byval.ll =================================================================== --- llvm/test/CodeGen/X86/win64-byval.ll +++ llvm/test/CodeGen/X86/win64-byval.ll @@ -32,3 +32,31 @@ call void @foo({ float, double }* byval %arg) ret void } + +declare void @foo2({ float, double }* byval, { float, double }* byval, { float, double }* byval, { float, double }* byval, { float, double }* byval, i64 %f) +@data = external constant { float, double } + +define void @test() { +; CHECK-LABEL: @test +; CHECK: movq (%rax), %rcx +; CHECK-NEXT: movq 8(%rax), %rax +; CHECK-NEXT: movq %rax, 120(%rsp) +; CHECK-NEXT: movq %rcx, 112(%rsp) +; CHECK-NEXT: movq %rcx, 96(%rsp) +; CHECK-NEXT: movq %rax, 104(%rsp) +; CHECK-NEXT: movq %rcx, 80(%rsp) +; CHECK-NEXT: movq %rax, 88(%rsp) +; CHECK-NEXT: movq %rcx, 64(%rsp) +; CHECK-NEXT: movq %rax, 72(%rsp) +; CHECK-NEXT: movq %rax, 56(%rsp) +; CHECK-NEXT: movq %rcx, 48(%rsp) +; CHECK-NEXT: leaq 48(%rsp), %rax +; CHECK-NEXT: movq %rax, 32(%rsp) +; CHECK-NEXT: movq $10, 40(%rsp) +; CHECK-NEXT: leaq 112(%rsp), %rcx +; CHECK-NEXT: leaq 96(%rsp), %rdx +; CHECK-NEXT: leaq 80(%rsp), %r8 +; CHECK-NEXT: leaq 64(%rsp), %r9 + call void @foo2({ float, double }* byval @G, { float, double }* byval @G, { float, double }* byval @G, { float, double }* byval @G, { float, double }* byval @G, i64 10) + ret void +}