diff --git a/llvm/lib/Target/SystemZ/SystemZCallingConv.td b/llvm/lib/Target/SystemZ/SystemZCallingConv.td --- a/llvm/lib/Target/SystemZ/SystemZCallingConv.td +++ b/llvm/lib/Target/SystemZ/SystemZCallingConv.td @@ -162,11 +162,7 @@ //===----------------------------------------------------------------------===// // z/OS XPLINK64 callee-saved registers //===----------------------------------------------------------------------===// -// %R7D is volatile by the spec, but it must be saved in the prologue by -// any non-leaf function and restored in the epilogue for use by the -// return instruction so it functions exactly like a callee-saved register. -def CSR_SystemZ_XPLINK64 : CalleeSavedRegs<(add (sequence "R%dD", 7, 15), - (sequence "R%dD", 4, 4), +def CSR_SystemZ_XPLINK64 : CalleeSavedRegs<(add (sequence "R%dD", 8, 15), (sequence "F%dD", 15, 8))>; def CSR_SystemZ_XPLINK64_Vector : CalleeSavedRegs<(add CSR_SystemZ_XPLINK64, 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 @@ -918,72 +918,74 @@ SystemZMachineFunctionInfo *MFI = MF.getInfo(); const SystemZSubtarget &Subtarget = MF.getSubtarget(); auto &Regs = Subtarget.getSpecialRegisters(); + auto &GRRegClass = SystemZ::GR64BitRegClass; + + // For non-leaf functions: + // - the address of callee (entry point) register R6 must be saved + CSI.push_back(CalleeSavedInfo(Regs.getAddressOfCalleeRegister())); + CSI.back().setRestored(false); + + // The return address register R7 must be saved and restored. + CSI.push_back(CalleeSavedInfo(Regs.getReturnFunctionAddressRegister())); + + // 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")) + CSI.push_back(CalleeSavedInfo(Regs.getStackPointerRegister())); // Scan the call-saved GPRs and find the bounds of the register spill area. - unsigned LowGPR = 0; - int LowOffset = INT32_MAX; - unsigned HighGPR = LowGPR; + Register LowRestoreGPR = 0; + int LowRestoreOffset = INT32_MAX; + Register LowSpillGPR = 0; + int LowSpillOffset = INT32_MAX; + Register HighGPR = 0; int HighOffset = -1; - unsigned RegSP = Regs.getStackPointerRegister(); - auto &GRRegClass = SystemZ::GR64BitRegClass; - const unsigned RegSize = 8; + for (auto &CS : CSI) { + Register Reg = CS.getReg(); + int Offset = RegSpillOffsets[Reg]; + if (Offset >= 0) { + if (GRRegClass.contains(Reg)) { + if (LowSpillOffset > Offset) { + LowSpillOffset = Offset; + LowSpillGPR = Reg; + } + if (CS.isRestored() && LowRestoreOffset > Offset) { + LowRestoreOffset = Offset; + LowRestoreGPR = Reg; + } - auto ProcessCSI = [&](std::vector &CSIList) { - for (auto &CS : CSIList) { - Register 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; - } + if (Offset > HighOffset) { + HighOffset = Offset; + HighGPR = Reg; } + // Non-volatile GPRs are saved in the dedicated register save area at + // the bottom of the stack and are not truly part of the "normal" stack + // frame. Mark the frame index as NoAlloc to indicate it as such. + unsigned RegSize = 8; int FrameIdx = MFFrame.CreateFixedSpillStackObject(RegSize, Offset); CS.setFrameIdx(FrameIdx); - } else - CS.setFrameIdx(INT32_MAX); + MFFrame.setStackID(FrameIdx, TargetStackID::NoAlloc); + } + } else { + Register 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); } - }; - - std::vector 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); + if (LowRestoreGPR) + MFI->setRestoreGPRRegs(LowRestoreGPR, HighGPR, LowRestoreOffset); // 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; - Register 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); - } + assert(LowSpillGPR && "Expected registers to spill"); + MFI->setSpillGPRRegs(LowSpillGPR, HighGPR, LowSpillOffset); return true; } @@ -1001,13 +1003,6 @@ // 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(