Skip to content

Commit

Permalink
[ThinLTO] Always create linked objects file for --thinlto-index-only=
Browse files Browse the repository at this point in the history
Summary:
ThinLTO indexing may decide to skip all objects. If we don't write something to
the list build system may consider this as failure or linker can reuse a file
from the previews build.

Reviewers: pcc, tejohnson

Subscribers: mehdi_amini, inglorion, eraman, hiraditya, llvm-commits

Differential Revision: https://reviews.llvm.org/D43415

llvm-svn: 325819
  • Loading branch information
vitalybuka committed Feb 22, 2018
1 parent ffbf7db commit a139b69
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 29 deletions.
4 changes: 3 additions & 1 deletion llvm/include/llvm/LTO/LTO.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,13 +210,15 @@ ThinBackend createInProcessThinBackend(unsigned ParallelismLevel);
/// appends ".thinlto.bc" and writes the index to that path. If
/// ShouldEmitImportsFiles is true it also writes a list of imported files to a
/// similar path with ".imports" appended instead.
/// LinkedObjectsFile is an output stream to write the list of object files for
/// the final ThinLTO linking. Can be nullptr.
/// OnWrite is callback which receives module identifier and notifies LTO user
/// that index file for the module (and optionally imports file) was created.
using IndexWriteCallback = std::function<void(const std::string &)>;
ThinBackend createWriteIndexesThinBackend(std::string OldPrefix,
std::string NewPrefix,
bool ShouldEmitImportsFiles,
std::string LinkedObjectsFile,
raw_fd_ostream *LinkedObjectsFile,
IndexWriteCallback OnWrite);

/// This class implements a resolution-based interface to LLVM's LTO
Expand Down
28 changes: 8 additions & 20 deletions llvm/lib/LTO/LTO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1038,22 +1038,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, lto::IndexWriteCallback OnWrite)
raw_fd_ostream *LinkedObjectsFile, lto::IndexWriteCallback OnWrite)
: ThinBackendProc(Conf, CombinedIndex, ModuleToDefinedGVSummaries),
OldPrefix(OldPrefix), NewPrefix(NewPrefix),
ShouldEmitImportsFiles(ShouldEmitImportsFiles),
LinkedObjectsFileName(LinkedObjectsFileName), OnWrite(OnWrite) {}
LinkedObjectsFile(LinkedObjectsFile), OnWrite(OnWrite) {}

Error start(
unsigned Task, BitcodeModule BM,
Expand All @@ -1065,21 +1062,14 @@ class WriteIndexesThinBackend : public ThinBackendProc {
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)
Expand All @@ -1101,11 +1091,9 @@ class WriteIndexesThinBackend : public ThinBackendProc {
};
} // end anonymous namespace

ThinBackend lto::createWriteIndexesThinBackend(std::string OldPrefix,
std::string NewPrefix,
bool ShouldEmitImportsFiles,
std::string LinkedObjectsFile,
IndexWriteCallback OnWrite) {
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) {
Expand Down
18 changes: 18 additions & 0 deletions llvm/test/tools/gold/X86/thinlto_no_objects.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
; Check that thinlto-index-only= always creates linked objects file, even
; if nothing to add there.

; Non-ThinLTO file should not get into list of linked objects.
; RUN: opt %s -o %t.o

; RUN: rm -f %t3
; RUN: %gold -plugin %llvmshlibdir/LLVMgold%shlibext \
; RUN: --plugin-opt=thinlto \
; RUN: --plugin-opt=thinlto-index-only=%t3 \
; RUN: -o %t5 \
; RUN: %t.o

; RUN: cat %t3 | count 0

target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

36 changes: 29 additions & 7 deletions llvm/tools/gold/gold-plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -736,7 +736,12 @@ static void getThinLTOOldAndNewPrefix(std::string &OldPrefix,
std::tie(OldPrefix, NewPrefix) = PrefixReplace.split(';');
}

static std::unique_ptr<LTO> createLTO(IndexWriteCallback OnIndexWrite) {
/// Creates instance of LTO.
/// OnIndexWrite is callback to let caller know when LTO writes index files.
/// LinkedObjectsFile is an output stream to write the list of object files for
/// the final ThinLTO linking. Can be nullptr.
static std::unique_ptr<LTO> createLTO(IndexWriteCallback OnIndexWrite,
raw_fd_ostream *LinkedObjectsFile) {
Config Conf;
ThinBackend Backend;

Expand All @@ -760,9 +765,9 @@ static std::unique_ptr<LTO> createLTO(IndexWriteCallback OnIndexWrite) {
if (options::thinlto_index_only) {
std::string OldPrefix, NewPrefix;
getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
Backend = createWriteIndexesThinBackend(
OldPrefix, NewPrefix, options::thinlto_emit_imports_files,
options::thinlto_linked_objects_file, OnIndexWrite);
Backend = createWriteIndexesThinBackend(OldPrefix, NewPrefix,
options::thinlto_emit_imports_files,
LinkedObjectsFile, OnIndexWrite);
}

Conf.OverrideTriple = options::triple;
Expand Down Expand Up @@ -844,6 +849,21 @@ static void writeEmptyDistributedBuildOutputs(const std::string &ModulePath,
}
}

// Creates and returns output stream with a list of object files for final
// linking of distributed ThinLTO.
static std::unique_ptr<raw_fd_ostream> CreateLinkedObjectsFile() {
if (options::thinlto_linked_objects_file.empty())
return nullptr;
assert(options::thinlto_index_only);
std::error_code EC;
auto LinkedObjectsFile = llvm::make_unique<raw_fd_ostream>(
options::thinlto_linked_objects_file, EC, sys::fs::OpenFlags::F_None);
if (EC)
message(LDPL_FATAL, "Failed to create '%s': %s",
options::thinlto_linked_objects_file.c_str(), EC.message().c_str());
return LinkedObjectsFile;
}

/// Runs LTO and return a list of pairs <FileName, IsTemporary>.
static std::vector<std::pair<SmallString<128>, bool>> runLTO() {
// Map to own RAII objects that manage the file opening and releasing
Expand All @@ -856,10 +876,12 @@ static std::vector<std::pair<SmallString<128>, bool>> runLTO() {
// Owns string objects and tells if index file was already created.
StringMap<bool> ObjectToIndexFileState;

std::unique_ptr<LTO> Lto =
createLTO([&ObjectToIndexFileState](const std::string &Identifier) {
std::unique_ptr<raw_fd_ostream> LinkedObjects = CreateLinkedObjectsFile();
std::unique_ptr<LTO> Lto = createLTO(
[&ObjectToIndexFileState](const std::string &Identifier) {
ObjectToIndexFileState[Identifier] = true;
});
},
LinkedObjects.get());

std::string OldPrefix, NewPrefix;
if (options::thinlto_index_only)
Expand Down
6 changes: 5 additions & 1 deletion llvm/tools/llvm-lto2/llvm-lto2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,11 @@ static int run(int argc, char **argv) {

ThinBackend Backend;
if (ThinLTODistributedIndexes)
Backend = createWriteIndexesThinBackend("", "", true, "", {});
Backend = createWriteIndexesThinBackend(/* OldPrefix */ "",
/* NewPrefix */ "",
/* ShouldEmitImportsFiles */ true,
/* LinkedObjectsFile */ nullptr,
/* OnWrite */ {});
else
Backend = createInProcessThinBackend(Threads);
LTO Lto(std::move(Conf), std::move(Backend));
Expand Down

0 comments on commit a139b69

Please sign in to comment.