diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2021-11-19 20:06:13 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2021-11-19 20:06:13 +0000 |
| commit | c0981da47d5696fe36474fcf86b4ce03ae3ff818 (patch) | |
| tree | f42add1021b9f2ac6a69ac7cf6c4499962739a45 /llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp | |
| parent | 344a3780b2e33f6ca763666c380202b18aab72a3 (diff) | |
Diffstat (limited to 'llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp')
| -rw-r--r-- | llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp | 341 |
1 files changed, 270 insertions, 71 deletions
diff --git a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp index d2f6ff96158d..d11d118fb8ee 100644 --- a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp @@ -24,7 +24,7 @@ using namespace llvm; namespace { // The ABI-defined register save slots, relative to the CFA (i.e. // incoming stack pointer + SystemZMC::ELFCallFrameSize). -static const TargetFrameLowering::SpillSlot SpillOffsetTable[] = { +static const TargetFrameLowering::SpillSlot ELFSpillOffsetTable[] = { { SystemZ::R2D, 0x10 }, { SystemZ::R3D, 0x18 }, { SystemZ::R4D, 0x20 }, @@ -44,29 +44,55 @@ static const TargetFrameLowering::SpillSlot SpillOffsetTable[] = { { SystemZ::F4D, 0x90 }, { SystemZ::F6D, 0x98 } }; + +static const TargetFrameLowering::SpillSlot XPLINKSpillOffsetTable[] = { + {SystemZ::R4D, 0x00}, {SystemZ::R5D, 0x08}, {SystemZ::R6D, 0x10}, + {SystemZ::R7D, 0x18}, {SystemZ::R8D, 0x20}, {SystemZ::R9D, 0x28}, + {SystemZ::R10D, 0x30}, {SystemZ::R11D, 0x38}, {SystemZ::R12D, 0x40}, + {SystemZ::R13D, 0x48}, {SystemZ::R14D, 0x50}, {SystemZ::R15D, 0x58}}; } // end anonymous namespace -SystemZFrameLowering::SystemZFrameLowering() - : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(8), - 0, Align(8), false /* StackRealignable */), - RegSpillOffsets(0) { - // Due to the SystemZ ABI, the DWARF CFA (Canonical Frame Address) is not - // equal to the incoming stack pointer, but to incoming stack pointer plus - // 160. Instead of using a Local Area Offset, the Register save area will - // be occupied by fixed frame objects, and all offsets are actually - // relative to CFA. +SystemZFrameLowering::SystemZFrameLowering(StackDirection D, Align StackAl, + int LAO, Align TransAl, + bool StackReal) + : TargetFrameLowering(D, StackAl, LAO, TransAl, StackReal) {} - // Create a mapping from register number to save slot offset. - // These offsets are relative to the start of the register save area. - RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS); - for (unsigned I = 0, E = array_lengthof(SpillOffsetTable); I != E; ++I) - RegSpillOffsets[SpillOffsetTable[I].Reg] = SpillOffsetTable[I].Offset; +std::unique_ptr<SystemZFrameLowering> +SystemZFrameLowering::create(const SystemZSubtarget &STI) { + if (STI.isTargetXPLINK64()) + return std::make_unique<SystemZXPLINKFrameLowering>(); + return std::make_unique<SystemZELFFrameLowering>(); +} + +MachineBasicBlock::iterator SystemZFrameLowering::eliminateCallFramePseudoInstr( + MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI) const { + switch (MI->getOpcode()) { + case SystemZ::ADJCALLSTACKDOWN: + case SystemZ::ADJCALLSTACKUP: + assert(hasReservedCallFrame(MF) && + "ADJSTACKDOWN and ADJSTACKUP should be no-ops"); + return MBB.erase(MI); + break; + + default: + llvm_unreachable("Unexpected call frame instruction"); + } +} + +bool SystemZFrameLowering::hasReservedCallFrame( + const MachineFunction &MF) const { + // The ELF ABI requires us to allocate 160 bytes of stack space for the + // callee, with any outgoing stack arguments being placed above that. It + // seems better to make that area a permanent feature of the frame even if + // we're using a frame pointer. Similarly, 64-bit XPLINK requires 96 bytes + // of stack space for the register save area. + return true; } -bool SystemZFrameLowering:: -assignCalleeSavedSpillSlots(MachineFunction &MF, - const TargetRegisterInfo *TRI, - std::vector<CalleeSavedInfo> &CSI) const { +bool SystemZELFFrameLowering::assignCalleeSavedSpillSlots( + MachineFunction &MF, const TargetRegisterInfo *TRI, + std::vector<CalleeSavedInfo> &CSI) const { SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); MachineFrameInfo &MFFrame = MF.getFrameInfo(); bool IsVarArg = MF.getFunction().isVarArg(); @@ -130,9 +156,9 @@ assignCalleeSavedSpillSlots(MachineFunction &MF, return true; } -void SystemZFrameLowering::determineCalleeSaves(MachineFunction &MF, - BitVector &SavedRegs, - RegScavenger *RS) const { +void SystemZELFFrameLowering::determineCalleeSaves(MachineFunction &MF, + BitVector &SavedRegs, + RegScavenger *RS) const { TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); MachineFrameInfo &MFFrame = MF.getFrameInfo(); @@ -179,6 +205,24 @@ void SystemZFrameLowering::determineCalleeSaves(MachineFunction &MF, } } +SystemZELFFrameLowering::SystemZELFFrameLowering() + : SystemZFrameLowering(TargetFrameLowering::StackGrowsDown, Align(8), 0, + Align(8), /* StackRealignable */ false), + RegSpillOffsets(0) { + + // Due to the SystemZ ABI, the DWARF CFA (Canonical Frame Address) is not + // equal to the incoming stack pointer, but to incoming stack pointer plus + // 160. Instead of using a Local Area Offset, the Register save area will + // be occupied by fixed frame objects, and all offsets are actually + // relative to CFA. + + // Create a mapping from register number to save slot offset. + // These offsets are relative to the start of the register save area. + RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS); + for (unsigned I = 0, E = array_lengthof(ELFSpillOffsetTable); I != E; ++I) + RegSpillOffsets[ELFSpillOffsetTable[I].Reg] = ELFSpillOffsetTable[I].Offset; +} + // Add GPR64 to the save instruction being built by MIB, which is in basic // block MBB. IsImplicit says whether this is an explicit operand to the // instruction, or an implicit one that comes between the explicit start @@ -196,7 +240,7 @@ static void addSavedGPR(MachineBasicBlock &MBB, MachineInstrBuilder &MIB, } } -bool SystemZFrameLowering::spillCalleeSavedRegisters( +bool SystemZELFFrameLowering::spillCalleeSavedRegisters( MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { if (CSI.empty()) @@ -256,7 +300,7 @@ bool SystemZFrameLowering::spillCalleeSavedRegisters( return true; } -bool SystemZFrameLowering::restoreCalleeSavedRegisters( +bool SystemZELFFrameLowering::restoreCalleeSavedRegisters( MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { if (CSI.empty()) @@ -312,9 +356,8 @@ bool SystemZFrameLowering::restoreCalleeSavedRegisters( return true; } -void SystemZFrameLowering:: -processFunctionBeforeFrameFinalized(MachineFunction &MF, - RegScavenger *RS) const { +void SystemZELFFrameLowering::processFunctionBeforeFrameFinalized( + MachineFunction &MF, RegScavenger *RS) const { MachineFrameInfo &MFFrame = MF.getFrameInfo(); SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); MachineRegisterInfo *MRI = &MF.getRegInfo(); @@ -410,8 +453,8 @@ static void buildDefCFAReg(MachineBasicBlock &MBB, .addCFIIndex(CFIIndex); } -void SystemZFrameLowering::emitPrologue(MachineFunction &MF, - MachineBasicBlock &MBB) const { +void SystemZELFFrameLowering::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(); @@ -530,8 +573,8 @@ void SystemZFrameLowering::emitPrologue(MachineFunction &MF, // 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 // saving the GPRs.) - for (auto I = std::next(MF.begin()), E = MF.end(); I != E; ++I) - I->addLiveIn(SystemZ::R11D); + for (MachineBasicBlock &MBBJ : llvm::drop_begin(MF)) + MBBJ.addLiveIn(SystemZ::R11D); } // Skip over the FPR/VR saves. @@ -573,15 +616,15 @@ void SystemZFrameLowering::emitPrologue(MachineFunction &MF, } } -void SystemZFrameLowering::emitEpilogue(MachineFunction &MF, - MachineBasicBlock &MBB) const { +void SystemZELFFrameLowering::emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); auto *ZII = static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo()); SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); MachineFrameInfo &MFFrame = MF.getFrameInfo(); - // See SystemZFrameLowering::emitPrologue + // See SystemZELFFrameLowering::emitPrologue if (MF.getFunction().getCallingConv() == CallingConv::GHC) return; @@ -619,8 +662,8 @@ void SystemZFrameLowering::emitEpilogue(MachineFunction &MF, } } -void SystemZFrameLowering::inlineStackProbe(MachineFunction &MF, - MachineBasicBlock &PrologMBB) const { +void SystemZELFFrameLowering::inlineStackProbe( + MachineFunction &MF, MachineBasicBlock &PrologMBB) const { auto *ZII = static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo()); const SystemZSubtarget &STI = MF.getSubtarget<SystemZSubtarget>(); @@ -719,24 +762,14 @@ void SystemZFrameLowering::inlineStackProbe(MachineFunction &MF, } } -bool SystemZFrameLowering::hasFP(const MachineFunction &MF) const { +bool SystemZELFFrameLowering::hasFP(const MachineFunction &MF) const { return (MF.getTarget().Options.DisableFramePointerElim(MF) || MF.getFrameInfo().hasVarSizedObjects() || MF.getInfo<SystemZMachineFunctionInfo>()->getManipulatesSP()); } -bool -SystemZFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { - // The ABI requires us to allocate 160 bytes of stack space for the callee, - // with any outgoing stack arguments being placed above that. It seems - // better to make that area a permanent feature of the frame even if - // we're using a frame pointer. - return true; -} - -StackOffset -SystemZFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, - Register &FrameReg) const { +StackOffset SystemZELFFrameLowering::getFrameIndexReference( + const MachineFunction &MF, int FI, Register &FrameReg) const { // Our incoming SP is actually SystemZMC::ELFCallFrameSize below the CFA, so // add that difference here. StackOffset Offset = @@ -744,25 +777,8 @@ SystemZFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, return Offset + StackOffset::getFixed(SystemZMC::ELFCallFrameSize); } -MachineBasicBlock::iterator SystemZFrameLowering:: -eliminateCallFramePseudoInstr(MachineFunction &MF, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI) const { - switch (MI->getOpcode()) { - case SystemZ::ADJCALLSTACKDOWN: - case SystemZ::ADJCALLSTACKUP: - assert(hasReservedCallFrame(MF) && - "ADJSTACKDOWN and ADJSTACKUP should be no-ops"); - return MBB.erase(MI); - break; - - default: - llvm_unreachable("Unexpected call frame instruction"); - } -} - -unsigned SystemZFrameLowering::getRegSpillOffset(MachineFunction &MF, - Register Reg) const { +unsigned SystemZELFFrameLowering::getRegSpillOffset(MachineFunction &MF, + Register Reg) const { bool IsVarArg = MF.getFunction().isVarArg(); bool BackChain = MF.getFunction().hasFnAttribute("backchain"); bool SoftFloat = MF.getSubtarget<SystemZSubtarget>().hasSoftFloat(); @@ -778,8 +794,8 @@ unsigned SystemZFrameLowering::getRegSpillOffset(MachineFunction &MF, return Offset; } -int SystemZFrameLowering:: -getOrCreateFramePointerSaveIndex(MachineFunction &MF) const { +int SystemZELFFrameLowering::getOrCreateFramePointerSaveIndex( + MachineFunction &MF) const { SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); int FI = ZFI->getFramePointerSaveIndex(); if (!FI) { @@ -791,7 +807,7 @@ getOrCreateFramePointerSaveIndex(MachineFunction &MF) const { return FI; } -bool SystemZFrameLowering::usePackedStack(MachineFunction &MF) const { +bool SystemZELFFrameLowering::usePackedStack(MachineFunction &MF) const { bool HasPackedStackAttr = MF.getFunction().hasFnAttribute("packed-stack"); bool BackChain = MF.getFunction().hasFnAttribute("backchain"); bool SoftFloat = MF.getSubtarget<SystemZSubtarget>().hasSoftFloat(); @@ -800,3 +816,186 @@ bool SystemZFrameLowering::usePackedStack(MachineFunction &MF) const { bool CallConv = MF.getFunction().getCallingConv() != CallingConv::GHC; return HasPackedStackAttr && CallConv; } + +SystemZXPLINKFrameLowering::SystemZXPLINKFrameLowering() + : SystemZFrameLowering(TargetFrameLowering::StackGrowsUp, Align(32), 128, + Align(32), /* StackRealignable */ false), + RegSpillOffsets(-1) { + + // Create a mapping from register number to save slot offset. + // These offsets are relative to the start of the local are area. + RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS); + for (unsigned I = 0, E = array_lengthof(XPLINKSpillOffsetTable); I != E; ++I) + RegSpillOffsets[XPLINKSpillOffsetTable[I].Reg] = + XPLINKSpillOffsetTable[I].Offset; +} + +bool SystemZXPLINKFrameLowering::assignCalleeSavedSpillSlots( + MachineFunction &MF, const TargetRegisterInfo *TRI, + std::vector<CalleeSavedInfo> &CSI) const { + MachineFrameInfo &MFFrame = MF.getFrameInfo(); + SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>(); + const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>(); + auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>(); + + // Scan the call-saved GPRs and find the bounds of the register spill area. + unsigned LowGPR = 0; + int LowOffset = INT32_MAX; + unsigned HighGPR = LowGPR; + int HighOffset = -1; + + unsigned RegSP = Regs.getStackPointerRegister(); + auto &GRRegClass = SystemZ::GR64BitRegClass; + const unsigned RegSize = 8; + + auto ProcessCSI = [&](std::vector<CalleeSavedInfo> &CSIList) { + for (auto &CS : CSIList) { + unsigned Reg = CS.getReg(); + int Offset = RegSpillOffsets[Reg]; + if (Offset >= 0) { + if (GRRegClass.contains(Reg)) { + if (LowOffset > Offset) { + LowOffset = Offset; + LowGPR = Reg; + } + + if (Offset > HighOffset) { + HighOffset = Offset; + HighGPR = Reg; + } + } + int FrameIdx = MFFrame.CreateFixedSpillStackObject(RegSize, Offset); + CS.setFrameIdx(FrameIdx); + } else + CS.setFrameIdx(INT32_MAX); + } + }; + + std::vector<CalleeSavedInfo> Spills; + + // For non-leaf functions: + // - the address of callee (entry point) register R6 must be saved + Spills.push_back(CalleeSavedInfo(Regs.getAddressOfCalleeRegister())); + + // If the function needs a frame pointer, or if the backchain pointer should + // be stored, then save the stack pointer register R4. + if (hasFP(MF) || MF.getFunction().hasFnAttribute("backchain")) + Spills.push_back(CalleeSavedInfo(RegSP)); + + // Save the range of call-saved registers, for use by the + // prologue/epilogue inserters. + ProcessCSI(CSI); + MFI->setRestoreGPRRegs(LowGPR, HighGPR, LowOffset); + + // Save the range of call-saved registers, for use by the epilogue inserter. + ProcessCSI(Spills); + MFI->setSpillGPRRegs(LowGPR, HighGPR, LowOffset); + + // Create spill slots for the remaining registers. + for (auto &CS : CSI) { + if (CS.getFrameIdx() != INT32_MAX) + continue; + unsigned Reg = CS.getReg(); + const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); + Align Alignment = TRI->getSpillAlign(*RC); + unsigned Size = TRI->getSpillSize(*RC); + Alignment = std::min(Alignment, getStackAlign()); + int FrameIdx = MFFrame.CreateStackObject(Size, Alignment, true); + CS.setFrameIdx(FrameIdx); + } + + return true; +} + +void SystemZXPLINKFrameLowering::determineCalleeSaves(MachineFunction &MF, + BitVector &SavedRegs, + RegScavenger *RS) const { + TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); + + bool HasFP = hasFP(MF); + const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>(); + auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>(); + + // If the function requires a frame pointer, record that the hard + // frame pointer will be clobbered. + if (HasFP) + SavedRegs.set(Regs.getFramePointerRegister()); + + // If the function is not an XPLeaf function, we need to save the + // return address register. We also always use that register for + // the return instruction, so it needs to be restored in the + // epilogue even though that register is considered to be volatile. + // #TODO: Implement leaf detection. + SavedRegs.set(Regs.getReturnFunctionAddressRegister()); +} + +bool SystemZXPLINKFrameLowering::spillCalleeSavedRegisters( + MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { + if (CSI.empty()) + return true; + + MachineFunction &MF = *MBB.getParent(); + SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); + const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); + auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>(); + SystemZ::GPRRegs SpillGPRs = ZFI->getSpillGPRRegs(); + DebugLoc DL; + + // Save GPRs + if (SpillGPRs.LowGPR) { + assert(SpillGPRs.LowGPR != SpillGPRs.HighGPR && + "Should be saving multiple registers"); + + // Build an STM/STMG instruction. + MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::STMG)); + + // Add the explicit register operands. + addSavedGPR(MBB, MIB, SpillGPRs.LowGPR, false); + addSavedGPR(MBB, MIB, SpillGPRs.HighGPR, false); + + // Add the address r4 + MIB.addReg(Regs.getStackPointerRegister()); + + // Add the partial offset + // We cannot add the actual offset as, at the stack is not finalized + MIB.addImm(SpillGPRs.GPROffset); + + // Make sure all call-saved GPRs are included as operands and are + // marked as live on entry. + auto &GRRegClass = SystemZ::GR64BitRegClass; + for (unsigned I = 0, E = CSI.size(); I != E; ++I) { + unsigned Reg = CSI[I].getReg(); + if (GRRegClass.contains(Reg)) + addSavedGPR(MBB, MIB, Reg, true); + } + } + + // Spill FPRs to the stack in the normal TargetInstrInfo way + for (unsigned I = 0, E = CSI.size(); I != E; ++I) { + unsigned Reg = CSI[I].getReg(); + if (SystemZ::FP64BitRegClass.contains(Reg)) { + MBB.addLiveIn(Reg); + TII->storeRegToStackSlot(MBB, MBBI, Reg, true, CSI[I].getFrameIdx(), + &SystemZ::FP64BitRegClass, TRI); + } + if (SystemZ::VR128BitRegClass.contains(Reg)) { + MBB.addLiveIn(Reg); + TII->storeRegToStackSlot(MBB, MBBI, Reg, true, CSI[I].getFrameIdx(), + &SystemZ::VR128BitRegClass, TRI); + } + } + + return true; +} + +void SystemZXPLINKFrameLowering::emitPrologue(MachineFunction &MF, + MachineBasicBlock &MBB) const {} + +void SystemZXPLINKFrameLowering::emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const {} + +bool SystemZXPLINKFrameLowering::hasFP(const MachineFunction &MF) const { + return false; +} |
