diff --git a/lld/ELF/Driver.h b/lld/ELF/Driver.h --- a/lld/ELF/Driver.h +++ b/lld/ELF/Driver.h @@ -34,7 +34,7 @@ void createFiles(llvm::opt::InputArgList &args); void inferMachineType(); template void link(llvm::opt::InputArgList &args); - template void compileBitcodeFiles(); + template void compileBitcodeFiles(bool skipLinkedOutput); // True if we are in --whole-archive and --no-whole-archive. bool inWholeArchive = false; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -87,6 +87,7 @@ inputSections.clear(); outputSections.clear(); + memoryBuffers.clear(); archiveFiles.clear(); binaryFiles.clear(); bitcodeFiles.clear(); @@ -1994,13 +1995,26 @@ // using LLVM functions and replaces bitcode symbols with the results. // Because all bitcode files that the program consists of are passed to // the compiler at once, it can do a whole-program optimization. -template void LinkerDriver::compileBitcodeFiles() { +template +void LinkerDriver::compileBitcodeFiles(bool skipLinkedOutput) { llvm::TimeTraceScope timeScope("LTO"); // Compile bitcode files and replace bitcode symbols. lto.reset(new BitcodeCompiler); for (BitcodeFile *file : bitcodeFiles) lto->add(*file); + // For --thinlto-index-only and other conditions which we skip the normal + // linked output, symbol and section names are nearly unused from now on + // (except few places like parseSymbolVersion below). Mark input files as + // MADV_DONTNEED so that these pages can be reused by the expensive thin link, + // saving memory. + // + // Marking most sections (except .strtab/.shstrtab) as MADV_DONTNEED will save + // more memory, but is tricky to implement. So we use this simple approach. + if (skipLinkedOutput) + for (MemoryBuffer &mb : llvm::make_pointee_range(memoryBuffers)) + mb.dontNeedIfMmap(); + for (InputFile *file : lto->compile()) { auto *obj = cast>(file); obj->parse(/*ignoreComdats=*/true); @@ -2364,18 +2378,6 @@ symtab->scanVersionScript(); } - // Do link-time optimization if given files are LLVM bitcode files. - // This compiles bitcode files into real object files. - // - // With this the symbol table should be complete. After this, no new names - // except a few linker-synthesized ones will be added to the symbol table. - compileBitcodeFiles(); - - // Symbol resolution finished. Report backward reference problems. - reportBackrefs(); - if (errorCount()) - return; - // If --thinlto-index-only is given, we should create only "index // files" and not object files. Index file creation is already done // in compileBitcodeFiles, so we are done if that's the case. @@ -2384,8 +2386,23 @@ // respectively. No object files are generated. // Also bail out here when only certain thinLTO modules are specified for // compilation. The intermediate object file are the expected output. - if (config->thinLTOIndexOnly || config->emitLLVM || config->ltoEmitAsm || - !config->thinLTOModulesToCompile.empty()) + const bool skipLinkedOutput = config->thinLTOIndexOnly || config->emitLLVM || + config->ltoEmitAsm || + !config->thinLTOModulesToCompile.empty(); + + // Do link-time optimization if given files are LLVM bitcode files. + // This compiles bitcode files into real object files. + // + // With this the symbol table should be complete. After this, no new names + // except a few linker-synthesized ones will be added to the symbol table. + compileBitcodeFiles(skipLinkedOutput); + + // Symbol resolution finished. Report backward reference problems. + reportBackrefs(); + if (errorCount()) + return; + + if (skipLinkedOutput) return; // Handle --exclude-libs again because lto.tmp may reference additional diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -407,6 +407,7 @@ std::string replaceThinLTOSuffix(StringRef path); +extern SmallVector> memoryBuffers; extern SmallVector archiveFiles; extern SmallVector binaryFiles; extern SmallVector bitcodeFiles; diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -43,6 +43,7 @@ bool InputFile::isInGroup; uint32_t InputFile::nextGroupId; +SmallVector> elf::memoryBuffers; SmallVector elf::archiveFiles; SmallVector elf::binaryFiles; SmallVector elf::bitcodeFiles; @@ -122,9 +123,8 @@ return None; } - std::unique_ptr &mb = *mbOrErr; - MemoryBufferRef mbref = mb->getMemBufferRef(); - make>(std::move(mb)); // take MB ownership + MemoryBufferRef mbref = (*mbOrErr)->getMemBufferRef(); + memoryBuffers.push_back(std::move(*mbOrErr)); // take MB ownership if (tar) tar->append(relativeToRoot(path), mbref.getBuffer());