/// insertPrologEpilogCode - Scan the function for modified callee saved /// registers, insert spill code for these callee saved registers, then add /// prolog and epilog code to the function. /// void PEI::insertPrologEpilogCode(MachineFunction &Fn) { const TargetFrameLowering &TFI = *Fn.getSubtarget().getFrameLowering(); // Add prologue to the function... TFI.emitPrologue(Fn); // Add epilogue to restore the callee-save registers in each exiting block for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) { // If last instruction is a return instruction, add an epilogue if (!I->empty() && I->back().isReturn()) TFI.emitEpilogue(Fn, *I); } // Emit additional code that is required to support segmented stacks, if // we've been asked for it. This, when linked with a runtime with support // for segmented stacks (libgcc is one), will result in allocating stack // space in small chunks instead of one large contiguous block. if (Fn.shouldSplitStack()) TFI.adjustForSegmentedStacks(Fn); // Emit additional code that is required to explicitly handle the stack in // HiPE native code (if needed) when loaded in the Erlang/OTP runtime. The // approach is rather similar to that of Segmented Stacks, but it uses a // different conditional check and another BIF for allocating more stack // space. if (Fn.getFunction()->getCallingConv() == CallingConv::HiPE) TFI.adjustForHiPEPrologue(Fn); }
/// insertPrologEpilogCode - Scan the function for modified callee saved /// registers, insert spill code for these callee saved registers, then add /// prolog and epilog code to the function. /// void PEI::insertPrologEpilogCode(MachineFunction &Fn) { const TargetFrameLowering &TFI = *Fn.getTarget().getFrameLowering(); // Add prologue to the function... TFI.emitPrologue(Fn); // Add epilogue to restore the callee-save registers in each exiting block for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) { // If last instruction is a return instruction, add an epilogue if (!I->empty() && I->back().isReturn()) TFI.emitEpilogue(Fn, *I); } // Emit additional code that is required to support segmented stacks, if // we've been asked for it. This, when linked with a runtime with support // for segmented stacks (libgcc is one), will result in allocating stack // space in small chunks instead of one large contiguous block. if (Fn.getTarget().Options.EnableSegmentedStacks) TFI.adjustForSegmentedStacks(Fn); // Emit additional code that is required to support Erlang HiPE native code, // if we've been asked for it. if (Fn.getTarget().Options.EnableHiPEPrologue) TFI.adjustForHiPEPrologue(Fn); }
bool NVPTXPrologEpilogPass::runOnMachineFunction(MachineFunction &MF) { const TargetMachine &TM = MF.getTarget(); const TargetFrameLowering &TFI = *TM.getFrameLowering(); const TargetRegisterInfo &TRI = *TM.getRegisterInfo(); bool Modified = false; calculateFrameObjectOffsets(MF); for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); BB != E; ++BB) { for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) { MachineInstr *MI = I; for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { if (!MI->getOperand(i).isFI()) continue; TRI.eliminateFrameIndex(MI, 0, i, nullptr); Modified = true; } } } // Add function prolog/epilog TFI.emitPrologue(MF); for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) { // If last instruction is a return instruction, add an epilogue if (!I->empty() && I->back().isReturn()) TFI.emitEpilogue(MF, *I); } return Modified; }
/// canFallThroughTo - Returns true either if ToBB is the next block after BB or /// that all the intervening blocks are empty (given BB can fall through to its /// next block). static bool canFallThroughTo(MachineBasicBlock *BB, MachineBasicBlock *ToBB) { MachineFunction::iterator I = BB; MachineFunction::iterator TI = ToBB; MachineFunction::iterator E = BB->getParent()->end(); while (++I != TI) if (I == E || !I->empty()) return false; return true; }
/// insertPrologEpilogCode - Scan the function for modified callee saved /// registers, insert spill code for these callee saved registers, then add /// prolog and epilog code to the function. /// void PEI::insertPrologEpilogCode(MachineFunction &Fn) { const TargetFrameLowering &TFI = *Fn.getTarget().getFrameLowering(); // Add prologue to the function... TFI.emitPrologue(Fn); // Add epilogue to restore the callee-save registers in each exiting block for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) { // If last instruction is a return instruction, add an epilogue if (!I->empty() && I->back().getDesc().isReturn()) TFI.emitEpilogue(Fn, *I); } }
bool StrongPHIElimination::runOnMachineFunction(MachineFunction &Fn) { LiveIntervals& LI = getAnalysis<LiveIntervals>(); // Compute DFS numbers of each block computeDFS(Fn); // Determine which phi node operands need copies for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) if (!I->empty() && I->begin()->isPHI()) processBlock(I); // Break interferences where two different phis want to coalesce // in the same register. std::set<unsigned> seen; typedef std::map<unsigned, std::map<unsigned, MachineBasicBlock*> > RenameSetType; for (RenameSetType::iterator I = RenameSets.begin(), E = RenameSets.end(); I != E; ++I) { for (std::map<unsigned, MachineBasicBlock*>::iterator OI = I->second.begin(), OE = I->second.end(); OI != OE; ) { if (!seen.count(OI->first)) { seen.insert(OI->first); ++OI; } else { Waiting[OI->second].insert(std::make_pair(OI->first, I->first)); unsigned reg = OI->first; ++OI; I->second.erase(reg); DEBUG(dbgs() << "Removing Renaming: " << reg << " -> " << I->first << "\n"); } } } // Insert copies // FIXME: This process should probably preserve LiveIntervals SmallPtrSet<MachineBasicBlock*, 16> visited; MachineDominatorTree& MDT = getAnalysis<MachineDominatorTree>(); InsertCopies(MDT.getRootNode(), visited); // Perform renaming for (RenameSetType::iterator I = RenameSets.begin(), E = RenameSets.end(); I != E; ++I) while (I->second.size()) { std::map<unsigned, MachineBasicBlock*>::iterator SI = I->second.begin(); DEBUG(dbgs() << "Renaming: " << SI->first << " -> " << I->first << "\n"); if (SI->first != I->first) { if (mergeLiveIntervals(I->first, SI->first)) { Fn.getRegInfo().replaceRegWith(SI->first, I->first); if (RenameSets.count(SI->first)) { I->second.insert(RenameSets[SI->first].begin(), RenameSets[SI->first].end()); RenameSets.erase(SI->first); } } else { // Insert a last-minute copy if a conflict was detected. const TargetInstrInfo *TII = Fn.getTarget().getInstrInfo(); const TargetRegisterClass *RC = Fn.getRegInfo().getRegClass(I->first); TII->copyRegToReg(*SI->second, SI->second->getFirstTerminator(), I->first, SI->first, RC, RC, DebugLoc()); LI.renumber(); LiveInterval& Int = LI.getOrCreateInterval(I->first); SlotIndex instrIdx = LI.getInstructionIndex(--SI->second->getFirstTerminator()); if (Int.liveAt(instrIdx.getDefIndex())) Int.removeRange(instrIdx.getDefIndex(), LI.getMBBEndIdx(SI->second).getNextSlot(), true); LiveRange R = LI.addLiveRangeToEndOfBlock(I->first, --SI->second->getFirstTerminator()); R.valno->setCopy(--SI->second->getFirstTerminator()); R.valno->def = instrIdx.getDefIndex(); DEBUG(dbgs() << "Renaming failed: " << SI->first << " -> " << I->first << "\n"); } } LiveInterval& Int = LI.getOrCreateInterval(I->first); const LiveRange* LR = Int.getLiveRangeContaining(LI.getMBBEndIdx(SI->second)); LR->valno->setHasPHIKill(true); I->second.erase(SI->first); } // Remove PHIs std::vector<MachineInstr*> phis; for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) { for (MachineBasicBlock::iterator BI = I->begin(), BE = I->end(); BI != BE; ++BI) if (BI->isPHI()) phis.push_back(BI); } for (std::vector<MachineInstr*>::iterator I = phis.begin(), E = phis.end(); I != E; ) { MachineInstr* PInstr = *(I++); // If this is a dead PHI node, then remove it from LiveIntervals. unsigned DestReg = PInstr->getOperand(0).getReg(); LiveInterval& PI = LI.getInterval(DestReg); if (PInstr->registerDefIsDead(DestReg)) { if (PI.containsOneValue()) { LI.removeInterval(DestReg); } else { SlotIndex idx = LI.getInstructionIndex(PInstr).getDefIndex(); PI.removeRange(*PI.getLiveRangeContaining(idx), true); } } else { // Trim live intervals of input registers. They are no longer live into // this block if they died after the PHI. If they lived after it, don't // trim them because they might have other legitimate uses. for (unsigned i = 1; i < PInstr->getNumOperands(); i += 2) { unsigned reg = PInstr->getOperand(i).getReg(); MachineBasicBlock* MBB = PInstr->getOperand(i+1).getMBB(); LiveInterval& InputI = LI.getInterval(reg); if (MBB != PInstr->getParent() && InputI.liveAt(LI.getMBBStartIdx(PInstr->getParent())) && InputI.expiredAt(LI.getInstructionIndex(PInstr).getNextIndex())) InputI.removeRange(LI.getMBBStartIdx(PInstr->getParent()), LI.getInstructionIndex(PInstr), true); } // If the PHI is not dead, then the valno defined by the PHI // now has an unknown def. SlotIndex idx = LI.getInstructionIndex(PInstr).getDefIndex(); const LiveRange* PLR = PI.getLiveRangeContaining(idx); PLR->valno->setIsPHIDef(true); LiveRange R (LI.getMBBStartIdx(PInstr->getParent()), PLR->start, PLR->valno); PI.addRange(R); } LI.RemoveMachineInstrFromMaps(PInstr); PInstr->eraseFromParent(); } LI.renumber(); return true; }