diff --git a/src/CFGraph/CFGraph.h b/src/CFGraph/CFGraph.h index 319b420..cdb190b 100644 --- a/src/CFGraph/CFGraph.h +++ b/src/CFGraph/CFGraph.h @@ -24,7 +24,7 @@ namespace SAPFOR std::vector next; std::vector prev; - + BasicBlock* idom{}; //reaching definition std::map> RD_in, RD_out; @@ -42,6 +42,7 @@ namespace SAPFOR void addInstruction(IR_Block* item); void addPrev(BasicBlock* prev_) { prev.push_back(prev_); } void addNext(BasicBlock* next_) { next.push_back(next_); } + void setIdom(BasicBlock* idom_) { idom = idom_; } int removePrev(BasicBlock* removed); int removeNext(BasicBlock* removed); @@ -69,7 +70,8 @@ namespace SAPFOR const std::vector& getInstructions() const { return instructions; } const std::vector& getNext() const { return next; } const std::vector& getPrev() const { return prev; } - + BasicBlock* getIdom() const { return idom; } + /* * FOR LIVE ANALYSIS */ @@ -146,4 +148,4 @@ static inline void deleteCFG(std::map + +using namespace std; + +namespace SAPFOR { +class DominatorFinder { +private: + BasicBlock* entry; + std::vector vertices; + std::unordered_map dfs_num; + std::vector parent, semi, vertex, ancestor, label; + std::vector> bucket; + int n; + + void DFS(BasicBlock* v, int parent_num) { + dfs_num[v] = n; + vertex[n] = n; + semi[n] = n; + label[n] = n; + ancestor[n] = -1; + parent[n] = parent_num; + vertices[n++] = v; + + for (const auto& w : v->getNext()) { + if (dfs_num[w] == -1) { + DFS(w, dfs_num[v]); + } + } + } + + void Compress(int v) { + if (ancestor[ancestor[v]] != -1) { + Compress(ancestor[v]); + if (semi[label[ancestor[v]]] < semi[label[v]]) + label[v] = label[ancestor[v]]; + ancestor[v] = ancestor[ancestor[v]]; + } + } + + int Eval(int v) { + if (ancestor[v] == -1) return v; + Compress(v); + return label[v]; + } + + void Link(int v, int w) { + ancestor[w] = v; + } + +public: + DominatorFinder(std::vector& blocks) { + if (blocks.empty()) return; + entry = blocks[0]; + n = 0; + + for (auto block : blocks) dfs_num[block] = -1; + + int max_size = blocks.size(); + vertices.resize(max_size); + parent.assign(max_size, -1); + semi.assign(max_size, -1); + vertex.assign(max_size, -1); + ancestor.assign(max_size, -1); + label.assign(max_size, -1); + bucket.resize(max_size); + + DFS(entry, -1); + + for (int i = n - 1; i > 0; --i) { + int w = vertex[i]; + + for (BasicBlock* v : vertices[w]->getPrev()) { + int u = Eval(dfs_num[v]); + if (semi[u] < semi[w]) + semi[w] = semi[u]; + } + bucket[vertex[semi[w]]].push_back(w); + Link(parent[w], w); + + for (int v : bucket[parent[w]]) + { + int u = Eval(v); + if (semi[u] < semi[v]) + vertices[v]->setIdom(vertices[u]); + else + vertices[v]->setIdom(vertices[parent[w]]); + } + bucket[parent[w]].clear(); + } + + for (int i = 1; i < n; ++i) { + int w = vertex[i]; + if (vertices[w]->getIdom() != vertices[vertex[semi[w]]]) + vertices[w]->setIdom(vertices[w]->getIdom()->getIdom()); + } + + entry->setIdom(nullptr); + } +}; + +void buildDominatorTreeLT(std::vector& blocks) { + DominatorFinder finder(blocks); +} + +} diff --git a/src/ProjectParameters/projectParameters.cpp b/src/ProjectParameters/projectParameters.cpp index 7ac33d0..4a5f5c6 100644 --- a/src/ProjectParameters/projectParameters.cpp +++ b/src/ProjectParameters/projectParameters.cpp @@ -1,10 +1,10 @@ -#include #include #include #include #include #include #include +#include #include #include #include @@ -20,14 +20,43 @@ #include "libSage++.h" #include "projectParameters.h" +#include "domTree.h" using namespace std; +tuple stmtToIR(const map>& CFGraph, SgStatement* stmt) +{ + SgStatement* cur = stmt; + while (cur->variant() != PROC_HEDR && cur->variant() != PROG_HEDR && cur->variant() != FUNC_HEDR) + cur = cur->controlParent(); + + string funcName = ((SgProcHedrStmt*)cur)->nameWithContains(); + + int stmtID = stmt->id(); + for (const auto& [func, bblocks] : CFGraph) + { + if (func->funcName != funcName) + continue; + + for (auto basicBlock : bblocks) + for (auto ins : basicBlock->getInstructions()) + if (stmtID == ins->getInstruction()->getOperator()->id()) + return make_tuple(func, ins->getInstruction(), basicBlock); + } + + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + return { NULL, NULL, NULL }; +} + template -static void processArgument(set& worklist, SAPFOR::Argument* arg, Iterator instr, Iterator first_instr) { +static void processArgument(set& worklist, + SAPFOR::Argument* arg, + Iterator instr, + Iterator first_instr) +{ if (arg == NULL) return; - if (arg->getType() == SAPFOR::CFG_ARG_TYPE::REG) + if (arg->getType() == SAPFOR::CFG_ARG_TYPE::REG) extract_vars_from_reg(worklist, arg, instr, first_instr); else if (arg->getType() == SAPFOR::CFG_ARG_TYPE::VAR && arg->getMemType() == SAPFOR::CFG_MEM_TYPE::LOCAL_) { @@ -37,9 +66,14 @@ static void processArgument(set& worklist, SAPFOR::Argument* } template -void extract_vars_from_reg(set& worklist, SAPFOR::Argument* reg, Iterator instr, Iterator first_instr) { - for (; instr >= first_instr; instr--) { - if ((*instr)->getInstruction()->getResult() == reg) +static void extract_vars_from_reg(set& worklist, + SAPFOR::Argument* reg, + Iterator instr, + Iterator first_instr) +{ + for (; instr >= first_instr; instr--) + { + if ((*instr)->getInstruction()->getResult() == reg) { processArgument(worklist, (*instr)->getInstruction()->getArg1(), instr, first_instr); processArgument(worklist, (*instr)->getInstruction()->getArg2(), instr, first_instr); @@ -48,14 +82,14 @@ void extract_vars_from_reg(set& worklist, SAPFOR::Argument* r } } -static void lookup_for_vars(ResultSet& result_set, +static void lookup_for_vars(std::map& where_to_add, set& worklist, SAPFOR::Instruction* instr, SAPFOR::BasicBlock* bblock, const std::map>& fullIR) { std::cout << "Lookup in bblock no." << bblock->getNumber() << std::endl; //DEBUG PRINT - + auto first_instr = bblock->getInstructions().begin(); auto cur_instr = std::find_if(first_instr, bblock->getInstructions().end(), [instr](SAPFOR::IR_Block* i) { return i->getInstruction() == instr; @@ -63,7 +97,7 @@ static void lookup_for_vars(ResultSet& result_set, for (; cur_instr >= bblock->getInstructions().begin(); cur_instr--) { - auto instr = (*cur_instr)->getInstruction(); + auto instr = (*cur_instr)->getInstruction(); auto result_arg = instr->getResult(); auto arg1 = instr->getArg1(); auto arg2 = instr->getArg2(); @@ -75,37 +109,37 @@ static void lookup_for_vars(ResultSet& result_set, std::cout << "worklist erase: " << result_arg->getValue() << std::endl; //DEBUG PRINT worklist.erase(result_arg); } - if (instr->getOperation() == SAPFOR::CFG_OP::PARAM && worklist.count(arg1)) + if (instr->getOperation() == SAPFOR::CFG_OP::PARAM && worklist.count(arg1)) { // skip to F_CALL auto f_call_instr = cur_instr; while ((*f_call_instr)->getInstruction()->getOperation() != SAPFOR::CFG_OP::F_CALL) f_call_instr++; - if ((*f_call_instr)->getInstruction()->getArg1()->getValue() == "_READ") + if ((*f_call_instr)->getInstruction()->getArg1()->getValue() == "_READ") { - auto filename = (*f_call_instr)->getInstruction()->getOperator()->fileName(); - auto line = (*f_call_instr)->getInstruction()->getOperator()->lineNumber(); + auto stmt_before = (*f_call_instr)->getInstruction()->getOperator(); + auto filename = stmt_before->fileName(); + auto line = stmt_before->lineNumber(); + auto var_name = arg1->getValue().substr(arg1->getValue().find('%') + 1); __spf_print(1,"Please specify value of variable %s on line %d of file %s", arg1->getValue().c_str(), line, filename); - result_set.insert(make_tuple(filename, line, arg1->getValue())); - + where_to_add[stmt_before] = var_name; std::cout << "worklist erase: " << arg1->getValue() << std::endl; //DEBUG PRINT worklist.erase(arg1); - } else + } else { //check if variable is modified in called function } } } - const auto& RD = bblock->getRD_In(); map group_by_block; - for (auto& arg : worklist) + for (auto& arg : worklist) { if (RD.count(arg)) { - if (RD.at(arg).size() == 0) + if (RD.at(arg).size() == 1 && *RD.at(arg).begin() == SAPFOR::CFG_VAL::UNINIT) __spf_print(1, "variable %s has no definition", arg->getValue().c_str()); else if (RD.at(arg).size() > 1) __spf_print(1, "variable %s has multiple reaching definitions, further analysis is impossible", arg->getValue().c_str()); @@ -114,24 +148,31 @@ static void lookup_for_vars(ResultSet& result_set, for (const auto& instr_num : RD.at(arg)) { auto [instr, bblock] = getInstructionAndBlockByNumber(fullIR, instr_num); - if (group_by_block[bblock] == NULL || group_by_block[bblock]->getNumber() < instr_num) + if (group_by_block[bblock] == NULL || group_by_block[bblock]->getNumber() < instr_num) group_by_block[bblock] = instr; } } } } - for (const auto& [bblock, instr] : group_by_block) + auto idom = bblock->getIdom(); + while (idom != NULL) { - lookup_for_vars(result_set, worklist, instr, bblock, fullIR); + if (group_by_block.count(idom)) + { + lookup_for_vars(where_to_add, worklist, group_by_block[idom], idom, fullIR); + return; + } + idom = idom->getIdom(); } } -static void handle_single_allocate(ResultSet& result_set, - SAPFOR::Instruction* instr, - SAPFOR::BasicBlock* bblock, +static void handle_single_allocate(std::map& where_to_add, + SgStatement* alloc_statement, const std::map>& fullIR) -{ +{ + auto [func, instr, bblock] = stmtToIR(fullIR, alloc_statement); + auto first_instr = bblock->getInstructions().begin(); auto cur_instr = std::find_if(first_instr, bblock->getInstructions().end(), [instr](SAPFOR::IR_Block* i) { return i->getInstruction() == instr; @@ -140,7 +181,7 @@ static void handle_single_allocate(ResultSet& result_set, // skip to F_CALL _ALLOC n while ((*alloc_instr)->getInstruction()->getOperation() != SAPFOR::CFG_OP::F_CALL || - (*alloc_instr)->getInstruction()->getArg1()->getValue() != "_ALLOC") + (*alloc_instr)->getInstruction()->getArg1()->getValue() != "_ALLOC") { alloc_instr++; } @@ -161,11 +202,11 @@ static void handle_single_allocate(ResultSet& result_set, } auto dimensions_num = stoi((*param_instr)->getInstruction()->getArg2()->getValue()); - + for (int j = 0; j < dimensions_num; j++) { auto ref_instr = --param_instr; - + auto arg = (*ref_instr)->getInstruction()->getArg1(); if (arg->getType() == SAPFOR::CFG_ARG_TYPE::REG) { @@ -178,33 +219,107 @@ static void handle_single_allocate(ResultSet& result_set, } } } - lookup_for_vars(result_set,worklist, instr, bblock, fullIR); + lookup_for_vars(where_to_add,worklist, instr, bblock, fullIR); } -ResultSet -findParameters(const std::map>& fullIR, +static void handle_single_loop(std::map& where_to_add, + SgStatement* loop_stmt, + const std::map>& fullIR) +{ + auto [func_name, instr, bblock] = stmtToIR(fullIR, loop_stmt); + std::cout << "bblock: " << bblock->getNumber() << " instr: " << instr->getNumber() << std::endl; + + auto cur_instr = bblock->getInstructions().end() - 1; + + set worklist; + extract_vars_from_reg(worklist, (*cur_instr)->getInstruction()->getResult(), cur_instr, bblock->getInstructions().begin()); + + lookup_for_vars(where_to_add, worklist, (*cur_instr)->getInstruction(), bblock, fullIR); +} + +void +findParameters(ResultSet& foundParameters, + std::map>& fullIR, const std::map, std::pair>& declaredArrays) { - ResultSet foundParameters; + map where_to_add; + + map name_to_func; + for (const auto& [func, _] : fullIR) + name_to_func[func->funcName] = func; + + map> call_sites; + for (auto& [func, bblocks] : fullIR) + { + for (const auto& block : bblocks) + { + for (const auto& ir_block : block->getInstructions()) + { + auto instr = ir_block->getInstruction(); + if (instr->getOperation() == SAPFOR::CFG_OP::F_CALL) + { + auto func_name = instr->getArg1()->getValue(); + auto func_info = name_to_func.find(func_name); + + if (func_info != name_to_func.end()) + call_sites[func_info->second].push_back(instr); + } + } + } + + SAPFOR::buildDominatorTreeLT(bblocks); + for (auto block : bblocks) + { + if (block->getIdom() != NULL) + std::cout << "BB: " << block->getNumber() << " IDOM: " << block->getIdom()->getNumber() << std::endl; + } + std::cout << "+++++++++++\n"; + } + std::set alloc_statements; - for (const auto& elem : declaredArrays) + for (const auto& elem : declaredArrays) { const auto& array = elem.second.first; - assert(array->GetLocation().first == Distribution::arrayLocation::l_LOCAL); // v0.1 - SgSymbol* arraySymb = array->GetDeclSymbol()->GetOriginal(); SgStatement* decl = declaratedInStmt(arraySymb); - for (auto &stmt : getAttributes(decl, set{ ALLOCATE_STMT })) - { + + for (auto& stmt : getAttributes(decl, set{ ALLOCATE_STMT })) alloc_statements.insert(stmt); - } } - + for (const auto& alloc_statement : alloc_statements) { - auto [instr, bblock] = getInstructionAndBlockByStatement(fullIR, alloc_statement); - ResultSet result_set; - handle_single_allocate(result_set, instr, bblock, fullIR); + handle_single_allocate(where_to_add, alloc_statement, fullIR); + } + + set for_statements; + // Find all FOR statements in the program + for (const auto& [func, bblocks] : fullIR) + for (const auto& block : bblocks) + for (auto instr = block->getInstructions().begin(); instr != block->getInstructions().end(); ++instr) + { + auto op = (*instr)->getInstruction()->getOperator(); + if (op && op->variant() == FOR_NODE) { + std::cout << block->getNumber() << std::endl; + for_statements.insert(op); + } + } + + for (const auto& stmt : for_statements) + { + handle_single_loop(where_to_add, stmt, fullIR); + } + + for (const auto& [stmt_before, var_name] : where_to_add) + { + // SgVariableSymb* var_symb = new SgVariableSymb(var_name.c_str()); + // SgVarRefExp* var = new SgVarRefExp(var_symb); + // SgValueExp* zero = new SgValueExp(0); + // SgExprListExp* ex = new SgExprListExp(); + // ex->setLhs(new SgExpression(ASSGN_OP, var, zero)); + // SgStatement* toAdd = new SgStatement(SPF_PARAMETER_OP, NULL, NULL, ex, NULL, NULL); + // stmt_before->insertStmtAfter(*toAdd, *stmt_before->controlParent()); + + foundParameters.insert(make_tuple(stmt_before->fileName(), stmt_before->lineNumber(), var_name)); } - return foundParameters; } diff --git a/src/ProjectParameters/projectParameters.h b/src/ProjectParameters/projectParameters.h index 25e32e4..36547b7 100644 --- a/src/ProjectParameters/projectParameters.h +++ b/src/ProjectParameters/projectParameters.h @@ -1,5 +1,6 @@ #pragma once +#include "libSage++.h" #include #include #include @@ -7,18 +8,25 @@ using ResultSet = std::set>; template -void extract_vars_from_reg(std::set& worklist, SAPFOR::Argument* reg, Iterator instr, Iterator first_instr); +static void extract_vars_from_reg(std::set& worklist, + SAPFOR::Argument* reg, + Iterator instr, + Iterator first_instr); template -static void processArgument(std::set& worklist, SAPFOR::Argument* arg, Iterator instr, Iterator first_instr); +static void processArgument(std::set& worklist, + SAPFOR::Argument* arg, + Iterator instr, + Iterator first_instr); -static void lookup_for_vars(ResultSet& result_set, +static void lookup_for_vars(std::map& where_to_add, std::set& worklist, SAPFOR::Instruction* instr, SAPFOR::BasicBlock* bblock, const std::map>& fullIR); -ResultSet -findParameters(const std::map>& fullIR, +void +findParameters(ResultSet& foundParameters, + std::map>& fullIR, const std::map, std::pair>& declaredArrays); diff --git a/src/Sapfor.cpp b/src/Sapfor.cpp index f2e9a74..38baba3 100644 --- a/src/Sapfor.cpp +++ b/src/Sapfor.cpp @@ -1882,9 +1882,7 @@ static bool runAnalysis(SgProject &project, const int curr_regime, const bool ne runRenameSymbols(&project, commonBlocks); else if (curr_regime == FIND_PARAMETERS) { - performRDSubst(fullIR, commonBlocks, &project); - parametersOfProject = findParameters(fullIR, declaredArrays); - performRDSubst(fullIR, commonBlocks, &project); + findParameters(parametersOfProject, fullIR, declaredArrays); } else if (curr_regime == BUILD_IR) {