DivergenceAnalysis::block_set DivergenceAnalysis::_getDivergentBlocksInPostdominanceFrontier( const DataflowGraph::iterator &block) { const Analysis* dfgAnalysis = getAnalysis("DataflowGraphAnalysis"); assert(dfgAnalysis != 0); const DataflowGraph &cdfg = static_cast<const DataflowGraph&>(*dfgAnalysis); DataflowGraph &dfg = const_cast<DataflowGraph&>(cdfg); PostdominatorTree* dtree = (PostdominatorTree*) (getAnalysis("PostDominatorTreeAnalysis")); auto postDominator = dfg.getCFGtoDFGMap()[ dtree->getPostDominator(block->block())]; block_set divergentBlocks; for (auto successor = block->successors().begin(); successor != block->successors().end(); ++successor) { if (*successor == postDominator) continue; block_set allDivergentPaths; buildDivergentSubgraph(allDivergentPaths, *successor, postDominator); divergentBlocks.insert(allDivergentPaths.begin(), allDivergentPaths.end()); } return divergentBlocks; }
static bool buildDivergentSubgraph( DivergenceAnalysis::block_set& graph, const DataflowGraph::iterator &block, const DataflowGraph::iterator &postDominator) { bool hitPostDominator = false; // don't include blocks with barriers if(hasBarrier(block)) return false; // skip loops if(!graph.insert(block).second) return false; for (auto successor = block->successors().begin(); successor != block->successors().end(); ++successor) { // stop at the post dominator if (*successor == postDominator) { hitPostDominator = true; continue; } hitPostDominator |= buildDivergentSubgraph(graph, *successor, postDominator); } return hitPostDominator; }
bool DivergenceAnalysis::_hasTrivialPathToExit( const DataflowGraph::iterator &block) const { // We can ignore divergent threads that immediately exit unsigned int exitingPaths = 0; const Analysis* dfgAnalysis = getAnalysis("DataflowGraphAnalysis"); assert(dfgAnalysis != 0); const DataflowGraph &dfg = static_cast<const DataflowGraph&>(*dfgAnalysis); auto exit = --dfg.end(); for (auto successor = block->successors().begin(); successor != block->successors().end(); ++successor) { auto path = *successor; while (true) { if (path == exit) { ++exitingPaths; break; } if (path->successors().size() != 1) { break; } if (!path->instructions().empty()) { if (path->instructions().size() == 1) { const ir::PTXInstruction &ptxI = *(static_cast<ir::PTXInstruction *> ( path->instructions().back().i)); if (ptxI.isExit()) { ++exitingPaths; } } break; } path = *path->successors().begin(); } } if (block->successors().size() - exitingPaths < 2) { return true; } return false; }
unsigned int DivergenceAnalysis::_numberOfDivergentPathsToPostDominator( const DataflowGraph::iterator &block) const { const Analysis* dfgAnalysis = getAnalysis("DataflowGraphAnalysis"); assert(dfgAnalysis != 0); const DataflowGraph &cdfg = static_cast<const DataflowGraph&>(*dfgAnalysis); DataflowGraph &dfg = const_cast<DataflowGraph&>(cdfg); PostdominatorTree* dtree = (PostdominatorTree*) (getAnalysis("PostDominatorTreeAnalysis")); auto postDominator = dfg.getCFGtoDFGMap()[ dtree->getPostDominator(block->block())]; unsigned int divergentPaths = 0; for (auto successor = block->successors().begin(); successor != block->successors().end(); ++successor) { if (*successor == postDominator) { ++divergentPaths; continue; } block_set allDivergentPaths; if (doAnyDivergentPathsReachThePostDominator(allDivergentPaths, *successor, postDominator)) { ++divergentPaths; } } report(" There are " << divergentPaths << " divergent paths from " << block->label() << " to post-dominator " << postDominator->label()); return divergentPaths; }