// OptimizePICCall methods. bool OptimizePICCall::runOnMachineFunction(MachineFunction &F) { if (static_cast<const MipsSubtarget &>(F.getSubtarget()).inMips16Mode()) return false; // Do a pre-order traversal of the dominator tree. MachineDominatorTree *MDT = &getAnalysis<MachineDominatorTree>(); bool Changed = false; SmallVector<MBBInfo, 8> WorkList(1, MBBInfo(MDT->getRootNode())); while (!WorkList.empty()) { MBBInfo &MBBI = WorkList.back(); // If this MBB has already been visited, destroy the scope for the MBB and // pop it from the work list. if (MBBI.isVisited()) { MBBI.postVisit(); WorkList.pop_back(); continue; } // Visit the MBB and add its children to the work list. MBBI.preVisit(ScopedHT); Changed |= visitNode(MBBI); const MachineDomTreeNode *Node = MBBI.getNode(); const std::vector<MachineDomTreeNode *> &Children = Node->getChildren(); WorkList.append(Children.begin(), Children.end()); } return Changed; }
/// Implements shrink-wrapping of the stack frame. By default, stack frame /// is created in the function entry block, and is cleaned up in every block /// that returns. This function finds alternate blocks: one for the frame /// setup (prolog) and one for the cleanup (epilog). void HexagonFrameLowering::findShrunkPrologEpilog(MachineFunction &MF, MachineBasicBlock *&PrologB, MachineBasicBlock *&EpilogB) const { static unsigned ShrinkCounter = 0; if (ShrinkLimit.getPosition()) { if (ShrinkCounter >= ShrinkLimit) return; ShrinkCounter++; } auto &HST = static_cast<const HexagonSubtarget&>(MF.getSubtarget()); auto &HRI = *HST.getRegisterInfo(); MachineDominatorTree MDT; MDT.runOnMachineFunction(MF); MachinePostDominatorTree MPT; MPT.runOnMachineFunction(MF); typedef DenseMap<unsigned,unsigned> UnsignedMap; UnsignedMap RPO; typedef ReversePostOrderTraversal<const MachineFunction*> RPOTType; RPOTType RPOT(&MF); unsigned RPON = 0; for (RPOTType::rpo_iterator I = RPOT.begin(), E = RPOT.end(); I != E; ++I) RPO[(*I)->getNumber()] = RPON++; // Don't process functions that have loops, at least for now. Placement // of prolog and epilog must take loop structure into account. For simpli- // city don't do it right now. for (auto &I : MF) { unsigned BN = RPO[I.getNumber()]; for (auto SI = I.succ_begin(), SE = I.succ_end(); SI != SE; ++SI) { // If found a back-edge, return. if (RPO[(*SI)->getNumber()] <= BN) return; } } // Collect the set of blocks that need a stack frame to execute. Scan // each block for uses/defs of callee-saved registers, calls, etc. SmallVector<MachineBasicBlock*,16> SFBlocks; BitVector CSR(Hexagon::NUM_TARGET_REGS); for (const MCPhysReg *P = HRI.getCalleeSavedRegs(&MF); *P; ++P) CSR[*P] = true; for (auto &I : MF) if (needsStackFrame(I, CSR)) SFBlocks.push_back(&I); DEBUG({ dbgs() << "Blocks needing SF: {"; for (auto &B : SFBlocks) dbgs() << " BB#" << B->getNumber(); dbgs() << " }\n"; });
void WebAssemblyExceptionInfo::discoverAndMapException( WebAssemblyException *WE, const MachineDominatorTree &MDT, const MachineDominanceFrontier &MDF) { unsigned NumBlocks = 0; unsigned NumSubExceptions = 0; // Map blocks that belong to a catchpad / cleanuppad MachineBasicBlock *EHPad = WE->getEHPad(); // We group catch & catch-all terminate pads together within an exception if (WebAssembly::isCatchTerminatePad(*EHPad)) { assert(EHPad->succ_size() == 1 && "Catch terminate pad has more than one successors"); changeExceptionFor(EHPad, WE); changeExceptionFor(*(EHPad->succ_begin()), WE); return; } SmallVector<MachineBasicBlock *, 8> WL; WL.push_back(EHPad); while (!WL.empty()) { MachineBasicBlock *MBB = WL.pop_back_val(); // Find its outermost discovered exception. If this is a discovered block, // check if it is already discovered to be a subexception of this exception. WebAssemblyException *SubE = getOutermostException(MBB); if (SubE) { if (SubE != WE) { // Discover a subexception of this exception. SubE->setParentException(WE); ++NumSubExceptions; NumBlocks += SubE->getBlocksVector().capacity(); // All blocks that belong to this subexception have been already // discovered. Skip all of them. Add the subexception's landing pad's // dominance frontier to the worklist. for (auto &Frontier : MDF.find(SubE->getEHPad())->second) if (MDT.dominates(EHPad, Frontier)) WL.push_back(Frontier); } continue; } // This is an undiscovered block. Map it to the current exception. changeExceptionFor(MBB, WE); ++NumBlocks; // Add successors dominated by the current BB to the worklist. for (auto *Succ : MBB->successors()) if (MDT.dominates(EHPad, Succ)) WL.push_back(Succ); } WE->getSubExceptions().reserve(NumSubExceptions); WE->reserveBlocks(NumBlocks); }
void MachineDominatorTree::verifyDomTree() const { MachineFunction &F = *getRoot()->getParent(); MachineDominatorTree OtherDT; OtherDT.DT->recalculate(F); if (compare(OtherDT)) { errs() << "MachineDominatorTree is not up to date!\nComputed:\n"; print(errs(), nullptr); errs() << "\nActual:\n"; OtherDT.print(errs(), nullptr); abort(); } }
void UserValue::extendDef(SlotIndex Idx, unsigned LocNo, LiveRange *LR, const VNInfo *VNI, SmallVectorImpl<SlotIndex> *Kills, LiveIntervals &LIS, MachineDominatorTree &MDT, UserValueScopes &UVS) { SmallVector<SlotIndex, 16> Todo; Todo.push_back(Idx); do { SlotIndex Start = Todo.pop_back_val(); MachineBasicBlock *MBB = LIS.getMBBFromIndex(Start); SlotIndex Stop = LIS.getMBBEndIdx(MBB); LocMap::iterator I = locInts.find(Start); // Limit to VNI's live range. bool ToEnd = true; if (LR && VNI) { LiveInterval::Segment *Segment = LR->getSegmentContaining(Start); if (!Segment || Segment->valno != VNI) { if (Kills) Kills->push_back(Start); continue; } if (Segment->end < Stop) Stop = Segment->end, ToEnd = false; } // There could already be a short def at Start. if (I.valid() && I.start() <= Start) { // Stop when meeting a different location or an already extended interval. Start = Start.getNextSlot(); if (I.value() != LocNo || I.stop() != Start) continue; // This is a one-slot placeholder. Just skip it. ++I; } // Limited by the next def. if (I.valid() && I.start() < Stop) Stop = I.start(), ToEnd = false; // Limited by VNI's live range. else if (!ToEnd && Kills) Kills->push_back(Stop); if (Start >= Stop) continue; I.insert(Start, Stop, LocNo); // If we extended to the MBB end, propagate down the dominator tree. if (!ToEnd) continue; const std::vector<MachineDomTreeNode*> &Children = MDT.getNode(MBB)->getChildren(); for (unsigned i = 0, e = Children.size(); i != e; ++i) { MachineBasicBlock *MBB = Children[i]->getBlock(); if (UVS.dominates(MBB)) Todo.push_back(LIS.getMBBStartIdx(MBB)); } } while (!Todo.empty()); }
bool SystemZLDCleanup::runOnMachineFunction(MachineFunction &F) { if (skipFunction(*F.getFunction())) return false; TII = static_cast<const SystemZInstrInfo *>(F.getSubtarget().getInstrInfo()); MF = &F; SystemZMachineFunctionInfo* MFI = F.getInfo<SystemZMachineFunctionInfo>(); if (MFI->getNumLocalDynamicTLSAccesses() < 2) { // No point folding accesses if there isn't at least two. return false; } MachineDominatorTree *DT = &getAnalysis<MachineDominatorTree>(); return VisitNode(DT->getRootNode(), 0); }
/// Test whether OneUse, a use of Reg, dominates all of Reg's other uses. static bool OneUseDominatesOtherUses(unsigned Reg, const MachineOperand &OneUse, const MachineBasicBlock &MBB, const MachineRegisterInfo &MRI, const MachineDominatorTree &MDT, LiveIntervals &LIS, WebAssemblyFunctionInfo &MFI) { const LiveInterval &LI = LIS.getInterval(Reg); const MachineInstr *OneUseInst = OneUse.getParent(); VNInfo *OneUseVNI = LI.getVNInfoBefore(LIS.getInstructionIndex(*OneUseInst)); for (const MachineOperand &Use : MRI.use_nodbg_operands(Reg)) { if (&Use == &OneUse) continue; const MachineInstr *UseInst = Use.getParent(); VNInfo *UseVNI = LI.getVNInfoBefore(LIS.getInstructionIndex(*UseInst)); if (UseVNI != OneUseVNI) continue; const MachineInstr *OneUseInst = OneUse.getParent(); if (UseInst == OneUseInst) { // Another use in the same instruction. We need to ensure that the one // selected use happens "before" it. if (&OneUse > &Use) return false; } else { // Test that the use is dominated by the one selected use. while (!MDT.dominates(OneUseInst, UseInst)) { // Actually, dominating is over-conservative. Test that the use would // happen after the one selected use in the stack evaluation order. // // This is needed as a consequence of using implicit get_locals for // uses and implicit set_locals for defs. if (UseInst->getDesc().getNumDefs() == 0) return false; const MachineOperand &MO = UseInst->getOperand(0); if (!MO.isReg()) return false; unsigned DefReg = MO.getReg(); if (!TargetRegisterInfo::isVirtualRegister(DefReg) || !MFI.isVRegStackified(DefReg)) return false; assert(MRI.hasOneUse(DefReg)); const MachineOperand &NewUse = *MRI.use_begin(DefReg); const MachineInstr *NewUseInst = NewUse.getParent(); if (NewUseInst == OneUseInst) { if (&OneUse > &NewUse) return false; break; } UseInst = NewUseInst; } } } return true; }
// Checks if there is potential path From instruction To instruction. // If CutOff is specified and it sits in between of that path we ignore // a higher portion of the path and report it is not reachable. static bool isReachable(const MachineInstr *From, const MachineInstr *To, const MachineBasicBlock *CutOff, MachineDominatorTree &MDT) { // If either From block dominates To block or instructions are in the same // block and From is higher. if (MDT.dominates(From, To)) return true; const MachineBasicBlock *MBBFrom = From->getParent(); const MachineBasicBlock *MBBTo = To->getParent(); if (MBBFrom == MBBTo) return false; // Instructions are in different blocks, do predecessor search. // We should almost never get here since we do not usually produce M0 stores // other than -1. return searchPredecessors(MBBTo, CutOff, [MBBFrom] (const MachineBasicBlock *MBB) { return MBB == MBBFrom; }); }
bool UnreachableMachineBlockElim::runOnMachineFunction(MachineFunction &F) { df_iterator_default_set<MachineBasicBlock*> Reachable; bool ModifiedPHI = false; MMI = getAnalysisIfAvailable<MachineModuleInfo>(); MachineDominatorTree *MDT = getAnalysisIfAvailable<MachineDominatorTree>(); MachineLoopInfo *MLI = getAnalysisIfAvailable<MachineLoopInfo>(); // Mark all reachable blocks. for (MachineBasicBlock *BB : depth_first_ext(&F, Reachable)) (void)BB/* Mark all reachable blocks */; // Loop over all dead blocks, remembering them and deleting all instructions // in them. std::vector<MachineBasicBlock*> DeadBlocks; for (MachineFunction::iterator I = F.begin(), E = F.end(); I != E; ++I) { MachineBasicBlock *BB = &*I; // Test for deadness. if (!Reachable.count(BB)) { DeadBlocks.push_back(BB); // Update dominator and loop info. if (MLI) MLI->removeBlock(BB); if (MDT && MDT->getNode(BB)) MDT->eraseNode(BB); while (BB->succ_begin() != BB->succ_end()) { MachineBasicBlock* succ = *BB->succ_begin(); MachineBasicBlock::iterator start = succ->begin(); while (start != succ->end() && start->isPHI()) { for (unsigned i = start->getNumOperands() - 1; i >= 2; i-=2) if (start->getOperand(i).isMBB() && start->getOperand(i).getMBB() == BB) { start->RemoveOperand(i); start->RemoveOperand(i-1); } start++; } BB->removeSuccessor(BB->succ_begin()); } } } // Actually remove the blocks now. for (unsigned i = 0, e = DeadBlocks.size(); i != e; ++i) DeadBlocks[i]->eraseFromParent(); // Cleanup PHI nodes. for (MachineFunction::iterator I = F.begin(), E = F.end(); I != E; ++I) { MachineBasicBlock *BB = &*I; // Prune unneeded PHI entries. SmallPtrSet<MachineBasicBlock*, 8> preds(BB->pred_begin(), BB->pred_end()); MachineBasicBlock::iterator phi = BB->begin(); while (phi != BB->end() && phi->isPHI()) { for (unsigned i = phi->getNumOperands() - 1; i >= 2; i-=2) if (!preds.count(phi->getOperand(i).getMBB())) { phi->RemoveOperand(i); phi->RemoveOperand(i-1); ModifiedPHI = true; } if (phi->getNumOperands() == 3) { const MachineOperand &Input = phi->getOperand(1); const MachineOperand &Output = phi->getOperand(0); unsigned InputReg = Input.getReg(); unsigned OutputReg = Output.getReg(); assert(Output.getSubReg() == 0 && "Cannot have output subregister"); ModifiedPHI = true; if (InputReg != OutputReg) { MachineRegisterInfo &MRI = F.getRegInfo(); unsigned InputSub = Input.getSubReg(); if (InputSub == 0 && MRI.constrainRegClass(InputReg, MRI.getRegClass(OutputReg))) { MRI.replaceRegWith(OutputReg, InputReg); } else { // The input register to the PHI has a subregister or it can't be // constrained to the proper register class: // insert a COPY instead of simply replacing the output // with the input. const TargetInstrInfo *TII = F.getSubtarget().getInstrInfo(); BuildMI(*BB, BB->getFirstNonPHI(), phi->getDebugLoc(), TII->get(TargetOpcode::COPY), OutputReg) .addReg(InputReg, getRegState(Input), InputSub); } phi++->eraseFromParent(); } continue; } ++phi; } } F.RenumberBlocks(); return (!DeadBlocks.empty() || ModifiedPHI); }
/// Insert a BLOCK marker for branches to MBB (if needed). static void PlaceBlockMarker(MachineBasicBlock &MBB, MachineFunction &MF, SmallVectorImpl<MachineBasicBlock *> &ScopeTops, const WebAssemblyInstrInfo &TII, const MachineLoopInfo &MLI, MachineDominatorTree &MDT, WebAssemblyFunctionInfo &MFI) { // First compute the nearest common dominator of all forward non-fallthrough // predecessors so that we minimize the time that the BLOCK is on the stack, // which reduces overall stack height. MachineBasicBlock *Header = nullptr; bool IsBranchedTo = false; int MBBNumber = MBB.getNumber(); for (MachineBasicBlock *Pred : MBB.predecessors()) if (Pred->getNumber() < MBBNumber) { Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred; if (ExplicitlyBranchesTo(Pred, &MBB)) IsBranchedTo = true; } if (!Header) return; if (!IsBranchedTo) return; assert(&MBB != &MF.front() && "Header blocks shouldn't have predecessors"); MachineBasicBlock *LayoutPred = &*prev(MachineFunction::iterator(&MBB)); // If the nearest common dominator is inside a more deeply nested context, // walk out to the nearest scope which isn't more deeply nested. for (MachineFunction::iterator I(LayoutPred), E(Header); I != E; --I) { if (MachineBasicBlock *ScopeTop = ScopeTops[I->getNumber()]) { if (ScopeTop->getNumber() > Header->getNumber()) { // Skip over an intervening scope. I = next(MachineFunction::iterator(ScopeTop)); } else { // We found a scope level at an appropriate depth. Header = ScopeTop; break; } } } // If there's a loop which ends just before MBB which contains Header, we can // reuse its label instead of inserting a new BLOCK. for (MachineLoop *Loop = MLI.getLoopFor(LayoutPred); Loop && Loop->contains(LayoutPred); Loop = Loop->getParentLoop()) if (Loop && LoopBottom(Loop) == LayoutPred && Loop->contains(Header)) return; // Decide where in Header to put the BLOCK. MachineBasicBlock::iterator InsertPos; MachineLoop *HeaderLoop = MLI.getLoopFor(Header); if (HeaderLoop && MBB.getNumber() > LoopBottom(HeaderLoop)->getNumber()) { // Header is the header of a loop that does not lexically contain MBB, so // the BLOCK needs to be above the LOOP, after any END constructs. InsertPos = Header->begin(); while (InsertPos->getOpcode() != WebAssembly::LOOP) ++InsertPos; } else { // Otherwise, insert the BLOCK as late in Header as we can, but before the // beginning of the local expression tree and any nested BLOCKs. InsertPos = Header->getFirstTerminator(); while (InsertPos != Header->begin() && IsChild(prev(InsertPos), MFI) && prev(InsertPos)->getOpcode() != WebAssembly::LOOP && prev(InsertPos)->getOpcode() != WebAssembly::END_BLOCK && prev(InsertPos)->getOpcode() != WebAssembly::END_LOOP) --InsertPos; } // Add the BLOCK. BuildMI(*Header, InsertPos, DebugLoc(), TII.get(WebAssembly::BLOCK)); // Mark the end of the block. InsertPos = MBB.begin(); while (InsertPos != MBB.end() && InsertPos->getOpcode() == WebAssembly::END_LOOP) ++InsertPos; BuildMI(MBB, InsertPos, DebugLoc(), TII.get(WebAssembly::END_BLOCK)); // Track the farthest-spanning scope that ends at this point. int Number = MBB.getNumber(); if (!ScopeTops[Number] || ScopeTops[Number]->getNumber() > Header->getNumber()) ScopeTops[Number] = Header; }
/// Sort the blocks, taking special care to make sure that loops are not /// interrupted by blocks not dominated by their header. /// TODO: There are many opportunities for improving the heuristics here. /// Explore them. static void SortBlocks(MachineFunction &MF, const MachineLoopInfo &MLI, const MachineDominatorTree &MDT) { // Prepare for a topological sort: Record the number of predecessors each // block has, ignoring loop backedges. MF.RenumberBlocks(); SmallVector<unsigned, 16> NumPredsLeft(MF.getNumBlockIDs(), 0); for (MachineBasicBlock &MBB : MF) { unsigned N = MBB.pred_size(); if (MachineLoop *L = MLI.getLoopFor(&MBB)) if (L->getHeader() == &MBB) for (const MachineBasicBlock *Pred : MBB.predecessors()) if (L->contains(Pred)) --N; NumPredsLeft[MBB.getNumber()] = N; } // Topological sort the CFG, with additional constraints: // - Between a loop header and the last block in the loop, there can be // no blocks not dominated by the loop header. // - It's desirable to preserve the original block order when possible. // We use two ready lists; Preferred and Ready. Preferred has recently // processed sucessors, to help preserve block sequences from the original // order. Ready has the remaining ready blocks. PriorityQueue<MachineBasicBlock *, std::vector<MachineBasicBlock *>, CompareBlockNumbers> Preferred; PriorityQueue<MachineBasicBlock *, std::vector<MachineBasicBlock *>, CompareBlockNumbersBackwards> Ready; SmallVector<Entry, 4> Loops; for (MachineBasicBlock *MBB = &MF.front();;) { const MachineLoop *L = MLI.getLoopFor(MBB); if (L) { // If MBB is a loop header, add it to the active loop list. We can't put // any blocks that it doesn't dominate until we see the end of the loop. if (L->getHeader() == MBB) Loops.push_back(Entry(L)); // For each active loop the block is in, decrement the count. If MBB is // the last block in an active loop, take it off the list and pick up any // blocks deferred because the header didn't dominate them. for (Entry &E : Loops) if (E.Loop->contains(MBB) && --E.NumBlocksLeft == 0) for (auto DeferredBlock : E.Deferred) Ready.push(DeferredBlock); while (!Loops.empty() && Loops.back().NumBlocksLeft == 0) Loops.pop_back(); } // The main topological sort logic. for (MachineBasicBlock *Succ : MBB->successors()) { // Ignore backedges. if (MachineLoop *SuccL = MLI.getLoopFor(Succ)) if (SuccL->getHeader() == Succ && SuccL->contains(MBB)) continue; // Decrement the predecessor count. If it's now zero, it's ready. if (--NumPredsLeft[Succ->getNumber()] == 0) Preferred.push(Succ); } // Determine the block to follow MBB. First try to find a preferred block, // to preserve the original block order when possible. MachineBasicBlock *Next = nullptr; while (!Preferred.empty()) { Next = Preferred.top(); Preferred.pop(); // If X isn't dominated by the top active loop header, defer it until that // loop is done. if (!Loops.empty() && !MDT.dominates(Loops.back().Loop->getHeader(), Next)) { Loops.back().Deferred.push_back(Next); Next = nullptr; continue; } // If Next was originally ordered before MBB, and it isn't because it was // loop-rotated above the header, it's not preferred. if (Next->getNumber() < MBB->getNumber() && (!L || !L->contains(Next) || L->getHeader()->getNumber() < Next->getNumber())) { Ready.push(Next); Next = nullptr; continue; } break; } // If we didn't find a suitable block in the Preferred list, check the // general Ready list. if (!Next) { // If there are no more blocks to process, we're done. if (Ready.empty()) { MaybeUpdateTerminator(MBB); break; } for (;;) { Next = Ready.top(); Ready.pop(); // If Next isn't dominated by the top active loop header, defer it until // that loop is done. if (!Loops.empty() && !MDT.dominates(Loops.back().Loop->getHeader(), Next)) { Loops.back().Deferred.push_back(Next); continue; } break; } } // Move the next block into place and iterate. Next->moveAfter(MBB); MaybeUpdateTerminator(MBB); MBB = Next; } assert(Loops.empty() && "Active loop list not finished"); MF.RenumberBlocks(); #ifndef NDEBUG SmallSetVector<MachineLoop *, 8> OnStack; // Insert a sentinel representing the degenerate loop that starts at the // function entry block and includes the entire function as a "loop" that // executes once. OnStack.insert(nullptr); for (auto &MBB : MF) { assert(MBB.getNumber() >= 0 && "Renumbered blocks should be non-negative."); MachineLoop *Loop = MLI.getLoopFor(&MBB); if (Loop && &MBB == Loop->getHeader()) { // Loop header. The loop predecessor should be sorted above, and the other // predecessors should be backedges below. for (auto Pred : MBB.predecessors()) assert( (Pred->getNumber() < MBB.getNumber() || Loop->contains(Pred)) && "Loop header predecessors must be loop predecessors or backedges"); assert(OnStack.insert(Loop) && "Loops should be declared at most once."); } else { // Not a loop header. All predecessors should be sorted above. for (auto Pred : MBB.predecessors()) assert(Pred->getNumber() < MBB.getNumber() && "Non-loop-header predecessors should be topologically sorted"); assert(OnStack.count(MLI.getLoopFor(&MBB)) && "Blocks must be nested in their loops"); } while (OnStack.size() > 1 && &MBB == LoopBottom(OnStack.back())) OnStack.pop_back(); } assert(OnStack.pop_back_val() == nullptr && "The function entry block shouldn't actually be a loop header"); assert(OnStack.empty() && "Control flow stack pushes and pops should be balanced."); #endif }
// Hoist and merge identical SGPR initializations into a common predecessor. // This is intended to combine M0 initializations, but can work with any // SGPR. A VGPR cannot be processed since we cannot guarantee vector // executioon. static bool hoistAndMergeSGPRInits(unsigned Reg, const MachineRegisterInfo &MRI, MachineDominatorTree &MDT) { // List of inits by immediate value. typedef std::map<unsigned, std::list<MachineInstr*>> InitListMap; InitListMap Inits; // List of clobbering instructions. SmallVector<MachineInstr*, 8> Clobbers; bool Changed = false; for (auto &MI : MRI.def_instructions(Reg)) { MachineOperand *Imm = nullptr; for (auto &MO: MI.operands()) { if ((MO.isReg() && ((MO.isDef() && MO.getReg() != Reg) || !MO.isDef())) || (!MO.isImm() && !MO.isReg()) || (MO.isImm() && Imm)) { Imm = nullptr; break; } else if (MO.isImm()) Imm = &MO; } if (Imm) Inits[Imm->getImm()].push_front(&MI); else Clobbers.push_back(&MI); } for (auto &Init : Inits) { auto &Defs = Init.second; for (auto I1 = Defs.begin(), E = Defs.end(); I1 != E; ) { MachineInstr *MI1 = *I1; for (auto I2 = std::next(I1); I2 != E; ) { MachineInstr *MI2 = *I2; // Check any possible interference auto intereferes = [&](MachineBasicBlock::iterator From, MachineBasicBlock::iterator To) -> bool { assert(MDT.dominates(&*To, &*From)); auto interferes = [&MDT, From, To](MachineInstr* &Clobber) -> bool { const MachineBasicBlock *MBBFrom = From->getParent(); const MachineBasicBlock *MBBTo = To->getParent(); bool MayClobberFrom = isReachable(Clobber, &*From, MBBTo, MDT); bool MayClobberTo = isReachable(Clobber, &*To, MBBTo, MDT); if (!MayClobberFrom && !MayClobberTo) return false; if ((MayClobberFrom && !MayClobberTo) || (!MayClobberFrom && MayClobberTo)) return true; // Both can clobber, this is not an interference only if both are // dominated by Clobber and belong to the same block or if Clobber // properly dominates To, given that To >> From, so it dominates // both and located in a common dominator. return !((MBBFrom == MBBTo && MDT.dominates(Clobber, &*From) && MDT.dominates(Clobber, &*To)) || MDT.properlyDominates(Clobber->getParent(), MBBTo)); }; return (any_of(Clobbers, interferes)) || (any_of(Inits, [&](InitListMap::value_type &C) { return C.first != Init.first && any_of(C.second, interferes); })); }; if (MDT.dominates(MI1, MI2)) { if (!intereferes(MI2, MI1)) { DEBUG(dbgs() << "Erasing from BB#" << MI2->getParent()->getNumber() << " " << *MI2); MI2->eraseFromParent(); Defs.erase(I2++); Changed = true; continue; } } else if (MDT.dominates(MI2, MI1)) { if (!intereferes(MI1, MI2)) { DEBUG(dbgs() << "Erasing from BB#" << MI1->getParent()->getNumber() << " " << *MI1); MI1->eraseFromParent(); Defs.erase(I1++); Changed = true; break; } } else { auto *MBB = MDT.findNearestCommonDominator(MI1->getParent(), MI2->getParent()); if (!MBB) { ++I2; continue; } MachineBasicBlock::iterator I = MBB->getFirstNonPHI(); if (!intereferes(MI1, I) && !intereferes(MI2, I)) { DEBUG(dbgs() << "Erasing from BB#" << MI1->getParent()->getNumber() << " " << *MI1 << "and moving from BB#" << MI2->getParent()->getNumber() << " to BB#" << I->getParent()->getNumber() << " " << *MI2); I->getParent()->splice(I, MI2->getParent(), MI2); MI1->eraseFromParent(); Defs.erase(I1++); Changed = true; break; } } ++I2; } ++I1; } } if (Changed) MRI.clearKillFlags(Reg); return Changed; }
bool UnreachableMachineBlockElim::runOnMachineFunction(MachineFunction &F) { SmallPtrSet<MachineBasicBlock*, 8> Reachable; MMI = getAnalysisIfAvailable<MachineModuleInfo>(); MachineDominatorTree *MDT = getAnalysisIfAvailable<MachineDominatorTree>(); MachineLoopInfo *MLI = getAnalysisIfAvailable<MachineLoopInfo>(); // Mark all reachable blocks. for (df_ext_iterator<MachineFunction*, SmallPtrSet<MachineBasicBlock*, 8> > I = df_ext_begin(&F, Reachable), E = df_ext_end(&F, Reachable); I != E; ++I) /* Mark all reachable blocks */; // Loop over all dead blocks, remembering them and deleting all instructions // in them. std::vector<MachineBasicBlock*> DeadBlocks; for (MachineFunction::iterator I = F.begin(), E = F.end(); I != E; ++I) { MachineBasicBlock *BB = I; // Test for deadness. if (!Reachable.count(BB)) { DeadBlocks.push_back(BB); // Update dominator and loop info. if (MLI) MLI->removeBlock(BB); if (MDT && MDT->getNode(BB)) MDT->eraseNode(BB); while (BB->succ_begin() != BB->succ_end()) { MachineBasicBlock* succ = *BB->succ_begin(); MachineBasicBlock::iterator start = succ->begin(); while (start != succ->end() && start->isPHI()) { for (unsigned i = start->getNumOperands() - 1; i >= 2; i-=2) if (start->getOperand(i).isMBB() && start->getOperand(i).getMBB() == BB) { start->RemoveOperand(i); start->RemoveOperand(i-1); } start++; } BB->removeSuccessor(BB->succ_begin()); } } } // Actually remove the blocks now. for (unsigned i = 0, e = DeadBlocks.size(); i != e; ++i) DeadBlocks[i]->eraseFromParent(); // Cleanup PHI nodes. for (MachineFunction::iterator I = F.begin(), E = F.end(); I != E; ++I) { MachineBasicBlock *BB = I; // Prune unneeded PHI entries. SmallPtrSet<MachineBasicBlock*, 8> preds(BB->pred_begin(), BB->pred_end()); MachineBasicBlock::iterator phi = BB->begin(); while (phi != BB->end() && phi->isPHI()) { for (unsigned i = phi->getNumOperands() - 1; i >= 2; i-=2) if (!preds.count(phi->getOperand(i).getMBB())) { phi->RemoveOperand(i); phi->RemoveOperand(i-1); } if (phi->getNumOperands() == 3) { unsigned Input = phi->getOperand(1).getReg(); unsigned Output = phi->getOperand(0).getReg(); MachineInstr* temp = phi; ++phi; temp->eraseFromParent(); if (Input != Output) F.getRegInfo().replaceRegWith(Output, Input); continue; } ++phi; } } F.RenumberBlocks(); return DeadBlocks.size(); }
// Replace uses of FromReg with ToReg if they are dominated by MI. static bool ReplaceDominatedUses(MachineBasicBlock &MBB, MachineInstr &MI, unsigned FromReg, unsigned ToReg, const MachineRegisterInfo &MRI, MachineDominatorTree &MDT, LiveIntervals &LIS) { bool Changed = false; LiveInterval *FromLI = &LIS.getInterval(FromReg); LiveInterval *ToLI = &LIS.getInterval(ToReg); SlotIndex FromIdx = LIS.getInstructionIndex(MI).getRegSlot(); VNInfo *FromVNI = FromLI->getVNInfoAt(FromIdx); SmallVector<SlotIndex, 4> Indices; for (auto I = MRI.use_nodbg_begin(FromReg), E = MRI.use_nodbg_end(); I != E;) { MachineOperand &O = *I++; MachineInstr *Where = O.getParent(); // Check that MI dominates the instruction in the normal way. if (&MI == Where || !MDT.dominates(&MI, Where)) continue; // If this use gets a different value, skip it. SlotIndex WhereIdx = LIS.getInstructionIndex(*Where); VNInfo *WhereVNI = FromLI->getVNInfoAt(WhereIdx); if (WhereVNI && WhereVNI != FromVNI) continue; // Make sure ToReg isn't clobbered before it gets there. VNInfo *ToVNI = ToLI->getVNInfoAt(WhereIdx); if (ToVNI && ToVNI != FromVNI) continue; Changed = true; LLVM_DEBUG(dbgs() << "Setting operand " << O << " in " << *Where << " from " << MI << "\n"); O.setReg(ToReg); // If the store's def was previously dead, it is no longer. if (!O.isUndef()) { MI.getOperand(0).setIsDead(false); Indices.push_back(WhereIdx.getRegSlot()); } } if (Changed) { // Extend ToReg's liveness. LIS.extendToIndices(*ToLI, Indices); // Shrink FromReg's liveness. LIS.shrinkToUses(FromLI); // If we replaced all dominated uses, FromReg is now killed at MI. if (!FromLI->liveAt(FromIdx.getDeadSlot())) MI.addRegisterKilled(FromReg, MBB.getParent() ->getSubtarget<WebAssemblySubtarget>() .getRegisterInfo()); } return Changed; }