llvm-lto support for generating combined function indexes
authorTeresa Johnson <tejohnson@google.com>
Mon, 19 Oct 2015 14:30:44 +0000 (14:30 +0000)
committerTeresa Johnson <tejohnson@google.com>
Mon, 19 Oct 2015 14:30:44 +0000 (14:30 +0000)
Summary:
This patch adds support to llvm-lto that mirrors the support added by
r249270 to the gold plugin. This enables better testing of combined
index generation for ThinLTO.

Added a new test, and this support will be used in the test in D13515.

Reviewers: joker.eph

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D13847

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@250699 91177308-0d34-0410-b5e6-96231b3b80d8

test/tools/llvm-lto/Inputs/thinlto.ll [new file with mode: 0644]
test/tools/llvm-lto/thinlto.ll [new file with mode: 0644]
tools/llvm-lto/CMakeLists.txt
tools/llvm-lto/LLVMBuild.txt
tools/llvm-lto/llvm-lto.cpp

diff --git a/test/tools/llvm-lto/Inputs/thinlto.ll b/test/tools/llvm-lto/Inputs/thinlto.ll
new file mode 100644 (file)
index 0000000..4e0840f
--- /dev/null
@@ -0,0 +1,4 @@
+define void @g() {
+entry:
+  ret void
+}
diff --git a/test/tools/llvm-lto/thinlto.ll b/test/tools/llvm-lto/thinlto.ll
new file mode 100644 (file)
index 0000000..29d3881
--- /dev/null
@@ -0,0 +1,24 @@
+; Test combined function index generation for ThinLTO via llvm-lto.
+; RUN: llvm-as -function-summary %s -o %t.o
+; RUN: llvm-as -function-summary %p/Inputs/thinlto.ll -o %t2.o
+; RUN: llvm-lto -thinlto -o %t3 %t.o %t2.o
+; RUN: llvm-bcanalyzer -dump %t3.thinlto.bc | FileCheck %s --check-prefix=COMBINED
+; RUN: not test -e %t3
+
+; COMBINED: <MODULE_STRTAB_BLOCK
+; COMBINED-NEXT: <ENTRY {{.*}} record string = '{{.*}}/thinlto.ll.tmp{{.*}}.o'
+; COMBINED-NEXT: <ENTRY {{.*}} record string = '{{.*}}/thinlto.ll.tmp{{.*}}.o'
+; COMBINED-NEXT: </MODULE_STRTAB_BLOCK
+; COMBINED-NEXT: <FUNCTION_SUMMARY_BLOCK
+; COMBINED-NEXT: <COMBINED_ENTRY
+; COMBINED-NEXT: <COMBINED_ENTRY
+; COMBINED-NEXT: </FUNCTION_SUMMARY_BLOCK
+; COMBINED-NEXT: <VALUE_SYMTAB
+; COMBINED-NEXT: <COMBINED_FNENTRY {{.*}} record string = '{{f|g}}'
+; COMBINED-NEXT: <COMBINED_FNENTRY {{.*}} record string = '{{f|g}}'
+; COMBINED-NEXT: </VALUE_SYMTAB
+
+define void @f() {
+entry:
+  ret void
+}
index 3ea1aee..6a35dd9 100644 (file)
@@ -1,7 +1,10 @@
 set(LLVM_LINK_COMPONENTS
   ${LLVM_TARGETS_TO_BUILD}
+  BitReader
+  Core
   LTO
   MC
+  Object
   Support
   Target
   )
index c1613a3..a586db6 100644 (file)
@@ -19,4 +19,4 @@
 type = Tool
 name = llvm-lto
 parent = Tools
-required_libraries = LTO Support all-targets
+required_libraries = BitReader Core LTO Object Support all-targets
index 50680cc..29d613f 100644 (file)
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ADT/StringSet.h"
+#include "llvm/Bitcode/ReaderWriter.h"
 #include "llvm/CodeGen/CommandFlags.h"
+#include "llvm/IR/LLVMContext.h"
 #include "llvm/LTO/LTOCodeGenerator.h"
 #include "llvm/LTO/LTOModule.h"
+#include "llvm/Object/FunctionIndexObjectFile.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/ManagedStatic.h"
@@ -56,6 +59,10 @@ static cl::opt<bool>
 UseDiagnosticHandler("use-diagnostic-handler", cl::init(false),
   cl::desc("Use a diagnostic handler to test the handler interface"));
 
+static cl::opt<bool> ThinLTO(
+    "thinlto", cl::init(false),
+    cl::desc("Only write combined global index for ThinLTO backends"));
+
 static cl::list<std::string>
 InputFilenames(cl::Positional, cl::OneOrMore,
   cl::desc("<input bitcode files>"));
@@ -151,6 +158,61 @@ static int listSymbols(StringRef Command, const TargetOptions &Options) {
   return 0;
 }
 
+/// Parse the function index out of an IR file and return the function
+/// index object if found, or nullptr if not.
+static std::unique_ptr<FunctionInfoIndex> getFunctionIndexForFile(
+    StringRef Path, std::string &Error, LLVMContext &Context) {
+  std::unique_ptr<MemoryBuffer> Buffer;
+  ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
+      MemoryBuffer::getFile(Path);
+  if (std::error_code EC = BufferOrErr.getError()) {
+    Error = EC.message();
+    return nullptr;
+  }
+  Buffer = std::move(BufferOrErr.get());
+  ErrorOr<std::unique_ptr<object::FunctionIndexObjectFile>> ObjOrErr =
+      object::FunctionIndexObjectFile::create(Buffer->getMemBufferRef(),
+                                              Context);
+  if (std::error_code EC = ObjOrErr.getError()) {
+    Error = EC.message();
+    return nullptr;
+  }
+  return (*ObjOrErr)->takeIndex();
+}
+
+/// Create a combined index file from the input IR files and write it.
+///
+/// This is meant to enable testing of ThinLTO combined index generation,
+/// currently available via the gold plugin via -thinlto.
+static int createCombinedFunctionIndex(StringRef Command) {
+  LLVMContext Context;
+  FunctionInfoIndex CombinedIndex;
+  uint64_t NextModuleId = 0;
+  for (auto &Filename : InputFilenames) {
+    std::string Error;
+    std::unique_ptr<FunctionInfoIndex> Index =
+        getFunctionIndexForFile(Filename, Error, Context);
+    if (!Index) {
+      errs() << Command << ": error loading file '" << Filename
+             << "': " << Error << "\n";
+      return 1;
+    }
+    CombinedIndex.mergeFrom(std::move(Index), ++NextModuleId);
+  }
+  std::error_code EC;
+  assert(!OutputFilename.empty());
+  raw_fd_ostream OS(OutputFilename + ".thinlto.bc", EC,
+                    sys::fs::OpenFlags::F_None);
+  if (EC) {
+    errs() << Command << ": error opening the file '" << OutputFilename
+           << ".thinlto.bc': " << EC.message() << "\n";
+    return 1;
+  }
+  WriteFunctionSummaryToFile(&CombinedIndex, OS);
+  OS.close();
+  return 0;
+}
+
 int main(int argc, char **argv) {
   // Print a stack trace if we signal out.
   sys::PrintStackTraceOnErrorSignal();
@@ -176,6 +238,8 @@ int main(int argc, char **argv) {
   if (ListSymbolsOnly)
     return listSymbols(argv[0], Options);
 
+  if (ThinLTO) return createCombinedFunctionIndex(argv[0]);
+
   unsigned BaseArg = 0;
 
   LTOCodeGenerator CodeGen;