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"));
44 bool HasProtected =
false;
58 return WithDSOLocalPropagation
63 [](
const std::unique_ptr<GlobalValueSummary> &Summary) {
64 return Summary->isDSOLocal();
72 [](
const std::unique_ptr<GlobalValueSummary> &Summary) {
73 return Summary->canAutoHide();
82 unsigned RORefCnt = 0, WORefCnt = 0;
84 for (
I = Refs.size() - 1;
I >= 0 && Refs[
I].isWriteOnly(); --
I)
86 for (;
I >= 0 && Refs[
I].isReadOnly(); --
I)
88 return {RORefCnt, WORefCnt};
120 assert(Flags <= 0x7ff &&
"Unexpected bits in flag");
169 for (
auto &GlobalList : *
this) {
170 auto GUID = GlobalList.first;
171 for (
auto &GlobSummary : GlobalList.second.getSummaryList()) {
177 if (Summary->modulePath() != ModulePath)
179 GVSummaryMap[GUID] = Summary;
186 bool PerModuleIndex)
const {
188 assert(VI &&
"GlobalValue not found in index");
189 assert((!PerModuleIndex || VI.getSummaryList().size() == 1) &&
190 "Expected a single entry per global value in per-module index");
191 auto &Summary = VI.getSummaryList()[0];
192 return Summary.get();
199 const auto &SummaryList = VI.getSummaryList();
200 if (SummaryList.empty())
202 for (
auto &
I : SummaryList)
219 for (
auto &VI : S->
refs()) {
221 if (!VI.getAccessSpecifier()) {
222 if (!MarkedNonReadWriteOnly.
insert(VI).second)
224 }
else if (MarkedNonReadWriteOnly.
contains(VI))
226 for (
auto &
Ref : VI.getSummaryList())
230 if (!VI.isReadOnly())
231 GVS->setReadOnly(
false);
232 if (!VI.isWriteOnly())
233 GVS->setWriteOnly(
false);
270 for (
auto &
P : *
this) {
271 bool IsDSOLocal =
true;
272 for (
auto &S :
P.second.getSummaryList()) {
282 P.second.getSummaryList(),
283 [&](
const std::unique_ptr<GlobalValueSummary> &Summary) {
284 return isGlobalValueLive(Summary.get());
304 GUIDPreservedSymbols.
count(
P.first)) {
305 GVS->setReadOnly(
false);
306 GVS->setWriteOnly(
false);
311 IsDSOLocal &= S->isDSOLocal();
316 for (
const std::unique_ptr<GlobalValueSummary> &Summary :
317 P.second.getSummaryList())
318 Summary->setDSOLocal(
false);
323 for (
auto &
P : *
this)
324 if (
P.second.getSummaryList().size())
326 P.second.getSummaryList()[0]->getBaseObject()))
328 if (GVS->maybeReadOnly())
330 if (GVS->maybeWriteOnly())
331 WriteOnlyLiveGVars++;
336 bool AnalyzeRefs)
const {
343 bool &CanImportDecl)
const {
364 const bool nonInterposable =
370 CanImportDecl = (nonInterposable && eligibleToImport);
377 return nonInterposable && eligibleToImport &&
378 (!AnalyzeRefs || !HasRefsPreventingImport(GVS));
388 O <<
"SCC (" <<
utostr(
I->size()) <<
" node" << (
I->size() == 1 ?
"" :
"s")
392 if (V.getSummaryList().size())
394 O <<
" " << (
F ==
nullptr ?
"External" :
"") <<
" " <<
utostr(V.getGUID())
395 << (
I.hasCycle() ?
" (has cycle)" :
"") <<
"\n";
405 void addComment(
const Twine &Comment);
406 std::string getAsString()
const;
408 std::vector<std::string> Attrs;
409 std::string Comments;
421 const Twine &Comment) {
422 std::string
A =
Name.str();
430void Attributes::addComment(
const Twine &Comment) {
431 if (!
Comment.isTriviallyEmpty()) {
432 if (Comments.empty())
440std::string Attributes::getAsString()
const {
444 std::string
Ret =
"[";
445 for (
auto &
A : Attrs)
462 return "linkonce_odr";
474 return "extern_weak";
483 auto FlagValue = [](
unsigned V) {
return V ?
'1' :
'0'; };
484 char FlagRep[] = {FlagValue(
F.ReadNone),
485 FlagValue(
F.ReadOnly),
486 FlagValue(
F.NoRecurse),
487 FlagValue(
F.ReturnDoesNotAlias),
488 FlagValue(
F.NoInline),
489 FlagValue(
F.AlwaysInline),
490 FlagValue(
F.NoUnwind),
491 FlagValue(
F.MayThrow),
492 FlagValue(
F.HasUnknownCall),
493 FlagValue(
F.MustBeUnreachable),
505 return std::string(
"inst: ") + std::to_string(FS->instCount()) +
510 return std::string(
"@") + std::to_string(Id);
525 Label += std::string(
" (") + Attrs +
")";
536 auto StrId = std::to_string(Id);
537 OS <<
" " << StrId <<
" [label=\"";
544 OS <<
"\"]; // defined externally\n";
549 return GVS->maybeReadOnly();
555 return GVS->maybeWriteOnly();
561 return GVS->isConstant();
568 std::vector<Edge> CrossModuleEdges;
570 using GVSOrderedMapTy = std::map<GlobalValue::GUID, GlobalValueSummary *>;
571 std::map<StringRef, GVSOrderedMapTy> ModuleToDefinedGVS;
577 std::vector<StringRef> ModulePaths;
579 ModulePaths.push_back(ModPath);
582 for (
auto &ModPath : ModulePaths)
588 return ModId == (
uint64_t)-1 ? std::to_string(Id)
589 : std::string(
"M") + std::to_string(ModId) +
590 "_" + std::to_string(Id);
602 static const char *EdgeAttrs[] = {
603 " [style=dotted]; // alias",
604 " [style=dashed]; // ref",
605 " [style=dashed,color=forestgreen]; // const-ref",
606 " [style=dashed,color=violetred]; // writeOnly-ref",
607 " // call (hotness : Unknown)",
608 " [color=blue]; // call (hotness : Cold)",
609 " // call (hotness : None)",
610 " [color=brown]; // call (hotness : Hot)",
611 " [style=bold,color=red]; // call (hotness : Critical)"};
613 assert(
static_cast<size_t>(TypeOrHotness) < std::size(EdgeAttrs));
614 OS << Pfx << NodeId(SrcMod, SrcId) <<
" -> " << NodeId(DstMod, DstId)
615 << EdgeAttrs[TypeOrHotness] <<
"\n";
618 OS <<
"digraph Summary {\n";
619 for (
auto &ModIt : ModuleToDefinedGVS) {
623 auto ModId = ModuleIdMap.
empty() ? 0 : ModuleIdMap[ModIt.first];
624 OS <<
" // Module: " << ModIt.first <<
"\n";
625 OS <<
" subgraph cluster_" << std::to_string(ModId) <<
" {\n";
626 OS <<
" style = filled;\n";
627 OS <<
" color = lightgrey;\n";
629 OS <<
" node [style=filled,fillcolor=lightblue];\n";
631 auto &GVSMap = ModIt.second;
633 if (!GVSMap.count(IdTo)) {
634 CrossModuleEdges.push_back({ModId, Hotness, IdFrom, IdTo});
637 DrawEdge(
" ", ModId, IdFrom, ModId, IdTo, Hotness);
640 for (
auto &SummaryIt : GVSMap) {
641 NodeMap[SummaryIt.first].push_back(ModId);
642 auto Flags = SummaryIt.second->flags();
645 A.add(
"shape",
"record",
"function");
647 A.add(
"style",
"dotted,filled",
"alias");
648 A.add(
"shape",
"box");
650 A.add(
"shape",
"Mrecord",
"variable");
652 A.addComment(
"immutable");
654 A.addComment(
"writeOnly");
656 A.addComment(
"constant");
658 if (Flags.Visibility)
659 A.addComment(
"visibility");
661 A.addComment(
"dsoLocal");
662 if (Flags.CanAutoHide)
663 A.addComment(
"canAutoHide");
665 A.addComment(
"definition");
667 A.addComment(
"declaration");
668 if (GUIDPreservedSymbols.
count(SummaryIt.first))
669 A.addComment(
"preserved");
674 A.add(
"fillcolor",
"red",
"dead");
675 else if (Flags.NotEligibleToImport)
676 A.add(
"fillcolor",
"yellow",
"not eligible to import");
678 OS <<
" " << NodeId(ModId, SummaryIt.first) <<
" " <<
A.getAsString()
681 OS <<
" // Edges:\n";
683 for (
auto &SummaryIt : GVSMap) {
684 auto *GVS = SummaryIt.second;
685 for (
auto &R : GVS->refs())
686 Draw(SummaryIt.first, R.getGUID(),
687 R.isWriteOnly() ? -1 : (R.isReadOnly() ? -2 : -3));
690 Draw(SummaryIt.first, AS->getAliaseeGUID(), -4);
695 for (
auto &CGEdge : FS->calls())
696 Draw(SummaryIt.first, CGEdge.first.getGUID(),
697 static_cast<int>(CGEdge.second.Hotness));
702 OS <<
" // Cross-module edges:\n";
703 for (
auto &E : CrossModuleEdges) {
704 auto &ModList = NodeMap[E.Dst];
705 if (ModList.empty()) {
709 ModList.push_back(-1);
711 for (
auto DstMod : ModList)
717 if (DstMod != E.SrcMod)
718 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).
static constexpr uint64_t BitcodeSummaryVersion
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.
static constexpr uint32_t RangeWidth
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).