dsa算法(26)

1.3.10. EquivBUDataStructures遍

EquivBUDataStructures是CompleteBUDataStructures的更进一步,它会为每个函数同类集产生一个简并的函数图,并以这个简并图作为同类集中每个函数的图。然后在此基础上,在前面CompleteDataStructure遍产生的调用链SCC上进行函数图内联。由此,函数图的个数,进而DSNode节点的个数将进一步减少。注意,这里的同类集不是调用链同类集,而是内存对象同类集(即由同一个DSNode代表)。

 

42      bool EquivBUDataStructures::runOnModule(Module&M) {

43        init(&getAnalysis<CompleteBUDataStructures>(),true, true, false, true);

44     

45        //make a list ofall the DSGraphs

46        std::set<DSGraph *>graphList;

47        for(Module::iteratorF = M.begin(); F != M.end(); ++F)

48        {

49          if(!(F->isDeclaration()))

50            graphList.insert(getOrCreateGraph(F));

51        }

52     

53        //update the EQclass from indirect calls

54        buildIndirectFunctionSets();

55        formGlobalECs();

56        mergeGraphsByGlobalECs();

 

EquivBUDataStructures前面的几步与CompleteBUDataStructures的前几步是一样的。不过这些操作是在CompleteBUDataStructures处理的结果上进行的。上面55行对最新的处理结果更新了同类集关系,56行的mergeGraphsByGlobalECs将函数同类集的图进行简并。

GlobalECs是一个同类集的容器,下面140及141行分别返回这个集合的首尾迭代器。142行的循环遍历这个集合,146行筛选掉不是Leader的成员。154行的member_iterator用于遍历某一个Leader所在的同类集(Leader总是这个同类集的首元素),155行就是遍历这个集合。这里的同类集由同一块内存所代表的对象组成,156行筛选出Function(函数)类型的对象。这里只处理函数的同类集。

对于某个同类集,176行的BaseGraph在一开始为0(147行处赋值),177、178行获取对应的DSGraph及指向返回值、可变参数、指针参数的DSNodeHandle节点。如果函数已经处理过,满足179行条件,我们需要简并这两次(甚至可能更多次)给出的参数,因为这两(几)次给出的参数的数目不一定相同,需要形如202~207行的处理。如果BaseGraph不是空,而指定函数尚未处理(214行条件),BaseGraph中的是同类集中的其他函数,那么218行通过cloneInto把函数图拷贝、简并入BaseGraph,接着简并参数。

 

131    void

132    EquivBUDataStructures::mergeGraphsByGlobalECs() {

133      //

134      // Merge thegraphs for each equivalence class.  Wefirst scan all elements

135      // in theequivalence classes and look for those elements which are leaders.

136      // For eachleader, we scan through all of its members and merge the DSGraphs

137      // for memberswhich are functions.

138      //

139   

140      EquivalenceClasses<const GlobalValue*>::iterator EQSI = GlobalECs.begin();

141      EquivalenceClasses<const GlobalValue*>::iterator EQSE = GlobalECs.end();

142      for (;EQSI !=EQSE; ++EQSI) {

143        //

144        // If thiselement is not a leader, then skip it.

145        //

146       if (!EQSI->isLeader()) continue;

147        DSGraph* BaseGraph = 0;

148        std::vector<DSNodeHandle> Args;

149   

150        //

151        // Iteratethrough all members of this equivalence class, looking for

152        // functions.

153        //

154        EquivalenceClasses<const GlobalValue*>::member_iterator MI;

155        for (MI =GlobalECs.member_begin(EQSI); MI != GlobalECs.member_end(); ++MI){

156          if (constFunction* F = dyn_cast<Function>(*MI)) {

157            //

158            // If thefunction has no body, then it has no DSGraph.

159            //

160            // FIXME: Idon't believe this is correct; the stdlib pass can assign

161            //        DSGraphs to C standard libraryfunctions.

162            //

163            if (F->isDeclaration())

164              continue;

165   

166            //

167            // We haveone of three possibilities:

168            //  1) This is the first function we'veseen.  If so, grab its DSGraph

169            //     and the DSNodes for its arguments.

170            //

171            //  2) We have already seen this functionbefore.  Do nothing.

172            //

173            //  3) We haven't seen this function before, andit's not the first one

174            //     we've seen.  Merge its DSGraph into the DSGraph we'recreating.

175            //

176            if (!BaseGraph) {

177              BaseGraph = getOrCreateGraph(F);

178              BaseGraph->getFunctionArgumentsForCall(F,Args);

179            } else if(BaseGraph->containsFunction(F)) {

180              //

181              // TheDSGraph for this function has already been merged into the

182              // graphthat we are creating.  However, that doesnot mean that

183              //function arguments of this function have been merged with the

184              // functionarguments of the other functions in the equivalence graph

185              // (oreven with functions belonging to the same SCC in the call

186              //graph).  Furthermore, it doesn'tnecessarily imply that the

187              //contained function's DSGraph is the same as the one we're

188              //building; it is possible (I think) for only the function's DSNodes

189              // andother information to have been merged in.

190              //

191              // Forthese reasons, we will merge the function argument DSNodes and

192              // setthis function's DSGraph to be the same graph used for all

193              // otherfunction's in this equivalence class.

194              //

195   

196              //

197              // Mergethe arguments together.

198              //

199              std::vector<DSNodeHandle>NextArgs;

200              BaseGraph->getFunctionArgumentsForCall(F,NextArgs);

201              unsigned i = 0, e = Args.size();

202              for(; i != e; ++i) {

203                if (i == NextArgs.size()) break;

204                Args[i].mergeWith(NextArgs[i]);

205              }

206              for(e = NextArgs.size(); i != e; ++i)

207                Args.push_back(NextArgs[i]);

208   

209              //

210              // Makethis function use the DSGraph that we're creating for all of

211              // thefunctions in this equivalence class.

212              //

213              setDSGraph(*F, BaseGraph);

214            } else {

215              //

216              // Mergein the DSGraph.

217              //

218              BaseGraph->cloneInto(getOrCreateGraph(F));

219   

220              //

221              // Merge thearguments together.

222              //

223              std::vector<DSNodeHandle>NextArgs;

224              BaseGraph->getFunctionArgumentsForCall(F,NextArgs);

225              unsigned i = 0, e = Args.size();

226              for(; i != e; ++i) {

227                if (i == NextArgs.size()) break;

228                Args[i].mergeWith(NextArgs[i]);

229              }

230              for(e = NextArgs.size(); i != e; ++i)

231                Args.push_back(NextArgs[i]);

232   

233              //

234              // Makethis function use the DSGraph that we're creating for all of

235              // thefunctions in this equivalence class.

236              //

237              setDSGraph(*F, BaseGraph);

238            }

239          }

240        }

241   

242        //

243        // Update theglobals graph with any information that has changed due to

244        // graphmerging.

245        //

246        if (BaseGraph)

247          cloneIntoGlobals(BaseGraph,DSGraph::DontCloneCallNodes |

248                           DSGraph::DontCloneAuxCallNodes |

249                           DSGraph::StripAllocaBit);

250      }

251    }

 

对于简并同类集最后得到的BaseGraph,在247行把其中的信息拷贝回全局图。因为在上面213及237行处把同类集中所有的函数的图都设置为BaseGraph,接下来59~63行把BaseGraph从graphList先行除去(因为BaseGraph可以与graphList中的图相同,参考177行,这对应同类集只包含一个函数的情况。否则BaseGraph是新建的,graphList中没有记录),然后在65~76行,把其余图删除。

 

EquivBUDataStructures::runOnModule(续)

 

58        //remove all theDSGraph, that still have references

59        for(Module::iteratorF = M.begin(); F != M.end(); ++F)

60        {

61          if(!(F->isDeclaration()))

62            graphList.erase(getOrCreateGraph(F));

63        }

64        // free memoryfor the DSGraphs, no longer in use.

65        for(std::set<DSGraph*>::iteratori = graphList.begin(),e = graphList.end();

66            i!=e;i++) {

67          delete(*i);

68        }

69        DEBUG(verifyMerging());

70     

71        formGlobalECs();

72     

73        for(Module::iterator F = M.begin(); F != M.end(); ++F) {

74          if (!(F->isDeclaration())) {

75            if (DSGraph * Graph =getOrCreateGraph(F)) {

76              cloneGlobalsInto(Graph, DSGraph::DontCloneCallNodes|

77                             DSGraph::DontCloneAuxCallNodes);

78            }

79          }

80        }

81       

82        bool result = runOnModuleInternal(M);

83       

84        // CBU containsthe correct call graph.

85        // Restore it, sothat subsequent passes and clients can get it.

86        restoreCorrectCallGraph();

87        returnresult;

88      }

 

71~82行的处理与BUDataStructure相同,但它是在CompleteDataStructure结果的基础上进行的。在86行,通过下面的函数把callgraph恢复为CompleteDataStructure给出的样子。这是因为callgraph反映的是实际函数的调用情况,尽管调用链SCC里的函数调用由其Leader来代表,EquivBUDataStructures实际上不应该改变callgraph,它只是简并同类集函数的图,减少节点数。但以目前的实现,EquivBUDataStructures有可能改变callgraph。

 

1512  void DataStructures::restoreCorrectCallGraph(){

1513    callgraph = GraphSource->callgraph;

1514  }

 

其中的GraphSource是在init时设置的,指向CompleteDataStructure的实例。

你可能感兴趣的:(算法,DSA,compiler,编译器,llvm)