22#define DEBUG_TYPE "module-summary-index"
25 "Number of live global variables marked read only");
27 "Number of live global variables marked write only");
31 cl::desc(
"Propagate attributes in index"));
35 cl::desc(
"Import constant global variables with references"));
42 bool HasProtected =
false;
56 return WithDSOLocalPropagation
61 [](
const std::unique_ptr<GlobalValueSummary> &Summary) {
62 return Summary->isDSOLocal();
70 [](
const std::unique_ptr<GlobalValueSummary> &Summary) {
71 return Summary->canAutoHide();
80 unsigned RORefCnt = 0, WORefCnt = 0;
82 for (
I = Refs.size() - 1;
I >= 0 && Refs[
I].isWriteOnly(); --
I)
84 for (;
I >= 0 && Refs[
I].isReadOnly(); --
I)
86 return {RORefCnt, WORefCnt};
116 assert(Flags <= 0x7ff &&
"Unexpected bits in flag");
165 for (
auto &GlobalList : *
this) {
166 auto GUID = GlobalList.first;
167 for (
auto &GlobSummary : GlobalList.second.getSummaryList()) {
173 if (Summary->modulePath() != ModulePath)
175 GVSummaryMap[GUID] = Summary;
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();
195 const auto &SummaryList = VI.getSummaryList();
196 if (SummaryList.empty())
198 for (
auto &
I : SummaryList)
215 for (
auto &VI : S->
refs()) {
217 if (!VI.getAccessSpecifier()) {
218 if (!MarkedNonReadWriteOnly.
insert(VI).second)
220 }
else if (MarkedNonReadWriteOnly.
contains(VI))
222 for (
auto &
Ref : VI.getSummaryList())
226 if (!VI.isReadOnly())
227 GVS->setReadOnly(
false);
228 if (!VI.isWriteOnly())
229 GVS->setWriteOnly(
false);
266 for (
auto &
P : *
this) {
267 bool IsDSOLocal =
true;
268 for (
auto &S :
P.second.getSummaryList()) {
278 P.second.getSummaryList(),
279 [&](
const std::unique_ptr<GlobalValueSummary> &Summary) {
280 return isGlobalValueLive(Summary.get());
300 GUIDPreservedSymbols.
count(
P.first)) {
301 GVS->setReadOnly(
false);
302 GVS->setWriteOnly(
false);
307 IsDSOLocal &= S->isDSOLocal();
312 for (
const std::unique_ptr<GlobalValueSummary> &Summary :
313 P.second.getSummaryList())
314 Summary->setDSOLocal(
false);
319 for (
auto &
P : *
this)
320 if (
P.second.getSummaryList().size())
322 P.second.getSummaryList()[0]->getBaseObject()))
324 if (GVS->maybeReadOnly())
326 if (GVS->maybeWriteOnly())
327 WriteOnlyLiveGVars++;
332 bool AnalyzeRefs)
const {
339 bool &CanImportDecl)
const {
360 const bool nonInterposable =
366 CanImportDecl = (nonInterposable && eligibleToImport);
373 return nonInterposable && eligibleToImport &&
374 (!AnalyzeRefs || !HasRefsPreventingImport(GVS));
384 O <<
"SCC (" <<
utostr(
I->size()) <<
" node" << (
I->size() == 1 ?
"" :
"s")
388 if (V.getSummaryList().size())
390 O <<
" " << (
F ==
nullptr ?
"External" :
"") <<
" " <<
utostr(V.getGUID())
391 << (
I.hasCycle() ?
" (has cycle)" :
"") <<
"\n";
401 void addComment(
const Twine &Comment);
402 std::string getAsString()
const;
404 std::vector<std::string> Attrs;
405 std::string Comments;
417 const Twine &Comment) {
418 std::string
A =
Name.str();
426void Attributes::addComment(
const Twine &Comment) {
427 if (!
Comment.isTriviallyEmpty()) {
428 if (Comments.empty())
436std::string Attributes::getAsString()
const {
440 std::string
Ret =
"[";
441 for (
auto &
A : Attrs)
458 return "linkonce_odr";
470 return "extern_weak";
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),
501 return std::string(
"inst: ") + std::to_string(FS->instCount()) +
506 return std::string(
"@") + std::to_string(Id);
521 Label += std::string(
" (") + Attrs +
")";
532 auto StrId = std::to_string(Id);
533 OS <<
" " << StrId <<
" [label=\"";
540 OS <<
"\"]; // defined externally\n";
545 return GVS->maybeReadOnly();
551 return GVS->maybeWriteOnly();
557 return GVS->isConstant();
564 std::vector<Edge> CrossModuleEdges;
566 using GVSOrderedMapTy = std::map<GlobalValue::GUID, GlobalValueSummary *>;
567 std::map<StringRef, GVSOrderedMapTy> ModuleToDefinedGVS;
573 std::vector<StringRef> ModulePaths;
575 ModulePaths.push_back(ModPath);
578 for (
auto &ModPath : ModulePaths)
584 return ModId == (
uint64_t)-1 ? std::to_string(Id)
585 : std::string(
"M") + std::to_string(ModId) +
586 "_" + std::to_string(Id);
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)"};
609 assert(
static_cast<size_t>(TypeOrHotness) < std::size(EdgeAttrs));
610 OS << Pfx << NodeId(SrcMod, SrcId) <<
" -> " << NodeId(DstMod, DstId)
611 << EdgeAttrs[TypeOrHotness] <<
"\n";
614 OS <<
"digraph Summary {\n";
615 for (
auto &ModIt : ModuleToDefinedGVS) {
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";
627 auto &GVSMap = ModIt.second;
629 if (!GVSMap.count(IdTo)) {
630 CrossModuleEdges.push_back({ModId, Hotness, IdFrom, IdTo});
633 DrawEdge(
" ", ModId, IdFrom, ModId, IdTo, Hotness);
636 for (
auto &SummaryIt : GVSMap) {
637 NodeMap[SummaryIt.first].push_back(ModId);
638 auto Flags = SummaryIt.second->flags();
641 A.add(
"shape",
"record",
"function");
643 A.add(
"style",
"dotted,filled",
"alias");
644 A.add(
"shape",
"box");
646 A.add(
"shape",
"Mrecord",
"variable");
648 A.addComment(
"immutable");
650 A.addComment(
"writeOnly");
652 A.addComment(
"constant");
654 if (Flags.Visibility)
655 A.addComment(
"visibility");
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");
670 A.add(
"fillcolor",
"red",
"dead");
671 else if (Flags.NotEligibleToImport)
672 A.add(
"fillcolor",
"yellow",
"not eligible to import");
674 OS <<
" " << NodeId(ModId, SummaryIt.first) <<
" " <<
A.getAsString()
677 OS <<
" // Edges:\n";
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));
686 Draw(SummaryIt.first, AS->getAliaseeGUID(), -4);
691 for (
auto &CGEdge : FS->calls())
692 Draw(SummaryIt.first, CGEdge.first.getGUID(),
693 static_cast<int>(CGEdge.second.Hotness));
698 OS <<
" // Cross-module edges:\n";
699 for (
auto &E : CrossModuleEdges) {
700 auto &ModList = NodeMap[E.Dst];
701 if (ModList.empty()) {
705 ModList.push_back(-1);
707 for (
auto DstMod : ModList)
713 if (DstMod != E.SrcMod)
714 DrawEdge(
" ", E.SrcMod, E.Src, DstMod, E.Dst, E.Hotness);
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)
static std::string getNodeLabel(const ValueInfo &VI, GlobalValueSummary *GVS)
static std::string getSummaryAttributes(GlobalValueSummary *GVS)
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)
static bool hasWriteOnlyFlag(const GlobalValueSummary *S)
static void propagateAttributesToRefs(GlobalValueSummary *S, DenseSet< ValueInfo > &MarkedNonReadWriteOnly)
static std::string linkageToString(GlobalValue::LinkageTypes LT)
static void defineExternalNode(raw_ostream &OS, const char *Pfx, const ValueInfo &VI, GlobalValue::GUID Id)
static cl::opt< bool > PropagateAttrs("propagate-attrs", cl::init(true), cl::Hidden, cl::desc("Propagate attributes in index"))
static bool hasReadOnlyFlag(const GlobalValueSummary *S)
static bool hasConstantFlag(const GlobalValueSummary *S)
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
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
bool isReadOnly(const GlobalVarSummary *GVS) const
LLVM_ABI void setFlags(uint64_t Flags)
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).
LLVM_ABI void dumpSCCs(raw_ostream &OS)
Print out strongly connected components for debugging.
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.
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.
bool hasUnifiedLTO() const
void setWithDSOLocalPropagation()
void setWithInternalizeAndPromote()
bool skipModuleByDistributedBackend() const
LLVM_ABI uint64_t getFlags() const
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.
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<X> - 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<X> - 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<X> - 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.
ArrayRef< std::unique_ptr< GlobalValueSummary > > getSummaryList() const
LLVM_ABI bool canAutoHide() const
Checks if all copies are eligible for auto-hiding (have flag set).
LLVM_ABI bool isDSOLocal(bool WithDSOLocalPropagation=false) const
Checks if all summaries are DSO local (have the flag set).