Handle FP callee-saved regs

llvm-svn: 76029
This commit is contained in:
Anton Korobeynikov 2009-07-16 14:23:01 +00:00
parent 871784ba88
commit b106b60456
3 changed files with 98 additions and 47 deletions

View File

@ -186,50 +186,71 @@ bool
SystemZInstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB, SystemZInstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI, MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI) const { const std::vector<CalleeSavedInfo> &CSI) const {
if (CSI.empty())
return false;
DebugLoc DL = DebugLoc::getUnknownLoc(); DebugLoc DL = DebugLoc::getUnknownLoc();
if (MI != MBB.end()) DL = MI->getDebugLoc(); if (MI != MBB.end()) DL = MI->getDebugLoc();
MachineFunction &MF = *MBB.getParent(); MachineFunction &MF = *MBB.getParent();
SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>(); SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>();
MFI->setCalleeSavedFrameSize(CSI.size() * 8); unsigned CalleeFrameSize = 0;
// Scan the callee-saved and find the bounds of register spill area. // Scan the callee-saved and find the bounds of register spill area.
unsigned LowReg = 0, HighReg = 0, StartOffset = -1U, EndOffset = 0; unsigned LowReg = 0, HighReg = 0, StartOffset = -1U, EndOffset = 0;
for (unsigned i = 0, e = CSI.size(); i != e; ++i) { for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
unsigned Reg = CSI[i].getReg(); unsigned Reg = CSI[i].getReg();
unsigned Offset = RegSpillOffsets[Reg]; const TargetRegisterClass *RegClass = CSI[i].getRegClass();
if (StartOffset > Offset) { if (RegClass != &SystemZ::FP64RegClass) {
LowReg = Reg; StartOffset = Offset; unsigned Offset = RegSpillOffsets[Reg];
} CalleeFrameSize += 8;
if (EndOffset < Offset) { if (StartOffset > Offset) {
HighReg = Reg; EndOffset = RegSpillOffsets[Reg]; LowReg = Reg; StartOffset = Offset;
}
if (EndOffset < Offset) {
HighReg = Reg; EndOffset = RegSpillOffsets[Reg];
}
} }
} }
// Save information for epilogue inserter. // Save information for epilogue inserter.
MFI->setCalleeSavedFrameSize(CalleeFrameSize);
MFI->setLowReg(LowReg); MFI->setHighReg(HighReg); MFI->setLowReg(LowReg); MFI->setHighReg(HighReg);
// Build a store instruction. Use STORE MULTIPLE instruction if there are many // Save GPRs
// registers to store, otherwise - just STORE. if (StartOffset) {
MachineInstrBuilder MIB = // Build a store instruction. Use STORE MULTIPLE instruction if there are many
BuildMI(MBB, MI, DL, get((LowReg == HighReg ? // registers to store, otherwise - just STORE.
SystemZ::MOV64mr : SystemZ::MOV64mrm))); MachineInstrBuilder MIB =
BuildMI(MBB, MI, DL, get((LowReg == HighReg ?
SystemZ::MOV64mr : SystemZ::MOV64mrm)));
// Add store operands. // Add store operands.
MIB.addReg(SystemZ::R15D).addImm(StartOffset); MIB.addReg(SystemZ::R15D).addImm(StartOffset);
if (LowReg == HighReg) if (LowReg == HighReg)
MIB.addReg(0); MIB.addReg(0);
MIB.addReg(LowReg, RegState::Kill); MIB.addReg(LowReg, RegState::Kill);
if (LowReg != HighReg) if (LowReg != HighReg)
MIB.addReg(HighReg, RegState::Kill); 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) { for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
unsigned Reg = CSI[i].getReg(); unsigned Reg = CSI[i].getReg();
// Add the callee-saved register as live-in. It's killed at the spill. const TargetRegisterClass *RegClass = CSI[i].getRegClass();
MBB.addLiveIn(Reg); if (RegClass == &SystemZ::FP64RegClass) {
if (Reg != LowReg && Reg != HighReg) MBB.addLiveIn(Reg);
MIB.addReg(Reg, RegState::ImplicitKill); storeRegToStackSlot(MBB, MI, Reg, true, CSI[i].getFrameIdx(), RegClass);
}
} }
return true; return true;
@ -249,29 +270,40 @@ SystemZInstrInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
const TargetRegisterInfo *RegInfo= MF.getTarget().getRegisterInfo(); const TargetRegisterInfo *RegInfo= MF.getTarget().getRegisterInfo();
SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>(); SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>();
// 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 LowReg = MFI->getLowReg(), HighReg = MFI->getHighReg();
unsigned StartOffset = RegSpillOffsets[LowReg]; unsigned StartOffset = RegSpillOffsets[LowReg];
// Build a load instruction. Use LOAD MULTIPLE instruction if there are many if (StartOffset) {
// registers to load, otherwise - just LOAD. // Build a load instruction. Use LOAD MULTIPLE instruction if there are many
MachineInstrBuilder MIB = // registers to load, otherwise - just LOAD.
BuildMI(MBB, MI, DL, get((LowReg == HighReg ? MachineInstrBuilder MIB =
SystemZ::MOV64rm : SystemZ::MOV64rmm))); BuildMI(MBB, MI, DL, get((LowReg == HighReg ?
// Add store operands. SystemZ::MOV64rm : SystemZ::MOV64rmm)));
MIB.addReg(LowReg, RegState::Define); // Add store operands.
if (LowReg != HighReg) MIB.addReg(LowReg, RegState::Define);
MIB.addReg(HighReg, RegState::Define); if (LowReg != HighReg)
MIB.addReg(HighReg, RegState::Define);
MIB.addReg((RegInfo->hasFP(MF) ? SystemZ::R11D : SystemZ::R15D)); MIB.addReg((RegInfo->hasFP(MF) ? SystemZ::R11D : SystemZ::R15D));
MIB.addImm(StartOffset); MIB.addImm(StartOffset);
if (LowReg == HighReg) if (LowReg == HighReg)
MIB.addReg(0); MIB.addReg(0);
// Do a second scan adding regs as being defined by instruction // Do a second scan adding regs as being defined by instruction
for (unsigned i = 0, e = CSI.size(); i != e; ++i) { for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
unsigned Reg = CSI[i].getReg(); unsigned Reg = CSI[i].getReg();
if (Reg != LowReg && Reg != HighReg) if (Reg != LowReg && Reg != HighReg)
MIB.addReg(Reg, RegState::ImplicitDefine); MIB.addReg(Reg, RegState::ImplicitDefine);
}
} }
return true; return true;

View File

@ -156,7 +156,8 @@ let isBranch = 1, isTerminator = 1 in {
let isCall = 1 in let isCall = 1 in
// All calls clobber the non-callee saved registers. Uses for argument // All calls clobber the non-callee saved registers. Uses for argument
// registers are added manually. // 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), def CALLi : Pseudo<(outs), (ins imm_pcrel:$dst, variable_ops),
"brasl\t%r14, $dst", [(SystemZcall imm:$dst)]>; "brasl\t%r14, $dst", [(SystemZcall imm:$dst)]>;
def CALLr : Pseudo<(outs), (ins ADDR64:$dst, variable_ops), def CALLr : Pseudo<(outs), (ins ADDR64:$dst, variable_ops),

View File

@ -39,7 +39,8 @@ SystemZRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
SystemZ::R6D, SystemZ::R7D, SystemZ::R8D, SystemZ::R9D, SystemZ::R6D, SystemZ::R7D, SystemZ::R8D, SystemZ::R9D,
SystemZ::R10D, SystemZ::R11D, SystemZ::R12D, SystemZ::R13D, SystemZ::R10D, SystemZ::R11D, SystemZ::R12D, SystemZ::R13D,
SystemZ::R14D, SystemZ::R15D, 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 0
}; };
@ -55,6 +56,8 @@ SystemZRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
&SystemZ::GR64RegClass, &SystemZ::GR64RegClass, &SystemZ::GR64RegClass, &SystemZ::GR64RegClass,
&SystemZ::GR64RegClass, &SystemZ::GR64RegClass, &SystemZ::GR64RegClass, &SystemZ::GR64RegClass,
&SystemZ::FP64RegClass, &SystemZ::FP64RegClass, &SystemZ::FP64RegClass, &SystemZ::FP64RegClass,
&SystemZ::FP64RegClass, &SystemZ::FP64RegClass,
&SystemZ::FP64RegClass, &SystemZ::FP64RegClass,
&SystemZ::FP64RegClass, &SystemZ::FP64RegClass, 0 &SystemZ::FP64RegClass, &SystemZ::FP64RegClass, 0
}; };
return CalleeSavedRegClasses; return CalleeSavedRegClasses;
@ -142,18 +145,33 @@ SystemZRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
// Determine whether R15/R14 will ever be clobbered inside the function. And // Determine whether R15/R14 will ever be clobbered inside the function. And
// if yes - mark it as 'callee' saved. // if yes - mark it as 'callee' saved.
MachineFrameInfo *FFI = MF.getFrameInfo(); 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()) if (FFI->hasCalls())
/* FIXME: function is varargs */ /* FIXME: function is varargs */
/* FIXME: function grabs RA */ /* FIXME: function grabs RA */
/* FIXME: function calls eh_return */ /* 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->getObjectIndexEnd() != 0 || // Contains automatic variables
FFI->hasVarSizedObjects() // Function calls dynamic alloca's FFI->hasVarSizedObjects() // Function calls dynamic alloca's
/* FIXME: function is varargs */) /* FIXME: function is varargs */)
MF.getRegInfo().setPhysRegUsed(SystemZ::R15D); MRI.setPhysRegUsed(SystemZ::R15D);
} }
/// emitSPUpdate - Emit a series of instructions to increment / decrement the /// emitSPUpdate - Emit a series of instructions to increment / decrement the