[LTO] Add option to generate optimization records
authorAdam Nemet <anemet@apple.com>
Fri, 18 Nov 2016 18:06:28 +0000 (18:06 +0000)
committerAdam Nemet <anemet@apple.com>
Fri, 18 Nov 2016 18:06:28 +0000 (18:06 +0000)
It is used to drive this from the clang driver via -mllvm.

Same option name is used as in opt.

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

llvm-svn: 287356

llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h
llvm/lib/LTO/LTOCodeGenerator.cpp
llvm/test/LTO/X86/diagnostic-handler-remarks.ll

index bbd671e..f146821 100644 (file)
@@ -41,6 +41,7 @@
 #include "llvm/ADT/StringSet.h"
 #include "llvm/IR/GlobalValue.h"
 #include "llvm/IR/Module.h"
+#include "llvm/Support/ToolOutputFile.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Target/TargetOptions.h"
 #include <string>
@@ -205,6 +206,9 @@ private:
   void emitError(const std::string &ErrMsg);
   void emitWarning(const std::string &ErrMsg);
 
+  bool setupOptimizationRemarks();
+  void finishOptimizationRemarks();
+
   LLVMContext &Context;
   std::unique_ptr<Module> MergedModule;
   std::unique_ptr<Linker> TheLinker;
@@ -232,6 +236,7 @@ private:
   bool ShouldEmbedUselists = false;
   bool ShouldRestoreGlobalsLinkage = false;
   TargetMachine::CodeGenFileType FileType = TargetMachine::CGFT_ObjectFile;
+  std::unique_ptr<tool_output_file> DiagnosticOutputFile;
 };
 }
 #endif
index 7581064..d2f964e 100644 (file)
@@ -49,6 +49,7 @@
 #include "llvm/Support/TargetRegistry.h"
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/YAMLTraits.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Target/TargetLowering.h"
 #include "llvm/Target/TargetOptions.h"
@@ -92,6 +93,11 @@ cl::opt<bool> LTOStripInvalidDebugInfo(
     cl::Hidden);
 }
 
+static cl::opt<std::string>
+    RemarksFilename("pass-remarks-output",
+                    cl::desc("Output filename for pass remarks"),
+                    cl::value_desc("filename"));
+
 LTOCodeGenerator::LTOCodeGenerator(LLVMContext &Context)
     : Context(Context), MergedModule(new Module("ld-temp.o", Context)),
       TheLinker(new Linker(*MergedModule)) {
@@ -495,6 +501,29 @@ void LTOCodeGenerator::verifyMergedModuleOnce() {
     report_fatal_error("Broken module found, compilation aborted!");
 }
 
+bool LTOCodeGenerator::setupOptimizationRemarks() {
+  if (RemarksFilename != "") {
+    std::error_code EC;
+    DiagnosticOutputFile = llvm::make_unique<tool_output_file>(
+        RemarksFilename, EC, sys::fs::F_None);
+    if (EC) {
+      emitError(EC.message());
+      return false;
+    }
+    Context.setDiagnosticsOutputFile(
+        new yaml::Output(DiagnosticOutputFile->os()));
+  }
+  return true;
+}
+
+void LTOCodeGenerator::finishOptimizationRemarks() {
+  if (DiagnosticOutputFile) {
+    DiagnosticOutputFile->keep();
+    // FIXME: LTOCodeGenerator dtor is not invoked on Darwin
+    DiagnosticOutputFile->os().flush();
+  }
+}
+
 /// Optimize merged modules using various IPO passes
 bool LTOCodeGenerator::optimize(bool DisableVerify, bool DisableInline,
                                 bool DisableGVNLoadPRE,
@@ -502,6 +531,9 @@ bool LTOCodeGenerator::optimize(bool DisableVerify, bool DisableInline,
   if (!this->determineTarget())
     return false;
 
+  if (!setupOptimizationRemarks())
+    return false;
+
   // We always run the verifier once on the merged module, the `DisableVerify`
   // parameter only applies to subsequent verify.
   verifyMergedModuleOnce();
@@ -535,6 +567,8 @@ bool LTOCodeGenerator::optimize(bool DisableVerify, bool DisableInline,
   // Run our queue of passes all at once now, efficiently.
   passes.run(*MergedModule);
 
+  finishOptimizationRemarks();
+
   return true;
 }
 
index 9da11f1..b861fa7 100644 (file)
 ; RUN:     FileCheck %s -allow-empty
 ; RUN: llvm-nm %t.o | FileCheck %s -check-prefix NM
 
+; Optimization records are collected regardless of the diagnostic handler
+; RUN: llvm-lto -pass-remarks-output=%t.yaml \
+; RUN:          -exported-symbol _func2 \
+; RUN:          -exported-symbol _main -o %t.o %t.bc 2>&1 | \
+; RUN:     FileCheck %s -allow-empty
+; RUN: cat %t.yaml | FileCheck %s -check-prefix=YAML
+
 ; REMARKS: remark: {{.*}} foo inlined into main
 ; REMARKS: remark: {{.*}} loop not vectorized: cannot prove it is safe to reorder memory operations
 ; REMARKS_DH: llvm-lto: remark: {{.*}} foo inlined into main
 ; NM: func2
 ; NM: main
 
+; YAML: --- !Passed
+; YAML: Pass:            inline
+; YAML: Name:            Inlined
+; YAML: Function:        main
+; YAML: Args:
+; YAML:   - Callee:          foo
+; YAML:   - String:          ' inlined into '
+; YAML:   - Caller:          main
+; YAML: ...
+
 target triple = "x86_64-apple-darwin"
 
 declare i32 @bar()