@@ -22,6 +22,8 @@ namespace opts {
22
22
extern cl::opt<unsigned > Verbosity;
23
23
extern cl::OptionCategory BoltOptCategory;
24
24
extern cl::opt<bool > InferStaleProfile;
25
+ extern cl::opt<bool > MatchProfileWithFunctionHash;
26
+ extern cl::opt<bool > Lite;
25
27
26
28
static llvm::cl::opt<bool >
27
29
IgnoreHash (" profile-ignore-hash" ,
@@ -363,9 +365,19 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) {
363
365
return Profile.Hash == static_cast <uint64_t >(BF.getHash ());
364
366
};
365
367
366
- // We have to do 2 passes since LTO introduces an ambiguity in function
367
- // names. The first pass assigns profiles that match 100% by name and
368
- // by hash. The second pass allows name ambiguity for LTO private functions.
368
+ uint64_t MatchedWithExactName = 0 ;
369
+ uint64_t MatchedWithHash = 0 ;
370
+ uint64_t MatchedWithLTOCommonName = 0 ;
371
+
372
+ // Computes hash for binary functions.
373
+ if (opts::MatchProfileWithFunctionHash)
374
+ for (auto &[_, BF] : BC.getBinaryFunctions ())
375
+ BF.computeHash (YamlBP.Header .IsDFSOrder , YamlBP.Header .HashFunction );
376
+ else if (!opts::IgnoreHash)
377
+ for (BinaryFunction *BF : ProfileBFs)
378
+ BF->computeHash (YamlBP.Header .IsDFSOrder , YamlBP.Header .HashFunction );
379
+
380
+ // This first pass assigns profiles that match 100% by name and by hash.
369
381
for (auto [YamlBF, BF] : llvm::zip_equal (YamlBP.Functions , ProfileBFs)) {
370
382
if (!BF)
371
383
continue ;
@@ -374,15 +386,34 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) {
374
386
// the profile.
375
387
Function.setExecutionCount (BinaryFunction::COUNT_NO_PROFILE);
376
388
377
- // Recompute hash once per function.
378
- if (!opts::IgnoreHash)
379
- Function.computeHash (YamlBP.Header .IsDFSOrder ,
380
- YamlBP.Header .HashFunction );
381
-
382
- if (profileMatches (YamlBF, Function))
389
+ if (profileMatches (YamlBF, Function)) {
383
390
matchProfileToFunction (YamlBF, Function);
391
+ ++MatchedWithExactName;
392
+ }
384
393
}
385
394
395
+ // Uses the strict hash of profiled and binary functions to match functions
396
+ // that are not matched by name or common name.
397
+ if (opts::MatchProfileWithFunctionHash) {
398
+ std::unordered_map<size_t , BinaryFunction *> StrictHashToBF;
399
+ StrictHashToBF.reserve (BC.getBinaryFunctions ().size ());
400
+
401
+ for (auto &[_, BF] : BC.getBinaryFunctions ())
402
+ StrictHashToBF[BF.getHash ()] = &BF;
403
+
404
+ for (yaml::bolt::BinaryFunctionProfile &YamlBF : YamlBP.Functions ) {
405
+ if (YamlBF.Used )
406
+ continue ;
407
+ auto It = StrictHashToBF.find (YamlBF.Hash );
408
+ if (It != StrictHashToBF.end () && !ProfiledFunctions.count (It->second )) {
409
+ BinaryFunction *BF = It->second ;
410
+ matchProfileToFunction (YamlBF, *BF);
411
+ ++MatchedWithHash;
412
+ }
413
+ }
414
+ }
415
+
416
+ // This second pass allows name ambiguity for LTO private functions.
386
417
for (const auto &[CommonName, LTOProfiles] : LTOCommonNameMap) {
387
418
if (!LTOCommonNameFunctionMap.contains (CommonName))
388
419
continue ;
@@ -396,6 +427,7 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) {
396
427
for (BinaryFunction *BF : Functions) {
397
428
if (!ProfiledFunctions.count (BF) && profileMatches (*YamlBF, *BF)) {
398
429
matchProfileToFunction (*YamlBF, *BF);
430
+ ++MatchedWithLTOCommonName;
399
431
return true ;
400
432
}
401
433
}
@@ -407,8 +439,10 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) {
407
439
// partially.
408
440
if (!ProfileMatched && LTOProfiles.size () == 1 && Functions.size () == 1 &&
409
441
!LTOProfiles.front ()->Used &&
410
- !ProfiledFunctions.count (*Functions.begin ()))
442
+ !ProfiledFunctions.count (*Functions.begin ())) {
411
443
matchProfileToFunction (*LTOProfiles.front (), **Functions.begin ());
444
+ ++MatchedWithLTOCommonName;
445
+ }
412
446
}
413
447
414
448
for (auto [YamlBF, BF] : llvm::zip_equal (YamlBP.Functions , ProfileBFs))
@@ -420,6 +454,15 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) {
420
454
errs () << " BOLT-WARNING: profile ignored for function " << YamlBF.Name
421
455
<< ' \n ' ;
422
456
457
+ if (opts::Verbosity >= 2 ) {
458
+ outs () << " BOLT-INFO: matched " << MatchedWithExactName
459
+ << " functions with identical names\n " ;
460
+ outs () << " BOLT-INFO: matched " << MatchedWithHash
461
+ << " functions with hash\n " ;
462
+ outs () << " BOLT-INFO: matched " << MatchedWithLTOCommonName
463
+ << " functions with matching LTO common names\n " ;
464
+ }
465
+
423
466
// Set for parseFunctionProfile().
424
467
NormalizeByInsnCount = usesEvent (" cycles" ) || usesEvent (" instructions" );
425
468
NormalizeByCalls = usesEvent (" branches" );
@@ -439,6 +482,11 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) {
439
482
440
483
BC.setNumUnusedProfiledObjects (NumUnused);
441
484
485
+ if (opts::Lite)
486
+ for (BinaryFunction *BF : BC.getAllBinaryFunctions ())
487
+ if (!BF->hasProfile ())
488
+ BF->setIgnored ();
489
+
442
490
return Error::success ();
443
491
}
444
492
0 commit comments