// Partition blocks in an outer/inner loop pair into blocks before and after // the loop static bool partitionOuterLoopBlocks(Loop *L, Loop *SubLoop, BasicBlockSet &ForeBlocks, BasicBlockSet &SubLoopBlocks, BasicBlockSet &AftBlocks, DominatorTree *DT) { BasicBlock *SubLoopLatch = SubLoop->getLoopLatch(); SubLoopBlocks.insert(SubLoop->block_begin(), SubLoop->block_end()); for (BasicBlock *BB : L->blocks()) { if (!SubLoop->contains(BB)) { if (DT->dominates(SubLoopLatch, BB)) AftBlocks.insert(BB); else ForeBlocks.insert(BB); } } // Check that all blocks in ForeBlocks together dominate the subloop // TODO: This might ideally be done better with a dominator/postdominators. BasicBlock *SubLoopPreHeader = SubLoop->getLoopPreheader(); for (BasicBlock *BB : ForeBlocks) { if (BB == SubLoopPreHeader) continue; TerminatorInst *TI = BB->getTerminator(); for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) if (!ForeBlocks.count(TI->getSuccessor(i))) return false; } return true; }
/** * Starting with an Instruction, traverse the CFG backward on all possible * paths, stopping on each path when we hit a task boundary. Return the set of * these task boundaries, sorted by distance (closest first). */ void DINOGlobal::CollectBBsPredicated(BasicBlock &BB, BasicBlockList &visited, BasicBlockSet &BL, BBPredicate &Collect, BBPredicate &Stop){ for( auto &VB : visited ){ if( &BB == VB ){ return; } } if( Collect(BB) ){ BL.insert(&BB); } if( Stop(BB) ){ return; } /*This fixed a bug where visited was carried along other future paths, rather than being popped off after this recursive call was complete */ BasicBlockList nextVisited(visited); nextVisited.push_back(&BB); for (pred_iterator PI = pred_begin(&BB), E = pred_end(&BB); PI != E; ++PI) { CollectBBsPredicated(*(*PI), nextVisited, BL, Collect, Stop); } }
LowerEmAsyncify::BasicBlockSet LowerEmAsyncify::FindReachableBlocksFrom(BasicBlock *src) { BasicBlockSet ReachableBlockSet; std::vector<BasicBlock*> pending; ReachableBlockSet.insert(src); pending.push_back(src); while (!pending.empty()) { BasicBlock *CurBlock = pending.back(); pending.pop_back(); for (succ_iterator SI = succ_begin(CurBlock), SE = succ_end(CurBlock); SI != SE; ++SI) { if (ReachableBlockSet.count(*SI) == 0) { ReachableBlockSet.insert(*SI); pending.push_back(*SI); } } } return ReachableBlockSet; }
/*! Computes the dominator tree from a CFG using algorithm __*/ void PostdominatorTree::computeDT() { int end_node = blocksToIndex[cfg->get_exit_block()]; bool changed = true; p_dom[end_node] = end_node; report( " Computing tree" ); while (changed) { changed = false; // post-order for (int b_ind = 0; b_ind < (int)blocks.size(); b_ind++) { if (b_ind == end_node) continue; ir::ControlFlowGraph::iterator b = blocks[b_ind]; assert(!b->successors.empty()); int new_pdom = 0; bool processed = false; ir::ControlFlowGraph::pointer_iterator succ_it = b->successors.begin(); for (; succ_it != b->successors.end(); ++succ_it) { int p = blocksToIndex[*succ_it]; assert(p<(int)p_dom.size()); if (p_dom[p] != -1) { if( !processed ) { new_pdom = p; processed = true; } else { new_pdom = intersect(p, new_pdom); } } } if( processed ) { if (p_dom[b_ind] != new_pdom) { p_dom[b_ind] = new_pdom; changed = true; } } } } dominated.resize(blocks.size()); for (int n = 0; n < (int)blocks.size(); n++) { if (p_dom[n] >= 0) { dominated[p_dom[n]].push_back(n); } } report(" Computing frontiers") frontiers.resize(blocks.size()); for (int b_ind = 0; b_ind < (int)blocks.size(); b_ind++) { ir::ControlFlowGraph::iterator block = blocks[b_ind]; if(block->successors.size() < 2) continue; typedef std::unordered_set<int> BasicBlockSet; BasicBlockSet blocksWithThisBlockInTheirFrontier; for (auto successor : block->successors) { auto runner = successor; while (runner != getPostDominator(block)) { blocksWithThisBlockInTheirFrontier.insert( blocksToIndex[runner]); runner = getPostDominator(runner); } } for (auto frontierBlock : blocksWithThisBlockInTheirFrontier) { frontiers[b_ind].push_back(frontierBlock); } } }