void DivergenceLinearScan::runOnKernel(ir::IRKernel& k) { auto dfg = static_cast<analysis::DataflowGraph*>( getAnalysis("DataflowGraphAnalysis")); dfg->convertToSSAType(analysis::DataflowGraph::Gated); #if DIVERGENCE_REGISTER_PROFILE_H_ divergenceProfiler::resetSpillData(); #endif _shared.clear(); LinearScanRegisterAllocationPass::runOnKernel(k); #if DIVERGENCE_REGISTER_PROFILE_H_ if(!k.function()) divergenceProfiler::printSpillResults(k.name); #endif }
void AffineLinearScan::runOnKernel(ir::IRKernel& k) { #if AFFINE_REGISTER_PROFILE_H_ affineProfiler::resetSpillData(); #endif AffineRegister::tempRegisters.clear(); AffineRegister::warpPosition = 0; _shared.clear(); LinearScanRegisterAllocationPass::runOnKernel(k); #if AFFINE_REGISTER_PROFILE_H_ if(!k.function()) { affineProfiler::printSpillResults(k.name); } #endif }
void SimpleAliasAnalysis::analyze(ir::IRKernel& kernel) { // Functions can be called _aStoreCanReachThisFunction = !kernel.function(); _kernel = &kernel; if(_aStoreCanReachThisFunction) return; for(auto block = kernel.cfg()->begin(); block != kernel.cfg()->end(); ++block) { for(auto instruction = block->instructions.begin(); instruction != block->instructions.end(); ++instruction) { auto ptx = static_cast<ir::PTXInstruction*>(*instruction); if(ptx->isStore()) { _aStoreCanReachThisFunction = true; return; } } } }
bool SimplifyControlFlowGraphPass::_mergeExitBlocks(ir::IRKernel& k) { typedef std::unordered_map<ir::ControlFlowGraph::iterator, ir::ControlFlowGraph::instruction_iterator> BlockMap; report(" Merging exit blocks..."); BlockMap exitBlocks; // Find all blocks with exit instructions for(ir::ControlFlowGraph::iterator block = k.cfg()->begin(); block != k.cfg()->end(); ++block) { for(ir::ControlFlowGraph::instruction_iterator instruction = block->instructions.begin(); instruction != block->instructions.end(); ++instruction) { ir::PTXInstruction& ptx = static_cast<ir::PTXInstruction&>(**instruction); if(ptx.isExit() && ptx.opcode != ir::PTXInstruction::Trap) { // There should be an edge to the exit block assertM(block->find_out_edge(k.cfg()->get_exit_block()) != block->out_edges.end(), "No edge from " << block->label() << " to exit node."); exitBlocks.insert(std::make_pair(block, instruction)); break; } } } // If there is only one/zero blocks, then don't change anything if(exitBlocks.size() < 2) { if(exitBlocks.size() == 1) { ir::PTXInstruction& ptx = static_cast<ir::PTXInstruction&>(**exitBlocks.begin()->second); if(k.function()) { ptx.opcode = ir::PTXInstruction::Ret; } else { ptx.opcode = ir::PTXInstruction::Exit; } } return false; } // Otherwise... // 1) create a new exit block ir::ControlFlowGraph::iterator newExit = k.cfg()->insert_block( ir::BasicBlock(k.cfg()->newId())); ir::BasicBlock::EdgePointerVector deletedEdges = k.cfg()->get_exit_block()->in_edges; // 1a) Create edges targetting the new block for(ir::ControlFlowGraph::edge_pointer_iterator edge = deletedEdges.begin(); edge != deletedEdges.end(); ++edge) { k.cfg()->insert_edge(ir::Edge((*edge)->head, newExit, (*edge)->type)); k.cfg()->remove_edge(*edge); } k.cfg()->insert_edge(ir::Edge(newExit, k.cfg()->get_exit_block(), ir::Edge::FallThrough)); // 2) Delete the instructions from their blocks for(BlockMap::iterator block = exitBlocks.begin(); block != exitBlocks.end(); ++block) { report(" merging block " << block->first->label()); // 2a) Insert a branch from blocks with branch edges ir::ControlFlowGraph::edge_pointer_iterator edge = newExit->find_in_edge(block->first); if((*edge)->type == ir::Edge::Branch) { ir::PTXInstruction* newBranch = new ir::PTXInstruction( ir::PTXInstruction::Bra, ir::PTXOperand(newExit->label())); newBranch->uni = true; block->first->instructions.push_back(newBranch); } delete *block->second; block->first->instructions.erase(block->second); } // 3 Add an appropriate exit instruction to the new exit block if(k.function()) { newExit->instructions.push_back( new ir::PTXInstruction(ir::PTXInstruction::Ret)); } else { newExit->instructions.push_back( new ir::PTXInstruction(ir::PTXInstruction::Exit)); } return true; }