Skip to content

Commit 348a619

Browse files
committed
Optimize calls to get the Users for a a points-to vertex.
The call to Value->users() is quite expensive. Because the result should not change between executions, we can cache the results for each Vertex of the points-to graph. This has a significant performance improvement. This change also modifies the n^2 loop to be n^2/2 as described in the comments -- the inner loop was previously starting at the beginning of the map instead of at the next item in the map, and we can avoid looking up in the map by using the appropriate iterators. These changes did not significantly impact performance, however the resulting code is more concise.
1 parent 2938c39 commit 348a619

2 files changed

Lines changed: 43 additions & 43 deletions

File tree

include/phasar/PhasarLLVM/Pointer/LLVMPointsToGraph.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ class PointsToGraph {
7777
VertexProperties() = default;
7878
VertexProperties(const llvm::Value *v);
7979
std::string getValueAsString() const;
80+
81+
// Fetching the users for V is expensive, so we cache the result.
82+
mutable std::vector<const llvm::User*> users;
83+
std::vector<const llvm::User*> getUsers() const;
8084
};
8185

8286
/**
@@ -91,7 +95,7 @@ class PointsToGraph {
9195
};
9296

9397
/// Data structure for holding the points-to graph.
94-
typedef boost::adjacency_list<boost::setS, boost::vecS, boost::undirectedS,
98+
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS,
9599
VertexProperties, EdgeProperties>
96100
graph_t;
97101

lib/PhasarLLVM/Pointer/LLVMPointsToGraph.cpp

Lines changed: 38 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,16 @@ std::string PointsToGraph::VertexProperties::getValueAsString() const {
123123
return llvmIRToString(V);
124124
}
125125

126+
std::vector<const llvm::User*>
127+
PointsToGraph::VertexProperties::getUsers() const {
128+
if (!users.empty() || V == nullptr) {
129+
return users;
130+
}
131+
auto allUsers = V->users();
132+
users.insert(users.end(), allUsers.begin(), allUsers.end());
133+
return users;
134+
}
135+
126136
PointsToGraph::EdgeProperties::EdgeProperties(const llvm::Value *V) : V(V) {}
127137

128138
std::string PointsToGraph::EdgeProperties::getValueAsString() const {
@@ -189,43 +199,31 @@ PointsToGraph::PointsToGraph(llvm::Function *F, llvm::AAResults &AA) {
189199
INC_COUNTER("GS Pointer", Pointers.size(), PAMM_SEVERITY_LEVEL::Core);
190200

191201
// make vertices for all pointers
192-
for (auto Pointer : Pointers) {
193-
ValueVertexMap[Pointer] = boost::add_vertex(VertexProperties(Pointer), PAG);
202+
for (auto P : Pointers) {
203+
ValueVertexMap[P] = boost::add_vertex(VertexProperties(P), PAG);
194204
}
195205
// iterate over the worklist, and run the full (n^2)/2 disambiguations
196-
for (llvm::SetVector<llvm::Value *>::iterator I1 = Pointers.begin(),
197-
E = Pointers.end();
198-
I1 != E; ++I1) {
199-
uint64_t I1Size = llvm::MemoryLocation::UnknownSize;
206+
const auto mapEnd = ValueVertexMap.end();
207+
for (auto I1 = ValueVertexMap.begin(); I1 != mapEnd; ++I1) {
200208
llvm::Type *I1ElTy =
201-
llvm::cast<llvm::PointerType>((*I1)->getType())->getElementType();
202-
if (I1ElTy->isSized()) {
203-
I1Size = DL.getTypeStoreSize(I1ElTy);
204-
}
205-
for (llvm::SetVector<llvm::Value *>::iterator I2 = Pointers.begin();
206-
I2 != I1; ++I2) {
207-
uint64_t I2Size = llvm::MemoryLocation::UnknownSize;
209+
llvm::cast<llvm::PointerType>(I1->first->getType())->getElementType();
210+
const uint64_t I1Size = I1ElTy->isSized() ? DL.getTypeStoreSize(I1ElTy)
211+
: llvm::MemoryLocation::UnknownSize;
212+
for (auto I2 = std::next(I1); I2 != mapEnd; ++I2) {
208213
llvm::Type *I2ElTy =
209-
llvm::cast<llvm::PointerType>((*I2)->getType())->getElementType();
210-
if (I2ElTy->isSized()) {
211-
I2Size = DL.getTypeStoreSize(I2ElTy);
212-
}
213-
switch (AA.alias(llvm::MemoryLocation(*I1, I1Size),
214-
llvm::MemoryLocation(*I2, I2Size))) {
214+
llvm::cast<llvm::PointerType>(I2->first->getType())->getElementType();
215+
const uint64_t I2Size = I2ElTy->isSized() ? DL.getTypeStoreSize(I2ElTy)
216+
: llvm::MemoryLocation::UnknownSize;
217+
218+
switch (AA.alias(I1->first, I1Size, I2->first, I2Size)) {
215219
case llvm::NoAlias:
216-
// NoAlias
217-
break;
218-
case llvm::MayAlias:
219-
boost::add_edge(ValueVertexMap[*I1], ValueVertexMap[*I2], PAG);
220-
break;
221-
case llvm::PartialAlias:
222-
boost::add_edge(ValueVertexMap[*I1], ValueVertexMap[*I2], PAG);
223220
break;
221+
case llvm::MayAlias: // no break
222+
case llvm::PartialAlias: // no break
224223
case llvm::MustAlias:
225-
boost::add_edge(ValueVertexMap[*I1], ValueVertexMap[*I2], PAG);
224+
boost::add_edge(I1->second, I2->second, PAG);
226225
break;
227226
default:
228-
// do nothing
229227
break;
230228
}
231229
}
@@ -235,10 +233,9 @@ PointsToGraph::PointsToGraph(llvm::Function *F, llvm::AAResults &AA) {
235233
vector<pair<unsigned, const llvm::Value *>>
236234
PointsToGraph::getPointersEscapingThroughParams() {
237235
vector<pair<unsigned, const llvm::Value *>> escaping_pointers;
238-
for (pair<vertex_iterator, vertex_iterator> vp = boost::vertices(PAG);
239-
vp.first != vp.second; ++vp.first) {
236+
for (auto vertexIter : boost::make_iterator_range(boost::vertices(PAG))) {
240237
if (const llvm::Argument *arg =
241-
llvm::dyn_cast<llvm::Argument>(PAG[*vp.first].V)) {
238+
llvm::dyn_cast<llvm::Argument>(PAG[vertexIter].V)) {
242239
escaping_pointers.push_back(make_pair(arg->getArgNo(), arg));
243240
}
244241
}
@@ -248,11 +245,11 @@ PointsToGraph::getPointersEscapingThroughParams() {
248245
vector<const llvm::Value *>
249246
PointsToGraph::getPointersEscapingThroughReturns() const {
250247
vector<const llvm::Value *> escaping_pointers;
251-
for (pair<vertex_iterator, vertex_iterator> vp = boost::vertices(PAG);
252-
vp.first != vp.second; ++vp.first) {
253-
for (auto user : PAG[*vp.first].V->users()) {
248+
for (auto vertexIter : boost::make_iterator_range(boost::vertices(PAG))) {
249+
auto& vertex = PAG[vertexIter];
250+
for (const auto user : vertex.getUsers()) {
254251
if (llvm::isa<llvm::ReturnInst>(user)) {
255-
escaping_pointers.push_back(PAG[*vp.first].V);
252+
escaping_pointers.push_back(vertex.V);
256253
}
257254
}
258255
}
@@ -263,12 +260,12 @@ vector<const llvm::Value *>
263260
PointsToGraph::getPointersEscapingThroughReturnsForFunction(
264261
const llvm::Function *F) const {
265262
vector<const llvm::Value *> escaping_pointers;
266-
for (pair<vertex_iterator, vertex_iterator> vp = boost::vertices(PAG);
267-
vp.first != vp.second; ++vp.first) {
268-
for (auto user : PAG[*vp.first].V->users()) {
263+
for (auto vertexIter : boost::make_iterator_range(boost::vertices(PAG))) {
264+
auto& vertex = PAG[vertexIter];
265+
for (const auto user : vertex.getUsers()) {
269266
if (auto R = llvm::dyn_cast<llvm::ReturnInst>(user)) {
270267
if (R->getFunction() == F)
271-
escaping_pointers.push_back(PAG[*vp.first].V);
268+
escaping_pointers.push_back(vertex.V);
272269
}
273270
}
274271
}
@@ -289,9 +286,8 @@ set<const llvm::Value *> PointsToGraph::getReachableAllocationSites(
289286
}
290287

291288
bool PointsToGraph::containsValue(llvm::Value *V) {
292-
pair<vertex_iterator, vertex_iterator> vp;
293-
for (vp = boost::vertices(PAG); vp.first != vp.second; ++vp.first)
294-
if (PAG[*vp.first].V == V)
289+
for (auto vertexIter : boost::make_iterator_range(boost::vertices(PAG)))
290+
if (PAG[vertexIter].V == V)
295291
return true;
296292
return false;
297293
}

0 commit comments

Comments
 (0)