#include #include #include #include #include #include "../Utils/errors.h" #include "../Utils/SgUtils.h" #include "../GraphCall/graph_calls.h" #include "../GraphCall/graph_calls_func.h" #include "../CFGraph/CFGraph.h" #include "../CFGraph/IR.h" #include "../GraphLoop/graph_loops.h" #include "swapOperators.h" using namespace std; unordered_set loop_tags = {FOR_NODE/*, FORALL_NODE, WHILE_NODE, DO_WHILE_NODE*/}; vector findInstructionsFromOperator(SgStatement* st, vector Blocks) { vector result; string filename = st -> fileName(); for (auto& block: Blocks) { vector instructionsInBlock = block -> getInstructions(); for (auto& instruction: instructionsInBlock) { SgStatement* curOperator = instruction -> getInstruction() -> getOperator(); if (curOperator -> lineNumber() == st -> lineNumber()) result.push_back(instruction); } } return result; } vector findFuncBlocksByFuncStatement(SgStatement *st, std::map>& FullIR) { vector result; Statement* forSt = (Statement*)st; for (auto& func : FullIR) { if (func.first -> funcPointer -> getCurrProcessFile() == forSt -> getCurrProcessFile() && func.first -> funcPointer -> lineNumber() == forSt -> lineNumber()) result = func.second; } return result; } map> findAndAnalyzeLoops(SgStatement *st, vector blocks) { map> result; SgStatement *lastNode = st->lastNodeOfStmt(); while (st && st != lastNode) { if (loop_tags.find(st -> variant()) != loop_tags.end()) { // part with find statements of loop SgForStmt *forSt = (SgForStmt*)st; SgStatement *loopBody = forSt -> body(); SgStatement *lastLoopNode = st->lastNodeOfStmt(); // part with find blocks and instructions of loops unordered_set blocks_nums; while (loopBody && loopBody != lastLoopNode) { SAPFOR::IR_Block* IR = findInstructionsFromOperator(loopBody, blocks).front(); 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(); } std::sort(result[forSt].begin(), result[forSt].end()); } st = st -> lexNext(); } return result; } map> AnalyzeLoopAndFindDeps(SgForStmt* forStatement, vector loopBlocks, map>& FullIR) { map> result; for (SAPFOR::BasicBlock* bb: loopBlocks) { std::map> blockReachingDefinitions = bb -> getRD_In(); vector instructions = bb -> getInstructions(); for (SAPFOR::IR_Block* irBlock: instructions) { // TODO: Think about what to do with function calls and array references. Because there are also dependencies there that are not reflected in RD, but they must be taken into account SAPFOR::Instruction* instr = irBlock -> getInstruction(); result[instr -> getOperator()]; // take Argument 1 and it's RD and push operators to final set if (instr -> getArg1() != NULL) { SAPFOR::Argument* arg = instr -> getArg1(); set prevInstructionsNumbers = blockReachingDefinitions[arg]; for (int i: prevInstructionsNumbers) { SAPFOR::Instruction* foundInstruction = getInstructionAndBlockByNumber(FullIR, i).first; if (foundInstruction != NULL) { SgStatement* prevOp = foundInstruction -> getOperator(); if (prevOp != forStatement && instr -> getOperator() != forStatement && instr -> getOperator() -> lineNumber() > prevOp -> lineNumber()) result[instr -> getOperator()].insert(prevOp); } } } // take Argument 2 (if exists) and it's RD and push operators to final set if (instr -> getArg2() != NULL) { SAPFOR::Argument* arg = instr -> getArg2(); set prevInstructionsNumbers = blockReachingDefinitions[arg]; for (int i: prevInstructionsNumbers) { SAPFOR::Instruction* foundInstruction = getInstructionAndBlockByNumber(FullIR, i).first; if (foundInstruction != NULL) { SgStatement* prevOp = foundInstruction -> getOperator(); if (prevOp != forStatement && instr -> getOperator() != forStatement && instr -> getOperator() -> lineNumber() > prevOp -> lineNumber()) result[instr -> getOperator()].insert(prevOp); } } } // update RD if (instr -> getResult() != NULL) blockReachingDefinitions[instr -> getResult()] = {instr -> getNumber()}; } } return result; } // int PrintSmthFromLoop(int firstLine, int lastLine, map> moveRules) { // // only cout done yet (( // cout << "LOOP ANALYZE FROM " << firstLine << " TO " << lastLine << " RES\n" << endl; // for (auto r: moveRules) { // cout << "OPERATOR: " << endl; // cout << r.first -> lineNumber() << r.first -> sunparse(); // cout << "DEPENDS FROM NEXT: " << endl; // for (SgStatement* st: r.second) // cout << st -> lineNumber() << endl; // } // cout << "\n\n\n"; // return 0; // } void GenNodesOfGraph( const map>& dependencies, set& allNodes, map>& outEdges, map>& inEdges) { for (const auto& node: dependencies) { SgStatement* u = node.first; allNodes.insert(u); for (SgStatement* v: node.second) { allNodes.insert(v); outEdges[v].insert(u); inEdges[u].insert(v); outEdges[u]; inEdges[v]; } outEdges[u]; inEdges[u]; } } vector> FindLinksInGraph( const set& allNodes, const map>& outEdges, const map>& inEdges) { set visited; vector> components; for (SgStatement* v: allNodes) { if (visited.count(v)) { continue; } set component; queue q; q.push(v); visited.insert(v); while (!q.empty()) { SgStatement* curr = q.front(); q.pop(); component.insert(curr); for (SgStatement* neighbour: outEdges.at(curr)) { if (!visited.count(neighbour)) { q.push(neighbour); visited.insert(neighbour); } } for (SgStatement* neighbour: inEdges.at(curr)) { if (!visited.count(neighbour)) { q.push(neighbour); visited.insert(neighbour); } } } components.push_back(component); } return components; } vector SortComponent( const set& component, const map>& outEdges, const map>& inEdges) { map inDegree; for (auto v: component) { inDegree[v] = inEdges.at(v).size(); } queue q; for (auto v : component) { if (inDegree[v] == 0) q.push(v); } vector result; while (!q.empty()) { auto curr = q.front(); q.pop(); result.push_back(curr); for (SgStatement* neighbour: outEdges.at(curr)) { if (component.count(neighbour)) { inDegree[neighbour]--; if (inDegree[neighbour] == 0) { q.push(neighbour); } } } } return result; } vector SortNoInterleaving(const map>& dependencies) { set allNodes; map> outEdges, inEdges; GenNodesOfGraph(dependencies, allNodes, outEdges, inEdges); auto components = FindLinksInGraph(allNodes, outEdges, inEdges); vector totalOrder; for (auto& comp : components) { auto part = SortComponent(comp, outEdges, inEdges); totalOrder.insert(totalOrder.end(), part.begin(), part.end()); } return totalOrder; } void runSwapOperators(SgFile *file, std::map>& loopGraph, std::map>& FullIR, int& countOfTransform) { std::cout << "SWAP_OPERATORS Pass" << std::endl; // to remove countOfTransform += 1; // to remove const int funcNum = file->numberOfFunctions(); for (int i = 0; i < funcNum; ++i) { SgStatement *st = file->functions(i); vector blocks = findFuncBlocksByFuncStatement(st, FullIR); map> loopsMapping = findAndAnalyzeLoops(st, blocks); for (pair> loopForAnalyze: loopsMapping) { map> dependencyGraph = AnalyzeLoopAndFindDeps(loopForAnalyze.first, loopForAnalyze.second, FullIR); // TODO: Write a function that will go through the operators and update all dependencies so that there are no mix-ups and splits inside the semantic blocks (for if, do and may be some other cases) cout << "\n\n"; for (auto v: dependencyGraph) { cout << "OPERATOR: " << v.first -> lineNumber() << "\nDEPENDS ON:" << endl; for (auto vv: v.second) { cout << vv -> lineNumber() << " "; } cout << endl; } if (dependencyGraph.size() != 0) { int firstLine = loopForAnalyze.first -> lineNumber(); int lastLine = loopForAnalyze.first -> lastNodeOfStmt() -> lineNumber(); // countOfTransform += PrintSmthFromLoop(firstLine, lastLine, dependencyGraph); vector new_order = SortNoInterleaving(dependencyGraph); cout << "\n\nLOOP ANALYZE FROM " << firstLine << " TO " << lastLine << " RES\n" << endl; for (auto v: new_order) if (v -> lineNumber() > firstLine) cout << v -> lineNumber() << " "; } } } return; };