diff --git a/src/Transformations/MoveOperators/move_operators.cpp b/src/Transformations/MoveOperators/move_operators.cpp index c68a9c4..bc9b1e5 100644 --- a/src/Transformations/MoveOperators/move_operators.cpp +++ b/src/Transformations/MoveOperators/move_operators.cpp @@ -5,6 +5,9 @@ #include #include #include +#include +#include +#include #include "../../Utils/errors.h" #include "../../Utils/SgUtils.h" @@ -21,6 +24,147 @@ set loop_tags = {FOR_NODE}; set control_tags = {IF_NODE, ELSEIF_NODE, DO_WHILE_NODE, WHILE_NODE, LOGIF_NODE}; set control_end_tags = {CONTROL_END}; +namespace +{ +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(INT_MIN) && r <= static_cast(INT_MAX)) + return string("I(") + to_string(static_cast(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; +} + +// Prefer AST from IR instruction (same SgArrayRef for matching store/load); fallback to idxStack string. +string memexKeyForArrayLoadStore(const SAPFOR::Instruction* instr, const function& irStackKey) +{ + 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 findInstructionsFromStatement(SgStatement* st, const vector& blocks) { @@ -151,83 +295,39 @@ static map> analyzeBasicBlockIntraDependencie return loop_tags.count(v) || control_tags.count(v) || control_end_tags.count(v); }; - auto isTrackable = [](const SAPFOR::Argument* a) -> bool + auto isVarArg = [](const SAPFOR::Argument* a) -> bool + { + return a && a->getType() == SAPFOR::CFG_ARG_TYPE::VAR; + }; + + auto isArrayArg = [](const SAPFOR::Argument* a) -> bool + { + return a && a->getType() == SAPFOR::CFG_ARG_TYPE::ARRAY; + }; + + auto varKey = [&](const SAPFOR::Argument* a) -> string { if (!a) + return string(); + return a->getValue(); + }; + + auto parseIntConst = [](const SAPFOR::Argument* a, int& out) -> bool + { + if (!a || a->getType() != SAPFOR::CFG_ARG_TYPE::CONST) 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 memKeyFromInstr = [&](const SAPFOR::Instruction* instr) -> string - { - if (!instr) - return string(); - SgExpression* ex = instr->getExpression(); - if (!ex) - return string(); - - auto exprKey = [&](auto&& self, SgExpression* e) -> string + try { - 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 += self(self, 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) - return string("F(") + (v->floatValue() ? v->floatValue() : "") + ")"; - if (e->variant() == DOUBLE_VAL) - return string("D(") + (v->doubleValue() ? v->doubleValue() : "") + ")"; - if (e->variant() == STRING_VAL) - return string("S(") + (v->stringValue() ? v->stringValue() : "") + ")"; - } - - string key = string("N(") + to_string(e->variant()); - if (e->lhs()) - key += ",L=" + self(self, e->lhs()); - if (e->rhs()) - key += ",R=" + self(self, e->rhs()); - key += ")"; - return key; - }; - - return "MEMEX#" + exprKey(exprKey, ex); + out = stoi(a->getValue()); + return true; + } + catch (...) + { + return false; + } }; - auto isBarrier = [&](const SAPFOR::Instruction* instr) -> bool + auto isBarrierInstr = [&](const SAPFOR::Instruction* instr) -> bool { if (!instr) return true; @@ -246,112 +346,229 @@ static map> analyzeBasicBlockIntraDependencie } }; - 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> lastDef; - map> lastMemDef; + map lastDef; + map lastMemDef; map> depsSets; - for (auto* ir : bb->getInstructions()) + const auto& irs = bb->getInstructions(); + size_t i = 0; + while (i < irs.size()) { + auto* ir = irs[i]; if (!ir || !ir->getInstruction()) - continue; - - const SAPFOR::Instruction* instr = ir->getInstruction(); - SgStatement* opStmt = instr->getOperator(); - if (!opStmt) - continue; - if (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; - } - for (auto it = lastMemDef.begin(); it != lastMemDef.end();) - { - const SAPFOR::Argument* a = it->second.second; - if (!a || a->isMemGlobal() || a->isParameter()) - it = lastMemDef.erase(it); - else - ++it; - } + ++i; + continue; } - if (!result.count(opStmt)) - result[opStmt] = {}; - - auto addDep = [&](SAPFOR::Argument* use) + const SAPFOR::Instruction* firstInstr = ir->getInstruction(); + SgStatement* stmt = firstInstr->getOperator(); + if (!stmt || isCompoundStmt(stmt)) { - if (!isTrackable(use)) - return; - const string k = argKey(use); - auto it = lastDef.find(k); - if (it == lastDef.end()) - return; - if (it->second.first && it->second.first != opStmt) - depsSets[opStmt].insert(it->second.first); + ++i; + continue; + } + + vector 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 usesVars; + set defsVars; + set usesMem; + set defsMem; + + vector 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 addMemDep = [&](const string& key) + auto joinIdx = [&](const vector& idx) -> string { - if (key.empty()) - return; - auto it = lastMemDef.find(key); - if (it == lastMemDef.end()) - return; - if (it->second.first && it->second.first != opStmt) - depsSets[opStmt].insert(it->second.first); + string s; + for (size_t k = 0; k < idx.size(); ++k) + { + if (k) + s += ","; + s += idx[k]; + } + return s; }; - addDep(instr->getArg1()); - addDep(instr->getArg2()); - if (instr->getOperation() == SAPFOR::CFG_OP::RANGE) - addDep(instr->getResult()); - - if (instr->getOperation() == SAPFOR::CFG_OP::STORE || instr->getOperation() == SAPFOR::CFG_OP::REC_REF_STORE) - addDep(instr->getResult()); - - if (instr->getOperation() == SAPFOR::CFG_OP::LOAD || instr->getOperation() == SAPFOR::CFG_OP::REC_REF_LOAD) + auto popLastIdx = [&](int cnt) -> vector { - const string memKey = memKeyFromInstr(instr); - addMemDep(memKey); - } + vector 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; + }; - if (isDef(instr)) + auto memKeyFromLoadStore = [&](const SAPFOR::Instruction* instr) -> string { - const string dk = argKey(instr->getResult()); - lastDef[dk] = { opStmt, instr->getResult() }; - } - - if (instr->getOperation() == SAPFOR::CFG_OP::STORE || instr->getOperation() == SAPFOR::CFG_OP::REC_REF_STORE) - { - const string k = memKeyFromInstr(instr); + if (!instr) + return string(); SAPFOR::Argument* base = instr->getArg1(); - if (!k.empty() && base) - lastMemDef[k] = { opStmt, base }; - addMemDep(k); + 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& 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; } }