summaryrefslogtreecommitdiffstats
path: root/llvm/lib/LTO
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/LTO')
-rw-r--r--llvm/lib/LTO/CMakeLists.txt1
-rw-r--r--llvm/lib/LTO/LLVMBuild.txt2
-rw-r--r--llvm/lib/LTO/LTO.cpp536
-rw-r--r--llvm/lib/LTO/LTOBackend.cpp277
4 files changed, 6 insertions, 810 deletions
diff --git a/llvm/lib/LTO/CMakeLists.txt b/llvm/lib/LTO/CMakeLists.txt
index c5e34fb0b3a..2007ef21a61 100644
--- a/llvm/lib/LTO/CMakeLists.txt
+++ b/llvm/lib/LTO/CMakeLists.txt
@@ -49,7 +49,6 @@ endif()
add_llvm_library(LLVMLTO
LTO.cpp
- LTOBackend.cpp
LTOModule.cpp
LTOCodeGenerator.cpp
UpdateCompilerUsed.cpp
diff --git a/llvm/lib/LTO/LLVMBuild.txt b/llvm/lib/LTO/LLVMBuild.txt
index f6bcaf558bc..cf0158c8b10 100644
--- a/llvm/lib/LTO/LLVMBuild.txt
+++ b/llvm/lib/LTO/LLVMBuild.txt
@@ -34,4 +34,4 @@ required_libraries =
Scalar
Support
Target
- TransformUtils
+ TransformUtils \ No newline at end of file
diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp
index f4be9b4205b..10226c4a3ff 100644
--- a/llvm/lib/LTO/LTO.cpp
+++ b/llvm/lib/LTO/LTO.cpp
@@ -12,39 +12,16 @@
//===----------------------------------------------------------------------===//
#include "llvm/LTO/LTO.h"
-#include "llvm/Analysis/TargetLibraryInfo.h"
-#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Bitcode/ReaderWriter.h"
-#include "llvm/CodeGen/Analysis.h"
-#include "llvm/IR/AutoUpgrade.h"
-#include "llvm/IR/DiagnosticPrinter.h"
-#include "llvm/IR/LegacyPassManager.h"
-#include "llvm/LTO/LTOBackend.h"
-#include "llvm/Linker/IRMover.h"
-#include "llvm/Object/ModuleSummaryIndexObjectFile.h"
-#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/TargetRegistry.h"
-#include "llvm/Support/ThreadPool.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetOptions.h"
-#include "llvm/Transforms/IPO.h"
-#include "llvm/Transforms/IPO/PassManagerBuilder.h"
-#include "llvm/Transforms/Utils/SplitModule.h"
-#include <set>
-
-using namespace llvm;
-using namespace lto;
-using namespace object;
+namespace llvm {
// Simple helper to load a module from bitcode
-std::unique_ptr<Module>
-llvm::loadModuleFromBuffer(const MemoryBufferRef &Buffer, LLVMContext &Context,
- bool Lazy) {
+std::unique_ptr<Module> loadModuleFromBuffer(const MemoryBufferRef &Buffer,
+ LLVMContext &Context, bool Lazy) {
SMDiagnostic Err;
ErrorOr<std::unique_ptr<Module>> ModuleOrErr(nullptr);
if (Lazy) {
@@ -99,7 +76,7 @@ static void thinLTOResolveWeakForLinkerGUID(
// current module. However there is a chance that another module is still
// referencing them because of the import. We make sure we always emit at least
// one copy.
-void llvm::thinLTOResolveWeakForLinkerInIndex(
+void thinLTOResolveWeakForLinkerInIndex(
ModuleSummaryIndex &Index,
function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
isPrevailing,
@@ -133,513 +110,10 @@ static void thinLTOInternalizeAndPromoteGUID(
// Update the linkages in the given \p Index to mark exported values
// as external and non-exported values as internal.
-void llvm::thinLTOInternalizeAndPromoteInIndex(
+void thinLTOInternalizeAndPromoteInIndex(
ModuleSummaryIndex &Index,
function_ref<bool(StringRef, GlobalValue::GUID)> isExported) {
for (auto &I : Index)
thinLTOInternalizeAndPromoteGUID(I.second, I.first, isExported);
}
-
-Expected<std::unique_ptr<InputFile>> InputFile::create(MemoryBufferRef Object) {
- std::unique_ptr<InputFile> File(new InputFile);
- std::string Msg;
- auto DiagHandler = [](const DiagnosticInfo &DI, void *MsgP) {
- auto *Msg = reinterpret_cast<std::string *>(MsgP);
- raw_string_ostream OS(*Msg);
- DiagnosticPrinterRawOStream DP(OS);
- DI.print(DP);
- };
- File->Ctx.setDiagnosticHandler(DiagHandler, static_cast<void *>(&Msg));
-
- ErrorOr<std::unique_ptr<object::IRObjectFile>> IRObj =
- IRObjectFile::create(Object, File->Ctx);
- if (!Msg.empty())
- return make_error<StringError>(Msg, inconvertibleErrorCode());
- if (!IRObj)
- return errorCodeToError(IRObj.getError());
- File->Obj = std::move(*IRObj);
-
- File->Ctx.setDiagnosticHandler(nullptr, nullptr);
-
- return std::move(File);
-}
-
-LTO::RegularLTOState::RegularLTOState(unsigned ParallelCodeGenParallelismLevel,
- Config &Conf)
- : ParallelCodeGenParallelismLevel(ParallelCodeGenParallelismLevel),
- Ctx(Conf), CombinedModule(make_unique<Module>("ld-temp.o", Ctx)),
- Mover(*CombinedModule) {}
-
-LTO::ThinLTOState::ThinLTOState(ThinBackend Backend) : Backend(Backend) {
- if (!Backend)
- this->Backend = createInProcessThinBackend(thread::hardware_concurrency());
-}
-
-LTO::LTO(Config Conf, ThinBackend Backend,
- unsigned ParallelCodeGenParallelismLevel)
- : Conf(std::move(Conf)),
- RegularLTO(ParallelCodeGenParallelismLevel, this->Conf),
- ThinLTO(Backend) {}
-
-// Add the given symbol to the GlobalResolutions map, and resolve its partition.
-void LTO::addSymbolToGlobalRes(IRObjectFile *Obj,
- SmallPtrSet<GlobalValue *, 8> &Used,
- const InputFile::Symbol &Sym,
- SymbolResolution Res, size_t Partition) {
- GlobalValue *GV = Obj->getSymbolGV(Sym.I->getRawDataRefImpl());
-
- auto &GlobalRes = GlobalResolutions[Sym.getName()];
- if (GV) {
- GlobalRes.UnnamedAddr &= GV->hasGlobalUnnamedAddr();
- if (Res.Prevailing)
- GlobalRes.IRName = GV->getName();
- }
- if (Res.VisibleToRegularObj || (GV && Used.count(GV)) ||
- (GlobalRes.Partition != GlobalResolution::Unknown &&
- GlobalRes.Partition != Partition))
- GlobalRes.Partition = GlobalResolution::External;
- else
- GlobalRes.Partition = Partition;
-}
-
-void LTO::writeToResolutionFile(InputFile *Input,
- ArrayRef<SymbolResolution> Res) {
- StringRef Path = Input->Obj->getMemoryBufferRef().getBufferIdentifier();
- *Conf.ResolutionFile << Path << '\n';
- auto ResI = Res.begin();
- for (const InputFile::Symbol &Sym : Input->symbols()) {
- assert(ResI != Res.end());
- SymbolResolution Res = *ResI++;
-
- *Conf.ResolutionFile << "-r=" << Path << ',' << Sym.getName() << ',';
- if (Res.Prevailing)
- *Conf.ResolutionFile << 'p';
- if (Res.FinalDefinitionInLinkageUnit)
- *Conf.ResolutionFile << 'l';
- if (Res.VisibleToRegularObj)
- *Conf.ResolutionFile << 'x';
- *Conf.ResolutionFile << '\n';
- }
- assert(ResI == Res.end());
-}
-
-Error LTO::add(std::unique_ptr<InputFile> Input,
- ArrayRef<SymbolResolution> Res) {
- assert(!CalledGetMaxTasks);
-
- if (Conf.ResolutionFile)
- writeToResolutionFile(Input.get(), Res);
-
- Module &M = Input->Obj->getModule();
- SmallPtrSet<GlobalValue *, 8> Used;
- collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);
-
- if (!Conf.OverrideTriple.empty())
- M.setTargetTriple(Conf.OverrideTriple);
- else if (M.getTargetTriple().empty())
- M.setTargetTriple(Conf.DefaultTriple);
-
- MemoryBufferRef MBRef = Input->Obj->getMemoryBufferRef();
- bool HasThinLTOSummary = hasGlobalValueSummary(MBRef, Conf.DiagHandler);
-
- if (HasThinLTOSummary)
- return addThinLTO(std::move(Input), Res);
- else
- return addRegularLTO(std::move(Input), Res);
-}
-
-// Add a regular LTO object to the link.
-Error LTO::addRegularLTO(std::unique_ptr<InputFile> Input,
- ArrayRef<SymbolResolution> Res) {
- RegularLTO.HasModule = true;
-
- ErrorOr<std::unique_ptr<object::IRObjectFile>> ObjOrErr =
- IRObjectFile::create(Input->Obj->getMemoryBufferRef(), RegularLTO.Ctx);
- if (!ObjOrErr)
- return errorCodeToError(ObjOrErr.getError());
- std::unique_ptr<object::IRObjectFile> Obj = std::move(*ObjOrErr);
-
- Module &M = Obj->getModule();
- M.materializeMetadata();
- UpgradeDebugInfo(M);
-
- SmallPtrSet<GlobalValue *, 8> Used;
- collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);
-
- std::vector<GlobalValue *> Keep;
-
- for (GlobalVariable &GV : M.globals())
- if (GV.hasAppendingLinkage())
- Keep.push_back(&GV);
-
- auto ResI = Res.begin();
- for (const InputFile::Symbol &Sym :
- make_range(InputFile::symbol_iterator(Obj->symbol_begin()),
- InputFile::symbol_iterator(Obj->symbol_end()))) {
- assert(ResI != Res.end());
- SymbolResolution Res = *ResI++;
- addSymbolToGlobalRes(Obj.get(), Used, Sym, Res, 0);
-
- GlobalValue *GV = Obj->getSymbolGV(Sym.I->getRawDataRefImpl());
- if (Res.Prevailing && GV) {
- Keep.push_back(GV);
- switch (GV->getLinkage()) {
- default:
- break;
- case GlobalValue::LinkOnceAnyLinkage:
- GV->setLinkage(GlobalValue::WeakAnyLinkage);
- break;
- case GlobalValue::LinkOnceODRLinkage:
- GV->setLinkage(GlobalValue::WeakODRLinkage);
- break;
- }
- }
-
- // FIXME: use proposed local attribute for FinalDefinitionInLinkageUnit.
- }
- assert(ResI == Res.end());
-
- return RegularLTO.Mover.move(Obj->takeModule(), Keep,
- [](GlobalValue &, IRMover::ValueAdder) {});
-}
-
-// Add a ThinLTO object to the link.
-Error LTO::addThinLTO(std::unique_ptr<InputFile> Input,
- ArrayRef<SymbolResolution> Res) {
- Module &M = Input->Obj->getModule();
- SmallPtrSet<GlobalValue *, 8> Used;
- collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);
-
- // We need to initialize the target info for the combined regular LTO module
- // in case we have no regular LTO objects. In that case we still need to build
- // it as usual because the client may want to add symbol definitions to it.
- if (RegularLTO.CombinedModule->getTargetTriple().empty()) {
- RegularLTO.CombinedModule->setTargetTriple(M.getTargetTriple());
- RegularLTO.CombinedModule->setDataLayout(M.getDataLayout());
- }
-
- MemoryBufferRef MBRef = Input->Obj->getMemoryBufferRef();
- ErrorOr<std::unique_ptr<object::ModuleSummaryIndexObjectFile>>
- SummaryObjOrErr =
- object::ModuleSummaryIndexObjectFile::create(MBRef, Conf.DiagHandler);
- if (!SummaryObjOrErr)
- return errorCodeToError(SummaryObjOrErr.getError());
- ThinLTO.CombinedIndex.mergeFrom((*SummaryObjOrErr)->takeIndex(),
- ThinLTO.ModuleMap.size());
-
- auto ResI = Res.begin();
- for (const InputFile::Symbol &Sym : Input->symbols()) {
- assert(ResI != Res.end());
- SymbolResolution Res = *ResI++;
- addSymbolToGlobalRes(Input->Obj.get(), Used, Sym, Res,
- ThinLTO.ModuleMap.size() + 1);
-
- GlobalValue *GV = Input->Obj->getSymbolGV(Sym.I->getRawDataRefImpl());
- if (Res.Prevailing && GV)
- ThinLTO.PrevailingModuleForGUID[GV->getGUID()] =
- MBRef.getBufferIdentifier();
- }
- assert(ResI == Res.end());
-
- ThinLTO.ModuleMap[MBRef.getBufferIdentifier()] = MBRef;
- return Error();
-}
-
-size_t LTO::getMaxTasks() const {
- CalledGetMaxTasks = true;
- return RegularLTO.ParallelCodeGenParallelismLevel + ThinLTO.ModuleMap.size();
-}
-
-Error LTO::run(AddStreamFn AddStream) {
- // Invoke regular LTO if there was a regular LTO module to start with,
- // or if there are any hooks that the linker may have used to add
- // its own resolved symbols to the combined module.
- if (RegularLTO.HasModule || Conf.PreOptModuleHook ||
- Conf.PostInternalizeModuleHook || Conf.PostOptModuleHook ||
- Conf.PreCodeGenModuleHook)
- if (auto E = runRegularLTO(AddStream))
- return E;
- return runThinLTO(AddStream);
-}
-
-Error LTO::runRegularLTO(AddStreamFn AddStream) {
- if (Conf.PreOptModuleHook &&
- !Conf.PreOptModuleHook(0, *RegularLTO.CombinedModule))
- return Error();
-
- for (const auto &R : GlobalResolutions) {
- if (R.second.IRName.empty())
- continue;
- if (R.second.Partition != 0 &&
- R.second.Partition != GlobalResolution::External)
- continue;
-
- GlobalValue *GV = RegularLTO.CombinedModule->getNamedValue(R.second.IRName);
- // Ignore symbols defined in other partitions.
- if (!GV || GV->hasLocalLinkage())
- continue;
- GV->setUnnamedAddr(R.second.UnnamedAddr ? GlobalValue::UnnamedAddr::Global
- : GlobalValue::UnnamedAddr::None);
- if (R.second.Partition == 0)
- GV->setLinkage(GlobalValue::InternalLinkage);
- }
-
- if (Conf.PostInternalizeModuleHook &&
- !Conf.PostInternalizeModuleHook(0, *RegularLTO.CombinedModule))
- return Error();
-
- return backend(Conf, AddStream, RegularLTO.ParallelCodeGenParallelismLevel,
- std::move(RegularLTO.CombinedModule));
-}
-
-/// This class defines the interface to the ThinLTO backend.
-class lto::ThinBackendProc {
-protected:
- Config &Conf;
- ModuleSummaryIndex &CombinedIndex;
- AddStreamFn AddStream;
- StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries;
-
-public:
- ThinBackendProc(Config &Conf, ModuleSummaryIndex &CombinedIndex,
- AddStreamFn AddStream,
- StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries)
- : Conf(Conf), CombinedIndex(CombinedIndex), AddStream(AddStream),
- ModuleToDefinedGVSummaries(ModuleToDefinedGVSummaries) {}
-
- virtual ~ThinBackendProc() {}
- virtual Error start(size_t Task, MemoryBufferRef MBRef,
- StringMap<FunctionImporter::ImportMapTy> &ImportLists,
- MapVector<StringRef, MemoryBufferRef> &ModuleMap) = 0;
- virtual Error wait() = 0;
-};
-
-class InProcessThinBackend : public ThinBackendProc {
- ThreadPool BackendThreadPool;
-
- Optional<Error> Err;
- std::mutex ErrMu;
-
-public:
- InProcessThinBackend(Config &Conf, ModuleSummaryIndex &CombinedIndex,
- unsigned ThinLTOParallelismLevel,
- StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries,
- AddStreamFn AddStream)
- : ThinBackendProc(Conf, CombinedIndex, AddStream,
- ModuleToDefinedGVSummaries),
- BackendThreadPool(ThinLTOParallelismLevel) {}
-
- Error
- runThinLTOBackendThread(AddStreamFn AddStream, size_t Task,
- MemoryBufferRef MBRef,
- ModuleSummaryIndex &CombinedIndex,
- const FunctionImporter::ImportMapTy &ImportList,
- const GVSummaryMapTy &DefinedGlobals,
- MapVector<StringRef, MemoryBufferRef> &ModuleMap) {
- LLVMContext BackendContext;
-
- ErrorOr<std::unique_ptr<Module>> MOrErr =
- parseBitcodeFile(MBRef, BackendContext);
- assert(MOrErr && "Unable to load module in thread?");
-
- return thinBackend(Conf, Task, AddStream, **MOrErr, CombinedIndex,
- ImportList, DefinedGlobals, ModuleMap);
- }
-
- Error start(size_t Task, MemoryBufferRef MBRef,
- StringMap<FunctionImporter::ImportMapTy> &ImportLists,
- MapVector<StringRef, MemoryBufferRef> &ModuleMap) override {
- StringRef ModulePath = MBRef.getBufferIdentifier();
- BackendThreadPool.async(
- [=](MemoryBufferRef MBRef, ModuleSummaryIndex &CombinedIndex,
- const FunctionImporter::ImportMapTy &ImportList,
- GVSummaryMapTy &DefinedGlobals,
- MapVector<StringRef, MemoryBufferRef> &ModuleMap) {
- Error E =
- runThinLTOBackendThread(AddStream, Task, MBRef, CombinedIndex,
- ImportList, DefinedGlobals, ModuleMap);
- if (E) {
- std::unique_lock<std::mutex> L(ErrMu);
- if (Err)
- Err = joinErrors(std::move(*Err), std::move(E));
- else
- Err = std::move(E);
- }
- },
- MBRef, std::ref(CombinedIndex), std::ref(ImportLists[ModulePath]),
- std::ref(ModuleToDefinedGVSummaries[ModulePath]), std::ref(ModuleMap));
- return Error();
- }
-
- Error wait() override {
- BackendThreadPool.wait();
- if (Err)
- return std::move(*Err);
- else
- return Error();
- }
-};
-
-ThinBackend lto::createInProcessThinBackend(unsigned ParallelismLevel) {
- return [=](Config &Conf, ModuleSummaryIndex &CombinedIndex,
- StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries,
- AddStreamFn AddStream) {
- return make_unique<InProcessThinBackend>(
- Conf, CombinedIndex, ParallelismLevel, ModuleToDefinedGVSummaries,
- AddStream);
- };
-}
-
-class WriteIndexesThinBackend : public ThinBackendProc {
- std::string OldPrefix, NewPrefix;
- bool ShouldEmitImportsFiles;
-
- std::string LinkedObjectsFileName;
- std::unique_ptr<llvm::raw_fd_ostream> LinkedObjectsFile;
-
-public:
- WriteIndexesThinBackend(Config &Conf, ModuleSummaryIndex &CombinedIndex,
- StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries,
- AddStreamFn AddStream, std::string OldPrefix,
- std::string NewPrefix, bool ShouldEmitImportsFiles,
- std::string LinkedObjectsFileName)
- : ThinBackendProc(Conf, CombinedIndex, AddStream,
- ModuleToDefinedGVSummaries),
- OldPrefix(OldPrefix), NewPrefix(NewPrefix),
- ShouldEmitImportsFiles(ShouldEmitImportsFiles),
- LinkedObjectsFileName(LinkedObjectsFileName) {}
-
- /// Given the original \p Path to an output file, replace any path
- /// prefix matching \p OldPrefix with \p NewPrefix. Also, create the
- /// resulting directory if it does not yet exist.
- std::string getThinLTOOutputFile(const std::string &Path,
- const std::string &OldPrefix,
- const std::string &NewPrefix) {
- if (OldPrefix.empty() && NewPrefix.empty())
- return Path;
- SmallString<128> NewPath(Path);
- llvm::sys::path::replace_path_prefix(NewPath, OldPrefix, NewPrefix);
- StringRef ParentPath = llvm::sys::path::parent_path(NewPath.str());
- if (!ParentPath.empty()) {
- // Make sure the new directory exists, creating it if necessary.
- if (std::error_code EC = llvm::sys::fs::create_directories(ParentPath))
- llvm::errs() << "warning: could not create directory '" << ParentPath
- << "': " << EC.message() << '\n';
- }
- return NewPath.str();
- }
-
- Error start(size_t Task, MemoryBufferRef MBRef,
- StringMap<FunctionImporter::ImportMapTy> &ImportLists,
- MapVector<StringRef, MemoryBufferRef> &ModuleMap) override {
- StringRef ModulePath = MBRef.getBufferIdentifier();
- std::string NewModulePath =
- getThinLTOOutputFile(ModulePath, OldPrefix, NewPrefix);
-
- std::error_code EC;
- if (!LinkedObjectsFileName.empty()) {
- if (!LinkedObjectsFile) {
- LinkedObjectsFile = make_unique<raw_fd_ostream>(
- LinkedObjectsFileName, EC, sys::fs::OpenFlags::F_None);
- if (EC)
- return errorCodeToError(EC);
- }
- *LinkedObjectsFile << NewModulePath << '\n';
- }
-
- std::map<std::string, GVSummaryMapTy> ModuleToSummariesForIndex;
- gatherImportedSummariesForModule(ModulePath, ModuleToDefinedGVSummaries,
- ImportLists, ModuleToSummariesForIndex);
-
- 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", ImportLists));
- return Error();
- }
-
- Error wait() override { return Error(); }
-};
-
-ThinBackend lto::createWriteIndexesThinBackend(std::string OldPrefix,
- std::string NewPrefix,
- bool ShouldEmitImportsFiles,
- std::string LinkedObjectsFile) {
- return [=](Config &Conf, ModuleSummaryIndex &CombinedIndex,
- StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries,
- AddStreamFn AddStream) {
- return make_unique<WriteIndexesThinBackend>(
- Conf, CombinedIndex, ModuleToDefinedGVSummaries, AddStream, OldPrefix,
- NewPrefix, ShouldEmitImportsFiles, LinkedObjectsFile);
- };
-}
-
-Error LTO::runThinLTO(AddStreamFn AddStream) {
- if (ThinLTO.ModuleMap.empty())
- return Error();
-
- if (Conf.CombinedIndexHook && !Conf.CombinedIndexHook(ThinLTO.CombinedIndex))
- return Error();
-
- // Collect for each module the list of function it defines (GUID ->
- // Summary).
- StringMap<std::map<GlobalValue::GUID, GlobalValueSummary *>>
- ModuleToDefinedGVSummaries(ThinLTO.ModuleMap.size());
- ThinLTO.CombinedIndex.collectDefinedGVSummariesPerModule(
- ModuleToDefinedGVSummaries);
-
- StringMap<FunctionImporter::ImportMapTy> ImportLists(
- ThinLTO.ModuleMap.size());
- StringMap<FunctionImporter::ExportSetTy> ExportLists(
- ThinLTO.ModuleMap.size());
- ComputeCrossModuleImport(ThinLTO.CombinedIndex, ModuleToDefinedGVSummaries,
- ImportLists, ExportLists);
-
- std::set<GlobalValue::GUID> ExportedGUIDs;
- for (auto &Res : GlobalResolutions) {
- if (!Res.second.IRName.empty() &&
- Res.second.Partition == GlobalResolution::External)
- ExportedGUIDs.insert(GlobalValue::getGUID(Res.second.IRName));
- }
-
- auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) {
- return ThinLTO.PrevailingModuleForGUID[GUID] == S->modulePath();
- };
- 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);
- thinLTOResolveWeakForLinkerInIndex(
- ThinLTO.CombinedIndex, isPrevailing,
- [](StringRef, GlobalValue::GUID, GlobalValue::LinkageTypes) {});
-
- std::unique_ptr<ThinBackendProc> BackendProc = ThinLTO.Backend(
- Conf, ThinLTO.CombinedIndex, ModuleToDefinedGVSummaries, AddStream);
-
- // Partition numbers for ThinLTO jobs start at 1 (see comments for
- // GlobalResolution in LTO.h). Task numbers, however, start at
- // ParallelCodeGenParallelismLevel, as tasks 0 through
- // ParallelCodeGenParallelismLevel-1 are reserved for parallel code generation
- // partitions.
- size_t Task = RegularLTO.ParallelCodeGenParallelismLevel;
- size_t Partition = 1;
-
- for (auto &Mod : ThinLTO.ModuleMap) {
- if (Error E = BackendProc->start(Task, Mod.second, ImportLists,
- ThinLTO.ModuleMap))
- return E;
-
- ++Task;
- ++Partition;
- }
-
- return BackendProc->wait();
}
diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp
deleted file mode 100644
index 2a5e97dc686..00000000000
--- a/llvm/lib/LTO/LTOBackend.cpp
+++ /dev/null
@@ -1,277 +0,0 @@
-//===-LTOBackend.cpp - LLVM Link Time Optimizer Backend -------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the "backend" phase of LTO, i.e. it performs
-// optimization and code generation on a loaded module. It is generally used
-// internally by the LTO class but can also be used independently, for example
-// to implement a standalone ThinLTO backend.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/LTO/LTOBackend.h"
-#include "llvm/Analysis/TargetLibraryInfo.h"
-#include "llvm/Analysis/TargetTransformInfo.h"
-#include "llvm/Bitcode/ReaderWriter.h"
-#include "llvm/IR/LegacyPassManager.h"
-#include "llvm/MC/SubtargetFeature.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/TargetRegistry.h"
-#include "llvm/Support/ThreadPool.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Transforms/IPO.h"
-#include "llvm/Transforms/IPO/PassManagerBuilder.h"
-#include "llvm/Transforms/Utils/FunctionImportUtils.h"
-#include "llvm/Transforms/Utils/SplitModule.h"
-
-using namespace llvm;
-using namespace lto;
-
-Error Config::addSaveTemps(std::string OutputFileName) {
- ShouldDiscardValueNames = false;
-
- std::error_code EC;
- ResolutionFile = make_unique<raw_fd_ostream>(
- OutputFileName + ".resolution.txt", EC, sys::fs::OpenFlags::F_Text);
- if (EC)
- return errorCodeToError(EC);
-
- auto setHook = [&](std::string PathSuffix, ModuleHookFn &Hook) {
- // Keep track of the hook provided by the linker, which also needs to run.
- ModuleHookFn LinkerHook = Hook;
- Hook = [=](size_t Task, Module &M) {
- // If the linker's hook returned false, we need to pass that result
- // through.
- if (LinkerHook && !LinkerHook(Task, M))
- return false;
-
- std::string PathPrefix;
- PathPrefix = OutputFileName;
- if (Task != 0)
- PathPrefix += "." + utostr(Task);
- std::string Path = PathPrefix + "." + PathSuffix + ".bc";
- std::error_code EC;
- raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::F_None);
- if (EC) {
- // Because -save-temps is a debugging feature, we report the error
- // directly and exit.
- llvm::errs() << "failed to open " << Path << ": " << EC.message()
- << '\n';
- exit(1);
- }
- WriteBitcodeToFile(&M, OS, /*ShouldPreserveUseListOrder=*/false);
- return true;
- };
- };
-
- setHook("0.preopt", PreOptModuleHook);
- setHook("1.promote", PostPromoteModuleHook);
- setHook("2.internalize", PostInternalizeModuleHook);
- setHook("3.import", PostImportModuleHook);
- setHook("4.opt", PostOptModuleHook);
- setHook("5.precodegen", PreCodeGenModuleHook);
-
- CombinedIndexHook = [=](const ModuleSummaryIndex &Index) {
- std::string Path = OutputFileName + ".index.bc";
- std::error_code EC;
- raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::F_None);
- if (EC) {
- // Because -save-temps is a debugging feature, we report the error
- // directly and exit.
- llvm::errs() << "failed to open " << Path << ": " << EC.message() << '\n';
- exit(1);
- }
- WriteIndexToFile(Index, OS);
- return true;
- };
-
- return Error();
-}
-
-namespace {
-
-std::unique_ptr<TargetMachine>
-createTargetMachine(Config &C, StringRef TheTriple, const Target *TheTarget) {
- SubtargetFeatures Features;
- Features.getDefaultSubtargetFeatures(Triple(TheTriple));
- for (const std::string &A : C.MAttrs)
- Features.AddFeature(A);
-
- return std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine(
- TheTriple, C.CPU, Features.getString(), C.Options, C.RelocModel,
- C.CodeModel, C.CGOptLevel));
-}
-
-bool opt(Config &C, TargetMachine *TM, size_t Task, Module &M, bool IsThinLto) {
- M.setDataLayout(TM->createDataLayout());
-
- legacy::PassManager passes;
- passes.add(createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis()));
-
- PassManagerBuilder PMB;
- PMB.LibraryInfo = new TargetLibraryInfoImpl(Triple(TM->getTargetTriple()));
- PMB.Inliner = createFunctionInliningPass();
- // Unconditionally verify input since it is not verified before this
- // point and has unknown origin.
- PMB.VerifyInput = true;
- PMB.VerifyOutput = !C.DisableVerify;
- PMB.LoopVectorize = true;
- PMB.SLPVectorize = true;
- PMB.OptLevel = C.OptLevel;
- if (IsThinLto)
- PMB.populateThinLTOPassManager(passes);
- else
- PMB.populateLTOPassManager(passes);
- passes.run(M);
-
- if (C.PostOptModuleHook && !C.PostOptModuleHook(Task, M))
- return false;
-
- return true;
-}
-
-void codegen(Config &C, TargetMachine *TM, AddStreamFn AddStream, size_t Task,
- Module &M) {
- if (C.PreCodeGenModuleHook && !C.PreCodeGenModuleHook(Task, M))
- return;
-
- std::unique_ptr<raw_pwrite_stream> OS = AddStream(Task);
- legacy::PassManager CodeGenPasses;
- if (TM->addPassesToEmitFile(CodeGenPasses, *OS,
- TargetMachine::CGFT_ObjectFile))
- report_fatal_error("Failed to setup codegen");
- CodeGenPasses.run(M);
-}
-
-void splitCodeGen(Config &C, TargetMachine *TM, AddStreamFn AddStream,
- unsigned ParallelCodeGenParallelismLevel,
- std::unique_ptr<Module> M) {
- ThreadPool CodegenThreadPool(ParallelCodeGenParallelismLevel);
- unsigned ThreadCount = 0;
- const Target *T = &TM->getTarget();
-
- SplitModule(
- std::move(M), ParallelCodeGenParallelismLevel,
- [&](std::unique_ptr<Module> MPart) {
- // We want to clone the module in a new context to multi-thread the
- // codegen. We do it by serializing partition modules to bitcode
- // (while still on the main thread, in order to avoid data races) and
- // spinning up new threads which deserialize the partitions into
- // separate contexts.
- // FIXME: Provide a more direct way to do this in LLVM.
- SmallString<0> BC;
- raw_svector_ostream BCOS(BC);
- WriteBitcodeToFile(MPart.get(), BCOS);
-
- // Enqueue the task
- CodegenThreadPool.async(
- [&](const SmallString<0> &BC, unsigned ThreadId) {
- LTOLLVMContext Ctx(C);
- ErrorOr<std::unique_ptr<Module>> MOrErr = parseBitcodeFile(
- MemoryBufferRef(StringRef(BC.data(), BC.size()), "ld-temp.o"),
- Ctx);
- if (!MOrErr)
- report_fatal_error("Failed to read bitcode");
- std::unique_ptr<Module> MPartInCtx = std::move(MOrErr.get());
-
- std::unique_ptr<TargetMachine> TM =
- createTargetMachine(C, MPartInCtx->getTargetTriple(), T);
- codegen(C, TM.get(), AddStream, ThreadId, *MPartInCtx);
- },
- // Pass BC using std::move to ensure that it get moved rather than
- // copied into the thread's context.
- std::move(BC), ThreadCount++);
- },
- false);
-}
-
-Expected<const Target *> initAndLookupTarget(Config &C, Module &M) {
- if (!C.OverrideTriple.empty())
- M.setTargetTriple(C.OverrideTriple);
- else if (M.getTargetTriple().empty())
- M.setTargetTriple(C.DefaultTriple);
-
- std::string Msg;
- const Target *T = TargetRegistry::lookupTarget(M.getTargetTriple(), Msg);
- if (!T)
- return make_error<StringError>(Msg, inconvertibleErrorCode());
- return T;
-}
-
-}
-
-Error lto::backend(Config &C, AddStreamFn AddStream,
- unsigned ParallelCodeGenParallelismLevel,
- std::unique_ptr<Module> M) {
- Expected<const Target *> TOrErr = initAndLookupTarget(C, *M);
- if (!TOrErr)
- return TOrErr.takeError();
-
- std::unique_ptr<TargetMachine> TM =
- createTargetMachine(C, M->getTargetTriple(), *TOrErr);
-
- if (!opt(C, TM.get(), 0, *M, /*IsThinLto=*/false))
- return Error();
-
- if (ParallelCodeGenParallelismLevel == 1)
- codegen(C, TM.get(), AddStream, 0, *M);
- else
- splitCodeGen(C, TM.get(), AddStream, ParallelCodeGenParallelismLevel,
- std::move(M));
- return Error();
-}
-
-Error lto::thinBackend(Config &C, size_t Task, AddStreamFn AddStream, Module &M,
- ModuleSummaryIndex &CombinedIndex,
- const FunctionImporter::ImportMapTy &ImportList,
- const GVSummaryMapTy &DefinedGlobals,
- MapVector<StringRef, MemoryBufferRef> &ModuleMap) {
- Expected<const Target *> TOrErr = initAndLookupTarget(C, M);
- if (!TOrErr)
- return TOrErr.takeError();
-
- std::unique_ptr<TargetMachine> TM =
- createTargetMachine(C, M.getTargetTriple(), *TOrErr);
-
- if (C.PreOptModuleHook && !C.PreOptModuleHook(Task, M))
- return Error();
-
- thinLTOResolveWeakForLinkerModule(M, DefinedGlobals);
-
- renameModuleForThinLTO(M, CombinedIndex);
-
- if (C.PostPromoteModuleHook && !C.PostPromoteModuleHook(Task, M))
- return Error();
-
- if (!DefinedGlobals.empty())
- thinLTOInternalizeModule(M, DefinedGlobals);
-
- if (C.PostInternalizeModuleHook && !C.PostInternalizeModuleHook(Task, M))
- return Error();
-
- auto ModuleLoader = [&](StringRef Identifier) {
- return std::move(getLazyBitcodeModule(MemoryBuffer::getMemBuffer(
- ModuleMap[Identifier], false),
- M.getContext(),
- /*ShouldLazyLoadMetadata=*/true)
- .get());
- };
-
- FunctionImporter Importer(CombinedIndex, ModuleLoader);
- Importer.importFunctions(M, ImportList);
-
- if (C.PostImportModuleHook && !C.PostImportModuleHook(Task, M))
- return Error();
-
- if (!opt(C, TM.get(), Task, M, /*IsThinLto=*/true))
- return Error();
-
- codegen(C, TM.get(), AddStream, Task, M);
- return Error();
-}
OpenPOWER on IntegriCloud