Skip to content

Commit 3756f52

Browse files
authored
Merge pull request #94 from ddiepo-pjr/OptimizeIcfg
ICFG Optimizations -- graph merging and others.
2 parents 2938c39 + 9a435ba commit 3756f52

10 files changed

Lines changed: 101 additions & 90 deletions

File tree

include/phasar/DB/ProjectIRDB.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
#include <llvm/IR/LLVMContext.h>
2121
#include <llvm/IR/Module.h>
2222

23-
#include <phasar/PhasarLLVM/Pointer/LLVMPointsToGraph.h>
2423
#include <phasar/Utils/EnumFlags.h>
2524

2625
namespace llvm {

include/phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h

Lines changed: 3 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ class LLVMBasedICFG
8888
};
8989

9090
/// Specify the type of graph to be used.
91-
typedef boost::adjacency_list<boost::multisetS, boost::vecS,
91+
typedef boost::adjacency_list<boost::vecS, boost::vecS,
9292
boost::bidirectionalS, VertexProperties,
9393
EdgeProperties>
9494
bidigraph_t;
@@ -106,7 +106,7 @@ class LLVMBasedICFG
106106
/// Maps function names to the corresponding vertex id.
107107
std::unordered_map<const llvm::Function *, vertex_t> FunctionVertexMap;
108108

109-
void constructionWalker(const llvm::Function *F, Resolver *Res);
109+
void constructionWalker(const llvm::Function *F, Resolver &Resolver);
110110

111111
struct dependency_visitor;
112112

@@ -162,44 +162,7 @@ class LLVMBasedICFG
162162
using LLVMBasedCFG::print; // tell the compiler we wish to have both prints
163163
void print(std::ostream &OS = std::cout) const override;
164164

165-
// provide a VertexPropertyWrite to tell boost how to write a vertex
166-
class CallGraphVertexWriter {
167-
public:
168-
CallGraphVertexWriter(const bidigraph_t &CGraph) : CGraph(CGraph) {}
169-
template <class VertexOrEdge>
170-
void operator()(std::ostream &out, const VertexOrEdge &v) const {
171-
out << "[label=\"" << CGraph[v].getFunctionName() << "\"]";
172-
}
173-
174-
private:
175-
const bidigraph_t &CGraph;
176-
};
177-
178-
// a function to conveniently create the vertex writer
179-
CallGraphVertexWriter
180-
makeCallGraphVertexWriter(const bidigraph_t &CGraph) const {
181-
return CallGraphVertexWriter(CGraph);
182-
}
183-
184-
// provide a EdgePropertyWrite to tell boost how to write an edge
185-
class CallGraphEdgeWriter {
186-
public:
187-
CallGraphEdgeWriter(const bidigraph_t &CGraph) : CGraph(CGraph) {}
188-
template <class VertexOrEdge>
189-
void operator()(std::ostream &out, const VertexOrEdge &v) const {
190-
out << "[label=\"" << CGraph[v].getCallSiteAsString() << "\"]";
191-
}
192-
193-
private:
194-
const bidigraph_t &CGraph;
195-
};
196-
197-
// a function to conveniently create the edge writer
198-
CallGraphEdgeWriter makeCallGraphEdgeWriter(const bidigraph_t &CGraph) const {
199-
return CallGraphEdgeWriter(CGraph);
200-
}
201-
202-
void printAsDot(std::ostream &OS = std::cout) const;
165+
void printAsDot(std::ostream &OS = std::cout, bool printEdgeLabels = true) const;
203166

204167
void printInternalPTGAsDot(std::ostream &OS = std::cout) const;
205168

lib/DB/ProjectIRDB.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
#include <boost/filesystem.hpp>
3030

31+
#include <phasar/Config/Configuration.h>
3132
#include <phasar/DB/ProjectIRDB.h>
3233
#include <phasar/PhasarLLVM/DataFlowSolver/IfdsIde/LLVMZeroValue.h>
3334
#include <phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h>

lib/PhasarLLVM/ControlFlow/LLVMBasedICFG.cpp

Lines changed: 85 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ LLVMBasedICFG::LLVMBasedICFG(ProjectIRDB &IRDB, CallGraphAnalysisType CGType,
143143
PointsToGraph *PTG = PT->getPointsToGraph(F);
144144
WholeModulePTG.mergeWith(PTG, F);
145145
}
146-
constructionWalker(F, Res.get());
146+
constructionWalker(F, *Res.get());
147147
}
148148
REG_COUNTER("WM-PTG Vertices", WholeModulePTG.getNumOfVertices(),
149149
PAMM_SEVERITY_LEVEL::Full);
@@ -166,29 +166,33 @@ LLVMBasedICFG::~LLVMBasedICFG() {
166166
}
167167

168168
void LLVMBasedICFG::constructionWalker(const llvm::Function *F,
169-
Resolver *Resolver) {
169+
Resolver &Resolver) {
170170
PAMM_GET_INSTANCE;
171171
auto &lg = lg::get();
172172
LOG_IF_ENABLE(BOOST_LOG_SEV(lg, DEBUG)
173173
<< "Walking in function: " << F->getName().str());
174-
if (VisitedFunctions.count(F) || F->isDeclaration()) {
174+
if (F->isDeclaration() || !VisitedFunctions.insert(F).second ) {
175175
LOG_IF_ENABLE(BOOST_LOG_SEV(lg, DEBUG)
176176
<< "Function already visited or only declaration: "
177177
<< F->getName().str());
178178
return;
179179
}
180-
VisitedFunctions.insert(F);
181180

182181
// add a node for function F to the call graph (if not present already)
183-
if (!FunctionVertexMap.count(F)) {
184-
FunctionVertexMap[F] = boost::add_vertex(CallGraph);
185-
CallGraph[FunctionVertexMap[F]] = VertexProperties(F);
182+
vertex_t thisFunctionVertexDescriptor;
183+
auto fvmItr = FunctionVertexMap.find(F);
184+
if (fvmItr != FunctionVertexMap.end())
185+
thisFunctionVertexDescriptor = fvmItr->second;
186+
else {
187+
thisFunctionVertexDescriptor = boost::add_vertex(VertexProperties(F), CallGraph);
188+
FunctionVertexMap[F] = thisFunctionVertexDescriptor;
186189
}
190+
187191
// iterate all instructions of the current function
188192
for (auto &BB : *F) {
189193
for (auto &I : BB) {
190194
if (llvm::isa<llvm::CallInst>(I) || llvm::isa<llvm::InvokeInst>(I)) {
191-
Resolver->preCall(&I);
195+
Resolver.preCall(&I);
192196

193197
llvm::ImmutableCallSite cs(&I);
194198
set<const llvm::Function *> possible_targets;
@@ -200,10 +204,11 @@ void LLVMBasedICFG::constructionWalker(const llvm::Function *F,
200204
<< " " << llvmIRToString(cs.getInstruction()));
201205
} else {
202206
// still try to resolve the called function statically
203-
const llvm::Value *v = cs.getCalledValue();
204-
const llvm::Value *sv = v->stripPointerCasts();
205-
if (sv->hasName() && IRDB.getFunction(sv->getName())) {
206-
possible_targets.insert(IRDB.getFunction(sv->getName()));
207+
const llvm::Value *sv = cs.getCalledValue()->stripPointerCasts();
208+
const llvm::Function *valueFunction =
209+
!sv->hasName() ? nullptr : IRDB.getFunction(sv->getName());
210+
if (valueFunction) {
211+
possible_targets.insert(valueFunction);
207212
LOG_IF_ENABLE(BOOST_LOG_SEV(lg, DEBUG)
208213
<< "Found static call-site: "
209214
<< llvmIRToString(cs.getInstruction()));
@@ -215,9 +220,9 @@ void LLVMBasedICFG::constructionWalker(const llvm::Function *F,
215220
<< " " << llvmIRToString(cs.getInstruction()));
216221
// call the resolve routine
217222
if (isVirtualFunctionCall(cs.getInstruction())) {
218-
possible_targets = Resolver->resolveVirtualCall(cs);
223+
possible_targets = Resolver.resolveVirtualCall(cs);
219224
} else {
220-
possible_targets = Resolver->resolveFunctionPointer(cs);
225+
possible_targets = Resolver.resolveFunctionPointer(cs);
221226
}
222227
}
223228
}
@@ -226,18 +231,19 @@ void LLVMBasedICFG::constructionWalker(const llvm::Function *F,
226231
<< "Found " << possible_targets.size()
227232
<< " possible target(s)");
228233

229-
Resolver->handlePossibleTargets(cs, possible_targets);
234+
Resolver.handlePossibleTargets(cs, possible_targets);
230235
// Insert possible target inside the graph and add the link with
231236
// the current function
232237
for (auto &possible_target : possible_targets) {
233-
auto target = possible_target;
234-
if (!FunctionVertexMap.count(target)) {
235-
FunctionVertexMap[target] = boost::add_vertex(CallGraph);
236-
CallGraph[FunctionVertexMap[target]] =
237-
VertexProperties(possible_target);
238+
vertex_t targetVertex;
239+
auto targetFvmItr = FunctionVertexMap.find(possible_target);
240+
if (targetFvmItr != FunctionVertexMap.end())
241+
targetVertex = targetFvmItr->second;
242+
else {
243+
targetVertex = boost::add_vertex(VertexProperties(possible_target), CallGraph);
244+
FunctionVertexMap[possible_target] = targetVertex;
238245
}
239-
240-
boost::add_edge(FunctionVertexMap[F], FunctionVertexMap[target],
246+
boost::add_edge(thisFunctionVertexDescriptor, targetVertex,
241247
EdgeProperties(cs.getInstruction()), CallGraph);
242248
}
243249

@@ -246,9 +252,9 @@ void LLVMBasedICFG::constructionWalker(const llvm::Function *F,
246252
constructionWalker(possible_target, Resolver);
247253
}
248254

249-
Resolver->postCall(&I);
255+
Resolver.postCall(&I);
250256
} else {
251-
Resolver->otherInst(&I);
257+
Resolver.otherInst(&I);
252258
}
253259
}
254260
}
@@ -446,23 +452,14 @@ LLVMBasedICFG::getLastInstructionOf(const string &name) {
446452
}
447453

448454
void LLVMBasedICFG::mergeWith(const LLVMBasedICFG &other) {
449-
// Copy other graph into this graph
450-
typedef typename boost::property_map<bidigraph_t, boost::vertex_index_t>::type
451-
index_map_t;
452-
// For simple adjacency_list<> this type would be more efficient:
453-
typedef typename boost::iterator_property_map<
454-
typename std::vector<LLVMBasedICFG::vertex_t>::iterator, index_map_t,
455-
LLVMBasedICFG::vertex_t, LLVMBasedICFG::vertex_t &>
456-
IsoMap;
457-
// For more generic graphs, one can try typedef std::map<vertex_t, vertex_t>
458-
// IsoMap;
459-
vector<LLVMBasedICFG::vertex_t> orig2copy_data(
460-
boost::num_vertices(other.CallGraph));
461-
IsoMap mapV = boost::make_iterator_property_map(
462-
orig2copy_data.begin(), get(boost::vertex_index, other.CallGraph));
463-
boost::copy_graph(other.CallGraph, CallGraph,
464-
boost::orig_to_copy(mapV)); // means g1 += g2
465-
// This vector hols the call-sites that are used to merge the whole-module
455+
typedef bidigraph_t::vertex_descriptor vertex_t;
456+
typedef std::map<vertex_t, vertex_t> vertex_map_t;
457+
vertex_map_t oldToNewVertexMapping;
458+
boost::associative_property_map<vertex_map_t> vertexMapWrapper(
459+
oldToNewVertexMapping);
460+
boost::copy_graph(other.CallGraph, CallGraph, boost::orig_to_copy(vertexMapWrapper));
461+
462+
// This vector holds the call-sites that are used to merge the whole-module
466463
// points-to graphs
467464
vector<pair<llvm::ImmutableCallSite, const llvm::Function *>> Calls;
468465
vertex_iterator vi_v, vi_v_end, vi_u, vi_u_end;
@@ -494,12 +491,16 @@ void LLVMBasedICFG::mergeWith(const LLVMBasedICFG &other) {
494491
}
495492
}
496493
}
497-
// Update the FunctionVertexMap
498-
FunctionVertexMap.clear();
499-
for (boost::tie(vi_v, vi_v_end) = boost::vertices(CallGraph);
500-
vi_v != vi_v_end; ++vi_v) {
501-
FunctionVertexMap.insert(make_pair(CallGraph[*vi_v].F, *vi_v));
494+
495+
// Update the FunctionVertexMap:
496+
for (const auto &otherValues : other.FunctionVertexMap) {
497+
auto mappingIter = oldToNewVertexMapping.find(otherValues.second);
498+
if (mappingIter != oldToNewVertexMapping.end()) {
499+
FunctionVertexMap.insert(
500+
make_pair(otherValues.first, mappingIter->second));
501+
}
502502
}
503+
503504
// Merge the already visited functions
504505
VisitedFunctions.insert(other.VisitedFunctions.begin(),
505506
other.VisitedFunctions.end());
@@ -535,9 +536,44 @@ void LLVMBasedICFG::print(ostream &OS) const {
535536
}
536537
}
537538

538-
void LLVMBasedICFG::printAsDot(std::ostream &OS) const {
539-
boost::write_graphviz(OS, CallGraph, makeCallGraphVertexWriter(CallGraph),
540-
makeCallGraphEdgeWriter(CallGraph));
539+
namespace {
540+
template <class graphType>
541+
class VertexWriter {
542+
public:
543+
VertexWriter(const graphType &CGraph) : CGraph(CGraph) {}
544+
template <class VertexOrEdge>
545+
void operator()(std::ostream &out, const VertexOrEdge &v) const {
546+
out << "[label=\"" << CGraph[v].getFunctionName() << "\"]";
547+
}
548+
549+
private:
550+
const graphType &CGraph;
551+
};
552+
553+
template <class graphType>
554+
class EdgeLabelWriter {
555+
public:
556+
EdgeLabelWriter(const graphType &CGraph) : CGraph(CGraph) {}
557+
template <class VertexOrEdge>
558+
void operator()(std::ostream &out, const VertexOrEdge &v) const {
559+
out << "[label=\"" << CGraph[v].getCallSiteAsString() << "\"]";
560+
}
561+
562+
private:
563+
const graphType &CGraph;
564+
};
565+
}
566+
567+
void LLVMBasedICFG::printAsDot(std::ostream &OS, bool printEdgeLabels) const {
568+
if (printEdgeLabels) {
569+
boost::write_graphviz(OS, CallGraph,
570+
VertexWriter<bidigraph_t>(CallGraph),
571+
EdgeLabelWriter<bidigraph_t>(CallGraph));
572+
} else {
573+
boost::write_graphviz(OS, CallGraph,
574+
VertexWriter<bidigraph_t>(CallGraph));
575+
576+
}
541577
}
542578

543579
void LLVMBasedICFG::printInternalPTGAsDot(std::ostream &OS) const {

lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include <llvm/IR/Instructions.h>
3636
#include <llvm/IR/Module.h>
3737

38+
#include <phasar/Config/Configuration.h>
3839
#include <phasar/DB/ProjectIRDB.h>
3940
#include <phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h>
4041
#include <phasar/Utils/GraphExtensions.h>

unittests/PhasarLLVM/ControlFlow/LLVMBasedBackwardCFGTest.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#include <gtest/gtest.h>
22
#include <llvm/IR/InstIterator.h>
3+
#include <llvm/IR/Function.h>
4+
#include <llvm/IR/Instructions.h>
5+
#include <phasar/Config/Configuration.h>
36
#include <phasar/DB/ProjectIRDB.h>
47
#include <phasar/PhasarLLVM/ControlFlow/LLVMBasedBackwardCFG.h>
58
#include <phasar/Utils/LLVMShorthands.h>

unittests/PhasarLLVM/ControlFlow/LLVMBasedCFGTest.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#include <gtest/gtest.h>
22
#include <llvm/IR/InstIterator.h>
3+
#include <llvm/IR/Function.h>
4+
#include <llvm/IR/Instructions.h>
5+
#include <phasar/Config/Configuration.h>
36
#include <phasar/DB/ProjectIRDB.h>
47
#include <phasar/PhasarLLVM/ControlFlow/LLVMBasedCFG.h>
58
#include <phasar/Utils/LLVMShorthands.h>

unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyTest.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include <gtest/gtest.h>
88

9+
#include <phasar/Config/Configuration.h>
910
#include <phasar/DB/ProjectIRDB.h>
1011
#include <phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h>
1112
#include <phasar/Utils/LLVMShorthands.h>

unittests/PhasarLLVM/TypeHierarchy/TypeGraphTest.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <phasar/PhasarLLVM/Pointer/TypeGraphs/LazyTypeGraph.h>
55

66
#include <boost/graph/isomorphism.hpp>
7+
#include <phasar/Config/Configuration.h>
78
#include <phasar/Utils/LLVMShorthands.h>
89
#include <phasar/Utils/Utilities.h>
910

unittests/Utils/LLVMShorthandsTest.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
#include <gtest/gtest.h>
2+
#include <llvm/IR/Function.h>
3+
#include <llvm/IR/Instructions.h>
4+
#include <phasar/Config/Configuration.h>
25
#include <phasar/DB/ProjectIRDB.h>
36
#include <phasar/Utils/LLVMShorthands.h>
47
#include <phasar/Utils/Utilities.h>

0 commit comments

Comments
 (0)