bool NEONMoveFixPass::InsertMoves(MachineBasicBlock &MBB) { RegMap Defs; bool Modified = false; // Walk over MBB tracking the def points of the registers. MachineBasicBlock::iterator MII = MBB.begin(), E = MBB.end(); MachineBasicBlock::iterator NextMII; for (; MII != E; MII = NextMII) { NextMII = llvm::next(MII); MachineInstr *MI = &*MII; if (MI->getOpcode() == ARM::VMOVD && !TII->isPredicated(MI)) { unsigned SrcReg = MI->getOperand(1).getReg(); // If we do not find an instruction defining the reg, this means the // register should be live-in for this BB. It's always to better to use // NEON reg-reg moves. unsigned Domain = ARMII::DomainNEON; RegMap::iterator DefMI = Defs.find(SrcReg); if (DefMI != Defs.end()) { Domain = DefMI->second->getDesc().TSFlags & ARMII::DomainMask; // Instructions in general domain are subreg accesses. // Map them to NEON reg-reg moves. if (Domain == ARMII::DomainGeneral) Domain = ARMII::DomainNEON; } if (Domain & ARMII::DomainNEON) { // Convert VMOVD to VMOVDneon unsigned DestReg = MI->getOperand(0).getReg(); DEBUG({errs() << "vmov convert: "; MI->dump();}); // It's safe to ignore imp-defs / imp-uses here, since: // - We're running late, no intelligent condegen passes should be run // afterwards // - The imp-defs / imp-uses are superregs only, we don't care about // them. AddDefaultPred(BuildMI(MBB, *MI, MI->getDebugLoc(), TII->get(ARM::VMOVDneon), DestReg).addReg(SrcReg)); MBB.erase(MI); MachineBasicBlock::iterator I = prior(NextMII); MI = &*I; DEBUG({errs() << " into: "; MI->dump();});
bool AMDGPUInstrInfo::expandPostRAPseudo (MachineBasicBlock::iterator MI) const { MachineBasicBlock *MBB = MI->getParent(); int OffsetOpIdx = AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::addr); // addr is a custom operand with multiple MI operands, and only the // first MI operand is given a name. int RegOpIdx = OffsetOpIdx + 1; int ChanOpIdx = AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::chan); if (isRegisterLoad(*MI)) { int DstOpIdx = AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::dst); unsigned RegIndex = MI->getOperand(RegOpIdx).getImm(); unsigned Channel = MI->getOperand(ChanOpIdx).getImm(); unsigned Address = calculateIndirectAddress(RegIndex, Channel); unsigned OffsetReg = MI->getOperand(OffsetOpIdx).getReg(); if (OffsetReg == AMDGPU::INDIRECT_BASE_ADDR) { buildMovInstr(MBB, MI, MI->getOperand(DstOpIdx).getReg(), getIndirectAddrRegClass()->getRegister(Address)); } else { buildIndirectRead(MBB, MI, MI->getOperand(DstOpIdx).getReg(), Address, OffsetReg); } } else if (isRegisterStore(*MI)) { int ValOpIdx = AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::val); unsigned RegIndex = MI->getOperand(RegOpIdx).getImm(); unsigned Channel = MI->getOperand(ChanOpIdx).getImm(); unsigned Address = calculateIndirectAddress(RegIndex, Channel); unsigned OffsetReg = MI->getOperand(OffsetOpIdx).getReg(); if (OffsetReg == AMDGPU::INDIRECT_BASE_ADDR) { buildMovInstr(MBB, MI, getIndirectAddrRegClass()->getRegister(Address), MI->getOperand(ValOpIdx).getReg()); } else { buildIndirectWrite(MBB, MI, MI->getOperand(ValOpIdx).getReg(), calculateIndirectAddress(RegIndex, Channel), OffsetReg); } } else { return false; } MBB->erase(MI); return true; }
bool Thumb1FrameLowering:: restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const std::vector<CalleeSavedInfo> &CSI, const TargetRegisterInfo *TRI) const { if (CSI.empty()) return false; MachineFunction &MF = *MBB.getParent(); ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); const TargetInstrInfo &TII = *STI.getInstrInfo(); bool isVarArg = AFI->getArgRegsSaveSize() > 0; DebugLoc DL = MI != MBB.end() ? MI->getDebugLoc() : DebugLoc(); MachineInstrBuilder MIB = BuildMI(MF, DL, TII.get(ARM::tPOP)); AddDefaultPred(MIB); bool NumRegs = false; for (unsigned i = CSI.size(); i != 0; --i) { unsigned Reg = CSI[i-1].getReg(); if (Reg == ARM::LR && MBB.succ_empty()) { // Special epilogue for vararg functions. See emitEpilogue if (isVarArg) continue; // ARMv4T requires BX, see emitEpilogue if (STI.hasV4TOps() && !STI.hasV5TOps()) continue; Reg = ARM::PC; (*MIB).setDesc(TII.get(ARM::tPOP_RET)); if (MI != MBB.end()) MIB.copyImplicitOps(&*MI); MI = MBB.erase(MI); } MIB.addReg(Reg, getDefRegState(true)); NumRegs = true; } // It's illegal to emit pop instruction without operands. if (NumRegs) MBB.insert(MI, &*MIB); else MF.DeleteMachineInstr(MIB); return true; }
MachineBasicBlock::iterator AArch64FrameLowering::eliminateCallFramePseudoInstr( MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { const AArch64InstrInfo *TII = static_cast<const AArch64InstrInfo *>(MF.getSubtarget().getInstrInfo()); DebugLoc DL = I->getDebugLoc(); unsigned Opc = I->getOpcode(); bool IsDestroy = Opc == TII->getCallFrameDestroyOpcode(); uint64_t CalleePopAmount = IsDestroy ? I->getOperand(1).getImm() : 0; const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); if (!TFI->hasReservedCallFrame(MF)) { unsigned Align = getStackAlignment(); int64_t Amount = I->getOperand(0).getImm(); Amount = alignTo(Amount, Align); if (!IsDestroy) Amount = -Amount; // N.b. if CalleePopAmount is valid but zero (i.e. callee would pop, but it // doesn't have to pop anything), then the first operand will be zero too so // this adjustment is a no-op. if (CalleePopAmount == 0) { // FIXME: in-function stack adjustment for calls is limited to 24-bits // because there's no guaranteed temporary register available. // // ADD/SUB (immediate) has only LSL #0 and LSL #12 available. // 1) For offset <= 12-bit, we use LSL #0 // 2) For 12-bit <= offset <= 24-bit, we use two instructions. One uses // LSL #0, and the other uses LSL #12. // // Most call frames will be allocated at the start of a function so // this is OK, but it is a limitation that needs dealing with. assert(Amount > -0xffffff && Amount < 0xffffff && "call frame too large"); emitFrameOffset(MBB, I, DL, AArch64::SP, AArch64::SP, Amount, TII); } } else if (CalleePopAmount != 0) { // If the calling convention demands that the callee pops arguments from the // stack, we want to add it back if we have a reserved call frame. assert(CalleePopAmount < 0xffffff && "call frame too large"); emitFrameOffset(MBB, I, DL, AArch64::SP, AArch64::SP, -CalleePopAmount, TII); } return MBB.erase(I); }
// Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions void MipsSEFrameLowering:: eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { const MipsSEInstrInfo &TII = *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo()); if (!hasReservedCallFrame(MF)) { int64_t Amount = I->getOperand(0).getImm(); if (I->getOpcode() == Mips::ADJCALLSTACKDOWN) Amount = -Amount; unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP; TII.adjustStackPtr(SP, Amount, MBB, I); } MBB.erase(I); }
/// ReplaceTailWithBranchTo - Delete the instruction OldInst and everything /// after it, replacing it with an unconditional branch to NewDest. void TargetInstrInfoImpl::ReplaceTailWithBranchTo(MachineBasicBlock::iterator Tail, MachineBasicBlock *NewDest) const { MachineBasicBlock *MBB = Tail->getParent(); // Remove all the old successors of MBB from the CFG. while (!MBB->succ_empty()) MBB->removeSuccessor(MBB->succ_begin()); // Remove all the dead instructions from the end of MBB. MBB->erase(Tail, MBB->end()); // If MBB isn't immediately before MBB, insert a branch to it. if (++MachineFunction::iterator(MBB) != MachineFunction::iterator(NewDest)) InsertBranch(*MBB, NewDest, 0, SmallVector<MachineOperand, 0>(), Tail->getDebugLoc()); MBB->addSuccessor(NewDest); }
/// runOnMachineBasicBlock - Fixup FpMOVD instructions in this MBB. /// bool FPMover::runOnMachineBasicBlock(MachineBasicBlock &MBB) { bool Changed = false; for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ) { MachineInstr *MI = I++; DebugLoc dl = MI->getDebugLoc(); if (MI->getOpcode() == SP::FpMOVD || MI->getOpcode() == SP::FpABSD || MI->getOpcode() == SP::FpNEGD) { Changed = true; unsigned DestDReg = MI->getOperand(0).getReg(); unsigned SrcDReg = MI->getOperand(1).getReg(); if (DestDReg == SrcDReg && MI->getOpcode() == SP::FpMOVD) { MBB.erase(MI); // Eliminate the noop copy. ++NoopFpDs; continue; } unsigned EvenSrcReg = 0, OddSrcReg = 0, EvenDestReg = 0, OddDestReg = 0; getDoubleRegPair(DestDReg, EvenDestReg, OddDestReg); getDoubleRegPair(SrcDReg, EvenSrcReg, OddSrcReg); const TargetInstrInfo *TII = TM.getInstrInfo(); if (MI->getOpcode() == SP::FpMOVD) MI->setDesc(TII->get(SP::FMOVS)); else if (MI->getOpcode() == SP::FpNEGD) MI->setDesc(TII->get(SP::FNEGS)); else if (MI->getOpcode() == SP::FpABSD) MI->setDesc(TII->get(SP::FABSS)); else llvm_unreachable("Unknown opcode!"); MI->getOperand(0).setReg(EvenDestReg); MI->getOperand(1).setReg(EvenSrcReg); DEBUG(errs() << "FPMover: the modified instr is: " << *MI); // Insert copy for the other half of the double. if (DestDReg != SrcDReg) { MI = BuildMI(MBB, I, dl, TM.getInstrInfo()->get(SP::FMOVS), OddDestReg) .addReg(OddSrcReg); DEBUG(errs() << "FPMover: the inserted instr is: " << *MI); } ++NumFpDs; } } return Changed; }
// This function eliminate ADJCALLSTACKDOWN, // ADJCALLSTACKUP pseudo instructions void MipsSERegisterInfo:: eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); if (!TFI->hasReservedCallFrame(MF)) { int64_t Amount = I->getOperand(0).getImm(); if (I->getOpcode() == Mips::ADJCALLSTACKDOWN) Amount = -Amount; const MipsSEInstrInfo *II = static_cast<const MipsSEInstrInfo*>(&TII); unsigned SP = Subtarget.isABI_N64() ? Mips::SP_64 : Mips::SP; II->adjustStackPtr(SP, Amount, MBB, I); } MBB.erase(I); }
MachineBasicBlock::iterator Z80FrameLowering:: eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { //if (!hasReservedCallFrame(MF)) { unsigned Amount = TII.getFrameSize(*I); unsigned ScratchReg = I->getOperand(I->getNumOperands() - 1).getReg(); assert((Z80::A24RegClass.contains(ScratchReg) || Z80::A16RegClass.contains(ScratchReg)) && "Expected last operand to be the scratch reg."); if (I->getOpcode() == TII.getCallFrameDestroyOpcode()) { Amount -= TII.getFramePoppedByCallee(*I); assert(TargetRegisterInfo::isPhysicalRegister(ScratchReg) && "Reg alloc should have already happened."); BuildStackAdjustment(MF, MBB, I, I->getDebugLoc(), ScratchReg, Amount); } //} return MBB.erase(I); }
void ARMBaseRegisterInfo:: eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); if (!TFI->hasReservedCallFrame(MF)) { // If we have alloca, convert as follows: // ADJCALLSTACKDOWN -> sub, sp, sp, amount // ADJCALLSTACKUP -> add, sp, sp, amount MachineInstr *Old = I; DebugLoc dl = Old->getDebugLoc(); unsigned Amount = Old->getOperand(0).getImm(); if (Amount != 0) { // We need to keep the stack aligned properly. To do this, we round the // amount of space needed for the outgoing arguments up to the next // alignment boundary. unsigned Align = TFI->getStackAlignment(); Amount = (Amount+Align-1)/Align*Align; ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); assert(!AFI->isThumb1OnlyFunction() && "This eliminateCallFramePseudoInstr does not support Thumb1!"); bool isARM = !AFI->isThumbFunction(); // Replace the pseudo instruction with a new instruction... unsigned Opc = Old->getOpcode(); int PIdx = Old->findFirstPredOperandIdx(); ARMCC::CondCodes Pred = (PIdx == -1) ? ARMCC::AL : (ARMCC::CondCodes)Old->getOperand(PIdx).getImm(); if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) { // Note: PredReg is operand 2 for ADJCALLSTACKDOWN. unsigned PredReg = Old->getOperand(2).getReg(); emitSPUpdate(isARM, MBB, I, dl, TII, -Amount, Pred, PredReg); } else { // Note: PredReg is operand 3 for ADJCALLSTACKUP. unsigned PredReg = Old->getOperand(3).getReg(); assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP); emitSPUpdate(isARM, MBB, I, dl, TII, Amount, Pred, PredReg); } } } MBB.erase(I); }
bool ExpandPseudo::expandInstr(MachineBasicBlock &MBB, Iter I) { switch(I->getOpcode()) { case Mips::LOAD_CCOND_DSP: case Mips::LOAD_CCOND_DSP_P8: expandLoadCCond(MBB, I); break; case Mips::STORE_CCOND_DSP: case Mips::STORE_CCOND_DSP_P8: expandStoreCCond(MBB, I); break; case Mips::LOAD_AC64: case Mips::LOAD_AC64_P8: case Mips::LOAD_AC_DSP: case Mips::LOAD_AC_DSP_P8: expandLoadACC(MBB, I, 4); break; case Mips::LOAD_AC128: case Mips::LOAD_AC128_P8: expandLoadACC(MBB, I, 8); break; case Mips::STORE_AC64: case Mips::STORE_AC64_P8: case Mips::STORE_AC_DSP: case Mips::STORE_AC_DSP_P8: expandStoreACC(MBB, I, 4); break; case Mips::STORE_AC128: case Mips::STORE_AC128_P8: expandStoreACC(MBB, I, 8); break; case TargetOpcode::COPY: if (!expandCopy(MBB, I)) return false; break; default: return false; } MBB.erase(I); return true; }
unsigned MipsInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { MachineBasicBlock::reverse_iterator I = MBB.rbegin(), REnd = MBB.rend(); MachineBasicBlock::reverse_iterator FirstBr; unsigned removed; // Skip all the debug instructions. while (I != REnd && I->isDebugValue()) ++I; FirstBr = I; // Up to 2 branches are removed. // Note that indirect branches are not removed. for (removed = 0; I != REnd && removed < 2; ++I, ++removed) if (!getAnalyzableBrOpc(I->getOpcode())) break; MBB.erase(I.base(), FirstBr.base()); return removed; }
// Replace Branch with the compact branch instruction. Iter Filler::replaceWithCompactBranch(MachineBasicBlock &MBB, Iter Branch, DebugLoc DL) { const MipsInstrInfo *TII = MBB.getParent()->getSubtarget<MipsSubtarget>().getInstrInfo(); unsigned NewOpcode = (((unsigned) Branch->getOpcode()) == Mips::BEQ) ? Mips::BEQZC_MM : Mips::BNEZC_MM; const MCInstrDesc &NewDesc = TII->get(NewOpcode); MachineInstrBuilder MIB = BuildMI(MBB, Branch, DL, NewDesc); MIB.addReg(Branch->getOperand(0).getReg()); MIB.addMBB(Branch->getOperand(2).getMBB()); Iter tmpIter = Branch; Branch = std::prev(Branch); MBB.erase(tmpIter); return Branch; }
bool DelJmp:: runOnMachineBasicBlock(MachineBasicBlock &MBB, MachineBasicBlock &MBBN) { bool Changed = false; MachineBasicBlock::iterator I = MBB.end(); if (I != MBB.begin()) I--; // set I to the last instruction else return Changed; if (I->getOpcode() == Cpu0::JMP && I->getOperand(0).getMBB() == &MBBN) { // I is the instruction of "jmp #offset=0", as follows, // jmp $BB0_3 // $BB0_3: // ld $4, 28($sp) ++NumDelJmp; MBB.erase(I); // delete the "JMP 0" instruction Changed = true; // Notify LLVM kernel Changed } return Changed; }
void AArch64FrameLowering::eliminateCallFramePseudoInstr( MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const { const AArch64InstrInfo &TII = *static_cast<const AArch64InstrInfo *>(MF.getTarget().getInstrInfo()); DebugLoc dl = MI->getDebugLoc(); int Opcode = MI->getOpcode(); bool IsDestroy = Opcode == TII.getCallFrameDestroyOpcode(); uint64_t CalleePopAmount = IsDestroy ? MI->getOperand(1).getImm() : 0; if (!hasReservedCallFrame(MF)) { unsigned Align = getStackAlignment(); int64_t Amount = MI->getOperand(0).getImm(); Amount = RoundUpToAlignment(Amount, Align); if (!IsDestroy) Amount = -Amount; // N.b. if CalleePopAmount is valid but zero (i.e. callee would pop, but it // doesn't have to pop anything), then the first operand will be zero too so // this adjustment is a no-op. if (CalleePopAmount == 0) { // FIXME: in-function stack adjustment for calls is limited to 12-bits // because there's no guaranteed temporary register available. Mostly call // frames will be allocated at the start of a function so this is OK, but // it is a limitation that needs dealing with. assert(Amount > -0xfff && Amount < 0xfff && "call frame too large"); emitSPUpdate(MBB, MI, dl, TII, AArch64::NoRegister, Amount); } } else if (CalleePopAmount != 0) { // If the calling convention demands that the callee pops arguments from the // stack, we want to add it back if we have a reserved call frame. assert(CalleePopAmount < 0xfff && "call frame too large"); emitSPUpdate(MBB, MI, dl, TII, AArch64::NoRegister, -CalleePopAmount); } MBB.erase(MI); }
bool Thumb1InstrInfo:: restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const std::vector<CalleeSavedInfo> &CSI, const TargetRegisterInfo *TRI) const { MachineFunction &MF = *MBB.getParent(); ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); if (CSI.empty()) return false; bool isVarArg = AFI->getVarArgsRegSaveSize() > 0; DebugLoc DL = MI->getDebugLoc(); MachineInstrBuilder MIB = BuildMI(MF, DL, get(ARM::tPOP)); AddDefaultPred(MIB); bool NumRegs = false; for (unsigned i = CSI.size(); i != 0; --i) { unsigned Reg = CSI[i-1].getReg(); if (Reg == ARM::LR) { // Special epilogue for vararg functions. See emitEpilogue if (isVarArg) continue; Reg = ARM::PC; (*MIB).setDesc(get(ARM::tPOP_RET)); MI = MBB.erase(MI); } MIB.addReg(Reg, getDefRegState(true)); NumRegs = true; } // It's illegal to emit pop instruction without operands. if (NumRegs) MBB.insert(MI, &*MIB); else MF.DeleteMachineInstr(MIB); return true; }
bool AMDGPUInstrInfo::expandPostRAPseudo (MachineBasicBlock::iterator MI) const { MachineBasicBlock *MBB = MI->getParent(); switch(MI->getOpcode()) { default: if (isRegisterLoad(*MI)) { unsigned RegIndex = MI->getOperand(2).getImm(); unsigned Channel = MI->getOperand(3).getImm(); unsigned Address = calculateIndirectAddress(RegIndex, Channel); unsigned OffsetReg = MI->getOperand(1).getReg(); if (OffsetReg == AMDGPU::INDIRECT_BASE_ADDR) { buildMovInstr(MBB, MI, MI->getOperand(0).getReg(), getIndirectAddrRegClass()->getRegister(Address)); } else { buildIndirectRead(MBB, MI, MI->getOperand(0).getReg(), Address, OffsetReg); } } else if (isRegisterStore(*MI)) { unsigned RegIndex = MI->getOperand(2).getImm(); unsigned Channel = MI->getOperand(3).getImm(); unsigned Address = calculateIndirectAddress(RegIndex, Channel); unsigned OffsetReg = MI->getOperand(1).getReg(); if (OffsetReg == AMDGPU::INDIRECT_BASE_ADDR) { buildMovInstr(MBB, MI, getIndirectAddrRegClass()->getRegister(Address), MI->getOperand(0).getReg()); } else { buildIndirectWrite(MBB, MI, MI->getOperand(0).getReg(), calculateIndirectAddress(RegIndex, Channel), OffsetReg); } } else { return false; } } MBB->erase(MI); return true; }
MachineBasicBlock::iterator ARCFrameLowering::eliminateCallFramePseudoInstr( MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { LLVM_DEBUG(dbgs() << "EmitCallFramePseudo: " << MF.getName() << "\n"); const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo(); MachineInstr &Old = *I; DebugLoc dl = Old.getDebugLoc(); unsigned Amt = Old.getOperand(0).getImm(); auto *AFI = MF.getInfo<ARCFunctionInfo>(); if (!hasFP(MF)) { if (Amt > AFI->MaxCallStackReq && Old.getOpcode() == ARC::ADJCALLSTACKDOWN) AFI->MaxCallStackReq = Amt; } else { if (Amt != 0) { assert((Old.getOpcode() == ARC::ADJCALLSTACKDOWN || Old.getOpcode() == ARC::ADJCALLSTACKUP) && "Unknown Frame Pseudo."); bool IsAdd = (Old.getOpcode() == ARC::ADJCALLSTACKUP); emitRegUpdate(MBB, I, dl, ARC::SP, Amt, IsAdd, TII); } } return MBB.erase(I); }
void NyuziFrameLowering::eliminateCallFramePseudoInstr( MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const { MachineInstr &MI = *MBBI; const NyuziInstrInfo &TII = *static_cast<const NyuziInstrInfo *>(MF.getSubtarget().getInstrInfo()); // Note the check for hasReservedCallFrame. If it returns true, // PEI::calculateFrameObjectOffsets has already reserved stack locations for // these variables and we don't need to adjust the stack here. int Amount = MI.getOperand(0).getImm(); if (Amount != 0 && !hasReservedCallFrame(MF)) { assert(hasFP(MF) && "Cannot adjust stack mid-function without a frame pointer"); if (MI.getOpcode() == Nyuzi::ADJCALLSTACKDOWN) Amount = -Amount; TII.adjustStackPointer(MBB, MBBI, Amount); } MBB.erase(MBBI); }
// This function eliminate ADJCALLSTACKDOWN/ADJCALLSTACKUP pseudo instructions void MBlazeRegisterInfo:: eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { const TargetFrameInfo *TFI = MF.getTarget().getFrameInfo(); if (!TFI->hasReservedCallFrame(MF)) { // If we have a frame pointer, turn the adjcallstackup instruction into a // 'addi r1, r1, -<amt>' and the adjcallstackdown instruction into // 'addi r1, r1, <amt>' MachineInstr *Old = I; int Amount = Old->getOperand(0).getImm() + 4; if (Amount != 0) { // We need to keep the stack aligned properly. To do this, we round the // amount of space needed for the outgoing arguments up to the next // alignment boundary. unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment(); Amount = (Amount+Align-1)/Align*Align; MachineInstr *New; if (Old->getOpcode() == MBlaze::ADJCALLSTACKDOWN) { New = BuildMI(MF, Old->getDebugLoc(), TII.get(MBlaze::ADDI), MBlaze::R1) .addReg(MBlaze::R1).addImm(-Amount); } else { assert(Old->getOpcode() == MBlaze::ADJCALLSTACKUP); New = BuildMI(MF, Old->getDebugLoc(), TII.get(MBlaze::ADDI), MBlaze::R1) .addReg(MBlaze::R1).addImm(Amount); } // Replace the pseudo instruction with a new instruction... MBB.insert(I, New); } } // Simply discard ADJCALLSTACKDOWN, ADJCALLSTACKUP instructions. MBB.erase(I); }
MachineBasicBlock::iterator X86InstrInfo::reverseBranchCondition(MachineBasicBlock::iterator MI) const { unsigned Opcode = MI->getOpcode(); assert(isBranch(Opcode) && "MachineInstr must be a branch"); unsigned ROpcode; switch (Opcode) { default: assert(0 && "Cannot reverse unconditional branches!"); case X86::JB: ROpcode = X86::JAE; break; case X86::JAE: ROpcode = X86::JB; break; case X86::JE: ROpcode = X86::JNE; break; case X86::JNE: ROpcode = X86::JE; break; case X86::JBE: ROpcode = X86::JA; break; case X86::JA: ROpcode = X86::JBE; break; case X86::JS: ROpcode = X86::JNS; break; case X86::JNS: ROpcode = X86::JS; break; case X86::JL: ROpcode = X86::JGE; break; case X86::JGE: ROpcode = X86::JL; break; case X86::JLE: ROpcode = X86::JG; break; case X86::JG: ROpcode = X86::JLE; break; } MachineBasicBlock* MBB = MI->getParent(); MachineBasicBlock* TMBB = MI->getOperand(0).getMachineBasicBlock(); return BuildMI(*MBB, MBB->erase(MI), ROpcode, 1).addMBB(TMBB); }
/// spillAroundUses - insert spill code around each use of Reg. void InlineSpiller::spillAroundUses(unsigned Reg) { DEBUG(dbgs() << "spillAroundUses " << PrintReg(Reg) << '\n'); LiveInterval &OldLI = LIS.getInterval(Reg); // Iterate over instructions using Reg. for (MachineRegisterInfo::reg_iterator RegI = MRI.reg_begin(Reg); MachineInstr *MI = RegI.skipBundle();) { // Debug values are not allowed to affect codegen. if (MI->isDebugValue()) { // Modify DBG_VALUE now that the value is in a spill slot. uint64_t Offset = MI->getOperand(1).getImm(); const MDNode *MDPtr = MI->getOperand(2).getMetadata(); DebugLoc DL = MI->getDebugLoc(); if (MachineInstr *NewDV = TII.emitFrameIndexDebugValue(MF, StackSlot, Offset, MDPtr, DL)) { DEBUG(dbgs() << "Modifying debug info due to spill:" << "\t" << *MI); MachineBasicBlock *MBB = MI->getParent(); MBB->insert(MBB->erase(MI), NewDV); } else { DEBUG(dbgs() << "Removing debug info due to spill:" << "\t" << *MI); MI->eraseFromParent(); } continue; } // Ignore copies to/from snippets. We'll delete them. if (SnippetCopies.count(MI)) continue; // Stack slot accesses may coalesce away. if (coalesceStackAccess(MI, Reg)) continue; // Analyze instruction. SmallVector<std::pair<MachineInstr*, unsigned>, 8> Ops; MIBundleOperands::VirtRegInfo RI = MIBundleOperands(MI).analyzeVirtReg(Reg, &Ops); // Find the slot index where this instruction reads and writes OldLI. // This is usually the def slot, except for tied early clobbers. SlotIndex Idx = LIS.getInstructionIndex(MI).getRegSlot(); if (VNInfo *VNI = OldLI.getVNInfoAt(Idx.getRegSlot(true))) if (SlotIndex::isSameInstr(Idx, VNI->def)) Idx = VNI->def; // Check for a sibling copy. unsigned SibReg = isFullCopyOf(MI, Reg); if (SibReg && isSibling(SibReg)) { // This may actually be a copy between snippets. if (isRegToSpill(SibReg)) { DEBUG(dbgs() << "Found new snippet copy: " << *MI); SnippetCopies.insert(MI); continue; } if (RI.Writes) { // Hoist the spill of a sib-reg copy. if (hoistSpill(OldLI, MI)) { // This COPY is now dead, the value is already in the stack slot. MI->getOperand(0).setIsDead(); DeadDefs.push_back(MI); continue; } } else { // This is a reload for a sib-reg copy. Drop spills downstream. LiveInterval &SibLI = LIS.getInterval(SibReg); eliminateRedundantSpills(SibLI, SibLI.getVNInfoAt(Idx)); // The COPY will fold to a reload below. } } // Attempt to fold memory ops. if (foldMemoryOperand(Ops)) continue; // Allocate interval around instruction. // FIXME: Infer regclass from instruction alone. LiveInterval &NewLI = Edit->createFrom(Reg); NewLI.markNotSpillable(); if (RI.Reads) insertReload(NewLI, Idx, MI); // Rewrite instruction operands. bool hasLiveDef = false; for (unsigned i = 0, e = Ops.size(); i != e; ++i) { MachineOperand &MO = Ops[i].first->getOperand(Ops[i].second); MO.setReg(NewLI.reg); if (MO.isUse()) { if (!Ops[i].first->isRegTiedToDefOperand(Ops[i].second)) MO.setIsKill(); } else { if (!MO.isDead()) hasLiveDef = true; } } DEBUG(dbgs() << "\trewrite: " << Idx << '\t' << *MI); // FIXME: Use a second vreg if instruction has no tied ops. if (RI.Writes) { if (hasLiveDef) insertSpill(NewLI, OldLI, Idx, MI); else { // This instruction defines a dead value. We don't need to spill it, // but do create a live range for the dead value. VNInfo *VNI = NewLI.getNextValue(Idx, LIS.getVNInfoAllocator()); NewLI.addRange(LiveRange(Idx, Idx.getDeadSlot(), VNI)); } } DEBUG(dbgs() << "\tinterval: " << NewLI << '\n'); } }
void AArch64FrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { AArch64MachineFunctionInfo *FuncInfo = MF.getInfo<AArch64MachineFunctionInfo>(); MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); DebugLoc DL = MBBI->getDebugLoc(); const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); MachineFrameInfo &MFI = *MF.getFrameInfo(); unsigned RetOpcode = MBBI->getOpcode(); // Initial and residual are named for consitency with the prologue. Note that // in the epilogue, the residual adjustment is executed first. uint64_t NumInitialBytes = FuncInfo->getInitialStackAdjust(); uint64_t NumResidualBytes = MFI.getStackSize() - NumInitialBytes; uint64_t ArgumentPopSize = 0; if (RetOpcode == AArch64::TC_RETURNdi || RetOpcode == AArch64::TC_RETURNxi) { MachineOperand &JumpTarget = MBBI->getOperand(0); MachineOperand &StackAdjust = MBBI->getOperand(1); MachineInstrBuilder MIB; if (RetOpcode == AArch64::TC_RETURNdi) { MIB = BuildMI(MBB, MBBI, DL, TII.get(AArch64::TAIL_Bimm)); if (JumpTarget.isGlobal()) { MIB.addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(), JumpTarget.getTargetFlags()); } else { assert(JumpTarget.isSymbol() && "unexpected tail call destination"); MIB.addExternalSymbol(JumpTarget.getSymbolName(), JumpTarget.getTargetFlags()); } } else { assert(RetOpcode == AArch64::TC_RETURNxi && JumpTarget.isReg() && "Unexpected tail call"); MIB = BuildMI(MBB, MBBI, DL, TII.get(AArch64::TAIL_BRx)); MIB.addReg(JumpTarget.getReg(), RegState::Kill); } // Add the extra operands onto the new tail call instruction even though // they're not used directly (so that liveness is tracked properly etc). for (unsigned i = 2, e = MBBI->getNumOperands(); i != e; ++i) MIB->addOperand(MBBI->getOperand(i)); // Delete the pseudo instruction TC_RETURN. MachineInstr *NewMI = std::prev(MBBI); MBB.erase(MBBI); MBBI = NewMI; // For a tail-call in a callee-pops-arguments environment, some or all of // the stack may actually be in use for the call's arguments, this is // calculated during LowerCall and consumed here... ArgumentPopSize = StackAdjust.getImm(); } else { // ... otherwise the amount to pop is *all* of the argument space, // conveniently stored in the MachineFunctionInfo by // LowerFormalArguments. This will, of course, be zero for the C calling // convention. ArgumentPopSize = FuncInfo->getArgumentStackToRestore(); } assert(NumInitialBytes % 16 == 0 && NumResidualBytes % 16 == 0 && "refusing to adjust stack by misaligned amt"); // We may need to address callee-saved registers differently, so find out the // bound on the frame indices. const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); int MinCSFI = 0; int MaxCSFI = -1; if (CSI.size()) { MinCSFI = CSI[0].getFrameIdx(); MaxCSFI = CSI[CSI.size() - 1].getFrameIdx(); } // The "residual" stack update comes first from this direction and guarantees // that SP is NumInitialBytes below its value on function entry, either by a // direct update or restoring it from the frame pointer. if (NumInitialBytes + ArgumentPopSize != 0) { emitSPUpdate(MBB, MBBI, DL, TII, AArch64::X16, NumInitialBytes + ArgumentPopSize); --MBBI; } // MBBI now points to the instruction just past the last callee-saved // restoration (either RET/B if NumInitialBytes == 0, or the "ADD sp, sp" // otherwise). // Now we need to find out where to put the bulk of the stack adjustment MachineBasicBlock::iterator FirstEpilogue = MBBI; while (MBBI != MBB.begin()) { --MBBI; unsigned FrameOp; for (FrameOp = 0; FrameOp < MBBI->getNumOperands(); ++FrameOp) { if (MBBI->getOperand(FrameOp).isFI()) break; } // If this instruction doesn't have a frame index we've reached the end of // the callee-save restoration. if (FrameOp == MBBI->getNumOperands()) break; // Likewise if it *is* a local reference, but not to a callee-saved object. int FrameIdx = MBBI->getOperand(FrameOp).getIndex(); if (FrameIdx < MinCSFI || FrameIdx > MaxCSFI) break; FirstEpilogue = MBBI; } if (MF.getFrameInfo()->hasVarSizedObjects()) { int64_t StaticFrameBase; StaticFrameBase = -(NumInitialBytes + FuncInfo->getFramePointerOffset()); emitRegUpdate(MBB, FirstEpilogue, DL, TII, AArch64::XSP, AArch64::X29, AArch64::NoRegister, StaticFrameBase); } else { emitSPUpdate(MBB, FirstEpilogue, DL,TII, AArch64::X16, NumResidualBytes); } }
// This function eliminate ADJCALLSTACKDOWN, // ADJCALLSTACKUP pseudo instructions void Cpu0FrameLowering:: eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { // Simply discard ADJCALLSTACKDOWN, ADJCALLSTACKUP instructions. MBB.erase(I); }
bool Thumb1FrameLowering:: restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, std::vector<CalleeSavedInfo> &CSI, const TargetRegisterInfo *TRI) const { if (CSI.empty()) return false; 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(); ARMRegSet LoRegsToRestore; ARMRegSet HiRegsToRestore; // Low registers (r0-r7) which can be used to restore the high registers. ARMRegSet CopyRegs; for (CalleeSavedInfo I : CSI) { unsigned Reg = I.getReg(); if (ARM::tGPRRegClass.contains(Reg) || Reg == ARM::LR) { LoRegsToRestore[Reg] = true; } else if (ARM::hGPRRegClass.contains(Reg) && Reg != ARM::LR) { HiRegsToRestore[Reg] = true; } 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[Reg] = true; } // 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[ARM::R0] = true; CopyRegs[ARM::R1] = true; CopyRegs[ARM::R2] = true; CopyRegs[ARM::R3] = true; for (auto Op : Terminator->implicit_operands()) { if (Op.isReg()) CopyRegs[Op.getReg()] = false; } } static const unsigned AllCopyRegs[] = {ARM::R0, ARM::R1, ARM::R2, ARM::R3, ARM::R4, ARM::R5, ARM::R6, ARM::R7}; static const unsigned AllHighRegs[] = {ARM::R8, ARM::R9, ARM::R10, ARM::R11}; const unsigned *AllCopyRegsEnd = std::end(AllCopyRegs); const unsigned *AllHighRegsEnd = std::end(AllHighRegs); // Find the first register to restore. auto HiRegToRestore = findNextOrderedReg(std::begin(AllHighRegs), HiRegsToRestore, AllHighRegsEnd); while (HiRegToRestore != AllHighRegsEnd) { assert(!CopyRegs.none()); // Find the first low register to use. auto CopyReg = findNextOrderedReg(std::begin(AllCopyRegs), CopyRegs, AllCopyRegsEnd); // Create the POP instruction. MachineInstrBuilder PopMIB = BuildMI(MBB, MI, DL, TII.get(ARM::tPOP)).add(predOps(ARMCC::AL)); while (HiRegToRestore != AllHighRegsEnd && CopyReg != AllCopyRegsEnd) { // Add the low register to the POP. PopMIB.addReg(*CopyReg, RegState::Define); // Create the MOV from low to high register. BuildMI(MBB, MI, DL, TII.get(ARM::tMOVr)) .addReg(*HiRegToRestore, RegState::Define) .addReg(*CopyReg, RegState::Kill) .add(predOps(ARMCC::AL)); CopyReg = findNextOrderedReg(++CopyReg, CopyRegs, AllCopyRegsEnd); HiRegToRestore = findNextOrderedReg(++HiRegToRestore, HiRegsToRestore, AllHighRegsEnd); } } MachineInstrBuilder MIB = BuildMI(MF, DL, TII.get(ARM::tPOP)).add(predOps(ARMCC::AL)); bool NeedsPop = false; for (unsigned i = CSI.size(); i != 0; --i) { CalleeSavedInfo &Info = CSI[i-1]; unsigned Reg = Info.getReg(); // High registers (excluding lr) have already been dealt with if (!(ARM::tGPRRegClass.contains(Reg) || Reg == ARM::LR)) continue; if (Reg == ARM::LR) { Info.setRestored(false); if (!MBB.succ_empty() || MI->getOpcode() == ARM::TCRETURNdi || MI->getOpcode() == ARM::TCRETURNri) // LR may only be popped into PC, as part of return sequence. // If this isn't the return sequence, we'll need emitPopSpecialFixUp // to restore LR the hard way. // FIXME: if we don't pass any stack arguments it would be actually // advantageous *and* correct to do the conversion to an ordinary call // instruction here. continue; // Special epilogue for vararg functions. See emitEpilogue if (isVarArg) continue; // ARMv4T requires BX, see emitEpilogue if (!STI.hasV5TOps()) continue; // Pop LR into PC. Reg = ARM::PC; (*MIB).setDesc(TII.get(ARM::tPOP_RET)); if (MI != MBB.end()) MIB.copyImplicitOps(*MI); MI = MBB.erase(MI); } MIB.addReg(Reg, getDefRegState(true)); NeedsPop = true; } // It's illegal to emit pop instruction without operands. if (NeedsPop) MBB.insert(MI, &*MIB); else MF.DeleteMachineInstr(MIB); return true; }
/// If \p MBBI is a pseudo instruction, this method expands /// it to the corresponding (sequence of) actual instruction(s). /// \returns true if \p MBBI has been expanded. bool X86ExpandPseudo::ExpandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) { MachineInstr &MI = *MBBI; unsigned Opcode = MI.getOpcode(); DebugLoc DL = MBBI->getDebugLoc(); switch (Opcode) { default: return false; case X86::TCRETURNdi: case X86::TCRETURNri: case X86::TCRETURNmi: case X86::TCRETURNdi64: case X86::TCRETURNri64: case X86::TCRETURNmi64: { bool isMem = Opcode == X86::TCRETURNmi || Opcode == X86::TCRETURNmi64; MachineOperand &JumpTarget = MBBI->getOperand(0); MachineOperand &StackAdjust = MBBI->getOperand(isMem ? 5 : 1); assert(StackAdjust.isImm() && "Expecting immediate value."); // Adjust stack pointer. int StackAdj = StackAdjust.getImm(); if (StackAdj) { // Check for possible merge with preceding ADD instruction. StackAdj += X86FL->mergeSPUpdates(MBB, MBBI, true); X86FL->emitSPUpdate(MBB, MBBI, StackAdj, /*InEpilogue=*/true); } // Jump to label or value in register. bool IsWin64 = STI->isTargetWin64(); if (Opcode == X86::TCRETURNdi || Opcode == X86::TCRETURNdi64) { unsigned Op = (Opcode == X86::TCRETURNdi) ? X86::TAILJMPd : (IsWin64 ? X86::TAILJMPd64_REX : X86::TAILJMPd64); MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(Op)); if (JumpTarget.isGlobal()) MIB.addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(), JumpTarget.getTargetFlags()); else { assert(JumpTarget.isSymbol()); MIB.addExternalSymbol(JumpTarget.getSymbolName(), JumpTarget.getTargetFlags()); } } else if (Opcode == X86::TCRETURNmi || Opcode == X86::TCRETURNmi64) { unsigned Op = (Opcode == X86::TCRETURNmi) ? X86::TAILJMPm : (IsWin64 ? X86::TAILJMPm64_REX : X86::TAILJMPm64); MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(Op)); for (unsigned i = 0; i != 5; ++i) MIB.addOperand(MBBI->getOperand(i)); } else if (Opcode == X86::TCRETURNri64) { BuildMI(MBB, MBBI, DL, TII->get(IsWin64 ? X86::TAILJMPr64_REX : X86::TAILJMPr64)) .addReg(JumpTarget.getReg(), RegState::Kill); } else { BuildMI(MBB, MBBI, DL, TII->get(X86::TAILJMPr)) .addReg(JumpTarget.getReg(), RegState::Kill); } MachineInstr *NewMI = std::prev(MBBI); NewMI->copyImplicitOps(*MBBI->getParent()->getParent(), *MBBI); // Delete the pseudo instruction TCRETURN. MBB.erase(MBBI); return true; } case X86::EH_RETURN: case X86::EH_RETURN64: { MachineOperand &DestAddr = MBBI->getOperand(0); assert(DestAddr.isReg() && "Offset should be in register!"); const bool Uses64BitFramePtr = STI->isTarget64BitLP64() || STI->isTargetNaCl64(); unsigned StackPtr = TRI->getStackRegister(); BuildMI(MBB, MBBI, DL, TII->get(Uses64BitFramePtr ? X86::MOV64rr : X86::MOV32rr), StackPtr) .addReg(DestAddr.getReg()); // The EH_RETURN pseudo is really removed during the MC Lowering. return true; } case X86::IRET: { // Adjust stack to erase error code int64_t StackAdj = MBBI->getOperand(0).getImm(); X86FL->emitSPUpdate(MBB, MBBI, StackAdj, true); // Replace pseudo with machine iret BuildMI(MBB, MBBI, DL, TII->get(STI->is64Bit() ? X86::IRET64 : X86::IRET32)); MBB.erase(MBBI); return true; } case X86::RET: { // Adjust stack to erase error code int64_t StackAdj = MBBI->getOperand(0).getImm(); MachineInstrBuilder MIB; if (StackAdj == 0) { MIB = BuildMI(MBB, MBBI, DL, TII->get(STI->is64Bit() ? X86::RETQ : X86::RETL)); } else if (isUInt<16>(StackAdj)) { MIB = BuildMI(MBB, MBBI, DL, TII->get(STI->is64Bit() ? X86::RETIQ : X86::RETIL)) .addImm(StackAdj); } else { assert(!STI->is64Bit() && "shouldn't need to do this for x86_64 targets!"); // A ret can only handle immediates as big as 2**16-1. If we need to pop // off bytes before the return address, we must do it manually. BuildMI(MBB, MBBI, DL, TII->get(X86::POP32r)).addReg(X86::ECX, RegState::Define); X86FL->emitSPUpdate(MBB, MBBI, StackAdj, /*InEpilogue=*/true); BuildMI(MBB, MBBI, DL, TII->get(X86::PUSH32r)).addReg(X86::ECX); MIB = BuildMI(MBB, MBBI, DL, TII->get(X86::RETL)); } for (unsigned I = 1, E = MBBI->getNumOperands(); I != E; ++I) MIB.addOperand(MBBI->getOperand(I)); MBB.erase(MBBI); return true; } case X86::EH_RESTORE: { // Restore ESP and EBP, and optionally ESI if required. bool IsSEH = isAsynchronousEHPersonality(classifyEHPersonality( MBB.getParent()->getFunction()->getPersonalityFn())); X86FL->restoreWin32EHStackPointers(MBB, MBBI, DL, /*RestoreSP=*/IsSEH); MBBI->eraseFromParent(); return true; } } llvm_unreachable("Previous switch has a fallthrough?"); }
static void analyzeFrameIndexes(MachineFunction &MF) { if (MBDisableStackAdjust) return; MachineFrameInfo *MFI = MF.getFrameInfo(); MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); const MachineRegisterInfo &MRI = MF.getRegInfo(); MachineRegisterInfo::livein_iterator LII = MRI.livein_begin(); MachineRegisterInfo::livein_iterator LIE = MRI.livein_end(); const SmallVector<int, 16> &LiveInFI = MBlazeFI->getLiveIn(); SmallVector<MachineInstr*, 16> EraseInstr; SmallVector<std::pair<int,int64_t>, 16> FrameRelocate; MachineBasicBlock *MBB = MF.getBlockNumbered(0); MachineBasicBlock::iterator MIB = MBB->begin(); MachineBasicBlock::iterator MIE = MBB->end(); int StackAdjust = 0; int StackOffset = -28; // In this loop we are searching frame indexes that corrospond to incoming // arguments that are already in the stack. We look for instruction sequences // like the following: // // LWI REG, FI1, 0 // ... // SWI REG, FI2, 0 // // As long as there are no defs of REG in the ... part, we can eliminate // the SWI instruction because the value has already been stored to the // stack by the caller. All we need to do is locate FI at the correct // stack location according to the calling convensions. // // Additionally, if the SWI operation kills the def of REG then we don't // need the LWI operation so we can erase it as well. for (unsigned i = 0, e = LiveInFI.size(); i < e; ++i) { for (MachineBasicBlock::iterator I=MIB; I != MIE; ++I) { if (I->getOpcode() != MBlaze::LWI || I->getNumOperands() != 3 || !I->getOperand(1).isFI() || !I->getOperand(0).isReg() || I->getOperand(1).getIndex() != LiveInFI[i]) continue; unsigned FIReg = I->getOperand(0).getReg(); MachineBasicBlock::iterator SI = I; for (SI++; SI != MIE; ++SI) { if (!SI->getOperand(0).isReg() || !SI->getOperand(1).isFI() || SI->getOpcode() != MBlaze::SWI) continue; int FI = SI->getOperand(1).getIndex(); if (SI->getOperand(0).getReg() != FIReg || MFI->isFixedObjectIndex(FI) || MFI->getObjectSize(FI) != 4) continue; if (SI->getOperand(0).isDef()) break; if (SI->getOperand(0).isKill()) { DEBUG(dbgs() << "LWI for FI#" << I->getOperand(1).getIndex() << " removed\n"); EraseInstr.push_back(I); } EraseInstr.push_back(SI); DEBUG(dbgs() << "SWI for FI#" << FI << " removed\n"); FrameRelocate.push_back(std::make_pair(FI,StackOffset)); DEBUG(dbgs() << "FI#" << FI << " relocated to " << StackOffset << "\n"); StackOffset -= 4; StackAdjust += 4; break; } } } // In this loop we are searching for frame indexes that corrospond to // incoming arguments that are in registers. We look for instruction // sequences like the following: // // ... SWI REG, FI, 0 // // As long as the ... part does not define REG and if REG is an incoming // parameter register then we know that, according to ABI convensions, the // caller has allocated stack space for it already. Instead of allocating // stack space on our frame, we record the correct location in the callers // frame. for (MachineRegisterInfo::livein_iterator LI = LII; LI != LIE; ++LI) { for (MachineBasicBlock::iterator I=MIB; I != MIE; ++I) { if (I->definesRegister(LI->first)) break; if (I->getOpcode() != MBlaze::SWI || I->getNumOperands() != 3 || !I->getOperand(1).isFI() || !I->getOperand(0).isReg() || I->getOperand(1).getIndex() < 0) continue; if (I->getOperand(0).getReg() == LI->first) { int FI = I->getOperand(1).getIndex(); MBlazeFI->recordLiveIn(FI); int FILoc = 0; switch (LI->first) { default: llvm_unreachable("invalid incoming parameter!"); case MBlaze::R5: FILoc = -4; break; case MBlaze::R6: FILoc = -8; break; case MBlaze::R7: FILoc = -12; break; case MBlaze::R8: FILoc = -16; break; case MBlaze::R9: FILoc = -20; break; case MBlaze::R10: FILoc = -24; break; } StackAdjust += 4; FrameRelocate.push_back(std::make_pair(FI,FILoc)); DEBUG(dbgs() << "FI#" << FI << " relocated to " << FILoc << "\n"); break; } } } // Go ahead and erase all of the instructions that we determined were // no longer needed. for (int i = 0, e = EraseInstr.size(); i < e; ++i) MBB->erase(EraseInstr[i]); // Replace all of the frame indexes that we have relocated with new // fixed object frame indexes. replaceFrameIndexes(MF, FrameRelocate); }
bool Thumb1FrameLowering::emitPopSpecialFixUp(MachineBasicBlock &MBB, bool DoIt) const { MachineFunction &MF = *MBB.getParent(); ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); unsigned ArgRegsSaveSize = AFI->getArgRegsSaveSize(); const TargetInstrInfo &TII = *STI.getInstrInfo(); const ThumbRegisterInfo *RegInfo = static_cast<const ThumbRegisterInfo *>(STI.getRegisterInfo()); // If MBBI is a return instruction, we may be able to directly restore // LR in the PC. // This is possible if we do not need to emit any SP update. // Otherwise, we need a temporary register to pop the value // and copy that value into LR. auto MBBI = MBB.getFirstTerminator(); if (!ArgRegsSaveSize && MBBI != MBB.end() && MBBI->getOpcode() == ARM::tBX_RET) { if (!DoIt) return true; MachineInstrBuilder MIB = AddDefaultPred( BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII.get(ARM::tPOP_RET))) .addReg(ARM::PC, RegState::Define); MIB.copyImplicitOps(&*MBBI); // erase the old tBX_RET instruction MBB.erase(MBBI); return true; } // Look for a temporary register to use. // First, compute the liveness information. LivePhysRegs UsedRegs(STI.getRegisterInfo()); UsedRegs.addLiveOuts(&MBB, /*AddPristines*/ true); // The semantic of pristines changed recently and now, // the callee-saved registers that are touched in the function // are not part of the pristines set anymore. // Add those callee-saved now. const TargetRegisterInfo *TRI = STI.getRegisterInfo(); const MCPhysReg *CSRegs = TRI->getCalleeSavedRegs(&MF); for (unsigned i = 0; CSRegs[i]; ++i) UsedRegs.addReg(CSRegs[i]); DebugLoc dl = DebugLoc(); if (MBBI != MBB.end()) { dl = MBBI->getDebugLoc(); auto InstUpToMBBI = MBB.end(); // The post-decrement is on purpose here. // We want to have the liveness right before MBBI. while (InstUpToMBBI-- != MBBI) UsedRegs.stepBackward(*InstUpToMBBI); } // Look for a register that can be directly use in the POP. unsigned PopReg = 0; // And some temporary register, just in case. unsigned TemporaryReg = 0; BitVector PopFriendly = TRI->getAllocatableSet(MF, TRI->getRegClass(ARM::tGPRRegClassID)); assert(PopFriendly.any() && "No allocatable pop-friendly register?!"); // Rebuild the GPRs from the high registers because they are removed // form the GPR reg class for thumb1. BitVector GPRsNoLRSP = TRI->getAllocatableSet(MF, TRI->getRegClass(ARM::hGPRRegClassID)); GPRsNoLRSP |= PopFriendly; GPRsNoLRSP.reset(ARM::LR); GPRsNoLRSP.reset(ARM::SP); GPRsNoLRSP.reset(ARM::PC); for (int Register = GPRsNoLRSP.find_first(); Register != -1; Register = GPRsNoLRSP.find_next(Register)) { if (!UsedRegs.contains(Register)) { // Remember the first pop-friendly register and exit. if (PopFriendly.test(Register)) { PopReg = Register; TemporaryReg = 0; break; } // Otherwise, remember that the register will be available to // save a pop-friendly register. TemporaryReg = Register; } } if (!DoIt && !PopReg && !TemporaryReg) return false; assert((PopReg || TemporaryReg) && "Cannot get LR"); if (TemporaryReg) { assert(!PopReg && "Unnecessary MOV is about to be inserted"); PopReg = PopFriendly.find_first(); AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr)) .addReg(TemporaryReg, RegState::Define) .addReg(PopReg, RegState::Kill)); } assert(PopReg && "Do not know how to get LR"); AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tPOP))) .addReg(PopReg, RegState::Define); emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, ArgRegsSaveSize); if (!TemporaryReg && MBBI != MBB.end() && MBBI->getOpcode() == ARM::tBX_RET) { MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(ARM::tBX)) .addReg(PopReg, RegState::Kill); AddDefaultPred(MIB); MIB.copyImplicitOps(&*MBBI); // erase the old tBX_RET instruction MBB.erase(MBBI); return true; } AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr)) .addReg(ARM::LR, RegState::Define) .addReg(PopReg, RegState::Kill)); if (TemporaryReg) { AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr)) .addReg(PopReg, RegState::Define) .addReg(TemporaryReg, RegState::Kill)); } return true; }
void RAFast::AllocateBasicBlock() { DEBUG(dbgs() << "\nAllocating " << *MBB); PhysRegState.assign(TRI->getNumRegs(), regDisabled); assert(LiveVirtRegs.empty() && "Mapping not cleared from last block?"); MachineBasicBlock::iterator MII = MBB->begin(); // Add live-in registers as live. for (MachineBasicBlock::livein_iterator I = MBB->livein_begin(), E = MBB->livein_end(); I != E; ++I) if (RegClassInfo.isAllocatable(*I)) definePhysReg(MII, *I, regReserved); SmallVector<unsigned, 8> VirtDead; SmallVector<MachineInstr*, 32> Coalesced; // Otherwise, sequentially allocate each instruction in the MBB. while (MII != MBB->end()) { MachineInstr *MI = MII++; const MCInstrDesc &MCID = MI->getDesc(); DEBUG({ dbgs() << "\n>> " << *MI << "Regs:"; for (unsigned Reg = 1, E = TRI->getNumRegs(); Reg != E; ++Reg) { if (PhysRegState[Reg] == regDisabled) continue; dbgs() << " " << TRI->getName(Reg); switch(PhysRegState[Reg]) { case regFree: break; case regReserved: dbgs() << "*"; break; default: { dbgs() << '=' << PrintReg(PhysRegState[Reg]); LiveRegMap::iterator I = findLiveVirtReg(PhysRegState[Reg]); assert(I != LiveVirtRegs.end() && "Missing VirtReg entry"); if (I->Dirty) dbgs() << "*"; assert(I->PhysReg == Reg && "Bad inverse map"); break; } } } dbgs() << '\n'; // Check that LiveVirtRegs is the inverse. for (LiveRegMap::iterator i = LiveVirtRegs.begin(), e = LiveVirtRegs.end(); i != e; ++i) { assert(TargetRegisterInfo::isVirtualRegister(i->VirtReg) && "Bad map key"); assert(TargetRegisterInfo::isPhysicalRegister(i->PhysReg) && "Bad map value"); assert(PhysRegState[i->PhysReg] == i->VirtReg && "Bad inverse map"); } }); // Debug values are not allowed to change codegen in any way. if (MI->isDebugValue()) { bool ScanDbgValue = true; while (ScanDbgValue) { ScanDbgValue = false; for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { MachineOperand &MO = MI->getOperand(i); if (!MO.isReg()) continue; unsigned Reg = MO.getReg(); if (!TargetRegisterInfo::isVirtualRegister(Reg)) continue; LiveRegMap::iterator LRI = findLiveVirtReg(Reg); if (LRI != LiveVirtRegs.end()) setPhysReg(MI, i, LRI->PhysReg); else { int SS = StackSlotForVirtReg[Reg]; if (SS == -1) { // We can't allocate a physreg for a DebugValue, sorry! DEBUG(dbgs() << "Unable to allocate vreg used by DBG_VALUE"); MO.setReg(0); } else { // Modify DBG_VALUE now that the value is in a spill slot. int64_t Offset = MI->getOperand(1).getImm(); const MDNode *MDPtr = MI->getOperand(MI->getNumOperands()-1).getMetadata(); DebugLoc DL = MI->getDebugLoc(); if (MachineInstr *NewDV = TII->emitFrameIndexDebugValue(*MF, SS, Offset, MDPtr, DL)) { DEBUG(dbgs() << "Modifying debug info due to spill:" << "\t" << *MI); MachineBasicBlock *MBB = MI->getParent(); MBB->insert(MBB->erase(MI), NewDV); // Scan NewDV operands from the beginning. MI = NewDV; ScanDbgValue = true; break; } else { // We can't allocate a physreg for a DebugValue; sorry! DEBUG(dbgs() << "Unable to allocate vreg used by DBG_VALUE"); MO.setReg(0); } } } LiveDbgValueMap[Reg].push_back(MI); } } // Next instruction. continue; } // GC register roots need special care here, since inserting reloads can // break the call sequence. if (MI->isGCRegRoot()) { handleGCRegRoot(MI); continue; } // If this is a copy, we may be able to coalesce. unsigned CopySrc = 0, CopyDst = 0, CopySrcSub = 0, CopyDstSub = 0; if (MI->isCopy()) { CopyDst = MI->getOperand(0).getReg(); CopySrc = MI->getOperand(1).getReg(); CopyDstSub = MI->getOperand(0).getSubReg(); CopySrcSub = MI->getOperand(1).getSubReg(); } // Track registers used by instruction. UsedInInstr.reset(); // First scan. // Mark physreg uses and early clobbers as used. // Find the end of the virtreg operands unsigned VirtOpEnd = 0; bool hasTiedOps = false; bool hasEarlyClobbers = false; bool hasPartialRedefs = false; bool hasPhysDefs = false; for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { MachineOperand &MO = MI->getOperand(i); if (!MO.isReg()) continue; unsigned Reg = MO.getReg(); if (!Reg) continue; if (TargetRegisterInfo::isVirtualRegister(Reg)) { VirtOpEnd = i+1; if (MO.isUse()) { hasTiedOps = hasTiedOps || MCID.getOperandConstraint(i, MCOI::TIED_TO) != -1; } else { if (MO.isEarlyClobber()) hasEarlyClobbers = true; if (MO.getSubReg() && MI->readsVirtualRegister(Reg)) hasPartialRedefs = true; } continue; } if (!RegClassInfo.isAllocatable(Reg)) continue; if (MO.isUse()) { usePhysReg(MO); } else if (MO.isEarlyClobber()) { definePhysReg(MI, Reg, (MO.isImplicit() || MO.isDead()) ? regFree : regReserved); hasEarlyClobbers = true; } else hasPhysDefs = true; } // The instruction may have virtual register operands that must be allocated // the same register at use-time and def-time: early clobbers and tied // operands. If there are also physical defs, these registers must avoid // both physical defs and uses, making them more constrained than normal // operands. // Similarly, if there are multiple defs and tied operands, we must make // sure the same register is allocated to uses and defs. // We didn't detect inline asm tied operands above, so just make this extra // pass for all inline asm. if (MI->isInlineAsm() || hasEarlyClobbers || hasPartialRedefs || (hasTiedOps && (hasPhysDefs || MCID.getNumDefs() > 1))) { handleThroughOperands(MI, VirtDead); // Don't attempt coalescing when we have funny stuff going on. CopyDst = 0; // Pretend we have early clobbers so the use operands get marked below. // This is not necessary for the common case of a single tied use. hasEarlyClobbers = true; } // Second scan. // Allocate virtreg uses. for (unsigned i = 0; i != VirtOpEnd; ++i) { MachineOperand &MO = MI->getOperand(i); if (!MO.isReg()) continue; unsigned Reg = MO.getReg(); if (!TargetRegisterInfo::isVirtualRegister(Reg)) continue; if (MO.isUse()) { LiveRegMap::iterator LRI = reloadVirtReg(MI, i, Reg, CopyDst); unsigned PhysReg = LRI->PhysReg; CopySrc = (CopySrc == Reg || CopySrc == PhysReg) ? PhysReg : 0; if (setPhysReg(MI, i, PhysReg)) killVirtReg(LRI); } } MRI->addPhysRegsUsed(UsedInInstr); // Track registers defined by instruction - early clobbers and tied uses at // this point. UsedInInstr.reset(); if (hasEarlyClobbers) { for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { MachineOperand &MO = MI->getOperand(i); if (!MO.isReg()) continue; unsigned Reg = MO.getReg(); if (!Reg || !TargetRegisterInfo::isPhysicalRegister(Reg)) continue; // Look for physreg defs and tied uses. if (!MO.isDef() && !MI->isRegTiedToDefOperand(i)) continue; for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) UsedInInstr.set(*AI); } } unsigned DefOpEnd = MI->getNumOperands(); if (MI->isCall()) { // Spill all virtregs before a call. This serves two purposes: 1. If an // exception is thrown, the landing pad is going to expect to find // registers in their spill slots, and 2. we don't have to wade through // all the <imp-def> operands on the call instruction. DefOpEnd = VirtOpEnd; DEBUG(dbgs() << " Spilling remaining registers before call.\n"); spillAll(MI); // The imp-defs are skipped below, but we still need to mark those // registers as used by the function. SkippedInstrs.insert(&MCID); } // Third scan. // Allocate defs and collect dead defs. for (unsigned i = 0; i != DefOpEnd; ++i) { MachineOperand &MO = MI->getOperand(i); if (!MO.isReg() || !MO.isDef() || !MO.getReg() || MO.isEarlyClobber()) continue; unsigned Reg = MO.getReg(); if (TargetRegisterInfo::isPhysicalRegister(Reg)) { if (!RegClassInfo.isAllocatable(Reg)) continue; definePhysReg(MI, Reg, (MO.isImplicit() || MO.isDead()) ? regFree : regReserved); continue; } LiveRegMap::iterator LRI = defineVirtReg(MI, i, Reg, CopySrc); unsigned PhysReg = LRI->PhysReg; if (setPhysReg(MI, i, PhysReg)) { VirtDead.push_back(Reg); CopyDst = 0; // cancel coalescing; } else CopyDst = (CopyDst == Reg || CopyDst == PhysReg) ? PhysReg : 0; } // Kill dead defs after the scan to ensure that multiple defs of the same // register are allocated identically. We didn't need to do this for uses // because we are crerating our own kill flags, and they are always at the // last use. for (unsigned i = 0, e = VirtDead.size(); i != e; ++i) killVirtReg(VirtDead[i]); VirtDead.clear(); MRI->addPhysRegsUsed(UsedInInstr); if (CopyDst && CopyDst == CopySrc && CopyDstSub == CopySrcSub) { DEBUG(dbgs() << "-- coalescing: " << *MI); Coalesced.push_back(MI); } else { DEBUG(dbgs() << "<< " << *MI); } }
bool Thumb1FrameLowering::emitPopSpecialFixUp(MachineBasicBlock &MBB, bool DoIt) const { MachineFunction &MF = *MBB.getParent(); ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); unsigned ArgRegsSaveSize = AFI->getArgRegsSaveSize(); const TargetInstrInfo &TII = *STI.getInstrInfo(); const ThumbRegisterInfo *RegInfo = static_cast<const ThumbRegisterInfo *>(STI.getRegisterInfo()); // If MBBI is a return instruction, or is a tPOP followed by a return // instruction in the successor BB, we may be able to directly restore // LR in the PC. // This is only possible with v5T ops (v4T can't change the Thumb bit via // a POP PC instruction), and only if we do not need to emit any SP update. // Otherwise, we need a temporary register to pop the value // and copy that value into LR. auto MBBI = MBB.getFirstTerminator(); bool CanRestoreDirectly = STI.hasV5TOps() && !ArgRegsSaveSize; if (CanRestoreDirectly) { if (MBBI != MBB.end() && MBBI->getOpcode() != ARM::tB) CanRestoreDirectly = (MBBI->getOpcode() == ARM::tBX_RET || MBBI->getOpcode() == ARM::tPOP_RET); else { auto MBBI_prev = MBBI; MBBI_prev--; assert(MBBI_prev->getOpcode() == ARM::tPOP); assert(MBB.succ_size() == 1); if ((*MBB.succ_begin())->begin()->getOpcode() == ARM::tBX_RET) MBBI = MBBI_prev; // Replace the final tPOP with a tPOP_RET. else CanRestoreDirectly = false; } } if (CanRestoreDirectly) { if (!DoIt || MBBI->getOpcode() == ARM::tPOP_RET) return true; MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII.get(ARM::tPOP_RET)) .add(predOps(ARMCC::AL)); // Copy implicit ops and popped registers, if any. for (auto MO: MBBI->operands()) if (MO.isReg() && (MO.isImplicit() || MO.isDef())) MIB.add(MO); MIB.addReg(ARM::PC, RegState::Define); // Erase the old instruction (tBX_RET or tPOP). MBB.erase(MBBI); return true; } // Look for a temporary register to use. // First, compute the liveness information. const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); LivePhysRegs UsedRegs(TRI); UsedRegs.addLiveOuts(MBB); // The semantic of pristines changed recently and now, // the callee-saved registers that are touched in the function // are not part of the pristines set anymore. // Add those callee-saved now. const MCPhysReg *CSRegs = TRI.getCalleeSavedRegs(&MF); for (unsigned i = 0; CSRegs[i]; ++i) UsedRegs.addReg(CSRegs[i]); DebugLoc dl = DebugLoc(); if (MBBI != MBB.end()) { dl = MBBI->getDebugLoc(); auto InstUpToMBBI = MBB.end(); while (InstUpToMBBI != MBBI) // The pre-decrement is on purpose here. // We want to have the liveness right before MBBI. UsedRegs.stepBackward(*--InstUpToMBBI); } // Look for a register that can be directly use in the POP. unsigned PopReg = 0; // And some temporary register, just in case. unsigned TemporaryReg = 0; BitVector PopFriendly = TRI.getAllocatableSet(MF, TRI.getRegClass(ARM::tGPRRegClassID)); assert(PopFriendly.any() && "No allocatable pop-friendly register?!"); // Rebuild the GPRs from the high registers because they are removed // form the GPR reg class for thumb1. BitVector GPRsNoLRSP = TRI.getAllocatableSet(MF, TRI.getRegClass(ARM::hGPRRegClassID)); GPRsNoLRSP |= PopFriendly; GPRsNoLRSP.reset(ARM::LR); GPRsNoLRSP.reset(ARM::SP); GPRsNoLRSP.reset(ARM::PC); findTemporariesForLR(GPRsNoLRSP, PopFriendly, UsedRegs, PopReg, TemporaryReg); // If we couldn't find a pop-friendly register, restore LR before popping the // other callee-saved registers, so we can use one of them as a temporary. bool UseLDRSP = false; if (!PopReg && MBBI != MBB.begin()) { auto PrevMBBI = MBBI; PrevMBBI--; if (PrevMBBI->getOpcode() == ARM::tPOP) { MBBI = PrevMBBI; UsedRegs.stepBackward(*MBBI); findTemporariesForLR(GPRsNoLRSP, PopFriendly, UsedRegs, PopReg, TemporaryReg); UseLDRSP = true; } } if (!DoIt && !PopReg && !TemporaryReg) return false; assert((PopReg || TemporaryReg) && "Cannot get LR"); if (UseLDRSP) { assert(PopReg && "Do not know how to get LR"); // Load the LR via LDR tmp, [SP, #off] BuildMI(MBB, MBBI, dl, TII.get(ARM::tLDRspi)) .addReg(PopReg, RegState::Define) .addReg(ARM::SP) .addImm(MBBI->getNumExplicitOperands() - 2) .add(predOps(ARMCC::AL)); // Move from the temporary register to the LR. BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr)) .addReg(ARM::LR, RegState::Define) .addReg(PopReg, RegState::Kill) .add(predOps(ARMCC::AL)); // Advance past the pop instruction. MBBI++; // Increment the SP. emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, ArgRegsSaveSize + 4); return true; } if (TemporaryReg) { assert(!PopReg && "Unnecessary MOV is about to be inserted"); PopReg = PopFriendly.find_first(); BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr)) .addReg(TemporaryReg, RegState::Define) .addReg(PopReg, RegState::Kill) .add(predOps(ARMCC::AL)); } if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tPOP_RET) { // We couldn't use the direct restoration above, so // perform the opposite conversion: tPOP_RET to tPOP. MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII.get(ARM::tPOP)) .add(predOps(ARMCC::AL)); bool Popped = false; for (auto MO: MBBI->operands()) if (MO.isReg() && (MO.isImplicit() || MO.isDef()) && MO.getReg() != ARM::PC) { MIB.add(MO); if (!MO.isImplicit()) Popped = true; } // Is there anything left to pop? if (!Popped) MBB.erase(MIB.getInstr()); // Erase the old instruction. MBB.erase(MBBI); MBBI = BuildMI(MBB, MBB.end(), dl, TII.get(ARM::tBX_RET)) .add(predOps(ARMCC::AL)); } assert(PopReg && "Do not know how to get LR"); BuildMI(MBB, MBBI, dl, TII.get(ARM::tPOP)) .add(predOps(ARMCC::AL)) .addReg(PopReg, RegState::Define); emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, ArgRegsSaveSize); BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr)) .addReg(ARM::LR, RegState::Define) .addReg(PopReg, RegState::Kill) .add(predOps(ARMCC::AL)); if (TemporaryReg) BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr)) .addReg(PopReg, RegState::Define) .addReg(TemporaryReg, RegState::Kill) .add(predOps(ARMCC::AL)); return true; }