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-profgen/CSPreInliner.cpp b/llvm/tools/llvm-profgen/CSPreInliner.cpp --- a/llvm/tools/llvm-profgen/CSPreInliner.cpp +++ b/llvm/tools/llvm-profgen/CSPreInliner.cpp @@ -29,6 +29,7 @@ STATISTIC( PreInlNumCSInlinedHitGrowthLimit, "Number of functions with FDO inline stopped due to growth size limit"); +STATISTIC(PreInlNumTrimmed, "Number of cold base profiles trimmed"); // The switches specify inline thresholds used in SampleProfileLoader inlining. // TODO: the actual threshold to be tuned here because the size here is based @@ -38,6 +39,7 @@ extern cl::opt ProfileInlineGrowthLimit; extern cl::opt ProfileInlineLimitMin; extern cl::opt ProfileInlineLimitMax; +extern cl::opt CSProfTrimColdContext; cl::opt EnableCSPreInliner( "csspgo-preinliner", cl::Hidden, cl::init(false), @@ -252,7 +254,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"); @@ -267,5 +269,23 @@ // Make sure ProfileMap's key is consistent with FunctionSamples' name. SampleContextTrimmer(ProfileMap).canonicalizeContextProfiles(); + // Remove cold profiles from ProfileMap. + if (CSProfTrimColdContext && ColdCountThreshold) { + LLVM_DEBUG(dbgs() << "Trimming cold base profiles with ColdCountThreshold=" + << ColdCountThreshold << "\n"); + std::vector ColdProfiles; + for (const auto &It : ProfileMap) { + const SampleContext &Context = It.first; + const FunctionSamples &FunctionProfile = It.second; + if (Context.isBaseContext() && + (FunctionProfile.getTotalSamples() < HotCountThreshold)) + ColdProfiles.push_back(Context); + } + PreInlNumTrimmed+= ColdProfiles.size(); + for (auto &ContextName : ColdProfiles) { + ProfileMap.erase(ContextName); + } + } + LLVM_DEBUG(printProfileNames(ProfileMap, false)); } 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 @@ -49,7 +49,7 @@ "the threshold, it will be merged into context-less base " "profile.")); -static cl::opt CSProfTrimColdContext( +cl::opt CSProfTrimColdContext( "csprof-trim-cold-context", cl::init(false), cl::ZeroOrMore, cl::desc("If the total count of the profile after all merge is done " "is still smaller than threshold, it will be trimmed.")); @@ -658,16 +658,15 @@ if (EnableCSPreInliner) { CSPreInliner(ProfileMap, *Binary, HotCountThreshold, ColdCountThreshold) .run(); - } - - // 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()) { - SampleContextTrimmer(ProfileMap) - .trimAndMergeColdContextProfiles( - HotCountThreshold, CSProfTrimColdContext, CSProfMergeColdContext, - CSProfMaxColdContextDepth); + } else { + // Trim and merge cold context profile using cold threshold above. By + // default, we skip such merging and trimming when preinliner is on. + if (CSProfTrimColdContext || CSProfMergeColdContext) { + SampleContextTrimmer(ProfileMap) + .trimAndMergeColdContextProfiles( + HotCountThreshold, CSProfTrimColdContext, CSProfMergeColdContext, + CSProfMaxColdContextDepth); + } } }