diff --git a/llvm/include/llvm/ProfileData/SampleProf.h b/llvm/include/llvm/ProfileData/SampleProf.h --- a/llvm/include/llvm/ProfileData/SampleProf.h +++ b/llvm/include/llvm/ProfileData/SampleProf.h @@ -1124,11 +1124,15 @@ class SampleContextTrimmer { public: SampleContextTrimmer(SampleProfileMap &Profiles) : ProfileMap(Profiles){}; - // Trim and merge cold context profile when requested. + // Trim and merge cold context profile when requested. TrimBaseProfileOnly + // should only be effective when TrimColdContext is true. On top of + // TrimColdContext, TrimBaseProfileOnly can be used to specify to trim all + // cold profiles or only cold base profiles. void trimAndMergeColdContextProfiles(uint64_t ColdCountThreshold, bool TrimColdContext, bool MergeColdContext, - uint32_t ColdContextFrameLength); + uint32_t ColdContextFrameLength, + bool TrimBaseProfileOnly); // Canonicalize context profile name and attributes. void canonicalizeContextProfiles(); diff --git a/llvm/lib/ProfileData/SampleProf.cpp b/llvm/lib/ProfileData/SampleProf.cpp --- a/llvm/lib/ProfileData/SampleProf.cpp +++ b/llvm/lib/ProfileData/SampleProf.cpp @@ -331,7 +331,7 @@ void SampleContextTrimmer::trimAndMergeColdContextProfiles( uint64_t ColdCountThreshold, bool TrimColdContext, bool MergeColdContext, - uint32_t ColdContextFrameLength) { + uint32_t ColdContextFrameLength, bool TrimBaseProfileOnly) { if (!TrimColdContext && !MergeColdContext) return; @@ -343,10 +343,11 @@ // container std::vector> ColdProfiles; for (const auto &I : ProfileMap) { + const SampleContext &Context = I.first; const FunctionSamples &FunctionProfile = I.second; - if (FunctionProfile.getTotalSamples() >= ColdCountThreshold) - continue; - ColdProfiles.emplace_back(I.first, &I.second); + if (FunctionProfile.getTotalSamples() < ColdCountThreshold && + (!TrimBaseProfileOnly || Context.isBaseContext())) + ColdProfiles.emplace_back(Context, &I.second); } // Remove the cold profile from ProfileMap and merge them into diff --git a/llvm/test/tools/llvm-profgen/cs-preinline.test b/llvm/test/tools/llvm-profgen/cs-preinline.test --- a/llvm/test/tools/llvm-profgen/cs-preinline.test +++ b/llvm/test/tools/llvm-profgen/cs-preinline.test @@ -10,6 +10,11 @@ ; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/inline-cs-noprobe.perfscript --binary=%S/Inputs/inline-cs-noprobe.perfbin --output=%t --csspgo-preinliner=1 -sample-profile-cold-inline-threshold=0 ; RUN: FileCheck %s --input-file %t --check-prefix=CHECK-NO-PREINL +; Test cold profile trimming. Only base profiles should be dropped. +; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/inline-cs-noprobe.perfscript --binary=%S/Inputs/inline-cs-noprobe.perfbin --output=%t --csspgo-preinliner=1 --csprof-trim-cold-context=1 --profile-summary-hot-count=250 + +; RUN: FileCheck %s --input-file %t --check-prefix=CHECK-TRIM + ; CHECK-DEFAULT: [main:1 @ foo]:225:0 ; CHECK-DEFAULT-NEXT: 2.1: 14 ; CHECK-DEFAULT-NEXT: 3: 15 @@ -39,3 +44,8 @@ ; CHECK-NO-PREINL-NEXT:[bar]:84:0 ; CHECK-NO-PREINL-NEXT: 1: 14 ; CHECK-NO-PREINL-NEXT: !Attributes: 1 + +; CHECK-TRIM-NOT: [foo]:225:0 +; CHECK-TRIM:[foo:3.1 @ bar]:84:0 +; CHECK-TRIM-NEXT: 1: 14 +; CHECK-TRIM-NEXT: !Attributes: 3 diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp --- a/llvm/tools/llvm-profdata/llvm-profdata.cpp +++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp @@ -759,7 +759,7 @@ SampleContextTrimmer(ProfileMap) .trimAndMergeColdContextProfiles( SampleProfColdThreshold, SampleTrimColdContext, - SampleMergeColdContext, SampleColdContextFrameDepth); + SampleMergeColdContext, SampleColdContextFrameDepth, false); } auto WriterOrErr = diff --git a/llvm/tools/llvm-profgen/CSPreInliner.cpp b/llvm/tools/llvm-profgen/CSPreInliner.cpp --- a/llvm/tools/llvm-profgen/CSPreInliner.cpp +++ b/llvm/tools/llvm-profgen/CSPreInliner.cpp @@ -252,7 +252,7 @@ // trim out such profiles from the output. std::vector ProfilesToBeRemoved; for (auto &It : ProfileMap) { - SampleContext Context = It.second.getContext(); + SampleContext &Context = It.second.getContext(); if (!Context.isBaseContext() && !Context.hasState(InlinedContext)) { assert(Context.hasState(MergedContext) && "Not inlined context profile should be merged already"); diff --git a/llvm/tools/llvm-profgen/ProfileGenerator.cpp b/llvm/tools/llvm-profgen/ProfileGenerator.cpp --- a/llvm/tools/llvm-profgen/ProfileGenerator.cpp +++ b/llvm/tools/llvm-profgen/ProfileGenerator.cpp @@ -658,16 +658,17 @@ if (EnableCSPreInliner) { CSPreInliner(ProfileMap, *Binary, HotCountThreshold, ColdCountThreshold) .run(); + // Turn off the profile merger by default unless it is explicitly enabled. + if (!CSProfMergeColdContext.getNumOccurrences()) + CSProfMergeColdContext = false; } - // Trim and merge cold context profile using cold threshold above. By default, - // we skip such merging and trimming when preinliner is on. - if (!EnableCSPreInliner || CSProfTrimColdContext.getNumOccurrences() || - CSProfMergeColdContext.getNumOccurrences()) { + // Trim and merge cold context profile using cold threshold above. + if (CSProfTrimColdContext || CSProfMergeColdContext) { SampleContextTrimmer(ProfileMap) .trimAndMergeColdContextProfiles( HotCountThreshold, CSProfTrimColdContext, CSProfMergeColdContext, - CSProfMaxColdContextDepth); + CSProfMaxColdContextDepth, EnableCSPreInliner); } }