1919#include " llvm/ADT/StringRef.h"
2020#include " llvm/Bitcode/BitcodeReader.h"
2121#include " llvm/IR/AutoUpgrade.h"
22- #include " llvm/IR/Constants.h"
2322#include " llvm/IR/Function.h"
2423#include " llvm/IR/GlobalAlias.h"
2524#include " llvm/IR/GlobalObject.h"
3029#include " llvm/IR/ModuleSummaryIndex.h"
3130#include " llvm/IRReader/IRReader.h"
3231#include " llvm/Linker/IRMover.h"
32+ #include " llvm/ProfileData/PGOCtxProfReader.h"
3333#include " llvm/Support/Casting.h"
3434#include " llvm/Support/CommandLine.h"
3535#include " llvm/Support/Debug.h"
@@ -185,6 +185,10 @@ static cl::opt<bool> ImportAssumeUniqueLocal(
185185 " user specify the full module path." ),
186186 cl::Hidden);
187187
188+ static cl::opt<std::string>
189+ ContextualProfile (" thinlto-pgo-ctx-prof" ,
190+ cl::desc (" Path to a contextual profile." ), cl::Hidden);
191+
188192namespace llvm {
189193extern cl::opt<bool > EnableMemProfContextDisambiguation;
190194}
@@ -604,13 +608,7 @@ class WorkloadImportsManager : public ModuleImportsManager {
604608 LLVM_DEBUG (dbgs () << " [Workload] Done\n " );
605609 }
606610
607- public:
608- WorkloadImportsManager (
609- function_ref<bool (GlobalValue::GUID, const GlobalValueSummary *)>
610- IsPrevailing,
611- const ModuleSummaryIndex &Index,
612- DenseMap<StringRef, FunctionImporter::ExportSetTy> *ExportLists)
613- : ModuleImportsManager(IsPrevailing, Index, ExportLists) {
611+ void loadFromJson () {
614612 // Since the workload def uses names, we need a quick lookup
615613 // name->ValueInfo.
616614 StringMap<ValueInfo> NameToValueInfo;
@@ -680,15 +678,81 @@ class WorkloadImportsManager : public ModuleImportsManager {
680678 }
681679 Set.insert (ElemIt->second );
682680 }
683- LLVM_DEBUG ({
681+ }
682+ }
683+
684+ void loadFromCtxProf () {
685+ std::error_code EC;
686+ auto BufferOrErr = MemoryBuffer::getFileOrSTDIN (ContextualProfile);
687+ if (std::error_code EC = BufferOrErr.getError ()) {
688+ report_fatal_error (" Failed to open contextual profile file" );
689+ return ;
690+ }
691+ auto Buffer = std::move (BufferOrErr.get ());
692+
693+ PGOCtxProfileReader Reader (Buffer->getBuffer ());
694+ auto Ctx = Reader.loadContexts ();
695+ if (!Ctx) {
696+ report_fatal_error (" Failed to parse contextual profiles" );
697+ return ;
698+ }
699+ const auto &CtxMap = *Ctx;
700+ DenseSet<GlobalValue::GUID> ContainedGUIDs;
701+ for (const auto &[RootGuid, Root] : CtxMap) {
702+ // Avoid ContainedGUIDs to get in/out of scope. Reuse its memory for
703+ // subsequent roots, but clear its contents.
704+ ContainedGUIDs.clear ();
705+
706+ auto RootVI = Index.getValueInfo (RootGuid);
707+ if (!RootVI) {
708+ LLVM_DEBUG (dbgs () << " [Workload] Root " << RootGuid
709+ << " not found in this linkage unit.\n " );
710+ continue ;
711+ }
712+ if (RootVI.getSummaryList ().size () != 1 ) {
713+ LLVM_DEBUG (dbgs () << " [Workload] Root " << RootGuid
714+ << " should have exactly one summary, but has "
715+ << RootVI.getSummaryList ().size () << " . Skipping.\n " );
716+ continue ;
717+ }
718+ StringRef RootDefiningModule =
719+ RootVI.getSummaryList ().front ()->modulePath ();
720+ LLVM_DEBUG (dbgs () << " [Workload] Root defining module for " << RootGuid
721+ << " is : " << RootDefiningModule << " \n " );
722+ auto &Set = Workloads[RootDefiningModule];
723+ Root.getContainedGuids (ContainedGUIDs);
724+ for (auto Guid : ContainedGUIDs)
725+ if (auto VI = Index.getValueInfo (Guid))
726+ Set.insert (VI);
727+ }
728+ }
729+
730+ public:
731+ WorkloadImportsManager (
732+ function_ref<bool (GlobalValue::GUID, const GlobalValueSummary *)>
733+ IsPrevailing,
734+ const ModuleSummaryIndex &Index,
735+ DenseMap<StringRef, FunctionImporter::ExportSetTy> *ExportLists)
736+ : ModuleImportsManager(IsPrevailing, Index, ExportLists) {
737+ if (ContextualProfile.empty () == WorkloadDefinitions.empty ()) {
738+ report_fatal_error (
739+ " Pass only one of: -thinlto-pgo-ctx-prof or -thinlto-workload-def" );
740+ return ;
741+ }
742+ if (!ContextualProfile.empty ())
743+ loadFromCtxProf ();
744+ else
745+ loadFromJson ();
746+ LLVM_DEBUG ({
747+ for (const auto &[Root, Set] : Workloads) {
684748 dbgs () << " [Workload] Root: " << Root << " we have " << Set.size ()
685749 << " distinct callees.\n " ;
686750 for (const auto &VI : Set) {
687751 dbgs () << " [Workload] Root: " << Root
688752 << " Would include: " << VI.getGUID () << " \n " ;
689753 }
690- });
691- }
754+ }
755+ });
692756 }
693757};
694758
@@ -697,7 +761,7 @@ std::unique_ptr<ModuleImportsManager> ModuleImportsManager::create(
697761 IsPrevailing,
698762 const ModuleSummaryIndex &Index,
699763 DenseMap<StringRef, FunctionImporter::ExportSetTy> *ExportLists) {
700- if (WorkloadDefinitions.empty ()) {
764+ if (WorkloadDefinitions.empty () && ContextualProfile. empty () ) {
701765 LLVM_DEBUG (dbgs () << " [Workload] Using the regular imports manager.\n " );
702766 return std::unique_ptr<ModuleImportsManager>(
703767 new ModuleImportsManager (IsPrevailing, Index, ExportLists));
0 commit comments