Fix move operators pass

This commit is contained in:
Egor Mayorov
2026-05-05 15:50:03 +03:00
parent f02ffe45f5
commit 62e996f2e2

View File

@@ -8,6 +8,7 @@
#include <cmath>
#include <climits>
#include <functional>
#include <cctype>
#include "../../Utils/errors.h"
#include "../../Utils/SgUtils.h"
@@ -20,254 +21,124 @@
using namespace std;
set<int> loop_tags = {FOR_NODE};
set<int> loop_tags = {FOR_NODE, WHILE_NODE, DO_WHILE_NODE};
set<int> control_tags = {IF_NODE, ELSEIF_NODE, DO_WHILE_NODE, WHILE_NODE, LOGIF_NODE};
set<int> control_end_tags = {CONTROL_END};
namespace
static bool isParentStmt(SgStatement* stmt, SgStatement* parent)
{
enum class ArrayIndexCompareResult
{
Equal,
NotEqual,
Unknown
};
// Structural key for array index / subscript analysis (stable across LOAD/STORE of the same access).
string buildStructuralExprKey(SgExpression* e)
{
if (!e)
return string("_");
if (auto* ar = isSgArrayRefExp(e))
{
SgSymbol* sym = ar->symbol() ? OriginalSymbol(ar->symbol()) : nullptr;
string key = string("A(") + (sym ? sym->identifier() : "?");
const int n = ar->numberOfSubscripts();
for (int i = 0; i < n; ++i)
{
key += ",";
key += buildStructuralExprKey(ar->subscript(i));
}
key += ")";
return key;
}
if (e->variant() == VAR_REF || e->variant() == CONST_REF)
{
SgSymbol* sym = e->symbol() ? OriginalSymbol(e->symbol()) : nullptr;
return string((e->variant() == VAR_REF) ? "V(" : "C(") + (sym ? sym->identifier() : "?") + ")";
}
if (auto* v = isSgValueExp(e))
{
if (e->variant() == INT_VAL)
return string("I(") + to_string(v->intValue()) + ")";
if (e->variant() == BOOL_VAL)
return string("B(") + (v->boolValue() ? "1" : "0") + ")";
if (e->variant() == CHAR_VAL)
return string("CH(") + string(1, v->charValue()) + ")";
if (e->variant() == FLOAT_VAL)
{
char* fv = v->floatValue();
return string("F(") + (fv ? string(fv) : string()) + ")";
}
if (e->variant() == DOUBLE_VAL)
{
char* dv = v->doubleValue();
if (!dv || !*dv)
return string("D()");
char* endp = nullptr;
const double d = strtod(dv, &endp);
if (endp != dv && std::isfinite(d))
{
const double r = std::round(d);
if (std::fabs(d - r) < 1e-12 && r >= static_cast<double>(INT_MIN) && r <= static_cast<double>(INT_MAX))
return string("I(") + to_string(static_cast<long long>(r)) + ")";
}
return string("D(") + string(dv) + ")";
}
if (e->variant() == STRING_VAL)
return string("S(") + (v->stringValue() ? v->stringValue() : string()) + ")";
}
if (e->variant() == MULT_OP && e->lhs() && e->rhs())
{
string a = buildStructuralExprKey(e->lhs());
string b = buildStructuralExprKey(e->rhs());
if (a > b)
swap(a, b);
return string("N(") + to_string(e->variant()) + ",L=" + a + ",R=" + b + ")";
}
string key = string("N(") + to_string(e->variant());
if (e->lhs())
key += ",L=" + buildStructuralExprKey(e->lhs());
if (e->rhs())
key += ",R=" + buildStructuralExprKey(e->rhs());
key += ")";
return key;
for (; stmt; stmt = stmt->controlParent())
if (stmt == parent)
return true;
return false;
}
// Prefer AST from IR instruction (same SgArrayRef for matching store/load); fallback to idxStack string.
string memexKeyForArrayLoadStore(const SAPFOR::Instruction* instr, const function<string()>& irStackKey)
static bool isStatementInFile(SgStatement* st, const string& fileName)
{
if (!instr)
return string();
SgExpression* ex = instr->getExpression();
if (ex)
{
if (isSgArrayRefExp(ex))
return string("MEMEX#") + buildStructuralExprKey(ex);
return string("MEMEX#") + buildStructuralExprKey(ex);
}
return irStackKey();
}
ArrayIndexCompareResult compareIndexExpressions(SgExpression* a, SgExpression* b)
{
if (!a && !b)
return ArrayIndexCompareResult::Equal;
if (!a || !b)
return ArrayIndexCompareResult::NotEqual;
const string ka = buildStructuralExprKey(a);
const string kb = buildStructuralExprKey(b);
if (ka.empty() || kb.empty())
return ArrayIndexCompareResult::Unknown;
if (ka == kb)
return ArrayIndexCompareResult::Equal;
return ArrayIndexCompareResult::NotEqual;
}
ArrayIndexCompareResult compareArrayRefExpressions(SgArrayRefExp* a, SgArrayRefExp* b)
{
if (!a && !b)
return ArrayIndexCompareResult::Equal;
if (!a || !b)
return ArrayIndexCompareResult::NotEqual;
SgSymbol* s1 = a->symbol() ? OriginalSymbol(a->symbol()) : nullptr;
SgSymbol* s2 = b->symbol() ? OriginalSymbol(b->symbol()) : nullptr;
if (s1 && s2)
{
if (strcmp(s1->identifier(), s2->identifier()) != 0)
return ArrayIndexCompareResult::NotEqual;
}
else if (s1 != s2)
return ArrayIndexCompareResult::NotEqual;
if (a->numberOfSubscripts() != b->numberOfSubscripts())
return ArrayIndexCompareResult::NotEqual;
for (int i = 0; i < a->numberOfSubscripts(); ++i)
{
ArrayIndexCompareResult c = compareIndexExpressions(a->subscript(i), b->subscript(i));
if (c != ArrayIndexCompareResult::Equal)
return c;
}
return ArrayIndexCompareResult::Equal;
}
} // namespace
static vector<SAPFOR::IR_Block*> findInstructionsFromStatement(SgStatement* st, const vector<SAPFOR::BasicBlock*>& blocks)
{
vector<SAPFOR::IR_Block*> result;
if (!st)
return result;
return false;
const int stmtId = st->id();
for (auto* bb : blocks)
const char* stmtFile = st->fileName();
return stmtFile && fileName == stmtFile;
}
static vector<SgStatement*> findLoopStatementsInFunction(SgStatement* funcStmt, const string& fileName)
{
vector<SgStatement*> loops;
if (!funcStmt)
return loops;
SgStatement* lastNode = funcStmt->lastNodeOfStmt();
for (SgStatement* st = funcStmt; st && st != lastNode; st = st->lexNext())
if (loop_tags.count(st->variant()) && isStatementInFile(st, fileName))
loops.push_back(st);
return loops;
}
static SgStatement* firstSignificantOperatorInBlock(const SAPFOR::BasicBlock* bb, const string& fileName)
{
if (!bb)
return nullptr;
for (auto* ir : bb->getInstructions())
{
if (!bb)
if (!ir || !ir->getInstruction())
continue;
for (auto* ir : bb->getInstructions())
{
if (!ir || !ir->getInstruction())
continue;
SgStatement* op = ir->getInstruction()->getOperator();
if (op && op->id() == stmtId)
result.push_back(ir);
}
SgStatement* st = ir->getInstruction()->getOperator();
if (isStatementInFile(st, fileName))
return st;
}
sort(result.begin(), result.end(),
[](const SAPFOR::IR_Block* a, const SAPFOR::IR_Block* b) { return a->getNumber() < b->getNumber(); });
return result;
return nullptr;
}
vector<SAPFOR::BasicBlock*> findFuncBlocksByFuncStatement(SgStatement *st, const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& FullIR) {
vector<SAPFOR::BasicBlock*> result;
if (!st)
return result;
static SgStatement* lastSignificantOperatorInBlock(const SAPFOR::BasicBlock* bb, const string& fileName)
{
if (!bb)
return nullptr;
Statement* forSt = (Statement*)st;
const string stmtFile = st->fileName();
const int stmtLine = st->lineNumber();
for (auto& func: FullIR) {
if (!func.first || !func.first->funcPointer)
const auto& instructions = bb->getInstructions();
for (auto it = instructions.rbegin(); it != instructions.rend(); ++it)
{
auto* ir = *it;
if (!ir || !ir->getInstruction())
continue;
const string funcFile = func.first->fileName;
const int funcLine = func.first->funcPointer->lineNumber();
// Important: select CFG blocks only for the same file and function header.
if (funcFile == stmtFile && funcLine == stmtLine)
{
result = func.second;
break;
}
SgStatement* st = ir->getInstruction()->getOperator();
if (isStatementInFile(st, fileName))
return st;
}
return result;
return nullptr;
}
map<SgForStmt*, vector<SAPFOR::BasicBlock*>> findAndAnalyzeLoops(SgStatement *st, const vector<SAPFOR::BasicBlock*>& blocks) {
map<SgForStmt*, vector<SAPFOR::BasicBlock*>> result;
SgStatement *lastNode = st->lastNodeOfStmt();
while (st && st != lastNode) {
if (loop_tags.find(st -> variant()) != loop_tags.end()) {
SgForStmt *forSt = (SgForStmt*)st;
SgStatement *loopBody = forSt -> body();
SgStatement *lastLoopNode = st->lastNodeOfStmt();
set<int> blocks_nums;
while (loopBody && loopBody != lastLoopNode) {
vector<SAPFOR::IR_Block*> irBlocks = findInstructionsFromStatement(loopBody, blocks);
if (!irBlocks.empty()) {
SAPFOR::IR_Block* IR = irBlocks.front();
if (IR && IR->getBasicBlock()) {
if (blocks_nums.find(IR -> getBasicBlock() -> getNumber()) == blocks_nums.end()) {
result[forSt].push_back(IR -> getBasicBlock());
blocks_nums.insert(IR -> getBasicBlock() -> getNumber());
}
}
}
loopBody = loopBody -> lexNext();
}
sort(result[forSt].begin(), result[forSt].end());
}
st = st -> lexNext();
}
return result;
static bool isBasicBlockInAnyLoop(const SAPFOR::BasicBlock* bb, const vector<SgStatement*>& loops, const string& fileName)
{
SgStatement* first = firstSignificantOperatorInBlock(bb, fileName);
SgStatement* last = lastSignificantOperatorInBlock(bb, fileName);
if (!first || !last)
return false;
for (auto* loop : loops)
if (loop && isParentStmt(first, loop) && isParentStmt(last, loop))
return true;
return false;
}
vector<SAPFOR::BasicBlock*> findBlocksInLoopsByFullIR(
SgStatement* funcStmt,
static vector<SAPFOR::BasicBlock*> findBlocksInLoopsByFullIR(
SgFile* file,
const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& FullIR)
{
vector<SAPFOR::BasicBlock*> result;
if (!funcStmt)
if (!file || !file->filename())
return result;
const vector<SAPFOR::BasicBlock*> funcBlocks = findFuncBlocksByFuncStatement(funcStmt, FullIR);
const auto loopsMapping = findAndAnalyzeLoops(funcStmt, funcBlocks);
const string fileName = file->filename();
set<SAPFOR::BasicBlock*> uniq;
for (const auto& kv : loopsMapping)
for (auto* bb : kv.second)
if (bb)
for (const auto& func : FullIR)
{
FuncInfo* funcInfo = func.first;
if (!funcInfo || !funcInfo->funcPointer)
continue;
if (funcInfo->fileName != fileName)
continue;
const vector<SgStatement*> loops = findLoopStatementsInFunction(funcInfo->funcPointer, fileName);
if (loops.empty())
continue;
for (auto* bb : func.second)
if (isBasicBlockInAnyLoop(bb, loops, fileName))
uniq.insert(bb);
}
result.assign(uniq.begin(), uniq.end());
sort(result.begin(), result.end(),
@@ -281,11 +152,10 @@ vector<SAPFOR::BasicBlock*> findBlocksInLoopsByFullIR(
return result;
}
static map<SgStatement*, vector<SgStatement*>> analyzeBasicBlockIntraDependencies(const SAPFOR::BasicBlock* bb)
static map<SgStatement*, set<SgStatement*>> analyzeBasicBlockIntraDependencies(const SAPFOR::BasicBlock* bb)
{
map<SgStatement*, vector<SgStatement*>> result;
if (!bb)
return result;
return {};
auto isCompoundStmt = [](SgStatement* st) -> bool
{
@@ -295,306 +165,193 @@ static map<SgStatement*, vector<SgStatement*>> analyzeBasicBlockIntraDependencie
return loop_tags.count(v) || control_tags.count(v) || control_end_tags.count(v);
};
auto isVarArg = [](const SAPFOR::Argument* a) -> bool
auto normalizeSageString = [](const string& src) -> string
{
return a && a->getType() == SAPFOR::CFG_ARG_TYPE::VAR;
string normalized;
bool prevSpace = false;
for (char ch : src)
{
const bool isSpace = std::isspace(static_cast<unsigned char>(ch));
if (isSpace)
{
if (!normalized.empty())
prevSpace = true;
continue;
}
if (prevSpace && !normalized.empty())
normalized += ' ';
normalized += ch;
prevSpace = false;
}
return normalized;
};
auto isArrayArg = [](const SAPFOR::Argument* a) -> bool
auto sageExprToString = [&](SgExpression* expr) -> string
{
return a && a->getType() == SAPFOR::CFG_ARG_TYPE::ARRAY;
};
auto varKey = [&](const SAPFOR::Argument* a) -> string
{
if (!a)
if (!expr)
return string();
return a->getValue();
char* raw = expr->unparse();
return normalizeSageString(raw ? string(raw) : string());
};
auto parseIntConst = [](const SAPFOR::Argument* a, int& out) -> bool
auto arrayElementKey = [&](SgArrayRefExp* arrayRef) -> string
{
if (!a || a->getType() != SAPFOR::CFG_ARG_TYPE::CONST)
return false;
try
if (!arrayRef)
return string();
string key;
SgSymbol* sym = arrayRef->symbol() ? OriginalSymbol(arrayRef->symbol()) : nullptr;
if (sym && sym->identifier())
key = sym->identifier();
else
return sageExprToString(arrayRef);
if (key.empty())
return string();
key += "(";
for (int i = 0; i < arrayRef->numberOfSubscripts(); ++i)
{
out = stoi(a->getValue());
return true;
if (i)
key += ", ";
key += sageExprToString(arrayRef->subscript(i));
}
catch (...)
key += ")";
return key;
};
function<void(SgExpression*, set<string>&)> collectUsedKeysFromExpression =
[&](SgExpression* expr, set<string>& usedKeys)
{
if (!expr)
return;
if (isSgValueExp(expr) || expr->variant() == CONST_REF)
return;
if (auto* arrayRef = isSgArrayRefExp(expr))
{
return false;
const string key = arrayElementKey(arrayRef);
if (!key.empty())
usedKeys.insert(key);
for (int i = 0; i < arrayRef->numberOfSubscripts(); ++i)
collectUsedKeysFromExpression(arrayRef->subscript(i), usedKeys);
return;
}
if (auto* call = isSgFunctionCallExp(expr))
{
for (int i = 0; i < call->numberOfArgs(); ++i)
collectUsedKeysFromExpression(call->arg(i), usedKeys);
return;
}
if (expr->variant() == VAR_REF)
{
SgSymbol* sym = expr->symbol() ? OriginalSymbol(expr->symbol()) : nullptr;
if (sym && sym->identifier())
usedKeys.insert(sym->identifier());
return;
}
collectUsedKeysFromExpression(expr->lhs(), usedKeys);
collectUsedKeysFromExpression(expr->rhs(), usedKeys);
};
auto collectUsedKeysFromArraySubscripts = [&](SgArrayRefExp* arrayRef, set<string>& usedKeys)
{
if (!arrayRef)
return;
for (int i = 0; i < arrayRef->numberOfSubscripts(); ++i)
collectUsedKeysFromExpression(arrayRef->subscript(i), usedKeys);
};
auto addOperatorDependencies = [&](SgStatement* stmt,
const set<string>& usedKeys,
const map<string, SgStatement*>& varDeclarations,
map<SgStatement*, set<SgStatement*>>& operatorsDependencies)
{
if (!stmt)
return;
for (const string& key : usedKeys)
{
auto it = varDeclarations.find(key);
if (it != varDeclarations.end() && it->second && it->second != stmt)
operatorsDependencies[stmt].insert(it->second);
}
};
auto isBarrierInstr = [&](const SAPFOR::Instruction* instr) -> bool
auto declarationKeyFromLeftPart = [&](SgStatement* stmt) -> string
{
if (!instr)
return true;
const auto op = instr->getOperation();
switch (op)
if (!stmt || stmt->variant() != ASSIGN_STAT)
return string();
SgExpression* lhs = stmt->expr(0);
if (!lhs)
return string();
if (auto* arrayRef = isSgArrayRefExp(lhs))
return arrayElementKey(arrayRef);
if (lhs->variant() == VAR_REF)
{
case SAPFOR::CFG_OP::F_CALL:
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;
SgSymbol* sym = lhs->symbol() ? OriginalSymbol(lhs->symbol()) : nullptr;
if (sym && sym->identifier())
return sym->identifier();
}
return string();
};
map<string, SgStatement*> lastDef;
map<string, SgStatement*> lastMemDef;
map<SgStatement*, set<SgStatement*>> depsSets;
vector<SgStatement*> operatorsOrder;
set<SgStatement*> seenOperators;
const auto& irs = bb->getInstructions();
size_t i = 0;
while (i < irs.size())
for (auto* ir : bb->getInstructions())
{
auto* ir = irs[i];
if (!ir || !ir->getInstruction())
{
++i;
continue;
}
const SAPFOR::Instruction* firstInstr = ir->getInstruction();
SgStatement* stmt = firstInstr->getOperator();
const SAPFOR::Instruction* instr = ir->getInstruction();
SgStatement* stmt = instr->getOperator();
if (!stmt || isCompoundStmt(stmt))
{
++i;
continue;
}
vector<const SAPFOR::Instruction*> group;
group.reserve(8);
bool isBarrierStmt = false;
while (i < irs.size())
{
auto* ir2 = irs[i];
if (!ir2 || !ir2->getInstruction())
{
++i;
continue;
}
const SAPFOR::Instruction* instr = ir2->getInstruction();
if (instr->getOperator() != stmt)
break;
group.push_back(instr);
if (isBarrierInstr(instr))
isBarrierStmt = true;
++i;
}
if (!result.count(stmt))
result[stmt] = {};
set<string> usesVars;
set<string> defsVars;
set<string> usesMem;
set<string> defsMem;
vector<string> idxStack;
idxStack.reserve(8);
auto idxAtom = [&](const SAPFOR::Argument* a) -> string
{
if (!a)
return string();
const auto t = a->getType();
if (t == SAPFOR::CFG_ARG_TYPE::VAR || t == SAPFOR::CFG_ARG_TYPE::CONST || t == SAPFOR::CFG_ARG_TYPE::CONST_STR)
return a->getValue();
return string("*");
};
auto joinIdx = [&](const vector<string>& idx) -> string
{
string s;
for (size_t k = 0; k < idx.size(); ++k)
{
if (k)
s += ",";
s += idx[k];
}
return s;
};
auto popLastIdx = [&](int cnt) -> vector<string>
{
vector<string> idx;
if (cnt <= 0 || (size_t)cnt > idxStack.size())
return idx;
idx.assign(idxStack.end() - cnt, idxStack.end());
idxStack.erase(idxStack.end() - cnt, idxStack.end());
return idx;
};
auto memKeyFromLoadStore = [&](const SAPFOR::Instruction* instr) -> string
{
if (!instr)
return string();
SAPFOR::Argument* base = instr->getArg1();
if (!isArrayArg(base))
return string();
int cnt = 0;
if (!parseIntConst(instr->getArg2(), cnt))
cnt = 0;
const auto idx = popLastIdx(cnt);
return base->getValue() + "[" + joinIdx(idx) + "]";
};
string lastStoreKey;
string lastScalarDefKey;
for (auto* instr : group)
{
if (!instr)
continue;
if (isVarArg(instr->getArg1()))
usesVars.insert(varKey(instr->getArg1()));
if (isVarArg(instr->getArg2()))
usesVars.insert(varKey(instr->getArg2()));
if (instr->getOperation() == SAPFOR::CFG_OP::RANGE && isVarArg(instr->getResult()))
usesVars.insert(varKey(instr->getResult()));
if ((instr->getOperation() == SAPFOR::CFG_OP::STORE || instr->getOperation() == SAPFOR::CFG_OP::REC_REF_STORE) &&
isVarArg(instr->getResult()))
{
usesVars.insert(varKey(instr->getResult()));
}
if (instr->getOperation() == SAPFOR::CFG_OP::REF)
{
idxStack.push_back(idxAtom(instr->getArg1()));
}
else if (instr->getOperation() == SAPFOR::CFG_OP::RANGE)
{
idxStack.push_back(idxAtom(instr->getArg1()) + ":" + idxAtom(instr->getArg2()) + ":" + idxAtom(instr->getResult()));
}
else if (instr->getOperation() == SAPFOR::CFG_OP::LOAD || instr->getOperation() == SAPFOR::CFG_OP::STORE)
{
int dimCnt = 0;
if (!parseIntConst(instr->getArg2(), dimCnt))
dimCnt = 0;
string k;
if (instr->getExpression())
{
k = memexKeyForArrayLoadStore(instr, []() { return string(); });
if (!k.empty())
popLastIdx(dimCnt);
}
if (k.empty())
k = memKeyFromLoadStore(instr);
if (!k.empty())
{
if (instr->getOperation() == SAPFOR::CFG_OP::LOAD)
usesMem.insert(k);
else
{
defsMem.insert(k);
lastStoreKey = k;
}
}
}
else if (instr->getOperation() == SAPFOR::CFG_OP::REC_REF_LOAD || instr->getOperation() == SAPFOR::CFG_OP::REC_REF_STORE)
{
SAPFOR::Argument* base = instr->getArg1();
if (base && (base->getType() == SAPFOR::CFG_ARG_TYPE::RECORD || base->getType() == SAPFOR::CFG_ARG_TYPE::VAR))
{
const string k = base->getValue();
if (instr->getOperation() == SAPFOR::CFG_OP::REC_REF_LOAD)
usesMem.insert(k);
else
{
defsMem.insert(k);
lastStoreKey = k;
}
}
}
}
if (!group.empty())
{
const SAPFOR::Instruction* last = group.back();
if (last && last->getOperation() == SAPFOR::CFG_OP::ASSIGN && isVarArg(last->getResult()))
{
lastScalarDefKey = varKey(last->getResult());
defsVars.insert(lastScalarDefKey);
}
else if (last && (last->getOperation() == SAPFOR::CFG_OP::STORE || last->getOperation() == SAPFOR::CFG_OP::REC_REF_STORE))
{
if (!lastStoreKey.empty())
defsMem.insert(lastStoreKey);
}
}
auto addDepFromMap = [&](const map<string, SgStatement*>& m, const string& k)
{
auto it = m.find(k);
if (it == m.end())
return;
if (it->second && it->second != stmt)
depsSets[stmt].insert(it->second);
};
for (const auto& k : usesVars)
addDepFromMap(lastDef, k);
for (const auto& k : usesMem)
addDepFromMap(lastMemDef, k);
if (isBarrierStmt)
{
lastDef.clear();
lastMemDef.clear();
continue;
}
for (const auto& k : defsVars)
{
addDepFromMap(lastDef, k);
lastDef[k] = stmt;
}
for (const auto& k : defsMem)
{
addDepFromMap(lastMemDef, k);
lastMemDef[k] = stmt;
}
if (seenOperators.insert(stmt).second)
operatorsOrder.push_back(stmt);
}
for (auto& kv : result)
map<string, SgStatement*> varDeclarations;
map<SgStatement*, set<SgStatement*>> operatorsDependencies;
for (SgStatement* stmt : operatorsOrder)
{
SgStatement* op = kv.first;
auto it = depsSets.find(op);
if (it == depsSets.end())
continue;
set<string> usedKeys;
if (stmt)
{
collectUsedKeysFromExpression(stmt->expr(1), usedKeys);
collectUsedKeysFromArraySubscripts(isSgArrayRefExp(stmt->expr(0)), usedKeys);
}
addOperatorDependencies(stmt, usedKeys, varDeclarations, operatorsDependencies);
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;
});
const string declarationKey = declarationKeyFromLeftPart(stmt);
if (!declarationKey.empty())
varDeclarations[declarationKey] = stmt;
}
return result;
return operatorsDependencies;
}
static bool reorderOperatorsInBasicBlockUsingDeps(SAPFOR::BasicBlock* bb, const char* expectedFile)
static bool reorderOperatorsInBasicBlockUsingDeps(
SAPFOR::BasicBlock* bb,
const map<SgStatement*, set<SgStatement*>>& operatorsDependencies)
{
if (!bb)
return false;
@@ -624,18 +381,6 @@ static bool reorderOperatorsInBasicBlockUsingDeps(SAPFOR::BasicBlock* bb, const
if (ops.size() < 2)
return false;
// Check that analyzed BB is in the same file as the expected file
const char* bbFile = ops.front()->fileName();
if (!bbFile)
bbFile = "(unknown)";
if (expectedFile && strcmp(expectedFile, bbFile) != 0)
return false;
for (auto* st : ops)
{
if (!st || !st->fileName() || strcmp(st->fileName(), bbFile) != 0)
return false;
}
SgStatement* parent = ops.front()->controlParent();
if (!parent)
return false;
@@ -683,76 +428,72 @@ static bool reorderOperatorsInBasicBlockUsingDeps(SAPFOR::BasicBlock* bb, const
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;
const vector<SgStatement*> originalOrder = ops;
const int nOrig = (int)originalOrder.size();
map<SgStatement*, int> originalIndex;
for (int i = 0; i < (int)ops.size(); ++i)
originalIndex[ops[i]] = i;
auto indexIn = [](const vector<SgStatement*>& v, SgStatement* s) -> int
{
for (int i = 0; i < (int)v.size(); ++i)
if (v[i] == s)
return i;
return -1;
};
map<SgStatement*, vector<SgStatement*>> moveAfter;
set<SgStatement*> moved;
auto indexInOriginal = [&](SgStatement* s) -> int
for (SgStatement* st : ops)
{
return indexIn(originalOrder, s);
};
for (SgStatement* s : ops)
{
auto itDeps = depsMap.find(s);
if (itDeps == depsMap.end() || itDeps->second.empty())
auto itDeps = operatorsDependencies.find(st);
if (itDeps == operatorsDependencies.end() || itDeps->second.empty())
continue;
int lastDepOrigIdx = -1;
SgStatement* lastDep = nullptr;
int lastDepIdx = -1;
for (SgStatement* dep : itDeps->second)
{
const int j = indexInOriginal(dep);
if (j >= 0)
lastDepOrigIdx = max(lastDepOrigIdx, j);
auto itIdx = originalIndex.find(dep);
if (itIdx != originalIndex.end() && itIdx->second > lastDepIdx)
{
lastDep = dep;
lastDepIdx = itIdx->second;
}
}
if (lastDepOrigIdx < 0)
if (!lastDep || lastDep == st)
continue;
SgStatement* successor = nullptr;
if (lastDepOrigIdx + 1 < nOrig)
successor = originalOrder[lastDepOrigIdx + 1];
int posS = indexIn(order, s);
if (posS < 0)
continue;
if (successor == nullptr)
{
if (posS == (int)order.size() - 1)
continue;
order.erase(order.begin() + posS);
order.push_back(s);
continue;
}
if (successor == s)
continue;
const int posSucc = indexIn(order, successor);
if (posSucc < 0)
continue;
if (posS + 1 == posSucc)
continue;
order.erase(order.begin() + posS);
const int posSucc2 = indexIn(order, successor);
if (posSucc2 < 0)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
order.insert(order.begin() + posSucc2, s);
moveAfter[lastDep].push_back(st);
moved.insert(st);
}
vector<SgStatement*> order;
order.reserve(ops.size());
set<SgStatement*> emitted;
set<SgStatement*> active;
bool invalidOrder = false;
function<void(SgStatement*)> emitStatement = [&](SgStatement* st)
{
if (!st || invalidOrder || emitted.count(st))
return;
if (active.count(st))
{
invalidOrder = true;
return;
}
active.insert(st);
emitted.insert(st);
order.push_back(st);
auto itMovedAfter = moveAfter.find(st);
if (itMovedAfter != moveAfter.end())
for (SgStatement* dependent : itMovedAfter->second)
emitStatement(dependent);
active.erase(st);
};
for (SgStatement* st : ops)
if (!moved.count(st))
emitStatement(st);
if (invalidOrder || order.size() != ops.size())
return false;
bool changed = false;
for (size_t i = 0; i < ops.size(); ++i)
if (ops[i] != order[i])
@@ -826,18 +567,14 @@ void moveOperators(SgFile* file, const map<FuncInfo*, vector<SAPFOR::BasicBlock*
return;
if (SgFile::switchToFile(file->filename()) == -1)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
const int funcNum = file->numberOfFunctions();
for (int i = 0; i < funcNum; ++i)
{
SgStatement* st = file->functions(i);
const auto loopBlocks = findBlocksInLoopsByFullIR(file, FullIR);
const auto loopBlocks = findBlocksInLoopsByFullIR(st, FullIR);
for (auto* bb : loopBlocks)
{
if (!bb)
continue;
if (reorderOperatorsInBasicBlockUsingDeps(bb, file->filename()))
countOfTransform += 1;
}
for (auto* bb : loopBlocks)
{
if (!bb)
continue;
const auto operatorsDependencies = analyzeBasicBlockIntraDependencies(bb);
if (reorderOperatorsInBasicBlockUsingDeps(bb, operatorsDependencies))
countOfTransform += 1;
}
}