Index: llvm/lib/Target/X86/X86CallingConv.cpp =================================================================== --- llvm/lib/Target/X86/X86CallingConv.cpp +++ llvm/lib/Target/X86/X86CallingConv.cpp @@ -64,6 +64,15 @@ return true; } +static bool NotEnoughRemaingRegisters(ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + static const MCPhysReg RegList[] = {X86::RDI, X86::RSI, X86::RDX, + X86::RCX, X86::R8, X86::R9}; + static const unsigned NumRegs = sizeof(RegList) / sizeof(RegList[0]); + unsigned FirstFree = State.getFirstUnallocated(RegList); + return FirstFree + 1 >= NumRegs; +} + static ArrayRef CC_X86_VectorCallGetSSEs(const MVT &ValVT) { if (ValVT.is512BitVector()) { static const MCPhysReg RegListZMM[] = {X86::ZMM0, X86::ZMM1, X86::ZMM2, Index: llvm/lib/Target/X86/X86CallingConv.td =================================================================== --- llvm/lib/Target/X86/X86CallingConv.td +++ llvm/lib/Target/X86/X86CallingConv.td @@ -542,6 +542,7 @@ // The first 6 integer arguments are passed in integer registers. CCIfType<[i32], CCAssignToReg<[EDI, ESI, EDX, ECX, R8D, R9D]>>, + CCIfConsecutiveRegs>>, CCIfType<[i64], CCAssignToReg<[RDI, RSI, RDX, RCX, R8 , R9 ]>>, // The first 8 MMX vector arguments are passed in XMM registers on Darwin. Index: llvm/lib/Target/X86/X86ISelLowering.h =================================================================== --- llvm/lib/Target/X86/X86ISelLowering.h +++ llvm/lib/Target/X86/X86ISelLowering.h @@ -1424,6 +1424,10 @@ bool supportSwiftError() const override; + bool functionArgumentNeedsConsecutiveRegisters( + Type *Ty, CallingConv::ID CallConv, bool isVarArg, + const DataLayout &DL) const override; + bool hasStackProbeSymbol(MachineFunction &MF) const override; bool hasInlineStackProbe(MachineFunction &MF) const override; StringRef getStackProbeSymbolName(MachineFunction &MF) const override; Index: llvm/lib/Target/X86/X86ISelLowering.cpp =================================================================== --- llvm/lib/Target/X86/X86ISelLowering.cpp +++ llvm/lib/Target/X86/X86ISelLowering.cpp @@ -53505,6 +53505,12 @@ return Subtarget.is64Bit(); } +bool X86TargetLowering::functionArgumentNeedsConsecutiveRegisters( + Type *Ty, CallingConv::ID CallConv, bool isVarArg, + const DataLayout &DL) const { + return Ty->isIntegerTy(128); +} + /// Returns true if stack probing through a function call is requested. bool X86TargetLowering::hasStackProbeSymbol(MachineFunction &MF) const { return !getStackProbeSymbolName(MF).empty(); Index: llvm/test/CodeGen/X86/large-argument-count-i128.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/X86/large-argument-count-i128.ll @@ -0,0 +1,32 @@ +; RUN: llc < %s -mtriple=x86_64-- | FileCheck %s + +; The important part of this test is that r9d is ot used to store the +; lower part of the i128. Instead r9d is unused and the i128 is passed +; on the stack. + +; CHECK-LABEL: bar: +; CHECK: # %bb.0: +; CHECK-NEXT: subq $40, %rsp +; CHECK-NEXT: .cfi_def_cfa_offset 48 +; CHECK-NEXT: movl %edi, 36(%rsp) +; CHECK-NEXT: movq $0, 16(%rsp) +; CHECK-NEXT: movq $1, (%rsp) +; CHECK-NEXT: leaq 36(%rsp), %rdx +; CHECK-NEXT: xorl %edi, %edi +; CHECK-NEXT: movl $1, %esi +; CHECK-NEXT: movl $3, %ecx +; CHECK-NEXT: movl $4, %r8d +; CHECK-NEXT: callq foo@PLT +; CHECK-NEXT: addq $40, %rsp +; CHECK-NEXT: .cfi_def_cfa_offset 8 +; CHECK-NEXT: retq + + +define void @bar(i32 %a) { + %b = alloca i32, align 4 + store i32 %a, i32* %b + call void @foo(i32 0, i32 1, i32* nonnull %b, i32 3, i32 4, i128 1) + ret void +} + +declare void @foo(i32, i32, i32*, i32, i32, i128)