Skip to content
Permalink
Browse files

[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
  • Loading branch information...
Eugene Leviant
Eugene Leviant committed Nov 16, 2018
1 parent 079c37d commit bf46e7410c8a1d26c4a434261baaae28a904d657
Showing with 865 additions and 92 deletions.
  1. +38 −12 llvm/include/llvm/IR/ModuleSummaryIndex.h
  2. +8 −0 llvm/include/llvm/Transforms/IPO/FunctionImport.h
  3. +0 −1 llvm/include/llvm/Transforms/Utils/FunctionImportUtils.h
  4. +58 −17 llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
  5. +2 −1 llvm/lib/AsmParser/LLParser.cpp
  6. +44 −7 llvm/lib/Bitcode/Reader/BitcodeReader.cpp
  7. +19 −3 llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
  8. +101 −6 llvm/lib/IR/ModuleSummaryIndex.cpp
  9. +4 −1 llvm/lib/LTO/LTO.cpp
  10. +14 −5 llvm/lib/LTO/ThinLTOCodeGenerator.cpp
  11. +0 −5 llvm/lib/Linker/IRMover.cpp
  12. +35 −4 llvm/lib/Transforms/IPO/FunctionImport.cpp
  13. +19 −2 llvm/lib/Transforms/Utils/FunctionImportUtils.cpp
  14. +1 −1 llvm/test/Bitcode/summary_version.ll
  15. +2 −2 llvm/test/Bitcode/thinlto-alias.ll
  16. +1 −1 llvm/test/Bitcode/thinlto-alias2.ll
  17. +2 −2 llvm/test/Bitcode/thinlto-function-summary-callgraph-cast.ll
  18. +2 −2 llvm/test/Bitcode/thinlto-function-summary-callgraph-pgo.ll
  19. +2 −2 llvm/test/Bitcode/thinlto-function-summary-callgraph-profile-summary.ll
  20. +1 −1 llvm/test/Bitcode/thinlto-function-summary-callgraph-relbf.ll
  21. +2 −2 llvm/test/Bitcode/thinlto-function-summary-callgraph-sample-profile-summary.ll
  22. +2 −2 llvm/test/Bitcode/thinlto-function-summary-callgraph.ll
  23. +6 −6 llvm/test/Bitcode/thinlto-function-summary-refgraph.ll
  24. +5 −0 llvm/test/ThinLTO/X86/Inputs/index-const-prop-alias.ll
  25. +19 −0 llvm/test/ThinLTO/X86/Inputs/index-const-prop-cache-foo.ll
  26. +10 −0 llvm/test/ThinLTO/X86/Inputs/index-const-prop-cache-test1.ll
  27. +14 −0 llvm/test/ThinLTO/X86/Inputs/index-const-prop-cache-test2.ll
  28. +5 −0 llvm/test/ThinLTO/X86/Inputs/index-const-prop-comdat.ll
  29. +4 −0 llvm/test/ThinLTO/X86/Inputs/index-const-prop-define-g.ll
  30. +12 −0 llvm/test/ThinLTO/X86/Inputs/index-const-prop-full-lto.ll
  31. +5 −0 llvm/test/ThinLTO/X86/Inputs/index-const-prop-gvref.ll
  32. +15 −0 llvm/test/ThinLTO/X86/Inputs/index-const-prop-linkage.ll
  33. +64 −0 llvm/test/ThinLTO/X86/Inputs/index-const-prop.ll
  34. +5 −5 llvm/test/ThinLTO/X86/dot-dumper.ll
  35. +2 −2 llvm/test/ThinLTO/X86/globals-import-const-fold.ll
  36. +18 −0 llvm/test/ThinLTO/X86/index-const-prop-O0.ll
  37. +42 −0 llvm/test/ThinLTO/X86/index-const-prop-alias.ll
  38. +41 −0 llvm/test/ThinLTO/X86/index-const-prop-cache.ll
  39. +17 −0 llvm/test/ThinLTO/X86/index-const-prop-comdat.ll
  40. +26 −0 llvm/test/ThinLTO/X86/index-const-prop-dead.ll
  41. +24 −0 llvm/test/ThinLTO/X86/index-const-prop-full-lto.ll
  42. +27 −0 llvm/test/ThinLTO/X86/index-const-prop-gvref.ll
  43. +21 −0 llvm/test/ThinLTO/X86/index-const-prop-ldst.ll
  44. +27 −0 llvm/test/ThinLTO/X86/index-const-prop-linkage.ll
  45. +40 −0 llvm/test/ThinLTO/X86/index-const-prop.ll
  46. +59 −0 llvm/test/ThinLTO/X86/index-const-prop2.ll
@@ -163,13 +163,13 @@ using GlobalValueSummaryMapTy =
/// Struct that holds a reference to a particular GUID in a global value
/// summary.
struct ValueInfo {
PointerIntPair<const GlobalValueSummaryMapTy::value_type *, 1, bool>
RefAndFlag;
PointerIntPair<const GlobalValueSummaryMapTy::value_type *, 2, int>
RefAndFlags;

ValueInfo() = default;
ValueInfo(bool HaveGVs, const GlobalValueSummaryMapTy::value_type *R) {
RefAndFlag.setPointer(R);
RefAndFlag.setInt(HaveGVs);
RefAndFlags.setPointer(R);
RefAndFlags.setInt(HaveGVs);
}

operator bool() const { return getRef(); }
@@ -189,10 +189,12 @@ struct ValueInfo {
: getRef()->second.U.Name;
}

bool haveGVs() const { return RefAndFlag.getInt(); }
bool haveGVs() const { return RefAndFlags.getInt() & 0x1; }
bool isReadOnly() const { return RefAndFlags.getInt() & 0x2; }
void setReadOnly() { RefAndFlags.setInt(RefAndFlags.getInt() | 0x2); }

const GlobalValueSummaryMapTy::value_type *getRef() const {
return RefAndFlag.getPointer();
return RefAndFlags.getPointer();
}

bool isDSOLocal() const;
@@ -543,6 +545,8 @@ class FunctionSummary : public GlobalValueSummary {
std::move(TypeTestAssumeConstVCalls),
std::move(TypeCheckedLoadConstVCalls)});
}
// Gets the number of immutable refs in RefEdgeList
unsigned immutableRefCount() const;

/// Check if this is a function summary.
static bool classof(const GlobalValueSummary *GVS) {
@@ -652,19 +656,30 @@ template <> struct DenseMapInfo<FunctionSummary::ConstVCall> {
/// Global variable summary information to aid decisions and
/// implementation of importing.
///
/// Currently this doesn't add anything to the base \p GlobalValueSummary,
/// but is a placeholder as additional info may be added to the summary
/// for variables.
/// Global variable summary has extra flag, telling if it is
/// modified during the program run or not. This affects ThinLTO
/// internalization
class GlobalVarSummary : public GlobalValueSummary {

public:
GlobalVarSummary(GVFlags Flags, std::vector<ValueInfo> Refs)
: GlobalValueSummary(GlobalVarKind, Flags, std::move(Refs)) {}
struct GVarFlags {
GVarFlags(bool ReadOnly = false) : ReadOnly(ReadOnly) {}

unsigned ReadOnly : 1;
} VarFlags;

GlobalVarSummary(GVFlags Flags, GVarFlags VarFlags,
std::vector<ValueInfo> Refs)
: GlobalValueSummary(GlobalVarKind, Flags, std::move(Refs)),
VarFlags(VarFlags) {}

/// Check if this is a global variable summary.
static bool classof(const GlobalValueSummary *GVS) {
return GVS->getSummaryKind() == GlobalVarKind;
}

GVarFlags varflags() const { return VarFlags; }
void setReadOnly(bool RO) { VarFlags.ReadOnly = RO; }
bool isReadOnly() const { return VarFlags.ReadOnly; }
};

struct TypeTestResolution {
@@ -1135,6 +1150,9 @@ class ModuleSummaryIndex {

/// Print out strongly connected components for debugging.
void dumpSCCs(raw_ostream &OS);

/// Analyze index and detect unmodified globals
void propagateConstants(const DenseSet<GlobalValue::GUID> &PreservedSymbols);
};

/// GraphTraits definition to build SCC for the index
@@ -1184,6 +1202,14 @@ struct GraphTraits<ModuleSummaryIndex *> : public GraphTraits<ValueInfo> {
}
};

static inline bool canImportGlobalVar(GlobalValueSummary *S) {
assert(isa<GlobalVarSummary>(S->getBaseObject()));

// We don't import GV with references, because it can result
// in promotion of local variables in the source module.
return !GlobalValue::isInterposableLinkage(S->linkage()) &&
!S->notEligibleToImport() && S->refs().empty();
}
} // end namespace llvm

#endif // LLVM_IR_MODULESUMMARYINDEX_H
@@ -176,6 +176,14 @@ void computeDeadSymbols(
const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols,
function_ref<PrevailingType(GlobalValue::GUID)> isPrevailing);

/// Compute dead symbols and run constant propagation in combined index
/// after that.
void computeDeadSymbolsWithConstProp(
ModuleSummaryIndex &Index,
const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols,
function_ref<PrevailingType(GlobalValue::GUID)> isPrevailing,
bool ImportEnabled);

/// Converts value \p GV to declaration, or replaces with a declaration if
/// it is an alias. Returns true if converted, false if replaced.
bool convertToDeclaration(GlobalValue &GV);
@@ -113,7 +113,6 @@ class FunctionImportGlobalProcessing {
bool renameModuleForThinLTO(
Module &M, const ModuleSummaryIndex &Index,
SetVector<GlobalValue *> *GlobalsToImport = nullptr);

} // End llvm namespace

#endif
@@ -220,10 +220,19 @@ static void addIntrinsicToSummary(
}
}

static void computeFunctionSummary(
ModuleSummaryIndex &Index, const Module &M, const Function &F,
BlockFrequencyInfo *BFI, ProfileSummaryInfo *PSI, DominatorTree &DT,
bool HasLocalsInUsedOrAsm, DenseSet<GlobalValue::GUID> &CantBePromoted) {
static bool isNonVolatileLoad(const Instruction *I) {
if (const auto *LI = dyn_cast<LoadInst>(I))
return !LI->isVolatile();

return false;
}

static void computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M,
const Function &F, BlockFrequencyInfo *BFI,
ProfileSummaryInfo *PSI, DominatorTree &DT,
bool HasLocalsInUsedOrAsm,
DenseSet<GlobalValue::GUID> &CantBePromoted,
bool IsThinLTO) {
// Summary not currently supported for anonymous functions, they should
// have been named.
assert(F.hasName());
@@ -244,6 +253,7 @@ static void computeFunctionSummary(
// Add personality function, prefix data and prologue data to function's ref
// list.
findRefEdges(Index, &F, RefEdges, Visited);
std::vector<const Instruction *> NonVolatileLoads;

bool HasInlineAsmMaybeReferencingInternal = false;
bool InitsVarArgs = false;
@@ -256,6 +266,13 @@ static void computeFunctionSummary(
InitsVarArgs = true;
}
++NumInsts;
if (isNonVolatileLoad(&I)) {
// Postpone processing of non-volatile load instructions
// See comments below
Visited.insert(&I);
NonVolatileLoads.push_back(&I);
continue;
}
findRefEdges(Index, &I, RefEdges, Visited);
auto CS = ImmutableCallSite(&I);
if (!CS)
@@ -345,6 +362,24 @@ static void computeFunctionSummary(
}
}

// By now we processed all instructions in a function, except
// non-volatile loads. All new refs we add in a loop below
// are obviously constant. All constant refs are grouped in the
// end of RefEdges vector, so we can use a single integer value
// to identify them.
unsigned RefCnt = RefEdges.size();
for (const Instruction *I : NonVolatileLoads) {
Visited.erase(I);
findRefEdges(Index, I, RefEdges, Visited);
}
std::vector<ValueInfo> Refs = RefEdges.takeVector();
// Regular LTO module doesn't participate in ThinLTO import,
// so no reference from it can be readonly, since this would
// require importing variable as local copy
if (IsThinLTO)
for (; RefCnt < Refs.size(); ++RefCnt)
Refs[RefCnt].setReadOnly();

// Explicit add hot edges to enforce importing for designated GUIDs for
// sample PGO, to enable the same inlines as the profiled optimized binary.
for (auto &I : F.getImportGUIDs())
@@ -368,9 +403,9 @@ static void computeFunctionSummary(
// Don't try to import functions with noinline attribute.
F.getAttributes().hasFnAttribute(Attribute::NoInline)};
auto FuncSummary = llvm::make_unique<FunctionSummary>(
Flags, NumInsts, FunFlags, RefEdges.takeVector(),
CallGraphEdges.takeVector(), TypeTests.takeVector(),
TypeTestAssumeVCalls.takeVector(), TypeCheckedLoadVCalls.takeVector(),
Flags, NumInsts, FunFlags, std::move(Refs), CallGraphEdges.takeVector(),
TypeTests.takeVector(), TypeTestAssumeVCalls.takeVector(),
TypeCheckedLoadVCalls.takeVector(),
TypeTestAssumeConstVCalls.takeVector(),
TypeCheckedLoadConstVCalls.takeVector());
if (NonRenamableLocal)
@@ -387,8 +422,13 @@ computeVariableSummary(ModuleSummaryIndex &Index, const GlobalVariable &V,
bool NonRenamableLocal = isNonRenamableLocal(V);
GlobalValueSummary::GVFlags Flags(V.getLinkage(), NonRenamableLocal,
/* Live = */ false, V.isDSOLocal());
auto GVarSummary =
llvm::make_unique<GlobalVarSummary>(Flags, RefEdges.takeVector());

// Don't mark variables we won't be able to internalize as read-only.
GlobalVarSummary::GVarFlags VarFlags(
!V.hasComdat() && !V.hasAppendingLinkage() && !V.isInterposable() &&
!V.hasAvailableExternallyLinkage() && !V.hasDLLExportStorageClass());
auto GVarSummary = llvm::make_unique<GlobalVarSummary>(Flags, VarFlags,
RefEdges.takeVector());
if (NonRenamableLocal)
CantBePromoted.insert(V.getGUID());
if (HasBlockAddress)
@@ -492,13 +532,19 @@ ModuleSummaryIndex llvm::buildModuleSummaryIndex(
Index.addGlobalValueSummary(*GV, std::move(Summary));
} else {
std::unique_ptr<GlobalVarSummary> Summary =
llvm::make_unique<GlobalVarSummary>(GVFlags,
ArrayRef<ValueInfo>{});
llvm::make_unique<GlobalVarSummary>(
GVFlags, GlobalVarSummary::GVarFlags(),
ArrayRef<ValueInfo>{});
Index.addGlobalValueSummary(*GV, std::move(Summary));
}
});
}

bool IsThinLTO = true;
if (auto *MD =
mdconst::extract_or_null<ConstantInt>(M.getModuleFlag("ThinLTO")))
IsThinLTO = MD->getZExtValue();

// Compute summaries for all functions defined in module, and save in the
// index.
for (auto &F : M) {
@@ -519,7 +565,7 @@ ModuleSummaryIndex llvm::buildModuleSummaryIndex(

computeFunctionSummary(Index, M, F, BFI, PSI, DT,
!LocalsUsed.empty() || HasLocalInlineAsmSymbol,
CantBePromoted);
CantBePromoted, IsThinLTO);
}

// Compute summaries for all variables defined in module, and save in the
@@ -550,11 +596,6 @@ ModuleSummaryIndex llvm::buildModuleSummaryIndex(
setLiveRoot(Index, "llvm.global_dtors");
setLiveRoot(Index, "llvm.global.annotations");

bool IsThinLTO = true;
if (auto *MD =
mdconst::extract_or_null<ConstantInt>(M.getModuleFlag("ThinLTO")))
IsThinLTO = MD->getZExtValue();

for (auto &GlobalList : Index) {
// Ignore entries for references that are undefined in the current module.
if (GlobalList.second.SummaryList.empty())
@@ -7715,7 +7715,8 @@ bool LLParser::ParseVariableSummary(std::string Name, GlobalValue::GUID GUID,
if (ParseToken(lltok::rparen, "expected ')' here"))
return true;

auto GS = llvm::make_unique<GlobalVarSummary>(GVFlags, std::move(Refs));
auto GS = llvm::make_unique<GlobalVarSummary>(
GVFlags, GlobalVarSummary::GVarFlags(), std::move(Refs));

GS->setModulePath(ModulePath);

Oops, something went wrong.

0 comments on commit bf46e74

Please sign in to comment.
You can’t perform that action at this time.