#include "leak_detector.h" #include "RegionsMerger.h" using namespace std; bool RegionsMerger::compareByStart(const DvmhRegion *a, const DvmhRegion *b) { if (a->getLoops().size() < 1 || b->getLoops().size() < 1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); int lineLeft = a->getLoops()[0]->lineNum; if (lineLeft < 0) lineLeft = a->getLoops()[0]->altLineNum; int lineRight = b->getLoops()[0]->lineNum; if (lineRight < 0) lineRight = b->getLoops()[0]->altLineNum; return lineLeft < lineRight; } bool RegionsMerger::canBeMoved(SgStatement* st, const DvmhRegion *region) const { // For now: st [a, d = b + c] can be moved IF [b, c] are not modified in region AND [a, d] not used for read in region // get usages for statement VarUsages st_usages = rw_analyzer.get_usages(st); // get usages for region auto loop_statements = vector(); for (auto& loop : region->getLoops()) loop_statements.push_back(loop->loop); auto region_usages = rw_analyzer.get_usages(loop_statements); // analyze if statement can be placed before region if (sets_intersect(st_usages.get_reads(), region_usages.get_writes())) // check that [b, c] not modified in region return false; if (sets_intersect(st_usages.get_writes(), region_usages.get_reads())) // check that [a, d] not read in region return false; return true; // everything's ok } vector RegionsMerger::getStatementsToMove(const DvmhRegion *first, const DvmhRegion *second, bool &can) const { // can not, abort operation if (first->getFileName() != second->getFileName() || first->getFunName() != second->getFunName()) { can = false; return vector(); } vector toMove; SgStatement* mediumSt = first->getLastSt()->lexNext(); // skip DVM PARALLEL and hidden stats while (mediumSt->variant() == DVM_PARALLEL_ON_DIR || mediumSt->variant() < 0) mediumSt = mediumSt->lexNext(); //no statements between regions, so can if (mediumSt == second->getFirstSt() && mediumSt->variant() == FOR_NODE) { can = true; return vector(); } //TODO else { can = false; return vector(); } //TODO: need to check and correct while (mediumSt->id() != second->getFirstSt()->id()) { if (mediumSt->variant() == DVM_PARALLEL_ON_DIR) { mediumSt = mediumSt->lexNext(); continue; } if (canBeMoved(mediumSt, first)) toMove.push_back(mediumSt); else // can not, abort operation { can = false; return vector(); } mediumSt = mediumSt->lexNext(); } return toMove; } // Places statements before region void RegionsMerger::moveStatements(const vector& sts, const DvmhRegion* region) { SgStatement* prev = region->getFirstSt()->lexPrev(); while (isDVM_stat(prev)) prev = prev->lexPrev(); for (auto& st : sts) { SgStatement *toInsert = st->copyPtr(); prev->insertStmtAfter(*toInsert, *prev->controlParent()); prev = toInsert; st->deleteStmt(); } rw_analyzer.invalidate(region->getFileName()); } vector RegionsMerger::mergeRegions() { if (regions.size() < 2) return regions; map> byFunc; for (auto& elem : regions) { const int line = elem->getLineForSort(); const string fName = elem->getFunName(); auto& itF = byFunc[fName]; if (itF.find(line) != itF.end()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); itF[line] = elem; } vector newRegions; for (auto& regsForFunc : byFunc) { map& regionsByFunc = regsForFunc.second; if (regionsByFunc.size() == 0) continue; DvmhRegion* newRegion = new DvmhRegion(); DvmhRegion* regionPrev = regionsByFunc.begin()->second; bool isFirst = true; for (auto& loop : regionPrev->getLoops()) newRegion->addLoop(loop); for (auto& region : regionsByFunc) { if (newRegion->getFunName() == "" && region.second->getLoops().size() > 0) { SgStatement* func_st = getFuncStat(region.second->getLoops()[0]->loop); string fun_name = func_st->symbol()->identifier(); newRegion->setFunName(fun_name); } if (isFirst) // skip first region { isFirst = false; continue; } bool can = true; auto toMove = getStatementsToMove(regionPrev, region.second, can); if (can) { //TODO if (toMove.size()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); // moveStatements(toMove, regionPrev); } else { __spf_print(1, " region before loop on line %d (alt %d) cannot be merged\n", region.second->getLoops()[0]->lineNum, region.second->getLoops()[0]->altLineNum); toMove = getStatementsToMove(regionPrev, region.second, can); newRegions.push_back(newRegion); newRegion = new DvmhRegion(); } newRegion->append(*region.second); regionPrev = region.second; } newRegions.push_back(newRegion); } for (auto& old : regions) delete old; regions.clear(); return newRegions; } bool RegionsMerger::sets_intersect(const set& set1, const set& set2) const { for (auto& symb : set1) if (set2.find(symb) != set2.end()) return true; return false; }