From b106b60456d2c5075c89634b6774a63a51c33e74 Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Thu, 16 Jul 2009 14:23:01 +0000 Subject: [PATCH] Handle FP callee-saved regs llvm-svn: 76029 --- llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp | 116 +++++++++++------- llvm/lib/Target/SystemZ/SystemZInstrInfo.td | 3 +- .../Target/SystemZ/SystemZRegisterInfo.cpp | 26 +++- 3 files changed, 98 insertions(+), 47 deletions(-) diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp index 61f6e939e81f..0826437f3330 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -186,50 +186,71 @@ bool SystemZInstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const std::vector &CSI) const { + if (CSI.empty()) + return false; + DebugLoc DL = DebugLoc::getUnknownLoc(); if (MI != MBB.end()) DL = MI->getDebugLoc(); MachineFunction &MF = *MBB.getParent(); SystemZMachineFunctionInfo *MFI = MF.getInfo(); - MFI->setCalleeSavedFrameSize(CSI.size() * 8); + unsigned CalleeFrameSize = 0; // Scan the callee-saved and find the bounds of register spill area. unsigned LowReg = 0, HighReg = 0, StartOffset = -1U, EndOffset = 0; for (unsigned i = 0, e = CSI.size(); i != e; ++i) { unsigned Reg = CSI[i].getReg(); - unsigned Offset = RegSpillOffsets[Reg]; - if (StartOffset > Offset) { - LowReg = Reg; StartOffset = Offset; - } - if (EndOffset < Offset) { - HighReg = Reg; EndOffset = RegSpillOffsets[Reg]; + const TargetRegisterClass *RegClass = CSI[i].getRegClass(); + if (RegClass != &SystemZ::FP64RegClass) { + unsigned Offset = RegSpillOffsets[Reg]; + CalleeFrameSize += 8; + if (StartOffset > Offset) { + LowReg = Reg; StartOffset = Offset; + } + if (EndOffset < Offset) { + HighReg = Reg; EndOffset = RegSpillOffsets[Reg]; + } } } // Save information for epilogue inserter. + MFI->setCalleeSavedFrameSize(CalleeFrameSize); MFI->setLowReg(LowReg); MFI->setHighReg(HighReg); - // Build a store instruction. Use STORE MULTIPLE instruction if there are many - // registers to store, otherwise - just STORE. - MachineInstrBuilder MIB = - BuildMI(MBB, MI, DL, get((LowReg == HighReg ? - SystemZ::MOV64mr : SystemZ::MOV64mrm))); + // Save GPRs + if (StartOffset) { + // Build a store instruction. Use STORE MULTIPLE instruction if there are many + // registers to store, otherwise - just STORE. + MachineInstrBuilder MIB = + BuildMI(MBB, MI, DL, get((LowReg == HighReg ? + SystemZ::MOV64mr : SystemZ::MOV64mrm))); - // Add store operands. - MIB.addReg(SystemZ::R15D).addImm(StartOffset); - if (LowReg == HighReg) - MIB.addReg(0); - MIB.addReg(LowReg, RegState::Kill); - if (LowReg != HighReg) - MIB.addReg(HighReg, RegState::Kill); + // Add store operands. + MIB.addReg(SystemZ::R15D).addImm(StartOffset); + if (LowReg == HighReg) + MIB.addReg(0); + MIB.addReg(LowReg, RegState::Kill); + if (LowReg != HighReg) + MIB.addReg(HighReg, RegState::Kill); - // Do a second scan adding regs as being killed by instruction + // Do a second scan adding regs as being killed by instruction + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + unsigned Reg = CSI[i].getReg(); + // Add the callee-saved register as live-in. It's killed at the spill. + MBB.addLiveIn(Reg); + if (Reg != LowReg && Reg != HighReg) + MIB.addReg(Reg, RegState::ImplicitKill); + } + } + + // Save FPRs for (unsigned i = 0, e = CSI.size(); i != e; ++i) { unsigned Reg = CSI[i].getReg(); - // Add the callee-saved register as live-in. It's killed at the spill. - MBB.addLiveIn(Reg); - if (Reg != LowReg && Reg != HighReg) - MIB.addReg(Reg, RegState::ImplicitKill); + const TargetRegisterClass *RegClass = CSI[i].getRegClass(); + if (RegClass == &SystemZ::FP64RegClass) { + MBB.addLiveIn(Reg); + storeRegToStackSlot(MBB, MI, Reg, true, CSI[i].getFrameIdx(), RegClass); + } } return true; @@ -249,29 +270,40 @@ SystemZInstrInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, const TargetRegisterInfo *RegInfo= MF.getTarget().getRegisterInfo(); SystemZMachineFunctionInfo *MFI = MF.getInfo(); + // Restore FP registers + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + unsigned Reg = CSI[i].getReg(); + const TargetRegisterClass *RegClass = CSI[i].getRegClass(); + if (RegClass == &SystemZ::FP64RegClass) + loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), RegClass); + } + + // Restore GP registers unsigned LowReg = MFI->getLowReg(), HighReg = MFI->getHighReg(); unsigned StartOffset = RegSpillOffsets[LowReg]; - // Build a load instruction. Use LOAD MULTIPLE instruction if there are many - // registers to load, otherwise - just LOAD. - MachineInstrBuilder MIB = - BuildMI(MBB, MI, DL, get((LowReg == HighReg ? - SystemZ::MOV64rm : SystemZ::MOV64rmm))); - // Add store operands. - MIB.addReg(LowReg, RegState::Define); - if (LowReg != HighReg) - MIB.addReg(HighReg, RegState::Define); + if (StartOffset) { + // Build a load instruction. Use LOAD MULTIPLE instruction if there are many + // registers to load, otherwise - just LOAD. + MachineInstrBuilder MIB = + BuildMI(MBB, MI, DL, get((LowReg == HighReg ? + SystemZ::MOV64rm : SystemZ::MOV64rmm))); + // Add store operands. + MIB.addReg(LowReg, RegState::Define); + if (LowReg != HighReg) + MIB.addReg(HighReg, RegState::Define); - MIB.addReg((RegInfo->hasFP(MF) ? SystemZ::R11D : SystemZ::R15D)); - MIB.addImm(StartOffset); - if (LowReg == HighReg) - MIB.addReg(0); + MIB.addReg((RegInfo->hasFP(MF) ? SystemZ::R11D : SystemZ::R15D)); + MIB.addImm(StartOffset); + if (LowReg == HighReg) + MIB.addReg(0); - // Do a second scan adding regs as being defined by instruction - for (unsigned i = 0, e = CSI.size(); i != e; ++i) { - unsigned Reg = CSI[i].getReg(); - if (Reg != LowReg && Reg != HighReg) - MIB.addReg(Reg, RegState::ImplicitDefine); + // Do a second scan adding regs as being defined by instruction + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + unsigned Reg = CSI[i].getReg(); + if (Reg != LowReg && Reg != HighReg) + MIB.addReg(Reg, RegState::ImplicitDefine); + } } return true; diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td index 83fa20b67625..b883cdd53177 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td @@ -156,7 +156,8 @@ let isBranch = 1, isTerminator = 1 in { let isCall = 1 in // All calls clobber the non-callee saved registers. Uses for argument // registers are added manually. - let Defs = [R0D, R1D, R2D, R3D, R4D, R5D, R14D] in { + let Defs = [R0D, R1D, R2D, R3D, R4D, R5D, R14D, + F0L, F1L, F2L, F3L, F4L, F5L, F6L, F7L] in { def CALLi : Pseudo<(outs), (ins imm_pcrel:$dst, variable_ops), "brasl\t%r14, $dst", [(SystemZcall imm:$dst)]>; def CALLr : Pseudo<(outs), (ins ADDR64:$dst, variable_ops), diff --git a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp index ee9c92922902..ab92ebb89e82 100644 --- a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp +++ b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp @@ -39,7 +39,8 @@ SystemZRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { SystemZ::R6D, SystemZ::R7D, SystemZ::R8D, SystemZ::R9D, SystemZ::R10D, SystemZ::R11D, SystemZ::R12D, SystemZ::R13D, SystemZ::R14D, SystemZ::R15D, - SystemZ::F1L, SystemZ::F3L, SystemZ::F5L, SystemZ::F7L, + SystemZ::F8L, SystemZ::F9L, SystemZ::F10L, SystemZ::F11L, + SystemZ::F12L, SystemZ::F13L, SystemZ::F14L, SystemZ::F15L, 0 }; @@ -55,6 +56,8 @@ SystemZRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const { &SystemZ::GR64RegClass, &SystemZ::GR64RegClass, &SystemZ::GR64RegClass, &SystemZ::GR64RegClass, &SystemZ::FP64RegClass, &SystemZ::FP64RegClass, + &SystemZ::FP64RegClass, &SystemZ::FP64RegClass, + &SystemZ::FP64RegClass, &SystemZ::FP64RegClass, &SystemZ::FP64RegClass, &SystemZ::FP64RegClass, 0 }; return CalleeSavedRegClasses; @@ -142,18 +145,33 @@ SystemZRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF, // Determine whether R15/R14 will ever be clobbered inside the function. And // if yes - mark it as 'callee' saved. MachineFrameInfo *FFI = MF.getFrameInfo(); + MachineRegisterInfo &MRI = MF.getRegInfo(); + + // Check whether high FPRs are ever used, if yes - we need to save R15 as + // well. + static const unsigned HighFPRs[] = { + SystemZ::F8L, SystemZ::F9L, SystemZ::F10L, SystemZ::F11L, + SystemZ::F12L, SystemZ::F13L, SystemZ::F14L, SystemZ::F15L, + SystemZ::F8S, SystemZ::F9S, SystemZ::F10S, SystemZ::F11S, + SystemZ::F12S, SystemZ::F13S, SystemZ::F14S, SystemZ::F15S, + }; + + bool HighFPRsUsed = false; + for (unsigned i = 0, e = array_lengthof(HighFPRs); i != e; ++i) + HighFPRsUsed |= MRI.isPhysRegUsed(HighFPRs[i]); if (FFI->hasCalls()) /* FIXME: function is varargs */ /* FIXME: function grabs RA */ /* FIXME: function calls eh_return */ - MF.getRegInfo().setPhysRegUsed(SystemZ::R14D); + MRI.setPhysRegUsed(SystemZ::R14D); - if (FFI->hasCalls() || + if (HighFPRsUsed || + FFI->hasCalls() || FFI->getObjectIndexEnd() != 0 || // Contains automatic variables FFI->hasVarSizedObjects() // Function calls dynamic alloca's /* FIXME: function is varargs */) - MF.getRegInfo().setPhysRegUsed(SystemZ::R15D); + MRI.setPhysRegUsed(SystemZ::R15D); } /// emitSPUpdate - Emit a series of instructions to increment / decrement the