Index: llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h =================================================================== --- llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h +++ llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h @@ -1169,8 +1169,16 @@ /// Collect for each module the list of Summaries it defines (GUID -> /// Summary). - void collectDefinedGVSummariesPerModule( - StringMap &ModuleToDefinedGVSummaries) const; + template + void + collectDefinedGVSummariesPerModule(Map &ModuleToDefinedGVSummaries) const { + for (auto &GlobalList : *this) { + auto GUID = GlobalList.first; + for (auto &Summary : GlobalList.second.SummaryList) { + ModuleToDefinedGVSummaries[Summary->modulePath()][GUID] = Summary.get(); + } + } + } /// Print to an output stream. void print(raw_ostream &OS, bool IsForDebug = false) const; Index: llvm/trunk/lib/IR/ModuleSummaryIndex.cpp =================================================================== --- llvm/trunk/lib/IR/ModuleSummaryIndex.cpp +++ llvm/trunk/lib/IR/ModuleSummaryIndex.cpp @@ -65,17 +65,6 @@ } } -// Collect for each module the list of function it defines (GUID -> Summary). -void ModuleSummaryIndex::collectDefinedGVSummariesPerModule( - StringMap &ModuleToDefinedGVSummaries) const { - for (auto &GlobalList : *this) { - auto GUID = GlobalList.first; - for (auto &Summary : GlobalList.second.SummaryList) { - ModuleToDefinedGVSummaries[Summary->modulePath()][GUID] = Summary.get(); - } - } -} - GlobalValueSummary * ModuleSummaryIndex::getGlobalValueSummary(uint64_t ValueGUID, bool PerModuleIndex) const { @@ -341,7 +330,8 @@ void ModuleSummaryIndex::exportToDot(raw_ostream &OS) const { std::vector CrossModuleEdges; DenseMap> NodeMap; - StringMap ModuleToDefinedGVS; + using GVSOrderedMapTy = std::map; + std::map ModuleToDefinedGVS; collectDefinedGVSummariesPerModule(ModuleToDefinedGVS); // Get node identifier in form MXXX_. The MXXX prefix is required, @@ -378,12 +368,12 @@ OS << "digraph Summary {\n"; for (auto &ModIt : ModuleToDefinedGVS) { - auto ModId = getModuleId(ModIt.first()); - OS << " // Module: " << ModIt.first() << "\n"; + auto ModId = getModuleId(ModIt.first); + OS << " // Module: " << ModIt.first << "\n"; OS << " subgraph cluster_" << std::to_string(ModId) << " {\n"; OS << " style = filled;\n"; OS << " color = lightgrey;\n"; - OS << " label = \"" << sys::path::filename(ModIt.first()) << "\";\n"; + OS << " label = \"" << sys::path::filename(ModIt.first) << "\";\n"; OS << " node [style=filled,fillcolor=lightblue];\n"; auto &GVSMap = ModIt.second; Index: llvm/trunk/test/ThinLTO/X86/dot-dumper.ll =================================================================== --- llvm/trunk/test/ThinLTO/X86/dot-dumper.ll +++ llvm/trunk/test/ThinLTO/X86/dot-dumper.ll @@ -10,64 +10,59 @@ ; RUN: -r=%t2.bc,A,p \ ; RUN: -r=%t2.bc,B,p -; Never assume specific order of clusters, nodes or edges -; RUN: cat %t1.dot | FileCheck --check-prefix=STRUCTURE1 %s -; RUN: cat %t1.dot | FileCheck --check-prefix=CLUSTER0 --check-prefix=PERMODULE0 %s -; RUN: cat %t2.dot | FileCheck --check-prefix=STRUCTURE2 %s -; RUN: cat %t2.dot | FileCheck --check-prefix=CLUSTER1 --check-prefix=PERMODULE1 %s -; RUN: cat %t3.index.dot | FileCheck --check-prefix=STRUCTURE %s -; RUN: cat %t3.index.dot | FileCheck --check-prefix=CLUSTER0 --check-prefix=COMBINED0 %s -; RUN: cat %t3.index.dot | FileCheck --check-prefix=CLUSTER1 --check-prefix=COMBINED1 %s - -; %t1 index -; STRUCTURE1: digraph Summary { -; STRUCTURE1: subgraph cluster_0 -; STRUCTURE1: // Cross-module edges: -; STRUCTURE1: 0 [label="@0"]; // defined externally -; STRUCTURE1: M0_{{[0-9]+}} -> 0 [style=dotted]; // alias -; STRUCTURE1-DAG: [[A:[0-9]+]] [label="A"]; // defined externally -; STRUCTURE1-DAG: [[FOO:[0-9]+]] [label="foo"]; // defined externally -; STRUCTURE1-DAG: M0_{{[0-9]+}} -> [[FOO]] // call -; STRUCTURE1-DAG: M0_{{[0-9]+}} -> [[A]] [{{.*}}]; // const-ref -; STRUCTURE1-NEXT: } - -; %t2 index -; STRUCTURE2: digraph Summary { -; STRUCTURE2: subgraph cluster_0 -; STRUCTURE2: // Cross-module edges: -; STRUCTURE2-NEXT: } - -; Combined index -; STRUCTURE: digraph Summary { -; STRUCTURE-DAG: subgraph cluster_0 -; STRUCTURE-DAG: subgraph cluster_1 -; STRUCTURE: // Cross-module edges: -; STRUCTURE-DAG: M0_{{[0-9]+}} -> M1_{{[0-9]+}} // call -; STRUCTURE-DAG: M0_{{[0-9]+}} -> M1_{{[0-9]+}} [{{.*}}]; // const-ref -; STRUCTURE-NEXT: } - -; PERMODULE0: // Module: -; COMBINED0: // Module: {{.*}}1.bc -; CLUSTER0-NEXT: subgraph cluster_[[ID0:[0-1]]] { -; CLUSTER0-DAG: M[[ID0]]_[[MAIN_ALIAS:[0-9]+]] [{{.*}}main_alias{{.*}}]; // alias, dead -; CLUSTER0-DAG: M[[ID0]]_[[MAIN:[0-9]+]] [{{.*}}main|extern{{.*}}]; // function -; CLUSTER0-NEXT: // Edges: -; COMBINED0-NEXT: M[[ID0]]_[[MAIN_ALIAS]] -> M[[ID0]]_[[MAIN]] [{{.*}}]; // alias -; CLUSTER0-NEXT: } - -; PERMODULE1: // Module: -; COMBINED1: // Module: {{.*}}2.bc -; CLUSTER1-NEXT: subgraph cluster_[[ID1:[0-1]]] { -; CLUSTER1-DAG: M[[ID1]]_[[A:[0-9]+]] [{{.*}}A|extern{{.*}}]; // variable -; COMBINED1-SAME: , immutable -; CLUSTER1-DAG: M[[ID1]]_[[FOO:[0-9]+]] [{{.*}}foo|extern{{.*}} ffl: 00001{{.*}}]; // function -; CLUSTER1-DAG: M[[ID1]]_[[B:[0-9]+]] [{{.*}}B|extern{{.*}}]; // variable -; COMBINED1-SAME: , immutable -; CLUSTER1-DAG: M[[ID1]]_[[BAR:[0-9]+]] [{{.*}}bar|extern{{.*}}]; // function, dead -; CLUSTER1-NEXT: // Edges: -; CLUSTER1-DAG: M[[ID1]]_[[FOO]] -> M[[ID1]]_[[B]] [{{.*}}]; // const-ref -; CLUSTER1-DAG: M[[ID1]]_[[FOO]] -> M[[ID1]]_[[A]] [{{.*}}]; // const-ref -; CLUSTER1-DAG: } +; RUN: cat %t1.dot | FileCheck --check-prefix=PERMODULE %s +; RUN: cat %t3.index.dot | FileCheck --check-prefix=COMBINED %s + +; PERMODULE: digraph Summary { +; PERMODULE-NEXT: // Module: +; PERMODULE-NEXT: subgraph cluster_0 { +; PERMODULE-NEXT: style = filled; +; PERMODULE-NEXT: color = lightgrey; +; PERMODULE-NEXT: label = ""; +; PERMODULE-NEXT: node [style=filled,fillcolor=lightblue]; +; PERMODULE-NEXT: M0_[[MAIN_ALIAS:[0-9]+]] [style="dotted,filled",shape="box",label="main_alias",fillcolor="red"]; // alias, dead +; PERMODULE-NEXT: M0_[[MAIN:[0-9]+]] [shape="record",label="main|extern (inst: 4, ffl: 00000)}",fillcolor="red"]; // function, dead +; PERMODULE-NEXT: // Edges: +; PERMODULE-NEXT: } +; PERMODULE-NEXT: // Cross-module edges: +; PERMODULE-NEXT: 0 [label="@0"]; // defined externally +; PERMODULE-NEXT: M0_[[MAIN_ALIAS]] -> 0 [style=dotted]; // alias +; PERMODULE-NEXT: [[A:[0-9]+]] [label="A"]; // defined externally +; PERMODULE-NEXT: M0_[[MAIN]] -> [[A]] [style=dashed,color=forestgreen]; // const-ref +; PERMODULE-NEXT: [[FOO:[0-9]+]] [label="foo"]; // defined externally +; PERMODULE-NEXT: M0_[[MAIN]] -> [[FOO]] // call (hotness : Unknown) +; PERMODULE-NEXT: } + +; COMBINED: digraph Summary { +; COMBINED-NEXT: // Module: {{.*}}dot-dumper{{.*}}1.bc +; COMBINED-NEXT: subgraph cluster_0 { +; COMBINED-NEXT: style = filled; +; COMBINED-NEXT: color = lightgrey; +; 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: 00000)}"]; // function +; COMBINED-NEXT: // Edges: +; COMBINED-NEXT: M0_[[MAIN_ALIAS]] -> M0_[[MAIN]] [style=dotted]; // alias +; COMBINED-NEXT: } +; COMBINED-NEXT: // Module: {{.*}}dot-dumper{{.*}}2.bc +; COMBINED-NEXT: subgraph cluster_1 { +; COMBINED-NEXT: style = filled; +; COMBINED-NEXT: color = lightgrey; +; COMBINED-NEXT: label = "dot-dumper{{.*}}2.bc"; +; COMBINED-NEXT: node [style=filled,fillcolor=lightblue]; +; COMBINED-NEXT: M1_[[FOO:[0-9]+]] [shape="record",label="foo|extern (inst: 4, ffl: 00001)}"]; // function +; COMBINED-NEXT: M1_[[A:[0-9]+]] [shape="Mrecord",label="A|extern}"]; // variable, immutable +; COMBINED-NEXT: M1_[[B:[0-9]+]] [shape="Mrecord",label="B|extern}"]; // variable, immutable +; COMBINED-NEXT: M1_{{[0-9]+}} [shape="record",label="bar|extern (inst: 1, ffl: 00000)}",fillcolor="red"]; // function, dead +; COMBINED-NEXT: // Edges: +; COMBINED-NEXT: M1_[[FOO]] -> M1_[[B]] [style=dashed,color=forestgreen]; // const-ref +; COMBINED-NEXT: M1_[[FOO]] -> M1_[[A]] [style=dashed,color=forestgreen]; // const-ref +; COMBINED-NEXT: } +; COMBINED-NEXT: // Cross-module edges: +; COMBINED-NEXT: M0_[[MAIN]] -> M1_[[A]] [style=dashed,color=forestgreen]; // const-ref +; COMBINED-NEXT: M0_[[MAIN]] -> M1_[[FOO]] // call (hotness : Unknown) +; COMBINED-NEXT: } target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu"