aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/LTO
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/LTO')
-rw-r--r--contrib/llvm/lib/LTO/Caching.cpp38
-rw-r--r--contrib/llvm/lib/LTO/LTO.cpp158
-rw-r--r--contrib/llvm/lib/LTO/LTOBackend.cpp119
-rw-r--r--contrib/llvm/lib/LTO/LTOCodeGenerator.cpp2
-rw-r--r--contrib/llvm/lib/LTO/LTOModule.cpp27
-rw-r--r--contrib/llvm/lib/LTO/ThinLTOCodeGenerator.cpp150
6 files changed, 330 insertions, 164 deletions
diff --git a/contrib/llvm/lib/LTO/Caching.cpp b/contrib/llvm/lib/LTO/Caching.cpp
index dd47eb584b7f..089e77e742eb 100644
--- a/contrib/llvm/lib/LTO/Caching.cpp
+++ b/contrib/llvm/lib/LTO/Caching.cpp
@@ -19,6 +19,12 @@
#include "llvm/Support/Process.h"
#include "llvm/Support/raw_ostream.h"
+#if !defined(_MSC_VER) && !defined(__MINGW32__)
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+
using namespace llvm;
using namespace llvm::lto;
@@ -33,16 +39,32 @@ Expected<NativeObjectCache> lto::localCache(StringRef CacheDirectoryPath,
SmallString<64> EntryPath;
sys::path::append(EntryPath, CacheDirectoryPath, "llvmcache-" + Key);
// First, see if we have a cache hit.
- ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =
- MemoryBuffer::getFile(EntryPath);
- if (MBOrErr) {
- AddBuffer(Task, std::move(*MBOrErr), EntryPath);
- return AddStreamFn();
+ int FD;
+ SmallString<64> ResultPath;
+ std::error_code EC = sys::fs::openFileForRead(
+ Twine(EntryPath), FD, sys::fs::OF_UpdateAtime, &ResultPath);
+ if (!EC) {
+ ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =
+ MemoryBuffer::getOpenFile(FD, EntryPath,
+ /*FileSize*/ -1,
+ /*RequiresNullTerminator*/ false);
+ close(FD);
+ if (MBOrErr) {
+ AddBuffer(Task, std::move(*MBOrErr));
+ return AddStreamFn();
+ }
+ EC = MBOrErr.getError();
}
- if (MBOrErr.getError() != errc::no_such_file_or_directory)
+ // On Windows we can fail to open a cache file with a permission denied
+ // error. This generally means that another process has requested to delete
+ // the file while it is still open, but it could also mean that another
+ // process has opened the file without the sharing permissions we need.
+ // Since the file is probably being deleted we handle it in the same way as
+ // if the file did not exist at all.
+ if (EC != errc::no_such_file_or_directory && EC != errc::permission_denied)
report_fatal_error(Twine("Failed to open cache file ") + EntryPath +
- ": " + MBOrErr.getError().message() + "\n");
+ ": " + EC.message() + "\n");
// This native object stream is responsible for commiting the resulting
// file to the cache and calling AddBuffer to add it to the link.
@@ -103,7 +125,7 @@ Expected<NativeObjectCache> lto::localCache(StringRef CacheDirectoryPath,
TempFile.TmpName + " to " + EntryPath + ": " +
toString(std::move(E)) + "\n");
- AddBuffer(Task, std::move(*MBOrErr), EntryPath);
+ AddBuffer(Task, std::move(*MBOrErr));
}
};
diff --git a/contrib/llvm/lib/LTO/LTO.cpp b/contrib/llvm/lib/LTO/LTO.cpp
index 64e5186255bd..68d210cb7d73 100644
--- a/contrib/llvm/lib/LTO/LTO.cpp
+++ b/contrib/llvm/lib/LTO/LTO.cpp
@@ -12,11 +12,13 @@
//===----------------------------------------------------------------------===//
#include "llvm/LTO/LTO.h"
+#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/CodeGen/Analysis.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/IR/AutoUpgrade.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/LegacyPassManager.h"
@@ -50,6 +52,10 @@ using namespace object;
#define DEBUG_TYPE "lto"
+static cl::opt<bool>
+ DumpThinCGSCCs("dump-thin-cg-sccs", cl::init(false), cl::Hidden,
+ cl::desc("Dump the SCCs in the ThinLTO index's callgraph"));
+
// The values are (type identifier, summary) pairs.
typedef DenseMap<
GlobalValue::GUID,
@@ -132,6 +138,7 @@ static void computeCacheKey(
AddString(Conf.AAPipeline);
AddString(Conf.OverrideTriple);
AddString(Conf.DefaultTriple);
+ AddString(Conf.DwoDir);
// Include the hash for the current module
auto ModHash = Index.getModuleHash(ModuleID);
@@ -149,7 +156,7 @@ static void computeCacheKey(
AddUint64(Entry.second.size());
for (auto &Fn : Entry.second)
- AddUint64(Fn.first);
+ AddUint64(Fn);
}
// Include the hash for the resolved ODR.
@@ -177,8 +184,11 @@ static void computeCacheKey(
auto AddUsedThings = [&](GlobalValueSummary *GS) {
if (!GS) return;
- for (const ValueInfo &VI : GS->refs())
+ AddUnsigned(GS->isLive());
+ for (const ValueInfo &VI : GS->refs()) {
+ AddUnsigned(VI.isDSOLocal());
AddUsedCfiGlobal(VI.getGUID());
+ }
if (auto *FS = dyn_cast<FunctionSummary>(GS)) {
for (auto &TT : FS->type_tests())
UsedTypeIds.insert(TT);
@@ -190,8 +200,10 @@ static void computeCacheKey(
UsedTypeIds.insert(TT.VFunc.GUID);
for (auto &TT : FS->type_checked_load_const_vcalls())
UsedTypeIds.insert(TT.VFunc.GUID);
- for (auto &ET : FS->calls())
+ for (auto &ET : FS->calls()) {
+ AddUnsigned(ET.first.isDSOLocal());
AddUsedCfiGlobal(ET.first.getGUID());
+ }
}
};
@@ -209,7 +221,7 @@ static void computeCacheKey(
// so we need to collect their used resolutions as well.
for (auto &ImpM : ImportList)
for (auto &ImpF : ImpM.second)
- AddUsedThings(Index.findSummaryInModule(ImpF.first, ImpM.first()));
+ AddUsedThings(Index.findSummaryInModule(ImpF, ImpM.first()));
auto AddTypeIdSummary = [&](StringRef TId, const TypeIdSummary &S) {
AddString(TId);
@@ -388,7 +400,8 @@ LTO::RegularLTOState::RegularLTOState(unsigned ParallelCodeGenParallelismLevel,
Ctx(Conf), CombinedModule(llvm::make_unique<Module>("ld-temp.o", Ctx)),
Mover(llvm::make_unique<IRMover>(*CombinedModule)) {}
-LTO::ThinLTOState::ThinLTOState(ThinBackend Backend) : Backend(Backend) {
+LTO::ThinLTOState::ThinLTOState(ThinBackend Backend)
+ : Backend(Backend), CombinedIndex(/*HaveGVs*/ false) {
if (!Backend)
this->Backend =
createInProcessThinBackend(llvm::heavyweight_hardware_concurrency());
@@ -415,11 +428,27 @@ void LTO::addModuleToGlobalRes(ArrayRef<InputFile::Symbol> Syms,
assert(ResI != ResE);
SymbolResolution Res = *ResI++;
- auto &GlobalRes = GlobalResolutions[Sym.getName()];
+ StringRef Name = Sym.getName();
+ Triple TT(RegularLTO.CombinedModule->getTargetTriple());
+ // Strip the __imp_ prefix from COFF dllimport symbols (similar to the
+ // way they are handled by lld), otherwise we can end up with two
+ // global resolutions (one with and one for a copy of the symbol without).
+ if (TT.isOSBinFormatCOFF() && Name.startswith("__imp_"))
+ Name = Name.substr(strlen("__imp_"));
+ auto &GlobalRes = GlobalResolutions[Name];
GlobalRes.UnnamedAddr &= Sym.isUnnamedAddr();
if (Res.Prevailing) {
- assert(GlobalRes.IRName.empty() &&
+ assert(!GlobalRes.Prevailing &&
"Multiple prevailing defs are not allowed");
+ GlobalRes.Prevailing = true;
+ GlobalRes.IRName = Sym.getIRName();
+ } else if (!GlobalRes.Prevailing && GlobalRes.IRName.empty()) {
+ // Sometimes it can be two copies of symbol in a module and prevailing
+ // symbol can have no IR name. That might happen if symbol is defined in
+ // module level inline asm block. In case we have multiple modules with
+ // the same symbol we want to use IR name of the prevailing symbol.
+ // Otherwise, if we haven't seen a prevailing symbol, set the name so that
+ // we can later use it to check if there is any prevailing copy in IR.
GlobalRes.IRName = Sym.getIRName();
}
@@ -639,7 +668,8 @@ LTO::addRegularLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
}
// Set the 'local' flag based on the linker resolution for this symbol.
- GV->setDSOLocal(Res.FinalDefinitionInLinkageUnit);
+ if (Res.FinalDefinitionInLinkageUnit)
+ GV->setDSOLocal(true);
}
// 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
@@ -744,20 +774,52 @@ unsigned LTO::getMaxTasks() const {
Error LTO::run(AddStreamFn AddStream, NativeObjectCache Cache) {
// Compute "dead" symbols, we don't want to import/export these!
DenseSet<GlobalValue::GUID> GUIDPreservedSymbols;
+ DenseMap<GlobalValue::GUID, PrevailingType> GUIDPrevailingResolutions;
for (auto &Res : GlobalResolutions) {
- 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())
+ // Normally resolution have IR name of symbol. We can do nothing here
+ // otherwise. See comments in GlobalResolution struct for more details.
+ if (Res.second.IRName.empty())
+ continue;
+
+ GlobalValue::GUID GUID = GlobalValue::getGUID(
+ GlobalValue::dropLLVMManglingEscape(Res.second.IRName));
+
+ if (Res.second.VisibleOutsideSummary && Res.second.Prevailing)
GUIDPreservedSymbols.insert(GlobalValue::getGUID(
GlobalValue::dropLLVMManglingEscape(Res.second.IRName)));
+
+ GUIDPrevailingResolutions[GUID] =
+ Res.second.Prevailing ? PrevailingType::Yes : PrevailingType::No;
+ }
+
+ auto isPrevailing = [&](GlobalValue::GUID G) {
+ auto It = GUIDPrevailingResolutions.find(G);
+ if (It == GUIDPrevailingResolutions.end())
+ return PrevailingType::Unknown;
+ return It->second;
+ };
+ computeDeadSymbols(ThinLTO.CombinedIndex, GUIDPreservedSymbols, isPrevailing);
+
+ // Setup output file to emit statistics.
+ std::unique_ptr<ToolOutputFile> StatsFile = nullptr;
+ if (!Conf.StatsFile.empty()) {
+ EnableStatistics(false);
+ std::error_code EC;
+ StatsFile =
+ llvm::make_unique<ToolOutputFile>(Conf.StatsFile, EC, sys::fs::F_None);
+ if (EC)
+ return errorCodeToError(EC);
+ StatsFile->keep();
}
- computeDeadSymbols(ThinLTO.CombinedIndex, GUIDPreservedSymbols);
+ Error Result = runRegularLTO(AddStream);
+ if (!Result)
+ Result = runThinLTO(AddStream, Cache);
+
+ if (StatsFile)
+ PrintStatisticsJSON(StatsFile->os());
- if (auto E = runRegularLTO(AddStream))
- return E;
- return runThinLTO(AddStream, Cache);
+ return Result;
}
Error LTO::runRegularLTO(AddStreamFn AddStream) {
@@ -801,7 +863,7 @@ Error LTO::runRegularLTO(AddStreamFn AddStream) {
if (!Conf.CodeGenOnly) {
for (const auto &R : GlobalResolutions) {
- if (R.second.IRName.empty())
+ if (!R.second.isPrevailingIRSymbol())
continue;
if (R.second.Partition != 0 &&
R.second.Partition != GlobalResolution::External)
@@ -810,7 +872,8 @@ Error LTO::runRegularLTO(AddStreamFn AddStream) {
GlobalValue *GV =
RegularLTO.CombinedModule->getNamedValue(R.second.IRName);
// Ignore symbols defined in other partitions.
- if (!GV || GV->hasLocalLinkage())
+ // Also skip declarations, which are not allowed to have internal linkage.
+ if (!GV || GV->hasLocalLinkage() || GV->isDeclaration())
continue;
GV->setUnnamedAddr(R.second.UnnamedAddr ? GlobalValue::UnnamedAddr::Global
: GlobalValue::UnnamedAddr::None);
@@ -1003,20 +1066,19 @@ namespace {
class WriteIndexesThinBackend : public ThinBackendProc {
std::string OldPrefix, NewPrefix;
bool ShouldEmitImportsFiles;
-
- std::string LinkedObjectsFileName;
- std::unique_ptr<llvm::raw_fd_ostream> LinkedObjectsFile;
+ raw_fd_ostream *LinkedObjectsFile;
+ lto::IndexWriteCallback OnWrite;
public:
WriteIndexesThinBackend(
Config &Conf, ModuleSummaryIndex &CombinedIndex,
const StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries,
std::string OldPrefix, std::string NewPrefix, bool ShouldEmitImportsFiles,
- std::string LinkedObjectsFileName)
+ raw_fd_ostream *LinkedObjectsFile, lto::IndexWriteCallback OnWrite)
: ThinBackendProc(Conf, CombinedIndex, ModuleToDefinedGVSummaries),
OldPrefix(OldPrefix), NewPrefix(NewPrefix),
ShouldEmitImportsFiles(ShouldEmitImportsFiles),
- LinkedObjectsFileName(LinkedObjectsFileName) {}
+ LinkedObjectsFile(LinkedObjectsFile), OnWrite(OnWrite) {}
Error start(
unsigned Task, BitcodeModule BM,
@@ -1028,30 +1090,29 @@ public:
std::string NewModulePath =
getThinLTOOutputFile(ModulePath, OldPrefix, NewPrefix);
- std::error_code EC;
- if (!LinkedObjectsFileName.empty()) {
- if (!LinkedObjectsFile) {
- LinkedObjectsFile = llvm::make_unique<raw_fd_ostream>(
- LinkedObjectsFileName, EC, sys::fs::OpenFlags::F_None);
- if (EC)
- return errorCodeToError(EC);
- }
+ if (LinkedObjectsFile)
*LinkedObjectsFile << NewModulePath << '\n';
- }
std::map<std::string, GVSummaryMapTy> ModuleToSummariesForIndex;
gatherImportedSummariesForModule(ModulePath, ModuleToDefinedGVSummaries,
ImportList, ModuleToSummariesForIndex);
+ std::error_code EC;
raw_fd_ostream OS(NewModulePath + ".thinlto.bc", EC,
sys::fs::OpenFlags::F_None);
if (EC)
return errorCodeToError(EC);
WriteIndexToFile(CombinedIndex, OS, &ModuleToSummariesForIndex);
- if (ShouldEmitImportsFiles)
- return errorCodeToError(
- EmitImportsFiles(ModulePath, NewModulePath + ".imports", ImportList));
+ if (ShouldEmitImportsFiles) {
+ EC = EmitImportsFiles(ModulePath, NewModulePath + ".imports",
+ ModuleToSummariesForIndex);
+ if (EC)
+ return errorCodeToError(EC);
+ }
+
+ if (OnWrite)
+ OnWrite(ModulePath);
return Error::success();
}
@@ -1059,16 +1120,15 @@ public:
};
} // end anonymous namespace
-ThinBackend lto::createWriteIndexesThinBackend(std::string OldPrefix,
- std::string NewPrefix,
- bool ShouldEmitImportsFiles,
- std::string LinkedObjectsFile) {
+ThinBackend lto::createWriteIndexesThinBackend(
+ std::string OldPrefix, std::string NewPrefix, bool ShouldEmitImportsFiles,
+ raw_fd_ostream *LinkedObjectsFile, IndexWriteCallback OnWrite) {
return [=](Config &Conf, ModuleSummaryIndex &CombinedIndex,
const StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries,
AddStreamFn AddStream, NativeObjectCache Cache) {
return llvm::make_unique<WriteIndexesThinBackend>(
Conf, CombinedIndex, ModuleToDefinedGVSummaries, OldPrefix, NewPrefix,
- ShouldEmitImportsFiles, LinkedObjectsFile);
+ ShouldEmitImportsFiles, LinkedObjectsFile, OnWrite);
};
}
@@ -1102,6 +1162,9 @@ Error LTO::runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache) {
ThinLTO.ModuleMap.size());
StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;
+ if (DumpThinCGSCCs)
+ ThinLTO.CombinedIndex.dumpSCCs(outs());
+
if (Conf.OptLevel > 0)
ComputeCrossModuleImport(ThinLTO.CombinedIndex, ModuleToDefinedGVSummaries,
ImportLists, ExportLists);
@@ -1112,13 +1175,10 @@ Error LTO::runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache) {
// 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())
+ // If the symbol does not have external references or it is not prevailing,
+ // then not need to mark it as exported from a ThinLTO partition.
+ if (Res.second.Partition != GlobalResolution::External ||
+ !Res.second.isPrevailingIRSymbol())
continue;
auto GUID = GlobalValue::getGUID(
GlobalValue::dropLLVMManglingEscape(Res.second.IRName));
@@ -1175,6 +1235,8 @@ Expected<std::unique_ptr<ToolOutputFile>>
lto::setupOptimizationRemarks(LLVMContext &Context,
StringRef LTORemarksFilename,
bool LTOPassRemarksWithHotness, int Count) {
+ if (LTOPassRemarksWithHotness)
+ Context.setDiagnosticsHotnessRequested(true);
if (LTORemarksFilename.empty())
return nullptr;
@@ -1189,8 +1251,6 @@ lto::setupOptimizationRemarks(LLVMContext &Context,
return errorCodeToError(EC);
Context.setDiagnosticsOutputFile(
llvm::make_unique<yaml::Output>(DiagnosticFile->os()));
- if (LTOPassRemarksWithHotness)
- Context.setDiagnosticsHotnessRequested(true);
DiagnosticFile->keep();
return std::move(DiagnosticFile);
}
diff --git a/contrib/llvm/lib/LTO/LTOBackend.cpp b/contrib/llvm/lib/LTO/LTOBackend.cpp
index 501d6284117b..eadbb410bd5a 100644
--- a/contrib/llvm/lib/LTO/LTOBackend.cpp
+++ b/contrib/llvm/lib/LTO/LTOBackend.cpp
@@ -30,6 +30,10 @@
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Program.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/ThreadPool.h"
#include "llvm/Target/TargetMachine.h"
@@ -72,17 +76,19 @@ Error Config::addSaveTemps(std::string OutputFileName,
// user hasn't requested using the input module's path, emit to a file
// named from the provided OutputFileName with the Task ID appended.
if (M.getModuleIdentifier() == "ld-temp.o" || !UseInputModulePath) {
- PathPrefix = OutputFileName + utostr(Task);
+ PathPrefix = OutputFileName;
+ if (Task != (unsigned)-1)
+ PathPrefix += utostr(Task) + ".";
} else
- PathPrefix = M.getModuleIdentifier();
- std::string Path = PathPrefix + "." + PathSuffix + ".bc";
+ PathPrefix = M.getModuleIdentifier() + ".";
+ std::string Path = PathPrefix + PathSuffix + ".bc";
std::error_code EC;
raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::F_None);
// Because -save-temps is a debugging feature, we report the error
// directly and exit.
if (EC)
reportOpenError(Path, EC.message());
- WriteBitcodeToFile(&M, OS, /*ShouldPreserveUseListOrder=*/false);
+ WriteBitcodeToFile(M, OS, /*ShouldPreserveUseListOrder=*/false);
return true;
};
};
@@ -103,6 +109,12 @@ Error Config::addSaveTemps(std::string OutputFileName,
if (EC)
reportOpenError(Path, EC.message());
WriteIndexToFile(Index, OS);
+
+ Path = OutputFileName + "index.dot";
+ raw_fd_ostream OSDot(Path, EC, sys::fs::OpenFlags::F_None);
+ if (EC)
+ reportOpenError(Path, EC.message());
+ Index.exportToDot(OSDot);
return true;
};
@@ -132,7 +144,9 @@ createTargetMachine(Config &Conf, const Target *TheTarget, Module &M) {
}
static void runNewPMPasses(Config &Conf, Module &Mod, TargetMachine *TM,
- unsigned OptLevel, bool IsThinLTO) {
+ unsigned OptLevel, bool IsThinLTO,
+ ModuleSummaryIndex *ExportSummary,
+ const ModuleSummaryIndex *ImportSummary) {
Optional<PGOOptions> PGOOpt;
if (!Conf.SampleProfile.empty())
PGOOpt = PGOOptions("", "", Conf.SampleProfile, false, true);
@@ -182,9 +196,10 @@ static void runNewPMPasses(Config &Conf, Module &Mod, TargetMachine *TM,
}
if (IsThinLTO)
- MPM = PB.buildThinLTODefaultPipeline(OL, Conf.DebugPassManager);
+ MPM = PB.buildThinLTODefaultPipeline(OL, Conf.DebugPassManager,
+ ImportSummary);
else
- MPM = PB.buildLTODefaultPipeline(OL, Conf.DebugPassManager);
+ MPM = PB.buildLTODefaultPipeline(OL, Conf.DebugPassManager, ExportSummary);
MPM.run(Mod, MAM);
// FIXME (davide): verify the output.
@@ -267,7 +282,8 @@ bool opt(Config &Conf, TargetMachine *TM, unsigned Task, Module &Mod,
runNewPMCustomPasses(Mod, TM, Conf.OptPipeline, Conf.AAPipeline,
Conf.DisableVerify);
else if (Conf.UseNewPM)
- runNewPMPasses(Conf, Mod, TM, Conf.OptLevel, IsThinLTO);
+ runNewPMPasses(Conf, Mod, TM, Conf.OptLevel, IsThinLTO, ExportSummary,
+ ImportSummary);
else
runOldPMPasses(Conf, Mod, TM, IsThinLTO, ExportSummary, ImportSummary);
return !Conf.PostOptModuleHook || Conf.PostOptModuleHook(Task, Mod);
@@ -278,11 +294,36 @@ void codegen(Config &Conf, TargetMachine *TM, AddStreamFn AddStream,
if (Conf.PreCodeGenModuleHook && !Conf.PreCodeGenModuleHook(Task, Mod))
return;
+ std::unique_ptr<ToolOutputFile> DwoOut;
+ SmallString<1024> DwoFile(Conf.DwoPath);
+ if (!Conf.DwoDir.empty()) {
+ std::error_code EC;
+ if (auto EC = llvm::sys::fs::create_directories(Conf.DwoDir))
+ report_fatal_error("Failed to create directory " + Conf.DwoDir + ": " +
+ EC.message());
+
+ DwoFile = Conf.DwoDir;
+ sys::path::append(DwoFile, std::to_string(Task) + ".dwo");
+ }
+
+ if (!DwoFile.empty()) {
+ std::error_code EC;
+ TM->Options.MCOptions.SplitDwarfFile = DwoFile.str().str();
+ DwoOut = llvm::make_unique<ToolOutputFile>(DwoFile, EC, sys::fs::F_None);
+ if (EC)
+ report_fatal_error("Failed to open " + DwoFile + ": " + EC.message());
+ }
+
auto Stream = AddStream(Task);
legacy::PassManager CodeGenPasses;
- if (TM->addPassesToEmitFile(CodeGenPasses, *Stream->OS, Conf.CGFileType))
+ if (TM->addPassesToEmitFile(CodeGenPasses, *Stream->OS,
+ DwoOut ? &DwoOut->os() : nullptr,
+ Conf.CGFileType))
report_fatal_error("Failed to setup codegen");
CodeGenPasses.run(Mod);
+
+ if (DwoOut)
+ DwoOut->keep();
}
void splitCodeGen(Config &C, TargetMachine *TM, AddStreamFn AddStream,
@@ -303,7 +344,7 @@ void splitCodeGen(Config &C, TargetMachine *TM, AddStreamFn AddStream,
// FIXME: Provide a more direct way to do this in LLVM.
SmallString<0> BC;
raw_svector_ostream BCOS(BC);
- WriteBitcodeToFile(MPart.get(), BCOS);
+ WriteBitcodeToFile(*MPart, BCOS);
// Enqueue the task
CodegenThreadPool.async(
@@ -348,14 +389,15 @@ Expected<const Target *> initAndLookupTarget(Config &C, Module &Mod) {
}
-static void
+static Error
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)
- return;
+ return Error::success();
DiagOutputFile->keep();
DiagOutputFile->os().flush();
+ return Error::success();
}
Error lto::backend(Config &C, AddStreamFn AddStream,
@@ -377,10 +419,8 @@ Error lto::backend(Config &C, AddStreamFn AddStream,
if (!C.CodeGenOnly) {
if (!opt(C, TM.get(), 0, *Mod, /*IsThinLTO=*/false,
- /*ExportSummary=*/&CombinedIndex, /*ImportSummary=*/nullptr)) {
- finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
- return Error::success();
- }
+ /*ExportSummary=*/&CombinedIndex, /*ImportSummary=*/nullptr))
+ return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
}
if (ParallelCodeGenParallelismLevel == 1) {
@@ -389,8 +429,28 @@ Error lto::backend(Config &C, AddStreamFn AddStream,
splitCodeGen(C, TM.get(), AddStream, ParallelCodeGenParallelismLevel,
std::move(Mod));
}
- finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
- return Error::success();
+ return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
+}
+
+static void dropDeadSymbols(Module &Mod, const GVSummaryMapTy &DefinedGlobals,
+ const ModuleSummaryIndex &Index) {
+ std::vector<GlobalValue*> DeadGVs;
+ for (auto &GV : Mod.global_values())
+ if (GlobalValueSummary *GVS = DefinedGlobals.lookup(GV.getGUID()))
+ if (!Index.isGlobalValueLive(GVS)) {
+ DeadGVs.push_back(&GV);
+ convertToDeclaration(GV);
+ }
+
+ // Now that all dead bodies have been dropped, delete the actual objects
+ // themselves when possible.
+ for (GlobalValue *GV : DeadGVs) {
+ GV->removeDeadConstantUsers();
+ // Might reference something defined in native object (i.e. dropped a
+ // non-prevailing IR def, but we need to keep the declaration).
+ if (GV->use_empty())
+ GV->eraseFromParent();
+ }
}
Error lto::thinBackend(Config &Conf, unsigned Task, AddStreamFn AddStream,
@@ -404,27 +464,36 @@ Error lto::thinBackend(Config &Conf, unsigned Task, AddStreamFn AddStream,
std::unique_ptr<TargetMachine> TM = createTargetMachine(Conf, *TOrErr, Mod);
+ // Setup optimization remarks.
+ auto DiagFileOrErr = lto::setupOptimizationRemarks(
+ Mod.getContext(), Conf.RemarksFilename, Conf.RemarksWithHotness, Task);
+ if (!DiagFileOrErr)
+ return DiagFileOrErr.takeError();
+ auto DiagnosticOutputFile = std::move(*DiagFileOrErr);
+
if (Conf.CodeGenOnly) {
codegen(Conf, TM.get(), AddStream, Task, Mod);
- return Error::success();
+ return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
}
if (Conf.PreOptModuleHook && !Conf.PreOptModuleHook(Task, Mod))
- return Error::success();
+ return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
renameModuleForThinLTO(Mod, CombinedIndex);
+ dropDeadSymbols(Mod, DefinedGlobals, CombinedIndex);
+
thinLTOResolveWeakForLinkerModule(Mod, DefinedGlobals);
if (Conf.PostPromoteModuleHook && !Conf.PostPromoteModuleHook(Task, Mod))
- return Error::success();
+ return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
if (!DefinedGlobals.empty())
thinLTOInternalizeModule(Mod, DefinedGlobals);
if (Conf.PostInternalizeModuleHook &&
!Conf.PostInternalizeModuleHook(Task, Mod))
- return Error::success();
+ return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
auto ModuleLoader = [&](StringRef Identifier) {
assert(Mod.getContext().isODRUniquingDebugTypes() &&
@@ -441,12 +510,12 @@ Error lto::thinBackend(Config &Conf, unsigned Task, AddStreamFn AddStream,
return Err;
if (Conf.PostImportModuleHook && !Conf.PostImportModuleHook(Task, Mod))
- return Error::success();
+ return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
if (!opt(Conf, TM.get(), Task, Mod, /*IsThinLTO=*/true,
/*ExportSummary=*/nullptr, /*ImportSummary=*/&CombinedIndex))
- return Error::success();
+ return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
codegen(Conf, TM.get(), AddStream, Task, Mod);
- return Error::success();
+ return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
}
diff --git a/contrib/llvm/lib/LTO/LTOCodeGenerator.cpp b/contrib/llvm/lib/LTO/LTOCodeGenerator.cpp
index c7306df95d3d..ffe9af74cdca 100644
--- a/contrib/llvm/lib/LTO/LTOCodeGenerator.cpp
+++ b/contrib/llvm/lib/LTO/LTOCodeGenerator.cpp
@@ -220,7 +220,7 @@ bool LTOCodeGenerator::writeMergedModules(StringRef Path) {
}
// write bitcode to it
- WriteBitcodeToFile(MergedModule.get(), Out.os(), ShouldEmbedUselists);
+ WriteBitcodeToFile(*MergedModule, Out.os(), ShouldEmbedUselists);
Out.os().close();
if (Out.os().has_error()) {
diff --git a/contrib/llvm/lib/LTO/LTOModule.cpp b/contrib/llvm/lib/LTO/LTOModule.cpp
index 626d2f5dc813..20fc0943539f 100644
--- a/contrib/llvm/lib/LTO/LTOModule.cpp
+++ b/contrib/llvm/lib/LTO/LTOModule.cpp
@@ -14,9 +14,7 @@
#include "llvm/LTO/legacy/LTOModule.h"
#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/LLVMContext.h"
@@ -39,6 +37,7 @@
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Transforms/Utils/GlobalStatus.h"
#include <system_error>
using namespace llvm;
@@ -57,11 +56,7 @@ LTOModule::~LTOModule() {}
bool LTOModule::isBitcodeFile(const void *Mem, size_t Length) {
Expected<MemoryBufferRef> BCData = IRObjectFile::findBitcodeInMemBuffer(
MemoryBufferRef(StringRef((const char *)Mem, Length), "<mem>"));
- if (!BCData) {
- consumeError(BCData.takeError());
- return false;
- }
- return true;
+ return !errorToBool(BCData.takeError());
}
bool LTOModule::isBitcodeFile(StringRef Path) {
@@ -72,11 +67,7 @@ bool LTOModule::isBitcodeFile(StringRef Path) {
Expected<MemoryBufferRef> BCData = IRObjectFile::findBitcodeInMemBuffer(
BufferOrErr.get()->getMemBufferRef());
- if (!BCData) {
- consumeError(BCData.takeError());
- return false;
- }
- return true;
+ return !errorToBool(BCData.takeError());
}
bool LTOModule::isThinLTO() {
@@ -92,10 +83,8 @@ bool LTOModule::isBitcodeForTarget(MemoryBuffer *Buffer,
StringRef TriplePrefix) {
Expected<MemoryBufferRef> BCOrErr =
IRObjectFile::findBitcodeInMemBuffer(Buffer->getMemBufferRef());
- if (!BCOrErr) {
- consumeError(BCOrErr.takeError());
+ if (errorToBool(BCOrErr.takeError()))
return false;
- }
LLVMContext Context;
ErrorOr<std::string> TripleOrErr =
expectedToErrorOrAndEmitErrors(Context, getBitcodeTargetTriple(*BCOrErr));
@@ -107,10 +96,8 @@ bool LTOModule::isBitcodeForTarget(MemoryBuffer *Buffer,
std::string LTOModule::getProducerString(MemoryBuffer *Buffer) {
Expected<MemoryBufferRef> BCOrErr =
IRObjectFile::findBitcodeInMemBuffer(Buffer->getMemBufferRef());
- if (!BCOrErr) {
- consumeError(BCOrErr.takeError());
+ if (errorToBool(BCOrErr.takeError()))
return "";
- }
LLVMContext Context;
ErrorOr<std::string> ProducerOrErr = expectedToErrorOrAndEmitErrors(
Context, getBitcodeProducerString(*BCOrErr));
@@ -220,7 +207,7 @@ LTOModule::makeLTOModule(MemoryBufferRef Buffer, const TargetOptions &options,
std::string errMsg;
const Target *march = TargetRegistry::lookupTarget(TripleStr, errMsg);
if (!march)
- return std::unique_ptr<LTOModule>(nullptr);
+ return make_error_code(object::object_error::arch_not_found);
// construct LTOModule, hand over ownership of module and target
SubtargetFeatures Features;
@@ -456,7 +443,7 @@ void LTOModule::addDefinedSymbol(StringRef Name, const GlobalValue *def,
attr |= LTO_SYMBOL_SCOPE_HIDDEN;
else if (def->hasProtectedVisibility())
attr |= LTO_SYMBOL_SCOPE_PROTECTED;
- else if (canBeOmittedFromSymbolTable(def))
+ else if (def->canBeOmittedFromSymbolTable())
attr |= LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN;
else
attr |= LTO_SYMBOL_SCOPE_DEFAULT;
diff --git a/contrib/llvm/lib/LTO/ThinLTOCodeGenerator.cpp b/contrib/llvm/lib/LTO/ThinLTOCodeGenerator.cpp
index abcd8905ad35..90d0f9bdb885 100644
--- a/contrib/llvm/lib/LTO/ThinLTOCodeGenerator.cpp
+++ b/contrib/llvm/lib/LTO/ThinLTOCodeGenerator.cpp
@@ -23,7 +23,7 @@
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/Bitcode/BitcodeWriterPass.h"
-#include "llvm/ExecutionEngine/ObjectMemoryBuffer.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/LLVMContext.h"
@@ -39,6 +39,7 @@
#include "llvm/Support/Error.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SHA1.h"
+#include "llvm/Support/SmallVectorMemoryBuffer.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/ThreadPool.h"
#include "llvm/Support/Threading.h"
@@ -54,6 +55,12 @@
#include <numeric>
+#if !defined(_MSC_VER) && !defined(__MINGW32__)
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+
using namespace llvm;
#define DEBUG_TYPE "thinlto"
@@ -82,7 +89,7 @@ static void saveTempBitcode(const Module &TheModule, StringRef TempDir,
if (EC)
report_fatal_error(Twine("Failed to open ") + SaveTempPath +
" to save optimized bitcode\n");
- WriteBitcodeToFile(&TheModule, OS, /* ShouldPreserveUseListOrder */ true);
+ WriteBitcodeToFile(TheModule, OS, /* ShouldPreserveUseListOrder */ true);
}
static const GlobalValueSummary *
@@ -267,14 +274,14 @@ std::unique_ptr<MemoryBuffer> codegenModule(Module &TheModule,
PM.add(createObjCARCContractPass());
// Setup the codegen now.
- if (TM.addPassesToEmitFile(PM, OS, TargetMachine::CGFT_ObjectFile,
+ if (TM.addPassesToEmitFile(PM, OS, nullptr, TargetMachine::CGFT_ObjectFile,
/* DisableVerify */ true))
report_fatal_error("Failed to setup codegen");
// Run codegen now. resulting binary is in OutputBuffer.
PM.run(TheModule);
}
- return make_unique<ObjectMemoryBuffer>(std::move(OutputBuffer));
+ return make_unique<SmallVectorMemoryBuffer>(std::move(OutputBuffer));
}
/// Manage caching for a single Module.
@@ -390,7 +397,18 @@ public:
ErrorOr<std::unique_ptr<MemoryBuffer>> tryLoadingBuffer() {
if (EntryPath.empty())
return std::error_code();
- return MemoryBuffer::getFile(EntryPath);
+ int FD;
+ SmallString<64> ResultPath;
+ std::error_code EC = sys::fs::openFileForRead(
+ Twine(EntryPath), FD, sys::fs::OF_UpdateAtime, &ResultPath);
+ if (EC)
+ return EC;
+ ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =
+ MemoryBuffer::getOpenFile(FD, EntryPath,
+ /*FileSize*/ -1,
+ /*RequiresNullTerminator*/ false);
+ close(FD);
+ return MBOrErr;
}
// Cache the Produced object file
@@ -400,9 +418,12 @@ public:
// Write to a temporary to avoid race condition
SmallString<128> TempFilename;
+ SmallString<128> CachePath(EntryPath);
int TempFD;
- std::error_code EC =
- sys::fs::createTemporaryFile("Thin", "tmp.o", TempFD, TempFilename);
+ llvm::sys::path::remove_filename(CachePath);
+ sys::path::append(TempFilename, CachePath, "Thin-%%%%%%.tmp.o");
+ std::error_code EC =
+ sys::fs::createUniqueFile(TempFilename, TempFD, TempFilename);
if (EC) {
errs() << "Error: " << EC.message() << "\n";
report_fatal_error("ThinLTO: Can't get a temporary file");
@@ -411,16 +432,10 @@ public:
raw_fd_ostream OS(TempFD, /* ShouldClose */ true);
OS << OutputBuffer.getBuffer();
}
- // Rename to final destination (hopefully race condition won't matter here)
+ // Rename temp file to final destination; rename is atomic
EC = sys::fs::rename(TempFilename, EntryPath);
- if (EC) {
+ if (EC)
sys::fs::remove(TempFilename);
- raw_fd_ostream OS(EntryPath, EC, sys::fs::F_None);
- if (EC)
- report_fatal_error(Twine("Failed to open ") + EntryPath +
- " to save cached entry\n");
- OS << OutputBuffer.getBuffer();
- }
}
};
@@ -476,9 +491,9 @@ ProcessThinLTOModule(Module &TheModule, ModuleSummaryIndex &Index,
raw_svector_ostream OS(OutputBuffer);
ProfileSummaryInfo PSI(TheModule);
auto Index = buildModuleSummaryIndex(TheModule, nullptr, &PSI);
- WriteBitcodeToFile(&TheModule, OS, true, &Index);
+ WriteBitcodeToFile(TheModule, OS, true, &Index);
}
- return make_unique<ObjectMemoryBuffer>(std::move(OutputBuffer));
+ return make_unique<SmallVectorMemoryBuffer>(std::move(OutputBuffer));
}
return codegenModule(TheModule, TM);
@@ -592,7 +607,7 @@ std::unique_ptr<TargetMachine> TargetMachineBuilder::create() const {
*/
std::unique_ptr<ModuleSummaryIndex> ThinLTOCodeGenerator::linkCombinedIndex() {
std::unique_ptr<ModuleSummaryIndex> CombinedIndex =
- llvm::make_unique<ModuleSummaryIndex>();
+ llvm::make_unique<ModuleSummaryIndex>(/*HaveGVs=*/false);
uint64_t NextModuleId = 0;
for (auto &ModuleBuffer : Modules) {
if (Error Err = readModuleSummaryIndex(ModuleBuffer.getMemBuffer(),
@@ -607,6 +622,32 @@ std::unique_ptr<ModuleSummaryIndex> ThinLTOCodeGenerator::linkCombinedIndex() {
return CombinedIndex;
}
+static void internalizeAndPromoteInIndex(
+ const StringMap<FunctionImporter::ExportSetTy> &ExportLists,
+ const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols,
+ ModuleSummaryIndex &Index) {
+ auto isExported = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID) {
+ const auto &ExportList = ExportLists.find(ModuleIdentifier);
+ return (ExportList != ExportLists.end() &&
+ ExportList->second.count(GUID)) ||
+ GUIDPreservedSymbols.count(GUID);
+ };
+
+ thinLTOInternalizeAndPromoteInIndex(Index, isExported);
+}
+
+static void computeDeadSymbolsInIndex(
+ ModuleSummaryIndex &Index,
+ const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols) {
+ // We have no symbols resolution available. And can't do any better now in the
+ // case where the prevailing symbol is in a native object. It can be refined
+ // with linker information in the future.
+ auto isPrevailing = [&](GlobalValue::GUID G) {
+ return PrevailingType::Unknown;
+ };
+ computeDeadSymbols(Index, GUIDPreservedSymbols, isPrevailing);
+}
+
/**
* Perform promotion and renaming of exported internal functions.
* Index is updated to reflect linkage changes from weak resolution.
@@ -625,7 +666,7 @@ void ThinLTOCodeGenerator::promote(Module &TheModule,
PreservedSymbols, Triple(TheModule.getTargetTriple()));
// Compute "dead" symbols, we don't want to import/export these!
- computeDeadSymbols(Index, GUIDPreservedSymbols);
+ computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
// Generate import/export list
StringMap<FunctionImporter::ImportMapTy> ImportLists(ModuleCount);
@@ -642,13 +683,7 @@ void ThinLTOCodeGenerator::promote(Module &TheModule,
// Promote the exported values in the index, so that they are promoted
// in the module.
- auto isExported = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID) {
- const auto &ExportList = ExportLists.find(ModuleIdentifier);
- return (ExportList != ExportLists.end() &&
- ExportList->second.count(GUID)) ||
- GUIDPreservedSymbols.count(GUID);
- };
- thinLTOInternalizeAndPromoteInIndex(Index, isExported);
+ internalizeAndPromoteInIndex(ExportLists, GUIDPreservedSymbols, Index);
promoteModule(TheModule, Index);
}
@@ -670,7 +705,7 @@ void ThinLTOCodeGenerator::crossModuleImport(Module &TheModule,
PreservedSymbols, Triple(TheModule.getTargetTriple()));
// Compute "dead" symbols, we don't want to import/export these!
- computeDeadSymbols(Index, GUIDPreservedSymbols);
+ computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
// Generate import/export list
StringMap<FunctionImporter::ImportMapTy> ImportLists(ModuleCount);
@@ -723,8 +758,14 @@ void ThinLTOCodeGenerator::emitImports(StringRef ModulePath,
ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries, ImportLists,
ExportLists);
+ std::map<std::string, GVSummaryMapTy> ModuleToSummariesForIndex;
+ llvm::gatherImportedSummariesForModule(ModulePath, ModuleToDefinedGVSummaries,
+ ImportLists[ModulePath],
+ ModuleToSummariesForIndex);
+
std::error_code EC;
- if ((EC = EmitImportsFiles(ModulePath, OutputName, ImportLists[ModulePath])))
+ if ((EC =
+ EmitImportsFiles(ModulePath, OutputName, ModuleToSummariesForIndex)))
report_fatal_error(Twine("Failed to open ") + OutputName +
" to save imports lists\n");
}
@@ -747,7 +788,7 @@ void ThinLTOCodeGenerator::internalize(Module &TheModule,
Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
// Compute "dead" symbols, we don't want to import/export these!
- computeDeadSymbols(Index, GUIDPreservedSymbols);
+ computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
// Generate import/export list
StringMap<FunctionImporter::ImportMapTy> ImportLists(ModuleCount);
@@ -762,13 +803,7 @@ void ThinLTOCodeGenerator::internalize(Module &TheModule,
return;
// Internalization
- auto isExported = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID) {
- const auto &ExportList = ExportLists.find(ModuleIdentifier);
- return (ExportList != ExportLists.end() &&
- ExportList->second.count(GUID)) ||
- GUIDPreservedSymbols.count(GUID);
- };
- thinLTOInternalizeAndPromoteInIndex(Index, isExported);
+ internalizeAndPromoteInIndex(ExportLists, GUIDPreservedSymbols, Index);
thinLTOInternalizeModule(TheModule,
ModuleToDefinedGVSummaries[ModuleIdentifier]);
}
@@ -899,7 +934,7 @@ void ThinLTOCodeGenerator::run() {
computeGUIDPreservedSymbols(PreservedSymbols, TMBuilder.TheTriple);
// Compute "dead" symbols, we don't want to import/export these!
- computeDeadSymbols(*Index, GUIDPreservedSymbols);
+ computeDeadSymbolsInIndex(*Index, GUIDPreservedSymbols);
// Collect the import/export lists for all modules from the call-graph in the
// combined index.
@@ -918,17 +953,10 @@ void ThinLTOCodeGenerator::run() {
// impacts the caching.
resolveWeakForLinkerInIndex(*Index, ResolvedODR);
- auto isExported = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID) {
- const auto &ExportList = ExportLists.find(ModuleIdentifier);
- return (ExportList != ExportLists.end() &&
- ExportList->second.count(GUID)) ||
- GUIDPreservedSymbols.count(GUID);
- };
-
// Use global summary-based analysis to identify symbols that can be
// internalized (because they aren't exported or preserved as per callback).
// Changes are made in the index, consumed in the ThinLTO backends.
- thinLTOInternalizeAndPromoteInIndex(*Index, isExported);
+ internalizeAndPromoteInIndex(ExportLists, GUIDPreservedSymbols, *Index);
// Make sure that every module has an entry in the ExportLists and
// ResolvedODR maps to enable threaded access to these maps below.
@@ -943,12 +971,12 @@ void ThinLTOCodeGenerator::run() {
std::vector<int> ModulesOrdering;
ModulesOrdering.resize(Modules.size());
std::iota(ModulesOrdering.begin(), ModulesOrdering.end(), 0);
- std::sort(ModulesOrdering.begin(), ModulesOrdering.end(),
- [&](int LeftIndex, int RightIndex) {
- auto LSize = Modules[LeftIndex].getBuffer().size();
- auto RSize = Modules[RightIndex].getBuffer().size();
- return LSize > RSize;
- });
+ llvm::sort(ModulesOrdering.begin(), ModulesOrdering.end(),
+ [&](int LeftIndex, int RightIndex) {
+ auto LSize = Modules[LeftIndex].getBuffer().size();
+ auto RSize = Modules[RightIndex].getBuffer().size();
+ return LSize > RSize;
+ });
// Parallel optimizer + codegen
{
@@ -971,9 +999,9 @@ void ThinLTOCodeGenerator::run() {
{
auto ErrOrBuffer = CacheEntry.tryLoadingBuffer();
- DEBUG(dbgs() << "Cache " << (ErrOrBuffer ? "hit" : "miss") << " '"
- << CacheEntryPath << "' for buffer " << count << " "
- << ModuleIdentifier << "\n");
+ LLVM_DEBUG(dbgs() << "Cache " << (ErrOrBuffer ? "hit" : "miss")
+ << " '" << CacheEntryPath << "' for buffer "
+ << count << " " << ModuleIdentifier << "\n");
if (ErrOrBuffer) {
// Cache Hit!
@@ -1020,15 +1048,15 @@ void ThinLTOCodeGenerator::run() {
if (SavedObjectsDirectoryPath.empty()) {
// We need to generated a memory buffer for the linker.
if (!CacheEntryPath.empty()) {
- // Cache is enabled, reload from the cache
- // We do this to lower memory pressuree: the buffer is on the heap
- // and releasing it frees memory that can be used for the next input
- // file. The final binary link will read from the VFS cache
- // (hopefully!) or from disk if the memory pressure wasn't too high.
+ // When cache is enabled, reload from the cache if possible.
+ // Releasing the buffer from the heap and reloading it from the
+ // cache file with mmap helps us to lower memory pressure.
+ // The freed memory can be used for the next input file.
+ // The final binary link will read from the VFS cache (hopefully!)
+ // or from disk (if the memory pressure was too high).
auto ReloadedBufferOrErr = CacheEntry.tryLoadingBuffer();
if (auto EC = ReloadedBufferOrErr.getError()) {
- // On error, keeping the preexisting buffer and printing a
- // diagnostic is more friendly than just crashing.
+ // On error, keep the preexisting buffer and print a diagnostic.
errs() << "error: can't reload cached file '" << CacheEntryPath
<< "': " << EC.message() << "\n";
} else {