ControlFlowGraph::BlockPointerVector ControlFlowGraph::reverse_topological_sequence() { typedef std::set<iterator, BlockSetCompare> BlockSet; typedef std::queue<iterator> Queue; report("Creating reverse topological order traversal"); BlockSet visited; BlockPointerVector sequence; Queue queue; queue.push(get_exit_block()); while (sequence.size() != size()) { if(queue.empty()) { for (pointer_iterator block = sequence.begin(); block != sequence.end(); ++block) { for (pointer_iterator pred = (*block)->predecessors.begin(); pred != (*block)->predecessors.end(); ++pred) { if (visited.count(*pred) == 0) { queue.push(*pred); break; } } if(!queue.empty()) { break; } } if(queue.empty()) break; // The remaining blocks are unreachable } iterator current = queue.front(); queue.pop(); if(!visited.insert(current).second) continue; sequence.push_back(current); report(" Adding block " << current->label()); for (pointer_iterator block = current->predecessors.begin(); block != current->predecessors.end(); ++block) { bool noDependencies = true; for (pointer_iterator successor = (*block)->successors.begin(); successor != (*block)->successors.end(); ++successor) { if (visited.count(*successor) == 0) { noDependencies = false; break; } } if(noDependencies) { queue.push(*block); } } } return sequence; }
SILValue StackAllocationPromoter::getLiveOutValue(BlockSet &PhiBlocks, SILBasicBlock *StartBB) { DEBUG(llvm::dbgs() << "*** Searching for a value definition.\n"); // Walk the Dom tree in search of a defining value: for (DomTreeNode *Node = DT->getNode(StartBB); Node; Node = Node->getIDom()) { SILBasicBlock *BB = Node->getBlock(); // If there is a store (that must come after the phi), use its value. BlockToInstMap::iterator it = LastStoreInBlock.find(BB); if (it != LastStoreInBlock.end()) if (auto *St = dyn_cast_or_null<StoreInst>(it->second)) { DEBUG(llvm::dbgs() << "*** Found Store def " << *St->getSrc()); return St->getSrc(); } // If there is a Phi definition in this block: if (PhiBlocks.count(BB)) { // Return the dummy instruction that represents the new value that we will // add to the basic block. SILValue Phi = BB->getArgument(BB->getNumArguments() - 1); DEBUG(llvm::dbgs() << "*** Found a dummy Phi def " << *Phi); return Phi; } // Move to the next dominating block. DEBUG(llvm::dbgs() << "*** Walking up the iDOM.\n"); } DEBUG(llvm::dbgs() << "*** Could not find a Def. Using Undef.\n"); return SILUndef::get(ASI->getElementType(), ASI->getModule()); }
static bool flagHammocksWithSideEffects(SafeRegion& region, const BlockSet& blocksWithSideEffects) { if(region.isLeaf()) { region.doesNotDependOnSideEffects = blocksWithSideEffects.count(region.block) == 0; } else { region.doesNotDependOnSideEffects = true; for(auto& child : region.children) { region.doesNotDependOnSideEffects &= flagHammocksWithSideEffects(child, blocksWithSideEffects); } } return region.doesNotDependOnSideEffects; }
SILValue StackAllocationPromoter::getLiveInValue(BlockSet &PhiBlocks, SILBasicBlock *BB) { // First, check if there is a Phi value in the current block. We know that // our loads happen before stores, so we need to first check for Phi nodes // in the first block, but stores first in all other stores in the idom // chain. if (PhiBlocks.count(BB)) { DEBUG(llvm::dbgs() << "*** Found a local Phi definition.\n"); return BB->getArgument(BB->getNumArguments() - 1); } if (BB->pred_empty() || !DT->getNode(BB)) return SILUndef::get(ASI->getElementType(), ASI->getModule()); // No phi for this value in this block means that the value flowing // out of the immediate dominator reaches here. DomTreeNode *IDom = DT->getNode(BB)->getIDom(); assert(IDom && "Attempt to get live-in value for alloc_stack in entry block!"); return getLiveOutValue(PhiBlocks, IDom->getBlock()); }
ControlFlowGraph::ConstBlockPointerVector ControlFlowGraph::executable_sequence() const { typedef std::unordered_set<const_iterator> BlockSet; ConstBlockPointerVector sequence; BlockSet unscheduled; for(const_iterator i = begin(); i != end(); ++i) { unscheduled.insert(i); } report("Getting executable sequence."); sequence.push_back(get_entry_block()); unscheduled.erase(get_entry_block()); report(" added " << get_entry_block()->label()); while (!unscheduled.empty()) { if (sequence.back()->has_fallthrough_edge()) { const_edge_iterator fallthroughEdge = sequence.back()->get_fallthrough_edge(); sequence.push_back(fallthroughEdge->tail); unscheduled.erase(fallthroughEdge->tail); } else { // find a new block, favor branch targets over random blocks const_iterator next = *unscheduled.begin(); for(const_edge_pointer_iterator edge = sequence.back()->out_edges.begin(); edge != sequence.back()->out_edges.end(); ++edge) { if(unscheduled.count((*edge)->tail) != 0) { next = (*edge)->tail; } } // rewind through fallthrough edges to find the beginning of the // next chain of fall throughs report(" restarting at " << next->label()); bool rewinding = true; while (rewinding) { rewinding = false; for (const_edge_pointer_iterator edge = next->in_edges.begin(); edge != next->in_edges.end(); ++edge) { if ((*edge)->type == Edge::FallThrough) { assertM(unscheduled.count((*edge)->head) != 0, (*edge)->head->label() << " has multiple fallthrough branches."); next = (*edge)->head; report(" rewinding to " << next->label()); rewinding = true; break; } } } sequence.push_back(next); unscheduled.erase(next); } report(" added " << sequence.back()->label()); } return sequence; }
void ReversePostOrderTraversal::analyze(Function& function) { typedef util::LargeSet<BasicBlock*> BlockSet; typedef std::stack<BasicBlock*> BlockStack; order.clear(); BlockSet visited; BlockStack stack; auto cfgAnalysis = getAnalysis("ControlFlowGraph"); auto cfg = static_cast<ControlFlowGraph*>(cfgAnalysis); report("Creating reverse post order traversal over function '" + function.name() + "'"); // reverse post order is reversed topological order stack.push(&*function.entry_block()); while(order.size() != function.size()) { if(stack.empty()) { for(auto block : order) { auto successors = cfg->getSuccessors(*block); for(auto successor : successors) { if(visited.insert(successor).second) { stack.push(successor); break; } } if(!stack.empty()) break; } } assertM(!stack.empty(), (function.size() - order.size()) << " blocks are not connected."); while(!stack.empty()) { BasicBlock* top = stack.top(); stack.pop(); auto successors = cfg->getSuccessors(*top); for(auto successor : successors) { assert(successor != nullptr); auto predecessors = cfg->getPredecessors(*successor); bool allPredecessorsVisited = true; for(auto predecessor : predecessors) { if(visited.count(predecessor) == 0) { allPredecessorsVisited = false; break; } } if(!allPredecessorsVisited) continue; if(visited.insert(successor).second) { stack.push(successor); } } order.push_back(top); report(" " << top->name()); } } // reverse the order std::reverse(order.begin(), order.end()); }