void SplitAnalysis::getCriticalPreds(const SplitAnalysis::LoopBlocks &Blocks, BlockPtrSet &CriticalPreds) { CriticalPreds.clear(); // A critical predecessor block has curli live-out, and has a successor that // has curli live-in and is not in the loop nor a loop exit block. For such a // predecessor block, we must carry the value in both the 'inside' and // 'outside' registers. for (BlockPtrSet::iterator I = Blocks.Preds.begin(), E = Blocks.Preds.end(); I != E; ++I) { const MachineBasicBlock *Pred = *I; // Definitely not a critical edge. if (Pred->succ_size() == 1) continue; // This block may not have curli live out at all if there is a PHI. if (!lis_.isLiveOutOfMBB(*curli_, Pred)) continue; // Does this block have a successor outside the loop? for (MachineBasicBlock::const_pred_iterator SI = Pred->succ_begin(), SE = Pred->succ_end(); SI != SE; ++SI) { const MachineBasicBlock *Succ = *SI; if (Blocks.Loop.count(Succ) || Blocks.Exits.count(Succ)) continue; if (!lis_.isLiveInToMBB(*curli_, Succ)) continue; // This is a critical predecessor block. CriticalPreds.insert(Pred); break; } } }
/// canSplitCriticalExits - Return true if it is possible to insert new exit /// blocks before the blocks in CriticalExits. bool SplitAnalysis::canSplitCriticalExits(const SplitAnalysis::LoopBlocks &Blocks, BlockPtrSet &CriticalExits) { // If we don't allow critical edge splitting, require no critical exits. if (!AllowSplit) return CriticalExits.empty(); for (BlockPtrSet::iterator I = CriticalExits.begin(), E = CriticalExits.end(); I != E; ++I) { const MachineBasicBlock *Succ = *I; // We want to insert a new pre-exit MBB before Succ, and change all the // in-loop blocks to branch to the pre-exit instead of Succ. // Check that all the in-loop predecessors can be changed. for (MachineBasicBlock::const_pred_iterator PI = Succ->pred_begin(), PE = Succ->pred_end(); PI != PE; ++PI) { const MachineBasicBlock *Pred = *PI; // The external predecessors won't be altered. if (!Blocks.Loop.count(Pred) && !Blocks.Preds.count(Pred)) continue; if (!canAnalyzeBranch(Pred)) return false; } // If Succ's layout predecessor falls through, that too must be analyzable. // We need to insert the pre-exit block in the gap. MachineFunction::const_iterator MFI = Succ; if (MFI == mf_.begin()) continue; if (!canAnalyzeBranch(--MFI)) return false; } // No problems found. return true; }
/// getCriticalExits - It may be necessary to partially break critical edges /// leaving the loop if an exit block has predecessors from outside the loop /// periphery. void SplitAnalysis::getCriticalExits(const SplitAnalysis::LoopBlocks &Blocks, BlockPtrSet &CriticalExits) { CriticalExits.clear(); // A critical exit block has curli live-in, and has a predecessor that is not // in the loop nor a loop predecessor. For such an exit block, the edges // carrying the new variable must be moved to a new pre-exit block. for (BlockPtrSet::iterator I = Blocks.Exits.begin(), E = Blocks.Exits.end(); I != E; ++I) { const MachineBasicBlock *Exit = *I; // A single-predecessor exit block is definitely not a critical edge. if (Exit->pred_size() == 1) continue; // This exit may not have curli live in at all. No need to split. if (!lis_.isLiveInToMBB(*curli_, Exit)) continue; // Does this exit block have a predecessor that is not a loop block or loop // predecessor? for (MachineBasicBlock::const_pred_iterator PI = Exit->pred_begin(), PE = Exit->pred_end(); PI != PE; ++PI) { const MachineBasicBlock *Pred = *PI; if (Blocks.Loop.count(Pred) || Blocks.Preds.count(Pred)) continue; // This is a critical exit block, and we need to split the exit edge. CriticalExits.insert(Exit); break; } } }
/// getCriticalExits - It may be necessary to partially break critical edges /// leaving the loop if an exit block has phi uses of curli. Collect the exit /// blocks that need special treatment into CriticalExits. void SplitAnalysis::getCriticalExits(const SplitAnalysis::LoopBlocks &Blocks, BlockPtrSet &CriticalExits) { CriticalExits.clear(); // A critical exit block contains a phi def of curli, and has a predecessor // that is not in the loop nor a loop predecessor. // For such an exit block, the edges carrying the new variable must be moved // to a new pre-exit block. for (BlockPtrSet::iterator I = Blocks.Exits.begin(), E = Blocks.Exits.end(); I != E; ++I) { const MachineBasicBlock *Succ = *I; SlotIndex SuccIdx = lis_.getMBBStartIdx(Succ); VNInfo *SuccVNI = curli_->getVNInfoAt(SuccIdx); // This exit may not have curli live in at all. No need to split. if (!SuccVNI) continue; // If this is not a PHI def, it is either using a value from before the // loop, or a value defined inside the loop. Both are safe. if (!SuccVNI->isPHIDef() || SuccVNI->def.getBaseIndex() != SuccIdx) continue; // This exit block does have a PHI. Does it also have a predecessor that is // not a loop block or loop predecessor? for (MachineBasicBlock::const_pred_iterator PI = Succ->pred_begin(), PE = Succ->pred_end(); PI != PE; ++PI) { const MachineBasicBlock *Pred = *PI; if (Blocks.Loop.count(Pred) || Blocks.Preds.count(Pred)) continue; // This is a critical exit block, and we need to split the exit edge. CriticalExits.insert(Succ); break; } } }
/// getMultiUseBlocks - if curli has more than one use in a basic block, it /// may be an advantage to split curli for the duration of the block. bool SplitAnalysis::getMultiUseBlocks(BlockPtrSet &Blocks) { // If curli is local to one block, there is no point to splitting it. if (usingBlocks_.size() <= 1) return false; // Add blocks with multiple uses. for (BlockCountMap::iterator I = usingBlocks_.begin(), E = usingBlocks_.end(); I != E; ++I) switch (I->second) { case 0: case 1: continue; case 2: { // It doesn't pay to split a 2-instr block if it redefines curli. VNInfo *VN1 = curli_->getVNInfoAt(lis_.getMBBStartIdx(I->first)); VNInfo *VN2 = curli_->getVNInfoAt(lis_.getMBBEndIdx(I->first).getPrevIndex()); // live-in and live-out with a different value. if (VN1 && VN2 && VN1 != VN2) continue; } // Fall through. default: Blocks.insert(I->first); } return !Blocks.empty(); }
void SplitAnalysis::print(const BlockPtrSet &B, raw_ostream &OS) const { for (BlockPtrSet::const_iterator I = B.begin(), E = B.end(); I != E; ++I) { unsigned count = usingBlocks_.lookup(*I); OS << " BB#" << (*I)->getNumber(); if (count) OS << '(' << count << ')'; } }
const MachineLoop *SplitAnalysis::getBestSplitLoop() { assert(curli_ && "Call analyze() before getBestSplitLoop"); if (usingLoops_.empty()) return 0; LoopPtrSet Loops; LoopBlocks Blocks; BlockPtrSet CriticalExits; // We split around loops where curli is used outside the periphery. for (LoopCountMap::const_iterator I = usingLoops_.begin(), E = usingLoops_.end(); I != E; ++I) { const MachineLoop *Loop = I->first; getLoopBlocks(Loop, Blocks); DEBUG({ dbgs() << " "; print(Blocks, dbgs()); }); switch(analyzeLoopPeripheralUse(Blocks)) { case OutsideLoop: break; case MultiPeripheral: // FIXME: We could split a live range with multiple uses in a peripheral // block and still make progress. However, it is possible that splitting // another live range will insert copies into a peripheral block, and // there is a small chance we can enter an infinity loop, inserting copies // forever. // For safety, stick to splitting live ranges with uses outside the // periphery. DEBUG(dbgs() << ": multiple peripheral uses\n"); break; case ContainedInLoop: DEBUG(dbgs() << ": fully contained\n"); continue; case SinglePeripheral: DEBUG(dbgs() << ": single peripheral use\n"); continue; } // Will it be possible to split around this loop? getCriticalExits(Blocks, CriticalExits); DEBUG(dbgs() << ": " << CriticalExits.size() << " critical exits\n"); if (!canSplitCriticalExits(Blocks, CriticalExits)) continue; // This is a possible split. Loops.insert(Loop); }
void BlockMap::Segment(Block& seed, BlockPtrSet& segment) { std::stack<Block*> blockStack; blockStack.push(&seed); while (!blockStack.empty()) { Block& currBlock = *(blockStack.top()); blockStack.pop(); currBlock.visited = true; segment.insert(&currBlock); for (const auto& neighborCoord : currBlock.GetNeighborCoords()) { Block& neighbor = GetBlock(neighborCoord); if (!neighbor.visited) { blockStack.push(&neighbor); } } } }
const MachineLoop *SplitAnalysis::getBestSplitLoop() { assert(curli_ && "Call analyze() before getBestSplitLoop"); if (usingLoops_.empty()) return 0; LoopPtrSet Loops, SecondLoops; LoopBlocks Blocks; BlockPtrSet CriticalExits; // Find first-class and second class candidate loops. // We prefer to split around loops where curli is used outside the periphery. for (LoopPtrSet::const_iterator I = usingLoops_.begin(), E = usingLoops_.end(); I != E; ++I) { getLoopBlocks(*I, Blocks); LoopPtrSet *LPS = 0; switch(analyzeLoopPeripheralUse(Blocks)) { case OutsideLoop: LPS = &Loops; break; case MultiPeripheral: LPS = &SecondLoops; break; case ContainedInLoop: DEBUG(dbgs() << "ContainedInLoop: " << **I); continue; case SinglePeripheral: DEBUG(dbgs() << "SinglePeripheral: " << **I); continue; } // Will it be possible to split around this loop? getCriticalExits(Blocks, CriticalExits); DEBUG(dbgs() << CriticalExits.size() << " critical exits: " << **I); if (!canSplitCriticalExits(Blocks, CriticalExits)) continue; // This is a possible split. assert(LPS); LPS->insert(*I); } DEBUG(dbgs() << "Got " << Loops.size() << " + " << SecondLoops.size() << " candidate loops\n"); // If there are no first class loops available, look at second class loops. if (Loops.empty()) Loops = SecondLoops; if (Loops.empty()) return 0; // Pick the earliest loop. // FIXME: Are there other heuristics to consider? const MachineLoop *Best = 0; SlotIndex BestIdx; for (LoopPtrSet::const_iterator I = Loops.begin(), E = Loops.end(); I != E; ++I) { SlotIndex Idx = lis_.getMBBStartIdx((*I)->getHeader()); if (!Best || Idx < BestIdx) Best = *I, BestIdx = Idx; } DEBUG(dbgs() << "Best: " << *Best); return Best; }