From fa85eb62378900a884a7eb4933a9deb6513d26ab Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Tue, 6 Apr 2010 20:26:37 +0000 Subject: [PATCH] Fix PR6696 and PR6663 When a frame pointer is not otherwise required, and dynamic stack alignment is necessary solely due to the spilling of a register with larger alignment requirements than the default stack alignment, the frame pointer can be both used as a general purpose register and a frame pointer. That goes poorly, for obvious reasons. This patch brings back a bit of old logic for identifying the use of such registers and conservatively reserves the frame pointer during register allocation in such cases. For now, implement for X86 only since it's 32-bit linux which is hitting this, and we want a targeted fix for 2.7. As a follow-on, this will be expanded to handle other targets, as theoretically the problem could arise elsewhere as well. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@100559 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86.h | 6 ++++ lib/Target/X86/X86MachineFunctionInfo.h | 10 +++++- lib/Target/X86/X86RegisterInfo.cpp | 43 +++++++++++++++++++++++++ lib/Target/X86/X86RegisterInfo.td | 38 ++++++++++++++-------- lib/Target/X86/X86TargetMachine.cpp | 1 + 5 files changed, 84 insertions(+), 14 deletions(-) diff --git a/lib/Target/X86/X86.h b/lib/Target/X86/X86.h index 9be38a4b56a..22e89a57f63 100644 --- a/lib/Target/X86/X86.h +++ b/lib/Target/X86/X86.h @@ -69,6 +69,12 @@ TargetAsmBackend *createX86_64AsmBackend(const Target &, const std::string &); /// FunctionPass *createEmitX86CodeToMemory(); +/// createX86MaxStackAlignmentHeuristicPass - This function returns a pass +/// which determines whether the frame pointer register should be +/// reserved in case dynamic stack alignment is later required. +/// +FunctionPass *createX86MaxStackAlignmentHeuristicPass(); + extern Target TheX86_32Target, TheX86_64Target; } // End llvm namespace diff --git a/lib/Target/X86/X86MachineFunctionInfo.h b/lib/Target/X86/X86MachineFunctionInfo.h index 4b2529bccf0..a916c6372ea 100644 --- a/lib/Target/X86/X86MachineFunctionInfo.h +++ b/lib/Target/X86/X86MachineFunctionInfo.h @@ -52,6 +52,10 @@ class X86MachineFunctionInfo : public MachineFunctionInfo { /// relocation models. unsigned GlobalBaseReg; + /// ReserveFP - whether the function should reserve the frame pointer + /// when allocating, even if there may not actually be a frame pointer used. + bool ReserveFP; + public: X86MachineFunctionInfo() : ForceFramePointer(false), CalleeSavedFrameSize(0), @@ -68,7 +72,8 @@ public: ReturnAddrIndex(0), TailCallReturnAddrDelta(0), SRetReturnReg(0), - GlobalBaseReg(0) {} + GlobalBaseReg(0), + ReserveFP(false) {} bool getForceFramePointer() const { return ForceFramePointer;} void setForceFramePointer(bool forceFP) { ForceFramePointer = forceFP; } @@ -90,6 +95,9 @@ public: unsigned getGlobalBaseReg() const { return GlobalBaseReg; } void setGlobalBaseReg(unsigned Reg) { GlobalBaseReg = Reg; } + + bool getReserveFP() const { return ReserveFP; } + void setReserveFP(bool reserveFP) { ReserveFP = reserveFP; } }; } // End llvm namespace diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index 32f28a52007..ba15079e98b 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -1487,3 +1487,46 @@ unsigned getX86SubSuperRegister(unsigned Reg, EVT VT, bool High) { } #include "X86GenRegisterInfo.inc" + +namespace { + struct MSAH : public MachineFunctionPass { + static char ID; + MSAH() : MachineFunctionPass(&ID) {} + + virtual bool runOnMachineFunction(MachineFunction &MF) { + const X86TargetMachine *TM = + static_cast(&MF.getTarget()); + const X86RegisterInfo *X86RI = TM->getRegisterInfo(); + MachineRegisterInfo &RI = MF.getRegInfo(); + X86MachineFunctionInfo *FuncInfo = MF.getInfo(); + unsigned StackAlignment = X86RI->getStackAlignment(); + + // Be over-conservative: scan over all vreg defs and find whether vector + // registers are used. If yes, there is a possibility that vector register + // will be spilled and thus require dynamic stack realignment. + for (unsigned RegNum = TargetRegisterInfo::FirstVirtualRegister; + RegNum < RI.getLastVirtReg(); ++RegNum) + if (RI.getRegClass(RegNum)->getAlignment() > StackAlignment) { + FuncInfo->setReserveFP(true); + return true; + } + + // Nothing to do + return false; + } + + virtual const char *getPassName() const { + return "X86 Maximal Stack Alignment Check"; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); + } + }; + + char MSAH::ID = 0; +} + +FunctionPass* +llvm::createX86MaxStackAlignmentHeuristicPass() { return new MSAH(); } diff --git a/lib/Target/X86/X86RegisterInfo.td b/lib/Target/X86/X86RegisterInfo.td index 76b8f7a953c..49a6ca09281 100644 --- a/lib/Target/X86/X86RegisterInfo.td +++ b/lib/Target/X86/X86RegisterInfo.td @@ -352,11 +352,12 @@ def GR8 : RegisterClass<"X86", [i8], 8, const TargetMachine &TM = MF.getTarget(); const TargetRegisterInfo *RI = TM.getRegisterInfo(); const X86Subtarget &Subtarget = TM.getSubtarget(); + const X86MachineFunctionInfo *MFI = MF.getInfo(); // Does the function dedicate RBP / EBP to being a frame ptr? if (!Subtarget.is64Bit()) // In 32-mode, none of the 8-bit registers aliases EBP or ESP. return begin() + 8; - else if (RI->hasFP(MF)) + else if (RI->hasFP(MF) || MFI->getReserveFP()) // If so, don't allocate SPL or BPL. return array_endof(X86_GR8_AO_64) - 1; else @@ -396,9 +397,10 @@ def GR16 : RegisterClass<"X86", [i16], 16, const TargetMachine &TM = MF.getTarget(); const TargetRegisterInfo *RI = TM.getRegisterInfo(); const X86Subtarget &Subtarget = TM.getSubtarget(); + const X86MachineFunctionInfo *MFI = MF.getInfo(); if (Subtarget.is64Bit()) { // Does the function dedicate RBP to being a frame ptr? - if (RI->hasFP(MF)) + if (RI->hasFP(MF) || MFI->getReserveFP()) // If so, don't allocate SP or BP. return array_endof(X86_GR16_AO_64) - 1; else @@ -406,7 +408,7 @@ def GR16 : RegisterClass<"X86", [i16], 16, return array_endof(X86_GR16_AO_64); } else { // Does the function dedicate EBP to being a frame ptr? - if (RI->hasFP(MF)) + if (RI->hasFP(MF) || MFI->getReserveFP()) // If so, don't allocate SP or BP. return begin() + 6; else @@ -447,9 +449,10 @@ def GR32 : RegisterClass<"X86", [i32], 32, const TargetMachine &TM = MF.getTarget(); const TargetRegisterInfo *RI = TM.getRegisterInfo(); const X86Subtarget &Subtarget = TM.getSubtarget(); + const X86MachineFunctionInfo *MFI = MF.getInfo(); if (Subtarget.is64Bit()) { // Does the function dedicate RBP to being a frame ptr? - if (RI->hasFP(MF)) + if (RI->hasFP(MF) || MFI->getReserveFP()) // If so, don't allocate ESP or EBP. return array_endof(X86_GR32_AO_64) - 1; else @@ -457,7 +460,7 @@ def GR32 : RegisterClass<"X86", [i32], 32, return array_endof(X86_GR32_AO_64); } else { // Does the function dedicate EBP to being a frame ptr? - if (RI->hasFP(MF)) + if (RI->hasFP(MF) || MFI->getReserveFP()) // If so, don't allocate ESP or EBP. return begin() + 6; else @@ -484,9 +487,11 @@ def GR64 : RegisterClass<"X86", [i64], 64, const TargetMachine &TM = MF.getTarget(); const TargetRegisterInfo *RI = TM.getRegisterInfo(); const X86Subtarget &Subtarget = TM.getSubtarget(); + const X86MachineFunctionInfo *MFI = MF.getInfo(); if (!Subtarget.is64Bit()) return begin(); // None of these are allocatable in 32-bit. - if (RI->hasFP(MF)) // Does the function dedicate RBP to being a frame ptr? + // Does the function dedicate RBP to being a frame ptr? + if (RI->hasFP(MF) || MFI->getReserveFP()) return end()-3; // If so, don't allocate RIP, RSP or RBP else return end()-2; // If not, just don't allocate RIP or RSP @@ -589,8 +594,9 @@ def GR16_NOREX : RegisterClass<"X86", [i16], 16, GR16_NOREXClass::allocation_order_end(const MachineFunction &MF) const { const TargetMachine &TM = MF.getTarget(); const TargetRegisterInfo *RI = TM.getRegisterInfo(); + const X86MachineFunctionInfo *MFI = MF.getInfo(); // Does the function dedicate RBP / EBP to being a frame ptr? - if (RI->hasFP(MF)) + if (RI->hasFP(MF) || MFI->getReserveFP()) // If so, don't allocate SP or BP. return end() - 2; else @@ -611,8 +617,9 @@ def GR32_NOREX : RegisterClass<"X86", [i32], 32, GR32_NOREXClass::allocation_order_end(const MachineFunction &MF) const { const TargetMachine &TM = MF.getTarget(); const TargetRegisterInfo *RI = TM.getRegisterInfo(); + const X86MachineFunctionInfo *MFI = MF.getInfo(); // Does the function dedicate RBP / EBP to being a frame ptr? - if (RI->hasFP(MF)) + if (RI->hasFP(MF) || MFI->getReserveFP()) // If so, don't allocate ESP or EBP. return end() - 2; else @@ -633,8 +640,9 @@ def GR64_NOREX : RegisterClass<"X86", [i64], 64, GR64_NOREXClass::allocation_order_end(const MachineFunction &MF) const { const TargetMachine &TM = MF.getTarget(); const TargetRegisterInfo *RI = TM.getRegisterInfo(); + const X86MachineFunctionInfo *MFI = MF.getInfo(); // Does the function dedicate RBP to being a frame ptr? - if (RI->hasFP(MF)) + if (RI->hasFP(MF) || MFI->getReserveFP()) // If so, don't allocate RIP, RSP or RBP. return end() - 3; else @@ -675,9 +683,10 @@ def GR32_NOSP : RegisterClass<"X86", [i32], 32, const TargetMachine &TM = MF.getTarget(); const TargetRegisterInfo *RI = TM.getRegisterInfo(); const X86Subtarget &Subtarget = TM.getSubtarget(); + const X86MachineFunctionInfo *MFI = MF.getInfo(); if (Subtarget.is64Bit()) { // Does the function dedicate RBP to being a frame ptr? - if (RI->hasFP(MF)) + if (RI->hasFP(MF) || MFI->getReserveFP()) // If so, don't allocate EBP. return array_endof(X86_GR32_NOSP_AO_64) - 1; else @@ -685,7 +694,7 @@ def GR32_NOSP : RegisterClass<"X86", [i32], 32, return array_endof(X86_GR32_NOSP_AO_64); } else { // Does the function dedicate EBP to being a frame ptr? - if (RI->hasFP(MF)) + if (RI->hasFP(MF) || MFI->getReserveFP()) // If so, don't allocate EBP. return begin() + 6; else @@ -710,9 +719,11 @@ def GR64_NOSP : RegisterClass<"X86", [i64], 64, const TargetMachine &TM = MF.getTarget(); const TargetRegisterInfo *RI = TM.getRegisterInfo(); const X86Subtarget &Subtarget = TM.getSubtarget(); + const X86MachineFunctionInfo *MFI = MF.getInfo(); if (!Subtarget.is64Bit()) return begin(); // None of these are allocatable in 32-bit. - if (RI->hasFP(MF)) // Does the function dedicate RBP to being a frame ptr? + // Does the function dedicate RBP to being a frame ptr? + if (RI->hasFP(MF) || MFI->getReserveFP()) return end()-1; // If so, don't allocate RBP else return end(); // If not, any reg in this class is ok. @@ -733,8 +744,9 @@ def GR64_NOREX_NOSP : RegisterClass<"X86", [i64], 64, { const TargetMachine &TM = MF.getTarget(); const TargetRegisterInfo *RI = TM.getRegisterInfo(); + const X86MachineFunctionInfo *MFI = MF.getInfo(); // Does the function dedicate RBP to being a frame ptr? - if (RI->hasFP(MF)) + if (RI->hasFP(MF) || MFI->getReserveFP()) // If so, don't allocate RBP. return end() - 1; else diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp index c608e56c8fb..59fd7a9c328 100644 --- a/lib/Target/X86/X86TargetMachine.cpp +++ b/lib/Target/X86/X86TargetMachine.cpp @@ -161,6 +161,7 @@ bool X86TargetMachine::addInstSelector(PassManagerBase &PM, bool X86TargetMachine::addPreRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel) { + PM.add(createX86MaxStackAlignmentHeuristicPass()); return false; // -print-machineinstr shouldn't print after this. } -- 2.34.1