Index: include/llvm/Transforms/IPO/SampleProfile.h =================================================================== --- include/llvm/Transforms/IPO/SampleProfile.h +++ include/llvm/Transforms/IPO/SampleProfile.h @@ -26,9 +26,11 @@ class SampleProfileLoaderPass : public PassInfoMixin { public: SampleProfileLoaderPass(std::string File = "", std::string RemappingFile = "", - bool IsThinLTOPreLink = false) + bool IsThinLTOPreLink = false, + bool IsThinLTOPostLink = false) : ProfileFileName(File), ProfileRemappingFileName(RemappingFile), - IsThinLTOPreLink(IsThinLTOPreLink) {} + IsThinLTOPreLink(IsThinLTOPreLink), + IsThinLTOPostLink(IsThinLTOPostLink) {} PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); @@ -36,6 +38,7 @@ std::string ProfileFileName; std::string ProfileRemappingFileName; bool IsThinLTOPreLink; + bool IsThinLTOPostLink; }; } // end namespace llvm Index: lib/Passes/PassBuilder.cpp =================================================================== --- lib/Passes/PassBuilder.cpp +++ lib/Passes/PassBuilder.cpp @@ -607,9 +607,9 @@ if (PGOOpt && !PGOOpt->SampleProfileFile.empty()) { // Annotate sample profile right after early FPM to ensure freshness of // the debug info. - MPM.addPass(SampleProfileLoaderPass(PGOOpt->SampleProfileFile, - PGOOpt->ProfileRemappingFile, - Phase == ThinLTOPhase::PreLink)); + MPM.addPass(SampleProfileLoaderPass( + PGOOpt->SampleProfileFile, PGOOpt->ProfileRemappingFile, + Phase == ThinLTOPhase::PreLink, Phase == ThinLTOPhase::PostLink)); // Do not invoke ICP in the ThinLTOPrelink phase as it makes it hard // for the profile annotation to be accurate in the ThinLTO backend. if (Phase != ThinLTOPhase::PreLink) Index: lib/Transforms/IPO/SampleProfile.cpp =================================================================== --- lib/Transforms/IPO/SampleProfile.cpp +++ lib/Transforms/IPO/SampleProfile.cpp @@ -123,6 +123,11 @@ cl::desc("Use this option to turn off/on warnings about function with " "samples but without debug information to use those samples. ")); +static cl::opt FlattenProfileUsed( + "flatten-profile-used", cl::init(false), cl::Hidden, + cl::desc("Indicate the sample profile being used is flatten, i.e., " + "no inline hierachy exists in the profile. ")); + namespace { using BlockWeightMap = DenseMap; @@ -191,11 +196,13 @@ public: SampleProfileLoader( StringRef Name, StringRef RemapName, bool IsThinLTOPreLink, + bool IsThinLTOPostLink, std::function GetAssumptionCache, std::function GetTargetTransformInfo) : GetAC(std::move(GetAssumptionCache)), GetTTI(std::move(GetTargetTransformInfo)), Filename(Name), - RemappingFilename(RemapName), IsThinLTOPreLink(IsThinLTOPreLink) {} + RemappingFilename(RemapName), IsThinLTOPreLink(IsThinLTOPreLink), + IsThinLTOPostLink(IsThinLTOPostLink) {} bool doInitialization(Module &M); bool runOnModule(Module &M, ModuleAnalysisManager *AM, @@ -300,6 +307,8 @@ /// In this phase, in annotation, we should not promote indirect calls. /// Instead, we will mark GUIDs that needs to be annotated to the function. bool IsThinLTOPreLink; + /// Flag indicating if the pass is invoked in ThinLTO backend compile phase. + bool IsThinLTOPostLink; /// Profile Summary Info computed from sample profile. ProfileSummaryInfo *PSI = nullptr; @@ -320,15 +329,17 @@ static char ID; SampleProfileLoaderLegacyPass(StringRef Name = SampleProfileFile, - bool IsThinLTOPreLink = false) - : ModulePass(ID), - SampleLoader(Name, SampleProfileRemappingFile, IsThinLTOPreLink, - [&](Function &F) -> AssumptionCache & { - return ACT->getAssumptionCache(F); - }, - [&](Function &F) -> TargetTransformInfo & { - return TTIWP->getTTI(F); - }) { + bool IsThinLTOPreLink = false, + bool IsThinLTOPostLink = false) + : ModulePass(ID), SampleLoader( + Name, SampleProfileRemappingFile, IsThinLTOPreLink, + IsThinLTOPostLink, + [&](Function &F) -> AssumptionCache & { + return ACT->getAssumptionCache(F); + }, + [&](Function &F) -> TargetTransformInfo & { + return TTIWP->getTTI(F); + }) { initializeSampleProfileLoaderLegacyPassPass( *PassRegistry::getPassRegistry()); } @@ -1516,6 +1527,14 @@ "Sample Profile loader", false, false) bool SampleProfileLoader::doInitialization(Module &M) { + // In ThinLTO mode, when flatten profile is used, all the available + // profile information will be annotated in Prelink phase so there is + // no need to read the profile again. + if (IsThinLTOPostLink && FlattenProfileUsed) + return false; + + LLVM_DEBUG(dbgs() << "SampleProfileLoader initialize for Module: " << M.getName() << "\n"); + auto &Ctx = M.getContext(); auto ReaderOrErr = SampleProfileReader::create(Filename, Ctx); if (std::error_code EC = ReaderOrErr.getError()) { @@ -1640,7 +1659,7 @@ ProfileFileName.empty() ? SampleProfileFile : ProfileFileName, ProfileRemappingFileName.empty() ? SampleProfileRemappingFile : ProfileRemappingFileName, - IsThinLTOPreLink, GetAssumptionCache, GetTTI); + IsThinLTOPreLink, IsThinLTOPostLink, GetAssumptionCache, GetTTI); SampleLoader.doInitialization(M); Index: test/Transforms/SampleProfile/Inputs/flatten.prof =================================================================== --- test/Transforms/SampleProfile/Inputs/flatten.prof +++ test/Transforms/SampleProfile/Inputs/flatten.prof @@ -0,0 +1,2 @@ +foo:100:100 + 1: 100 Index: test/Transforms/SampleProfile/flatten.ll =================================================================== --- test/Transforms/SampleProfile/flatten.ll +++ test/Transforms/SampleProfile/flatten.ll @@ -0,0 +1,30 @@ +; REQUIRES: asserts +; RUN: opt < %s -passes='thinlto' -pgo-kind=new-pm-pgo-sample-use-pipeline -profile-file=%S/Inputs/flatten.prof -debug-only=sample-profile -flatten-profile-used -S 2>&1| FileCheck %s +; +; Check SampleProfileLoader doesn't read the profile in ThinLTO postlink stage +; when flatten sample profile is used. +; CHECK-NOT: SampleProfileLoader initialize for Module: + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; Function Attrs: norecurse nounwind readnone uwtable +define dso_local i32 @foo() local_unnamed_addr !dbg !7 { +entry: + ret i32 -1, !dbg !9 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 8.0.0 (trunk 345241)", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "a.c", directory: "") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 8.0.0 (trunk 345241)"} +!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: true, unit: !0, retainedNodes: !2) +!8 = !DISubroutineType(types: !2) +!9 = !DILocation(line: 2, column: 3, scope: !7)