llvm.org GIT mirror llvm / 93150c7
Temporarily revert r323062 to investigate buildbot failures git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@323065 91177308-0d34-0410-b5e6-96231b3b80d8 Eugene Leviant 2 years ago
14 changed file(s) with 35 addition(s) and 435 deletion(s). Raw diff Collapse all Expand all
6868 using GlobalValueSummaryList = std::vector>;
6969
7070 struct GlobalValueSummaryInfo {
71 union NameOrGV {
72 NameOrGV(bool IsAnalysis) {
73 if (IsAnalysis)
74 GV = nullptr;
75 else
76 Name = "";
77 }
78
79 /// The GlobalValue corresponding to this summary. This is only used in
80 /// per-module summaries, when module analysis is being run.
81 const GlobalValue *GV;
82
83 /// Summary string representation. This StringRef points to BC module
84 /// string table and is valid until module data is stored in memory.
85 /// This is guaranteed to happen until runThinLTOBackend function is
86 /// called, so it is safe to use this field during thin link. This field
87 /// is only valid if summary index was loaded from BC file.
88 StringRef Name;
89 } U;
90
91 GlobalValueSummaryInfo(bool IsAnalysis) : U(IsAnalysis) {}
71 /// The GlobalValue corresponding to this summary. This is only used in
72 /// per-module summaries.
73 const GlobalValue *GV = nullptr;
9274
9375 /// List of global value summary structures for a particular value held
9476 /// in the GlobalValueMap. Requires a vector in the case of multiple
10890 /// Struct that holds a reference to a particular GUID in a global value
10991 /// summary.
11092 struct ValueInfo {
111 PointerIntPair
112 RefAndFlag;
93 const GlobalValueSummaryMapTy::value_type *Ref = nullptr;
11394
11495 ValueInfo() = default;
115 ValueInfo(bool IsAnalysis, const GlobalValueSummaryMapTy::value_type *R) {
116 RefAndFlag.setPointer(R);
117 RefAndFlag.setInt(IsAnalysis);
118 }
119
120 operator bool() const { return getRef(); }
121
122 GlobalValue::GUID getGUID() const { return getRef()->first; }
123 const GlobalValue *getValue() const {
124 assert(isFromAnalysis());
125 return getRef()->second.U.GV;
126 }
96 ValueInfo(const GlobalValueSummaryMapTy::value_type *Ref) : Ref(Ref) {}
97
98 operator bool() const { return Ref; }
99
100 GlobalValue::GUID getGUID() const { return Ref->first; }
101 const GlobalValue *getValue() const { return Ref->second.GV; }
127102
128103 ArrayRef> getSummaryList() const {
129 return getRef()->second.SummaryList;
130 }
131
132 StringRef name() const {
133 return isFromAnalysis() ? getRef()->second.U.GV->getName()
134 : getRef()->second.U.Name;
135 }
136
137 bool isFromAnalysis() const { return RefAndFlag.getInt(); }
138
139 const GlobalValueSummaryMapTy::value_type *getRef() const {
140 return RefAndFlag.getPointer();
104 return Ref->second.SummaryList;
141105 }
142106 };
143107
144108 template <> struct DenseMapInfo {
145109 static inline ValueInfo getEmptyKey() {
146 return ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-8);
110 return ValueInfo((GlobalValueSummaryMapTy::value_type *)-1);
147111 }
148112
149113 static inline ValueInfo getTombstoneKey() {
150 return ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-16);
151 }
152
153 static inline bool isSpecialKey(ValueInfo V) {
154 return V == getTombstoneKey() || V == getEmptyKey();
155 }
156
157 static bool isEqual(ValueInfo L, ValueInfo R) {
158 // We are not supposed to mix ValueInfo(s) with different analysis flag
159 // in a same container.
160 assert(isSpecialKey(L) || isSpecialKey(R) ||
161 (L.isFromAnalysis() == R.isFromAnalysis()));
162 return L.getRef() == R.getRef();
163 }
164 static unsigned getHashValue(ValueInfo I) { return (uintptr_t)I.getRef(); }
114 return ValueInfo((GlobalValueSummaryMapTy::value_type *)-2);
115 }
116
117 static bool isEqual(ValueInfo L, ValueInfo R) { return L.Ref == R.Ref; }
118 static unsigned getHashValue(ValueInfo I) { return (uintptr_t)I.Ref; }
165119 };
166120
167121 /// \brief Function and variable summary information to aid decisions and
664618 /// considered live.
665619 bool WithGlobalValueDeadStripping = false;
666620
667 /// If true then we're performing analysis of IR module, filling summary
668 /// accordingly. The value of 'false' means we're reading summary from
669 /// BC or YAML source. Affects the type of value stored in NameOrGV union
670 bool IsAnalysis;
671
672621 std::set CfiFunctionDefs;
673622 std::set CfiFunctionDecls;
674623
677626
678627 GlobalValueSummaryMapTy::value_type *
679628 getOrInsertValuePtr(GlobalValue::GUID GUID) {
680 return &*GlobalValueMap.emplace(GUID, GlobalValueSummaryInfo(IsAnalysis)).first;
629 return &*GlobalValueMap.emplace(GUID, GlobalValueSummaryInfo{}).first;
681630 }
682631
683632 public:
684 // See IsAnalysis variable comment.
685 ModuleSummaryIndex(bool IsPerformingAnalysis)
686 : IsAnalysis(IsPerformingAnalysis) {}
687
688 bool isPerformingAnalysis() const { return IsAnalysis; }
689
690633 gvsummary_iterator begin() { return GlobalValueMap.begin(); }
691634 const_gvsummary_iterator begin() const { return GlobalValueMap.begin(); }
692635 gvsummary_iterator end() { return GlobalValueMap.end(); }
708651 /// Return a ValueInfo for GUID if it exists, otherwise return ValueInfo().
709652 ValueInfo getValueInfo(GlobalValue::GUID GUID) const {
710653 auto I = GlobalValueMap.find(GUID);
711 return ValueInfo(IsAnalysis, I == GlobalValueMap.end() ? nullptr : &*I);
654 return ValueInfo(I == GlobalValueMap.end() ? nullptr : &*I);
712655 }
713656
714657 /// Return a ValueInfo for \p GUID.
715658 ValueInfo getOrInsertValueInfo(GlobalValue::GUID GUID) {
716 return ValueInfo(IsAnalysis, getOrInsertValuePtr(GUID));
717 }
718
719 /// Return a ValueInfo for \p GUID setting value \p Name.
720 ValueInfo getOrInsertValueInfo(GlobalValue::GUID GUID, StringRef Name) {
721 assert(!IsAnalysis);
722 auto VP = getOrInsertValuePtr(GUID);
723 VP->second.U.Name = Name;
724 return ValueInfo(IsAnalysis, VP);
659 return ValueInfo(getOrInsertValuePtr(GUID));
725660 }
726661
727662 /// Return a ValueInfo for \p GV and mark it as belonging to GV.
728663 ValueInfo getOrInsertValueInfo(const GlobalValue *GV) {
729 assert(IsAnalysis);
730664 auto VP = getOrInsertValuePtr(GV->getGUID());
731 VP->second.U.GV = GV;
732 return ValueInfo(IsAnalysis, VP);
665 VP->second.GV = GV;
666 return ValueInfo(VP);
733667 }
734668
735669 /// Return the GUID for \p OriginalId in the OidGuidMap.
757691 addOriginalName(VI.getGUID(), Summary->getOriginalName());
758692 // Here we have a notionally const VI, but the value it points to is owned
759693 // by the non-const *this.
760 const_cast(VI.getRef())
694 const_cast(VI.Ref)
761695 ->second.SummaryList.push_back(std::move(Summary));
762696 }
763697
888822 /// Summary).
889823 void collectDefinedGVSummariesPerModule(
890824 StringMap &ModuleToDefinedGVSummaries) const;
891
892 /// Export summary to dot file for GraphViz.
893 void exportToDot(raw_ostream& OS) const;
894825 };
895826
896827 } // end namespace llvm
206206 io.setError("key not an integer");
207207 return;
208208 }
209 auto P = V.emplace(KeyInt, /*IsAnalysis=*/false);
210 auto &Elem = (*P.first).second;
209 auto &Elem = V[KeyInt];
211210 for (auto &FSum : FSums) {
212211 Elem.SummaryList.push_back(llvm::make_unique(
213212 GlobalValueSummary::GVFlags(
371371 std::function GetBFICallback,
372372 ProfileSummaryInfo *PSI) {
373373 assert(PSI);
374 ModuleSummaryIndex Index(/*IsPerformingAnalysis=*/true);
374 ModuleSummaryIndex Index;
375375
376376 // Identify the local values in the llvm.used and llvm.compiler.used sets,
377377 // which should not be exported as they would then require renaming and
48124812 if (PrintSummaryGUIDs)
48134813 dbgs() << "GUID " << ValueGUID << "(" << OriginalNameID << ") is "
48144814 << ValueName << "\n";
4815
4816 // UseStrtab is false for legacy summary formats and value names are
4817 // created on stack. We can't use them outside of parseValueSymbolTable.
4818 ValueIdToValueInfoMap[ValueID] = std::make_pair(
4819 TheIndex.getOrInsertValueInfo(ValueGUID, UseStrtab ? ValueName : ""),
4820 OriginalNameID);
4815 ValueIdToValueInfoMap[ValueID] =
4816 std::make_pair(TheIndex.getOrInsertValueInfo(ValueGUID), OriginalNameID);
48214817 }
48224818
48234819 // Specialized value symbol table parser used when reading module index
56825678 BitstreamCursor Stream(Buffer);
56835679 Stream.JumpToBit(ModuleBit);
56845680
5685 auto Index =
5686 llvm::make_unique(/*IsPerformingAnalysis=*/false);
5681 auto Index = llvm::make_unique();
56875682 ModuleSummaryIndexBitcodeReader R(std::move(Stream), Strtab, *Index,
56885683 ModuleIdentifier, 0);
56895684
1313
1414 #include "llvm/IR/ModuleSummaryIndex.h"
1515 #include "llvm/ADT/StringMap.h"
16 #include "llvm/Support/Path.h"
1716 using namespace llvm;
1817
1918 // Collect for the given module the list of function it defines
6968 return true;
7069 return false;
7170 }
72
73 namespace {
74 struct Attributes {
75 void add(const Twine &Name, const Twine &Value,
76 const Twine &Comment = Twine());
77 std::string getAsString() const;
78
79 std::vector Attrs;
80 std::string Comments;
81 };
82
83 struct Edge {
84 uint64_t SrcMod;
85 int Hotness;
86 GlobalValue::GUID Src;
87 GlobalValue::GUID Dst;
88 };
89 }
90
91 void Attributes::add(const Twine &Name, const Twine &Value,
92 const Twine &Comment) {
93 std::string A = Name.str();
94 A += "=\"";
95 A += Value.str();
96 A += "\"";
97 Attrs.push_back(A);
98 if (!Comment.isTriviallyEmpty()) {
99 if (Comments.empty())
100 Comments = " // ";
101 else
102 Comments += ", ";
103 Comments += Comment.str();
104 }
105 }
106
107 std::string Attributes::getAsString() const {
108 if (Attrs.empty())
109 return "";
110
111 std::string Ret = "[";
112 for (auto &A : Attrs)
113 Ret += A + ",";
114 Ret.pop_back();
115 Ret += "];";
116 Ret += Comments;
117 return Ret;
118 }
119
120 static std::string linkageToString(GlobalValue::LinkageTypes LT) {
121 switch (LT) {
122 case GlobalValue::ExternalLinkage:
123 return "extern";
124 case GlobalValue::AvailableExternallyLinkage:
125 return "av_ext";
126 case GlobalValue::LinkOnceAnyLinkage:
127 return "linkonce";
128 case GlobalValue::LinkOnceODRLinkage:
129 return "linkonce_odr";
130 case GlobalValue::WeakAnyLinkage:
131 return "weak";
132 case GlobalValue::WeakODRLinkage:
133 return "weak_odr";
134 case GlobalValue::AppendingLinkage:
135 return "appending";
136 case GlobalValue::InternalLinkage:
137 return "internal";
138 case GlobalValue::PrivateLinkage:
139 return "private";
140 case GlobalValue::ExternalWeakLinkage:
141 return "extern_weak";
142 case GlobalValue::CommonLinkage:
143 return "common";
144 }
145
146 return "";
147 }
148
149 static std::string fflagsToString(FunctionSummary::FFlags F) {
150 auto FlagValue = [](unsigned V) { return V ? '1' : '0'; };
151 char FlagRep[] = {FlagValue(F.ReadNone), FlagValue(F.ReadOnly),
152 FlagValue(F.NoRecurse), FlagValue(F.ReturnDoesNotAlias), 0};
153
154 return FlagRep;
155 }
156
157 // Get string representation of function instruction count and flags.
158 static std::string getSummaryAttributes(GlobalValueSummary* GVS) {
159 auto *FS = dyn_cast_or_null(GVS);
160 if (!FS)
161 return "";
162
163 return std::string("inst: ") + std::to_string(FS->instCount()) +
164 ", ffl: " + fflagsToString(FS->fflags());
165 }
166
167 static std::string getNodeVisualName(const ValueInfo &VI) {
168 return VI.name().empty() ? std::string("@") + std::to_string(VI.getGUID())
169 : VI.name().str();
170 }
171
172 static std::string getNodeLabel(const ValueInfo &VI, GlobalValueSummary *GVS) {
173 if (isa(GVS))
174 return getNodeVisualName(VI);
175
176 std::string Attrs = getSummaryAttributes(GVS);
177 std::string Label =
178 getNodeVisualName(VI) + "|" + linkageToString(GVS->linkage());
179 if (!Attrs.empty())
180 Label += std::string(" (") + Attrs + ")";
181 Label += "}";
182
183 return Label;
184 }
185
186 // Write definition of external node, which doesn't have any
187 // specific module associated with it. Typically this is function
188 // or variable defined in native object or library.
189 static void defineExternalNode(raw_ostream &OS, const char *Pfx,
190 const ValueInfo &VI) {
191 auto StrId = std::to_string(VI.getGUID());
192 OS << " " << StrId << " [label=\"" << getNodeVisualName(VI)
193 << "\"]; // defined externally\n";
194 }
195
196 void ModuleSummaryIndex::exportToDot(raw_ostream& OS) const {
197 std::vector CrossModuleEdges;
198 DenseMap> NodeMap;
199 StringMap ModuleToDefinedGVS;
200 collectDefinedGVSummariesPerModule(ModuleToDefinedGVS);
201
202 // Get node identifier in form MXXX_. The MXXX prefix is required,
203 // because we may have multiple linkonce functions summaries.
204 auto NodeId = [](uint64_t ModId, GlobalValue::GUID Id) {
205 return ModId == (uint64_t)-1 ? std::to_string(Id)
206 : std::string("M") + std::to_string(ModId) +
207 "_" + std::to_string(Id);
208 };
209
210 auto DrawEdge = [&](const char *Pfx, int SrcMod, GlobalValue::GUID SrcId,
211 int DstMod, GlobalValue::GUID DstId, int TypeOrHotness) {
212 // 0 corresponds to alias edge, 1 to ref edge, 2 to call with unknown
213 // hotness, ...
214 TypeOrHotness += 2;
215 static const char *EdgeAttrs[] = {
216 " [style=dotted]; // alias",
217 " [style=dashed]; // ref",
218 " // call (hotness : Unknown)",
219 " [color=blue]; // call (hotness : Cold)",
220 " // call (hotness : None)",
221 " [color=brown]; // call (hotness : Hot)",
222 " [style=bold,color=red]; // call (hotness : Critical)"};
223
224 assert(static_cast(TypeOrHotness) <
225 sizeof(EdgeAttrs) / sizeof(EdgeAttrs[0]));
226 OS << Pfx << NodeId(SrcMod, SrcId) << " -> " << NodeId(DstMod, DstId)
227 << EdgeAttrs[TypeOrHotness] << "\n";
228 };
229
230 OS << "digraph Summary {\n";
231 for (auto &ModIt : ModuleToDefinedGVS) {
232 auto ModId = getModuleId(ModIt.first());
233 OS << " // Module: " << ModIt.first() << "\n";
234 OS << " subgraph cluster_" << std::to_string(ModId) << " {\n";
235 OS << " style = filled;\n";
236 OS << " color = lightgrey;\n";
237 OS << " label = \"" << sys::path::filename(ModIt.first()) << "\";\n";
238 OS << " node [style=filled,fillcolor=lightblue];\n";
239
240 auto &GVSMap = ModIt.second;
241 auto Draw = [&](GlobalValue::GUID IdFrom, GlobalValue::GUID IdTo, int Hotness) {
242 if (!GVSMap.count(IdTo)) {
243 CrossModuleEdges.push_back({ModId, Hotness, IdFrom, IdTo});
244 return;
245 }
246 DrawEdge(" ", ModId, IdFrom, ModId, IdTo, Hotness);
247 };
248
249 for (auto &SummaryIt : GVSMap) {
250 NodeMap[SummaryIt.first].push_back(ModId);
251 auto Flags = SummaryIt.second->flags();
252 Attributes A;
253 if (isa(SummaryIt.second)) {
254 A.add("shape", "record", "function");
255 } else if (isa(SummaryIt.second)) {
256 A.add("style", "dotted,filled", "alias");
257 A.add("shape", "box");
258 } else {
259 A.add("shape", "Mrecord", "variable");
260 }
261
262 auto VI = getValueInfo(SummaryIt.first);
263 A.add("label", getNodeLabel(VI, SummaryIt.second));
264 if (!Flags.Live)
265 A.add("fillcolor", "red", "dead");
266 else if (Flags.NotEligibleToImport)
267 A.add("fillcolor", "yellow", "not eligible to import");
268
269 OS << " " << NodeId(ModId, SummaryIt.first) << " " << A.getAsString()
270 << "\n";
271 }
272 OS << " // Edges:\n";
273
274 for (auto &SummaryIt : GVSMap) {
275 auto *GVS = SummaryIt.second;
276 for (auto &R : GVS->refs())
277 Draw(SummaryIt.first, R.getGUID(), -1);
278
279 if (auto *AS = dyn_cast_or_null(SummaryIt.second)) {
280 auto AliaseeOrigId = AS->getAliasee().getOriginalName();
281 auto AliaseeId = getGUIDFromOriginalID(AliaseeOrigId);
282
283 Draw(SummaryIt.first, AliaseeId ? AliaseeId : AliaseeOrigId, -2);
284 continue;
285 }
286
287 if (auto *FS = dyn_cast_or_null(SummaryIt.second))
288 for (auto &CGEdge : FS->calls())
289 Draw(SummaryIt.first, CGEdge.first.getGUID(),
290 static_cast(CGEdge.second.Hotness));
291 }
292 OS << " }\n";
293 }
294
295 for (auto &E : CrossModuleEdges) {
296 auto &ModList = NodeMap[E.Dst];
297 if (ModList.empty()) {
298 defineExternalNode(OS, " ", getValueInfo(E.Dst));
299 // Add fake module to the list to draw an edge to an external node
300 // in the loop below.
301 ModList.push_back(-1);
302 }
303 for (auto DstMod : ModList)
304 // The edge representing call or ref is drawn to every module where target
305 // symbol is defined. When target is a linkonce symbol there can be
306 // multiple edges representing a single call or ref, both intra-module and
307 // cross-module. As we've already drawn all intra-module edges before we
308 // skip it here.
309 if (DstMod != E.SrcMod)
310 DrawEdge(" ", E.SrcMod, E.Src, DstMod, E.Dst, E.Hotness);
311 }
312
313 OS << "}";
314 }
387387 Ctx(Conf), CombinedModule(llvm::make_unique("ld-temp.o", Ctx)),
388388 Mover(llvm::make_unique(*CombinedModule)) {}
389389
390 LTO::ThinLTOState::ThinLTOState(ThinBackend Backend)
391 : Backend(Backend), CombinedIndex(/*IsPeformingAnalysis*/ false) {
390 LTO::ThinLTOState::ThinLTOState(ThinBackend Backend) : Backend(Backend) {
392391 if (!Backend)
393392 this->Backend =
394393 createInProcessThinBackend(llvm::heavyweight_hardware_concurrency());
102102 if (EC)
103103 reportOpenError(Path, EC.message());
104104 WriteIndexToFile(Index, OS);
105
106 Path = OutputFileName + "index.dot";
107 raw_fd_ostream OSDot(Path, EC, sys::fs::OpenFlags::F_None);
108 if (EC)
109 reportOpenError(Path, EC.message());
110 Index.exportToDot(OSDot);
111105 return true;
112106 };
113107
591591 */
592592 std::unique_ptr ThinLTOCodeGenerator::linkCombinedIndex() {
593593 std::unique_ptr CombinedIndex =
594 llvm::make_unique(/*IsPeformingAnalysis=*/false);
594 llvm::make_unique();
595595 uint64_t NextModuleId = 0;
596596 for (auto &ModuleBuffer : Modules) {
597597 if (Error Err = readModuleSummaryIndex(ModuleBuffer.getMemBuffer(),
230230 // it, rather than needing to perform this mapping on each walk.
231231 auto GUID = Index.getGUIDFromOriginalID(VI.getGUID());
232232 if (GUID == 0)
233 return ValueInfo();
233 return nullptr;
234234 return Index.getValueInfo(GUID);
235235 }
236236
516516 for (auto &S : Entry.second.SummaryList)
517517 if (S->isLive()) {
518518 DEBUG(dbgs() << "Live root: " << Entry.first << "\n");
519 Worklist.push_back(ValueInfo(/*IsAnalysis=*/false, &Entry));
519 Worklist.push_back(ValueInfo(&Entry));
520520 ++LiveSymbols;
521521 break;
522522 }
15281528 }
15291529
15301530 bool LowerTypeTestsModule::runForTesting(Module &M) {
1531 ModuleSummaryIndex Summary(/*IsPerformingAnalysis=*/false);
1531 ModuleSummaryIndex Summary;
15321532
15331533 // Handle the command-line summary arguments. This code is for testing
15341534 // purposes only, so we handle errors directly.
583583 bool DevirtModule::runForTesting(
584584 Module &M, function_ref AARGetter,
585585 function_ref OREGetter) {
586 ModuleSummaryIndex Summary(/*IsPerformingAnalysis=*/false);
586 ModuleSummaryIndex Summary;
587587
588588 // Handle the command-line summary arguments. This code is for testing
589589 // purposes only, so we handle errors directly.
+0
-20
test/ThinLTO/X86/Inputs/dot-dumper.ll less more
None target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
1 target triple = "x86_64-unknown-linux-gnu"
2
3 @A = local_unnamed_addr global i32 10, align 4
4 @B = local_unnamed_addr global i32 20, align 4
5
6 ; Function Attrs: norecurse nounwind readonly uwtable
7 define i32 @foo() local_unnamed_addr #0 {
8 %1 = load i32, i32* @B, align 4
9 %2 = load i32, i32* @A, align 4
10 %3 = add nsw i32 %2, %1
11 ret i32 %3
12 }
13
14 ; Function Attrs: norecurse nounwind readnone uwtable
15 define i32 @bar() local_unnamed_addr {
16 ret i32 42
17 }
18
19 attributes #0 = { noinline }
+0
-54
test/ThinLTO/X86/dot-dumper.ll less more
None ; RUN: opt -module-summary %s -o %t1.bc
1 ; RUN: opt -module-summary %p/Inputs/dot-dumper.ll -o %t2.bc
2 ; RUN: llvm-lto2 run -save-temps %t1.bc %t2.bc -o %t3 \
3 ; RUN: -r=%t1.bc,main,px \
4 ; RUN: -r=%t1.bc,main_alias,p \
5 ; RUN: -r=%t1.bc,foo, \
6 ; RUN: -r=%t1.bc,A, \
7 ; RUN: -r=%t2.bc,foo,p \
8 ; RUN: -r=%t2.bc,bar,p \
9 ; RUN: -r=%t2.bc,A,p \
10 ; RUN: -r=%t2.bc,B,p
11 ; RUN: cat %t3.index.dot | FileCheck %s
12
13 ; CHECK: digraph Summary
14 ; CHECK-NEXT: Module:
15
16 ; CHECK-LABEL: subgraph cluster_0
17 ; Node definitions can appear in any order, but they should go before edge list.
18 ; CHECK: M0_[[MAIN_ALIAS:[0-9]+]] [{{.*}}main_alias{{.*}}]; // alias, dead
19 ; CHECK: M0_[[MAIN:[0-9]+]] [{{.*}}main|extern{{.*}}]; // function
20 ; CHECK: // Edges:
21 ; CHECK-NEXT: M0_[[MAIN_ALIAS]] -> M0_[[MAIN]] [{{.*}}]; // alias
22
23 ; CHECK-LABEL: subgraph cluster_1 {
24 ; CHECK: M1_[[A:[0-9]+]] [{{.*}}A|extern{{.*}}]; // variable
25
26 ; CHECK: M1_[[FOO:[0-9]+]] [{{.*}}foo|extern{{.*}}]; // function, not eligible to import
27 ; CHECK: M1_[[B:[0-9]+]] [{{.*}}B|extern{{.*}}]; // variable
28 ; CHECK: M1_[[BAR:[0-9]+]] [{{.*}}bar|extern{{.*}}]; // function, dead
29 ; CHECK: Edges:
30
31 ; Order of edges in dot file is undefined
32 ; CHECK: M1_[[FOO]] -> M1_[[B]] [{{.*}}]; // ref
33 ; CHECK: M1_[[FOO]] -> M1_[[A]] [{{.*}}]; // ref
34 ; CHECK: }
35
36 ; Cross-module edges
37 ; CHECK: M0_[[MAIN]] -> M1_[[A]] [{{.*}}]; // ref
38 ; CHECK: M0_[[MAIN]] -> M1_[[FOO]] // call
39
40 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
41 target triple = "x86_64-unknown-linux-gnu"
42
43 @A = external local_unnamed_addr global i32, align 4
44
45 ; Function Attrs: nounwind uwtable
46 define i32 @main() local_unnamed_addr {
47 %1 = tail call i32 (...) @foo()
48 %2 = load i32, i32* @A, align 4
49 %3 = add nsw i32 %2, %1
50 ret i32 %3
51 }
52 @main_alias = weak_odr alias i32 (), i32 ()* @main
53 declare i32 @foo(...) local_unnamed_addr
366366 /// This is meant to enable testing of ThinLTO combined index generation,
367367 /// currently available via the gold plugin via -thinlto.
368368 static void createCombinedModuleSummaryIndex() {
369 ModuleSummaryIndex CombinedIndex(/*IsPerformingAnalysis=*/false);
369 ModuleSummaryIndex CombinedIndex;
370370 uint64_t NextModuleId = 0;
371371 for (auto &Filename : InputFilenames) {
372372 ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename + "': ");