summaryrefslogtreecommitdiff
path: root/lib/LTO
diff options
context:
space:
mode:
Diffstat (limited to 'lib/LTO')
-rw-r--r--lib/LTO/Caching.cpp80
-rw-r--r--lib/LTO/LTO.cpp210
-rw-r--r--lib/LTO/LTOBackend.cpp31
-rw-r--r--lib/LTO/LTOCodeGenerator.cpp68
-rw-r--r--lib/LTO/LTOModule.cpp43
-rw-r--r--lib/LTO/ThinLTOCodeGenerator.cpp10
-rw-r--r--lib/LTO/UpdateCompilerUsed.cpp5
7 files changed, 266 insertions, 181 deletions
diff --git a/lib/LTO/Caching.cpp b/lib/LTO/Caching.cpp
index e32e46c4c3c8..dd47eb584b7f 100644
--- a/lib/LTO/Caching.cpp
+++ b/lib/LTO/Caching.cpp
@@ -14,9 +14,9 @@
#include "llvm/LTO/Caching.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Errc.h"
-#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@@ -36,7 +36,7 @@ Expected<NativeObjectCache> lto::localCache(StringRef CacheDirectoryPath,
ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =
MemoryBuffer::getFile(EntryPath);
if (MBOrErr) {
- AddBuffer(Task, std::move(*MBOrErr));
+ AddBuffer(Task, std::move(*MBOrErr), EntryPath);
return AddStreamFn();
}
@@ -48,54 +48,80 @@ Expected<NativeObjectCache> lto::localCache(StringRef CacheDirectoryPath,
// file to the cache and calling AddBuffer to add it to the link.
struct CacheStream : NativeObjectStream {
AddBufferFn AddBuffer;
- std::string TempFilename;
+ sys::fs::TempFile TempFile;
std::string EntryPath;
unsigned Task;
CacheStream(std::unique_ptr<raw_pwrite_stream> OS, AddBufferFn AddBuffer,
- std::string TempFilename, std::string EntryPath,
+ sys::fs::TempFile TempFile, std::string EntryPath,
unsigned Task)
: NativeObjectStream(std::move(OS)), AddBuffer(std::move(AddBuffer)),
- TempFilename(std::move(TempFilename)),
- EntryPath(std::move(EntryPath)), Task(Task) {}
+ TempFile(std::move(TempFile)), EntryPath(std::move(EntryPath)),
+ Task(Task) {}
~CacheStream() {
- // FIXME: This code could race with the cache pruner, but it is unlikely
- // that the cache pruner will choose to remove a newly created file.
-
- // Make sure the file is closed before committing it.
+ // Make sure the stream is closed before committing it.
OS.reset();
- // This is atomic on POSIX systems.
- if (auto EC = sys::fs::rename(TempFilename, EntryPath))
- report_fatal_error(Twine("Failed to rename temporary file ") +
- TempFilename + ": " + EC.message() + "\n");
+ // Open the file first to avoid racing with a cache pruner.
ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =
- MemoryBuffer::getFile(EntryPath);
+ MemoryBuffer::getOpenFile(TempFile.FD, TempFile.TmpName,
+ /*FileSize*/ -1,
+ /*RequiresNullTerminator*/ false);
if (!MBOrErr)
- report_fatal_error(Twine("Failed to open cache file ") + EntryPath +
- ": " + MBOrErr.getError().message() + "\n");
- AddBuffer(Task, std::move(*MBOrErr));
+ report_fatal_error(Twine("Failed to open new cache file ") +
+ TempFile.TmpName + ": " +
+ MBOrErr.getError().message() + "\n");
+
+ // On POSIX systems, this will atomically replace the destination if
+ // it already exists. We try to emulate this on Windows, but this may
+ // fail with a permission denied error (for example, if the destination
+ // is currently opened by another process that does not give us the
+ // sharing permissions we need). Since the existing file should be
+ // semantically equivalent to the one we are trying to write, we give
+ // AddBuffer a copy of the bytes we wrote in that case. We do this
+ // instead of just using the existing file, because the pruner might
+ // delete the file before we get a chance to use it.
+ Error E = TempFile.keep(EntryPath);
+ E = handleErrors(std::move(E), [&](const ECError &E) -> Error {
+ std::error_code EC = E.convertToErrorCode();
+ if (EC != errc::permission_denied)
+ return errorCodeToError(EC);
+
+ auto MBCopy = MemoryBuffer::getMemBufferCopy((*MBOrErr)->getBuffer(),
+ EntryPath);
+ MBOrErr = std::move(MBCopy);
+
+ // FIXME: should we consume the discard error?
+ consumeError(TempFile.discard());
+
+ return Error::success();
+ });
+
+ if (E)
+ report_fatal_error(Twine("Failed to rename temporary file ") +
+ TempFile.TmpName + " to " + EntryPath + ": " +
+ toString(std::move(E)) + "\n");
+
+ AddBuffer(Task, std::move(*MBOrErr), EntryPath);
}
};
return [=](size_t Task) -> std::unique_ptr<NativeObjectStream> {
// Write to a temporary to avoid race condition
- int TempFD;
- SmallString<64> TempFilenameModel, TempFilename;
+ SmallString<64> TempFilenameModel;
sys::path::append(TempFilenameModel, CacheDirectoryPath, "Thin-%%%%%%.tmp.o");
- std::error_code EC =
- sys::fs::createUniqueFile(TempFilenameModel, TempFD, TempFilename,
- sys::fs::owner_read | sys::fs::owner_write);
- if (EC) {
- errs() << "Error: " << EC.message() << "\n";
+ Expected<sys::fs::TempFile> Temp = sys::fs::TempFile::create(
+ TempFilenameModel, sys::fs::owner_read | sys::fs::owner_write);
+ if (!Temp) {
+ errs() << "Error: " << toString(Temp.takeError()) << "\n";
report_fatal_error("ThinLTO: Can't get a temporary file");
}
// This CacheStream will move the temporary file into the cache when done.
return llvm::make_unique<CacheStream>(
- llvm::make_unique<raw_fd_ostream>(TempFD, /* ShouldClose */ true),
- AddBuffer, TempFilename.str(), EntryPath.str(), Task);
+ llvm::make_unique<raw_fd_ostream>(Temp->FD, /* ShouldClose */ false),
+ AddBuffer, std::move(*Temp), EntryPath.str(), Task);
};
};
}
diff --git a/lib/LTO/LTO.cpp b/lib/LTO/LTO.cpp
index 19973946ac5a..64e5186255bd 100644
--- a/lib/LTO/LTO.cpp
+++ b/lib/LTO/LTO.cpp
@@ -65,7 +65,9 @@ static void computeCacheKey(
const FunctionImporter::ExportSetTy &ExportList,
const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
const GVSummaryMapTy &DefinedGlobals,
- const TypeIdSummariesByGuidTy &TypeIdSummariesByGuid) {
+ const TypeIdSummariesByGuidTy &TypeIdSummariesByGuid,
+ const std::set<GlobalValue::GUID> &CfiFunctionDefs,
+ const std::set<GlobalValue::GUID> &CfiFunctionDecls) {
// Compute the unique hash for this entry.
// This is based on the current compiler version, the module itself, the
// export list, the hash for every single module in the import list, the
@@ -118,7 +120,10 @@ static void computeCacheKey(
AddUnsigned(*Conf.RelocModel);
else
AddUnsigned(-1);
- AddUnsigned(Conf.CodeModel);
+ if (Conf.CodeModel)
+ AddUnsigned(*Conf.CodeModel);
+ else
+ AddUnsigned(-1);
AddUnsigned(Conf.CGOptLevel);
AddUnsigned(Conf.CGFileType);
AddUnsigned(Conf.OptLevel);
@@ -155,22 +160,39 @@ static void computeCacheKey(
sizeof(GlobalValue::LinkageTypes)));
}
+ // Members of CfiFunctionDefs and CfiFunctionDecls that are referenced or
+ // defined in this module.
+ std::set<GlobalValue::GUID> UsedCfiDefs;
+ std::set<GlobalValue::GUID> UsedCfiDecls;
+
+ // Typeids used in this module.
std::set<GlobalValue::GUID> UsedTypeIds;
- auto AddUsedTypeIds = [&](GlobalValueSummary *GS) {
- auto *FS = dyn_cast_or_null<FunctionSummary>(GS);
- if (!FS)
- return;
- for (auto &TT : FS->type_tests())
- UsedTypeIds.insert(TT);
- for (auto &TT : FS->type_test_assume_vcalls())
- UsedTypeIds.insert(TT.GUID);
- for (auto &TT : FS->type_checked_load_vcalls())
- UsedTypeIds.insert(TT.GUID);
- for (auto &TT : FS->type_test_assume_const_vcalls())
- UsedTypeIds.insert(TT.VFunc.GUID);
- for (auto &TT : FS->type_checked_load_const_vcalls())
- UsedTypeIds.insert(TT.VFunc.GUID);
+ auto AddUsedCfiGlobal = [&](GlobalValue::GUID ValueGUID) {
+ if (CfiFunctionDefs.count(ValueGUID))
+ UsedCfiDefs.insert(ValueGUID);
+ if (CfiFunctionDecls.count(ValueGUID))
+ UsedCfiDecls.insert(ValueGUID);
+ };
+
+ auto AddUsedThings = [&](GlobalValueSummary *GS) {
+ if (!GS) return;
+ for (const ValueInfo &VI : GS->refs())
+ AddUsedCfiGlobal(VI.getGUID());
+ if (auto *FS = dyn_cast<FunctionSummary>(GS)) {
+ for (auto &TT : FS->type_tests())
+ UsedTypeIds.insert(TT);
+ for (auto &TT : FS->type_test_assume_vcalls())
+ UsedTypeIds.insert(TT.GUID);
+ for (auto &TT : FS->type_checked_load_vcalls())
+ UsedTypeIds.insert(TT.GUID);
+ for (auto &TT : FS->type_test_assume_const_vcalls())
+ UsedTypeIds.insert(TT.VFunc.GUID);
+ for (auto &TT : FS->type_checked_load_const_vcalls())
+ UsedTypeIds.insert(TT.VFunc.GUID);
+ for (auto &ET : FS->calls())
+ AddUsedCfiGlobal(ET.first.getGUID());
+ }
};
// Include the hash for the linkage type to reflect internalization and weak
@@ -179,14 +201,15 @@ static void computeCacheKey(
GlobalValue::LinkageTypes Linkage = GS.second->linkage();
Hasher.update(
ArrayRef<uint8_t>((const uint8_t *)&Linkage, sizeof(Linkage)));
- AddUsedTypeIds(GS.second);
+ AddUsedCfiGlobal(GS.first);
+ AddUsedThings(GS.second);
}
// Imported functions may introduce new uses of type identifier resolutions,
// so we need to collect their used resolutions as well.
for (auto &ImpM : ImportList)
for (auto &ImpF : ImpM.second)
- AddUsedTypeIds(Index.findSummaryInModule(ImpF.first, ImpM.first()));
+ AddUsedThings(Index.findSummaryInModule(ImpF.first, ImpM.first()));
auto AddTypeIdSummary = [&](StringRef TId, const TypeIdSummary &S) {
AddString(TId);
@@ -194,6 +217,11 @@ static void computeCacheKey(
AddUnsigned(S.TTRes.TheKind);
AddUnsigned(S.TTRes.SizeM1BitWidth);
+ AddUint64(S.TTRes.AlignLog2);
+ AddUint64(S.TTRes.SizeM1);
+ AddUint64(S.TTRes.BitMask);
+ AddUint64(S.TTRes.InlineBits);
+
AddUint64(S.WPDRes.size());
for (auto &WPD : S.WPDRes) {
AddUnsigned(WPD.first);
@@ -207,6 +235,8 @@ static void computeCacheKey(
AddUint64(Arg);
AddUnsigned(ByArg.second.TheKind);
AddUint64(ByArg.second.Info);
+ AddUnsigned(ByArg.second.Byte);
+ AddUnsigned(ByArg.second.Bit);
}
}
};
@@ -219,6 +249,14 @@ static void computeCacheKey(
AddTypeIdSummary(Summary->first, Summary->second);
}
+ AddUnsigned(UsedCfiDefs.size());
+ for (auto &V : UsedCfiDefs)
+ AddUint64(V);
+
+ AddUnsigned(UsedCfiDecls.size());
+ for (auto &V : UsedCfiDecls)
+ AddUint64(V);
+
if (!Conf.SampleProfile.empty()) {
auto FileOrErr = MemoryBuffer::getFile(Conf.SampleProfile);
if (FileOrErr)
@@ -347,7 +385,8 @@ StringRef InputFile::getName() const {
LTO::RegularLTOState::RegularLTOState(unsigned ParallelCodeGenParallelismLevel,
Config &Conf)
: ParallelCodeGenParallelismLevel(ParallelCodeGenParallelismLevel),
- Ctx(Conf) {}
+ Ctx(Conf), CombinedModule(llvm::make_unique<Module>("ld-temp.o", Ctx)),
+ Mover(llvm::make_unique<IRMover>(*CombinedModule)) {}
LTO::ThinLTOState::ThinLTOState(ThinBackend Backend) : Backend(Backend) {
if (!Backend)
@@ -378,8 +417,11 @@ void LTO::addModuleToGlobalRes(ArrayRef<InputFile::Symbol> Syms,
auto &GlobalRes = GlobalResolutions[Sym.getName()];
GlobalRes.UnnamedAddr &= Sym.isUnnamedAddr();
- if (Res.Prevailing)
+ if (Res.Prevailing) {
+ assert(GlobalRes.IRName.empty() &&
+ "Multiple prevailing defs are not allowed");
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
@@ -431,6 +473,9 @@ Error LTO::add(std::unique_ptr<InputFile> Input,
if (Conf.ResolutionFile)
writeToResolutionFile(*Conf.ResolutionFile, Input.get(), Res);
+ if (RegularLTO.CombinedModule->getTargetTriple().empty())
+ RegularLTO.CombinedModule->setTargetTriple(Input->getTargetTriple());
+
const SymbolResolution *ResI = Res.begin();
for (unsigned I = 0; I != Input->Mods.size(); ++I)
if (Error Err = addModule(*Input, I, ResI, Res.end()))
@@ -592,6 +637,9 @@ LTO::addRegularLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
NonPrevailingComdats.insert(GV->getComdat());
cast<GlobalObject>(GV)->setComdat(nullptr);
}
+
+ // Set the 'local' flag based on the linker resolution for this symbol.
+ GV->setDSOLocal(Res.FinalDefinitionInLinkageUnit);
}
// Common resolution: collect the maximum size/alignment over all commons.
// We also record if we see an instance of a common as prevailing, so that
@@ -605,7 +653,6 @@ LTO::addRegularLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
CommonRes.Prevailing |= Res.Prevailing;
}
- // FIXME: use proposed local attribute for FinalDefinitionInLinkageUnit.
}
if (!M.getComdatSymbolTable().empty())
for (GlobalValue &GV : M.global_values())
@@ -616,12 +663,6 @@ LTO::addRegularLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
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()))
@@ -660,10 +701,10 @@ Error LTO::addThinLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
assert(ResI != ResE);
SymbolResolution Res = *ResI++;
- if (Res.Prevailing) {
- if (!Sym.getIRName().empty()) {
- auto GUID = GlobalValue::getGUID(GlobalValue::getGlobalIdentifier(
- Sym.getIRName(), GlobalValue::ExternalLinkage, ""));
+ if (!Sym.getIRName().empty()) {
+ auto GUID = GlobalValue::getGUID(GlobalValue::getGlobalIdentifier(
+ Sym.getIRName(), GlobalValue::ExternalLinkage, ""));
+ if (Res.Prevailing) {
ThinLTO.PrevailingModuleForGUID[GUID] = BM.getModuleIdentifier();
// For linker redefined symbols (via --wrap or --defsym) we want to
@@ -675,6 +716,15 @@ Error LTO::addThinLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
GUID, BM.getModuleIdentifier()))
S->setLinkage(GlobalValue::WeakAnyLinkage);
}
+
+ // If the linker resolved the symbol to a local definition then mark it
+ // as local in the summary for the module we are adding.
+ if (Res.FinalDefinitionInLinkageUnit) {
+ if (auto S = ThinLTO.CombinedIndex.findSummaryInModule(
+ GUID, BM.getModuleIdentifier())) {
+ S->setDSOLocal(true);
+ }
+ }
}
}
@@ -705,16 +755,9 @@ Error LTO::run(AddStreamFn AddStream, NativeObjectCache Cache) {
computeDeadSymbols(ThinLTO.CombinedIndex, GUIDPreservedSymbols);
- // 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 ||
- !RegularLTO.ModsWithSummaries.empty();
- // Invoke regular LTO if there was a regular LTO module to start with.
- if (HasRegularLTO)
- if (auto E = runRegularLTO(AddStream))
- return E;
- return runThinLTO(AddStream, Cache, HasRegularLTO);
+ if (auto E = runRegularLTO(AddStream))
+ return E;
+ return runThinLTO(AddStream, Cache);
}
Error LTO::runRegularLTO(AddStreamFn AddStream) {
@@ -812,6 +855,8 @@ class InProcessThinBackend : public ThinBackendProc {
AddStreamFn AddStream;
NativeObjectCache Cache;
TypeIdSummariesByGuidTy TypeIdSummariesByGuid;
+ std::set<GlobalValue::GUID> CfiFunctionDefs;
+ std::set<GlobalValue::GUID> CfiFunctionDecls;
Optional<Error> Err;
std::mutex ErrMu;
@@ -831,6 +876,12 @@ public:
// each function without needing to compute GUIDs in each backend.
for (auto &TId : CombinedIndex.typeIds())
TypeIdSummariesByGuid[GlobalValue::getGUID(TId.first)].push_back(&TId);
+ for (auto &Name : CombinedIndex.cfiFunctionDefs())
+ CfiFunctionDefs.insert(
+ GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name)));
+ for (auto &Name : CombinedIndex.cfiFunctionDecls())
+ CfiFunctionDecls.insert(
+ GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name)));
}
Error runThinLTOBackendThread(
@@ -864,7 +915,8 @@ public:
SmallString<40> Key;
// The module may be cached, this helps handling it.
computeCacheKey(Key, Conf, CombinedIndex, ModuleID, ImportList, ExportList,
- ResolvedODR, DefinedGlobals, TypeIdSummariesByGuid);
+ ResolvedODR, DefinedGlobals, TypeIdSummariesByGuid,
+ CfiFunctionDefs, CfiFunctionDecls);
if (AddStreamFn CacheAddStream = Cache(Task, Key))
return RunThinBackend(CacheAddStream);
@@ -1020,8 +1072,7 @@ ThinBackend lto::createWriteIndexesThinBackend(std::string OldPrefix,
};
}
-Error LTO::runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache,
- bool HasRegularLTO) {
+Error LTO::runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache) {
if (ThinLTO.ModuleMap.empty())
return Error::success();
@@ -1051,36 +1102,45 @@ Error LTO::runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache,
ThinLTO.ModuleMap.size());
StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;
- if (Conf.OptLevel > 0) {
+ if (Conf.OptLevel > 0)
ComputeCrossModuleImport(ThinLTO.CombinedIndex, ModuleToDefinedGVSummaries,
ImportLists, ExportLists);
- std::set<GlobalValue::GUID> ExportedGUIDs;
- for (auto &Res : GlobalResolutions) {
- // First check if the symbol was flagged as having external references.
- if (Res.second.Partition != GlobalResolution::External)
- continue;
- // IRName will be defined if we have seen the prevailing copy of
- // this value. If not, no need to mark as exported from a ThinLTO
- // partition (and we can't get the GUID).
- if (Res.second.IRName.empty())
- continue;
- auto GUID = GlobalValue::getGUID(
- GlobalValue::dropLLVMManglingEscape(Res.second.IRName));
- // Mark exported unless index-based analysis determined it to be dead.
- if (ThinLTO.CombinedIndex.isGUIDLive(GUID))
- ExportedGUIDs.insert(GUID);
- }
-
- auto isExported = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID) {
- const auto &ExportList = ExportLists.find(ModuleIdentifier);
- return (ExportList != ExportLists.end() &&
- ExportList->second.count(GUID)) ||
- ExportedGUIDs.count(GUID);
- };
- thinLTOInternalizeAndPromoteInIndex(ThinLTO.CombinedIndex, isExported);
+ // Figure out which symbols need to be internalized. This also needs to happen
+ // at -O0 because summary-based DCE is implemented using internalization, and
+ // we must apply DCE consistently with the full LTO module in order to avoid
+ // undefined references during the final link.
+ std::set<GlobalValue::GUID> ExportedGUIDs;
+ for (auto &Res : GlobalResolutions) {
+ // First check if the symbol was flagged as having external references.
+ if (Res.second.Partition != GlobalResolution::External)
+ continue;
+ // IRName will be defined if we have seen the prevailing copy of
+ // this value. If not, no need to mark as exported from a ThinLTO
+ // partition (and we can't get the GUID).
+ if (Res.second.IRName.empty())
+ continue;
+ auto GUID = GlobalValue::getGUID(
+ GlobalValue::dropLLVMManglingEscape(Res.second.IRName));
+ // Mark exported unless index-based analysis determined it to be dead.
+ if (ThinLTO.CombinedIndex.isGUIDLive(GUID))
+ ExportedGUIDs.insert(GUID);
}
+ // Any functions referenced by the jump table in the regular LTO object must
+ // be exported.
+ for (auto &Def : ThinLTO.CombinedIndex.cfiFunctionDefs())
+ ExportedGUIDs.insert(
+ GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Def)));
+
+ auto isExported = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID) {
+ const auto &ExportList = ExportLists.find(ModuleIdentifier);
+ return (ExportList != ExportLists.end() &&
+ ExportList->second.count(GUID)) ||
+ ExportedGUIDs.count(GUID);
+ };
+ thinLTOInternalizeAndPromoteInIndex(ThinLTO.CombinedIndex, isExported);
+
auto isPrevailing = [&](GlobalValue::GUID GUID,
const GlobalValueSummary *S) {
return ThinLTO.PrevailingModuleForGUID[GUID] == S->modulePath();
@@ -1097,11 +1157,9 @@ Error LTO::runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache,
ThinLTO.Backend(Conf, ThinLTO.CombinedIndex, ModuleToDefinedGVSummaries,
AddStream, Cache);
- // Task numbers start at ParallelCodeGenParallelismLevel if an LTO
- // module is present, as tasks 0 through ParallelCodeGenParallelismLevel-1
- // are reserved for parallel code generation partitions.
- unsigned Task =
- HasRegularLTO ? RegularLTO.ParallelCodeGenParallelismLevel : 0;
+ // Tasks 0 through ParallelCodeGenParallelismLevel-1 are reserved for combined
+ // module and parallel code generation partitions.
+ unsigned Task = RegularLTO.ParallelCodeGenParallelismLevel;
for (auto &Mod : ThinLTO.ModuleMap) {
if (Error E = BackendProc->start(Task, Mod.second, ImportLists[Mod.first],
ExportLists[Mod.first],
@@ -1113,7 +1171,7 @@ Error LTO::runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache,
return BackendProc->wait();
}
-Expected<std::unique_ptr<tool_output_file>>
+Expected<std::unique_ptr<ToolOutputFile>>
lto::setupOptimizationRemarks(LLVMContext &Context,
StringRef LTORemarksFilename,
bool LTOPassRemarksWithHotness, int Count) {
@@ -1126,7 +1184,7 @@ lto::setupOptimizationRemarks(LLVMContext &Context,
std::error_code EC;
auto DiagnosticFile =
- llvm::make_unique<tool_output_file>(Filename, EC, sys::fs::F_None);
+ llvm::make_unique<ToolOutputFile>(Filename, EC, sys::fs::F_None);
if (EC)
return errorCodeToError(EC);
Context.setDiagnosticsOutputFile(
diff --git a/lib/LTO/LTOBackend.cpp b/lib/LTO/LTOBackend.cpp
index 3f72e446cdf2..501d6284117b 100644
--- a/lib/LTO/LTOBackend.cpp
+++ b/lib/LTO/LTOBackend.cpp
@@ -131,18 +131,23 @@ createTargetMachine(Config &Conf, const Target *TheTarget, Module &M) {
Conf.CodeModel, Conf.CGOptLevel));
}
-static void runNewPMPasses(Module &Mod, TargetMachine *TM, unsigned OptLevel,
- bool IsThinLTO) {
- PassBuilder PB(TM);
+static void runNewPMPasses(Config &Conf, Module &Mod, TargetMachine *TM,
+ unsigned OptLevel, bool IsThinLTO) {
+ Optional<PGOOptions> PGOOpt;
+ if (!Conf.SampleProfile.empty())
+ PGOOpt = PGOOptions("", "", Conf.SampleProfile, false, true);
+
+ PassBuilder PB(TM, PGOOpt);
AAManager AA;
// Parse a custom AA pipeline if asked to.
- assert(PB.parseAAPipeline(AA, "default"));
+ if (!PB.parseAAPipeline(AA, "default"))
+ report_fatal_error("Error parsing default AA pipeline");
- LoopAnalysisManager LAM;
- FunctionAnalysisManager FAM;
- CGSCCAnalysisManager CGAM;
- ModuleAnalysisManager MAM;
+ LoopAnalysisManager LAM(Conf.DebugPassManager);
+ FunctionAnalysisManager FAM(Conf.DebugPassManager);
+ CGSCCAnalysisManager CGAM(Conf.DebugPassManager);
+ ModuleAnalysisManager MAM(Conf.DebugPassManager);
// Register the AA manager first so that our version is the one used.
FAM.registerPass([&] { return std::move(AA); });
@@ -154,7 +159,7 @@ static void runNewPMPasses(Module &Mod, TargetMachine *TM, unsigned OptLevel,
PB.registerLoopAnalyses(LAM);
PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
- ModulePassManager MPM;
+ ModulePassManager MPM(Conf.DebugPassManager);
// FIXME (davide): verify the input.
PassBuilder::OptimizationLevel OL;
@@ -177,9 +182,9 @@ static void runNewPMPasses(Module &Mod, TargetMachine *TM, unsigned OptLevel,
}
if (IsThinLTO)
- MPM = PB.buildThinLTODefaultPipeline(OL, false /* DebugLogging */);
+ MPM = PB.buildThinLTODefaultPipeline(OL, Conf.DebugPassManager);
else
- MPM = PB.buildLTODefaultPipeline(OL, false /* DebugLogging */);
+ MPM = PB.buildLTODefaultPipeline(OL, Conf.DebugPassManager);
MPM.run(Mod, MAM);
// FIXME (davide): verify the output.
@@ -262,7 +267,7 @@ bool opt(Config &Conf, TargetMachine *TM, unsigned Task, Module &Mod,
runNewPMCustomPasses(Mod, TM, Conf.OptPipeline, Conf.AAPipeline,
Conf.DisableVerify);
else if (Conf.UseNewPM)
- runNewPMPasses(Mod, TM, Conf.OptLevel, IsThinLTO);
+ runNewPMPasses(Conf, Mod, TM, Conf.OptLevel, IsThinLTO);
else
runOldPMPasses(Conf, Mod, TM, IsThinLTO, ExportSummary, ImportSummary);
return !Conf.PostOptModuleHook || Conf.PostOptModuleHook(Task, Mod);
@@ -344,7 +349,7 @@ Expected<const Target *> initAndLookupTarget(Config &C, Module &Mod) {
}
static void
-finalizeOptimizationRemarks(std::unique_ptr<tool_output_file> DiagOutputFile) {
+finalizeOptimizationRemarks(std::unique_ptr<ToolOutputFile> DiagOutputFile) {
// Make sure we flush the diagnostic remarks file in case the linker doesn't
// call the global destructors before exiting.
if (!DiagOutputFile)
diff --git a/lib/LTO/LTOCodeGenerator.cpp b/lib/LTO/LTOCodeGenerator.cpp
index 6a275560dc92..c7306df95d3d 100644
--- a/lib/LTO/LTOCodeGenerator.cpp
+++ b/lib/LTO/LTOCodeGenerator.cpp
@@ -21,7 +21,7 @@
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/CodeGen/ParallelCG.h"
-#include "llvm/CodeGen/RuntimeLibcalls.h"
+#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/Config/config.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
@@ -52,10 +52,7 @@
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetOptions.h"
-#include "llvm/Target/TargetRegisterInfo.h"
-#include "llvm/Target/TargetSubtargetInfo.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/Internalize.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
@@ -83,16 +80,6 @@ cl::opt<bool> LTODiscardValueNames(
#endif
cl::Hidden);
-cl::opt<bool> LTOStripInvalidDebugInfo(
- "lto-strip-invalid-debug-info",
- cl::desc("Strip invalid debug info metadata during LTO instead of aborting."),
-#ifdef NDEBUG
- cl::init(true),
-#else
- cl::init(false),
-#endif
- cl::Hidden);
-
cl::opt<std::string>
LTORemarksFilename("lto-pass-remarks-output",
cl::desc("Output filename for pass remarks"),
@@ -141,7 +128,6 @@ void LTOCodeGenerator::initializeLTOPasses() {
initializeMemCpyOptLegacyPassPass(R);
initializeDCELegacyPassPass(R);
initializeCFGSimplifyPassPass(R);
- initializeLateCFGSimplifyPassPass(R);
}
void LTOCodeGenerator::setAsmUndefinedRefs(LTOModule *Mod) {
@@ -225,10 +211,10 @@ bool LTOCodeGenerator::writeMergedModules(StringRef Path) {
// create output file
std::error_code EC;
- tool_output_file Out(Path, EC, sys::fs::F_None);
+ ToolOutputFile Out(Path, EC, sys::fs::F_None);
if (EC) {
std::string ErrMsg = "could not open bitcode file for writing: ";
- ErrMsg += Path;
+ ErrMsg += Path.str() + ": " + EC.message();
emitError(ErrMsg);
return false;
}
@@ -239,7 +225,7 @@ bool LTOCodeGenerator::writeMergedModules(StringRef Path) {
if (Out.os().has_error()) {
std::string ErrMsg = "could not write bitcode file: ";
- ErrMsg += Path;
+ ErrMsg += Path.str() + ": " + Out.os().error().message();
emitError(ErrMsg);
Out.os().clear_error();
return false;
@@ -265,12 +251,14 @@ bool LTOCodeGenerator::compileOptimizedToFile(const char **Name) {
}
// generate object file
- tool_output_file objFile(Filename, FD);
+ ToolOutputFile objFile(Filename, FD);
bool genResult = compileOptimized(&objFile.os());
objFile.os().close();
if (objFile.os().has_error()) {
- emitError((Twine("could not write object file: ") + Filename).str());
+ emitError((Twine("could not write object file: ") + Filename + ": " +
+ objFile.os().error().message())
+ .str());
objFile.os().clear_error();
sys::fs::remove(Twine(Filename));
return false;
@@ -368,9 +356,8 @@ bool LTOCodeGenerator::determineTarget() {
}
std::unique_ptr<TargetMachine> LTOCodeGenerator::createTargetMachine() {
- return std::unique_ptr<TargetMachine>(
- MArch->createTargetMachine(TripleStr, MCpu, FeatureStr, Options,
- RelocModel, CodeModel::Default, CGOptLevel));
+ return std::unique_ptr<TargetMachine>(MArch->createTargetMachine(
+ TripleStr, MCpu, FeatureStr, Options, RelocModel, None, CGOptLevel));
}
// If a linkonce global is present in the MustPreserveSymbols, we need to make
@@ -482,11 +469,9 @@ void LTOCodeGenerator::restoreLinkageForExternals() {
GV.setLinkage(I->second);
};
- std::for_each(MergedModule->begin(), MergedModule->end(), externalize);
- std::for_each(MergedModule->global_begin(), MergedModule->global_end(),
- externalize);
- std::for_each(MergedModule->alias_begin(), MergedModule->alias_end(),
- externalize);
+ llvm::for_each(MergedModule->functions(), externalize);
+ llvm::for_each(MergedModule->globals(), externalize);
+ llvm::for_each(MergedModule->aliases(), externalize);
}
void LTOCodeGenerator::verifyMergedModuleOnce() {
@@ -496,8 +481,7 @@ void LTOCodeGenerator::verifyMergedModuleOnce() {
HasVerifiedInput = true;
bool BrokenDebugInfo = false;
- if (verifyModule(*MergedModule, &dbgs(),
- LTOStripInvalidDebugInfo ? &BrokenDebugInfo : nullptr))
+ if (verifyModule(*MergedModule, &dbgs(), &BrokenDebugInfo))
report_fatal_error("Broken module found, compilation aborted!");
if (BrokenDebugInfo) {
emitWarning("Invalid debug info found, debug info will be stripped");
@@ -623,12 +607,8 @@ void LTOCodeGenerator::parseCodeGenDebugOptions() {
}
}
-void LTOCodeGenerator::DiagnosticHandler(const DiagnosticInfo &DI,
- void *Context) {
- ((LTOCodeGenerator *)Context)->DiagnosticHandler2(DI);
-}
-void LTOCodeGenerator::DiagnosticHandler2(const DiagnosticInfo &DI) {
+void LTOCodeGenerator::DiagnosticHandler(const DiagnosticInfo &DI) {
// Map the LLVM internal diagnostic severity to the LTO diagnostic severity.
lto_codegen_diagnostic_severity_t Severity;
switch (DI.getSeverity()) {
@@ -658,17 +638,29 @@ void LTOCodeGenerator::DiagnosticHandler2(const DiagnosticInfo &DI) {
(*DiagHandler)(Severity, MsgStorage.c_str(), DiagContext);
}
+namespace {
+struct LTODiagnosticHandler : public DiagnosticHandler {
+ LTOCodeGenerator *CodeGenerator;
+ LTODiagnosticHandler(LTOCodeGenerator *CodeGenPtr)
+ : CodeGenerator(CodeGenPtr) {}
+ bool handleDiagnostics(const DiagnosticInfo &DI) override {
+ CodeGenerator->DiagnosticHandler(DI);
+ return true;
+ }
+};
+}
+
void
LTOCodeGenerator::setDiagnosticHandler(lto_diagnostic_handler_t DiagHandler,
void *Ctxt) {
this->DiagHandler = DiagHandler;
this->DiagContext = Ctxt;
if (!DiagHandler)
- return Context.setDiagnosticHandler(nullptr, nullptr);
+ return Context.setDiagnosticHandler(nullptr);
// Register the LTOCodeGenerator stub in the LLVMContext to forward the
// diagnostic to the external DiagHandler.
- Context.setDiagnosticHandler(LTOCodeGenerator::DiagnosticHandler, this,
- /* RespectFilters */ true);
+ Context.setDiagnosticHandler(llvm::make_unique<LTODiagnosticHandler>(this),
+ true);
}
namespace {
diff --git a/lib/LTO/LTOModule.cpp b/lib/LTO/LTOModule.cpp
index 3cc8b7d0e770..51b4f225939f 100644
--- a/lib/LTO/LTOModule.cpp
+++ b/lib/LTO/LTOModule.cpp
@@ -16,17 +16,16 @@
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/ObjectUtils.h"
#include "llvm/Bitcode/BitcodeReader.h"
+#include "llvm/CodeGen/TargetLoweringObjectFile.h"
+#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/Constants.h"
-#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
-#include "llvm/MC/MCParser/MCTargetAsmParser.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
@@ -40,10 +39,6 @@
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
-#include "llvm/Target/TargetLowering.h"
-#include "llvm/Target/TargetLoweringObjectFile.h"
-#include "llvm/Target/TargetRegisterInfo.h"
-#include "llvm/Target/TargetSubtargetInfo.h"
#include "llvm/Transforms/Utils/GlobalStatus.h"
#include <system_error>
using namespace llvm;
@@ -60,9 +55,13 @@ LTOModule::~LTOModule() {}
/// isBitcodeFile - Returns 'true' if the file (or memory contents) is LLVM
/// bitcode.
bool LTOModule::isBitcodeFile(const void *Mem, size_t Length) {
- ErrorOr<MemoryBufferRef> BCData = IRObjectFile::findBitcodeInMemBuffer(
+ Expected<MemoryBufferRef> BCData = IRObjectFile::findBitcodeInMemBuffer(
MemoryBufferRef(StringRef((const char *)Mem, Length), "<mem>"));
- return bool(BCData);
+ if (!BCData) {
+ consumeError(BCData.takeError());
+ return false;
+ }
+ return true;
}
bool LTOModule::isBitcodeFile(StringRef Path) {
@@ -71,9 +70,13 @@ bool LTOModule::isBitcodeFile(StringRef Path) {
if (!BufferOrErr)
return false;
- ErrorOr<MemoryBufferRef> BCData = IRObjectFile::findBitcodeInMemBuffer(
+ Expected<MemoryBufferRef> BCData = IRObjectFile::findBitcodeInMemBuffer(
BufferOrErr.get()->getMemBufferRef());
- return bool(BCData);
+ if (!BCData) {
+ consumeError(BCData.takeError());
+ return false;
+ }
+ return true;
}
bool LTOModule::isThinLTO() {
@@ -87,10 +90,12 @@ bool LTOModule::isThinLTO() {
bool LTOModule::isBitcodeForTarget(MemoryBuffer *Buffer,
StringRef TriplePrefix) {
- ErrorOr<MemoryBufferRef> BCOrErr =
+ Expected<MemoryBufferRef> BCOrErr =
IRObjectFile::findBitcodeInMemBuffer(Buffer->getMemBufferRef());
- if (!BCOrErr)
+ if (!BCOrErr) {
+ consumeError(BCOrErr.takeError());
return false;
+ }
LLVMContext Context;
ErrorOr<std::string> TripleOrErr =
expectedToErrorOrAndEmitErrors(Context, getBitcodeTargetTriple(*BCOrErr));
@@ -100,10 +105,12 @@ bool LTOModule::isBitcodeForTarget(MemoryBuffer *Buffer,
}
std::string LTOModule::getProducerString(MemoryBuffer *Buffer) {
- ErrorOr<MemoryBufferRef> BCOrErr =
+ Expected<MemoryBufferRef> BCOrErr =
IRObjectFile::findBitcodeInMemBuffer(Buffer->getMemBufferRef());
- if (!BCOrErr)
+ if (!BCOrErr) {
+ consumeError(BCOrErr.takeError());
return "";
+ }
LLVMContext Context;
ErrorOr<std::string> ProducerOrErr = expectedToErrorOrAndEmitErrors(
Context, getBitcodeProducerString(*BCOrErr));
@@ -174,11 +181,11 @@ LTOModule::createInLocalContext(std::unique_ptr<LLVMContext> Context,
static ErrorOr<std::unique_ptr<Module>>
parseBitcodeFileImpl(MemoryBufferRef Buffer, LLVMContext &Context,
bool ShouldBeLazy) {
-
// Find the buffer.
- ErrorOr<MemoryBufferRef> MBOrErr =
+ Expected<MemoryBufferRef> MBOrErr =
IRObjectFile::findBitcodeInMemBuffer(Buffer);
- if (std::error_code EC = MBOrErr.getError()) {
+ if (Error E = MBOrErr.takeError()) {
+ std::error_code EC = errorToErrorCode(std::move(E));
Context.emitError(EC.message());
return EC;
}
diff --git a/lib/LTO/ThinLTOCodeGenerator.cpp b/lib/LTO/ThinLTOCodeGenerator.cpp
index 1efd481b246c..c8b3892375f6 100644
--- a/lib/LTO/ThinLTOCodeGenerator.cpp
+++ b/lib/LTO/ThinLTOCodeGenerator.cpp
@@ -63,7 +63,6 @@ namespace llvm {
extern cl::opt<bool> LTODiscardValueNames;
extern cl::opt<std::string> LTORemarksFilename;
extern cl::opt<bool> LTOPassRemarksWithHotness;
-extern cl::opt<bool> LTOStripInvalidDebugInfo;
}
namespace {
@@ -158,8 +157,7 @@ public:
/// Verify the module and strip broken debug info.
static void verifyLoadedModule(Module &TheModule) {
bool BrokenDebugInfo = false;
- if (verifyModule(TheModule, &dbgs(),
- LTOStripInvalidDebugInfo ? &BrokenDebugInfo : nullptr))
+ if (verifyModule(TheModule, &dbgs(), &BrokenDebugInfo))
report_fatal_error("Broken module found, compilation aborted!");
if (BrokenDebugInfo) {
TheModule.getContext().diagnose(ThinLTODiagnosticInfo(
@@ -583,9 +581,9 @@ std::unique_ptr<TargetMachine> TargetMachineBuilder::create() const {
Features.getDefaultSubtargetFeatures(TheTriple);
std::string FeatureStr = Features.getString();
- return std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine(
- TheTriple.str(), MCpu, FeatureStr, Options, RelocModel,
- CodeModel::Default, CGOptLevel));
+ return std::unique_ptr<TargetMachine>(
+ TheTarget->createTargetMachine(TheTriple.str(), MCpu, FeatureStr, Options,
+ RelocModel, None, CGOptLevel));
}
/**
diff --git a/lib/LTO/UpdateCompilerUsed.cpp b/lib/LTO/UpdateCompilerUsed.cpp
index 5165cc965038..c982a5b0e5aa 100644
--- a/lib/LTO/UpdateCompilerUsed.cpp
+++ b/lib/LTO/UpdateCompilerUsed.cpp
@@ -13,11 +13,10 @@
#include "llvm/LTO/legacy/UpdateCompilerUsed.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/CodeGen/TargetLowering.h"
+#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Mangler.h"
-#include "llvm/Target/TargetLowering.h"
-#include "llvm/Target/TargetSubtargetInfo.h"
-#include "llvm/Transforms/IPO/Internalize.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
using namespace llvm;