diff --git a/llvm/include/llvm/CodeGen/MachineFrameInfo.h b/llvm/include/llvm/CodeGen/MachineFrameInfo.h --- a/llvm/include/llvm/CodeGen/MachineFrameInfo.h +++ b/llvm/include/llvm/CodeGen/MachineFrameInfo.h @@ -338,6 +338,9 @@ /// Size of the UnsafeStack Frame uint64_t UnsafeStackSize = 0; + /// Base pointer register is clobbed by inline assembly. + bool BasePointerClobbered = false; + public: explicit MachineFrameInfo(Align StackAlignment, bool StackRealignable, bool ForcedRealign) @@ -809,6 +812,9 @@ uint64_t getUnsafeStackSize() const { return UnsafeStackSize; } void setUnsafeStackSize(uint64_t Size) { UnsafeStackSize = Size; } + bool isBasePointerClobbered() const { return BasePointerClobbered; } + void setBasePointerClobbered() { BasePointerClobbered = true; } + /// Return a set of physical registers that are pristine. /// /// Pristine registers hold a value that is useless to the current function, diff --git a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h --- a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h +++ b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h @@ -548,6 +548,12 @@ return false; } + /// Returns true if PhysReg is is base pointer register. + virtual bool isBasePointerReg(const MachineFunction &MF, + unsigned PhysReg) const { + return false; + } + /// Returns true if PhysReg is unallocatable and constant throughout the /// function. Used by MachineRegisterInfo::isConstantPhysReg(). virtual bool isConstantPhysReg(MCRegister PhysReg) const { return false; } diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -9045,6 +9045,16 @@ } return false; }; + auto DetectBasePtrRegister = [&]() { + MachineFunction &MF = DAG.getMachineFunction(); + const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); + for (unsigned Reg : OpInfo.AssignedRegs.Regs) { + if (Register::isPhysicalRegister(Reg) && + TRI.isBasePointerReg(MF, Reg)) { + MF.getFrameInfo().setBasePointerClobbered(); + } + } + }; assert((OpInfo.ConstraintType != TargetLowering::C_Address || (OpInfo.Type == InlineAsm::isInput && !OpInfo.isMatchingInputConstraint())) && @@ -9077,6 +9087,7 @@ if (DetectWriteToReservedRegister()) return; + DetectBasePtrRegister(); // Add information to the INLINEASM node to know that this register is // set. @@ -9259,6 +9270,7 @@ if (DetectWriteToReservedRegister()) return; + DetectBasePtrRegister(); SDLoc dl = getCurSDLoc(); @@ -9272,10 +9284,12 @@ case InlineAsm::isClobber: // Add the clobbered value to the operand list, so that the register // allocator is aware that the physreg got clobbered. - if (!OpInfo.AssignedRegs.Regs.empty()) + if (!OpInfo.AssignedRegs.Regs.empty()) { OpInfo.AssignedRegs.AddInlineAsmOperands(InlineAsm::Kind_Clobber, false, 0, getCurSDLoc(), DAG, AsmNodeOperands); + DetectBasePtrRegister(); + } break; } } diff --git a/llvm/lib/Target/X86/X86RegisterInfo.h b/llvm/lib/Target/X86/X86RegisterInfo.h --- a/llvm/lib/Target/X86/X86RegisterInfo.h +++ b/llvm/lib/Target/X86/X86RegisterInfo.h @@ -127,6 +127,10 @@ bool isFixedRegister(const MachineFunction &MF, MCRegister PhysReg) const override; + /// Return true if the PhysReg is base pointer register. + bool isBasePointerReg(const MachineFunction &MF, + unsigned PhysReg) const override; + void adjustStackMapLiveOutMask(uint32_t *Mask) const override; bool hasBasePointer(const MachineFunction &MF) const; diff --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp b/llvm/lib/Target/X86/X86RegisterInfo.cpp --- a/llvm/lib/Target/X86/X86RegisterInfo.cpp +++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp @@ -672,6 +672,14 @@ return X86GenRegisterInfo::isFixedRegister(MF, PhysReg); } +bool X86RegisterInfo::isBasePointerReg(const MachineFunction &MF, + unsigned PhysReg) const { + const X86Subtarget &ST = MF.getSubtarget(); + const TargetRegisterInfo &TRI = *ST.getRegisterInfo(); + + return TRI.isSuperOrSubRegisterEq(BasePtr, PhysReg); +} + bool X86RegisterInfo::isTileRegisterClass(const TargetRegisterClass *RC) const { return RC->getID() == X86::TILERegClassID; } @@ -707,7 +715,7 @@ const MachineFrameInfo &MFI = MF.getFrameInfo(); - if (!EnableBasePointer) + if (!EnableBasePointer || MFI.isBasePointerClobbered()) return false; // When we need stack realignment, we can't address the stack from the frame @@ -734,7 +742,7 @@ // If a base pointer is necessary. Check that it isn't too late to reserve // it. if (CantUseSP(MFI)) - return MRI->canReserveReg(BasePtr); + return !MFI.isBasePointerClobbered() && MRI->canReserveReg(BasePtr); return true; } 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 @@ -37,9 +37,7 @@ ; CHECK-NEXT: pushl %ebp ; CHECK-NEXT: movl %esp, %ebp ; CHECK-NEXT: pushl %esi -; CHECK-NEXT: andl $-128, %esp -; CHECK-NEXT: subl $128, %esp -; CHECK-NEXT: movl %esp, %esi +; CHECK-NEXT: subl $116, %esp ; CHECK-NEXT: calll helper@PLT ; CHECK-NEXT: movl %esp, %ecx ; CHECK-NEXT: leal 31(,%eax,4), %eax @@ -54,7 +52,7 @@ ; CHECK-NEXT: #NO_APP ; CHECK-NEXT: movl $8, %edx ; CHECK-NEXT: #APP -; CHECK-NEXT: movl %edx, (%esi) +; CHECK-NEXT: movl %edx, -120(%ebp) ; CHECK-NEXT: #NO_APP ; CHECK-NEXT: movl $0, (%ecx,%eax) ; CHECK-NEXT: leal -4(%ebp), %esp diff --git a/llvm/test/CodeGen/X86/swifttail-realign.ll b/llvm/test/CodeGen/X86/swifttail-realign.ll --- a/llvm/test/CodeGen/X86/swifttail-realign.ll +++ b/llvm/test/CodeGen/X86/swifttail-realign.ll @@ -10,7 +10,7 @@ ; CHECK: pushq %rbp ; CHECK: movq %rsp, %rbp ; CHECK: pushq %rbx -; CHECK: andq $-32, %rsp +; CHECK-NOT: andq $-32, %rsp ; [... don't really care what happens to rsp to allocate %ptr ...] ; CHECK: movq 24(%rbp), [[RETADDR:%.*]] ; CHECK: movq [[RETADDR]], 8(%rbp) @@ -27,3 +27,27 @@ tail call swifttailcc void @callee([6 x i64] undef, i64 42, i64 0) ret void } + +define swifttailcc void @caller2(i64 %n) { +; CHECK-LABEL: caller2: +; CHECK: subq $16, %rsp +; CHECK: pushq %rbp +; CHECK: movq %rsp, %rbp +; CHECK: pushq %rbx +; CHECK: andq $-32, %rsp +; [... don't really care what happens to rsp to allocate %ptr ...] +; CHECK: movq 24(%rbp), [[RETADDR:%.*]] +; CHECK: movq [[RETADDR]], 8(%rbp) +; CHECK: movq $42, 16(%rbp) +; CHECK: movq $0, 24(%rbp) +; CHECK: leaq -8(%rbp), %rsp +; CHECK: popq %rbx +; CHECK: popq %rbp +; CHECK: jmp callee + + call void asm sideeffect "", "~{rax}"() + %ptr = alloca i8, i64 %n, align 32 + store ptr %ptr, ptr @var + tail call swifttailcc void @callee([6 x i64] undef, i64 42, i64 0) + ret void +} 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 @@ -70,9 +70,7 @@ ; CHECK-NEXT: pushq %rbp ; CHECK-NEXT: movq %rsp, %rbp ; CHECK-NEXT: pushq %rbx -; CHECK-NEXT: andq $-128, %rsp -; CHECK-NEXT: subq $128, %rsp -; CHECK-NEXT: movq %rsp, %rbx +; CHECK-NEXT: subq $104, %rsp ; CHECK-NEXT: callq helper@PLT ; CHECK-NEXT: movq %rsp, %rcx ; CHECK-NEXT: movl %eax, %eax @@ -88,7 +86,7 @@ ; CHECK-NEXT: #NO_APP ; CHECK-NEXT: movl $8, %edx ; CHECK-NEXT: #APP -; CHECK-NEXT: movl %edx, (%rbx) +; CHECK-NEXT: movl %edx, -112(%rbp) ; CHECK-NEXT: #NO_APP ; CHECK-NEXT: movl $0, (%rcx,%rax) ; CHECK-NEXT: leaq -8(%rbp), %rsp @@ -101,9 +99,7 @@ ; X32ABI-NEXT: pushq %rbp ; X32ABI-NEXT: movl %esp, %ebp ; X32ABI-NEXT: pushq %rbx -; X32ABI-NEXT: andl $-128, %esp -; X32ABI-NEXT: subl $128, %esp -; X32ABI-NEXT: movl %esp, %ebx +; X32ABI-NEXT: subl $104, %esp ; X32ABI-NEXT: callq helper@PLT ; X32ABI-NEXT: # kill: def $eax killed $eax def $rax ; X32ABI-NEXT: leal 31(,%rax,4), %eax @@ -119,7 +115,7 @@ ; X32ABI-NEXT: #NO_APP ; X32ABI-NEXT: movl $8, %edx ; X32ABI-NEXT: #APP -; X32ABI-NEXT: movl %edx, (%ebx) +; X32ABI-NEXT: movl %edx, -112(%ebp) ; X32ABI-NEXT: #NO_APP ; X32ABI-NEXT: movl $0, (%ecx,%eax) ; X32ABI-NEXT: leal -8(%ebp), %esp