summaryrefslogtreecommitdiffstats
path: root/llvm/lib/IR/ModuleSummaryIndex.cpp
diff options
context:
space:
mode:
authorEugene Leviant <eleviant@accesssoftek.com>2018-11-16 07:08:00 +0000
committerEugene Leviant <eleviant@accesssoftek.com>2018-11-16 07:08:00 +0000
commitbf46e7410c8a1d26c4a434261baaae28a904d657 (patch)
treea8037e2560e4fd3aee808885ae87901c8e857afa /llvm/lib/IR/ModuleSummaryIndex.cpp
parent079c37da5870239d0332870e6c8cea877b335600 (diff)
downloadbcm5719-llvm-bf46e7410c8a1d26c4a434261baaae28a904d657.tar.gz
bcm5719-llvm-bf46e7410c8a1d26c4a434261baaae28a904d657.zip
[ThinLTO] Internalize readonly globals
An attempt to recommit r346584 after failure on OSX build bot. Fixed cache key computation in ThinLTOCodeGenerator and added test case llvm-svn: 347033
Diffstat (limited to 'llvm/lib/IR/ModuleSummaryIndex.cpp')
-rw-r--r--llvm/lib/IR/ModuleSummaryIndex.cpp107
1 files changed, 101 insertions, 6 deletions
diff --git a/llvm/lib/IR/ModuleSummaryIndex.cpp b/llvm/lib/IR/ModuleSummaryIndex.cpp
index 8d85f7901b0..6c0d3973715 100644
--- a/llvm/lib/IR/ModuleSummaryIndex.cpp
+++ b/llvm/lib/IR/ModuleSummaryIndex.cpp
@@ -30,6 +30,17 @@ bool ValueInfo::isDSOLocal() const {
});
}
+// Gets the number of immutable refs in RefEdgeList
+unsigned FunctionSummary::immutableRefCount() const {
+ // Here we take advantage of having all readonly references
+ // located in the end of the RefEdgeList.
+ auto Refs = refs();
+ unsigned ImmutableRefCnt = 0;
+ for (int I = Refs.size() - 1; I >= 0 && Refs[I].isReadOnly(); --I)
+ ImmutableRefCnt++;
+ return ImmutableRefCnt;
+}
+
// Collect for the given module the list of function it defines
// (GUID -> Summary).
void ModuleSummaryIndex::collectDefinedFunctionsForModule(
@@ -84,6 +95,73 @@ bool ModuleSummaryIndex::isGUIDLive(GlobalValue::GUID GUID) const {
return false;
}
+static void propagateConstantsToRefs(GlobalValueSummary *S) {
+ // If reference is not readonly then referenced summary is not
+ // readonly either. Note that:
+ // - All references from GlobalVarSummary are conservatively considered as
+ // not readonly. Tracking them properly requires more complex analysis
+ // then we have now.
+ //
+ // - AliasSummary objects have no refs at all so this function is a no-op
+ // for them.
+ for (auto &VI : S->refs()) {
+ if (VI.isReadOnly()) {
+ // We only mark refs as readonly when computing function summaries on
+ // analysis phase.
+ assert(isa<FunctionSummary>(S));
+ continue;
+ }
+ for (auto &Ref : VI.getSummaryList())
+ // If references to alias is not readonly then aliasee is not readonly
+ if (auto *GVS = dyn_cast<GlobalVarSummary>(Ref->getBaseObject()))
+ GVS->setReadOnly(false);
+ }
+}
+
+// Do the constant propagation in combined index.
+// The goal of constant propagation is internalization of readonly
+// variables. To determine which variables are readonly and which
+// are not we take following steps:
+// - During analysis we speculatively assign readonly attribute to
+// all variables which can be internalized. When computing function
+// summary we also assign readonly attribute to a reference if
+// function doesn't modify referenced variable.
+//
+// - After computing dead symbols in combined index we do the constant
+// propagation. During this step we clear readonly attribute from
+// all variables which:
+// a. are dead, preserved or can't be imported
+// b. referenced by any global variable initializer
+// c. referenced by a function and reference is not readonly
+//
+// Internalization itself happens in the backend after import is finished
+// See internalizeImmutableGVs.
+void ModuleSummaryIndex::propagateConstants(
+ const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols) {
+ for (auto &P : *this)
+ for (auto &S : P.second.SummaryList) {
+ if (!isGlobalValueLive(S.get()))
+ // We don't examine references from dead objects
+ continue;
+
+ // Global variable can't be marked read only if it is not eligible
+ // to import since we need to ensure that all external references
+ // get a local (imported) copy. It also can't be marked read only
+ // if it or any alias (since alias points to the same memory) are
+ // preserved or notEligibleToImport, since either of those means
+ // there could be writes that are not visible (because preserved
+ // means it could have external to DSO writes, and notEligibleToImport
+ // means it could have writes via inline assembly leading it to be
+ // in the @llvm.*used).
+ if (auto *GVS = dyn_cast<GlobalVarSummary>(S->getBaseObject()))
+ // Here we intentionally pass S.get() not GVS, because S could be
+ // an alias.
+ if (!canImportGlobalVar(S.get()) || GUIDPreservedSymbols.count(P.first))
+ GVS->setReadOnly(false);
+ propagateConstantsToRefs(S.get());
+ }
+}
+
// TODO: write a graphviz dumper for SCCs (see ModuleSummaryIndex::exportToDot)
// then delete this function and update its tests
LLVM_DUMP_METHOD
@@ -108,6 +186,7 @@ namespace {
struct Attributes {
void add(const Twine &Name, const Twine &Value,
const Twine &Comment = Twine());
+ void addComment(const Twine &Comment);
std::string getAsString() const;
std::vector<std::string> Attrs;
@@ -129,6 +208,10 @@ void Attributes::add(const Twine &Name, const Twine &Value,
A += Value.str();
A += "\"";
Attrs.push_back(A);
+ addComment(Comment);
+}
+
+void Attributes::addComment(const Twine &Comment) {
if (!Comment.isTriviallyEmpty()) {
if (Comments.empty())
Comments = " // ";
@@ -237,6 +320,12 @@ static void defineExternalNode(raw_ostream &OS, const char *Pfx,
OS << "\"]; // defined externally\n";
}
+static bool hasReadOnlyFlag(const GlobalValueSummary *S) {
+ if (auto *GVS = dyn_cast<GlobalVarSummary>(S))
+ return GVS->isReadOnly();
+ return false;
+}
+
void ModuleSummaryIndex::exportToDot(raw_ostream &OS) const {
std::vector<Edge> CrossModuleEdges;
DenseMap<GlobalValue::GUID, std::vector<uint64_t>> NodeMap;
@@ -252,13 +341,17 @@ void ModuleSummaryIndex::exportToDot(raw_ostream &OS) const {
};
auto DrawEdge = [&](const char *Pfx, uint64_t SrcMod, GlobalValue::GUID SrcId,
- uint64_t DstMod, GlobalValue::GUID DstId, int TypeOrHotness) {
- // 0 corresponds to alias edge, 1 to ref edge, 2 to call with unknown
- // hotness, ...
- TypeOrHotness += 2;
+ uint64_t DstMod, GlobalValue::GUID DstId,
+ int TypeOrHotness) {
+ // 0 - alias
+ // 1 - reference
+ // 2 - constant reference
+ // Other value: (hotness - 3).
+ TypeOrHotness += 3;
static const char *EdgeAttrs[] = {
" [style=dotted]; // alias",
" [style=dashed]; // ref",
+ " [style=dashed,color=forestgreen]; // const-ref",
" // call (hotness : Unknown)",
" [color=blue]; // call (hotness : Cold)",
" // call (hotness : None)",
@@ -301,6 +394,8 @@ void ModuleSummaryIndex::exportToDot(raw_ostream &OS) const {
A.add("shape", "box");
} else {
A.add("shape", "Mrecord", "variable");
+ if (Flags.Live && hasReadOnlyFlag(SummaryIt.second))
+ A.addComment("immutable");
}
auto VI = getValueInfo(SummaryIt.first);
@@ -318,7 +413,7 @@ void ModuleSummaryIndex::exportToDot(raw_ostream &OS) const {
for (auto &SummaryIt : GVSMap) {
auto *GVS = SummaryIt.second;
for (auto &R : GVS->refs())
- Draw(SummaryIt.first, R.getGUID(), -1);
+ Draw(SummaryIt.first, R.getGUID(), R.isReadOnly() ? -1 : -2);
if (auto *AS = dyn_cast_or_null<AliasSummary>(SummaryIt.second)) {
GlobalValue::GUID AliaseeId;
@@ -331,7 +426,7 @@ void ModuleSummaryIndex::exportToDot(raw_ostream &OS) const {
AliaseeId = AliaseeOrigId;
}
- Draw(SummaryIt.first, AliaseeId, -2);
+ Draw(SummaryIt.first, AliaseeId, -3);
continue;
}
OpenPOWER on IntegriCloud