@@ -331,55 +331,26 @@ void IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) {
331
331
std::atomic<uint64_t > CallsSavedEstimate{0 };
332
332
std::atomic<uint64_t > NumFoldedLastIteration{0 };
333
333
CongruentBucketsMap CongruentBuckets;
334
- std::unique_ptr<ThreadPool> ThPool;
335
- if (!opts::NoThreads)
336
- ThPool = std::make_unique<ThreadPool>(opts::ThreadCount);
337
334
338
335
// Hash all the functions
339
336
auto hashFunctions = [&]() {
340
337
NamedRegionTimer HashFunctionsTimer (" hashing" , " hashing" , " ICF breakdown" ,
341
338
" ICF breakdown" , opts::TimeICF);
339
+ ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) {
340
+ // Make sure indices are in-order.
341
+ BF.updateLayoutIndices ();
342
342
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);
361
345
};
362
346
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
+ };
381
350
382
- ThPool->wait ();
351
+ ParallelUtilities::runOnEachFunction (
352
+ BC, ParallelUtilities::SchedulingPolicy::SP_TRIVIAL, WorkFun, SkipFunc,
353
+ " hashFunctions" , /* ForceSequential*/ false , 2 );
383
354
};
384
355
385
356
// Creates buckets with congruent functions - functions that potentially
@@ -405,8 +376,12 @@ void IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) {
405
376
Timer SinglePass (" single fold pass" , " single fold pass" );
406
377
DEBUG (SinglePass.startTimer ());
407
378
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) {
410
385
Timer T (" folding single congruent list" , " folding single congruent list" );
411
386
DEBUG (T.startTimer ());
412
387
@@ -426,7 +401,8 @@ void IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) {
426
401
// different options.
427
402
std::stable_sort (Twins.begin (), Twins.end (),
428
403
[](const BinaryFunction *A, const BinaryFunction *B) {
429
- return A->getFunctionNumber () < B->getFunctionNumber ();
404
+ return A->getFunctionNumber () <
405
+ B->getFunctionNumber ();
430
406
});
431
407
432
408
BinaryFunction *ParentBF = Twins[0 ];
@@ -457,21 +433,21 @@ void IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) {
457
433
DEBUG (T.stopTimer ());
458
434
};
459
435
460
- // Create a task for each congruent list
436
+ // Create a task for each congruent bucket
461
437
for (auto &Entry : CongruentBuckets) {
462
- auto &Candidates = Entry.second ;
463
- if (Candidates .size () < 2 )
438
+ auto &Bucket = Entry.second ;
439
+ if (Bucket .size () < 2 )
464
440
continue ;
465
441
466
442
if (opts::NoThreads)
467
- performFoldingForItem (Candidates );
443
+ procesSingleBucket (Bucket );
468
444
else
469
- ThPool->async (performFoldingForItem , std::ref (Candidates ));
445
+ ThPool->async (procesSingleBucket , std::ref (Bucket ));
470
446
}
471
- if (opts::NoThreads)
472
- return ;
473
447
474
- ThPool->wait ();
448
+ if (!opts::NoThreads)
449
+ ThPool->wait ();
450
+
475
451
DEBUG (SinglePass.stopTimer ());
476
452
};
477
453
0 commit comments