[PATCH] Add support for optimization reports.

Diego Novillo dnovillo at google.com
Mon Mar 31 09:26:25 PDT 2014


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

The patch is still WIP:

1- I still need to add tests. Both in the front and middle end.

2- The diagnostic is emitted with a confusing [-WRpass] suffix. I'm
   not quite sure how to remove that. I think it's related to diagnostic
   groups?

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

Files:
  include/clang/Basic/DiagnosticDriverKinds.td
  include/clang/Basic/DiagnosticFrontendKinds.td
  include/clang/Basic/DiagnosticGroups.td
  include/clang/Driver/Options.td
  include/clang/Frontend/CodeGenOptions.h
  lib/CodeGen/CodeGenAction.cpp
  lib/Driver/Tools.cpp
  lib/Frontend/CompilerInvocation.cpp

Index: include/clang/Basic/DiagnosticDriverKinds.td
===================================================================
--- include/clang/Basic/DiagnosticDriverKinds.td
+++ include/clang/Basic/DiagnosticDriverKinds.td
@@ -111,6 +111,8 @@
   "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_report_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">,
Index: include/clang/Basic/DiagnosticFrontendKinds.td
===================================================================
--- include/clang/Basic/DiagnosticFrontendKinds.td
+++ include/clang/Basic/DiagnosticFrontendKinds.td
@@ -32,6 +32,9 @@
 def remark_fe_backend_plugin: Remark<"%0">, CatBackend, InGroup<RemarkBackendPlugin>;
 def note_fe_backend_plugin: Note<"%0">, CatBackend;
 
+def remark_fe_backend_optimization_report: Remark<"%0">, CatBackend,
+    InGroup<BackendOptimizationReport>;
+
 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">,
Index: include/clang/Basic/DiagnosticGroups.td
===================================================================
--- include/clang/Basic/DiagnosticGroups.td
+++ include/clang/Basic/DiagnosticGroups.td
@@ -662,3 +662,4 @@
 def BackendFrameLargerThan : DiagGroup<"frame-larger-than">;
 def BackendPlugin : DiagGroup<"backend-plugin">;
 def RemarkBackendPlugin : DiagGroup<"remark-backend-plugin">;
+def BackendOptimizationReport : DiagGroup<"Rpass">;
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -60,6 +60,7 @@
 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,8 @@
 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">;
 def S : Flag<["-"], "S">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>,
   HelpText<"Only run preprocess and compilation steps">;
 def Tbss : JoinedOrSeparate<["-"], "Tbss">, Group<T_Group>;
Index: include/clang/Frontend/CodeGenOptions.h
===================================================================
--- include/clang/Frontend/CodeGenOptions.h
+++ include/clang/Frontend/CodeGenOptions.h
@@ -16,6 +16,7 @@
 
 #include <string>
 #include <vector>
+#include "llvm/Support/Regex.h"
 
 namespace clang {
 
@@ -145,6 +146,13 @@
   /// 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 reports. 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.
+  llvm::Regex *OptimizationReportPattern;
+
 public:
   // Define accessors/mutators for code generation options of enumeration type.
 #define CODEGENOPT(Name, Bits, Default)
Index: lib/CodeGen/CodeGenAction.cpp
===================================================================
--- lib/CodeGen/CodeGenAction.cpp
+++ lib/CodeGen/CodeGenAction.cpp
@@ -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 @@
     /// \return True if the diagnostic has been successfully reported, false
     /// otherwise.
     bool StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D);
+    /// \brief Specialized handler for the optimization report diagnostic.
+    /// \return True if the diagnostic has been successfully reported, false
+    /// otherwise.
+    bool
+    OptimizationReportHandler(const llvm::DiagnosticInfoOptimizationReport &D);
   };
   
   void BackendConsumer::anchor() {}
@@ -374,6 +380,27 @@
   return true;
 }
 
+bool BackendConsumer::OptimizationReportHandler(
+    const llvm::DiagnosticInfoOptimizationReport &D) {
+  if (CodeGenOpts.OptimizationReportPattern->match(D.getPassName())) {
+    SourceLocation Loc;
+    // FIXME: This should be done earlier.
+    Diags.setDiagnosticMapping(diag::remark_fe_backend_optimization_report,
+                               diag::Mapping::MAP_REMARK, Loc);
+    // FIXME: There should be a way of transferring the DILocation
+    // content into a SourceLocation. We are building the location string
+    // unnecessarily.
+    DILocation DIL(D.getDebugLoc().getAsMDNode(D.getFunction().getContext()));
+    StringRef FileName = DIL.getFilename();
+    unsigned LineNum = DIL.getLineNumber();
+    unsigned ColumnNum = DIL.getColumnNumber();
+    Diags.Report(Loc, diag::remark_fe_backend_optimization_report)
+        << Twine(FileName + ":" + Twine(LineNum) + ":" + Twine(ColumnNum) +
+                 ": " + D.getMsg()).str();
+  }
+  return true;
+}
+
 /// \brief This function is invoked when the backend needs
 /// to report something to the user.
 void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) {
@@ -391,6 +418,10 @@
       return;
     ComputeDiagID(Severity, backend_frame_larger_than, DiagID);
     break;
+  case llvm::DK_OptimizationReport:
+    if (CodeGenOpts.OptimizationReportPattern)
+      OptimizationReportHandler(cast<DiagnosticInfoOptimizationReport>(DI));
+    return;
   default:
     // Plugin IDs are not bound to any value as they are set dynamically.
     ComputeDiagRemarkID(Severity, backend_plugin, DiagID);
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -3293,6 +3293,10 @@
       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");
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -520,6 +520,23 @@
 
   Opts.DependentLibraries = Args.getAllArgValues(OPT_dependent_lib);
 
+  if (Arg *A = Args.getLastArg(OPT_Rpass_EQ)) {
+    StringRef Val = A->getValue();
+    std::string RegexError;
+    Opts.OptimizationReportPattern = new llvm::Regex(Val);
+    if (!Opts.OptimizationReportPattern->isValid(RegexError)) {
+      Diags.Report(diag::err_drv_optimization_report_pattern)
+          << RegexError << A->getAsString(Args);
+      delete Opts.OptimizationReportPattern;
+      Opts.OptimizationReportPattern = 0;
+    } else {
+      // Optimization report diagnostics need to extract location information
+      // from the instructions they are emitted on. When -Rpass is used,
+      // enable line table generation.
+      Opts.setDebugInfo(CodeGenOptions::DebugLineTablesOnly);
+    }
+  }
+
   return Success;
 }
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D3226.1.patch
Type: text/x-patch
Size: 8103 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140331/0ae7151e/attachment.bin>


More information about the llvm-commits mailing list