From c43a59b48feb6144f04c1c33c69adf54ae48c2f0 Mon Sep 17 00:00:00 2001 From: jdh8d <jdh8d@git.zephyr-software.com> Date: Thu, 2 Jun 2016 20:14:26 +0000 Subject: [PATCH] Former-commit-id: 80b417a1a63d048050cb9a9c82edc51406d1d9e4 --- .gitattributes | 1 + libIRDB/src/cfg/domgraph.cpp | 310 +++++++++++++++++++++++++++++++++++ 2 files changed, 311 insertions(+) create mode 100644 libIRDB/src/cfg/domgraph.cpp diff --git a/.gitattributes b/.gitattributes index ce4a0f652..1b0c9c46b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -238,6 +238,7 @@ libIRDB/src/cfg/Makefile -text libIRDB/src/cfg/SConscript -text libIRDB/src/cfg/SConstruct -text libIRDB/src/cfg/callgraph.cpp -text +libIRDB/src/cfg/domgraph.cpp -text libIRDB/src/core/Makefile -text libIRDB/src/core/SConscript -text libIRDB/src/core/SConstruct -text diff --git a/libIRDB/src/cfg/domgraph.cpp b/libIRDB/src/cfg/domgraph.cpp new file mode 100644 index 000000000..9fafa6a61 --- /dev/null +++ b/libIRDB/src/cfg/domgraph.cpp @@ -0,0 +1,310 @@ + +#include <libIRDB-cfg.hpp> +#include <algorithm> +#include <utils.hpp> + + + +using namespace std; +using namespace libIRDB; + + +// constructor +DominatorGraph_t::DominatorGraph_t(const ControlFlowGraph_t* p_cfg, bool needs_postdoms, bool needs_idoms) + : cfg(*p_cfg) +{ + + + assert(needs_postdoms==false); + assert(needs_idoms==false); + + +// typedef const BasicBlockSet_t& (*) (const BasicBlock_t* node) pred_func_ptr_t; + pred_func_ptr_t func_get_predecessors=[](const BasicBlock_t* node) -> const BasicBlockSet_t& + { + return node->GetPredecessors(); + }; + pred_func_ptr_t func_get_successors=[](const BasicBlock_t* node) -> const BasicBlockSet_t& + { + return node->GetSuccessors(); + }; + + dom_graph=Dom_Comp(p_cfg->GetBlocks(), func_get_predecessors, p_cfg->GetEntry()); + idom_graph=Idom_Comp(p_cfg->GetBlocks(), dom_graph, p_cfg->GetEntry()); + +// a func may have multiple exit nodes. how do we deal with that? +// psuedo-block? invoke this for each exit block? +// post_dom_graph=Dom_Comp(p_cfg->GetBlocks(), func_get_successors, p_cfg->GetEntry()); +// post_idom_graph=IDom_Comp(p_cfg->GetBlocks(), post_dom_graph, p_cfg->GetEntry()); +} + + + + +/* + +algorithm from advanced compiler design & impelmentation, Mucnick, 2nd edition page 18 + +procedure Dom_Comp(N,Pred,r) returns Node-> set of Node + N: in set of Node + Pred: in Node -> set of Node + r: in Node + D, T: set of Node + n, p: Node + change := true: boolean + Domin: Node -> set of Node + Domin(r) := { r } + + for each n \in N - {r} do + Domin(n)={N} + od + repeat + change := false + for each n \in N - {r} do + + T := N + for each p \in Pred(n) do + T = T intersect Domin(p) + done + D = {n} union T + if D != Domin(n) then + change := true + Domin(n) := D + fi + done + until ! change + return Domin +end || Dom_Comp + +*/ + +DominatorMap_t DominatorGraph_t::Dom_Comp(const BasicBlockSet_t& N, pred_func_ptr_t get_preds, BasicBlock_t* r) +{ +/* + D, T: set of Node + n, p: Node + change := true: boolean + Domin: Node -> set of Node + Domin(r) := { r } +*/ + BasicBlockSet_t D, T; + BasicBlock_t* n=NULL, *p=NULL; + bool change=true; + DominatorMap_t Domin; + Domin[r].insert(r); + + BasicBlockSet_t NminusR=N; + NminusR.erase(r); + +/* + for each n \in N - {r} do + Domin(n)={N} + od +*/ + for_each( NminusR.begin(), NminusR.end(), [&](BasicBlock_t* n) + { + Domin[n]=N; + }); + +/* + repeat +*/ + do + { + change = false; + /* + for each n \in N - {r} do + */ + for_each(NminusR.begin(), NminusR.end(), [&](BasicBlock_t* n) + { + /* T := N */ + T=N; +/* + + for each p \in Pred(n) do + T = T intersect Domin(p) + done +*/ + for_each(get_preds(n).begin(), get_preds(n).end(), [&](const BasicBlock_t* p) + { + BasicBlockSet_t tmp; + set_intersection(T.begin(), T.end(), Domin[p].begin(), Domin[p].end(), inserter(tmp,tmp.begin())); + T=tmp; + + }); + /* + D = {n} union T + */ + D=T; + D.insert(n); + + /* + if D != Domin(n) then + change := true + Domin(n) := D + fi + */ + if(D != Domin[n]) + { + change=true; // keep trying + Domin[n]=D; + } + }); +/* + done + until ! change +*/ + } + while ( change ); + + +// log output +#if 0 + + for_each(N.begin(), N.end(), [&](const BasicBlock_t* blk) + { + assert(blk); + const BasicBlockSet_t& blk_dominates=Domin[blk]; + Instruction_t* first_insn=*(blk->GetInstructions().begin()); + assert(first_insn); +#if 1 + cout<<"\tBlock " <<endl<<*blk<<endl; + +#endif + cout<<"\t Dominated by:"<<endl; + for_each(blk_dominates.begin(), blk_dominates.end(), [&](const BasicBlock_t* dom_blk) + { + cout<<*dom_blk<<endl; + }); + }); +#endif + return Domin; +} + + + +/* algorith for constructing immediate dominators from Muchnick, page 184. + +procedure Idom_Comp(N,Domin,r) returns Node -> Node + N: in set of Node + Domin: in Node -> set of Node + r: in Node +begin + n, s, t: Node + Tmp: Node -> set of Node + IDom: Node->Node + for each n \in N do + Tmp(n) := Domin(n) - {n} + od + + for each n \in N - {r} do + for each s \in Tmp(n) do + for each t \in Tmp(n) - {s} do + if t \in Tmp(s) then + Tmp(n) -= {t} + fi + od + od + od + + for each n \in N-{r} do + IDom(n) = <only element in>Tmp(n) + od + return IDdom +end || IDom_Comp +*/ + + + +BlockToBlockMap_t DominatorGraph_t::Idom_Comp(const BasicBlockSet_t& N, const DominatorMap_t &Domin, BasicBlock_t* r) +{ + // n, s, t: Node + BasicBlock_t* n=NULL, *s=NULL, *t=NULL; + + // Tmp: Node -> set of Node + DominatorMap_t Tmp; + + // IDom: Node->Node + BlockToBlockMap_t IDom; + + + // calculate this set as we use it several times + BasicBlockSet_t NminusR = N; + NminusR.erase(r); + + + // for each n \in N do + for_each( N.begin(), N.end(), [&](BasicBlock_t* n) + { + //Tmp(n) := Domin(n) - {n} + Tmp[n] = Domin.at(n); + Tmp[n].erase(n); + // od + }); + + + //for each n \in N - {r} do + for_each( NminusR.begin(), NminusR.end(), [&]( BasicBlock_t* n) + { + // for each s \in Tmp(n) do + auto Tmp_n=Tmp[n]; + for_each( Tmp_n.begin(), Tmp_n.end(), [&]( BasicBlock_t* s) + { + + //for each t \in Tmp(n) - {s} do + for_each( Tmp_n.begin(), Tmp_n.end(), [&]( BasicBlock_t* t) + { + // quickly do Tmp(n)-s + if(t != s) + { + //if t \in Tmp(s) then + if( is_in_container(Tmp[s],t)) + { + //Tmp(n) -= {t} + Tmp[n].erase(t); + } + } + }); + }); + }); + + //for each n \in N-{r} do + for_each( NminusR.begin(), NminusR.end(), [&](BasicBlock_t* n) + { + //IDom(n) = <only element in>Tmp(n) + IDom[n]= *(Tmp[n].begin()); + assert(Tmp[n].size()<=1); // should only be one idominator. + }); + return IDom; +} // IDom_Comp + + + + +ostream& libIRDB::operator<<(ostream& os, const DominatorGraph_t& dg) +{ + for_each(dg.cfg.GetBlocks().begin(), dg.cfg.GetBlocks().end(), [&](const BasicBlock_t* blk) + { + assert(blk); + const BasicBlockSet_t& blk_dominates=dg.GetDominators(blk); + Instruction_t* first_insn=*(blk->GetInstructions().begin()); + assert(first_insn); + + os<<"\tBlock entry id:" <<blk->GetInstructions()[0]->GetBaseID()<<endl; + os<<"\t\tDominated by: "; + for_each(blk_dominates.begin(), blk_dominates.end(), [&os](const BasicBlock_t* dom) + { + os<<dom->GetInstructions()[0]->GetBaseID()<<", "; + }); + os<<endl; + + const BasicBlock_t* idom=dg.GetImmediateDominator(blk); + if(idom) + os<<"\t\tImmediate Dominator: "<<hex<<idom->GetInstructions()[0]->GetBaseID()<<endl; + else + os<<"\t\tNo Immed Dominator."<<endl; + + }); + + return os; +} -- GitLab