static bool canRemoveAliveOut(analysis::DataflowGraph& dfg, iterator block, const Register& aliveOut) { for(BlockPointerSet::iterator successor = block->targets().begin(); successor != block->targets().end(); ++successor) { for(RegisterSet::iterator aliveIn = (*successor)->aliveIn().begin(); aliveIn != (*successor)->aliveIn().end(); ++aliveIn) { // A target successor uses the value if(aliveIn->id == aliveOut.id) return false; } } if(block->fallthrough() != dfg.end()) { iterator successor = block->fallthrough(); for(RegisterSet::iterator aliveIn = successor->aliveIn().begin(); aliveIn != successor->aliveIn().end(); ++aliveIn) { // A fallthrough successor uses the value if(aliveIn->id == aliveOut.id) return false; } } // No successors use the value return true; }
static void eliminateRedundantInstructions(analysis::DataflowGraph& dfg, BlockSet& blocks, iterator block) { typedef std::vector<unsigned int> KillList; KillList killList; report(" Propagating constants through instructions in BB_" << block->id()); unsigned int index = 0; for(auto instruction = block->instructions().begin(); instruction != block->instructions().end(); ++instruction) { if(!propagateValueToSuccessors(dfg, blocks, instruction)) { ++index; continue; } if(canRemoveInstruction(block, instruction)) { report(" value is not used, removed it."); killList.push_back(index); // schedule the block for more work // TODO: do this when we consider values in multiple blocks } else { ++index; } } for(KillList::iterator killed = killList.begin(); killed != killList.end(); ++killed) { dfg.erase(block, *killed); } }
static void eliminateDeadInstructions(analysis::DataflowGraph& dfg, BlockSet& blocks, iterator block) { typedef analysis::DataflowGraph::Block Block; typedef analysis::DataflowGraph::RegisterSet RegisterSet; typedef std::vector<unsigned int> KillList; typedef std::vector<PhiInstructionVector::iterator> PhiKillList; typedef std::vector<RegisterSet::iterator> AliveKillList; report(" Eliminating dead instructions from BB_" << block->id()); report(" Removing dead alive out values"); AliveKillList aliveOutKillList; for(RegisterSet::iterator aliveOut = block->aliveOut().begin(); aliveOut != block->aliveOut().end(); ++aliveOut) { if(canRemoveAliveOut(dfg, block, *aliveOut)) { report(" removed " << aliveOut->id); aliveOutKillList.push_back(aliveOut); } } for(AliveKillList::iterator killed = aliveOutKillList.begin(); killed != aliveOutKillList.end(); ++killed) { block->aliveOut().erase(*killed); } KillList killList; report(" Removing dead instructions"); unsigned int index = 0; for(InstructionVector::iterator instruction = block->instructions().begin(); instruction != block->instructions().end(); ++instruction) { if(canRemoveInstruction(block, instruction)) { report(" removed '" << instruction->i->toString() << "'"); killList.push_back(index); // schedule the block for more work report(" scheduled this block again"); blocks.insert(block); } else { ++index; } } for(KillList::iterator killed = killList.begin(); killed != killList.end(); ++killed) { dfg.erase(block, *killed); } PhiKillList phiKillList; report(" Removing dead phi instructions"); for(PhiInstructionVector::iterator phi = block->phis().begin(); phi != block->phis().end(); ++phi) { if(canRemovePhi(block, *phi)) { report(" removed " << phi->d.id); phiKillList.push_back(phi); } } report(" Removing dead alive in values"); AliveKillList aliveInKillList; for(RegisterSet::iterator aliveIn = block->aliveIn().begin(); aliveIn != block->aliveIn().end(); ++aliveIn) { if(canRemoveAliveIn(block, *aliveIn)) { report(" removed " << aliveIn->id); aliveInKillList.push_back(aliveIn); // schedule the predecessors for more work for(BlockPointerSet::iterator predecessor = block->predecessors().begin(); predecessor != block->predecessors().end(); ++predecessor) { report(" scheduled predecessor BB_" << (*predecessor)->id()); blocks.insert(*predecessor); } } } for(AliveKillList::iterator killed = aliveInKillList.begin(); killed != aliveInKillList.end(); ++killed) { block->aliveIn().erase(*killed); } }
bool TestDataflowGraph::_verify( const analysis::DataflowGraph& graph ) { for( analysis::DataflowGraph::const_iterator block = graph.begin(); block != graph.end(); ++block ) { analysis::DataflowGraph::Block::RegisterSet defined; report( " Alive in registers:" ); for( analysis::DataflowGraph::Block::RegisterSet::const_iterator reg = block->aliveIn().begin(); reg != block->aliveIn().end(); ++reg ) { report( " " << reg->id ); defined.insert( *reg ); } if( !block->phis().empty() ) { status << " Block " << block->label() << " has " << block->phis().size() << " phi instructions." << std::endl; return false; } for( analysis::DataflowGraph::InstructionVector::const_iterator instruction = block->instructions().begin(); instruction != block->instructions().end(); ++instruction ) { report( " " << instruction->label << ": " << hydrazine::toFormattedString( instruction->d.begin(), instruction->d.end(), Double() ) << " <- " << hydrazine::toFormattedString( instruction->s.begin(), instruction->s.end(), Double() ) ); analysis::DataflowGraph::RegisterPointerVector::const_iterator reg = instruction->s.begin(); for( ; reg != instruction->s.end(); ++reg ) { if( !defined.count( *reg ) ) { status << " Register " << *reg->pointer << " in instruction " << instruction->label << " in block " << block->label() << " used uninitialized." << std::endl; return false; } } reg = instruction->d.begin(); for( ; reg != instruction->d.end(); ++reg ) { defined.insert( *reg ); } } for( analysis::DataflowGraph::Block::RegisterSet::const_iterator reg = block->aliveOut().begin(); reg != block->aliveOut().end(); ++reg ) { if( !defined.count( *reg ) ) { status << " Register " << reg->id << " out set of block " << block->label() << " used uninitialized." << std::endl; return false; } } } return true; }
bool TestDataflowGraph::_verifyIdentities( analysis::DataflowGraph& graph ) { analysis::DataflowGraph::Block::RegisterSet global; analysis::InstructionConverter converter; analysis::DataflowGraph::iterator block1 = graph.begin(); for( ; block1 != graph.end(); ++block1 ) { analysis::DataflowGraph::iterator block2 = graph.begin(); for( ; block2 != graph.end(); ++block2 ) { if (block1 != block2) { analysis::DataflowGraph::InstructionVector::const_iterator inst1 = block1->instructions().begin(); analysis::DataflowGraph::InstructionVector::const_iterator inst2 = block2->instructions().begin(); while((inst1 != block1->instructions().end()) && (inst2 != block2->instructions().end())) { ir::PTXInstruction* ptxInst1 = static_cast< ir::PTXInstruction* >(inst1->i); ir::PTXInstruction* ptxInst2 = static_cast< ir::PTXInstruction* >(inst2->i); std::cout << ptxInst1->toString() << ": " << hydrazine::toFormattedString( inst1->d.begin(), inst1->d.end(), Double() ) << " <- " << hydrazine::toFormattedString( inst1->s.begin(), inst1->s.end(), Double() ) << " | "; std::cout << ptxInst2->toString() << ": " << hydrazine::toFormattedString( inst2->d.begin(), inst2->d.end(), Double() ) << " <- " << hydrazine::toFormattedString( inst2->s.begin(), inst2->s.end(), Double() ) << std::endl; // try to match inst1 and inst2 analysis::DataflowGraph::Instruction matchedInst1; analysis::DataflowGraph::Instruction matchedInst2; bool matched = converter.normalize(matchedInst1, matchedInst2, *inst1, *inst2); if (matched) { ir::PTXInstruction* matchedPtx1 = static_cast< ir::PTXInstruction* >(matchedInst1.i); ir::PTXInstruction* matchedPtx2 = static_cast< ir::PTXInstruction* >(matchedInst2.i); std::cout << "matched:" << std::endl; std::cout << matchedPtx1->toString() << ": " << hydrazine::toFormattedString( matchedInst1.d.begin(), matchedInst1.d.end(), Double() ) << " <- " << hydrazine::toFormattedString( matchedInst1.s.begin(), matchedInst1.s.end(), Double() ) << " | "; std::cout << matchedPtx2->toString() << ": " << hydrazine::toFormattedString( matchedInst2.d.begin(), matchedInst2.d.end(), Double() ) << " <- " << hydrazine::toFormattedString( matchedInst2.s.begin(), matchedInst2.s.end(), Double() ) << std::endl; } std::cout << "-----------" << std::endl; ++inst1; ++inst2; } // while } // if } // for } // for return true; }
bool TestDataflowGraph::_verifySsa( const analysis::DataflowGraph& graph ) { analysis::DataflowGraph::Block::RegisterSet global; for( analysis::DataflowGraph::const_iterator block = graph.begin(); block != graph.end(); ++block ) { analysis::DataflowGraph::Block::RegisterSet defined; report( block->label() ); report( " Alive in registers:" ); for( analysis::DataflowGraph::Block::RegisterSet::const_iterator reg = block->aliveIn().begin(); reg != block->aliveIn().end(); ++reg ) { report( " " << reg->id ); defined.insert( *reg ); } for( analysis::DataflowGraph::PhiInstructionVector::const_iterator phi = block->phis().begin(); phi != block->phis().end(); ++phi ) { report( " phi " << phi->d.id << " <- " << hydrazine::toFormattedString( phi->s.begin(), phi->s.end(), ToId() ) ); for( analysis::DataflowGraph::RegisterVector::const_iterator reg = phi->s.begin(); reg != phi->s.end(); ++reg ) { if( !defined.count( *reg ) ) { status << " Register " << reg->id << " in phi instruction " << std::distance( block->phis().begin(), phi ) << " in " << block->label() << " used uninitialized." << std::endl; return false; } } defined.insert( phi->d ); if( !global.insert( phi->d ).second ) { status << " In " << block->label() << ", instruction phi " << std::distance( block->phis().begin(), phi ) << ", reg " << phi->d.id << " already defined globally." << std::endl; return false; } } for( analysis::DataflowGraph::InstructionVector::const_iterator instruction = block->instructions().begin(); instruction != block->instructions().end(); ++instruction ) { report( " " << instruction->label << ": " << hydrazine::toFormattedString( instruction->d.begin(), instruction->d.end(), Double() ) << " <- " << hydrazine::toFormattedString( instruction->s.begin(), instruction->s.end(), Double() ) ); analysis::DataflowGraph::RegisterPointerVector::const_iterator reg = instruction->s.begin(); for( ; reg != instruction->s.end(); ++reg ) { if( !defined.count( *reg ) ) { status << " Register " << *reg->pointer << " in instruction " << instruction->label << " in " << block->label() << " used uninitialized." << std::endl; return false; } } for( reg = instruction->d.begin(); reg != instruction->d.end(); ++reg ) { defined.insert( *reg ); if( !global.insert( *reg ).second ) { status << " In " << block->label() << ", instruction " << instruction->label << ", reg " << *reg->pointer << " already defined globally." << std::endl; return false; } } } for( analysis::DataflowGraph::Block::RegisterSet::const_iterator reg = block->aliveOut().begin(); reg != block->aliveOut().end(); ++reg ) { if( !defined.count( *reg ) ) { status << " Register " << reg->id << " out set of block " << block->label() << " used uninitialized." << std::endl; return false; } } } return true; }