diff --git a/llvm/lib/Target/SystemZ/SystemZFrameLowering.h b/llvm/lib/Target/SystemZ/SystemZFrameLowering.h --- a/llvm/lib/Target/SystemZ/SystemZFrameLowering.h +++ b/llvm/lib/Target/SystemZ/SystemZFrameLowering.h @@ -19,10 +19,27 @@ class SystemZSubtarget; class SystemZFrameLowering : public TargetFrameLowering { + +public: + SystemZFrameLowering(StackDirection D, Align StackAl, int LAO, Align TransAl, + bool StackReal); + + static std::unique_ptr + create(const SystemZSubtarget &STI); + + // Override TargetFrameLowering. + bool isFPCloseToIncomingSP() const override { return false; } + bool hasReservedCallFrame(const MachineFunction &MF) const override; + MachineBasicBlock::iterator + eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI) const override; +}; + +class SystemZELFFrameLowering : public SystemZFrameLowering { IndexedMap RegSpillOffsets; public: - SystemZFrameLowering(); + SystemZELFFrameLowering(); // Override TargetFrameLowering. bool isFPCloseToIncomingSP() const override { return false; } @@ -48,21 +65,14 @@ void inlineStackProbe(MachineFunction &MF, MachineBasicBlock &PrologMBB) const override; bool hasFP(const MachineFunction &MF) const override; - bool hasReservedCallFrame(const MachineFunction &MF) const override; StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const override; - MachineBasicBlock::iterator - eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI) const override; // Return the byte offset from the incoming stack pointer of Reg's // ABI-defined save slot. Return 0 if no slot is defined for Reg. Adjust // the offset in case MF has packed-stack. unsigned getRegSpillOffset(MachineFunction &MF, Register Reg) const; - // Get or create the frame index of where the old frame pointer is stored. - int getOrCreateFramePointerSaveIndex(MachineFunction &MF) const; - bool usePackedStack(MachineFunction &MF) const; // Return the offset of the backchain. @@ -70,6 +80,20 @@ // The back chain is stored topmost with packed-stack. return usePackedStack(MF) ? SystemZMC::ELFCallFrameSize - 8 : 0; } + + // Get or create the frame index of where the old frame pointer is stored. + int getOrCreateFramePointerSaveIndex(MachineFunction &MF) const; +}; + +class SystemZXPLINKFrameLowering : public SystemZFrameLowering { +public: + SystemZXPLINKFrameLowering(); + + void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; + + void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; + + bool hasFP(const MachineFunction &MF) const override; }; } // end namespace llvm diff --git a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp --- a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp @@ -46,27 +46,47 @@ }; } // 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) {} + +std::unique_ptr +SystemZFrameLowering::create(const SystemZSubtarget &STI) { + if (STI.isTargetXPLINK64()) + return std::make_unique(); + return std::make_unique(); +} - // 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; +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:: -assignCalleeSavedSpillSlots(MachineFunction &MF, - const TargetRegisterInfo *TRI, - std::vector &CSI) const { +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 SystemZELFFrameLowering::assignCalleeSavedSpillSlots( + MachineFunction &MF, const TargetRegisterInfo *TRI, + std::vector &CSI) const { SystemZMachineFunctionInfo *ZFI = MF.getInfo(); MachineFrameInfo &MFFrame = MF.getFrameInfo(); bool IsVarArg = MF.getFunction().isVarArg(); @@ -130,9 +150,9 @@ 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 +199,23 @@ } } +SystemZELFFrameLowering::SystemZELFFrameLowering() + : SystemZFrameLowering(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. + + // 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; +} + // 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 +233,7 @@ } } -bool SystemZFrameLowering::spillCalleeSavedRegisters( +bool SystemZELFFrameLowering::spillCalleeSavedRegisters( MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, ArrayRef CSI, const TargetRegisterInfo *TRI) const { if (CSI.empty()) @@ -256,7 +293,7 @@ return true; } -bool SystemZFrameLowering::restoreCalleeSavedRegisters( +bool SystemZELFFrameLowering::restoreCalleeSavedRegisters( MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, MutableArrayRef CSI, const TargetRegisterInfo *TRI) const { if (CSI.empty()) @@ -312,9 +349,8 @@ 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(); MachineRegisterInfo *MRI = &MF.getRegInfo(); @@ -410,8 +446,8 @@ .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(); const SystemZTargetLowering &TLI = *STI.getTargetLowering(); @@ -573,15 +609,15 @@ } } -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(MF.getSubtarget().getInstrInfo()); SystemZMachineFunctionInfo *ZFI = MF.getInfo(); MachineFrameInfo &MFFrame = MF.getFrameInfo(); - // See SystemZFrameLowering::emitPrologue + // See SystemZELFFrameLowering::emitPrologue if (MF.getFunction().getCallingConv() == CallingConv::GHC) return; @@ -619,8 +655,8 @@ } } -void SystemZFrameLowering::inlineStackProbe(MachineFunction &MF, - MachineBasicBlock &PrologMBB) const { +void SystemZELFFrameLowering::inlineStackProbe( + MachineFunction &MF, MachineBasicBlock &PrologMBB) const { auto *ZII = static_cast(MF.getSubtarget().getInstrInfo()); const SystemZSubtarget &STI = MF.getSubtarget(); @@ -719,24 +755,14 @@ } } -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()->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 +770,8 @@ 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().hasSoftFloat(); @@ -778,8 +787,8 @@ return Offset; } -int SystemZFrameLowering:: -getOrCreateFramePointerSaveIndex(MachineFunction &MF) const { +int SystemZELFFrameLowering::getOrCreateFramePointerSaveIndex( + MachineFunction &MF) const { SystemZMachineFunctionInfo *ZFI = MF.getInfo(); int FI = ZFI->getFramePointerSaveIndex(); if (!FI) { @@ -791,7 +800,7 @@ 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().hasSoftFloat(); @@ -800,3 +809,17 @@ bool CallConv = MF.getFunction().getCallingConv() != CallingConv::GHC; return HasPackedStackAttr && CallConv; } + +SystemZXPLINKFrameLowering::SystemZXPLINKFrameLowering() + : SystemZFrameLowering(TargetFrameLowering::StackGrowsUp, Align(32), 128, + Align(32), false /* StackRealignable */) {} + +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; +} diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -1426,8 +1426,7 @@ MachineRegisterInfo &MRI = MF.getRegInfo(); SystemZMachineFunctionInfo *FuncInfo = MF.getInfo(); - auto *TFL = - static_cast(Subtarget.getFrameLowering()); + auto *TFL = Subtarget.getFrameLowering(); EVT PtrVT = getPointerTy(DAG.getDataLayout()); // Detect unsupported vector argument types. @@ -3320,8 +3319,7 @@ SDValue SystemZTargetLowering::lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { - auto *TFL = - static_cast(Subtarget.getFrameLowering()); + auto *TFL = Subtarget.getFrameLowering(); MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo &MFI = MF.getFrameInfo(); MFI.setFrameAddressIsTaken(true); @@ -8264,8 +8262,7 @@ SDValue SystemZTargetLowering:: getBackchainAddress(SDValue SP, SelectionDAG &DAG) const { MachineFunction &MF = DAG.getMachineFunction(); - auto *TFL = - static_cast(Subtarget.getFrameLowering()); + auto *TFL = Subtarget.getFrameLowering(); SDLoc DL(SP); return DAG.getNode(ISD::ADD, DL, MVT::i64, SP, DAG.getIntPtrConstant(TFL->getBackchainOffset(MF), DL)); diff --git a/llvm/lib/Target/SystemZ/SystemZSubtarget.h b/llvm/lib/Target/SystemZ/SystemZSubtarget.h --- a/llvm/lib/Target/SystemZ/SystemZSubtarget.h +++ b/llvm/lib/Target/SystemZ/SystemZSubtarget.h @@ -81,7 +81,7 @@ SystemZInstrInfo InstrInfo; SystemZTargetLowering TLInfo; SystemZSelectionDAGInfo TSInfo; - SystemZFrameLowering FrameLowering; + std::unique_ptr FrameLowering; SystemZSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS); @@ -97,8 +97,13 @@ } const TargetFrameLowering *getFrameLowering() const override { - return &FrameLowering; + return FrameLowering.get(); } + + template const TFL *getFrameLowering() const { + return static_cast(getFrameLowering()); + } + const SystemZInstrInfo *getInstrInfo() const override { return &InstrInfo; } const SystemZRegisterInfo *getRegisterInfo() const override { return &InstrInfo.getRegisterInfo(); diff --git a/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp b/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp --- a/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp +++ b/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp @@ -89,7 +89,7 @@ HasSoftFloat(false), TargetTriple(TT), SpecialRegisters(initializeSpecialRegisters()), InstrInfo(initializeSubtargetDependencies(CPU, FS)), TLInfo(TM, *this), - TSInfo(), FrameLowering() {} + TSInfo(), FrameLowering(SystemZFrameLowering::create(*this)) {} bool SystemZSubtarget::enableSubRegLiveness() const { return UseSubRegLiveness;