r206401 - Add support for optimization reports.

Diego Novillo dnovillo at google.com
Wed Apr 16 09:54:24 PDT 2014


Author: dnovillo
Date: Wed Apr 16 11:54:24 2014
New Revision: 206401

URL: http://llvm.org/viewvc/llvm-project?rev=206401&view=rev
Log:
Add support for optimization reports.

Summary:
This patch adds a new flag -Rpass=. The flag indicates the name
of the optimization pass that should emit remarks stating when it
made a transformation to the code.

This implements the design I proposed in:

https://docs.google.com/document/d/1FYUatSjZZO-zmFBxjOiuOzAy9mhHA8hqdvklZv68WuQ/edit?usp=sharing

Other changes:
- Add DiagnosticIDs::isRemark(). Use it in printDiagnosticOptions to
  print "-R" instead of "-W" in the diagnostic message.

- In BackendConsumer::OptimizationRemarkHandler, get a SourceLocation
  object out of the file name, line and column number. Use that location
  in the call to Diags.Report().

- When -Rpass is used without debug info a note is emitted alerting
  the user that they need to use -gline-tables-only -gcolumn-info to
  get this information.

CC: llvm-commits

Differential Revision: http://llvm-reviews.chandlerc.com/D3226

Added:
    cfe/trunk/test/Frontend/optimization-remark.c
Modified:
    cfe/trunk/include/clang/Basic/Diagnostic.td
    cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td
    cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td
    cfe/trunk/include/clang/Basic/DiagnosticGroups.td
    cfe/trunk/include/clang/Basic/DiagnosticIDs.h
    cfe/trunk/include/clang/Driver/Options.td
    cfe/trunk/include/clang/Frontend/CodeGenOptions.h
    cfe/trunk/lib/Basic/DiagnosticIDs.cpp
    cfe/trunk/lib/CodeGen/CodeGenAction.cpp
    cfe/trunk/lib/Driver/Tools.cpp
    cfe/trunk/lib/Frontend/CompilerInvocation.cpp
    cfe/trunk/lib/Frontend/TextDiagnosticPrinter.cpp

Modified: cfe/trunk/include/clang/Basic/Diagnostic.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Diagnostic.td?rev=206401&r1=206400&r2=206401&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Diagnostic.td (original)
+++ cfe/trunk/include/clang/Basic/Diagnostic.td Wed Apr 16 11:54:24 2014
@@ -102,6 +102,7 @@ class DefaultWarnNoWerror {
 class DefaultWarnShowInSystemHeader {
   bit WarningShowInSystemHeader = 1;
 }
+class DefaultRemark { DiagMapping DefaultMapping = MAP_REMARK; }
 
 // Definitions for Diagnostics.
 include "DiagnosticASTKinds.td"

Modified: cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td?rev=206401&r1=206400&r2=206401&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td Wed Apr 16 11:54:24 2014
@@ -114,6 +114,8 @@ def err_drv_unknown_objc_runtime : Error
   "unknown or ill-formed Objective-C runtime '%0'">;
 def err_drv_emit_llvm_link : Error<
    "-emit-llvm cannot be used when linking">;
+def err_drv_optimization_remark_pattern : Error<
+  "%0 in '%1'">;
 
 def warn_O4_is_O3 : Warning<"-O4 is equivalent to -O3">, InGroup<Deprecated>;
 def warn_drv_optimization_value : Warning<"optimization level '%0' is unsupported; using '%1%2' instead">,

Modified: cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td?rev=206401&r1=206400&r2=206401&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td Wed Apr 16 11:54:24 2014
@@ -32,6 +32,12 @@ def err_fe_backend_plugin: Error<"%0">,
 def remark_fe_backend_plugin: Remark<"%0">, CatBackend, InGroup<RemarkBackendPlugin>;
 def note_fe_backend_plugin: Note<"%0">, CatBackend;
 
+def remark_fe_backend_optimization_remark : Remark<"%0">, CatBackend,
+    InGroup<BackendOptimizationRemark>, DefaultRemark;
+def note_fe_backend_optimization_remark_missing_loc : Note<"use "
+  "-gline-tables-only -gcolumn-info to track source location information "
+  "for this optimization remark">;
+
 def err_fe_invalid_code_complete_file : Error<
     "cannot locate code-completion file %0">, DefaultFatal;
 def err_fe_stdout_binary : Error<"unable to change standard output to binary">,

Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=206401&r1=206400&r2=206401&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Wed Apr 16 11:54:24 2014
@@ -665,6 +665,7 @@ def BackendInlineAsm : DiagGroup<"inline
 def BackendFrameLargerThan : DiagGroup<"frame-larger-than">;
 def BackendPlugin : DiagGroup<"backend-plugin">;
 def RemarkBackendPlugin : DiagGroup<"remark-backend-plugin">;
+def BackendOptimizationRemark : DiagGroup<"pass">;
 
 // Instrumentation based profiling warnings.
 def ProfileInstrOutOfDate : DiagGroup<"profile-instr-out-of-date">;

Modified: cfe/trunk/include/clang/Basic/DiagnosticIDs.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticIDs.h?rev=206401&r1=206400&r2=206401&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticIDs.h (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticIDs.h Wed Apr 16 11:54:24 2014
@@ -154,6 +154,9 @@ public:
   /// default.
   static bool isDefaultMappingAsError(unsigned DiagID);
 
+  /// \brief Return true if the specified diagnostic is a Remark.
+  static bool isRemark(unsigned DiagID);
+
   /// \brief Determine whether the given built-in diagnostic ID is a Note.
   static bool isBuiltinNote(unsigned DiagID);
 

Modified: cfe/trunk/include/clang/Driver/Options.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=206401&r1=206400&r2=206401&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/Options.td (original)
+++ cfe/trunk/include/clang/Driver/Options.td Wed Apr 16 11:54:24 2014
@@ -60,6 +60,7 @@ def I_Group               : OptionGroup<
 def M_Group               : OptionGroup<"<M group>">, Group<CompileOnly_Group>;
 def T_Group               : OptionGroup<"<T group>">;
 def O_Group               : OptionGroup<"<O group>">, Group<CompileOnly_Group>;
+def R_Group               : OptionGroup<"<R group>">, Group<CompileOnly_Group>;
 def W_Group               : OptionGroup<"<W group>">, Group<CompileOnly_Group>;
 def d_Group               : OptionGroup<"<d group>">;
 def f_Group               : OptionGroup<"<f group>">, Group<CompileOnly_Group>;
@@ -253,7 +254,9 @@ def Qn : Flag<["-"], "Qn">;
 def Qunused_arguments : Flag<["-"], "Qunused-arguments">, Flags<[DriverOption, CoreOption]>,
   HelpText<"Don't emit warning for unused driver arguments">;
 def Q : Flag<["-"], "Q">;
-def R : Flag<["-"], "R">;
+def Rpass_EQ : Joined<["-"], "Rpass=">, Group<R_Group>, Flags<[CC1Option]>,
+  HelpText<"Report transformations performed by optimization passes whose "
+           "name matches the given POSIX regular expression">;
 def S : Flag<["-"], "S">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>,
   HelpText<"Only run preprocess and compilation steps">;
 def Tbss : JoinedOrSeparate<["-"], "Tbss">, Group<T_Group>;

Modified: cfe/trunk/include/clang/Frontend/CodeGenOptions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/CodeGenOptions.h?rev=206401&r1=206400&r2=206401&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/CodeGenOptions.h (original)
+++ cfe/trunk/include/clang/Frontend/CodeGenOptions.h Wed Apr 16 11:54:24 2014
@@ -16,6 +16,7 @@
 
 #include <string>
 #include <vector>
+#include "llvm/Support/Regex.h"
 
 namespace clang {
 
@@ -145,6 +146,13 @@ public:
   /// Name of the profile file to use as input for -fprofile-instr-use
   std::string InstrProfileInput;
 
+  /// Regular expression to select optimizations for which we should enable
+  /// optimization remarks. Transformation passes whose name matches this
+  /// expression (and support this feature), will emit a diagnostic
+  /// whenever they perform a transformation. This is enabled by the
+  /// -Rpass=regexp flag.
+  std::shared_ptr<llvm::Regex> OptimizationRemarkPattern;
+
 public:
   // Define accessors/mutators for code generation options of enumeration type.
 #define CODEGENOPT(Name, Bits, Default)

Modified: cfe/trunk/lib/Basic/DiagnosticIDs.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/DiagnosticIDs.cpp?rev=206401&r1=206400&r2=206401&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/DiagnosticIDs.cpp (original)
+++ cfe/trunk/lib/Basic/DiagnosticIDs.cpp Wed Apr 16 11:54:24 2014
@@ -361,6 +361,11 @@ bool DiagnosticIDs::isDefaultMappingAsEr
   return GetDefaultDiagMappingInfo(DiagID).getMapping() == diag::MAP_ERROR;
 }
 
+bool DiagnosticIDs::isRemark(unsigned DiagID) {
+  return DiagID < diag::DIAG_UPPER_LIMIT &&
+         getBuiltinDiagClass(DiagID) == CLASS_REMARK;
+}
+
 /// getDescription - Given a diagnostic ID, return a description of the
 /// issue.
 StringRef DiagnosticIDs::getDescription(unsigned DiagID) const {

Modified: cfe/trunk/lib/CodeGen/CodeGenAction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenAction.cpp?rev=206401&r1=206400&r2=206401&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenAction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenAction.cpp Wed Apr 16 11:54:24 2014
@@ -20,6 +20,7 @@
 #include "clang/Frontend/FrontendDiagnostic.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/DiagnosticPrinter.h"
 #include "llvm/IR/LLVMContext.h"
@@ -220,6 +221,11 @@ namespace clang {
     /// \return True if the diagnostic has been successfully reported, false
     /// otherwise.
     bool StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D);
+    /// \brief Specialized handler for the optimization diagnostic.
+    /// Note that this handler only accepts remarks and it always handles
+    /// them.
+    void
+    OptimizationRemarkHandler(const llvm::DiagnosticInfoOptimizationRemark &D);
   };
   
   void BackendConsumer::anchor() {}
@@ -374,6 +380,44 @@ BackendConsumer::StackSizeDiagHandler(co
   return true;
 }
 
+void BackendConsumer::OptimizationRemarkHandler(
+    const llvm::DiagnosticInfoOptimizationRemark &D) {
+  // We only support remarks.
+  assert (D.getSeverity() == llvm::DS_Remark);
+
+  // Optimization remarks are active only if -Rpass=regexp is given and the
+  // regular expression pattern in 'regexp' matches the name of the pass
+  // name in \p D.
+  if (CodeGenOpts.OptimizationRemarkPattern &&
+      CodeGenOpts.OptimizationRemarkPattern->match(D.getPassName())) {
+    SourceManager &SourceMgr = Context->getSourceManager();
+    FileManager &FileMgr = SourceMgr.getFileManager();
+    StringRef Filename;
+    unsigned Line, Column;
+    D.getLocation(&Filename, &Line, &Column);
+    SourceLocation Loc;
+    if (Line > 0) {
+      // If -gcolumn-info was not used, Column will be 0. This upsets the
+      // source manager, so if Column is not set, set it to 1.
+      if (Column == 0)
+        Column = 1;
+      Loc = SourceMgr.translateFileLineCol(FileMgr.getFile(Filename), Line,
+                                           Column);
+    }
+    Diags.Report(Loc, diag::remark_fe_backend_optimization_remark)
+        << D.getMsg().str();
+
+    if (Line == 0)
+      // If we could not extract a source location for the diagnostic,
+      // inform the user how they can get source locations back.
+      //
+      // FIXME: We should really be generating !srcloc annotations when
+      // -Rpass is used. !srcloc annotations need to be emitted in
+      // approximately the same spots as !dbg nodes.
+      Diags.Report(diag::note_fe_backend_optimization_remark_missing_loc);
+  }
+}
+
 /// \brief This function is invoked when the backend needs
 /// to report something to the user.
 void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) {
@@ -391,6 +435,11 @@ void BackendConsumer::DiagnosticHandlerI
       return;
     ComputeDiagID(Severity, backend_frame_larger_than, DiagID);
     break;
+  case llvm::DK_OptimizationRemark:
+    // Optimization remarks are always handled completely by this
+    // handler. There is no generic way of emitting them.
+    OptimizationRemarkHandler(cast<DiagnosticInfoOptimizationRemark>(DI));
+    return;
   default:
     // Plugin IDs are not bound to any value as they are set dynamically.
     ComputeDiagRemarkID(Severity, backend_plugin, DiagID);

Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=206401&r1=206400&r2=206401&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Wed Apr 16 11:54:24 2014
@@ -3417,6 +3417,9 @@ void Clang::ConstructJob(Compilation &C,
       A->render(Args, CmdArgs);
   }
 
+  if (Arg *A = Args.getLastArg(options::OPT_Rpass_EQ))
+    A->render(Args, CmdArgs);
+
   if (Args.hasArg(options::OPT_mkernel)) {
     if (!Args.hasArg(options::OPT_fapple_kext) && types::isCXX(InputType))
       CmdArgs.push_back("-fapple-kext");

Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=206401&r1=206400&r2=206401&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Wed Apr 16 11:54:24 2014
@@ -520,6 +520,17 @@ static bool ParseCodeGenArgs(CodeGenOpti
 
   Opts.DependentLibraries = Args.getAllArgValues(OPT_dependent_lib);
 
+  if (Arg *A = Args.getLastArg(OPT_Rpass_EQ)) {
+    StringRef Val = A->getValue();
+    std::string RegexError;
+    Opts.OptimizationRemarkPattern = std::make_shared<llvm::Regex>(Val);
+    if (!Opts.OptimizationRemarkPattern->isValid(RegexError)) {
+      Diags.Report(diag::err_drv_optimization_remark_pattern)
+          << RegexError << A->getAsString(Args);
+      Opts.OptimizationRemarkPattern.reset();
+    }
+  }
+
   return Success;
 }
 

Modified: cfe/trunk/lib/Frontend/TextDiagnosticPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/TextDiagnosticPrinter.cpp?rev=206401&r1=206400&r2=206401&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/TextDiagnosticPrinter.cpp (original)
+++ cfe/trunk/lib/Frontend/TextDiagnosticPrinter.cpp Wed Apr 16 11:54:24 2014
@@ -81,7 +81,8 @@ static void printDiagnosticOptions(raw_o
 
     StringRef Opt = DiagnosticIDs::getWarningOptionForDiag(Info.getID());
     if (!Opt.empty()) {
-      OS << (Started ? "," : " [") << "-W" << Opt;
+      OS << (Started ? "," : " [")
+         << (DiagnosticIDs::isRemark(Info.getID()) ? "-R" : "-W") << Opt;
       Started = true;
     }
   }

Added: cfe/trunk/test/Frontend/optimization-remark.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Frontend/optimization-remark.c?rev=206401&view=auto
==============================================================================
--- cfe/trunk/test/Frontend/optimization-remark.c (added)
+++ cfe/trunk/test/Frontend/optimization-remark.c Wed Apr 16 11:54:24 2014
@@ -0,0 +1,19 @@
+// This file tests the -Rpass= flag with the inliner. The test is
+// designed to always trigger the inliner, so it should be independent
+// of the optimization level.
+
+// RUN: %clang -c %s -Rpass=inline -O0 -gline-tables-only -o /dev/null 2> %t.err
+// RUN: FileCheck < %t.err %s --check-prefix=INLINE
+
+// RUN: %clang -c %s -Rpass=inline -O0 -o /dev/null 2> %t.err
+// RUN: FileCheck < %t.err %s --check-prefix=INLINE-NO-LOC
+
+int foo(int x, int y) __attribute__((always_inline));
+
+int foo(int x, int y) { return x + y; }
+int bar(int j) { return foo(j, j - 2); }
+
+// INLINE: remark: foo inlined into bar [-Rpass]
+
+// INLINE-NO-LOC: {{^remark: foo inlined into bar}}
+// INLINE-NO-LOC: note: use -gline-tables-only -gcolumn-info to track





More information about the cfe-commits mailing list