hfinkel updated this revision to Diff 55907.
hfinkel added a comment.

Renamed the option from -flisting to -foptimization-report as suggested. Moved 
I/O-related and formatting-related code into Frontend.


http://reviews.llvm.org/D19678

Files:
  include/clang/Driver/CC1Options.td
  include/clang/Driver/Options.td
  include/clang/Frontend/CompilerInstance.h
  include/clang/Frontend/CompilerInvocation.h
  include/clang/Frontend/FrontendActions.h
  include/clang/Frontend/OptReport.h
  lib/CodeGen/CodeGenAction.cpp
  lib/Driver/Tools.cpp
  lib/Frontend/CMakeLists.txt
  lib/Frontend/CompilerInvocation.cpp
  lib/Frontend/OptReport.cpp
  lib/FrontendTool/ExecuteCompilerInvocation.cpp
  test/CodeGen/opt-report.c
  test/Driver/opt-report.c

Index: test/Driver/opt-report.c
===================================================================
--- /dev/null
+++ test/Driver/opt-report.c
@@ -0,0 +1,9 @@
+// RUN: %clang -### -S -o FOO -foptimization-report %s 2>&1 | FileCheck %s
+// RUN: %clang -### -S -o FOO -foptimization-report=BAR.txt %s 2>&1 | FileCheck %s -check-prefix=CHECK-EQ
+
+// CHECK: "-cc1"
+// CHECK: "-opt-report-file" "opt-report.lst"
+
+// CHECK-EQ: "-cc1"
+// CHECK-EQ: "-opt-report-file" "BAR.txt"
+
Index: test/CodeGen/opt-report.c
===================================================================
--- /dev/null
+++ test/CodeGen/opt-report.c
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -O3 -triple x86_64-unknown-linux-gnu -target-cpu x86-64 %s -o %t -dwarf-column-info -opt-report-file %t.lst -emit-obj
+// RUN: cat %t.lst | FileCheck %s
+// REQUIRES: x86-registered-target
+
+void bar();
+void foo() { bar(); }
+
+void Test(int *res, int *c, int *d, int *p, int n) {
+  int i;
+
+#pragma clang loop vectorize(assume_safety)
+  for (i = 0; i < 1600; i++) {
+    res[i] = (p[i] == 0) ? res[i] : res[i] + d[i];
+  }
+
+// CHECK: {{[0-9]+}}     | #pragma clang loop vectorize(assume_safety)
+// CHECK: {{[0-9]+}}   V |   for (i = 0; i < 1600; i++) {
+
+  for (i = 0; i < 16; i++) {
+    res[i] = (p[i] == 0) ? res[i] : res[i] + d[i];
+  }
+
+  foo();
+// CHECK: {{[0-9]+}} I   |   foo();
+
+  foo(); bar(); foo();
+// CHECK: {{[0-9]+}}     |   foo(); bar(); foo();
+// CHECK-NEXT:       I   |   ^
+// CHECK-NEXT:       I   |                 ^
+}
+
Index: lib/FrontendTool/ExecuteCompilerInvocation.cpp
===================================================================
--- lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -165,6 +165,10 @@
     Act = llvm::make_unique<ASTMergeAction>(std::move(Act),
                                             FEOpts.ASTMergeFiles);
 
+  // If an optimization report is requested, generate this after compilation.
+  if (!CI.getOptReportInfo().FileName.empty())
+    Act = llvm::make_unique<OptReportAction>(std::move(Act));
+
   return Act;
 }
 
Index: lib/Frontend/OptReport.cpp
===================================================================
--- /dev/null
+++ lib/Frontend/OptReport.cpp
@@ -0,0 +1,123 @@
+//===------------------------ OptReport.cpp -------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/OptReport.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/Format.h"
+
+using namespace clang;
+
+void OptReportAction::EndSourceFileAction() {
+  GenerateReportFile();
+  WrapperFrontendAction::EndSourceFileAction();
+}
+
+void OptReportAction::GenerateReportFile() {
+  CompilerInstance &CI = getCompilerInstance();
+  DiagnosticsEngine &Diags = CI.getDiagnostics();
+  OptReportInfo &OptReport = CI.getOptReportInfo();
+  if (OptReport.FileName.empty())
+    return;
+
+  std::error_code EC;
+  llvm::raw_fd_ostream OS(OptReport.FileName, EC,
+              llvm::sys::fs::F_Text);
+  if (EC) {
+    Diags.Report(diag::err_fe_error_opening) << OptReport.FileName <<
+                                                EC.message();
+    return;
+  }
+
+  SourceManager &SourceMgr = CI.getSourceManager();
+  std::set<FileID> FileIDs;
+  for (auto &I : OptReport.LocationInfo)
+    FileIDs.insert(SourceMgr.getFileID(I.first));
+
+  for (auto &FID : FileIDs) {
+    SourceLocation FirstLoc = SourceMgr.getLocForStartOfFile(FID);
+    OS << "< " << SourceMgr.getFilename(FirstLoc) << "\n";
+
+    auto I = OptReport.LocationInfo.lower_bound(FirstLoc);
+    StringRef MB = SourceMgr.getBufferData(FID);
+    const SrcMgr::ContentCache *
+      Content = SourceMgr.getSLocEntry(FID).getFile().getContentCache();
+    unsigned LNDigits = llvm::utostr(Content->NumLines).size();
+    for (unsigned L = 0; L < Content->NumLines - 1; ++L) {
+      unsigned LStartOff = Content->SourceLineCache[L];
+      unsigned LEndOff = (L == Content->NumLines) ?
+                         Content->getSize() :
+                         Content->SourceLineCache[L + 1];
+
+      std::map<unsigned, OptReportLocationInfo> ColsInfo;
+      unsigned InlinedCols = 0, UnrolledCols = 0, VectorizedCols = 0;
+
+      OptReportLocationInfo LLI;
+      if (I != OptReport.LocationInfo.end()) {
+        auto DI = SourceMgr.getDecomposedLoc(I->first);
+        while (I != OptReport.LocationInfo.end() && DI.first == FID &&
+               DI.second < LStartOff) {
+          ++I;
+          if (I != OptReport.LocationInfo.end())
+            DI = SourceMgr.getDecomposedLoc(I->first);
+        }
+
+        while (I != OptReport.LocationInfo.end() && DI.first == FID &&
+            DI.second >= LStartOff && DI.second < LEndOff) {
+          unsigned Col = SourceMgr.getColumnNumber(FID, DI.second);
+          ColsInfo[Col] = I->second;
+          InlinedCols += I->second.Inlined.Analyzed;
+          UnrolledCols += I->second.Unrolled.Analyzed;
+          VectorizedCols += I->second.Vectorized.Analyzed;
+          LLI |= I->second;
+
+          ++I;
+          if (I != OptReport.LocationInfo.end())
+            DI = SourceMgr.getDecomposedLoc(I->first);
+        }
+      }
+
+      // We try to keep the output as concise as possible. If only one thing on
+      // a given line could have been inlined, vectorized, etc. then we can put
+      // the marker on the source line itself. If there are multiple options
+      // then we want to distinguish them by placing the marker for each
+      // transformation on a separate line following the source line. When we
+      // do this, we use a '^' character to point to the appropriate column in
+      // the source line.
+
+      OS << llvm::format_decimal(L + 1, LNDigits) << " ";
+      OS << (LLI.Inlined.Transformed && InlinedCols < 2 ? "I" : " ");
+      OS << (LLI.Unrolled.Transformed && UnrolledCols < 2 ? "U" : " ");
+      OS << (LLI.Vectorized.Transformed && VectorizedCols < 2 ? "V" : " ");
+
+      OS << " | " << MB.slice(LStartOff, LEndOff);
+
+      for (auto &J : ColsInfo) {
+        if ((J.second.Inlined.Transformed && InlinedCols > 1) ||
+            (J.second.Unrolled.Transformed && UnrolledCols > 1) ||
+            (J.second.Vectorized.Transformed && VectorizedCols > 1)) {
+          OS << std::string(LNDigits + 1, ' ');
+          OS << (J.second.Inlined.Transformed &&
+                 InlinedCols > 1 ? "I" : " ");
+          OS << (J.second.Unrolled.Transformed &&
+                 UnrolledCols > 1 ? "U" : " ");
+          OS << (J.second.Vectorized.Transformed &&
+                 VectorizedCols > 1 ? "V" : " ");
+
+          OS << " | " << std::string(J.first - 1, ' ') << "^\n";
+        }
+      }
+
+      if (LEndOff == Content->getSize())
+        OS << "\n";
+    }
+  }
+}
+
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -415,7 +415,8 @@
     Opts.setProfileUse(CodeGenOptions::ProfileClangInstr);
 }
 
-static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
+static bool ParseCodeGenArgs(CodeGenOptions &Opts, OptReportInfo &OptReport,
+                             ArgList &Args, InputKind IK,
                              DiagnosticsEngine &Diags,
                              const TargetOptions &TargetOpts) {
   using namespace options;
@@ -488,6 +489,8 @@
   Opts.DebugTypeExtRefs = Args.hasArg(OPT_dwarf_ext_refs);
   Opts.DebugExplicitImport = Triple.isPS4CPU(); 
 
+  OptReport.FileName = Args.getLastArgValue(OPT_opt_report_file);
+
   for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ))
     Opts.DebugPrefixMap.insert(StringRef(Arg).split('='));
 
@@ -764,6 +767,10 @@
   if (!Opts.SampleProfileFile.empty())
     NeedLocTracking = true;
 
+  // To generate an optimization report, source location information is needed.
+  if (!OptReport.FileName.empty())
+    NeedLocTracking = true;
+
   // If the user requested a flag that requires source locations available in
   // the backend, make sure that the backend tracks source location information.
   if (NeedLocTracking && Opts.getDebugInfo() == codegenoptions::NoDebugInfo)
@@ -2130,7 +2137,8 @@
   // FIXME: We shouldn't have to pass the DashX option around here
   InputKind DashX = ParseFrontendArgs(Res.getFrontendOpts(), Args, Diags);
   ParseTargetArgs(Res.getTargetOpts(), Args, Diags);
-  Success &= ParseCodeGenArgs(Res.getCodeGenOpts(), Args, DashX, Diags,
+  Success &= ParseCodeGenArgs(Res.getCodeGenOpts(), Res.getOptReportInfo(),
+                              Args, DashX, Diags,
                               Res.getTargetOpts());
   ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args);
   if (DashX == IK_AST || DashX == IK_LLVM_IR) {
Index: lib/Frontend/CMakeLists.txt
===================================================================
--- lib/Frontend/CMakeLists.txt
+++ lib/Frontend/CMakeLists.txt
@@ -32,6 +32,7 @@
   LogDiagnosticPrinter.cpp
   ModuleDependencyCollector.cpp
   MultiplexConsumer.cpp
+  OptReport.cpp
   PCHContainerOperations.cpp
   PrintPreprocessedOutput.cpp
   SerializedDiagnosticPrinter.cpp
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -3141,23 +3141,29 @@
   }
 }
 
-static const char *SplitDebugName(const ArgList &Args, const InputInfo &Input) {
+static const char *getAltExtOutputName(const ArgList &Args,
+                                       const InputInfo &Input,
+                                       const char *Ext) {
   Arg *FinalOutput = Args.getLastArg(options::OPT_o);
   if (FinalOutput && Args.hasArg(options::OPT_c)) {
     SmallString<128> T(FinalOutput->getValue());
-    llvm::sys::path::replace_extension(T, "dwo");
+    llvm::sys::path::replace_extension(T, Ext);
     return Args.MakeArgString(T);
   } else {
     // Use the compilation dir.
     SmallString<128> T(
         Args.getLastArgValue(options::OPT_fdebug_compilation_dir));
     SmallString<128> F(llvm::sys::path::stem(Input.getBaseInput()));
-    llvm::sys::path::replace_extension(F, "dwo");
+    llvm::sys::path::replace_extension(F, Ext);
     T += F;
     return Args.MakeArgString(F);
   }
 }
 
+static const char *SplitDebugName(const ArgList &Args, const InputInfo &Input) {
+  return getAltExtOutputName(Args, Input, "dwo");
+}
+
 static void SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T,
                            const JobAction &JA, const ArgList &Args,
                            const InputInfo &Output, const char *OutFile) {
@@ -3182,6 +3188,10 @@
   C.addCommand(llvm::make_unique<Command>(JA, T, Exec, StripArgs, II));
 }
 
+static const char *getOptReportName(const ArgList &Args, const InputInfo &Input) {
+  return getAltExtOutputName(Args, Input, "lst");
+}
+
 /// \brief Vectorize at all optimization levels greater than 1 except for -Oz.
 /// For -Oz the loop vectorizer is disable, while the slp vectorizer is enabled.
 static bool shouldEnableVectorizerAtOLevel(const ArgList &Args, bool isSlpVec) {
@@ -5650,6 +5660,18 @@
     CmdArgs.push_back("-fno-math-builtin");
   }
 
+  if (Args.hasFlag(options::OPT_foptimization_report,
+                   options::OPT_foptimization_report_EQ,
+                   options::OPT_fno_optimization_report, false)) {
+    CmdArgs.push_back("-opt-report-file");
+
+    const Arg *A = Args.getLastArg(options::OPT_foptimization_report_EQ);
+    if (A)
+      CmdArgs.push_back(A->getValue());
+    else
+      CmdArgs.push_back(getOptReportName(Args, Input));
+  }
+
 // Default to -fno-builtin-str{cat,cpy} on Darwin for ARM.
 //
 // FIXME: Now that PR4941 has been fixed this can be enabled.
Index: lib/CodeGen/CodeGenAction.cpp
===================================================================
--- lib/CodeGen/CodeGenAction.cpp
+++ lib/CodeGen/CodeGenAction.cpp
@@ -20,6 +20,7 @@
 #include "clang/CodeGen/ModuleBuilder.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/OptReport.h"
 #include "clang/Lex/Preprocessor.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Bitcode/ReaderWriter.h"
@@ -31,6 +32,7 @@
 #include "llvm/IRReader/IRReader.h"
 #include "llvm/Linker/Linker.h"
 #include "llvm/Pass.h"
+#include "llvm/Support/Format.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/Timer.h"
@@ -46,6 +48,7 @@
     const CodeGenOptions &CodeGenOpts;
     const TargetOptions &TargetOpts;
     const LangOptions &LangOpts;
+    OptReportInfo &OptReport;
     raw_pwrite_stream *AsmOutStream;
     ASTContext *Context;
 
@@ -66,13 +69,14 @@
         const HeaderSearchOptions &HeaderSearchOpts,
         const PreprocessorOptions &PPOpts, const CodeGenOptions &CodeGenOpts,
         const TargetOptions &TargetOpts, const LangOptions &LangOpts,
-        bool TimePasses, const std::string &InFile,
+        OptReportInfo &OptReport, bool TimePasses, const std::string &InFile,
         const SmallVectorImpl<std::pair<unsigned, llvm::Module *>> &LinkModules,
         raw_pwrite_stream *OS, LLVMContext &C,
         CoverageSourceInfo *CoverageInfo = nullptr)
         : Diags(Diags), Action(Action), CodeGenOpts(CodeGenOpts),
-          TargetOpts(TargetOpts), LangOpts(LangOpts), AsmOutStream(OS),
-          Context(nullptr), LLVMIRGeneration("LLVM IR Generation Time"),
+          TargetOpts(TargetOpts), LangOpts(LangOpts), OptReport(OptReport),
+          AsmOutStream(OS), Context(nullptr),
+          LLVMIRGeneration("LLVM IR Generation Time"),
           Gen(CreateLLVMCodeGen(Diags, InFile, HeaderSearchOpts, PPOpts,
                                 CodeGenOpts, C, CoverageInfo)) {
       llvm::TimePassesIsEnabled = TimePasses;
@@ -254,6 +258,9 @@
         const llvm::DiagnosticInfoOptimizationRemarkAnalysisAliasing &D);
     void OptimizationFailureHandler(
         const llvm::DiagnosticInfoOptimizationFailure &D);
+
+    void OptimizationRemarkOptReportHandler(
+      const llvm::DiagnosticInfoOptimizationBase &D, bool Transformed = false);
   };
   
   void BackendConsumer::anchor() {}
@@ -513,6 +520,9 @@
   if (CodeGenOpts.OptimizationRemarkPattern &&
       CodeGenOpts.OptimizationRemarkPattern->match(D.getPassName()))
     EmitOptimizationMessage(D, diag::remark_fe_backend_optimization_remark);
+
+  // Record optimization decisions for the listing file.
+  OptimizationRemarkOptReportHandler(D, true);
 }
 
 void BackendConsumer::OptimizationRemarkHandler(
@@ -524,6 +534,9 @@
       CodeGenOpts.OptimizationRemarkMissedPattern->match(D.getPassName()))
     EmitOptimizationMessage(D,
                             diag::remark_fe_backend_optimization_remark_missed);
+
+  // Record optimization decisions for the listing file.
+  OptimizationRemarkOptReportHandler(D);
 }
 
 void BackendConsumer::OptimizationRemarkHandler(
@@ -537,6 +550,9 @@
        CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName())))
     EmitOptimizationMessage(
         D, diag::remark_fe_backend_optimization_remark_analysis);
+
+  // Record optimization decisions for the listing file.
+  OptimizationRemarkOptReportHandler(D);
 }
 
 void BackendConsumer::OptimizationRemarkHandler(
@@ -550,6 +566,9 @@
        CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName())))
     EmitOptimizationMessage(
         D, diag::remark_fe_backend_optimization_remark_analysis_fpcommute);
+
+  // Record optimization decisions for the listing file.
+  OptimizationRemarkOptReportHandler(D);
 }
 
 void BackendConsumer::OptimizationRemarkHandler(
@@ -563,13 +582,58 @@
        CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName())))
     EmitOptimizationMessage(
         D, diag::remark_fe_backend_optimization_remark_analysis_aliasing);
+
+  // Record optimization decisions for the listing file.
+  OptimizationRemarkOptReportHandler(D);
 }
 
 void BackendConsumer::OptimizationFailureHandler(
     const llvm::DiagnosticInfoOptimizationFailure &D) {
   EmitOptimizationMessage(D, diag::warn_fe_backend_optimization_failure);
 }
 
+void BackendConsumer::OptimizationRemarkOptReportHandler(
+    const llvm::DiagnosticInfoOptimizationBase &D, bool Transformed) {
+  if (OptReport.FileName.empty() || !D.isLocationAvailable())
+    return;
+
+  SourceManager &SourceMgr = Context->getSourceManager();
+  FileManager &FileMgr = SourceMgr.getFileManager();
+
+  StringRef Filename;
+  unsigned Line, Column;
+  D.getLocation(&Filename, &Line, &Column);
+  const FileEntry *FE = FileMgr.getFile(Filename);
+  if (!FE || !Line)
+    return;
+
+  // If -gcolumn-info was not used, Column will be 0. This upsets the
+  // source manager, so pass 1 if Column is not set.
+  SourceLocation DILoc =
+    SourceMgr.translateFileLineCol(FE, Line, Column ? Column : 1);
+  if (DILoc.isInvalid())
+    return;
+
+  // We track information on both actual and potential transformations. This
+  // way, if there are multiple possible things on a line that are, or could
+  // have been transformed, we can indicate that explicitly in the output.
+  auto UpdateLLII = [Transformed](OptReportLocationItemInfo &LLII) {
+    LLII.Analyzed = true;
+    if (Transformed)
+      LLII.Transformed = true;
+  };
+
+  // FIXME: The backend should use proper diagnostic subclasses here,
+  // and we should match those instead of looking at the pass name.
+  StringRef PassName = D.getPassName();
+  if (PassName == "inline")
+    UpdateLLII(OptReport.LocationInfo[DILoc].Inlined);
+  else if (PassName == "loop-unroll")
+    UpdateLLII(OptReport.LocationInfo[DILoc].Unrolled);
+  else if (PassName == "loop-vectorize")
+    UpdateLLII(OptReport.LocationInfo[DILoc].Vectorized);
+}
+
 /// \brief This function is invoked when the backend needs
 /// to report something to the user.
 void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) {
@@ -750,8 +814,8 @@
   std::unique_ptr<BackendConsumer> Result(new BackendConsumer(
       BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(),
       CI.getPreprocessorOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(),
-      CI.getLangOpts(), CI.getFrontendOpts().ShowTimers, InFile, LinkModules,
-      OS, *VMContext, CoverageInfo));
+      CI.getLangOpts(), CI.getOptReportInfo(), CI.getFrontendOpts().ShowTimers,
+      InFile, LinkModules, OS, *VMContext, CoverageInfo));
   BEConsumer = Result.get();
   return std::move(Result);
 }
Index: include/clang/Frontend/OptReport.h
===================================================================
--- /dev/null
+++ include/clang/Frontend/OptReport.h
@@ -0,0 +1,67 @@
+//===---- OptReport.h - Clang Optimization-Report Generation ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_OPTREPORT_H_
+#define LLVM_CLANG_FRONTEND_OPTREPORT_H_
+
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Frontend/FrontendAction.h"
+#include <map>
+#include <string>
+
+namespace clang {
+// For each location in the source file, the common per-transformation state
+// collected.
+struct OptReportLocationItemInfo {
+  bool Analyzed = false;
+  bool Transformed = false;
+
+  OptReportLocationItemInfo &operator |= (
+    const OptReportLocationItemInfo &RHS) {
+    Analyzed |= RHS.Analyzed;
+    Transformed |= RHS.Transformed;
+
+    return *this;
+  }
+};
+
+// The per-location information collected for producing an optimization report.
+struct OptReportLocationInfo {
+  OptReportLocationItemInfo Inlined;
+  OptReportLocationItemInfo Unrolled;
+  OptReportLocationItemInfo Vectorized;
+
+  OptReportLocationInfo &operator |= (const OptReportLocationInfo &RHS) {
+    Inlined |= RHS.Inlined;
+    Unrolled |= RHS.Unrolled;
+    Vectorized |= RHS.Vectorized;
+
+    return *this;
+  }
+};
+
+// The parameters and accumulated state necessary to generate an optimization
+// report.
+struct OptReportInfo {
+  std::string FileName;
+  std::map<SourceLocation, OptReportLocationInfo> LocationInfo;
+};
+
+class OptReportAction : public WrapperFrontendAction {
+public:
+  OptReportAction(std::unique_ptr<FrontendAction> WrappedAction)
+    : WrapperFrontendAction(std::move(WrappedAction)) {}
+
+protected:
+  void EndSourceFileAction() override;
+  void GenerateReportFile();
+};
+} // end namespace clang
+
+#endif
Index: include/clang/Frontend/FrontendActions.h
===================================================================
--- include/clang/Frontend/FrontendActions.h
+++ include/clang/Frontend/FrontendActions.h
@@ -236,7 +236,7 @@
 
   bool hasPCHSupport() const override { return true; }
 };
-  
+
 }  // end namespace clang
 
 #endif
Index: include/clang/Frontend/CompilerInvocation.h
===================================================================
--- include/clang/Frontend/CompilerInvocation.h
+++ include/clang/Frontend/CompilerInvocation.h
@@ -19,6 +19,7 @@
 #include "clang/Frontend/FrontendOptions.h"
 #include "clang/Frontend/LangStandard.h"
 #include "clang/Frontend/MigratorOptions.h"
+#include "clang/Frontend/OptReport.h"
 #include "clang/Frontend/PreprocessorOutputOptions.h"
 #include "clang/Lex/HeaderSearchOptions.h"
 #include "clang/Lex/PreprocessorOptions.h"
@@ -117,6 +118,9 @@
   /// Options controlling the frontend itself.
   FrontendOptions FrontendOpts;
 
+  /// Optimization-report options and state.
+  OptReportInfo OptReport;
+
   /// Options controlling preprocessed output.
   PreprocessorOutputOptions PreprocessorOutputOpts;
 
@@ -196,6 +200,13 @@
     return FrontendOpts;
   }
 
+  OptReportInfo &getOptReportInfo() {
+    return OptReport;
+  }
+  const OptReportInfo &getOptReportInfo() const {
+    return OptReport;
+  }
+
   PreprocessorOutputOptions &getPreprocessorOutputOpts() {
     return PreprocessorOutputOpts;
   }
Index: include/clang/Frontend/CompilerInstance.h
===================================================================
--- include/clang/Frontend/CompilerInstance.h
+++ include/clang/Frontend/CompilerInstance.h
@@ -298,6 +298,13 @@
     return *Invocation->getLangOpts();
   }
 
+  OptReportInfo &getOptReportInfo() {
+    return Invocation->getOptReportInfo();
+  }
+  const OptReportInfo &getOptReportInfo() const {
+    return Invocation->getOptReportInfo();
+  }
+
   PreprocessorOptions &getPreprocessorOpts() {
     return Invocation->getPreprocessorOpts();
   }
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -1078,6 +1078,12 @@
                                    Group<f_Group>;
 def foperator_arrow_depth_EQ : Joined<["-"], "foperator-arrow-depth=">,
                                Group<f_Group>;
+def foptimization_report : Flag<["-"], "foptimization-report">, Group<f_Group>,
+  HelpText<"Generate an optimization report file">;
+def fno_optimization_report : Flag<["-"], "fno-optimization-report">,
+  Group<f_Group>, Flags<[NoArgumentUnused]>;
+def foptimization_report_EQ : Joined<["-"], "foptimization-report=">,Group<f_Group>,
+  HelpText<"Generate an optimization report file with the specified name">;
 def ftest_coverage : Flag<["-"], "ftest-coverage">, Group<f_Group>;
 def fvectorize : Flag<["-"], "fvectorize">, Group<f_Group>,
   HelpText<"Enable the loop vectorization passes">;
Index: include/clang/Driver/CC1Options.td
===================================================================
--- include/clang/Driver/CC1Options.td
+++ include/clang/Driver/CC1Options.td
@@ -483,6 +483,9 @@
 def arcmt_migrate : Flag<["-"], "arcmt-migrate">,
   HelpText<"Apply modifications and produces temporary files that conform to ARC">;
 
+def opt_report_file : Separate<["-"], "opt-report-file">,
+  HelpText<"File name to use for optimization listing output">;
+
 def print_stats : Flag<["-"], "print-stats">,
   HelpText<"Print performance metrics and statistics">;
 def fdump_record_layouts : Flag<["-"], "fdump-record-layouts">,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to