From 0896dd5cb9fe9aeff395bc2f97c6f0479ac095ca Mon Sep 17 00:00:00 2001 From: Jason Hiser <jdhiser@gmail.com> Date: Thu, 1 Aug 2019 11:22:50 -0400 Subject: [PATCH] added DFS api, used it to speed up dominator calculations --- irdb-libs/libIRDB-cfg/include/domgraph.hpp | 4 +- irdb-libs/libIRDB-cfg/src/SConscript | 2 +- irdb-libs/libIRDB-cfg/src/dfs.cpp | 49 +++++++++++++++++ irdb-libs/libIRDB-cfg/src/domgraph.cpp | 64 +++++++++++++--------- irdb-sdk | 2 +- 5 files changed, 91 insertions(+), 30 deletions(-) create mode 100644 irdb-libs/libIRDB-cfg/src/dfs.cpp diff --git a/irdb-libs/libIRDB-cfg/include/domgraph.hpp b/irdb-libs/libIRDB-cfg/include/domgraph.hpp index db37459ae..b7fb70b29 100644 --- a/irdb-libs/libIRDB-cfg/include/domgraph.hpp +++ b/irdb-libs/libIRDB-cfg/include/domgraph.hpp @@ -51,8 +51,8 @@ namespace libIRDB using pred_func_ptr_t = const IRDB_SDK::BasicBlockSet_t& (*) (const IRDB_SDK::BasicBlock_t* node); - DominatorMap_t Dom_Comp(const IRDB_SDK::BasicBlockSet_t& N, pred_func_ptr_t pred_func, IRDB_SDK::BasicBlock_t* r); - BlockToBlockMap_t Idom_Comp(const IRDB_SDK::BasicBlockSet_t& N, const DominatorMap_t &Domin, IRDB_SDK::BasicBlock_t* r); + DominatorMap_t Dom_Comp(const IRDB_SDK::BasicBlockVector_t& N, pred_func_ptr_t pred_func, IRDB_SDK::BasicBlock_t* r); + BlockToBlockMap_t Idom_Comp(const IRDB_SDK::BasicBlockVector_t& N, const DominatorMap_t &Domin, IRDB_SDK::BasicBlock_t* r); DominatorMap_t dom_graph; diff --git a/irdb-libs/libIRDB-cfg/src/SConscript b/irdb-libs/libIRDB-cfg/src/SConscript index cb08c53f8..17ecf7b52 100644 --- a/irdb-libs/libIRDB-cfg/src/SConscript +++ b/irdb-libs/libIRDB-cfg/src/SConscript @@ -8,7 +8,7 @@ myenv.Replace(SECURITY_TRANSFORMS_HOME=os.environ['SECURITY_TRANSFORMS_HOME']) libname="irdb-cfg" files= ''' - BasicBlock.cpp callgraph.cpp CFG.cpp domgraph.cpp criticaledge.cpp + BasicBlock.cpp callgraph.cpp CFG.cpp domgraph.cpp criticaledge.cpp dfs.cpp ''' cpppath=''' $IRDB_SDK/include/ diff --git a/irdb-libs/libIRDB-cfg/src/dfs.cpp b/irdb-libs/libIRDB-cfg/src/dfs.cpp new file mode 100644 index 000000000..b8d28a260 --- /dev/null +++ b/irdb-libs/libIRDB-cfg/src/dfs.cpp @@ -0,0 +1,49 @@ + + +#include <irdb-core> +#include <irdb-cfg> +#include <vector> + +using namespace IRDB_SDK; + +using VisitedMap_t = map<BasicBlock_t*,bool> ; + +static void doDFS(BasicBlockVector_t &order, VisitedMap_t &visited, BasicBlock_t* node) +{ + // visit this node + visited[node]=true; + order.push_back(node); + + // visit each successor + for(auto successor : node->getSuccessors()) + { + if(!visited[successor]) + doDFS(order,visited,successor); + } + +} + +BasicBlockVector_t IRDB_SDK::getDFSOrder(ControlFlowGraph_t* cfg) +{ + assert(cfg!=nullptr); + + auto ret = BasicBlockVector_t(); + ret.reserve(cfg->getBlocks().size()); + auto visited = VisitedMap_t(); + + // explicitly fill the map with falses. + for(auto& node : cfg->getBlocks()) + visited[node]=false; + + doDFS(ret,visited,cfg->getEntry()); + + // for each node in the map + for(auto &p : visited) + // if it's not visited + if(p.second == false) + // that means it appeared unreachable from the entry block + // add it to the dfs end. + ret.push_back(p.first); + + return move(ret); +} diff --git a/irdb-libs/libIRDB-cfg/src/domgraph.cpp b/irdb-libs/libIRDB-cfg/src/domgraph.cpp index 36a10b4ce..204ab0d81 100644 --- a/irdb-libs/libIRDB-cfg/src/domgraph.cpp +++ b/irdb-libs/libIRDB-cfg/src/domgraph.cpp @@ -44,20 +44,18 @@ inline S const& find_map_object( const std::map< T , S > &a_map, const T& key) DominatorGraph_t::DominatorGraph_t(const ControlFlowGraph_t* p_cfg, bool needs_postdoms, bool needs_idoms) : cfg(*p_cfg), warn(false) { - auto &blocks=p_cfg->getBlocks(); - - assert(needs_postdoms==false); assert(needs_idoms==false); + const auto dfs_order = getDFSOrder(const_cast<ControlFlowGraph_t*>(p_cfg)); pred_func_ptr_t func_get_predecessors=[](const IRDB_SDK::BasicBlock_t* node) -> const IRDB_SDK::BasicBlockSet_t& { return node->getPredecessors(); }; - dom_graph=Dom_Comp(blocks, func_get_predecessors, p_cfg->getEntry()); - idom_graph=Idom_Comp(blocks, dom_graph, p_cfg->getEntry()); + dom_graph = Dom_Comp(dfs_order, func_get_predecessors, p_cfg->getEntry()); + idom_graph = Idom_Comp(dfs_order, dom_graph, p_cfg->getEntry()); Dominated_Compute(); @@ -111,7 +109,7 @@ end || Dom_Comp */ -DominatorMap_t DominatorGraph_t::Dom_Comp(const IRDB_SDK::BasicBlockSet_t& N, pred_func_ptr_t get_preds, IRDB_SDK::BasicBlock_t* r) +DominatorMap_t DominatorGraph_t::Dom_Comp(const IRDB_SDK::BasicBlockVector_t& N, pred_func_ptr_t get_preds, IRDB_SDK::BasicBlock_t* r) { /* D, T: set of Node @@ -125,17 +123,15 @@ DominatorMap_t DominatorGraph_t::Dom_Comp(const IRDB_SDK::BasicBlockSet_t& N, pr DominatorMap_t Domin; Domin[r].insert(r); - IRDB_SDK::BasicBlockSet_t NminusR=N; - NminusR.erase(r); - /* for each n \in N - {r} do Domin(n)={N} od */ - for( auto n : NminusR) + for( const auto &n : N) { - Domin[n]=N; + if(n==r) continue; + Domin[n]=IRDB_SDK::BasicBlockSet_t(ALLOF(N)); }; /* @@ -147,17 +143,18 @@ DominatorMap_t DominatorGraph_t::Dom_Comp(const IRDB_SDK::BasicBlockSet_t& N, pr /* for each n \in N - {r} do */ - for( auto n : NminusR) + for( const auto &n : N) { + if(n == r) continue; /* T := N */ - T=N; + T = IRDB_SDK::BasicBlockSet_t(ALLOF(N)); /* for each p \in Pred(n) do T = T intersect Domin(p) done */ - for(auto p : get_preds(n) ) + for(const auto &p : get_preds(n) ) { IRDB_SDK::BasicBlockSet_t tmp; set_intersection(T.begin(), T.end(), Domin[p].begin(), Domin[p].end(), inserter(tmp,tmp.begin())); @@ -248,21 +245,20 @@ end || IDom_Comp -BlockToBlockMap_t DominatorGraph_t::Idom_Comp(const IRDB_SDK::BasicBlockSet_t& N, const DominatorMap_t &Domin, IRDB_SDK::BasicBlock_t* r) +BlockToBlockMap_t DominatorGraph_t::Idom_Comp(const IRDB_SDK::BasicBlockVector_t& N, const DominatorMap_t &Domin, IRDB_SDK::BasicBlock_t* r) { // n, s, t: Node - //BasicBlock_t* n=NULL, *s=NULL, *t=NULL; + const auto verbose=false; // Tmp: Node -> set of Node - DominatorMap_t Tmp; + auto Tmp = DominatorMap_t(); // IDom: Node->Node - BlockToBlockMap_t IDom; - + auto IDom = BlockToBlockMap_t() ; - // calculate this set as we use it several times - IRDB_SDK::BasicBlockSet_t NminusR = N; - NminusR.erase(r); + auto tmp_n_total_size = 0u; + auto inner_total = 0u; + auto inner_checks = 0u; // for each n \in N do @@ -271,15 +267,22 @@ BlockToBlockMap_t DominatorGraph_t::Idom_Comp(const IRDB_SDK::BasicBlockSet_t& N //Tmp(n) := Domin(n) - {n} Tmp[n] = Domin.at(n); Tmp[n].erase(n); + tmp_n_total_size += Tmp[n].size(); // od - }; + } + + if(verbose) + cout << "Average size of Tmp[n] = " << tmp_n_total_size / Tmp.size() << endl; //for each n \in N - {r} do - for(auto n : NminusR) + for(auto n : N) { + if( n == r) continue; + // for each s \in Tmp(n) do auto Tmp_n=Tmp[n]; + // for_each( Tmp_n.begin(), Tmp_n.end(), [&]( BasicBlock_t* s) for (auto s : Tmp_n) { @@ -292,20 +295,29 @@ BlockToBlockMap_t DominatorGraph_t::Idom_Comp(const IRDB_SDK::BasicBlockSet_t& N if(t != s) { //if t \in Tmp(s) then + inner_checks ++; if( is_in_container(Tmp[s],t)) { //Tmp(n) -= {t} - Tmp[n].erase(t); + Tmp[n].erase(t); + inner_total ++; } } }; }; }; + if(verbose) + { + cout << "Inner checks = " << inner_checks << endl; + cout << "Inner total = " << inner_total << endl; + } //for each n \in N-{r} do - for (auto n : NminusR) + for (auto n : N) { + if(n == r) continue; + //IDom(n) = <only element in>Tmp(n) IDom[n]= *(Tmp[n].begin()); if(Tmp[n].size()!=1) // should only be one idominator. diff --git a/irdb-sdk b/irdb-sdk index 3267ac263..f2ad120cb 160000 --- a/irdb-sdk +++ b/irdb-sdk @@ -1 +1 @@ -Subproject commit 3267ac26338c701dffa3267da6c6ca15475b4999 +Subproject commit f2ad120cbf9fa7d965288472b67cecb197bb5a12 -- GitLab