Index: lib/Target/X86/X86CallingConv.td =================================================================== --- lib/Target/X86/X86CallingConv.td +++ lib/Target/X86/X86CallingConv.td @@ -294,8 +294,8 @@ CCIfNest>>, CCIfNest>, - // A SwiftSelf is passed in R10. - CCIfSwiftSelf>>, + // Pass SwiftSelf in a callee saved register. + CCIfSwiftSelf>>, // The first 6 integer arguments are passed in integer registers. CCIfType<[i32], CCAssignToReg<[EDI, ESI, EDX, ECX, R8D, R9D]>>, Index: lib/Target/X86/X86FrameLowering.cpp =================================================================== --- lib/Target/X86/X86FrameLowering.cpp +++ lib/Target/X86/X86FrameLowering.cpp @@ -1871,16 +1871,24 @@ 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. + bool isKill = !isLiveIn; + + BuildMI(MBB, MI, DL, TII.get(Opc)).addReg(Reg, getKillRegState(isKill)) .setMIFlag(MachineInstr::FrameSetup); } Index: test/CodeGen/X86/swiftself.ll =================================================================== --- test/CodeGen/X86/swiftself.ll +++ test/CodeGen/X86/swiftself.ll @@ -1,41 +1,39 @@ -; 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: - - %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 +; 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 } -@var8_3 = global i8 0 -declare void @take_swiftself(i8* swiftself %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: +; 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 +} - 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 +; 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 +} +; Demonstrate that we do not need any movs when calling multiple functions +; with swiftself argument. +; CHECK-LABEL: swiftself_passthrough: +; CHECK-OPT: callq {{_?}}swiftself_param +; CHECK-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 }