[llvm] r305482 - Apply summary-based dead stripping to regular LTO modules with summaries.
Peter Collingbourne via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 15 10:26:13 PDT 2017
Author: pcc
Date: Thu Jun 15 12:26:13 2017
New Revision: 305482
URL: http://llvm.org/viewvc/llvm-project?rev=305482&view=rev
Log:
Apply summary-based dead stripping to regular LTO modules with summaries.
If a regular LTO module has a summary index, then instead of linking
it into the combined regular LTO module right away, add it to the
combined summary index and associate it with a special module that
represents the combined regular LTO module.
Any such modules are linked during LTO::run(), at which time we use
the results of summary-based dead stripping to control whether to
link prevailing symbols.
Differential Revision: https://reviews.llvm.org/D33922
Added:
llvm/trunk/test/LTO/Resolution/X86/Inputs/dead-strip-fulllto.ll
llvm/trunk/test/LTO/Resolution/X86/dead-strip-fulllto.ll
Modified:
llvm/trunk/include/llvm/Bitcode/BitcodeReader.h
llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h
llvm/trunk/include/llvm/LTO/LTO.h
llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
llvm/trunk/lib/IR/ModuleSummaryIndex.cpp
llvm/trunk/lib/LTO/LTO.cpp
llvm/trunk/lib/LTO/LTOModule.cpp
Modified: llvm/trunk/include/llvm/Bitcode/BitcodeReader.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/BitcodeReader.h?rev=305482&r1=305481&r2=305482&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Bitcode/BitcodeReader.h (original)
+++ llvm/trunk/include/llvm/Bitcode/BitcodeReader.h Thu Jun 15 12:26:13 2017
@@ -42,6 +42,12 @@ namespace llvm {
struct BitcodeFileContents;
+ /// Basic information extracted from a bitcode module to be used for LTO.
+ struct BitcodeLTOInfo {
+ bool IsThinLTO;
+ bool HasSummary;
+ };
+
/// Represents a module in a bitcode file.
class BitcodeModule {
// This covers the identification (if present) and module blocks.
@@ -90,15 +96,17 @@ namespace llvm {
/// Read the entire bitcode module and return it.
Expected<std::unique_ptr<Module>> parseModule(LLVMContext &Context);
- /// Check if the given bitcode buffer contains a summary block.
- Expected<bool> hasSummary();
+ /// Returns information about the module to be used for LTO: whether to
+ /// compile with ThinLTO, and whether it has a summary.
+ Expected<BitcodeLTOInfo> getLTOInfo();
/// Parse the specified bitcode buffer, returning the module summary index.
Expected<std::unique_ptr<ModuleSummaryIndex>> getSummary();
/// Parse the specified bitcode buffer and merge its module summary index
/// into CombinedIndex.
- Error readSummary(ModuleSummaryIndex &CombinedIndex, unsigned ModuleId);
+ Error readSummary(ModuleSummaryIndex &CombinedIndex, StringRef ModulePath,
+ uint64_t ModuleId);
};
struct BitcodeFileContents {
@@ -147,8 +155,8 @@ namespace llvm {
Expected<std::unique_ptr<Module>> parseBitcodeFile(MemoryBufferRef Buffer,
LLVMContext &Context);
- /// Check if the given bitcode buffer contains a summary block.
- Expected<bool> hasGlobalValueSummary(MemoryBufferRef Buffer);
+ /// Returns LTO information for the specified bitcode file.
+ Expected<BitcodeLTOInfo> getBitcodeLTOInfo(MemoryBufferRef Buffer);
/// Parse the specified bitcode buffer, returning the module summary index.
Expected<std::unique_ptr<ModuleSummaryIndex>>
@@ -157,7 +165,7 @@ namespace llvm {
/// Parse the specified bitcode buffer and merge the index into CombinedIndex.
Error readModuleSummaryIndex(MemoryBufferRef Buffer,
ModuleSummaryIndex &CombinedIndex,
- unsigned ModuleId);
+ uint64_t ModuleId);
/// Parse the module summary index out of an IR file and return the module
/// summary index object if found, or an empty summary if not. If Path refers
Modified: llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h?rev=305482&r1=305481&r2=305482&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h (original)
+++ llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h Thu Jun 15 12:26:13 2017
@@ -567,6 +567,7 @@ public:
bool isGlobalValueLive(const GlobalValueSummary *GVS) const {
return !WithGlobalValueDeadStripping || GVS->isLive();
}
+ bool isGUIDLive(GlobalValue::GUID GUID) const;
/// Return a ValueInfo for GUID if it exists, otherwise return ValueInfo().
ValueInfo getValueInfo(GlobalValue::GUID GUID) const {
Modified: llvm/trunk/include/llvm/LTO/LTO.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LTO/LTO.h?rev=305482&r1=305481&r2=305482&view=diff
==============================================================================
--- llvm/trunk/include/llvm/LTO/LTO.h (original)
+++ llvm/trunk/include/llvm/LTO/LTO.h Thu Jun 15 12:26:13 2017
@@ -281,6 +281,16 @@ private:
bool HasModule = false;
std::unique_ptr<Module> CombinedModule;
std::unique_ptr<IRMover> Mover;
+
+ // This stores the information about a regular LTO module that we have added
+ // to the link. It will either be linked immediately (for modules without
+ // summaries) or after summary-based dead stripping (for modules with
+ // summaries).
+ struct AddedModule {
+ std::unique_ptr<Module> M;
+ std::vector<GlobalValue *> Keep;
+ };
+ std::vector<AddedModule> ModsWithSummaries;
} RegularLTO;
struct ThinLTOState {
@@ -303,9 +313,10 @@ private:
/// The unmangled name of the global.
std::string IRName;
- /// Keep track if the symbol is visible outside of ThinLTO (i.e. in
- /// either a regular object or the regular LTO partition).
- bool VisibleOutsideThinLTO = false;
+ /// Keep track if the symbol is visible outside of a module with a summary
+ /// (i.e. in either a regular object or a regular LTO module without a
+ /// summary).
+ bool VisibleOutsideSummary = false;
bool UnnamedAddr = true;
@@ -339,8 +350,9 @@ private:
// Global mapping from mangled symbol names to resolutions.
StringMap<GlobalResolution> GlobalResolutions;
- void addSymbolToGlobalRes(const InputFile::Symbol &Sym, SymbolResolution Res,
- unsigned Partition);
+ void addModuleToGlobalRes(ArrayRef<InputFile::Symbol> Syms,
+ ArrayRef<SymbolResolution> Res, unsigned Partition,
+ bool InSummary);
// These functions take a range of symbol resolutions [ResI, ResE) and consume
// the resolutions used by a single input module by incrementing ResI. After
@@ -348,10 +360,13 @@ private:
// the remaining modules in the InputFile.
Error addModule(InputFile &Input, unsigned ModI,
const SymbolResolution *&ResI, const SymbolResolution *ResE);
- Error addRegularLTO(BitcodeModule BM,
- ArrayRef<InputFile::Symbol> Syms,
- const SymbolResolution *&ResI,
- const SymbolResolution *ResE);
+
+ Expected<RegularLTOState::AddedModule>
+ addRegularLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
+ const SymbolResolution *&ResI, const SymbolResolution *ResE);
+ Error linkRegularLTO(RegularLTOState::AddedModule Mod,
+ bool LivenessFromIndex);
+
Error addThinLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
const SymbolResolution *&ResI, const SymbolResolution *ResE);
Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=305482&r1=305481&r2=305482&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Thu Jun 15 12:26:13 2017
@@ -733,7 +733,7 @@ private:
std::vector<FunctionSummary::EdgeTy> makeCallList(ArrayRef<uint64_t> Record,
bool IsOldProfileFormat,
bool HasProfile);
- Error parseEntireSummary();
+ Error parseEntireSummary(unsigned ID);
Error parseModuleStringTable();
std::pair<ValueInfo, GlobalValue::GUID>
@@ -4854,6 +4854,7 @@ Error ModuleSummaryIndexBitcodeReader::p
return error("Invalid record");
break;
case bitc::GLOBALVAL_SUMMARY_BLOCK_ID:
+ case bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID:
assert(!SeenValueSymbolTable &&
"Already read VST when parsing summary block?");
// We might not have a VST if there were no values in the
@@ -4866,7 +4867,7 @@ Error ModuleSummaryIndexBitcodeReader::p
SeenValueSymbolTable = true;
}
SeenGlobalValSummary = true;
- if (Error Err = parseEntireSummary())
+ if (Error Err = parseEntireSummary(Entry.ID))
return Err;
break;
case bitc::MODULE_STRTAB_BLOCK_ID:
@@ -4974,8 +4975,8 @@ std::vector<FunctionSummary::EdgeTy> Mod
// Eagerly parse the entire summary block. This populates the GlobalValueSummary
// objects in the index.
-Error ModuleSummaryIndexBitcodeReader::parseEntireSummary() {
- if (Stream.EnterSubBlock(bitc::GLOBALVAL_SUMMARY_BLOCK_ID))
+Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
+ if (Stream.EnterSubBlock(ID))
return error("Invalid record");
SmallVector<uint64_t, 64> Record;
@@ -5517,13 +5518,16 @@ BitcodeModule::getLazyModule(LLVMContext
}
// Parse the specified bitcode buffer and merge the index into CombinedIndex.
+// We don't use ModuleIdentifier here because the client may need to control the
+// module path used in the combined summary (e.g. when reading summaries for
+// regular LTO modules).
Error BitcodeModule::readSummary(ModuleSummaryIndex &CombinedIndex,
- unsigned ModuleId) {
+ StringRef ModulePath, uint64_t ModuleId) {
BitstreamCursor Stream(Buffer);
Stream.JumpToBit(ModuleBit);
ModuleSummaryIndexBitcodeReader R(std::move(Stream), Strtab, CombinedIndex,
- ModuleIdentifier, ModuleId);
+ ModulePath, ModuleId);
return R.parseModule();
}
@@ -5543,7 +5547,7 @@ Expected<std::unique_ptr<ModuleSummaryIn
}
// Check if the given bitcode buffer contains a global value summary block.
-Expected<bool> BitcodeModule::hasSummary() {
+Expected<BitcodeLTOInfo> BitcodeModule::getLTOInfo() {
BitstreamCursor Stream(Buffer);
Stream.JumpToBit(ModuleBit);
@@ -5557,11 +5561,14 @@ Expected<bool> BitcodeModule::hasSummary
case BitstreamEntry::Error:
return error("Malformed block");
case BitstreamEntry::EndBlock:
- return false;
+ return BitcodeLTOInfo{/*IsThinLTO=*/false, /*HasSummary=*/false};
case BitstreamEntry::SubBlock:
if (Entry.ID == bitc::GLOBALVAL_SUMMARY_BLOCK_ID)
- return true;
+ return BitcodeLTOInfo{/*IsThinLTO=*/true, /*HasSummary=*/true};
+
+ if (Entry.ID == bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID)
+ return BitcodeLTOInfo{/*IsThinLTO=*/false, /*HasSummary=*/true};
// Ignore other sub-blocks.
if (Stream.SkipBlock())
@@ -5648,12 +5655,12 @@ Expected<std::string> llvm::getBitcodePr
Error llvm::readModuleSummaryIndex(MemoryBufferRef Buffer,
ModuleSummaryIndex &CombinedIndex,
- unsigned ModuleId) {
+ uint64_t ModuleId) {
Expected<BitcodeModule> BM = getSingleModule(Buffer);
if (!BM)
return BM.takeError();
- return BM->readSummary(CombinedIndex, ModuleId);
+ return BM->readSummary(CombinedIndex, BM->getModuleIdentifier(), ModuleId);
}
Expected<std::unique_ptr<ModuleSummaryIndex>>
@@ -5665,12 +5672,12 @@ llvm::getModuleSummaryIndex(MemoryBuffer
return BM->getSummary();
}
-Expected<bool> llvm::hasGlobalValueSummary(MemoryBufferRef Buffer) {
+Expected<BitcodeLTOInfo> llvm::getBitcodeLTOInfo(MemoryBufferRef Buffer) {
Expected<BitcodeModule> BM = getSingleModule(Buffer);
if (!BM)
return BM.takeError();
- return BM->hasSummary();
+ return BM->getLTOInfo();
}
Expected<std::unique_ptr<ModuleSummaryIndex>>
Modified: llvm/trunk/lib/IR/ModuleSummaryIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/ModuleSummaryIndex.cpp?rev=305482&r1=305481&r2=305482&view=diff
==============================================================================
--- llvm/trunk/lib/IR/ModuleSummaryIndex.cpp (original)
+++ llvm/trunk/lib/IR/ModuleSummaryIndex.cpp Thu Jun 15 12:26:13 2017
@@ -56,3 +56,13 @@ ModuleSummaryIndex::getGlobalValueSummar
auto &Summary = VI.getSummaryList()[0];
return Summary.get();
}
+
+bool ModuleSummaryIndex::isGUIDLive(GlobalValue::GUID GUID) const {
+ auto VI = getValueInfo(GUID);
+ if (!VI)
+ return false;
+ for (auto &I : VI.getSummaryList())
+ if (isGlobalValueLive(I.get()))
+ return true;
+ return false;
+}
Modified: llvm/trunk/lib/LTO/LTO.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/LTO.cpp?rev=305482&r1=305481&r2=305482&view=diff
==============================================================================
--- llvm/trunk/lib/LTO/LTO.cpp (original)
+++ llvm/trunk/lib/LTO/LTO.cpp Thu Jun 15 12:26:13 2017
@@ -364,31 +364,39 @@ LTO::LTO(Config Conf, ThinBackend Backen
// Requires a destructor for MapVector<BitcodeModule>.
LTO::~LTO() = default;
-// Add the given symbol to the GlobalResolutions map, and resolve its partition.
-void LTO::addSymbolToGlobalRes(const InputFile::Symbol &Sym,
- SymbolResolution Res, unsigned Partition) {
- auto &GlobalRes = GlobalResolutions[Sym.getName()];
- GlobalRes.UnnamedAddr &= Sym.isUnnamedAddr();
- if (Res.Prevailing)
- GlobalRes.IRName = Sym.getIRName();
-
- // Set the partition to external if we know it is re-defined by the linker
- // with -defsym or -wrap options, used elsewhere, e.g. it is visible to a
- // regular object, is referenced from llvm.compiler_used, or was already
- // recorded as being referenced from a different partition.
- if (Res.LinkerRedefined || Res.VisibleToRegularObj || Sym.isUsed() ||
- (GlobalRes.Partition != GlobalResolution::Unknown &&
- GlobalRes.Partition != Partition)) {
- GlobalRes.Partition = GlobalResolution::External;
- } else
- // First recorded reference, save the current partition.
- GlobalRes.Partition = Partition;
-
- // Flag as visible outside of ThinLTO if visible from a regular object or
- // if this is a reference in the regular LTO partition.
- GlobalRes.VisibleOutsideThinLTO |=
- (Res.VisibleToRegularObj || Sym.isUsed() ||
- Partition == GlobalResolution::RegularLTO);
+// Add the symbols in the given module to the GlobalResolutions map, and resolve
+// their partitions.
+void LTO::addModuleToGlobalRes(ArrayRef<InputFile::Symbol> Syms,
+ ArrayRef<SymbolResolution> Res,
+ unsigned Partition, bool InSummary) {
+ auto *ResI = Res.begin();
+ auto *ResE = Res.end();
+ for (const InputFile::Symbol &Sym : Syms) {
+ assert(ResI != ResE);
+ SymbolResolution Res = *ResI++;
+
+ auto &GlobalRes = GlobalResolutions[Sym.getName()];
+ GlobalRes.UnnamedAddr &= Sym.isUnnamedAddr();
+ if (Res.Prevailing)
+ GlobalRes.IRName = Sym.getIRName();
+
+ // Set the partition to external if we know it is re-defined by the linker
+ // with -defsym or -wrap options, used elsewhere, e.g. it is visible to a
+ // regular object, is referenced from llvm.compiler_used, or was already
+ // recorded as being referenced from a different partition.
+ if (Res.LinkerRedefined || Res.VisibleToRegularObj || Sym.isUsed() ||
+ (GlobalRes.Partition != GlobalResolution::Unknown &&
+ GlobalRes.Partition != Partition)) {
+ GlobalRes.Partition = GlobalResolution::External;
+ } else
+ // First recorded reference, save the current partition.
+ GlobalRes.Partition = Partition;
+
+ // Flag as visible outside of summary if visible from a regular object or
+ // from a module that does not have a summary.
+ GlobalRes.VisibleOutsideSummary |=
+ (Res.VisibleToRegularObj || Sym.isUsed() || !InSummary);
+ }
}
static void writeToResolutionFile(raw_ostream &OS, InputFile *Input,
@@ -434,46 +442,61 @@ Error LTO::add(std::unique_ptr<InputFile
Error LTO::addModule(InputFile &Input, unsigned ModI,
const SymbolResolution *&ResI,
const SymbolResolution *ResE) {
- Expected<bool> HasThinLTOSummary = Input.Mods[ModI].hasSummary();
- if (!HasThinLTOSummary)
- return HasThinLTOSummary.takeError();
+ Expected<BitcodeLTOInfo> LTOInfo = Input.Mods[ModI].getLTOInfo();
+ if (!LTOInfo)
+ return LTOInfo.takeError();
+ BitcodeModule BM = Input.Mods[ModI];
auto ModSyms = Input.module_symbols(ModI);
- if (*HasThinLTOSummary)
- return addThinLTO(Input.Mods[ModI], ModSyms, ResI, ResE);
- else
- return addRegularLTO(Input.Mods[ModI], ModSyms, ResI, ResE);
+ addModuleToGlobalRes(ModSyms, {ResI, ResE},
+ LTOInfo->IsThinLTO ? ThinLTO.ModuleMap.size() + 1 : 0,
+ LTOInfo->HasSummary);
+
+ if (LTOInfo->IsThinLTO)
+ return addThinLTO(BM, ModSyms, ResI, ResE);
+
+ Expected<RegularLTOState::AddedModule> ModOrErr =
+ addRegularLTO(BM, ModSyms, ResI, ResE);
+ if (!ModOrErr)
+ return ModOrErr.takeError();
+
+ if (!LTOInfo->HasSummary)
+ return linkRegularLTO(std::move(*ModOrErr), /*LivenessFromIndex=*/false);
+
+ // Regular LTO module summaries are added to a dummy module that represents
+ // the combined regular LTO module.
+ if (Error Err = BM.readSummary(ThinLTO.CombinedIndex, "", -1ull))
+ return Err;
+ RegularLTO.ModsWithSummaries.push_back(std::move(*ModOrErr));
+ return Error::success();
}
// Add a regular LTO object to the link.
-Error LTO::addRegularLTO(BitcodeModule BM,
- ArrayRef<InputFile::Symbol> Syms,
- const SymbolResolution *&ResI,
- const SymbolResolution *ResE) {
- if (!RegularLTO.CombinedModule) {
- RegularLTO.CombinedModule =
- llvm::make_unique<Module>("ld-temp.o", RegularLTO.Ctx);
- RegularLTO.Mover = llvm::make_unique<IRMover>(*RegularLTO.CombinedModule);
- }
+// The resulting module needs to be linked into the combined LTO module with
+// linkRegularLTO.
+Expected<LTO::RegularLTOState::AddedModule>
+LTO::addRegularLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
+ const SymbolResolution *&ResI,
+ const SymbolResolution *ResE) {
+ RegularLTOState::AddedModule Mod;
Expected<std::unique_ptr<Module>> MOrErr =
BM.getLazyModule(RegularLTO.Ctx, /*ShouldLazyLoadMetadata*/ true,
/*IsImporting*/ false);
if (!MOrErr)
return MOrErr.takeError();
-
Module &M = **MOrErr;
+ Mod.M = std::move(*MOrErr);
+
if (Error Err = M.materializeMetadata())
- return Err;
+ return std::move(Err);
UpgradeDebugInfo(M);
ModuleSymbolTable SymTab;
SymTab.addModule(&M);
- std::vector<GlobalValue *> Keep;
-
for (GlobalVariable &GV : M.globals())
if (GV.hasAppendingLinkage())
- Keep.push_back(&GV);
+ Mod.Keep.push_back(&GV);
DenseSet<GlobalObject *> AliasedGlobals;
for (auto &GA : M.aliases())
@@ -502,7 +525,6 @@ Error LTO::addRegularLTO(BitcodeModule B
for (const InputFile::Symbol &Sym : Syms) {
assert(ResI != ResE);
SymbolResolution Res = *ResI++;
- addSymbolToGlobalRes(Sym, Res, 0);
assert(MsymI != MsymE);
ModuleSymbolTable::Symbol Msym = *MsymI++;
@@ -512,7 +534,7 @@ Error LTO::addRegularLTO(BitcodeModule B
if (Res.Prevailing) {
if (Sym.isUndefined())
continue;
- Keep.push_back(GV);
+ Mod.Keep.push_back(GV);
// For symbols re-defined with linker -wrap and -defsym options,
// set the linkage to weak to inhibit IPO. The linkage will be
// restored by the linker.
@@ -527,17 +549,14 @@ Error LTO::addRegularLTO(BitcodeModule B
(GV->hasLinkOnceODRLinkage() || GV->hasWeakODRLinkage() ||
GV->hasAvailableExternallyLinkage()) &&
!AliasedGlobals.count(cast<GlobalObject>(GV))) {
- // Either of the above three types of linkage indicates that the
+ // Any of the above three types of linkage indicates that the
// chosen prevailing symbol will have the same semantics as this copy of
- // the symbol, so we can link it with available_externally linkage. We
- // only need to do this if the symbol is undefined.
- GlobalValue *CombinedGV =
- RegularLTO.CombinedModule->getNamedValue(GV->getName());
- if (!CombinedGV || CombinedGV->isDeclaration()) {
- Keep.push_back(GV);
- GV->setLinkage(GlobalValue::AvailableExternallyLinkage);
- cast<GlobalObject>(GV)->setComdat(nullptr);
- }
+ // the symbol, so we may be able to link it with available_externally
+ // linkage. We will decide later whether to do that when we link this
+ // module (in linkRegularLTO), based on whether it is undefined.
+ Mod.Keep.push_back(GV);
+ GV->setLinkage(GlobalValue::AvailableExternallyLinkage);
+ cast<GlobalObject>(GV)->setComdat(nullptr);
}
}
// Common resolution: collect the maximum size/alignment over all commons.
@@ -555,25 +574,54 @@ Error LTO::addRegularLTO(BitcodeModule B
// FIXME: use proposed local attribute for FinalDefinitionInLinkageUnit.
}
assert(MsymI == MsymE);
+ return std::move(Mod);
+}
- return RegularLTO.Mover->move(std::move(*MOrErr), Keep,
+Error LTO::linkRegularLTO(RegularLTOState::AddedModule Mod,
+ bool LivenessFromIndex) {
+ if (!RegularLTO.CombinedModule) {
+ RegularLTO.CombinedModule =
+ llvm::make_unique<Module>("ld-temp.o", RegularLTO.Ctx);
+ RegularLTO.Mover = llvm::make_unique<IRMover>(*RegularLTO.CombinedModule);
+ }
+
+ std::vector<GlobalValue *> Keep;
+ for (GlobalValue *GV : Mod.Keep) {
+ if (LivenessFromIndex && !ThinLTO.CombinedIndex.isGUIDLive(GV->getGUID()))
+ continue;
+
+ if (!GV->hasAvailableExternallyLinkage()) {
+ Keep.push_back(GV);
+ continue;
+ }
+
+ // Only link available_externally definitions if we don't already have a
+ // definition.
+ GlobalValue *CombinedGV =
+ RegularLTO.CombinedModule->getNamedValue(GV->getName());
+ if (CombinedGV && !CombinedGV->isDeclaration())
+ continue;
+
+ Keep.push_back(GV);
+ }
+
+ return RegularLTO.Mover->move(std::move(Mod.M), Keep,
[](GlobalValue &, IRMover::ValueAdder) {},
/* IsPerformingImport */ false);
}
-// Add a ThinLTO object to the link.
-Error LTO::addThinLTO(BitcodeModule BM,
- ArrayRef<InputFile::Symbol> Syms,
+// Add a ThinLTO module to the link.
+Error LTO::addThinLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
const SymbolResolution *&ResI,
const SymbolResolution *ResE) {
if (Error Err =
- BM.readSummary(ThinLTO.CombinedIndex, ThinLTO.ModuleMap.size()))
+ BM.readSummary(ThinLTO.CombinedIndex, BM.getModuleIdentifier(),
+ ThinLTO.ModuleMap.size()))
return Err;
for (const InputFile::Symbol &Sym : Syms) {
assert(ResI != ResE);
SymbolResolution Res = *ResI++;
- addSymbolToGlobalRes(Sym, Res, ThinLTO.ModuleMap.size() + 1);
if (Res.Prevailing) {
if (!Sym.getIRName().empty()) {
@@ -601,7 +649,7 @@ Error LTO::run(AddStreamFn AddStream, Na
// Compute "dead" symbols, we don't want to import/export these!
DenseSet<GlobalValue::GUID> GUIDPreservedSymbols;
for (auto &Res : GlobalResolutions) {
- if (Res.second.VisibleOutsideThinLTO &&
+ if (Res.second.VisibleOutsideSummary &&
// IRName will be defined if we have seen the prevailing copy of
// this value. If not, no need to preserve any ThinLTO copies.
!Res.second.IRName.empty())
@@ -614,7 +662,8 @@ Error LTO::run(AddStreamFn AddStream, Na
// Save the status of having a regularLTO combined module, as
// this is needed for generating the ThinLTO Task ID, and
// the CombinedModule will be moved at the end of runRegularLTO.
- bool HasRegularLTO = RegularLTO.CombinedModule != nullptr;
+ bool HasRegularLTO = RegularLTO.CombinedModule != nullptr ||
+ !RegularLTO.ModsWithSummaries.empty();
// Invoke regular LTO if there was a regular LTO module to start with.
if (HasRegularLTO)
if (auto E = runRegularLTO(AddStream))
@@ -623,6 +672,11 @@ Error LTO::run(AddStreamFn AddStream, Na
}
Error LTO::runRegularLTO(AddStreamFn AddStream) {
+ for (auto &M : RegularLTO.ModsWithSummaries)
+ if (Error Err = linkRegularLTO(std::move(M),
+ /*LivenessFromIndex=*/true))
+ return Err;
+
// Make sure commons have the right size/alignment: we kept the largest from
// all the prevailing when adding the inputs, and we apply it here.
const DataLayout &DL = RegularLTO.CombinedModule->getDataLayout();
@@ -920,17 +974,6 @@ ThinBackend lto::createWriteIndexesThinB
};
}
-static bool IsLiveByGUID(const ModuleSummaryIndex &Index,
- GlobalValue::GUID GUID) {
- auto VI = Index.getValueInfo(GUID);
- if (!VI)
- return false;
- for (auto &I : VI.getSummaryList())
- if (Index.isGlobalValueLive(I.get()))
- return true;
- return false;
-}
-
Error LTO::runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache,
bool HasRegularLTO) {
if (ThinLTO.ModuleMap.empty())
@@ -979,7 +1022,7 @@ Error LTO::runThinLTO(AddStreamFn AddStr
auto GUID = GlobalValue::getGUID(
GlobalValue::dropLLVMManglingEscape(Res.second.IRName));
// Mark exported unless index-based analysis determined it to be dead.
- if (IsLiveByGUID(ThinLTO.CombinedIndex, GUID))
+ if (ThinLTO.CombinedIndex.isGUIDLive(GUID))
ExportedGUIDs.insert(GUID);
}
Modified: llvm/trunk/lib/LTO/LTOModule.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/LTOModule.cpp?rev=305482&r1=305481&r2=305482&view=diff
==============================================================================
--- llvm/trunk/lib/LTO/LTOModule.cpp (original)
+++ llvm/trunk/lib/LTO/LTOModule.cpp Thu Jun 15 12:26:13 2017
@@ -77,14 +77,12 @@ bool LTOModule::isBitcodeFile(StringRef
}
bool LTOModule::isThinLTO() {
- // Right now the detection is only based on the summary presence. We may want
- // to add a dedicated flag at some point.
- Expected<bool> Result = hasGlobalValueSummary(MBRef);
+ Expected<BitcodeLTOInfo> Result = getBitcodeLTOInfo(MBRef);
if (!Result) {
logAllUnhandledErrors(Result.takeError(), errs(), "");
return false;
}
- return *Result;
+ return Result->IsThinLTO;
}
bool LTOModule::isBitcodeForTarget(MemoryBuffer *Buffer,
Added: llvm/trunk/test/LTO/Resolution/X86/Inputs/dead-strip-fulllto.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LTO/Resolution/X86/Inputs/dead-strip-fulllto.ll?rev=305482&view=auto
==============================================================================
--- llvm/trunk/test/LTO/Resolution/X86/Inputs/dead-strip-fulllto.ll (added)
+++ llvm/trunk/test/LTO/Resolution/X86/Inputs/dead-strip-fulllto.ll Thu Jun 15 12:26:13 2017
@@ -0,0 +1,16 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @live1() {
+ call void @live2()
+ ret void
+}
+
+declare void @live2()
+
+define void @dead1() {
+ call void @dead2()
+ ret void
+}
+
+declare void @dead2()
Added: llvm/trunk/test/LTO/Resolution/X86/dead-strip-fulllto.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LTO/Resolution/X86/dead-strip-fulllto.ll?rev=305482&view=auto
==============================================================================
--- llvm/trunk/test/LTO/Resolution/X86/dead-strip-fulllto.ll (added)
+++ llvm/trunk/test/LTO/Resolution/X86/dead-strip-fulllto.ll Thu Jun 15 12:26:13 2017
@@ -0,0 +1,37 @@
+; RUN: opt -module-summary -o %t %s
+; RUN: opt -module-summary -o %t2 %S/Inputs/dead-strip-fulllto.ll
+; RUN: llvm-lto2 run %t -r %t,main,px -r %t,live1,p -r %t,live2,p -r %t,dead2,p \
+; RUN: %t2 -r %t2,live1,p -r %t2,live2, -r %t2,dead1,p -r %t2,dead2, \
+; RUN: -save-temps -o %t3
+; RUN: llvm-nm %t3.0 | FileCheck --check-prefix=FULL %s
+; RUN: llvm-nm %t3.1 | FileCheck --check-prefix=THIN %s
+
+; FULL-NOT: dead
+; FULL: U live1
+; FULL: T live2
+; FULL: T main
+
+; THIN-NOT: dead
+; THIN: T live1
+; THIN: U live2
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @main() {
+ call void @live1()
+ ret void
+}
+
+declare void @live1()
+
+define void @live2() {
+ ret void
+}
+
+define void @dead2() {
+ ret void
+}
+
+!0 = !{i32 1, !"ThinLTO", i32 0}
+!llvm.module.flags = !{ !0 }
More information about the llvm-commits
mailing list