diff --git a/llvm/lib/Target/X86/X86FrameLowering.h b/llvm/lib/Target/X86/X86FrameLowering.h --- a/llvm/lib/Target/X86/X86FrameLowering.h +++ b/llvm/lib/Target/X86/X86FrameLowering.h @@ -265,6 +265,10 @@ void emitCatchRetReturnValue(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, MachineInstr *CatchRet) const; + + /// Save and restore base pointer register around MI which clobber the + /// register. + void saveRestoreBasePointerReg(MachineFunction &MF) const; }; } // End llvm namespace diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp --- a/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/llvm/lib/Target/X86/X86FrameLowering.cpp @@ -3862,6 +3862,7 @@ void X86FrameLowering::processFunctionBeforeFrameIndicesReplaced( MachineFunction &MF, RegScavenger *RS) const { + saveRestoreBasePointerReg(MF); if (STI.is32Bit() && MF.hasEHFunclets()) restoreWinEHStackPointersInParent(MF); } @@ -3880,3 +3881,37 @@ /*RestoreSP=*/IsSEH); } } + +void X86FrameLowering::saveRestoreBasePointerReg(MachineFunction &MF) const { + MachineFrameInfo &MFI = MF.getFrameInfo(); + int FI = INT_MAX; + + if (!TRI->hasBasePointer(MF)) + return; + + Register BasePtr = TRI->getBaseRegister(); + for (MachineBasicBlock &MBB : MF) { + for (MachineBasicBlock::iterator MII = MBB.begin(); MII != MBB.end(); ++MII) { + if (!MII->isInlineAsm()) + continue; + for (const MachineOperand &MO : MII->operands()) { + if (!MO.isReg()) + continue; + Register Reg = MO.getReg(); + if (!Register::isPhysicalRegister(Reg)) + continue; + if (!TRI->isSuperOrSubRegisterEq(BasePtr, Reg)) + continue; + + const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(BasePtr); + if (FI == INT_MAX) + FI = MFI.CreateSpillStackObject(SlotSize, Align(SlotSize)); + TII.storeRegToStackSlot(MBB, MII, Reg, true, FI, RC, TRI, + Register()); + + MII++; + TII.loadRegFromStackSlot(MBB, MII, Reg, FI, RC, TRI, Register()); + } + } + } +} diff --git a/llvm/test/CodeGen/X86/i386-baseptr.ll b/llvm/test/CodeGen/X86/i386-baseptr.ll --- a/llvm/test/CodeGen/X86/i386-baseptr.ll +++ b/llvm/test/CodeGen/X86/i386-baseptr.ll @@ -49,9 +49,11 @@ ; CHECK-NEXT: movl %edx, %esp ; CHECK-NEXT: negl %eax ; CHECK-NEXT: movl $405, %esi # imm = 0x195 +; CHECK-NEXT: movl %esi, 128(%esi) # 4-byte Spill ; CHECK-NEXT: #APP ; CHECK-NEXT: nop ; CHECK-NEXT: #NO_APP +; CHECK-NEXT: movl 128(%esi), %esi # 4-byte Reload ; CHECK-NEXT: movl $8, %edx ; CHECK-NEXT: #APP ; CHECK-NEXT: movl %edx, (%esi) diff --git a/llvm/test/CodeGen/X86/x86-64-baseptr.ll b/llvm/test/CodeGen/X86/x86-64-baseptr.ll --- a/llvm/test/CodeGen/X86/x86-64-baseptr.ll +++ b/llvm/test/CodeGen/X86/x86-64-baseptr.ll @@ -83,9 +83,11 @@ ; CHECK-NEXT: movq %rdx, %rsp ; CHECK-NEXT: negq %rax ; CHECK-NEXT: movl $405, %ebx # imm = 0x195 +; CHECK-NEXT: movq %ebx, 128(%rbx) # 8-byte Spill ; CHECK-NEXT: #APP ; CHECK-NEXT: nop ; CHECK-NEXT: #NO_APP +; CHECK-NEXT: movq 128(%rbx), %ebx # 8-byte Reload ; CHECK-NEXT: movl $8, %edx ; CHECK-NEXT: #APP ; CHECK-NEXT: movl %edx, (%rbx) @@ -114,9 +116,11 @@ ; X32ABI-NEXT: negl %eax ; X32ABI-NEXT: movl %edx, %esp ; X32ABI-NEXT: movl $405, %ebx # imm = 0x195 +; X32ABI-NEXT: movl %ebx, 128(%ebx) # 8-byte Spill ; X32ABI-NEXT: #APP ; X32ABI-NEXT: nop ; X32ABI-NEXT: #NO_APP +; X32ABI-NEXT: movl 128(%ebx), %ebx # 8-byte Reload ; X32ABI-NEXT: movl $8, %edx ; X32ABI-NEXT: #APP ; X32ABI-NEXT: movl %edx, (%ebx)