diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index e90fc6cccc3..b7e8af972f4 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -641,24 +641,17 @@ public: virtual void processFunctionBeforeFrameFinalized(MachineFunction &MF) const { } - /// saveScavengerRegister - Save the register so it can be used by the - /// register scavenger. Return true if the register was saved, false - /// otherwise. If this function does not save the register, the scavenger + /// saveScavengerRegister - Spill the register so it can be used by the + /// register scavenger. Return true if the register was spilled, false + /// otherwise. If this function does not spill the register, the scavenger /// will instead spill it to the emergency spill slot. /// virtual bool saveScavengerRegister(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + MachineBasicBlock::iterator &UseMI, const TargetRegisterClass *RC, unsigned Reg) const {return false;} - /// restoreScavengerRegister - Restore a register saved by - /// saveScavengerRegister(). - /// - virtual void restoreScavengerRegister(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - const TargetRegisterClass *RC, - unsigned Reg) const {} - /// eliminateFrameIndex - This method must be overriden to eliminate abstract /// frame indices from instructions which may use them. The instruction /// referenced by the iterator contains an MO_FrameIndex operand which must be diff --git a/lib/CodeGen/RegisterScavenging.cpp b/lib/CodeGen/RegisterScavenging.cpp index 5f1c4e2594c..5fa28d281a5 100644 --- a/lib/CodeGen/RegisterScavenging.cpp +++ b/lib/CodeGen/RegisterScavenging.cpp @@ -300,7 +300,7 @@ unsigned RegScavenger::scavengeRegister(const TargetRegisterClass *RC, // If the target knows how to save/restore the register, let it do so; // otherwise, use the emergency stack spill slot. - if (!TRI->saveScavengerRegister(*MBB, I, RC, SReg)) { + if (!TRI->saveScavengerRegister(*MBB, I, UseMI, RC, SReg)) { // Spill the scavenged register before I. assert(ScavengingFrameIndex >= 0 && "Cannot scavenge register without an emergency spill slot!"); @@ -310,8 +310,7 @@ unsigned RegScavenger::scavengeRegister(const TargetRegisterClass *RC, // Restore the scavenged register before its use (or first terminator). TII->loadRegFromStackSlot(*MBB, UseMI, SReg, ScavengingFrameIndex, RC); - } else - TRI->restoreScavengerRegister(*MBB, UseMI, RC, SReg); + } ScavengeRestore = prior(UseMI); diff --git a/lib/Target/ARM/Thumb1RegisterInfo.cpp b/lib/Target/ARM/Thumb1RegisterInfo.cpp index 3c896da4c0c..33537883dc4 100644 --- a/lib/Target/ARM/Thumb1RegisterInfo.cpp +++ b/lib/Target/ARM/Thumb1RegisterInfo.cpp @@ -394,31 +394,48 @@ rewriteFrameIndex(MachineInstr &MI, unsigned FrameRegIdx, return 0; } -/// saveScavengerRegister - Save the register so it can be used by the +/// saveScavengerRegister - Spill the register so it can be used by the /// register scavenger. Return true. -bool Thumb1RegisterInfo::saveScavengerRegister(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - const TargetRegisterClass *RC, - unsigned Reg) const { +bool +Thumb1RegisterInfo::saveScavengerRegister(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + MachineBasicBlock::iterator &UseMI, + const TargetRegisterClass *RC, + unsigned Reg) const { // Thumb1 can't use the emergency spill slot on the stack because // ldr/str immediate offsets must be positive, and if we're referencing // off the frame pointer (if, for example, there are alloca() calls in // the function, the offset will be negative. Use R12 instead since that's // a call clobbered register that we know won't be used in Thumb1 mode. + DebugLoc DL = DebugLoc::getUnknownLoc(); + BuildMI(MBB, I, DL, TII.get(ARM::tMOVtgpr2gpr)). + addReg(ARM::R12, RegState::Define).addReg(Reg, RegState::Kill); + + // The UseMI is where we would like to restore the register. If there's + // interference with R12 before then, however, we'll need to restore it + // before that instead and adjust the UseMI. + bool done = false; + for (MachineBasicBlock::iterator II = I; !done && II != UseMI ; ++II) { + // If this instruction affects R12, adjust our restore point. + for (unsigned i = 0, e = II->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = II->getOperand(i); + if (!MO.isReg() || MO.isUndef() || !MO.getReg() || + TargetRegisterInfo::isVirtualRegister(MO.getReg())) + continue; + if (MO.getReg() == ARM::R12) { + UseMI = II; + done = true; + break; + } + } + } + // Restore the register from R12 + BuildMI(MBB, UseMI, DL, TII.get(ARM::tMOVgpr2tgpr)). + addReg(Reg, RegState::Define).addReg(ARM::R12, RegState::Kill); - TII.copyRegToReg(MBB, I, ARM::R12, Reg, ARM::GPRRegisterClass, RC); return true; } -/// restoreScavengerRegister - restore a registers saved by -// saveScavengerRegister(). -void Thumb1RegisterInfo::restoreScavengerRegister(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - const TargetRegisterClass *RC, - unsigned Reg) const { - TII.copyRegToReg(MBB, I, Reg, ARM::R12, RC, ARM::GPRRegisterClass); -} - unsigned Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, int *Value, diff --git a/lib/Target/ARM/Thumb1RegisterInfo.h b/lib/Target/ARM/Thumb1RegisterInfo.h index bb7a6199d10..570a5bc8c2e 100644 --- a/lib/Target/ARM/Thumb1RegisterInfo.h +++ b/lib/Target/ARM/Thumb1RegisterInfo.h @@ -57,12 +57,9 @@ public: bool saveScavengerRegister(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + MachineBasicBlock::iterator &UseMI, const TargetRegisterClass *RC, unsigned Reg) const; - void restoreScavengerRegister(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - const TargetRegisterClass *RC, - unsigned Reg) const; unsigned eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, int *Value = NULL, RegScavenger *RS = NULL) const;