Analyze program block by block & reorder operators only in basic blocks
This commit is contained in:
@@ -749,20 +749,395 @@ static void processLoopRecursively(SgForStmt* loop, const vector<SAPFOR::BasicBl
|
|||||||
reorderMovableRegionsInLoop(loop, blocks);
|
reorderMovableRegionsInLoop(loop, blocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vector<SAPFOR::BasicBlock*> findBlocksInLoopsByFullIR(
|
||||||
|
SgStatement* funcStmt,
|
||||||
|
const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& FullIR)
|
||||||
|
{
|
||||||
|
vector<SAPFOR::BasicBlock*> result;
|
||||||
|
if (!funcStmt)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
const vector<SAPFOR::BasicBlock*> funcBlocks = findFuncBlocksByFuncStatement(funcStmt, FullIR);
|
||||||
|
const auto loopsMapping = findAndAnalyzeLoops(funcStmt, funcBlocks);
|
||||||
|
|
||||||
|
set<SAPFOR::BasicBlock*> uniq;
|
||||||
|
for (const auto& kv : loopsMapping)
|
||||||
|
for (auto* bb : kv.second)
|
||||||
|
if (bb)
|
||||||
|
uniq.insert(bb);
|
||||||
|
|
||||||
|
result.assign(uniq.begin(), uniq.end());
|
||||||
|
sort(result.begin(), result.end(),
|
||||||
|
[](const SAPFOR::BasicBlock* a, const SAPFOR::BasicBlock* b)
|
||||||
|
{
|
||||||
|
if (!a || !b)
|
||||||
|
return a < b;
|
||||||
|
return a->getNumber() < b->getNumber();
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static map<SgStatement*, vector<SgStatement*>> analyzeBasicBlockIntraDependencies(const SAPFOR::BasicBlock* bb)
|
||||||
|
{
|
||||||
|
map<SgStatement*, vector<SgStatement*>> result;
|
||||||
|
if (!bb)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
auto isCompoundStmt = [](SgStatement* st) -> bool
|
||||||
|
{
|
||||||
|
if (!st)
|
||||||
|
return true;
|
||||||
|
const int v = st->variant();
|
||||||
|
return loop_tags.count(v) || control_tags.count(v) || control_end_tags.count(v);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto isTrackable = [](const SAPFOR::Argument* a) -> bool
|
||||||
|
{
|
||||||
|
if (!a)
|
||||||
|
return false;
|
||||||
|
const auto t = a->getType();
|
||||||
|
return t == SAPFOR::CFG_ARG_TYPE::VAR || t == SAPFOR::CFG_ARG_TYPE::REG;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto argKey = [&](const SAPFOR::Argument* a) -> string
|
||||||
|
{
|
||||||
|
if (!a)
|
||||||
|
return string();
|
||||||
|
return to_string((int)a->getType()) + "#" + to_string((int)a->getMemType()) + "#" + a->getValue();
|
||||||
|
};
|
||||||
|
|
||||||
|
auto isBarrier = [&](const SAPFOR::Instruction* instr) -> bool
|
||||||
|
{
|
||||||
|
if (!instr)
|
||||||
|
return true;
|
||||||
|
const auto op = instr->getOperation();
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case SAPFOR::CFG_OP::F_CALL:
|
||||||
|
case SAPFOR::CFG_OP::STORE:
|
||||||
|
case SAPFOR::CFG_OP::REC_REF_STORE:
|
||||||
|
case SAPFOR::CFG_OP::IO_PARAM:
|
||||||
|
case SAPFOR::CFG_OP::DVM_DIR:
|
||||||
|
case SAPFOR::CFG_OP::SPF_DIR:
|
||||||
|
case SAPFOR::CFG_OP::POINTER_ASS:
|
||||||
|
case SAPFOR::CFG_OP::EXIT:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto isDef = [&](const SAPFOR::Instruction* instr) -> bool
|
||||||
|
{
|
||||||
|
if (!instr)
|
||||||
|
return false;
|
||||||
|
SAPFOR::Argument* r = instr->getResult();
|
||||||
|
if (!isTrackable(r))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const auto op = instr->getOperation();
|
||||||
|
if (op == SAPFOR::CFG_OP::STORE || op == SAPFOR::CFG_OP::REC_REF_STORE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Reaching definitions inside the BasicBlock in straight-line order:
|
||||||
|
// lastDef[var] = last operator in this block that defined it.
|
||||||
|
map<string, pair<SgStatement*, const SAPFOR::Argument*>> lastDef;
|
||||||
|
map<SgStatement*, set<SgStatement*>> depsSets;
|
||||||
|
|
||||||
|
for (auto* ir : bb->getInstructions())
|
||||||
|
{
|
||||||
|
if (!ir || !ir->getInstruction())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const SAPFOR::Instruction* instr = ir->getInstruction();
|
||||||
|
SgStatement* opStmt = instr->getOperator();
|
||||||
|
if (!opStmt || isCompoundStmt(opStmt))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (isBarrier(instr))
|
||||||
|
{
|
||||||
|
for (auto it = lastDef.begin(); it != lastDef.end();)
|
||||||
|
{
|
||||||
|
const SAPFOR::Argument* a = it->second.second;
|
||||||
|
if (!a || a->isMemGlobal() || a->isParameter())
|
||||||
|
it = lastDef.erase(it);
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result.count(opStmt))
|
||||||
|
result[opStmt] = {};
|
||||||
|
|
||||||
|
auto addDep = [&](SAPFOR::Argument* use)
|
||||||
|
{
|
||||||
|
if (!isTrackable(use))
|
||||||
|
return;
|
||||||
|
auto it = lastDef.find(argKey(use));
|
||||||
|
if (it == lastDef.end())
|
||||||
|
return; // only deps inside this BB are needed
|
||||||
|
if (it->second.first && it->second.first != opStmt)
|
||||||
|
depsSets[opStmt].insert(it->second.first);
|
||||||
|
};
|
||||||
|
|
||||||
|
addDep(instr->getArg1());
|
||||||
|
addDep(instr->getArg2());
|
||||||
|
|
||||||
|
if (isDef(instr))
|
||||||
|
lastDef[argKey(instr->getResult())] = { opStmt, instr->getResult() };
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& kv : result)
|
||||||
|
{
|
||||||
|
SgStatement* op = kv.first;
|
||||||
|
auto it = depsSets.find(op);
|
||||||
|
if (it == depsSets.end())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
kv.second.assign(it->second.begin(), it->second.end());
|
||||||
|
sort(kv.second.begin(), kv.second.end(),
|
||||||
|
[](SgStatement* a, SgStatement* b)
|
||||||
|
{
|
||||||
|
const int la = a ? a->lineNumber() : -1;
|
||||||
|
const int lb = b ? b->lineNumber() : -1;
|
||||||
|
if (la != lb)
|
||||||
|
return la < lb;
|
||||||
|
return a < b;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool reorderOperatorsInBasicBlockUsingDeps(SAPFOR::BasicBlock* bb)
|
||||||
|
{
|
||||||
|
if (!bb)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto isCompoundStmt = [](SgStatement* st) -> bool
|
||||||
|
{
|
||||||
|
if (!st)
|
||||||
|
return true;
|
||||||
|
const int v = st->variant();
|
||||||
|
return loop_tags.count(v) || control_tags.count(v) || control_end_tags.count(v);
|
||||||
|
};
|
||||||
|
|
||||||
|
vector<SgStatement*> ops;
|
||||||
|
ops.reserve(bb->getInstructions().size());
|
||||||
|
set<SgStatement*> seen;
|
||||||
|
for (auto* ir : bb->getInstructions())
|
||||||
|
{
|
||||||
|
if (!ir || !ir->getInstruction())
|
||||||
|
continue;
|
||||||
|
SgStatement* st = ir->getInstruction()->getOperator();
|
||||||
|
if (!st || isCompoundStmt(st))
|
||||||
|
continue;
|
||||||
|
if (seen.insert(st).second)
|
||||||
|
ops.push_back(st);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ops.size() < 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
SgStatement* parent = ops.front()->controlParent();
|
||||||
|
if (!parent)
|
||||||
|
return false;
|
||||||
|
for (auto* st : ops)
|
||||||
|
if (!st || st->controlParent() != parent)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
set<SgStatement*> opSet(ops.begin(), ops.end());
|
||||||
|
{
|
||||||
|
SgStatement* lastNode = parent->lastNodeOfStmt();
|
||||||
|
SgStatement* cur = ops.front();
|
||||||
|
size_t idx = 0;
|
||||||
|
|
||||||
|
{
|
||||||
|
SgStatement* scan = parent->lexNext();
|
||||||
|
SgStatement* end = lastNode;
|
||||||
|
bool found = false;
|
||||||
|
while (scan && scan != end)
|
||||||
|
{
|
||||||
|
if (scan == ops.front())
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
scan = scan->lexNext();
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (cur && cur != lastNode && idx < ops.size())
|
||||||
|
{
|
||||||
|
if (cur == ops[idx])
|
||||||
|
{
|
||||||
|
++idx;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (isSgExecutableStatement(cur) && !opSet.count(cur))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (idx == ops.size())
|
||||||
|
break;
|
||||||
|
cur = cur->lexNext();
|
||||||
|
}
|
||||||
|
if (idx != ops.size())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute dependencies (inside BB) and build a new order by moving each statement
|
||||||
|
// as close as possible after its last dependency (if any).
|
||||||
|
const auto depsMap = analyzeBasicBlockIntraDependencies(bb);
|
||||||
|
vector<SgStatement*> order = ops;
|
||||||
|
|
||||||
|
map<SgStatement*, int> pos;
|
||||||
|
for (int i = 0; i < (int)order.size(); ++i)
|
||||||
|
pos[order[i]] = i;
|
||||||
|
|
||||||
|
for (int i = 0; i < (int)order.size(); ++i)
|
||||||
|
{
|
||||||
|
SgStatement* cur = order[i];
|
||||||
|
auto it = depsMap.find(cur);
|
||||||
|
if (it == depsMap.end() || it->second.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int lastDepIdx = -1;
|
||||||
|
for (SgStatement* dep : it->second)
|
||||||
|
{
|
||||||
|
auto itP = pos.find(dep);
|
||||||
|
if (itP != pos.end())
|
||||||
|
lastDepIdx = max(lastDepIdx, itP->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastDepIdx < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const int target = lastDepIdx + 1;
|
||||||
|
if (target == i)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SgStatement* moved = order[i];
|
||||||
|
order.erase(order.begin() + i);
|
||||||
|
|
||||||
|
int insertIdx = target;
|
||||||
|
if (target > i)
|
||||||
|
insertIdx = target - 1;
|
||||||
|
if (insertIdx < 0)
|
||||||
|
insertIdx = 0;
|
||||||
|
if (insertIdx > (int)order.size())
|
||||||
|
insertIdx = (int)order.size();
|
||||||
|
|
||||||
|
order.insert(order.begin() + insertIdx, moved);
|
||||||
|
|
||||||
|
pos.clear();
|
||||||
|
for (int k = 0; k < (int)order.size(); ++k)
|
||||||
|
pos[order[k]] = k;
|
||||||
|
|
||||||
|
i = max(-1, min(i, insertIdx) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool changed = false;
|
||||||
|
for (size_t i = 0; i < ops.size(); ++i)
|
||||||
|
if (ops[i] != order[i])
|
||||||
|
{
|
||||||
|
changed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!changed)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
SgStatement* anchor = parent;
|
||||||
|
{
|
||||||
|
SgStatement* scan = parent->lexNext();
|
||||||
|
SgStatement* end = parent->lastNodeOfStmt();
|
||||||
|
while (scan && scan != end)
|
||||||
|
{
|
||||||
|
if (scan == ops.front())
|
||||||
|
break;
|
||||||
|
anchor = scan;
|
||||||
|
scan = scan->lexNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// apply AST reordering
|
||||||
|
map<SgStatement*, int> savedLine;
|
||||||
|
map<SgStatement*, char*> savedComments;
|
||||||
|
map<SgStatement*, SgStatement*> extracted;
|
||||||
|
|
||||||
|
for (SgStatement* st : ops)
|
||||||
|
{
|
||||||
|
if (!st)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
savedLine[st] = st->lineNumber();
|
||||||
|
savedComments[st] = st->comments() ? strdup(st->comments()) : nullptr;
|
||||||
|
|
||||||
|
SgStatement* ex = st->extractStmt();
|
||||||
|
if (!ex)
|
||||||
|
return false;
|
||||||
|
extracted[st] = ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
SgStatement* insertAfter = anchor;
|
||||||
|
for (SgStatement* st : order)
|
||||||
|
{
|
||||||
|
SgStatement* ex = extracted[st];
|
||||||
|
if (!ex)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto itC = savedComments.find(st);
|
||||||
|
if (itC != savedComments.end() && itC->second)
|
||||||
|
ex->setComments(itC->second);
|
||||||
|
|
||||||
|
auto itL = savedLine.find(st);
|
||||||
|
if (itL != savedLine.end())
|
||||||
|
ex->setlineNumber(itL->second);
|
||||||
|
|
||||||
|
insertAfter->insertStmtAfter(*ex, *parent);
|
||||||
|
insertAfter = ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& kv : savedComments)
|
||||||
|
if (kv.second)
|
||||||
|
free(kv.second);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void moveOperators(SgFile *file, map<string, vector<LoopGraph*>>& loopGraph,
|
void moveOperators(SgFile *file, map<string, vector<LoopGraph*>>& loopGraph,
|
||||||
const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& FullIR,
|
const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& FullIR,
|
||||||
int& countOfTransform) {
|
int& countOfTransform) {
|
||||||
countOfTransform += 1;
|
// countOfTransform += 1;
|
||||||
|
|
||||||
const int funcNum = file -> numberOfFunctions();
|
if (!file)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const int funcNum = file->numberOfFunctions();
|
||||||
|
|
||||||
for (int i = 0; i < funcNum; ++i) {
|
for (int i = 0; i < funcNum; ++i) {
|
||||||
SgStatement *st = file -> functions(i);
|
SgStatement* st = file->functions(i);
|
||||||
|
|
||||||
vector<SAPFOR::BasicBlock*> blocks = findFuncBlocksByFuncStatement(st, FullIR);
|
const auto loopBlocks = findBlocksInLoopsByFullIR(st, FullIR);
|
||||||
map<SgForStmt*, vector<SAPFOR::BasicBlock*>> loopsMapping = findAndAnalyzeLoops(st, blocks);
|
for (auto* bb : loopBlocks)
|
||||||
|
{
|
||||||
|
if (!bb)
|
||||||
|
continue;
|
||||||
|
if (reorderOperatorsInBasicBlockUsingDeps(bb))
|
||||||
|
countOfTransform += 1;
|
||||||
|
}
|
||||||
|
|
||||||
for (auto& loopForAnalyze: loopsMapping)
|
// vector<SAPFOR::BasicBlock*> blocks = findFuncBlocksByFuncStatement(st, FullIR);
|
||||||
processLoopRecursively(loopForAnalyze.first, loopForAnalyze.second, FullIR);
|
// map<SgForStmt*, vector<SAPFOR::BasicBlock*>> loopsMapping = findAndAnalyzeLoops(st, blocks);
|
||||||
|
|
||||||
|
// for (auto& loopForAnalyze : loopsMapping)
|
||||||
|
// processLoopRecursively(loopForAnalyze.first, loopForAnalyze.second, FullIR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user