@@ -91,6 +91,7 @@ static cl::opt<bool> UpdateTotalSamples(
91
91
llvm::cl::Optional);
92
92
93
93
extern cl::opt<int > ProfileSummaryCutoffHot;
94
+ extern cl::opt<bool > UseContextLessSummary;
94
95
95
96
static cl::opt<bool > GenCSNestedProfile (
96
97
" gen-cs-nested-profile" , cl::Hidden, cl::init(true ),
@@ -128,14 +129,13 @@ ProfileGeneratorBase::create(ProfiledBinary *Binary,
128
129
}
129
130
130
131
std::unique_ptr<ProfileGeneratorBase>
131
- ProfileGeneratorBase::create (ProfiledBinary *Binary,
132
- const SampleProfileMap &&Profiles,
132
+ ProfileGeneratorBase::create (ProfiledBinary *Binary, SampleProfileMap &Profiles,
133
133
bool ProfileIsCS) {
134
134
std::unique_ptr<ProfileGeneratorBase> Generator;
135
135
if (ProfileIsCS) {
136
136
if (Binary->useFSDiscriminator ())
137
137
exitWithError (" FS discriminator is not supported in CS profile." );
138
- Generator.reset (new CSProfileGenerator (Binary, std::move ( Profiles) ));
138
+ Generator.reset (new CSProfileGenerator (Binary, Profiles));
139
139
} else {
140
140
Generator.reset (new ProfileGenerator (Binary, std::move (Profiles)));
141
141
}
@@ -403,43 +403,73 @@ void ProfileGeneratorBase::updateFunctionSamples() {
403
403
404
404
void ProfileGeneratorBase::collectProfiledFunctions () {
405
405
std::unordered_set<const BinaryFunction *> ProfiledFunctions;
406
- if (SampleCounters) {
407
- // Go through all the stacks, ranges and branches in sample counters, use
408
- // the start of the range to look up the function it belongs and record the
409
- // function.
410
- for (const auto &CI : *SampleCounters) {
411
- if (const auto *CtxKey = dyn_cast<AddrBasedCtxKey>(CI.first .getPtr ())) {
412
- for (auto Addr : CtxKey->Context ) {
413
- if (FuncRange *FRange = Binary->findFuncRangeForOffset (
414
- Binary->virtualAddrToOffset (Addr)))
415
- ProfiledFunctions.insert (FRange->Func );
416
- }
417
- }
406
+ if (collectFunctionsFromRawProfile (ProfiledFunctions))
407
+ Binary->setProfiledFunctions (ProfiledFunctions);
408
+ else if (collectFunctionsFromLLVMProfile (ProfiledFunctions))
409
+ Binary->setProfiledFunctions (ProfiledFunctions);
410
+ else
411
+ llvm_unreachable (" Unsupported input profile" );
412
+ }
418
413
419
- for (auto Item : CI.second .RangeCounter ) {
420
- uint64_t StartOffset = Item.first .first ;
421
- if (FuncRange *FRange = Binary->findFuncRangeForOffset (StartOffset))
414
+ bool ProfileGeneratorBase::collectFunctionsFromRawProfile (
415
+ std::unordered_set<const BinaryFunction *> &ProfiledFunctions) {
416
+ if (!SampleCounters)
417
+ return false ;
418
+ // Go through all the stacks, ranges and branches in sample counters, use
419
+ // the start of the range to look up the function it belongs and record the
420
+ // function.
421
+ for (const auto &CI : *SampleCounters) {
422
+ if (const auto *CtxKey = dyn_cast<AddrBasedCtxKey>(CI.first .getPtr ())) {
423
+ for (auto Addr : CtxKey->Context ) {
424
+ if (FuncRange *FRange = Binary->findFuncRangeForOffset (
425
+ Binary->virtualAddrToOffset (Addr)))
422
426
ProfiledFunctions.insert (FRange->Func );
423
427
}
428
+ }
424
429
425
- for (auto Item : CI.second .BranchCounter ) {
426
- uint64_t SourceOffset = Item.first .first ;
427
- uint64_t TargetOffset = Item.first .first ;
428
- if (FuncRange *FRange = Binary->findFuncRangeForOffset (SourceOffset))
429
- ProfiledFunctions.insert (FRange->Func );
430
- if (FuncRange *FRange = Binary->findFuncRangeForOffset (TargetOffset))
431
- ProfiledFunctions.insert (FRange->Func );
432
- }
430
+ for (auto Item : CI.second .RangeCounter ) {
431
+ uint64_t StartOffset = Item.first .first ;
432
+ if (FuncRange *FRange = Binary->findFuncRangeForOffset (StartOffset))
433
+ ProfiledFunctions.insert (FRange->Func );
433
434
}
434
- } else {
435
- // This is for the case the input is a llvm sample profile.
436
- for (const auto &FS : ProfileMap) {
437
- if (auto *Func = Binary->getBinaryFunction (FS.first .getName ()))
438
- ProfiledFunctions.insert (Func);
435
+
436
+ for (auto Item : CI.second .BranchCounter ) {
437
+ uint64_t SourceOffset = Item.first .first ;
438
+ uint64_t TargetOffset = Item.first .first ;
439
+ if (FuncRange *FRange = Binary->findFuncRangeForOffset (SourceOffset))
440
+ ProfiledFunctions.insert (FRange->Func );
441
+ if (FuncRange *FRange = Binary->findFuncRangeForOffset (TargetOffset))
442
+ ProfiledFunctions.insert (FRange->Func );
439
443
}
440
444
}
445
+ return true ;
446
+ }
447
+
448
+ bool ProfileGenerator::collectFunctionsFromLLVMProfile (
449
+ std::unordered_set<const BinaryFunction *> &ProfiledFunctions) {
450
+ for (const auto &FS : ProfileMap) {
451
+ if (auto *Func = Binary->getBinaryFunction (FS.first .getName ()))
452
+ ProfiledFunctions.insert (Func);
453
+ }
454
+ return true ;
455
+ }
441
456
442
- Binary->setProfiledFunctions (ProfiledFunctions);
457
+ bool CSProfileGenerator::collectFunctionsFromLLVMProfile (
458
+ std::unordered_set<const BinaryFunction *> &ProfiledFunctions) {
459
+ std::queue<ContextTrieNode *> NodeQueue;
460
+ NodeQueue.push (&getRootContext ());
461
+ while (!NodeQueue.empty ()) {
462
+ ContextTrieNode *Node = NodeQueue.front ();
463
+ NodeQueue.pop ();
464
+
465
+ if (!Node->getFuncName ().empty ())
466
+ if (auto *Func = Binary->getBinaryFunction (Node->getFuncName ()))
467
+ ProfiledFunctions.insert (Func);
468
+
469
+ for (auto &It : Node->getAllChildContext ())
470
+ NodeQueue.push (&It.second );
471
+ }
472
+ return true ;
443
473
}
444
474
445
475
FunctionSamples &
@@ -471,7 +501,7 @@ void ProfileGenerator::generateProfile() {
471
501
}
472
502
473
503
void ProfileGenerator::postProcessProfiles () {
474
- computeSummaryAndThreshold ();
504
+ computeSummaryAndThreshold (ProfileMap );
475
505
trimColdProfiles (ProfileMap, ColdCountThreshold);
476
506
calculateAndShowDensity (ProfileMap);
477
507
}
@@ -965,13 +995,12 @@ void CSProfileGenerator::convertToProfileMap() {
965
995
}
966
996
967
997
void CSProfileGenerator::postProcessProfiles () {
968
- if (SampleCounters)
969
- convertToProfileMap ();
970
-
971
998
// Compute hot/cold threshold based on profile. This will be used for cold
972
999
// context profile merging/trimming.
973
1000
computeSummaryAndThreshold ();
974
1001
1002
+ convertToProfileMap ();
1003
+
975
1004
// Run global pre-inliner to adjust/merge context profile based on estimated
976
1005
// inline decisions.
977
1006
if (EnableCSPreInliner) {
@@ -1003,15 +1032,33 @@ void CSProfileGenerator::postProcessProfiles() {
1003
1032
}
1004
1033
}
1005
1034
1006
- void ProfileGeneratorBase::computeSummaryAndThreshold () {
1035
+ void ProfileGeneratorBase::computeSummaryAndThreshold (
1036
+ SampleProfileMap &Profiles) {
1007
1037
SampleProfileSummaryBuilder Builder (ProfileSummaryBuilder::DefaultCutoffs);
1008
- Summary = Builder.computeSummaryForProfiles (ProfileMap );
1038
+ Summary = Builder.computeSummaryForProfiles (Profiles );
1009
1039
HotCountThreshold = ProfileSummaryBuilder::getHotCountThreshold (
1010
1040
(Summary->getDetailedSummary ()));
1011
1041
ColdCountThreshold = ProfileSummaryBuilder::getColdCountThreshold (
1012
1042
(Summary->getDetailedSummary ()));
1013
1043
}
1014
1044
1045
+ void CSProfileGenerator::computeSummaryAndThreshold () {
1046
+ // Always merge and use context-less profile map to compute summary.
1047
+ SampleProfileMap ContextLessProfiles;
1048
+ ContextTracker.createContextLessProfileMap (ContextLessProfiles);
1049
+
1050
+ // Set the flag below to avoid merging the profile again in
1051
+ // computeSummaryAndThreshold
1052
+ FunctionSamples::ProfileIsCS = false ;
1053
+ assert (
1054
+ (!UseContextLessSummary.getNumOccurrences () || UseContextLessSummary) &&
1055
+ " Don't set --profile-summary-contextless to false for profile "
1056
+ " generation" );
1057
+ ProfileGeneratorBase::computeSummaryAndThreshold (ContextLessProfiles);
1058
+ // Recover the old value.
1059
+ FunctionSamples::ProfileIsCS = true ;
1060
+ }
1061
+
1015
1062
void ProfileGeneratorBase::extractProbesFromRange (
1016
1063
const RangeSample &RangeCounter, ProbeCounterMap &ProbeCounter,
1017
1064
bool FindDisjointRanges) {
0 commit comments