LLVM: lib/IR/ModuleSummaryIndex.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
20using namespace llvm;
21
22#define DEBUG_TYPE "module-summary-index"
23
25 "Number of live global variables marked read only");
27 "Number of live global variables marked write only");
28
31 cl::desc("Propagate attributes in index"));
32
35 cl::desc("Import constant global variables with references"));
36
40
42 bool HasProtected = false;
47 HasProtected = true;
48 }
51}
52
54
55
56 return WithDSOLocalPropagation
61 [](const std::unique_ptr &Summary) {
62 return Summary->isDSOLocal();
63 });
64}
65
67
70 [](const std::unique_ptr &Summary) {
71 return Summary->canAutoHide();
72 });
73}
74
75
77
78
79 auto Refs = refs();
80 unsigned RORefCnt = 0, WORefCnt = 0;
81 int I;
82 for (I = Refs.size() - 1; I >= 0 && Refs[I].isWriteOnly(); --I)
83 WORefCnt++;
84 for (; I >= 0 && Refs[I].isReadOnly(); --I)
85 RORefCnt++;
86 return {RORefCnt, WORefCnt};
87}
88
91
93 Flags |= 0x1;
95 Flags |= 0x2;
97 Flags |= 0x8;
99 Flags |= 0x10;
101 Flags |= 0x20;
103 Flags |= 0x40;
105 Flags |= 0x80;
107 Flags |= 0x100;
109 Flags |= 0x200;
111 Flags |= 0x400;
112 return Flags;
113}
114
116 assert(Flags <= 0x7ff && "Unexpected bits in flag");
117
118
119 if (Flags & 0x1)
121
122
123 if (Flags & 0x2)
125
126
127
128
129 if (Flags & 0x8)
131
132
133 if (Flags & 0x10)
135
136
137 if (Flags & 0x20)
139
140
141 if (Flags & 0x40)
143
144
145 if (Flags & 0x80)
147
148
149 if (Flags & 0x100)
151
152
153 if (Flags & 0x200)
155
156
157 if (Flags & 0x400)
159}
160
161
162
165 for (auto &GlobalList : *this) {
166 auto GUID = GlobalList.first;
167 for (auto &GlobSummary : GlobalList.second.getSummaryList()) {
169 if (!Summary)
170
171 continue;
172
173 if (Summary->modulePath() != ModulePath)
174 continue;
175 GVSummaryMap[GUID] = Summary;
176 }
177 }
178}
179
182 bool PerModuleIndex) const {
184 assert(VI && "GlobalValue not found in index");
185 assert((!PerModuleIndex || VI.getSummaryList().size() == 1) &&
186 "Expected a single entry per global value in per-module index");
187 auto &Summary = VI.getSummaryList()[0];
188 return Summary.get();
189}
190
193 if (!VI)
194 return true;
195 const auto &SummaryList = VI.getSummaryList();
196 if (SummaryList.empty())
197 return true;
198 for (auto &I : SummaryList)
200 return true;
201 return false;
202}
203
204static void
207
208
209
210
211
212
213
214
215 for (auto &VI : S->refs()) {
217 if (!VI.getAccessSpecifier()) {
218 if (!MarkedNonReadWriteOnly.insert(VI).second)
219 continue;
220 } else if (MarkedNonReadWriteOnly.contains(VI))
221 continue;
222 for (auto &Ref : VI.getSummaryList())
223
224
226 if (!VI.isReadOnly())
227 GVS->setReadOnly(false);
228 if (!VI.isWriteOnly())
229 GVS->setWriteOnly(false);
230 }
231 }
232}
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
264 return;
266 for (auto &P : *this) {
267 bool IsDSOLocal = true;
268 for (auto &S : P.second.getSummaryList()) {
270
271
272
273
274
275
276
278 P.second.getSummaryList(),
279 [&](const std::unique_ptr &Summary) {
280 return isGlobalValueLive(Summary.get());
281 }));
282
283 break;
284 }
285
286
287
288
289
290
291
292
293
294
296
297
298
300 GUIDPreservedSymbols.count(P.first)) {
301 GVS->setReadOnly(false);
302 GVS->setWriteOnly(false);
303 }
305
306
307 IsDSOLocal &= S->isDSOLocal();
308 }
309 if (!IsDSOLocal)
310
311
312 for (const std::unique_ptr &Summary :
313 P.second.getSummaryList())
314 Summary->setDSOLocal(false);
315 }
319 for (auto &P : *this)
320 if (P.second.getSummaryList().size())
322 P.second.getSummaryList()[0]->getBaseObject()))
324 if (GVS->maybeReadOnly())
325 ReadOnlyLiveGVars++;
326 if (GVS->maybeWriteOnly())
327 WriteOnlyLiveGVars++;
328 }
329}
330
332 bool AnalyzeRefs) const {
333 bool CanImportDecl;
335}
336
338 bool AnalyzeRefs,
339 bool &CanImportDecl) const {
340 auto HasRefsPreventingImport = [this](const GlobalVarSummary *GVS) {
341
342
343
344
345
346
347
348
349
350
351
352
353
354
357 };
359
360 const bool nonInterposable =
363
364
365
366 CanImportDecl = (nonInterposable && eligibleToImport);
367
368
369
370
371
372
373 return nonInterposable && eligibleToImport &&
374 (!AnalyzeRefs || !HasRefsPreventingImport(GVS));
375}
376
377
378
383 .isAtEnd(); ++I) {
384 O << "SCC (" << utostr(I->size()) << " node" << (I->size() == 1 ? "" : "s")
385 << ") {\n";
388 if (V.getSummaryList().size())
390 O << " " << (F == nullptr ? "External" : "") << " " << utostr(V.getGUID())
391 << (I.hasCycle() ? " (has cycle)" : "") << "\n";
392 }
393 O << "}\n";
394 }
395}
396
397namespace {
398struct Attributes {
401 void addComment(const Twine &Comment);
402 std::string getAsString() const;
403
404 std::vectorstd::string Attrs;
405 std::string Comments;
406};
407
408struct Edge {
410 int Hotness;
413};
414}
415
416void Attributes::add(const Twine &Name, const Twine &Value,
417 const Twine &Comment) {
418 std::string A = Name.str();
419 A += "=\"";
421 A += "\"";
423 addComment(Comment);
424}
425
426void Attributes::addComment(const Twine &Comment) {
427 if (.isTriviallyEmpty()) {
428 if (Comments.empty())
429 Comments = " // ";
430 else
431 Comments += ", ";
432 Comments += Comment.str();
433 }
434}
435
436std::string Attributes::getAsString() const {
437 if (Attrs.empty())
438 return "";
439
440 std::string Ret = "[";
441 for (auto &A : Attrs)
442 Ret += A + ",";
443 Ret.pop_back();
444 Ret += "];";
445 Ret += Comments;
446 return Ret;
447}
448
450 switch (LT) {
452 return "extern";
454 return "av_ext";
456 return "linkonce";
458 return "linkonce_odr";
460 return "weak";
462 return "weak_odr";
464 return "appending";
466 return "internal";
468 return "private";
470 return "extern_weak";
472 return "common";
473 }
474
475 return "";
476}
477
479 auto FlagValue = [](unsigned V) { return V ? '1' : '0'; };
480 char FlagRep[] = {FlagValue(F.ReadNone),
481 FlagValue(F.ReadOnly),
482 FlagValue(F.NoRecurse),
483 FlagValue(F.ReturnDoesNotAlias),
484 FlagValue(F.NoInline),
485 FlagValue(F.AlwaysInline),
486 FlagValue(F.NoUnwind),
487 FlagValue(F.MayThrow),
488 FlagValue(F.HasUnknownCall),
489 FlagValue(F.MustBeUnreachable),
490 0};
491
492 return FlagRep;
493}
494
495
498 if (!FS)
499 return "";
500
501 return std::string("inst: ") + std::to_string(FS->instCount()) +
503}
504
506 return std::string("@") + std::to_string(Id);
507}
508
510 return VI.name().empty() ? getNodeVisualName(VI.getGUID()) : VI.name().str();
511}
512
516
518 std::string Label =
520 if (!Attrs.empty())
521 Label += std::string(" (") + Attrs + ")";
522 Label += "}";
523
524 return Label;
525}
526
527
528
529
532 auto StrId = std::to_string(Id);
533 OS << " " << StrId << " [label=\"";
534
535 if (VI) {
537 } else {
539 }
540 OS << "\"]; // defined externally\n";
541}
542
545 return GVS->maybeReadOnly();
546 return false;
547}
548
551 return GVS->maybeWriteOnly();
552 return false;
553}
554
557 return GVS->isConstant();
558 return false;
559}
560
564 std::vector CrossModuleEdges;
566 using GVSOrderedMapTy = std::map<GlobalValue::GUID, GlobalValueSummary *>;
567 std::map<StringRef, GVSOrderedMapTy> ModuleToDefinedGVS;
569
570
571
572
573 std::vector ModulePaths;
575 ModulePaths.push_back(ModPath);
578 for (auto &ModPath : ModulePaths)
580
581
582
584 return ModId == (uint64_t)-1 ? std::to_string(Id)
585 : std::string("M") + std::to_string(ModId) +
586 "_" + std::to_string(Id);
587 };
588
591 int TypeOrHotness) {
592
593
594
595
596
597 TypeOrHotness += 4;
598 static const char *EdgeAttrs[] = {
599 " [style=dotted]; // alias",
600 " [style=dashed]; // ref",
601 " [style=dashed,color=forestgreen]; // const-ref",
602 " [style=dashed,color=violetred]; // writeOnly-ref",
603 " // call (hotness : Unknown)",
604 " [color=blue]; // call (hotness : Cold)",
605 " // call (hotness : None)",
606 " [color=brown]; // call (hotness : Hot)",
607 " [style=bold,color=red]; // call (hotness : Critical)"};
608
609 assert(static_cast<size_t>(TypeOrHotness) < std::size(EdgeAttrs));
610 OS << Pfx << NodeId(SrcMod, SrcId) << " -> " << NodeId(DstMod, DstId)
611 << EdgeAttrs[TypeOrHotness] << "\n";
612 };
613
614 OS << "digraph Summary {\n";
615 for (auto &ModIt : ModuleToDefinedGVS) {
616
617
618 assert(ModuleIdMap.count(ModIt.first) || ModuleIdMap.empty());
619 auto ModId = ModuleIdMap.empty() ? 0 : ModuleIdMap[ModIt.first];
620 OS << " // Module: " << ModIt.first << "\n";
621 OS << " subgraph cluster_" << std::to_string(ModId) << " {\n";
622 OS << " style = filled;\n";
623 OS << " color = lightgrey;\n";
625 OS << " node [style=filled,fillcolor=lightblue];\n";
626
627 auto &GVSMap = ModIt.second;
629 if (!GVSMap.count(IdTo)) {
630 CrossModuleEdges.push_back({ModId, Hotness, IdFrom, IdTo});
631 return;
632 }
633 DrawEdge(" ", ModId, IdFrom, ModId, IdTo, Hotness);
634 };
635
636 for (auto &SummaryIt : GVSMap) {
637 NodeMap[SummaryIt.first].push_back(ModId);
638 auto Flags = SummaryIt.second->flags();
639 Attributes A;
641 A.add("shape", "record", "function");
643 A.add("style", "dotted,filled", "alias");
644 A.add("shape", "box");
645 } else {
646 A.add("shape", "Mrecord", "variable");
648 A.addComment("immutable");
650 A.addComment("writeOnly");
652 A.addComment("constant");
653 }
654 if (Flags.Visibility)
655 A.addComment("visibility");
656 if (Flags.DSOLocal)
657 A.addComment("dsoLocal");
658 if (Flags.CanAutoHide)
659 A.addComment("canAutoHide");
661 A.addComment("definition");
663 A.addComment("declaration");
664 if (GUIDPreservedSymbols.count(SummaryIt.first))
665 A.addComment("preserved");
666
668 A.add("label", getNodeLabel(VI, SummaryIt.second));
669 if (!Flags.Live)
670 A.add("fillcolor", "red", "dead");
671 else if (Flags.NotEligibleToImport)
672 A.add("fillcolor", "yellow", "not eligible to import");
673
674 OS << " " << NodeId(ModId, SummaryIt.first) << " " << A.getAsString()
675 << "\n";
676 }
677 OS << " // Edges:\n";
678
679 for (auto &SummaryIt : GVSMap) {
680 auto *GVS = SummaryIt.second;
681 for (auto &R : GVS->refs())
682 Draw(SummaryIt.first, R.getGUID(),
683 R.isWriteOnly() ? -1 : (R.isReadOnly() ? -2 : -3));
684
686 Draw(SummaryIt.first, AS->getAliaseeGUID(), -4);
687 continue;
688 }
689
691 for (auto &CGEdge : FS->calls())
692 Draw(SummaryIt.first, CGEdge.first.getGUID(),
693 static_cast<int>(CGEdge.second.Hotness));
694 }
695 OS << " }\n";
696 }
697
698 OS << " // Cross-module edges:\n";
699 for (auto &E : CrossModuleEdges) {
700 auto &ModList = NodeMap[E.Dst];
701 if (ModList.empty()) {
703
704
705 ModList.push_back(-1);
706 }
707 for (auto DstMod : ModList)
708
709
710
711
712
713 if (DstMod != E.SrcMod)
714 DrawEdge(" ", E.SrcMod, E.Src, DstMod, E.Dst, E.Hotness);
715 }
716
717 OS << "}";
718}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
static std::string getNodeVisualName(GlobalValue::GUID Id)
Definition ModuleSummaryIndex.cpp:505
static std::string getNodeLabel(const ValueInfo &VI, GlobalValueSummary *GVS)
Definition ModuleSummaryIndex.cpp:513
static std::string getSummaryAttributes(GlobalValueSummary *GVS)
Definition ModuleSummaryIndex.cpp:496
static cl::opt< bool > ImportConstantsWithRefs("import-constants-with-refs", cl::init(true), cl::Hidden, cl::desc("Import constant global variables with references"))
static std::string fflagsToString(FunctionSummary::FFlags F)
Definition ModuleSummaryIndex.cpp:478
static bool hasWriteOnlyFlag(const GlobalValueSummary *S)
Definition ModuleSummaryIndex.cpp:549
static void propagateAttributesToRefs(GlobalValueSummary *S, DenseSet< ValueInfo > &MarkedNonReadWriteOnly)
Definition ModuleSummaryIndex.cpp:205
static std::string linkageToString(GlobalValue::LinkageTypes LT)
Definition ModuleSummaryIndex.cpp:449
static void defineExternalNode(raw_ostream &OS, const char *Pfx, const ValueInfo &VI, GlobalValue::GUID Id)
Definition ModuleSummaryIndex.cpp:530
static cl::opt< bool > PropagateAttrs("propagate-attrs", cl::init(true), cl::Hidden, cl::desc("Propagate attributes in index"))
static bool hasReadOnlyFlag(const GlobalValueSummary *S)
Definition ModuleSummaryIndex.cpp:543
static bool hasConstantFlag(const GlobalValueSummary *S)
Definition ModuleSummaryIndex.cpp:555
ModuleSummaryIndex.h This file contains the declarations the classes that hold the module index and s...
This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected components (SCCs) of a ...
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Implements a dense probed hash-table based set.
Function summary information to aid decisions and implementation of importing.
static LLVM_ABI FunctionSummary ExternalNode
A dummy node to reference external functions that aren't in the index.
static FunctionSummary makeDummyFunctionSummary(SmallVectorImpl< FunctionSummary::EdgeTy > &&Edges)
Create an empty FunctionSummary (with specified call edges).
LLVM_ABI std::pair< unsigned, unsigned > specialRefCounts() const
Definition ModuleSummaryIndex.cpp:76
Function and variable summary information to aid decisions and implementation of importing.
GlobalValueSummary * getBaseObject()
If this is an alias summary, returns the summary of the aliased object (a global variable or function...
ArrayRef< ValueInfo > refs() const
Return the list of values referenced by this global value definition.
GlobalValue::LinkageTypes linkage() const
Return linkage type recorded for this global value.
bool notEligibleToImport() const
Return true if this global value can't be imported.
uint64_t GUID
Declare a type to represent a global unique identifier for a global value.
VisibilityTypes
An enumeration for the kinds of visibility of global values.
@ DefaultVisibility
The GV is visible.
@ HiddenVisibility
The GV is hidden.
@ ProtectedVisibility
The GV is protected.
static bool isInterposableLinkage(LinkageTypes Linkage)
Whether the definition of this global may be replaced by something non-equivalent at link time.
LinkageTypes
An enumeration for the kinds of linkage for global values.
@ PrivateLinkage
Like Internal, but omit from symbol table.
@ CommonLinkage
Tentative definitions.
@ InternalLinkage
Rename collisions when linking (static functions).
@ LinkOnceAnyLinkage
Keep one copy of function when linking (inline)
@ WeakODRLinkage
Same, but only replaced by something equivalent.
@ ExternalLinkage
Externally visible function.
@ WeakAnyLinkage
Keep one copy of named function when linking (weak)
@ AppendingLinkage
Special purpose, only applies to global arrays.
@ AvailableExternallyLinkage
Available for inspection, not emission.
@ ExternalWeakLinkage
ExternalWeak linkage description.
@ LinkOnceODRLinkage
Same, but only replaced by something equivalent.
Global variable summary information to aid decisions and implementation of importing.
bool withAttributePropagation() const
bool withInternalizeAndPromote() const
bool withGlobalValueDeadStripping() const
bool withWholeProgramVisibility() const
LLVM_ABI bool isGUIDLive(GlobalValue::GUID GUID) const
Definition ModuleSummaryIndex.cpp:191
bool isReadOnly(const GlobalVarSummary *GVS) const
LLVM_ABI void setFlags(uint64_t Flags)
Definition ModuleSummaryIndex.cpp:115
bool isWriteOnly(const GlobalVarSummary *GVS) const
void setPartiallySplitLTOUnits()
ValueInfo getValueInfo(const GlobalValueSummaryMapTy::value_type &R) const
Return a ValueInfo for the index value_type (convenient when iterating index).
void setEnableSplitLTOUnit()
bool partiallySplitLTOUnits() const
LLVM_ABI void collectDefinedFunctionsForModule(StringRef ModulePath, GVSummaryMapTy &GVSummaryMap) const
Collect for the given module the list of functions it defines (GUID -> Summary).
Definition ModuleSummaryIndex.cpp:163
LLVM_ABI void dumpSCCs(raw_ostream &OS)
Print out strongly connected components for debugging.
Definition ModuleSummaryIndex.cpp:380
bool isGlobalValueLive(const GlobalValueSummary *GVS) const
bool enableSplitLTOUnit() const
void setWithSupportsHotColdNew()
LLVM_ABI void propagateAttributes(const DenseSet< GlobalValue::GUID > &PreservedSymbols)
Do the access attribute and DSOLocal propagation in combined index.
Definition ModuleSummaryIndex.cpp:261
void setSkipModuleByDistributedBackend()
void setWithAttributePropagation()
const StringMap< ModuleHash > & modulePaths() const
Table of modules, containing module hash and id.
bool withSupportsHotColdNew() const
void collectDefinedGVSummariesPerModule(Map &ModuleToDefinedGVSummaries) const
Collect for each module the list of Summaries it defines (GUID -> Summary).
bool withDSOLocalPropagation() const
LLVM_ABI void exportToDot(raw_ostream &OS, const DenseSet< GlobalValue::GUID > &GUIDPreservedSymbols) const
Export summary to dot file for GraphViz.
Definition ModuleSummaryIndex.cpp:561
bool hasUnifiedLTO() const
void setWithDSOLocalPropagation()
void setWithInternalizeAndPromote()
bool skipModuleByDistributedBackend() const
LLVM_ABI uint64_t getFlags() const
Definition ModuleSummaryIndex.cpp:89
GlobalValueSummary * getGlobalValueSummary(const GlobalValue &GV, bool PerModuleIndex=true) const
Returns the first GlobalValueSummary for GV, asserting that there is only one if PerModuleIndex.
void setWithGlobalValueDeadStripping()
void setWithWholeProgramVisibility()
LLVM_ABI bool canImportGlobalVar(const GlobalValueSummary *S, bool AnalyzeRefs) const
Checks if we can import global variable from another module.
Definition ModuleSummaryIndex.cpp:331
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM Value Representation.
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
This class implements an extremely fast bulk output stream that can only output to a stream.
Enumerate the SCCs of a directed graph in reverse topological order of the SCC DAG.
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
initializer< Ty > init(const Ty &Val)
LLVM_ABI StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get filename.
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
DenseMap< GlobalValue::GUID, GlobalValueSummary * > GVSummaryMapTy
Map of global value GUID to its summary, used to identify values defined in a particular module,...
scc_iterator< T > scc_begin(const T &G)
Construct the begin iterator for a deduced graph type T.
std::string utostr(uint64_t X, bool isNeg=false)
auto dyn_cast_or_null(const Y &Val)
iterator_range< pointee_iterator< WrappedIteratorT > > make_pointee_range(RangeT &&Range)
void sort(IteratorTy Start, IteratorTy End)
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool AreStatisticsEnabled()
Check if statistics are enabled.
bool isa(const From &Val)
isa - Return true if the parameter to the template is an instance of one of the template type argu...
@ Ref
The access may reference the value stored in memory.
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
Flags specific to function summaries.
Struct that holds a reference to a particular GUID in a global value summary.
LLVM_ABI GlobalValue::VisibilityTypes getELFVisibility() const
Returns the most constraining visibility among summaries.
Definition ModuleSummaryIndex.cpp:41
ArrayRef< std::unique_ptr< GlobalValueSummary > > getSummaryList() const
LLVM_ABI bool canAutoHide() const
Checks if all copies are eligible for auto-hiding (have flag set).
Definition ModuleSummaryIndex.cpp:66
LLVM_ABI bool isDSOLocal(bool WithDSOLocalPropagation=false) const
Checks if all summaries are DSO local (have the flag set).
Definition ModuleSummaryIndex.cpp:53