Skip to content

Commit d924501

Browse files
committed
[llvm-profgen] Filter out ambiguous profiles during profile generation
1 parent 5992b32 commit d924501

File tree

6 files changed

+68
-3
lines changed

6 files changed

+68
-3
lines changed

llvm/include/llvm/ProfileData/SampleProf.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ struct SampleContextFrame {
466466
LineLocation Location;
467467

468468
SampleContextFrame() : Location(0, 0) {}
469-
469+
470470
SampleContextFrame(FunctionId Func, LineLocation Location)
471471
: Func(Func), Location(Location) {}
472472

@@ -527,7 +527,7 @@ class SampleContext {
527527
: Func(Name), State(UnknownContext), Attributes(ContextNone) {
528528
assert(!Name.empty() && "Name is empty");
529529
}
530-
530+
531531
SampleContext(FunctionId Func)
532532
: Func(Func), State(UnknownContext), Attributes(ContextNone) {}
533533

@@ -975,6 +975,8 @@ class FunctionSamples {
975975
return CallsiteSamples;
976976
}
977977

978+
CallsiteSampleMap &getCallsiteSamples() { return CallsiteSamples; }
979+
978980
/// Return the maximum of sample counts in a function body. When SkipCallSite
979981
/// is false, which is the default, the return count includes samples in the
980982
/// inlined functions. When SkipCallSite is true, the return count only

llvm/lib/Transforms/IPO/SampleProfile.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1129,7 +1129,7 @@ void SampleProfileLoader::findExternalInlineCandidate(
11291129
CalleeSample->getContext().hasAttribute(ContextShouldBeInlined);
11301130
if (!PreInline && CalleeSample->getHeadSamplesEstimate() < Threshold)
11311131
continue;
1132-
1132+
11331133
Function *Func = SymbolMap.lookup(CalleeSample->getFunction());
11341134
// Add to the import list only when it's defined out of module.
11351135
if (!Func || Func->isDeclaration())
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
foo:12345:1000
2+
1: 1000
3+
4: bar:1000
4+
1: 1000
5+
2: __tls_init.llvm.123:1
6+
1: 1
7+
3: goo:300
8+
1: 300
9+
8: __cxx_global_var_init.4:4
10+
1: 1
11+
2: goo:3
12+
1: 3
13+
__cxx_global_var_init.1:1:1
14+
1: 1
15+
__tls_init.llvm.345:1:1
16+
1: 1
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
; RUN: llvm-profgen --format=text --llvm-sample-profile=%S/Inputs/filter-ambiguous-profile.prof --binary=%S/Inputs/inline-cs-noprobe.perfbin --csspgo-preinliner=0 --output=%t1 || FileCheck %s --input-file %t1
2+
3+
;CHECK: foo:12345:1000
4+
;CHECK-NEXT 1: 1000
5+
;CHECK-NEXT 4: bar:1000
6+
;CHECK-NEXT 1: 1000
7+
;CHECK-NEXT 3: goo:300
8+
;CHECK-NEXT 1: 300

llvm/tools/llvm-profgen/ProfileGenerator.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,39 @@ void ProfileGeneratorBase::showDensitySuggestion(double Density) {
196196
<< "% total samples: " << format("%.1f", Density) << "\n";
197197
}
198198

199+
// Those functions are usually cold but could have multiple versions, the
200+
// profile are either from one version or the merged version, which is
201+
// ambiguous. We can't attribute the profile for each version accurately, so
202+
// filter them out from the profile map.
203+
static constexpr const char *FuncPrefixsToFilter[] = {"__cxx_global_var_init",
204+
"__tls_init"};
205+
206+
bool ProfileGeneratorBase::filterAmbiguousProfile(FunctionSamples &FS) {
207+
for (const auto &Prefix : FuncPrefixsToFilter) {
208+
if (FS.getFuncName().starts_with(Prefix))
209+
return true;
210+
}
211+
212+
// Filter the function profiles for the inlinees.
213+
for (auto &Callees : FS.getCallsiteSamples()) {
214+
auto &CalleesMap = Callees.second;
215+
for (auto I = CalleesMap.begin(); I != CalleesMap.end();) {
216+
auto Tmp = I++;
217+
if (filterAmbiguousProfile(Tmp->second))
218+
CalleesMap.erase(Tmp);
219+
}
220+
}
221+
return false;
222+
}
223+
224+
void ProfileGeneratorBase::filterAmbiguousProfile(SampleProfileMap &Profiles) {
225+
for (auto I = ProfileMap.begin(); I != ProfileMap.end();) {
226+
auto Tmp = I++;
227+
if (filterAmbiguousProfile(Tmp->second))
228+
ProfileMap.erase(Tmp);
229+
}
230+
}
231+
199232
double ProfileGeneratorBase::calculateDensity(const SampleProfileMap &Profiles,
200233
uint64_t HotCntThreshold) {
201234
double Density = DBL_MAX;
@@ -492,6 +525,7 @@ void ProfileGenerator::postProcessProfiles() {
492525
computeSummaryAndThreshold(ProfileMap);
493526
trimColdProfiles(ProfileMap, ColdCountThreshold);
494527
calculateAndShowDensity(ProfileMap);
528+
filterAmbiguousProfile(ProfileMap);
495529
}
496530

497531
void ProfileGenerator::trimColdProfiles(const SampleProfileMap &Profiles,
@@ -1024,6 +1058,7 @@ void CSProfileGenerator::postProcessProfiles() {
10241058
CSConverter.convertCSProfiles();
10251059
FunctionSamples::ProfileIsCS = false;
10261060
}
1061+
filterAmbiguousProfile(ProfileMap);
10271062
}
10281063

10291064
void ProfileGeneratorBase::computeSummaryAndThreshold(

llvm/tools/llvm-profgen/ProfileGenerator.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ class ProfileGeneratorBase {
108108

109109
void updateCallsiteSamples();
110110

111+
void filterAmbiguousProfile(SampleProfileMap &Profiles);
112+
113+
bool filterAmbiguousProfile(FunctionSamples &FS);
114+
111115
StringRef getCalleeNameForAddress(uint64_t TargetAddress);
112116

113117
void computeSummaryAndThreshold(SampleProfileMap &ProfileMap);

0 commit comments

Comments
 (0)