Index: lib/Target/X86/X86CallingConv.td =================================================================== --- lib/Target/X86/X86CallingConv.td +++ 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: lib/Target/X86/X86FrameLowering.cpp =================================================================== --- lib/Target/X86/X86FrameLowering.cpp +++ 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: lib/Target/X86/X86ISelLowering.cpp =================================================================== --- lib/Target/X86/X86ISelLowering.cpp +++ 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,25 @@ } } } + + // 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(); + if (!MachineOperand::clobbersPhysReg(CallerPreserved, Reg)) { + // Check that we pass the value used for the caller. + 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: test/CodeGen/X86/swiftself.ll =================================================================== --- test/CodeGen/X86/swiftself.ll +++ test/CodeGen/X86/swiftself.ll @@ -1,41 +1,59 @@ -; 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 +; 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 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: +; Parameter with swiftself should be allocated to r12. +; CHECK-LABEL: swiftself_param: +; CHECK: movq %r12, %rax +define i8 *@swiftself_param(i8* swiftself %addr0) { + ret i8 *%addr0 +} - %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 +; Check that r12 is used to pass a swiftself argument. +; CHECK-LABEL: call_swiftself: +; CHECK: movq %rdi, %r12 +; CHECK: callq {{_?}}swiftself_param +define i8 *@call_swiftself(i8* %arg) { + %res = call i8 *@swiftself_param(i8* swiftself %arg) + ret i8 *%res } -@var8_3 = global i8 0 -declare void @take_swiftself(i8* swiftself %addr0) +; r12 should be saved by the callee even if used for swiftself +; CHECK-LABEL: swiftself_clobber: +; CHECK: pushq %r12 +; ... +; CHECK: popq %r12 +define i8 *@swiftself_clobber(i8* swiftself %addr0) { + call void asm sideeffect "nop", "~{r12}"() + ret i8 *%addr0 +} -define void @simple_args() { -; CHECK-LABEL: simple_args: -; CHECK-O0-LABEL: simple_args: -; CHECK-i386-LABEL: simple_args: -; CHECK-i386-O0-LABEL: simple_args: +; Demonstrate that we do not need any movs when calling multiple functions +; with swiftself argument. +; CHECK-LABEL: swiftself_passthrough: +; OPT: callq {{_?}}swiftself_param +; 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 +} - 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 +; 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 "", "~{x19}"() + %res = tail call i8* @swiftself_param(i8* swiftself %addr0) + ret i8* %res +} - ret void +; We can not use a tail call if the callee swiftself is not the same as the +; caller one. +; CHECK-LABEL: swiftself_notail: +; 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 }