aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clang/lib/CodeGen/BackendUtil.cpp22
-rw-r--r--clang/test/CodeGen/Inputs/thinlto-distributed-backend-skip.bcbin0 -> 124 bytes
-rw-r--r--clang/test/CodeGen/thinlto-distributed-backend-skip.ll21
-rw-r--r--llvm/include/llvm/IR/ModuleSummaryIndex.h14
-rw-r--r--llvm/lib/Bitcode/Reader/BitcodeReader.cpp5
-rw-r--r--llvm/lib/Bitcode/Writer/BitcodeWriter.cpp11
-rw-r--r--llvm/test/tools/gold/X86/v1.12/thinlto_emit_linked_objects.ll18
-rw-r--r--llvm/tools/gold/gold-plugin.cpp22
8 files changed, 100 insertions, 13 deletions
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index 384800e..dde6577 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -1153,6 +1153,7 @@ void clang::EmitBackendOutput(DiagnosticsEngine &Diags,
const llvm::DataLayout &TDesc, Module *M,
BackendAction Action,
std::unique_ptr<raw_pwrite_stream> OS) {
+ std::unique_ptr<llvm::Module> EmptyModule;
if (!CGOpts.ThinLTOIndexFile.empty()) {
// If we are performing a ThinLTO importing compile, load the function index
// into memory and pass it into runThinLTOBackend, which will run the
@@ -1170,11 +1171,22 @@ void clang::EmitBackendOutput(DiagnosticsEngine &Diags,
// A null CombinedIndex means we should skip ThinLTO compilation
// (LLVM will optionally ignore empty index files, returning null instead
// of an error).
- bool DoThinLTOBackend = CombinedIndex != nullptr;
- if (DoThinLTOBackend) {
- runThinLTOBackend(CombinedIndex.get(), M, HeaderOpts, CGOpts, TOpts,
- LOpts, std::move(OS), CGOpts.SampleProfileFile, Action);
- return;
+ if (CombinedIndex) {
+ if (!CombinedIndex->skipModuleByDistributedBackend()) {
+ runThinLTOBackend(CombinedIndex.get(), M, HeaderOpts, CGOpts, TOpts,
+ LOpts, std::move(OS), CGOpts.SampleProfileFile,
+ Action);
+ return;
+ }
+ // Distributed indexing detected that nothing from the module is needed
+ // for the final linking. So we can skip the compilation. We sill need to
+ // output an empty object file to make sure that a linker does not fail
+ // trying to read it. Also for some features, like CFI, we must skip
+ // the compilation as CombinedIndex does not contain all required
+ // information.
+ EmptyModule = llvm::make_unique<llvm::Module>("empty", M->getContext());
+ EmptyModule->setTargetTriple(M->getTargetTriple());
+ M = EmptyModule.get();
}
}
diff --git a/clang/test/CodeGen/Inputs/thinlto-distributed-backend-skip.bc b/clang/test/CodeGen/Inputs/thinlto-distributed-backend-skip.bc
new file mode 100644
index 0000000..0243eb6
--- /dev/null
+++ b/clang/test/CodeGen/Inputs/thinlto-distributed-backend-skip.bc
Binary files differ
diff --git a/clang/test/CodeGen/thinlto-distributed-backend-skip.ll b/clang/test/CodeGen/thinlto-distributed-backend-skip.ll
new file mode 100644
index 0000000..d9fa47d2
--- /dev/null
+++ b/clang/test/CodeGen/thinlto-distributed-backend-skip.ll
@@ -0,0 +1,21 @@
+; REQUIRES: x86-registered-target
+
+; Check that ThinLTO backend respects "SkipModuleByDistributedBackend"
+; flag which can be set by indexing.
+
+; RUN: opt -thinlto-bc -o %t.o %s
+
+; RUN: %clang_cc1 -triple x86_64-grtev4-linux-gnu \
+; RUN: -fthinlto-index=%S/Inputs/thinlto-distributed-backend-skip.bc \
+; RUN: -emit-llvm -o - -x ir %t.o | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-grtev4-linux-gnu"
+
+; CHECK: "empty"
+; CHECK: target triple =
+; CHECK-NOT: @main
+define i32 @main() {
+entry:
+ ret i32 0
+}
diff --git a/llvm/include/llvm/IR/ModuleSummaryIndex.h b/llvm/include/llvm/IR/ModuleSummaryIndex.h
index 75b22a9..95d1748 100644
--- a/llvm/include/llvm/IR/ModuleSummaryIndex.h
+++ b/llvm/include/llvm/IR/ModuleSummaryIndex.h
@@ -682,6 +682,13 @@ private:
/// considered live.
bool WithGlobalValueDeadStripping = false;
+ /// Indicates that distributed backend should skip compilation of the
+ /// module. Flag is suppose to be set by distributed ThinLTO indexing
+ /// when it detected that the module is not needed during the final
+ /// linking. As result distributed backend should just output a minimal
+ /// valid object file.
+ bool SkipModuleByDistributedBackend = false;
+
/// If true then we're performing analysis of IR module, filling summary
/// accordingly. The value of 'false' means we're reading summary from
/// BC or YAML source. Affects the type of value stored in NameOrGV union
@@ -718,6 +725,13 @@ public:
WithGlobalValueDeadStripping = true;
}
+ bool skipModuleByDistributedBackend() const {
+ return SkipModuleByDistributedBackend;
+ }
+ void setSkipModuleByDistributedBackend() {
+ SkipModuleByDistributedBackend = true;
+ }
+
bool isGlobalValueLive(const GlobalValueSummary *GVS) const {
return !WithGlobalValueDeadStripping || GVS->isLive();
}
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index a6e42b2..f38f7df 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -5186,11 +5186,14 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
case bitc::FS_FLAGS: { // [flags]
uint64_t Flags = Record[0];
// Scan flags (set only on the combined index).
- assert(Flags <= 1 && "Unexpected bits in flag");
+ assert(Flags <= 0x3 && "Unexpected bits in flag");
// 1 bit: WithGlobalValueDeadStripping flag.
if (Flags & 0x1)
TheIndex.setWithGlobalValueDeadStripping();
+ // 1 bit: SkipModuleByDistributedBackend flag.
+ if (Flags & 0x2)
+ TheIndex.setSkipModuleByDistributedBackend();
break;
}
case bitc::FS_VALUE_GUID: { // [valueid, refguid]
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 5a473d6..15c06f5 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -3604,10 +3604,13 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
Stream.EnterSubblock(bitc::GLOBALVAL_SUMMARY_BLOCK_ID, 3);
Stream.EmitRecord(bitc::FS_VERSION, ArrayRef<uint64_t>{INDEX_VERSION});
- // Write the index flags. Currently we only write a single flag, the value of
- // withGlobalValueDeadStripping, which only applies to the combined index.
- Stream.EmitRecord(bitc::FS_FLAGS,
- ArrayRef<uint64_t>{Index.withGlobalValueDeadStripping()});
+ // Write the index flags.
+ uint64_t Flags = 0;
+ if (Index.withGlobalValueDeadStripping())
+ Flags |= 0x1;
+ if (Index.skipModuleByDistributedBackend())
+ Flags |= 0x2;
+ Stream.EmitRecord(bitc::FS_FLAGS, ArrayRef<uint64_t>{Flags});
for (const auto &GVI : valueIds()) {
Stream.EmitRecord(bitc::FS_VALUE_GUID,
diff --git a/llvm/test/tools/gold/X86/v1.12/thinlto_emit_linked_objects.ll b/llvm/test/tools/gold/X86/v1.12/thinlto_emit_linked_objects.ll
index e4f2ed8..cf86a66 100644
--- a/llvm/test/tools/gold/X86/v1.12/thinlto_emit_linked_objects.ll
+++ b/llvm/test/tools/gold/X86/v1.12/thinlto_emit_linked_objects.ll
@@ -31,6 +31,24 @@
; RUN: ls %t2.o.imports
; RUN: ls %t3.o.imports
+; Regular *thinlto.bc file. "SkipModuleByDistributedBackend" flag (0x2)
+; should not be set.
+; RUN: llvm-bcanalyzer --dump %t1.o.thinlto.bc | FileCheck %s -check-prefixes=CHECK-BC1
+; CHECK-BC1: <GLOBALVAL_SUMMARY_BLOCK
+; CHECK-BC1: <FLAGS op0=1/>
+; CHECK-BC1: </GLOBALVAL_SUMMARY_BLOCK
+
+; Nothing interesting in the corresponding object file, so
+; "SkipModuleByDistributedBackend" flag (0x2) should be set.
+; RUN: llvm-bcanalyzer --dump %t2.o.thinlto.bc | FileCheck %s -check-prefixes=CHECK-BC2
+; CHECK-BC2: <GLOBALVAL_SUMMARY_BLOCK
+; CHECK-BC2: <FLAGS op0=2/>
+; CHECK-BC2: </GLOBALVAL_SUMMARY_BLOCK
+
+; Empty as the corresponding object file is not ThinTLO.
+; RUN: not llvm-bcanalyzer --dump %t3.o.thinlto.bc 2>&1 | FileCheck %s -check-prefixes=CHECK-BC3
+; CHECK-BC3: LLVM ERROR: Unexpected end of file
+
; RUN: cat %t.index | FileCheck %s
; CHECK: thinlto_emit_linked_objects.ll.tmp1.o
; CHECK-NOT: thinlto_emit_linked_objects.ll.tmp2.o
diff --git a/llvm/tools/gold/gold-plugin.cpp b/llvm/tools/gold/gold-plugin.cpp
index f7ae0e3..3551077 100644
--- a/llvm/tools/gold/gold-plugin.cpp
+++ b/llvm/tools/gold/gold-plugin.cpp
@@ -811,9 +811,14 @@ static std::unique_ptr<LTO> createLTO(IndexWriteCallback OnIndexWrite) {
// final link. Frequently the distributed build system will want to
// confirm that all expected outputs are created based on all of the
// modules provided to the linker.
+// If SkipModule is true then .thinlto.bc should contain just
+// SkipModuleByDistributedBackend flag which requests distributed backend
+// to skip the compilation of the corresponding module and produce an empty
+// object file.
static void writeEmptyDistributedBuildOutputs(const std::string &ModulePath,
const std::string &OldPrefix,
- const std::string &NewPrefix) {
+ const std::string &NewPrefix,
+ bool SkipModule) {
std::string NewModulePath =
getThinLTOOutputFile(ModulePath, OldPrefix, NewPrefix);
std::error_code EC;
@@ -823,6 +828,12 @@ static void writeEmptyDistributedBuildOutputs(const std::string &ModulePath,
if (EC)
message(LDPL_FATAL, "Failed to write '%s': %s",
(NewModulePath + ".thinlto.bc").c_str(), EC.message().c_str());
+
+ if (SkipModule) {
+ ModuleSummaryIndex Index(false);
+ Index.setSkipModuleByDistributedBackend();
+ WriteIndexToFile(Index, OS, nullptr);
+ }
}
if (options::thinlto_emit_imports_files) {
raw_fd_ostream OS(NewModulePath + ".imports", EC,
@@ -878,6 +889,11 @@ static ld_plugin_status allSymbolsReadHook() {
assert(ObjFilename.second);
if (const void *View = getSymbolsAndView(F))
addModule(*Lto, F, View, ObjFilename.first->first());
+ else if (options::thinlto_index_only) {
+ ObjFilename.first->second = true;
+ writeEmptyDistributedBuildOutputs(Identifier, OldPrefix, NewPrefix,
+ /* SkipModule */ true);
+ }
}
SmallString<128> Filename;
@@ -895,7 +911,7 @@ static ld_plugin_status allSymbolsReadHook() {
auto AddStream =
[&](size_t Task) -> std::unique_ptr<lto::NativeObjectStream> {
IsTemporary[Task] = !SaveTemps;
- int FD = getOutputFileName(Filename, /*TempOutFile=*/!SaveTemps,
+ int FD = getOutputFileName(Filename, /* TempOutFile */ !SaveTemps,
Filenames[Task], Task);
return llvm::make_unique<lto::NativeObjectStream>(
llvm::make_unique<llvm::raw_fd_ostream>(FD, true));
@@ -920,7 +936,7 @@ static ld_plugin_status allSymbolsReadHook() {
for (auto &Identifier : ObjectToIndexFileState)
if (!Identifier.getValue())
writeEmptyDistributedBuildOutputs(Identifier.getKey(), OldPrefix,
- NewPrefix);
+ NewPrefix, /* SkipModule */ false);
if (options::TheOutputType == options::OT_DISABLE ||
options::TheOutputType == options::OT_BC_ONLY)