diff options
Diffstat (limited to 'llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp')
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp | 323 |
1 files changed, 215 insertions, 108 deletions
diff --git a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp index 3cdf6bf98ee08..985722fdcab4a 100644 --- a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp @@ -17,6 +17,7 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/RegisterScavenging.h" #include "llvm/IR/Function.h" +#include "llvm/Target/TargetMachine.h" using namespace llvm; @@ -62,18 +63,6 @@ SystemZFrameLowering::SystemZFrameLowering() RegSpillOffsets[SpillOffsetTable[I].Reg] = SpillOffsetTable[I].Offset; } -static bool usePackedStack(MachineFunction &MF) { - bool HasPackedStackAttr = MF.getFunction().hasFnAttribute("packed-stack"); - bool IsVarArg = MF.getFunction().isVarArg(); - bool CallConv = MF.getFunction().getCallingConv() != CallingConv::GHC; - bool BackChain = MF.getFunction().hasFnAttribute("backchain"); - bool FramAddressTaken = MF.getFrameInfo().isFrameAddressTaken(); - if (HasPackedStackAttr && BackChain) - report_fatal_error("packed-stack with backchain is currently unsupported."); - return HasPackedStackAttr && !IsVarArg && CallConv && !BackChain && - !FramAddressTaken; -} - bool SystemZFrameLowering:: assignCalleeSavedSpillSlots(MachineFunction &MF, const TargetRegisterInfo *TRI, @@ -87,71 +76,44 @@ assignCalleeSavedSpillSlots(MachineFunction &MF, unsigned LowGPR = 0; unsigned HighGPR = SystemZ::R15D; int StartSPOffset = SystemZMC::CallFrameSize; - int CurrOffset; - if (!usePackedStack(MF)) { - for (auto &CS : CSI) { - unsigned Reg = CS.getReg(); - int Offset = RegSpillOffsets[Reg]; - if (Offset) { - if (SystemZ::GR64BitRegClass.contains(Reg) && StartSPOffset > Offset) { - LowGPR = Reg; - StartSPOffset = Offset; - } - Offset -= SystemZMC::CallFrameSize; - int FrameIdx = MFFrame.CreateFixedSpillStackObject(8, Offset); - CS.setFrameIdx(FrameIdx); - } else - CS.setFrameIdx(INT32_MAX); - } - - // Save the range of call-saved registers, for use by the - // prologue/epilogue inserters. - ZFI->setRestoreGPRRegs(LowGPR, HighGPR, StartSPOffset); - if (IsVarArg) { - // Also save the GPR varargs, if any. R6D is call-saved, so would - // already be included, but we also need to handle the call-clobbered - // argument registers. - unsigned FirstGPR = ZFI->getVarArgsFirstGPR(); - if (FirstGPR < SystemZ::NumArgGPRs) { - unsigned Reg = SystemZ::ArgGPRs[FirstGPR]; - int Offset = RegSpillOffsets[Reg]; - if (StartSPOffset > Offset) { - LowGPR = Reg; StartSPOffset = Offset; - } + for (auto &CS : CSI) { + unsigned Reg = CS.getReg(); + int Offset = getRegSpillOffset(MF, Reg); + if (Offset) { + if (SystemZ::GR64BitRegClass.contains(Reg) && StartSPOffset > Offset) { + LowGPR = Reg; + StartSPOffset = Offset; } - } - ZFI->setSpillGPRRegs(LowGPR, HighGPR, StartSPOffset); + Offset -= SystemZMC::CallFrameSize; + int FrameIdx = MFFrame.CreateFixedSpillStackObject(8, Offset); + CS.setFrameIdx(FrameIdx); + } else + CS.setFrameIdx(INT32_MAX); + } - CurrOffset = -SystemZMC::CallFrameSize; - } else { - // Packed stack: put all the GPRs at the top of the Register save area. - uint32_t LowGR64Num = UINT32_MAX; - for (auto &CS : CSI) { - unsigned Reg = CS.getReg(); - if (SystemZ::GR64BitRegClass.contains(Reg)) { - unsigned GR64Num = SystemZMC::getFirstReg(Reg); - int Offset = -8 * (15 - GR64Num + 1); - if (LowGR64Num > GR64Num) { - LowGR64Num = GR64Num; - StartSPOffset = SystemZMC::CallFrameSize + Offset; - } - int FrameIdx = MFFrame.CreateFixedSpillStackObject(8, Offset); - CS.setFrameIdx(FrameIdx); - } else - CS.setFrameIdx(INT32_MAX); + // Save the range of call-saved registers, for use by the + // prologue/epilogue inserters. + ZFI->setRestoreGPRRegs(LowGPR, HighGPR, StartSPOffset); + if (IsVarArg) { + // Also save the GPR varargs, if any. R6D is call-saved, so would + // already be included, but we also need to handle the call-clobbered + // argument registers. + unsigned FirstGPR = ZFI->getVarArgsFirstGPR(); + if (FirstGPR < SystemZ::NumArgGPRs) { + unsigned Reg = SystemZ::ArgGPRs[FirstGPR]; + int Offset = getRegSpillOffset(MF, Reg); + if (StartSPOffset > Offset) { + LowGPR = Reg; StartSPOffset = Offset; + } } - if (LowGR64Num < UINT32_MAX) - LowGPR = SystemZMC::GR64Regs[LowGR64Num]; - - // Save the range of call-saved registers, for use by the - // prologue/epilogue inserters. - ZFI->setRestoreGPRRegs(LowGPR, HighGPR, StartSPOffset); - ZFI->setSpillGPRRegs(LowGPR, HighGPR, StartSPOffset); - - CurrOffset = LowGPR ? -(SystemZMC::CallFrameSize - StartSPOffset) : 0; } + ZFI->setSpillGPRRegs(LowGPR, HighGPR, StartSPOffset); // Create fixed stack objects for the remaining registers. + int CurrOffset = -SystemZMC::CallFrameSize; + if (usePackedStack(MF)) + CurrOffset += StartSPOffset; + for (auto &CS : CSI) { if (CS.getFrameIdx() != INT32_MAX) continue; @@ -234,11 +196,9 @@ static void addSavedGPR(MachineBasicBlock &MBB, MachineInstrBuilder &MIB, } } -bool SystemZFrameLowering:: -spillCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - const std::vector<CalleeSavedInfo> &CSI, - const TargetRegisterInfo *TRI) const { +bool SystemZFrameLowering::spillCalleeSavedRegisters( + MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { if (CSI.empty()) return false; @@ -296,11 +256,9 @@ spillCalleeSavedRegisters(MachineBasicBlock &MBB, return true; } -bool SystemZFrameLowering:: -restoreCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - std::vector<CalleeSavedInfo> &CSI, - const TargetRegisterInfo *TRI) const { +bool SystemZFrameLowering::restoreCalleeSavedRegisters( + MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { if (CSI.empty()) return false; @@ -358,9 +316,10 @@ void SystemZFrameLowering:: processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *RS) const { MachineFrameInfo &MFFrame = MF.getFrameInfo(); + bool BackChain = MF.getFunction().hasFnAttribute("backchain"); - if (!usePackedStack(MF)) - // Always create the full incoming register save area. + if (!usePackedStack(MF) || BackChain) + // Create the incoming register save area. getOrCreateFramePointerSaveIndex(MF); // Get the size of our stack frame to be allocated ... @@ -382,16 +341,15 @@ processFunctionBeforeFrameFinalized(MachineFunction &MF, // are outside the reach of an unsigned 12-bit displacement. // Create 2 for the case where both addresses in an MVC are // out of range. - RS->addScavengingFrameIndex(MFFrame.CreateStackObject(8, 8, false)); - RS->addScavengingFrameIndex(MFFrame.CreateStackObject(8, 8, false)); + RS->addScavengingFrameIndex(MFFrame.CreateStackObject(8, Align(8), false)); + RS->addScavengingFrameIndex(MFFrame.CreateStackObject(8, Align(8), false)); } } // Emit instructions before MBBI (in MBB) to add NumBytes to Reg. static void emitIncrement(MachineBasicBlock &MBB, - MachineBasicBlock::iterator &MBBI, - const DebugLoc &DL, - unsigned Reg, int64_t NumBytes, + MachineBasicBlock::iterator &MBBI, const DebugLoc &DL, + Register Reg, int64_t NumBytes, const TargetInstrInfo *TII) { while (NumBytes) { unsigned Opcode; @@ -416,12 +374,39 @@ static void emitIncrement(MachineBasicBlock &MBB, } } +// Add CFI for the new CFA offset. +static void buildCFAOffs(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + const DebugLoc &DL, int Offset, + const SystemZInstrInfo *ZII) { + unsigned CFIIndex = MBB.getParent()->addFrameInst( + MCCFIInstruction::cfiDefCfaOffset(nullptr, -Offset)); + BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex); +} + +// Add CFI for the new frame location. +static void buildDefCFAReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + const DebugLoc &DL, unsigned Reg, + const SystemZInstrInfo *ZII) { + MachineFunction &MF = *MBB.getParent(); + MachineModuleInfo &MMI = MF.getMMI(); + const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); + unsigned RegNum = MRI->getDwarfRegNum(Reg, true); + unsigned CFIIndex = MF.addFrameInst( + MCCFIInstruction::createDefCfaRegister(nullptr, RegNum)); + BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex); +} + void SystemZFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const { assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); + const SystemZSubtarget &STI = MF.getSubtarget<SystemZSubtarget>(); + const SystemZTargetLowering &TLI = *STI.getTargetLowering(); MachineFrameInfo &MFFrame = MF.getFrameInfo(); - auto *ZII = - static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo()); + auto *ZII = static_cast<const SystemZInstrInfo *>(STI.getInstrInfo()); SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); MachineBasicBlock::iterator MBBI = MBB.begin(); MachineModuleInfo &MMI = MF.getMMI(); @@ -504,19 +489,31 @@ void SystemZFrameLowering::emitPrologue(MachineFunction &MF, // Allocate StackSize bytes. int64_t Delta = -int64_t(StackSize); - emitIncrement(MBB, MBBI, DL, SystemZ::R15D, Delta, ZII); - - // Add CFI for the allocation. - unsigned CFIIndex = MF.addFrameInst( - MCCFIInstruction::createDefCfaOffset(nullptr, SPOffsetFromCFA + Delta)); - BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION)) - .addCFIIndex(CFIIndex); + const unsigned ProbeSize = TLI.getStackProbeSize(MF); + bool FreeProbe = (ZFI->getSpillGPRRegs().GPROffset && + (ZFI->getSpillGPRRegs().GPROffset + StackSize) < ProbeSize); + if (!FreeProbe && + MF.getSubtarget().getTargetLowering()->hasInlineStackProbe(MF)) { + // Stack probing may involve looping, but splitting the prologue block + // is not possible at this point since it would invalidate the + // SaveBlocks / RestoreBlocks sets of PEI in the single block function + // case. Build a pseudo to be handled later by inlineStackProbe(). + BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::PROBED_STACKALLOC)) + .addImm(StackSize); + } + else { + emitIncrement(MBB, MBBI, DL, SystemZ::R15D, Delta, ZII); + buildCFAOffs(MBB, MBBI, DL, SPOffsetFromCFA + Delta, ZII); + } SPOffsetFromCFA += Delta; - if (StoreBackchain) + if (StoreBackchain) { + // The back chain is stored topmost with packed-stack. + int Offset = usePackedStack(MF) ? SystemZMC::CallFrameSize - 8 : 0; BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::STG)) - .addReg(SystemZ::R1D, RegState::Kill).addReg(SystemZ::R15D).addImm(0) - .addReg(0); + .addReg(SystemZ::R1D, RegState::Kill).addReg(SystemZ::R15D) + .addImm(Offset).addReg(0); + } } if (HasFP) { @@ -525,11 +522,7 @@ void SystemZFrameLowering::emitPrologue(MachineFunction &MF, .addReg(SystemZ::R15D); // Add CFI for the new frame location. - unsigned HardFP = MRI->getDwarfRegNum(SystemZ::R11D, true); - unsigned CFIIndex = MF.addFrameInst( - MCCFIInstruction::createDefCfaRegister(nullptr, HardFP)); - BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION)) - .addCFIIndex(CFIIndex); + buildDefCFAReg(MBB, MBBI, DL, SystemZ::R11D, ZII); // Mark the FramePtr as live at the beginning of every block except // the entry block. (We'll have marked R11 as live on entry when @@ -560,7 +553,7 @@ void SystemZFrameLowering::emitPrologue(MachineFunction &MF, // Add CFI for the this save. unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true); - unsigned IgnoredFrameReg; + Register IgnoredFrameReg; int64_t Offset = getFrameIndexReference(MF, Save.getFrameIdx(), IgnoredFrameReg); @@ -622,6 +615,91 @@ void SystemZFrameLowering::emitEpilogue(MachineFunction &MF, } } +void SystemZFrameLowering::inlineStackProbe(MachineFunction &MF, + MachineBasicBlock &PrologMBB) const { + auto *ZII = + static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo()); + const SystemZSubtarget &STI = MF.getSubtarget<SystemZSubtarget>(); + const SystemZTargetLowering &TLI = *STI.getTargetLowering(); + + MachineInstr *StackAllocMI = nullptr; + for (MachineInstr &MI : PrologMBB) + if (MI.getOpcode() == SystemZ::PROBED_STACKALLOC) { + StackAllocMI = &MI; + break; + } + if (StackAllocMI == nullptr) + return; + uint64_t StackSize = StackAllocMI->getOperand(0).getImm(); + const unsigned ProbeSize = TLI.getStackProbeSize(MF); + uint64_t NumFullBlocks = StackSize / ProbeSize; + uint64_t Residual = StackSize % ProbeSize; + int64_t SPOffsetFromCFA = -SystemZMC::CFAOffsetFromInitialSP; + MachineBasicBlock *MBB = &PrologMBB; + MachineBasicBlock::iterator MBBI = StackAllocMI; + const DebugLoc DL = StackAllocMI->getDebugLoc(); + + // Allocate a block of Size bytes on the stack and probe it. + auto allocateAndProbe = [&](MachineBasicBlock &InsMBB, + MachineBasicBlock::iterator InsPt, unsigned Size, + bool EmitCFI) -> void { + emitIncrement(InsMBB, InsPt, DL, SystemZ::R15D, -int64_t(Size), ZII); + if (EmitCFI) { + SPOffsetFromCFA -= Size; + buildCFAOffs(InsMBB, InsPt, DL, SPOffsetFromCFA, ZII); + } + // Probe by means of a volatile compare. + MachineMemOperand *MMO = MF.getMachineMemOperand(MachinePointerInfo(), + MachineMemOperand::MOVolatile | MachineMemOperand::MOLoad, 8, Align(1)); + BuildMI(InsMBB, InsPt, DL, ZII->get(SystemZ::CG)) + .addReg(SystemZ::R0D, RegState::Undef) + .addReg(SystemZ::R15D).addImm(Size - 8).addReg(0) + .addMemOperand(MMO); + }; + + if (NumFullBlocks < 3) { + // Emit unrolled probe statements. + for (unsigned int i = 0; i < NumFullBlocks; i++) + allocateAndProbe(*MBB, MBBI, ProbeSize, true/*EmitCFI*/); + } else { + // Emit a loop probing the pages. + uint64_t LoopAlloc = ProbeSize * NumFullBlocks; + SPOffsetFromCFA -= LoopAlloc; + + BuildMI(*MBB, MBBI, DL, ZII->get(SystemZ::LGR), SystemZ::R1D) + .addReg(SystemZ::R15D); + buildDefCFAReg(*MBB, MBBI, DL, SystemZ::R1D, ZII); + emitIncrement(*MBB, MBBI, DL, SystemZ::R1D, -int64_t(LoopAlloc), ZII); + buildCFAOffs(*MBB, MBBI, DL, -int64_t(SystemZMC::CallFrameSize + LoopAlloc), + ZII); + + MachineBasicBlock *DoneMBB = SystemZ::splitBlockBefore(MBBI, MBB); + MachineBasicBlock *LoopMBB = SystemZ::emitBlockAfter(MBB); + MBB->addSuccessor(LoopMBB); + LoopMBB->addSuccessor(LoopMBB); + LoopMBB->addSuccessor(DoneMBB); + + MBB = LoopMBB; + allocateAndProbe(*MBB, MBB->end(), ProbeSize, false/*EmitCFI*/); + BuildMI(*MBB, MBB->end(), DL, ZII->get(SystemZ::CLGR)) + .addReg(SystemZ::R15D).addReg(SystemZ::R1D); + BuildMI(*MBB, MBB->end(), DL, ZII->get(SystemZ::BRC)) + .addImm(SystemZ::CCMASK_ICMP).addImm(SystemZ::CCMASK_CMP_GT).addMBB(MBB); + + MBB = DoneMBB; + MBBI = DoneMBB->begin(); + buildDefCFAReg(*MBB, MBBI, DL, SystemZ::R15D, ZII); + + recomputeLiveIns(*DoneMBB); + recomputeLiveIns(*LoopMBB); + } + + if (Residual) + allocateAndProbe(*MBB, MBBI, Residual, true/*EmitCFI*/); + + StackAllocMI->eraseFromParent(); +} + bool SystemZFrameLowering::hasFP(const MachineFunction &MF) const { return (MF.getTarget().Options.DisableFramePointerElim(MF) || MF.getFrameInfo().hasVarSizedObjects() || @@ -639,7 +717,7 @@ SystemZFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { int SystemZFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, - unsigned &FrameReg) const { + Register &FrameReg) const { // Our incoming SP is actually SystemZMC::CallFrameSize below the CFA, so // add that difference here. int64_t Offset = @@ -664,14 +742,43 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, } } +unsigned SystemZFrameLowering::getRegSpillOffset(MachineFunction &MF, + Register Reg) const { + bool IsVarArg = MF.getFunction().isVarArg(); + bool BackChain = MF.getFunction().hasFnAttribute("backchain"); + bool SoftFloat = MF.getSubtarget<SystemZSubtarget>().hasSoftFloat(); + unsigned Offset = RegSpillOffsets[Reg]; + if (usePackedStack(MF) && !(IsVarArg && !SoftFloat)) { + if (SystemZ::GR64BitRegClass.contains(Reg)) + // Put all GPRs at the top of the Register save area with packed + // stack. Make room for the backchain if needed. + Offset += BackChain ? 24 : 32; + else + Offset = 0; + } + return Offset; +} + int SystemZFrameLowering:: getOrCreateFramePointerSaveIndex(MachineFunction &MF) const { SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); int FI = ZFI->getFramePointerSaveIndex(); if (!FI) { MachineFrameInfo &MFFrame = MF.getFrameInfo(); - FI = MFFrame.CreateFixedObject(8, -SystemZMC::CallFrameSize, false); + // The back chain is stored topmost with packed-stack. + int Offset = usePackedStack(MF) ? -8 : -SystemZMC::CallFrameSize; + FI = MFFrame.CreateFixedObject(8, Offset, false); ZFI->setFramePointerSaveIndex(FI); } return FI; } + +bool SystemZFrameLowering::usePackedStack(MachineFunction &MF) const { + bool HasPackedStackAttr = MF.getFunction().hasFnAttribute("packed-stack"); + bool BackChain = MF.getFunction().hasFnAttribute("backchain"); + bool SoftFloat = MF.getSubtarget<SystemZSubtarget>().hasSoftFloat(); + if (HasPackedStackAttr && BackChain && !SoftFloat) + report_fatal_error("packed-stack + backchain + hard-float is unsupported."); + bool CallConv = MF.getFunction().getCallingConv() != CallingConv::GHC; + return HasPackedStackAttr && CallConv; +} |