Skip to content

Commit febf79d

Browse files
Columpiomisonijnik
authored andcommitted
[chore] Optimized getDistance
1 parent bfaabef commit febf79d

6 files changed

Lines changed: 174 additions & 239 deletions

File tree

include/klee/Module/CodeGraphInfo.h

Lines changed: 28 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,35 @@
1616

1717
namespace klee {
1818

19+
using Block = llvm::BasicBlock;
20+
using BlockDistanceMap = std::unordered_map<Block *, unsigned>;
21+
using FunctionDistanceMap = std::unordered_map<llvm::Function *, unsigned>;
22+
using SortedBlockDistances = std::vector<std::pair<Block *, unsigned>>;
23+
using SortedFunctionDistances =
24+
std::vector<std::pair<llvm::Function *, unsigned>>;
25+
1926
class CodeGraphInfo {
2027

21-
using blockDistanceMap =
22-
std::unordered_map<KBlock *, std::unordered_map<KBlock *, unsigned>>;
23-
using blockDistanceList =
24-
std::unordered_map<KBlock *, std::vector<std::pair<KBlock *, unsigned>>>;
28+
using blockToDistanceMap = std::unordered_map<Block *, BlockDistanceMap>;
29+
using blockDistanceList = std::unordered_map<Block *, SortedBlockDistances>;
2530

26-
using functionDistanceMap =
27-
std::unordered_map<KFunction *,
28-
std::unordered_map<KFunction *, unsigned>>;
31+
using functionToDistanceMap =
32+
std::unordered_map<llvm::Function *, FunctionDistanceMap>;
2933
using functionDistanceList =
30-
std::unordered_map<KFunction *,
31-
std::vector<std::pair<KFunction *, unsigned>>>;
34+
std::unordered_map<llvm::Function *, SortedFunctionDistances>;
3235

3336
using functionBranchesSet =
3437
std::unordered_map<KFunction *, std::map<KBlock *, std::set<unsigned>>>;
3538

3639
private:
37-
blockDistanceMap blockDistance;
38-
blockDistanceMap blockBackwardDistance;
40+
blockToDistanceMap blockDistance;
41+
blockToDistanceMap blockBackwardDistance;
42+
std::set<Block *> blockCycles;
3943
blockDistanceList blockSortedDistance;
4044
blockDistanceList blockSortedBackwardDistance;
4145

42-
functionDistanceMap functionDistance;
43-
functionDistanceMap functionBackwardDistance;
46+
functionToDistanceMap functionDistance;
47+
functionToDistanceMap functionBackwardDistance;
4448
functionDistanceList functionSortedDistance;
4549
functionDistanceList functionSortedBackwardDistance;
4650

@@ -49,33 +53,24 @@ class CodeGraphInfo {
4953
functionBranchesSet functionBlocks;
5054

5155
private:
52-
void calculateDistance(KBlock *bb);
53-
void calculateBackwardDistance(KBlock *bb);
56+
void calculateDistance(Block *bb);
57+
void calculateBackwardDistance(Block *bb);
5458

55-
void calculateDistance(KFunction *kf);
56-
void calculateBackwardDistance(KFunction *kf);
59+
void calculateDistance(KFunction *f);
60+
void calculateBackwardDistance(KFunction *f);
5761

5862
void calculateFunctionBranches(KFunction *kf);
5963
void calculateFunctionConditionalBranches(KFunction *kf);
6064
void calculateFunctionBlocks(KFunction *kf);
6165

6266
public:
63-
const std::unordered_map<KBlock *, unsigned int> &getDistance(KBlock *kb);
64-
const std::unordered_map<KBlock *, unsigned int> &
65-
getBackwardDistance(KBlock *kb);
66-
const std::vector<std::pair<KBlock *, unsigned int>> &
67-
getSortedDistance(KBlock *kb);
68-
const std::vector<std::pair<KBlock *, unsigned int>> &
69-
getSortedBackwardDistance(KBlock *kb);
70-
71-
const std::unordered_map<KFunction *, unsigned int> &
72-
getDistance(KFunction *kf);
73-
const std::unordered_map<KFunction *, unsigned int> &
74-
getBackwardDistance(KFunction *kf);
75-
const std::vector<std::pair<KFunction *, unsigned int>> &
76-
getSortedDistance(KFunction *kf);
77-
const std::vector<std::pair<KFunction *, unsigned int>> &
78-
getSortedBackwardDistance(KFunction *kf);
67+
const BlockDistanceMap &getDistance(Block *b);
68+
const BlockDistanceMap &getDistance(KBlock *kb);
69+
const BlockDistanceMap &getBackwardDistance(KBlock *kb);
70+
bool hasCycle(KBlock *kb);
71+
72+
const FunctionDistanceMap &getDistance(KFunction *kf);
73+
const FunctionDistanceMap &getBackwardDistance(KFunction *kf);
7974

8075
void getNearestPredicateSatisfying(KBlock *from, KBlockPredicate predicate,
8176
std::set<KBlock *> &result);

lib/Core/DistanceCalculator.cpp

Lines changed: 48 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -56,18 +56,23 @@ DistanceResult DistanceCalculator::getDistance(const ExecutionState &state,
5656
DistanceResult DistanceCalculator::getDistance(KBlock *kb, TargetKind kind,
5757
KBlock *target) {
5858
SpeculativeState specState(kb, kind);
59-
if (distanceResultCache.count(target) == 0 ||
60-
distanceResultCache.at(target).count(specState) == 0) {
59+
auto it1 = distanceResultCache.find(target);
60+
if (it1 == distanceResultCache.end()) {
61+
SpeculativeStateToDistanceResultMap m;
62+
it1 = distanceResultCache.emplace(target, std::move(m)).first;
63+
}
64+
auto &m = it1->second;
65+
auto it2 = m.find(specState);
66+
if (it2 == m.end()) {
6167
auto result = computeDistance(kb, kind, target);
62-
distanceResultCache[target][specState] = result;
68+
m.emplace(specState, result);
69+
return result;
6370
}
64-
return distanceResultCache.at(target).at(specState);
71+
return it2->second;
6572
}
6673

6774
DistanceResult DistanceCalculator::computeDistance(KBlock *kb, TargetKind kind,
6875
KBlock *target) const {
69-
const auto &distanceToTargetFunction =
70-
codeGraphInfo.getBackwardDistance(target->parent);
7176
weight_type weight = 0;
7277
WeightResult res = Miss;
7378
bool isInsideFunction = true;
@@ -77,7 +82,7 @@ DistanceResult DistanceCalculator::computeDistance(KBlock *kb, TargetKind kind,
7782
break;
7883

7984
case PreTarget:
80-
res = tryGetPreTargetWeight(kb, weight, distanceToTargetFunction, target);
85+
res = tryGetPreTargetWeight(kb, weight, target);
8186
isInsideFunction = false;
8287
break;
8388

@@ -102,26 +107,21 @@ DistanceResult DistanceCalculator::getDistance(
102107
auto sfi = frames.rbegin(), sfe = frames.rend();
103108
bool strictlyAfterKB =
104109
sfi != sfe && sfi->kf->parent->inMainModule(*sfi->kf->function);
105-
for (; sfi != sfe; sfi++) {
110+
for (; sfi != sfe; sfi++, sfNum++) {
106111
unsigned callWeight;
107112
if (distanceInCallGraph(sfi->kf, kb, callWeight, distanceToTargetFunction,
108113
target, strictlyAfterKB && sfNum != 0)) {
109-
callWeight *= 2;
110-
callWeight += sfNum;
114+
callWeight = 2 * callWeight + sfNum;
111115

112116
if (callWeight < UINT_MAX) {
113117
minCallWeight = callWeight;
114118
minSfNum = sfNum;
119+
break;
115120
}
116121
}
117122

118-
if (sfi->caller) {
123+
if (sfi->caller)
119124
kb = sfi->caller->parent;
120-
}
121-
sfNum++;
122-
123-
if (minCallWeight < UINT_MAX)
124-
break;
125125
}
126126

127127
TargetKind kind = NoneTarget;
@@ -138,71 +138,38 @@ DistanceResult DistanceCalculator::getDistance(
138138

139139
bool DistanceCalculator::distanceInCallGraph(
140140
KFunction *kf, KBlock *origKB, unsigned int &distance,
141-
const std::unordered_map<KFunction *, unsigned int>
142-
&distanceToTargetFunction,
143-
KBlock *target, bool strictlyAfterKB) const {
144-
distance = UINT_MAX;
145-
const std::unordered_map<KBlock *, unsigned> &dist =
146-
codeGraphInfo.getDistance(origKB);
147-
KBlock *targetBB = target;
148-
KFunction *targetF = targetBB->parent;
149-
150-
if (kf == targetF && dist.count(targetBB) != 0) {
141+
const FunctionDistanceMap &distanceToTargetFunction, KBlock *targetKB,
142+
bool strictlyAfterKB) const {
143+
auto &dist = codeGraphInfo.getDistance(origKB->basicBlock);
144+
if (kf == targetKB->parent && dist.count(targetKB->basicBlock)) {
151145
distance = 0;
152146
return true;
153147
}
154148

155-
if (!strictlyAfterKB)
156-
return distanceInCallGraph(kf, origKB, distance, distanceToTargetFunction,
157-
target);
158-
auto min_distance = UINT_MAX;
159149
distance = UINT_MAX;
160-
for (auto bb : successors(origKB->basicBlock)) {
161-
auto kb = kf->blockMap[bb];
162-
distanceInCallGraph(kf, kb, distance, distanceToTargetFunction, target);
163-
if (distance < min_distance)
164-
min_distance = distance;
165-
}
166-
distance = min_distance;
167-
return distance != UINT_MAX;
168-
}
169-
170-
bool DistanceCalculator::distanceInCallGraph(
171-
KFunction *kf, KBlock *kb, unsigned int &distance,
172-
const std::unordered_map<KFunction *, unsigned int>
173-
&distanceToTargetFunction,
174-
KBlock *target) const {
175-
distance = UINT_MAX;
176-
const std::unordered_map<KBlock *, unsigned> &dist =
177-
codeGraphInfo.getDistance(kb);
178-
179-
for (auto &kCallBlock : kf->kCallBlocks) {
180-
if (dist.count(kCallBlock) == 0)
150+
bool cannotReachItself = strictlyAfterKB && !codeGraphInfo.hasCycle(origKB);
151+
for (auto kCallBlock : kf->kCallBlocks) {
152+
if (!dist.count(kCallBlock->basicBlock) ||
153+
(cannotReachItself && origKB == kCallBlock))
181154
continue;
182-
for (auto &calledFunction : kCallBlock->calledFunctions) {
183-
KFunction *calledKFunction = kf->parent->functionMap[calledFunction];
184-
if (distanceToTargetFunction.count(calledKFunction) != 0 &&
185-
distance > distanceToTargetFunction.at(calledKFunction) + 1) {
186-
distance = distanceToTargetFunction.at(calledKFunction) + 1;
187-
}
155+
for (auto calledFunction : kCallBlock->calledFunctions) {
156+
auto it = distanceToTargetFunction.find(calledFunction);
157+
if (it != distanceToTargetFunction.end() && distance > it->second + 1)
158+
distance = it->second + 1;
188159
}
189160
}
190161
return distance != UINT_MAX;
191162
}
192163

193-
WeightResult
194-
DistanceCalculator::tryGetLocalWeight(KBlock *kb, weight_type &weight,
195-
const std::vector<KBlock *> &localTargets,
196-
KBlock *target) const {
197-
KBlock *currentKB = kb;
198-
const std::unordered_map<KBlock *, unsigned> &dist =
199-
codeGraphInfo.getDistance(currentKB);
164+
WeightResult DistanceCalculator::tryGetLocalWeight(
165+
KBlock *kb, weight_type &weight,
166+
const std::vector<KBlock *> &localTargets) const {
167+
const auto &dist = codeGraphInfo.getDistance(kb);
200168
weight = UINT_MAX;
201-
for (auto &end : localTargets) {
202-
if (dist.count(end) > 0) {
203-
unsigned int w = dist.at(end);
204-
weight = std::min(w, weight);
205-
}
169+
for (auto end : localTargets) {
170+
auto it = dist.find(end->basicBlock);
171+
if (it != dist.end())
172+
weight = std::min(it->second, weight);
206173
}
207174

208175
if (weight == UINT_MAX)
@@ -214,27 +181,26 @@ DistanceCalculator::tryGetLocalWeight(KBlock *kb, weight_type &weight,
214181
return Continue;
215182
}
216183

217-
WeightResult DistanceCalculator::tryGetPreTargetWeight(
218-
KBlock *kb, weight_type &weight,
219-
const std::unordered_map<KFunction *, unsigned int>
220-
&distanceToTargetFunction,
221-
KBlock *target) const {
184+
WeightResult DistanceCalculator::tryGetPreTargetWeight(KBlock *kb,
185+
weight_type &weight,
186+
KBlock *target) const {
187+
auto &distanceToTargetFunction =
188+
codeGraphInfo.getBackwardDistance(target->parent);
222189
KFunction *currentKF = kb->parent;
223190
std::vector<KBlock *> localTargets;
224-
for (auto &kCallBlock : currentKF->kCallBlocks) {
225-
for (auto &calledFunction : kCallBlock->calledFunctions) {
226-
KFunction *calledKFunction =
227-
currentKF->parent->functionMap[calledFunction];
228-
if (distanceToTargetFunction.count(calledKFunction) > 0) {
191+
for (auto kCallBlock : currentKF->kCallBlocks) {
192+
for (auto calledFunction : kCallBlock->calledFunctions) {
193+
if (distanceToTargetFunction.count(calledFunction)) {
229194
localTargets.push_back(kCallBlock);
195+
break;
230196
}
231197
}
232198
}
233199

234200
if (localTargets.empty())
235201
return Miss;
236202

237-
WeightResult res = tryGetLocalWeight(kb, weight, localTargets, target);
203+
WeightResult res = tryGetLocalWeight(kb, weight, localTargets);
238204
return res == Done ? Continue : res;
239205
}
240206

@@ -247,14 +213,14 @@ WeightResult DistanceCalculator::tryGetPostTargetWeight(KBlock *kb,
247213
if (localTargets.empty())
248214
return Miss;
249215

250-
WeightResult res = tryGetLocalWeight(kb, weight, localTargets, target);
216+
WeightResult res = tryGetLocalWeight(kb, weight, localTargets);
251217
return res == Done ? Continue : res;
252218
}
253219

254220
WeightResult DistanceCalculator::tryGetTargetWeight(KBlock *kb,
255221
weight_type &weight,
256222
KBlock *target) const {
257223
std::vector<KBlock *> localTargets = {target};
258-
WeightResult res = tryGetLocalWeight(kb, weight, localTargets, target);
224+
WeightResult res = tryGetLocalWeight(kb, weight, localTargets);
259225
return res;
260226
}

lib/Core/DistanceCalculator.h

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#define KLEE_DISTANCE_CALCULATOR_H
1212

1313
#include "ExecutionState.h"
14+
#include "klee/Module/CodeGraphInfo.h"
1415

1516
namespace llvm {
1617
class BasicBlock;
@@ -107,22 +108,14 @@ class DistanceCalculator {
107108
KBlock *target) const;
108109

109110
bool distanceInCallGraph(KFunction *kf, KBlock *kb, unsigned int &distance,
110-
const std::unordered_map<KFunction *, unsigned int>
111-
&distanceToTargetFunction,
112-
KBlock *target) const;
113-
bool distanceInCallGraph(KFunction *kf, KBlock *kb, unsigned int &distance,
114-
const std::unordered_map<KFunction *, unsigned int>
115-
&distanceToTargetFunction,
111+
const FunctionDistanceMap &distanceToTargetFunction,
116112
KBlock *target, bool strictlyAfterKB) const;
117113

118-
WeightResult tryGetLocalWeight(KBlock *kb, weight_type &weight,
119-
const std::vector<KBlock *> &localTargets,
120-
KBlock *target) const;
121114
WeightResult
122-
tryGetPreTargetWeight(KBlock *kb, weight_type &weight,
123-
const std::unordered_map<KFunction *, unsigned int>
124-
&distanceToTargetFunction,
125-
KBlock *target) const;
115+
tryGetLocalWeight(KBlock *kb, weight_type &weight,
116+
const std::vector<KBlock *> &localTargets) const;
117+
WeightResult tryGetPreTargetWeight(KBlock *kb, weight_type &weight,
118+
KBlock *target) const;
126119
WeightResult tryGetTargetWeight(KBlock *kb, weight_type &weight,
127120
KBlock *target) const;
128121
WeightResult tryGetPostTargetWeight(KBlock *kb, weight_type &weight,

lib/Core/TargetedExecutionManager.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -379,18 +379,18 @@ bool TargetedExecutionManager::canReach(const ref<Location> &from,
379379
}
380380

381381
const auto &blockDist = codeGraphInfo.getDistance(fromBlock);
382-
if (blockDist.count(toBlock) != 0) {
382+
if (blockDist.count(toBlock->basicBlock) != 0) {
383383
return true;
384384
}
385385
} else {
386386
const auto &funcDist = codeGraphInfo.getDistance(fromKf);
387-
if (funcDist.count(toKf) != 0) {
387+
if (funcDist.count(toKf->function) != 0) {
388388
return true;
389389
}
390390

391391
const auto &backwardFuncDist =
392392
codeGraphInfo.getBackwardDistance(fromKf);
393-
if (backwardFuncDist.count(toKf) != 0) {
393+
if (backwardFuncDist.count(toKf->function) != 0) {
394394
return true;
395395
}
396396
}
@@ -464,9 +464,9 @@ KFunction *TargetedExecutionManager::tryResolveEntryFunction(
464464
KFunction *curKf = nullptr;
465465
for (size_t m = 0; m < currKFs.size() && !curKf; ++m) {
466466
curKf = currKFs.at(m);
467-
if (funcDist.count(curKf) == 0) {
467+
if (funcDist.count(curKf->function) == 0) {
468468
const auto &curFuncDist = codeGraphInfo.getDistance(curKf);
469-
if (curFuncDist.count(resKf) == 0) {
469+
if (curFuncDist.count(resKf->function) == 0) {
470470
curKf = nullptr;
471471
} else {
472472
i = j;

0 commit comments

Comments
 (0)