diff options
Diffstat (limited to 'llvm/lib/Target/ARM/Thumb1FrameLowering.cpp')
-rw-r--r-- | llvm/lib/Target/ARM/Thumb1FrameLowering.cpp | 263 |
1 files changed, 21 insertions, 242 deletions
diff --git a/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp b/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp index a23b85c1622..b3f26165a87 100644 --- a/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp +++ b/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp @@ -188,8 +188,7 @@ void Thumb1FrameLowering::emitPrologue(MachineFunction &MF, int FramePtrOffsetInBlock = 0; unsigned adjustedGPRCS1Size = GPRCS1Size; - if (GPRCS1Size > 0 && GPRCS2Size == 0 && - tryFoldSPUpdateIntoPushPop(STI, MF, &*std::prev(MBBI), NumBytes)) { + if (tryFoldSPUpdateIntoPushPop(STI, MF, &*std::prev(MBBI), NumBytes)) { FramePtrOffsetInBlock = NumBytes; adjustedGPRCS1Size += NumBytes; NumBytes = 0; @@ -262,48 +261,6 @@ void Thumb1FrameLowering::emitPrologue(MachineFunction &MF, AFI->setShouldRestoreSPFromFP(true); } - // Skip past the spilling of r8-r11, which could consist of multiple tPUSH - // and tMOVr instructions. We don't need to add any call frame information - // in-between these instructions, because they do not modify the high - // registers. - while (true) { - MachineBasicBlock::iterator OldMBBI = MBBI; - // Skip a run of tMOVr instructions - while (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tMOVr) - MBBI++; - if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tPUSH) { - MBBI++; - } else { - // We have reached an instruction which is not a push, so the previous - // run of tMOVr instructions (which may have been empty) was not part of - // the prologue. Reset MBBI back to the last PUSH of the prologue. - MBBI = OldMBBI; - break; - } - } - - // Emit call frame information for the callee-saved high registers. - for (auto &I : CSI) { - unsigned Reg = I.getReg(); - int FI = I.getFrameIdx(); - switch (Reg) { - case ARM::R8: - case ARM::R9: - case ARM::R10: - case ARM::R11: - case ARM::R12: { - unsigned CFIIndex = MMI.addFrameInst(MCCFIInstruction::createOffset( - nullptr, MRI->getDwarfRegNum(Reg, true), MFI.getObjectOffset(FI))); - BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) - .addCFIIndex(CFIIndex) - .setMIFlags(MachineInstr::FrameSetup); - break; - } - default: - break; - } - } - if (NumBytes) { // Insert it after all the callee-save spills. emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -NumBytes, @@ -351,12 +308,12 @@ static bool isCSRestore(MachineInstr &MI, const MCPhysReg *CSRegs) { isCalleeSavedRegister(MI.getOperand(0).getReg(), CSRegs)) return true; else if (MI.getOpcode() == ARM::tPOP) { + // The first two operands are predicates. The last two are + // imp-def and imp-use of SP. Check everything in between. + for (int i = 2, e = MI.getNumOperands() - 2; i != e; ++i) + if (!isCalleeSavedRegister(MI.getOperand(i).getReg(), CSRegs)) + return false; return true; - } else if (MI.getOpcode() == ARM::tMOVr) { - unsigned Dst = MI.getOperand(0).getReg(); - unsigned Src = MI.getOperand(1).getReg(); - return ((ARM::tGPRRegClass.contains(Src) || Src == ARM::LR) && - ARM::hGPRRegClass.contains(Dst)); } return false; } @@ -611,19 +568,6 @@ bool Thumb1FrameLowering::emitPopSpecialFixUp(MachineBasicBlock &MBB, return true; } -// Return the first iteraror after CurrentReg which is present in EnabledRegs, -// or OrderEnd if no further registers are in that set. This does not advance -// the iterator fiorst, so returns CurrentReg if it is in EnabledRegs. -template <unsigned SetSize> -static ArrayRef<unsigned>::const_iterator -findNextOrderedReg(ArrayRef<unsigned>::const_iterator CurrentReg, - SmallSet<unsigned, SetSize> &EnabledRegs, - ArrayRef<unsigned>::const_iterator OrderEnd) { - while (CurrentReg != OrderEnd && !EnabledRegs.count(*CurrentReg)) - ++CurrentReg; - return CurrentReg; -} - bool Thumb1FrameLowering:: spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, @@ -634,111 +578,29 @@ spillCalleeSavedRegisters(MachineBasicBlock &MBB, DebugLoc DL; const TargetInstrInfo &TII = *STI.getInstrInfo(); - MachineFunction &MF = *MBB.getParent(); - const ARMBaseRegisterInfo *RegInfo = static_cast<const ARMBaseRegisterInfo *>( - MF.getSubtarget().getRegisterInfo()); - - SmallSet<unsigned, 9> LoRegsToSave; // r0-r7, lr - SmallSet<unsigned, 4> HiRegsToSave; // r8-r11 - SmallSet<unsigned, 9> CopyRegs; // Registers which can be used after pushing - // LoRegs for saving HiRegs. + MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(ARM::tPUSH)); + AddDefaultPred(MIB); for (unsigned i = CSI.size(); i != 0; --i) { unsigned Reg = CSI[i-1].getReg(); + bool isKill = true; - if (ARM::tGPRRegClass.contains(Reg) || Reg == ARM::LR) { - LoRegsToSave.insert(Reg); - } else if (ARM::hGPRRegClass.contains(Reg) && Reg != ARM::LR) { - HiRegsToSave.insert(Reg); - } else { - llvm_unreachable("callee-saved register of unexpected class"); - } - - if ((ARM::tGPRRegClass.contains(Reg) || Reg == ARM::LR) && - !MF.getRegInfo().isLiveIn(Reg) && - !(hasFP(MF) && Reg == RegInfo->getFrameRegister(MF))) - CopyRegs.insert(Reg); - } - - // Unused argument registers can be used for the high register saving. - for (unsigned ArgReg : {ARM::R0, ARM::R1, ARM::R2, ARM::R3}) - if (!MF.getRegInfo().isLiveIn(ArgReg)) - CopyRegs.insert(ArgReg); - - // Push the low registers and lr - if (!LoRegsToSave.empty()) { - MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(ARM::tPUSH)); - AddDefaultPred(MIB); - for (unsigned Reg : {ARM::R4, ARM::R5, ARM::R6, ARM::R7, ARM::LR}) { - if (LoRegsToSave.count(Reg)) { - bool isKill = !MF.getRegInfo().isLiveIn(Reg); - if (isKill) - MBB.addLiveIn(Reg); - - MIB.addReg(Reg, getKillRegState(isKill)); - } - } - MIB.setMIFlags(MachineInstr::FrameSetup); - } - - // Push the high registers. There are no store instructions that can access - // these registers directly, so we have to move them to low registers, and - // push them. This might take multiple pushes, as it is possible for there to - // be fewer low registers available than high registers which need saving. - - // These are in reverse order so that in the case where we need to use - // multiple PUSH instructions, the order of the registers on the stack still - // matches the unwind info. They need to be swicthed back to ascending order - // before adding to the PUSH instruction. - ArrayRef<unsigned> AllCopyRegs({ARM::LR, - ARM::R7, ARM::R6, ARM::R5, ARM::R4, - ARM::R3, ARM::R2, ARM::R1, ARM::R0}); - ArrayRef<unsigned> AllHighRegs({ARM::R11, ARM::R10, ARM::R9, ARM::R8}); - - // Find the first register to save. - auto HiRegToSave = - findNextOrderedReg(AllHighRegs.begin(), HiRegsToSave, AllHighRegs.end()); - - while (HiRegToSave != AllHighRegs.end()) { - // Find the first low register to use. - auto CopyReg = - findNextOrderedReg(AllCopyRegs.begin(), CopyRegs, AllCopyRegs.end()); - - // Create the PUSH, but don't insert it yet (the MOVs need to come first). - MachineInstrBuilder PushMIB = BuildMI(MF, DL, TII.get(ARM::tPUSH)); - AddDefaultPred(PushMIB); - - SmallVector<unsigned, 4> RegsToPush; - while (HiRegToSave != AllHighRegs.end() && CopyReg != AllCopyRegs.end()) { - if (HiRegsToSave.count(*HiRegToSave)) { - bool isKill = !MF.getRegInfo().isLiveIn(*HiRegToSave); - if (isKill) - MBB.addLiveIn(*HiRegToSave); - - // Emit a MOV from the high reg to the low reg. - MachineInstrBuilder MIB = - BuildMI(MBB, MI, DL, TII.get(ARM::tMOVr)); - MIB.addReg(*CopyReg, RegState::Define); - MIB.addReg(*HiRegToSave, getKillRegState(isKill)); - AddDefaultPred(MIB); - - // Record the register that must be added to the PUSH. - RegsToPush.push_back(*CopyReg); - - CopyReg = findNextOrderedReg(++CopyReg, CopyRegs, AllCopyRegs.end()); - HiRegToSave = - findNextOrderedReg(++HiRegToSave, HiRegsToSave, AllHighRegs.end()); - } + // Add the callee-saved register as live-in unless it's LR and + // @llvm.returnaddress is called. If LR is returned for @llvm.returnaddress + // then it's already added to the function and entry block live-in sets. + if (Reg == ARM::LR) { + MachineFunction &MF = *MBB.getParent(); + if (MF.getFrameInfo().isReturnAddressTaken() && + MF.getRegInfo().isLiveIn(Reg)) + isKill = false; } - // Add the low registers to the PUSH, in ascending order. - for (unsigned Reg : reverse(RegsToPush)) - PushMIB.addReg(Reg, RegState::Kill); + if (isKill) + MBB.addLiveIn(Reg); - // Insert the PUSH instruction after the MOVs. - MBB.insert(MI, PushMIB); + MIB.addReg(Reg, getKillRegState(isKill)); } - + MIB.setMIFlags(MachineInstr::FrameSetup); return true; } @@ -753,98 +615,15 @@ restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineFunction &MF = *MBB.getParent(); ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); const TargetInstrInfo &TII = *STI.getInstrInfo(); - const ARMBaseRegisterInfo *RegInfo = static_cast<const ARMBaseRegisterInfo *>( - MF.getSubtarget().getRegisterInfo()); bool isVarArg = AFI->getArgRegsSaveSize() > 0; DebugLoc DL = MI != MBB.end() ? MI->getDebugLoc() : DebugLoc(); - - SmallSet<unsigned, 9> LoRegsToRestore; - SmallSet<unsigned, 4> HiRegsToRestore; - // Low registers (r0-r7) which can be used to restore the high registers. - SmallSet<unsigned, 9> CopyRegs; - - for (CalleeSavedInfo I : CSI) { - unsigned Reg = I.getReg(); - - if (ARM::tGPRRegClass.contains(Reg) || Reg == ARM::LR) { - LoRegsToRestore.insert(Reg); - } else if (ARM::hGPRRegClass.contains(Reg) && Reg != ARM::LR) { - HiRegsToRestore.insert(Reg); - } else { - llvm_unreachable("callee-saved register of unexpected class"); - } - - // If this is a low register not used as the frame pointer, we may want to - // use it for restoring the high registers. - if ((ARM::tGPRRegClass.contains(Reg)) && - !(hasFP(MF) && Reg == RegInfo->getFrameRegister(MF))) - CopyRegs.insert(Reg); - } - - // If this is a return block, we may be able to use some unused return value - // registers for restoring the high regs. - auto Terminator = MBB.getFirstTerminator(); - if (Terminator != MBB.end() && Terminator->getOpcode() == ARM::tBX_RET) { - CopyRegs.insert(ARM::R0); - CopyRegs.insert(ARM::R1); - CopyRegs.insert(ARM::R2); - CopyRegs.insert(ARM::R3); - for (auto Op : Terminator->implicit_operands()) { - if (Op.isReg()) - CopyRegs.erase(Op.getReg()); - } - } - - ArrayRef<unsigned> AllCopyRegs({ARM::R0, ARM::R1, ARM::R2, ARM::R3, - ARM::R4, ARM::R5, ARM::R6, ARM::R7}); - ArrayRef<unsigned> AllHighRegs({ARM::R8, ARM::R9, ARM::R10, ARM::R11}); - - // Find the first register to restore. - auto HiRegToRestore = findNextOrderedReg(AllHighRegs.begin(), HiRegsToRestore, - AllHighRegs.end()); - - while (HiRegToRestore != AllHighRegs.end()) { - assert(!CopyRegs.empty()); - // Find the first low register to use. - auto CopyReg = - findNextOrderedReg(AllCopyRegs.begin(), CopyRegs, AllCopyRegs.end()); - - // Create the POP instruction. - MachineInstrBuilder PopMIB = BuildMI(MBB, MI, DL, TII.get(ARM::tPOP)); - AddDefaultPred(PopMIB); - - while (HiRegToRestore != AllHighRegs.end() && CopyReg != AllCopyRegs.end()) { - // Add the low register to the POP. - PopMIB.addReg(*CopyReg, RegState::Define); - - // Create the MOV from low to high register. - MachineInstrBuilder MIB = - BuildMI(MBB, MI, DL, TII.get(ARM::tMOVr)); - MIB.addReg(*HiRegToRestore, RegState::Define); - MIB.addReg(*CopyReg, RegState::Kill); - AddDefaultPred(MIB); - - CopyReg = findNextOrderedReg(++CopyReg, CopyRegs, AllCopyRegs.end()); - HiRegToRestore = findNextOrderedReg(++HiRegToRestore, HiRegsToRestore, - AllHighRegs.end()); - } - } - - - - MachineInstrBuilder MIB = BuildMI(MF, DL, TII.get(ARM::tPOP)); AddDefaultPred(MIB); bool NeedsPop = false; for (unsigned i = CSI.size(); i != 0; --i) { unsigned Reg = CSI[i-1].getReg(); - - // High registers (excluding lr) have already been dealt with - if (!(ARM::tGPRRegClass.contains(Reg) || Reg == ARM::LR)) - continue; - if (Reg == ARM::LR) { if (MBB.succ_empty()) { // Special epilogue for vararg functions. See emitEpilogue |