1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00

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

llvm-svn: 305482
This commit is contained in:
Peter Collingbourne 2017-06-15 17:26:13 +00:00
parent d74b25c229
commit 910e0ef4ff
9 changed files with 243 additions and 108 deletions

View File

@ -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

View File

@ -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 {

View File

@ -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);

View File

@ -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::parseModule() {
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::parseModule() {
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> ModuleSummaryIndexBitcodeReader::makeCallLi
// 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 &Context, bool ShouldLazyLoadMetadata,
}
// 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<ModuleSummaryIndex>> BitcodeModule::getSummary() {
}
// 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::getBitcodeProducerString(MemoryBufferRef Buffer) {
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(MemoryBufferRef Buffer) {
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>>

View File

@ -56,3 +56,13 @@ ModuleSummaryIndex::getGlobalValueSummary(uint64_t ValueGUID,
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;
}

View File

@ -364,31 +364,39 @@ LTO::LTO(Config Conf, ThinBackend Backend,
// 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();
// 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++;
// 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;
auto &GlobalRes = GlobalResolutions[Sym.getName()];
GlobalRes.UnnamedAddr &= Sym.isUnnamedAddr();
if (Res.Prevailing)
GlobalRes.IRName = Sym.getIRName();
// 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);
// 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> Input,
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 BM,
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 BM,
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 BM,
(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 BM,
// 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, NativeObjectCache Cache) {
// 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, NativeObjectCache Cache) {
// 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, NativeObjectCache Cache) {
}
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::createWriteIndexesThinBackend(std::string OldPrefix,
};
}
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 AddStream, NativeObjectCache Cache,
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);
}

View File

@ -77,14 +77,12 @@ bool LTOModule::isBitcodeFile(StringRef Path) {
}
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,

View File

@ -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()

View File

@ -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 }