void DeadCodeEliminationPass::runOnKernel(ir::IRKernel& k) { report("Running dead code elimination on kernel " << k.name); reportE(REPORT_PTX, k); Analysis* dfgAnalysis = getAnalysis(Analysis::DataflowGraphAnalysis); assert(dfgAnalysis != 0); analysis::DataflowGraph& dfg = *static_cast<analysis::DataflowGraph*>(dfgAnalysis); assert(dfg.ssa() != analysis::DataflowGraph::SsaType::None); BlockSet blocks; report(" Starting by scanning all basic blocks"); for(iterator block = dfg.begin(); block != dfg.end(); ++block) { report(" Queueing up BB_" << block->id()); blocks.insert(block); } while(!blocks.empty()) { iterator block = *blocks.begin(); blocks.erase(blocks.begin()); eliminateDeadInstructions(dfg, blocks, block); } report("Finished running dead code elimination on kernel " << k.name); reportE(REPORT_PTX, k); }
void ConstantPropagationPass::runOnKernel(ir::IRKernel& k) { report("Running constant propagation on kernel " << k.name); Analysis* dfgAnalysis = getAnalysis("DataflowGraphAnalysis"); assert(dfgAnalysis != 0); analysis::DataflowGraph& dfg = *static_cast<analysis::DataflowGraph*>(dfgAnalysis); dfg.convertToSSAType(analysis::DataflowGraph::Minimal); assert(dfg.ssa() == analysis::DataflowGraph::Minimal); BlockSet blocks; report(" Starting by scanning all basic blocks"); for(iterator block = dfg.begin(); block != dfg.end(); ++block) { report(" Queueing up BB_" << block->id()); blocks.insert(block); } while(!blocks.empty()) { iterator block = *blocks.begin(); blocks.erase(blocks.begin()); eliminateRedundantInstructions(dfg, blocks, block); } report("Finished running constant propagation on kernel " << k.name); reportE(REPORT_PTX, k); }
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; }