Index: llvm/trunk/lib/Target/X86/X86CallingConv.td =================================================================== --- llvm/trunk/lib/Target/X86/X86CallingConv.td +++ llvm/trunk/lib/Target/X86/X86CallingConv.td @@ -297,8 +297,8 @@ CCIfNest>>, CCIfNest>, - // A SwiftSelf is passed in R10. - CCIfSwiftSelf>>, + // Pass SwiftSelf in a callee saved register. + CCIfSwiftSelf>>, // A SwiftError is passed in R12. CCIfSwiftError>>, Index: llvm/trunk/lib/Target/X86/X86FrameLowering.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86FrameLowering.cpp +++ llvm/trunk/lib/Target/X86/X86FrameLowering.cpp @@ -1871,16 +1871,25 @@ return true; // Push GPRs. It increases frame size. + const MachineFunction &MF = *MBB.getParent(); unsigned Opc = STI.is64Bit() ? X86::PUSH64r : X86::PUSH32r; for (unsigned i = CSI.size(); i != 0; --i) { unsigned Reg = CSI[i - 1].getReg(); if (!X86::GR64RegClass.contains(Reg) && !X86::GR32RegClass.contains(Reg)) continue; - // Add the callee-saved register as live-in. It's killed at the spill. - MBB.addLiveIn(Reg); - BuildMI(MBB, MI, DL, TII.get(Opc)).addReg(Reg, RegState::Kill) + bool isLiveIn = MF.getRegInfo().isLiveIn(Reg); + if (!isLiveIn) + MBB.addLiveIn(Reg); + + // Do not set a kill flag on values that are also marked as live-in. This + // happens with the @llvm-returnaddress intrinsic and with arguments + // passed in callee saved registers. + // Omitting the kill flags is conservatively correct even if the live-in + // is not used after all. + bool isKill = !isLiveIn; + BuildMI(MBB, MI, DL, TII.get(Opc)).addReg(Reg, getKillRegState(isKill)) .setMIFlag(MachineInstr::FrameSetup); } Index: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp @@ -3774,10 +3774,11 @@ RetCC_X86, RetCC_X86)) return false; // The callee has to preserve all registers the caller needs to preserve. + const X86RegisterInfo *TRI = Subtarget.getRegisterInfo(); + const uint32_t *CallerPreserved = TRI->getCallPreservedMask(MF, CallerCC); if (!CCMatch) { - const X86RegisterInfo *TRI = Subtarget.getRegisterInfo(); - if (!TRI->regmaskSubsetEqual(TRI->getCallPreservedMask(MF, CallerCC), - TRI->getCallPreservedMask(MF, CalleeCC))) + const uint32_t *CalleePreserved = TRI->getCallPreservedMask(MF, CalleeCC); + if (!TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved)) return false; } @@ -3847,6 +3848,28 @@ } } } + + // Parameters passed in callee saved registers must have the same value in + // caller and callee. + for (unsigned I = 0, E = ArgLocs.size(); I != E; ++I) { + const CCValAssign &ArgLoc = ArgLocs[I]; + if (!ArgLoc.isRegLoc()) + continue; + unsigned Reg = ArgLoc.getLocReg(); + // Only look at callee saved registers. + if (MachineOperand::clobbersPhysReg(CallerPreserved, Reg)) + continue; + // Check that we pass the value used for the caller. + // (We look for a CopyFromReg reading a virtual register that is used + // for the function live-in value of register Reg) + SDValue Value = OutVals[I]; + if (Value->getOpcode() != ISD::CopyFromReg) + return false; + unsigned ArgReg = cast(Value->getOperand(1))->getReg(); + const MachineRegisterInfo &MRI = MF.getRegInfo(); + if (MRI.getLiveInPhysReg(ArgReg) != Reg) + return false; + } } bool CalleeWillPop = Index: llvm/trunk/test/CodeGen/X86/swiftself.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/swiftself.ll +++ llvm/trunk/test/CodeGen/X86/swiftself.ll @@ -1,41 +1,62 @@ -; RUN: llc -verify-machineinstrs < %s -mtriple=x86_64-unknown-unknown | FileCheck %s -; RUN: llc -O0 -verify-machineinstrs < %s -mtriple=x86_64-unknown-unknown | FileCheck --check-prefix=CHECK-O0 %s -; RUN: llc -verify-machineinstrs < %s -march=x86 -mcpu=yonah -mtriple=i386-apple-darwin | FileCheck --check-prefix=CHECK-i386 %s -; RUN: llc -O0 -verify-machineinstrs < %s -march=x86 -mcpu=yonah -mtriple=i386-apple-darwin | FileCheck --check-prefix=CHECK-i386-O0 %s - -; Parameter with swiftself should be allocated to r10. -define void @check_swiftself(i32* swiftself %addr0) { -; CHECK-LABEL: check_swiftself: -; CHECK-O0-LABEL: check_swiftself: -; CHECK-i386-LABEL: check_swiftself: -; CHECK-i386-O0-LABEL: check_swiftself: - - %val0 = load volatile i32, i32* %addr0 -; CHECK: movl (%r10), -; CHECK-O0: movl (%r10), -; CHECK-i386: movl {{[0-9a-f]+}}(%esp) -; CHECK-i386-O0: movl {{[0-9a-f]+}}(%esp) - ret void +; RUN: llc -verify-machineinstrs -mtriple=x86_64-unknown-unknown -o - %s | FileCheck --check-prefix=CHECK --check-prefix=OPT %s +; RUN: llc -O0 -verify-machineinstrs -mtriple=x86_64-unknown-unknown -o - %s | FileCheck %s + +; Parameter with swiftself should be allocated to r13. +; CHECK-LABEL: swiftself_param: +; CHECK: movq %r13, %rax +define i8 *@swiftself_param(i8* swiftself %addr0) { + ret i8 *%addr0 } -@var8_3 = global i8 0 -declare void @take_swiftself(i8* swiftself %addr0) +; Check that r13 is used to pass a swiftself argument. +; CHECK-LABEL: call_swiftself: +; CHECK: movq %rdi, %r13 +; CHECK: callq {{_?}}swiftself_param +define i8 *@call_swiftself(i8* %arg) { + %res = call i8 *@swiftself_param(i8* swiftself %arg) + ret i8 *%res +} -define void @simple_args() { -; CHECK-LABEL: simple_args: -; CHECK-O0-LABEL: simple_args: -; CHECK-i386-LABEL: simple_args: -; CHECK-i386-O0-LABEL: simple_args: - - call void @take_swiftself(i8* @var8_3) -; CHECK: movl {{.*}}, %r10d -; CHECK: callq {{_?}}take_swiftself -; CHECK-O0: movabsq {{.*}}, %r10 -; CHECK-O0: callq {{_?}}take_swiftself -; CHECK-i386: movl {{.*}}, (%esp) -; CHECK-i386: calll {{.*}}take_swiftself -; CHECK-i386-O0: movl {{.*}}, (%esp) -; CHECK-i386-O0: calll {{.*}}take_swiftself +; r13 should be saved by the callee even if used for swiftself +; CHECK-LABEL: swiftself_clobber: +; CHECK: pushq %r13 +; ... +; CHECK: popq %r13 +define i8 *@swiftself_clobber(i8* swiftself %addr0) { + call void asm sideeffect "nop", "~{r13}"() + ret i8 *%addr0 +} +; Demonstrate that we do not need any movs when calling multiple functions +; with swiftself argument. +; CHECK-LABEL: swiftself_passthrough: +; OPT-NOT: mov{{.*}}r13 +; OPT: callq {{_?}}swiftself_param +; OPT-NOT: mov{{.*}}r13 +; OPT-NEXT: callq {{_?}}swiftself_param +define void @swiftself_passthrough(i8* swiftself %addr0) { + call i8 *@swiftself_param(i8* swiftself %addr0) + call i8 *@swiftself_param(i8* swiftself %addr0) ret void } + +; We can use a tail call if the callee swiftself is the same as the caller one. +; CHECK-LABEL: swiftself_tail: +; OPT: jmp {{_?}}swiftself_param +; OPT-NOT: ret +define i8* @swiftself_tail(i8* swiftself %addr0) { + call void asm sideeffect "", "~{r13}"() + %res = tail call i8* @swiftself_param(i8* swiftself %addr0) + ret i8* %res +} + +; We can not use a tail call if the callee swiftself is not the same as the +; caller one. +; CHECK-LABEL: swiftself_notail: +; CHECK: movq %rdi, %r13 +; CHECK: callq {{_?}}swiftself_param +; CHECK: retq +define i8* @swiftself_notail(i8* swiftself %addr0, i8* %addr1) nounwind { + %res = tail call i8* @swiftself_param(i8* swiftself %addr1) + ret i8* %res +}