diff options
| author | Matthias Braun <matze@braunis.de> | 2016-04-13 21:43:21 +0000 |
|---|---|---|
| committer | Matthias Braun <matze@braunis.de> | 2016-04-13 21:43:21 +0000 |
| commit | 588d1cdad486dcddd8fe410bdc6e7080c1cfdbdd (patch) | |
| tree | da934bd2e6a7fc1bc49bfbb57956548b4bffa70b | |
| parent | 74a0bd319ad9a6bca95684d4c87851e4583725e9 (diff) | |
| download | bcm5719-llvm-588d1cdad486dcddd8fe410bdc6e7080c1cfdbdd.tar.gz bcm5719-llvm-588d1cdad486dcddd8fe410bdc6e7080c1cfdbdd.zip | |
X86: Use a callee save register for the swiftself parameter.
It is very likely that the swiftself parameter is alive throughout most
functions function so putting it into a callee save register should
avoid spills for the callers with only a minimum amount of extra spills
in the callees.
Currently the generated code is correct but unnecessarily spills and
reloads arguments passed in callee save registers, I will address this
in upcoming patches.
This also adds a missing check that for tail calls the preserved value
of the caller must be the same as the callees parameter.
Differential Revision: http://reviews.llvm.org/D18902
llvm-svn: 266252
| -rw-r--r-- | llvm/lib/Target/X86/X86CallingConv.td | 4 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/X86FrameLowering.cpp | 15 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.cpp | 29 | ||||
| -rw-r--r-- | llvm/test/CodeGen/X86/swiftself.ll | 87 |
4 files changed, 94 insertions, 41 deletions
diff --git a/llvm/lib/Target/X86/X86CallingConv.td b/llvm/lib/Target/X86/X86CallingConv.td index 4d99af68a04..ed17b1d4d04 100644 --- a/llvm/lib/Target/X86/X86CallingConv.td +++ b/llvm/lib/Target/X86/X86CallingConv.td @@ -297,8 +297,8 @@ def CC_X86_64_C : CallingConv<[ CCIfNest<CCIfSubtarget<"isTarget64BitILP32()", CCAssignToReg<[R10D]>>>, CCIfNest<CCAssignToReg<[R10]>>, - // A SwiftSelf is passed in R10. - CCIfSwiftSelf<CCIfType<[i64], CCAssignToReg<[R10]>>>, + // Pass SwiftSelf in a callee saved register. + CCIfSwiftSelf<CCIfType<[i64], CCAssignToReg<[R13]>>>, // A SwiftError is passed in R12. CCIfSwiftError<CCIfType<[i64], CCAssignToReg<[R12]>>>, diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp index ec858671c42..8efe7038daf 100644 --- a/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/llvm/lib/Target/X86/X86FrameLowering.cpp @@ -1871,16 +1871,25 @@ bool X86FrameLowering::spillCalleeSavedRegisters( 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); } diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 2fdddd8fe45..7cf909f1039 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -3774,10 +3774,11 @@ bool X86TargetLowering::IsEligibleForTailCallOptimization( 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 @@ bool X86TargetLowering::IsEligibleForTailCallOptimization( } } } + + // 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<RegisterSDNode>(Value->getOperand(1))->getReg(); + const MachineRegisterInfo &MRI = MF.getRegInfo(); + if (MRI.getLiveInPhysReg(ArgReg) != Reg) + return false; + } } bool CalleeWillPop = diff --git a/llvm/test/CodeGen/X86/swiftself.ll b/llvm/test/CodeGen/X86/swiftself.ll index 14b049632a4..c5e90594560 100644 --- a/llvm/test/CodeGen/X86/swiftself.ll +++ b/llvm/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 +; 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 r13. +; CHECK-LABEL: swiftself_param: +; CHECK: movq %r13, %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 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 } -@var8_3 = global i8 0 -declare void @take_swiftself(i8* swiftself %addr0) +; 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 +} -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-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 +} - 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 "", "~{r13}"() + %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: 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 } |

