Skip to content

Commit e0d2b6c

Browse files
committed
Refactor Points-To graph merging logic.
Changes the merge logic for points-to graph to avoid re-creating the ValueVertexMap from scratch each time. When merging we can ask boost to provide a mapping so we can simply append to the existing ValueVertexMap instead. For large applications this makes a measurable runtime improvement since the number of merge calls is large.
1 parent 42ba7f5 commit e0d2b6c

3 files changed

Lines changed: 62 additions & 131 deletions

File tree

include/phasar/PhasarLLVM/Pointer/LLVMPointsToGraph.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,12 @@ class PointsToGraph {
116116

117117
/// The points to graph.
118118
graph_t PAG;
119-
std::unordered_map<const llvm::Value *, vertex_t> ValueVertexMap;
119+
typedef std::unordered_map<const llvm::Value *, vertex_t> ValueVertexMapT;
120+
ValueVertexMapT ValueVertexMap;
120121
/// Keep track of what has already been merged into this points-to graph.
121-
std::unordered_set<std::string> ContainedFunctions;
122+
std::unordered_set<const llvm::Function* > ContainedFunctions;
123+
124+
void mergeGraph(const PointsToGraph &Other);
122125

123126
public:
124127
/**
@@ -213,11 +216,13 @@ class PointsToGraph {
213216
// TODO add more detailed description
214217
inline bool representsSingleFunction();
215218
void mergeWith(const PointsToGraph *Other, const llvm::Function *F);
219+
220+
void mergeCallSite(const llvm::ImmutableCallSite &CS,
221+
const llvm::Function *F);
222+
216223
void mergeWith(const PointsToGraph &Other,
217224
const std::vector<std::pair<llvm::ImmutableCallSite,
218225
const llvm::Function *>> &Calls);
219-
void mergeWith(PointsToGraph *Other, llvm::ImmutableCallSite CS,
220-
const llvm::Function *F);
221226

222227
/**
223228
* The value-vertex-map maps each Value of the points-to graph to

lib/PhasarLLVM/ControlFlow/Resolver/OTFResolver.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
#include <phasar/DB/ProjectIRDB.h>
2525
#include <phasar/PhasarLLVM/ControlFlow/Resolver/OTFResolver.h>
26+
#include <phasar/PhasarLLVM/Pointer/LLVMPointsToGraph.h>
2627
#include <phasar/PhasarLLVM/Pointer/LLVMPointsToInfo.h>
2728
#include <phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h>
2829
#include <phasar/Utils/LLVMShorthands.h>
@@ -52,7 +53,8 @@ void OTFResolver::handlePossibleTargets(
5253
// only if they are available
5354
if (!CalleeTarget->isDeclaration()) {
5455
auto CalleePTG = PT.getPointsToGraph(CalleeTarget);
55-
WholeModulePTG.mergeWith(CalleePTG, CS, CalleeTarget);
56+
WholeModulePTG.mergeWith(CalleePTG, CalleeTarget);
57+
WholeModulePTG.mergeCallSite(CS, CalleeTarget);
5658
}
5759
}
5860
}

lib/PhasarLLVM/Pointer/LLVMPointsToGraph.cpp

Lines changed: 50 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ PointsToGraph::PointsToGraph(llvm::Function *F, llvm::AAResults &AA) {
136136
auto &lg = lg::get();
137137
LOG_IF_ENABLE(BOOST_LOG_SEV(lg, DEBUG)
138138
<< "Analyzing function: " << F->getName().str());
139-
ContainedFunctions.insert(F->getName().str());
139+
ContainedFunctions.insert(F);
140140
bool PrintAll, PrintNoAlias, PrintMayAlias, PrintPartialAlias, PrintMustAlias,
141141
EvalAAMD, PrintNoModRef, PrintMod, PrintRef, PrintModRef, PrintMust,
142142
PrintMustMod, PrintMustRef, PrintMustModRef;
@@ -190,8 +190,7 @@ PointsToGraph::PointsToGraph(llvm::Function *F, llvm::AAResults &AA) {
190190

191191
// make vertices for all pointers
192192
for (auto Pointer : Pointers) {
193-
ValueVertexMap[Pointer] = boost::add_vertex(PAG);
194-
PAG[ValueVertexMap[Pointer]] = VertexProperties(Pointer);
193+
ValueVertexMap[Pointer] = boost::add_vertex(VertexProperties(Pointer), PAG);
195194
}
196195
// iterate over the worklist, and run the full (n^2)/2 disambiguations
197196
for (llvm::SetVector<llvm::Value *>::iterator I1 = Pointers.begin(),
@@ -353,7 +352,7 @@ bool PointsToGraph::representsSingleFunction() {
353352

354353
void PointsToGraph::print(std::ostream &OS) const {
355354
for (const auto &Fn : ContainedFunctions) {
356-
cout << "PointsToGraph for " << Fn << ":\n";
355+
cout << "PointsToGraph for " << Fn->getName().str() << ":\n";
357356
vertex_iterator ui, ui_end;
358357
for (boost::tie(ui, ui_end) = boost::vertices(PAG); ui != ui_end; ++ui) {
359358
OS << PAG[*ui].getValueAsString() << " <--> ";
@@ -396,140 +395,65 @@ void PointsToGraph::printValueVertexMap() {
396395
}
397396
}
398397

399-
void PointsToGraph::mergeWith(const PointsToGraph *Other,
400-
const llvm::Function *F) {
401-
if (!ContainedFunctions.count(F->getName().str())) {
402-
ContainedFunctions.insert(F->getName().str());
403-
copy_graph<PointsToGraph::graph_t, PointsToGraph::vertex_t>(PAG,
404-
Other->PAG);
405-
ValueVertexMap.clear();
406-
vertex_iterator vi, vi_end;
407-
for (boost::tie(vi, vi_end) = boost::vertices(PAG); vi != vi_end; ++vi) {
408-
ValueVertexMap.insert(make_pair(PAG[*vi].V, *vi));
398+
void PointsToGraph::mergeGraph(const PointsToGraph &Other) {
399+
typedef graph_t::vertex_descriptor vertex_t;
400+
typedef std::map<vertex_t, vertex_t> vertex_map_t;
401+
vertex_map_t oldToNewVertexMapping;
402+
boost::associative_property_map<vertex_map_t> vertexMapWrapper(
403+
oldToNewVertexMapping);
404+
boost::copy_graph(Other.PAG, PAG, boost::orig_to_copy(vertexMapWrapper));
405+
406+
for (const auto &otherValues : Other.ValueVertexMap) {
407+
auto mappingIter = oldToNewVertexMapping.find(otherValues.second);
408+
if (mappingIter != oldToNewVertexMapping.end()) {
409+
ValueVertexMap.insert(
410+
make_pair(otherValues.first, mappingIter->second));
409411
}
410412
}
411413
}
412414

413-
void PointsToGraph::mergeWith(
414-
const PointsToGraph &Other,
415-
const vector<pair<llvm::ImmutableCallSite, const llvm::Function *>>
416-
&Calls) {
417-
vector<tuple<PointsToGraph::vertex_t, PointsToGraph::vertex_t,
418-
const llvm::Instruction *>>
419-
v_in_g1_u_in_g2;
420-
for (auto Call : Calls) {
421-
cout << "performing parameter mapping\n";
422-
for (unsigned i = 0; i < Call.first.getNumArgOperands(); ++i) {
423-
auto Formal = getNthFunctionArgument(Call.second, i);
424-
// cout << "CONTAINS VALUE IN PARAMLIST: " <<
425-
// Other.ValueVertexMap.count(Formal) << endl;
426-
// Check if the value is of type pointer, therefore it must be contained
427-
// in the value_vertex_maps
428-
if (ValueVertexMap.count(Call.first.getArgOperand(i)) &&
429-
Other.ValueVertexMap.count(Formal)) {
430-
v_in_g1_u_in_g2.push_back(
431-
tuple<PointsToGraph::vertex_t, PointsToGraph::vertex_t,
432-
const llvm::Instruction *>(
433-
ValueVertexMap[Call.first.getArgOperand(i)],
434-
Other.ValueVertexMap.at(Formal), Call.first.getInstruction()));
435-
}
415+
void PointsToGraph::mergeCallSite(const llvm::ImmutableCallSite &CS,
416+
const llvm::Function *F) {
417+
auto formalArgRange = F->args();
418+
auto formalIter = formalArgRange.begin();
419+
auto mapEnd = ValueVertexMap.end();
420+
for (const auto &arg : CS.args()) {
421+
const llvm::Argument *Formal = &*formalIter++;
422+
auto argMapIter = ValueVertexMap.find(arg);
423+
auto formalMapIter = ValueVertexMap.find(Formal);
424+
if (argMapIter != mapEnd && formalMapIter != mapEnd) {
425+
boost::add_edge(argMapIter->second, formalMapIter->second,
426+
CS.getInstruction(), PAG);
436427
}
428+
if (formalIter == formalArgRange.end())
429+
break;
430+
}
437431

438-
for (auto Formal :
439-
Other.getPointersEscapingThroughReturnsForFunction(Call.second)) {
440-
if (ValueVertexMap.count(Call.first.getInstruction()) &&
441-
Other.ValueVertexMap.count(Formal)) {
442-
v_in_g1_u_in_g2.push_back(
443-
tuple<PointsToGraph::vertex_t, PointsToGraph::vertex_t,
444-
const llvm::Instruction *>(
445-
ValueVertexMap[Call.first.getInstruction()],
446-
Other.ValueVertexMap.at(Formal), Call.first.getInstruction()));
447-
}
432+
for (auto Formal : getPointersEscapingThroughReturnsForFunction(F)) {
433+
auto instrMapIter = ValueVertexMap.find(CS.getInstruction());
434+
auto formalMapIter = ValueVertexMap.find(Formal);
435+
if (instrMapIter != mapEnd && formalMapIter != mapEnd) {
436+
boost::add_edge(instrMapIter->second, formalMapIter->second,
437+
CS.getInstruction(), PAG);
448438
}
449-
ContainedFunctions.insert(Call.second->getName().str());
450-
}
451-
merge_graphs<PointsToGraph::graph_t, PointsToGraph::vertex_t,
452-
PointsToGraph::EdgeProperties, const llvm::Instruction *>(
453-
PAG, Other.PAG, v_in_g1_u_in_g2);
454-
ValueVertexMap.clear();
455-
vertex_iterator vi, vi_end;
456-
for (boost::tie(vi, vi_end) = boost::vertices(PAG); vi != vi_end; ++vi) {
457-
ValueVertexMap.insert(make_pair(PAG[*vi].V, *vi));
458439
}
459440
}
460441

461-
void PointsToGraph::mergeWith(PointsToGraph *Other, llvm::ImmutableCallSite CS,
442+
void PointsToGraph::mergeWith(const PointsToGraph *Other,
462443
const llvm::Function *F) {
463-
// Check if points-to graph of F is already within 'this' whole module
464-
// points-to graph
465-
if (ContainedFunctions.count(F->getName().str())) {
466-
for (unsigned i = 0; i < CS.getNumArgOperands(); ++i) {
467-
auto Formal = getNthFunctionArgument(F, i);
468-
// Only draw the edges, when these values are of type pointer and
469-
// therefore contained in ValueVertexMap
470-
if (ValueVertexMap.count(CS.getArgOperand(i)) &&
471-
ValueVertexMap.count(Formal)) {
472-
boost::add_edge(ValueVertexMap[CS.getArgOperand(i)],
473-
ValueVertexMap[Formal], CS.getInstruction(), PAG);
474-
}
475-
}
476-
477-
for (auto Formal : getPointersEscapingThroughReturnsForFunction(F)) {
478-
if (ValueVertexMap.count(CS.getInstruction()) &&
479-
ValueVertexMap.count(Formal)) {
480-
boost::add_edge(ValueVertexMap[CS.getInstruction()],
481-
ValueVertexMap[Formal], CS.getInstruction(), PAG);
482-
}
483-
}
484-
} else {
485-
ContainedFunctions.insert(F->getName().str());
486-
// TODO this function has to check if F's points-to graph is already
487-
// merged into the 'this' points-to graph. If so, is is not allowed to
488-
// copy it a second time into 'this' PAG.
489-
vector<pair<PointsToGraph::vertex_t, PointsToGraph::vertex_t>>
490-
v_in_g1_u_in_g2;
491-
for (unsigned i = 0; i < CS.getNumArgOperands(); ++i) {
492-
auto Formal = getNthFunctionArgument(F, i);
493-
if (ValueVertexMap.count(CS.getArgOperand(i)) &&
494-
Other->ValueVertexMap.count(Formal)) {
495-
v_in_g1_u_in_g2.push_back(make_pair(ValueVertexMap[CS.getArgOperand(i)],
496-
Other->ValueVertexMap[Formal]));
497-
}
498-
}
499-
500-
for (auto Formal : Other->getPointersEscapingThroughReturnsForFunction(F)) {
501-
if (ValueVertexMap.count(CS.getInstruction()) &&
502-
Other->ValueVertexMap.count(Formal)) {
503-
v_in_g1_u_in_g2.push_back(make_pair(ValueVertexMap[CS.getInstruction()],
504-
Other->ValueVertexMap[Formal]));
505-
}
506-
}
507-
508-
typedef
509-
typename boost::property_map<PointsToGraph::graph_t,
510-
boost::vertex_index_t>::type index_map_t;
511-
// for simple adjacency_list<> this type would be more efficient:
512-
typedef typename boost::iterator_property_map<
513-
typename std::vector<PointsToGraph::vertex_t>::iterator, index_map_t,
514-
PointsToGraph::vertex_t, PointsToGraph::vertex_t &>
515-
IsoMap;
516-
// for more generic graphs, one can try typedef std::map<vertex_t,
517-
// vertex_t> IsoMap;
518-
vector<PointsToGraph::vertex_t> orig2copy_data(
519-
boost::num_vertices(Other->PAG));
520-
IsoMap mapV = boost::make_iterator_property_map(
521-
orig2copy_data.begin(), get(boost::vertex_index, Other->PAG));
522-
boost::copy_graph(Other->PAG, PAG,
523-
boost::orig_to_copy(mapV)); // means g1 += g2
524-
for (auto &entry : v_in_g1_u_in_g2) {
525-
PointsToGraph::vertex_t u_in_g1 = mapV[entry.second];
526-
boost::add_edge(entry.first, u_in_g1, CS.getInstruction(), PAG);
527-
}
444+
if (ContainedFunctions.insert(F).second) {
445+
mergeGraph(*Other);
528446
}
529-
ValueVertexMap.clear();
530-
vertex_iterator vi, vi_end;
531-
for (boost::tie(vi, vi_end) = boost::vertices(PAG); vi != vi_end; ++vi) {
532-
ValueVertexMap.insert(make_pair(PAG[*vi].V, *vi));
447+
}
448+
449+
void PointsToGraph::mergeWith(
450+
const PointsToGraph &Other,
451+
const vector<pair<llvm::ImmutableCallSite, const llvm::Function *>>
452+
&Calls) {
453+
ContainedFunctions.insert(Other.ContainedFunctions.begin(), Other.ContainedFunctions.end());
454+
mergeGraph(Other);
455+
for (const auto &call : Calls) {
456+
mergeCallSite(call.first, call.second);
533457
}
534458
}
535459

0 commit comments

Comments
 (0)