Skip to content

Commit 5084534

Browse files
laithsakkamaksfb
authored andcommitted
Rewrite ICF using parallel utilities
Summary: Rewrite ICF using parallel utilities (cherry picked from FBD16472975)
1 parent 8d5854e commit 5084534

File tree

1 file changed

+27
-51
lines changed

1 file changed

+27
-51
lines changed

bolt/src/Passes/IdenticalCodeFolding.cpp

Lines changed: 27 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -331,55 +331,26 @@ void IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) {
331331
std::atomic<uint64_t> CallsSavedEstimate{0};
332332
std::atomic<uint64_t> NumFoldedLastIteration{0};
333333
CongruentBucketsMap CongruentBuckets;
334-
std::unique_ptr<ThreadPool> ThPool;
335-
if (!opts::NoThreads)
336-
ThPool = std::make_unique<ThreadPool>(opts::ThreadCount);
337334

338335
// Hash all the functions
339336
auto hashFunctions = [&]() {
340337
NamedRegionTimer HashFunctionsTimer("hashing", "hashing", "ICF breakdown",
341338
"ICF breakdown", opts::TimeICF);
339+
ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) {
340+
// Make sure indices are in-order.
341+
BF.updateLayoutIndices();
342342

343-
// Perform hashing for a block of functions
344-
auto hashBlock =
345-
[&](std::map<uint64_t, BinaryFunction>::iterator BlockBegin,
346-
std::map<uint64_t, BinaryFunction>::iterator BlockEnd) {
347-
Timer T("hash block", "hash block");
348-
DEBUG(T.startTimer());
349-
350-
for (auto It = BlockBegin; It != BlockEnd; ++It) {
351-
auto &BF = It->second;
352-
if (!this->shouldOptimize(BF))
353-
continue;
354-
// Make sure indices are in-order.
355-
BF.updateLayoutIndices();
356-
357-
// Pre-compute hash before pushing into hashtable.
358-
BF.hash(/*Recompute=*/true, opts::UseDFS);
359-
}
360-
DEBUG(T.stopTimer());
343+
// Pre-compute hash before pushing into hashtable.
344+
BF.hash(/*Recompute=*/true, opts::UseDFS);
361345
};
362346

363-
if (opts::NoThreads) {
364-
hashBlock(BC.getBinaryFunctions().begin(), BC.getBinaryFunctions().end());
365-
return;
366-
}
367-
368-
const unsigned BlockSize = OriginalFunctionCount / (2 * opts::ThreadCount);
369-
unsigned Counter = 0;
370-
auto BlockBegin = BC.getBinaryFunctions().begin();
371-
372-
for (auto It = BC.getBinaryFunctions().begin();
373-
It != BC.getBinaryFunctions().end(); ++It, ++Counter) {
374-
if (Counter >= BlockSize) {
375-
ThPool->async(hashBlock, BlockBegin, std::next(It));
376-
BlockBegin = std::next(It);
377-
Counter = 0;
378-
}
379-
}
380-
ThPool->async(hashBlock, BlockBegin, BC.getBinaryFunctions().end());
347+
ParallelUtilities::PredicateTy SkipFunc = [&](const BinaryFunction &BF) {
348+
return !shouldOptimize(BF);
349+
};
381350

382-
ThPool->wait();
351+
ParallelUtilities::runOnEachFunction(
352+
BC, ParallelUtilities::SchedulingPolicy::SP_TRIVIAL, WorkFun, SkipFunc,
353+
"hashFunctions", /*ForceSequential*/ false, 2);
383354
};
384355

385356
// Creates buckets with congruent functions - functions that potentially
@@ -405,8 +376,12 @@ void IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) {
405376
Timer SinglePass("single fold pass", "single fold pass");
406377
DEBUG(SinglePass.startTimer());
407378

408-
// Perform the work for a single congruent list
409-
auto performFoldingForItem = [&](std::set<BinaryFunction *> &Candidates) {
379+
ThreadPool *ThPool;
380+
if (!opts::NoThreads)
381+
ThPool = &ParallelUtilities::getThreadPool();
382+
383+
// Fold identical functions within a single congruent bucket
384+
auto procesSingleBucket = [&](std::set<BinaryFunction *> &Candidates) {
410385
Timer T("folding single congruent list", "folding single congruent list");
411386
DEBUG(T.startTimer());
412387

@@ -426,7 +401,8 @@ void IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) {
426401
// different options.
427402
std::stable_sort(Twins.begin(), Twins.end(),
428403
[](const BinaryFunction *A, const BinaryFunction *B) {
429-
return A->getFunctionNumber() < B->getFunctionNumber();
404+
return A->getFunctionNumber() <
405+
B->getFunctionNumber();
430406
});
431407

432408
BinaryFunction *ParentBF = Twins[0];
@@ -457,21 +433,21 @@ void IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) {
457433
DEBUG(T.stopTimer());
458434
};
459435

460-
// Create a task for each congruent list
436+
// Create a task for each congruent bucket
461437
for (auto &Entry : CongruentBuckets) {
462-
auto &Candidates = Entry.second;
463-
if (Candidates.size() < 2)
438+
auto &Bucket = Entry.second;
439+
if (Bucket.size() < 2)
464440
continue;
465441

466442
if (opts::NoThreads)
467-
performFoldingForItem(Candidates);
443+
procesSingleBucket(Bucket);
468444
else
469-
ThPool->async(performFoldingForItem, std::ref(Candidates));
445+
ThPool->async(procesSingleBucket, std::ref(Bucket));
470446
}
471-
if (opts::NoThreads)
472-
return;
473447

474-
ThPool->wait();
448+
if (!opts::NoThreads)
449+
ThPool->wait();
450+
475451
DEBUG(SinglePass.stopTimer());
476452
};
477453

0 commit comments

Comments
 (0)