@@ -22,6 +22,8 @@ namespace opts {
2222extern cl::opt<unsigned > Verbosity;
2323extern cl::OptionCategory BoltOptCategory;
2424extern cl::opt<bool > InferStaleProfile;
25+ extern cl::opt<bool > MatchProfileWithFunctionHash;
26+ extern cl::opt<bool > Lite;
2527
2628static llvm::cl::opt<bool >
2729 IgnoreHash (" profile-ignore-hash" ,
@@ -363,9 +365,19 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) {
363365 return Profile.Hash == static_cast <uint64_t >(BF.getHash ());
364366 };
365367
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.
369381 for (auto [YamlBF, BF] : llvm::zip_equal (YamlBP.Functions , ProfileBFs)) {
370382 if (!BF)
371383 continue ;
@@ -374,15 +386,34 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) {
374386 // the profile.
375387 Function.setExecutionCount (BinaryFunction::COUNT_NO_PROFILE);
376388
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)) {
383390 matchProfileToFunction (YamlBF, Function);
391+ ++MatchedWithExactName;
392+ }
384393 }
385394
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.
386417 for (const auto &[CommonName, LTOProfiles] : LTOCommonNameMap) {
387418 if (!LTOCommonNameFunctionMap.contains (CommonName))
388419 continue ;
@@ -396,6 +427,7 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) {
396427 for (BinaryFunction *BF : Functions) {
397428 if (!ProfiledFunctions.count (BF) && profileMatches (*YamlBF, *BF)) {
398429 matchProfileToFunction (*YamlBF, *BF);
430+ ++MatchedWithLTOCommonName;
399431 return true ;
400432 }
401433 }
@@ -407,8 +439,10 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) {
407439 // partially.
408440 if (!ProfileMatched && LTOProfiles.size () == 1 && Functions.size () == 1 &&
409441 !LTOProfiles.front ()->Used &&
410- !ProfiledFunctions.count (*Functions.begin ()))
442+ !ProfiledFunctions.count (*Functions.begin ())) {
411443 matchProfileToFunction (*LTOProfiles.front (), **Functions.begin ());
444+ ++MatchedWithLTOCommonName;
445+ }
412446 }
413447
414448 for (auto [YamlBF, BF] : llvm::zip_equal (YamlBP.Functions , ProfileBFs))
@@ -420,6 +454,15 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) {
420454 errs () << " BOLT-WARNING: profile ignored for function " << YamlBF.Name
421455 << ' \n ' ;
422456
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+
423466 // Set for parseFunctionProfile().
424467 NormalizeByInsnCount = usesEvent (" cycles" ) || usesEvent (" instructions" );
425468 NormalizeByCalls = usesEvent (" branches" );
@@ -439,6 +482,11 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) {
439482
440483 BC.setNumUnusedProfiledObjects (NumUnused);
441484
485+ if (opts::Lite)
486+ for (BinaryFunction *BF : BC.getAllBinaryFunctions ())
487+ if (!BF->hasProfile ())
488+ BF->setIgnored ();
489+
442490 return Error::success ();
443491}
444492
0 commit comments