Index: llvm/include/llvm/IR/ModuleSummaryIndex.h =================================================================== --- llvm/include/llvm/IR/ModuleSummaryIndex.h +++ llvm/include/llvm/IR/ModuleSummaryIndex.h @@ -1376,7 +1376,9 @@ void dump() const; /// Export summary to dot file for GraphViz. - void exportToDot(raw_ostream& OS) const; + void + exportToDot(raw_ostream &OS, + const DenseSet &GUIDPreservedSymbols) const; /// Print out strongly connected components for debugging. void dumpSCCs(raw_ostream &OS); Index: llvm/include/llvm/LTO/Config.h =================================================================== --- llvm/include/llvm/LTO/Config.h +++ llvm/include/llvm/LTO/Config.h @@ -183,8 +183,9 @@ /// /// It is called regardless of whether the backend is in-process, although it /// is not called from individual backend processes. - using CombinedIndexHookFn = - std::function; + using CombinedIndexHookFn = std::function &GUIDPreservedSymbols)>; CombinedIndexHookFn CombinedIndexHook; /// This is a convenience function that configures this Config object to write Index: llvm/lib/Analysis/ModuleSummaryAnalysis.cpp =================================================================== --- llvm/lib/Analysis/ModuleSummaryAnalysis.cpp +++ llvm/lib/Analysis/ModuleSummaryAnalysis.cpp @@ -820,7 +820,7 @@ if (EC) report_fatal_error(Twine("Failed to open dot file ") + ModuleSummaryDotFile + ": " + EC.message() + "\n"); - Index.exportToDot(OSDot); + Index.exportToDot(OSDot, {}); } return Index; Index: llvm/lib/IR/ModuleSummaryIndex.cpp =================================================================== --- llvm/lib/IR/ModuleSummaryIndex.cpp +++ llvm/lib/IR/ModuleSummaryIndex.cpp @@ -405,7 +405,9 @@ return false; } -void ModuleSummaryIndex::exportToDot(raw_ostream &OS) const { +void ModuleSummaryIndex::exportToDot( + raw_ostream &OS, + const DenseSet &GUIDPreservedSymbols) const { std::vector CrossModuleEdges; DenseMap> NodeMap; using GVSOrderedMapTy = std::map; @@ -485,6 +487,8 @@ A.addComment("dsoLocal"); if (Flags.CanAutoHide) A.addComment("canAutoHide"); + if (GUIDPreservedSymbols.count(SummaryIt.first)) + A.addComment("preserved"); auto VI = getValueInfo(SummaryIt.first); A.add("label", getNodeLabel(VI, SummaryIt.second)); Index: llvm/lib/LTO/LTO.cpp =================================================================== --- llvm/lib/LTO/LTO.cpp +++ llvm/lib/LTO/LTO.cpp @@ -1264,7 +1264,8 @@ if (ThinLTO.ModuleMap.empty()) return Error::success(); - if (Conf.CombinedIndexHook && !Conf.CombinedIndexHook(ThinLTO.CombinedIndex)) + if (Conf.CombinedIndexHook && + !Conf.CombinedIndexHook(ThinLTO.CombinedIndex, GUIDPreservedSymbols)) return Error::success(); // Collect for each module the list of function it defines (GUID -> Index: llvm/lib/LTO/LTOBackend.cpp =================================================================== --- llvm/lib/LTO/LTOBackend.cpp +++ llvm/lib/LTO/LTOBackend.cpp @@ -101,23 +101,25 @@ setHook("4.opt", PostOptModuleHook); setHook("5.precodegen", PreCodeGenModuleHook); - CombinedIndexHook = [=](const ModuleSummaryIndex &Index) { - std::string Path = OutputFileName + "index.bc"; - std::error_code EC; - raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::OF_None); - // Because -save-temps is a debugging feature, we report the error - // directly and exit. - if (EC) - reportOpenError(Path, EC.message()); - WriteIndexToFile(Index, OS); - - Path = OutputFileName + "index.dot"; - raw_fd_ostream OSDot(Path, EC, sys::fs::OpenFlags::OF_None); - if (EC) - reportOpenError(Path, EC.message()); - Index.exportToDot(OSDot); - return true; - }; + CombinedIndexHook = + [=](const ModuleSummaryIndex &Index, + const DenseSet &GUIDPreservedSymbols) { + std::string Path = OutputFileName + "index.bc"; + std::error_code EC; + raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::OF_None); + // Because -save-temps is a debugging feature, we report the error + // directly and exit. + if (EC) + reportOpenError(Path, EC.message()); + WriteIndexToFile(Index, OS); + + Path = OutputFileName + "index.dot"; + raw_fd_ostream OSDot(Path, EC, sys::fs::OpenFlags::OF_None); + if (EC) + reportOpenError(Path, EC.message()); + Index.exportToDot(OSDot, GUIDPreservedSymbols); + return true; + }; return Error::success(); } Index: llvm/test/ThinLTO/X86/dot-dumper.ll =================================================================== --- llvm/test/ThinLTO/X86/dot-dumper.ll +++ llvm/test/ThinLTO/X86/dot-dumper.ll @@ -40,7 +40,7 @@ ; COMBINED-NEXT: label = "dot-dumper{{.*}}1.bc"; ; COMBINED-NEXT: node [style=filled,fillcolor=lightblue]; ; COMBINED-NEXT: M0_[[MAIN_ALIAS:[0-9]+]] [style="dotted,filled",shape="box",label="main_alias",fillcolor="red"]; // alias, dead -; COMBINED-NEXT: M0_[[MAIN:[0-9]+]] [shape="record",label="main|extern (inst: 4, ffl: 000000)}"]; // function +; COMBINED-NEXT: M0_[[MAIN:[0-9]+]] [shape="record",label="main|extern (inst: 4, ffl: 000000)}"]; // function, preserved ; COMBINED-NEXT: // Edges: ; COMBINED-NEXT: M0_[[MAIN_ALIAS]] -> M0_[[MAIN]] [style=dotted]; // alias ; COMBINED-NEXT: }