Add support for optimization reports.
authorDiego Novillo <dnovillo@google.com>
Tue, 8 Apr 2014 16:42:34 +0000 (16:42 +0000)
committerDiego Novillo <dnovillo@google.com>
Tue, 8 Apr 2014 16:42:34 +0000 (16:42 +0000)
Summary:
This patch adds backend support for -Rpass=, which indicates the name
of the optimization pass that should emit remarks stating when it
made a transformation to the code.

Pass names are taken from their DEBUG_NAME definitions.

When emitting an optimization report diagnostic, the lack of debug
information causes the diagnostic to use "<unknown>:0:0" as the
location string.

This is the back end counterpart for

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

Reviewers: qcolombet

CC: llvm-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D3227

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

include/llvm/IR/DiagnosticInfo.h
include/llvm/IR/LLVMContext.h
lib/IR/DiagnosticInfo.cpp
lib/IR/LLVMContext.cpp
lib/Transforms/IPO/Inliner.cpp

index 49eb1b0c1448eb52afe20877da66eadb07da4b14..589291a12806a2c81a1562cc9101d3191767b130 100644 (file)
@@ -26,6 +26,7 @@ class Function;
 class Instruction;
 class Twine;
 class Value;
+class DebugLoc;
 
 /// \brief Defines the different supported severity of a diagnostic.
 enum DiagnosticSeverity {
@@ -44,6 +45,7 @@ enum DiagnosticKind {
   DK_StackSize,
   DK_DebugMetadataVersion,
   DK_SampleProfile,
+  DK_OptimizationRemark,
   DK_FirstPluginKind
 };
 
@@ -235,6 +237,63 @@ private:
   const Twine &Msg;
 };
 
+/// Diagnostic information for optimization remarks.
+class DiagnosticInfoOptimizationRemark : public DiagnosticInfo {
+public:
+  /// \p PassName is the name of the pass emitting this diagnostic. If
+  /// this name matches the regular expression given in -Rpass=, then the
+  /// diagnostic will be emitted. \p Fn is the function where the diagnostic
+  /// is being emitted. \p DLoc is the location information to use in the
+  /// diagnostic. If line table information is available, the diagnostic
+  /// will include the source code location. \p Msg is the message to show.
+  /// Note that this class does not copy this message, so this reference
+  /// must be valid for the whole life time of the diagnostic.
+  DiagnosticInfoOptimizationRemark(const char *PassName, const Function &Fn,
+                                   const DebugLoc &DLoc, const Twine &Msg)
+      : DiagnosticInfo(DK_OptimizationRemark, DS_Remark), PassName(PassName),
+        Fn(Fn), DLoc(DLoc), Msg(Msg) {}
+
+  /// \see DiagnosticInfo::print.
+  void print(DiagnosticPrinter &DP) const override;
+
+  /// Hand rolled RTTI.
+  static bool classof(const DiagnosticInfo *DI) {
+    return DI->getKind() == DK_OptimizationRemark;
+  }
+
+  /// Return true if location information is available for this diagnostic.
+  bool isLocationAvailable() const;
+
+  /// Return a string with the location information for this diagnostic
+  /// in the format "file:line:col". If location information is not available,
+  /// it returns "<unknown>:0:0".
+  const StringRef getLocationStr() const;
+
+  /// Return location information for this diagnostic in three parts:
+  /// the source file name, line number and column.
+  void getLocation(StringRef *Filename, unsigned *Line, unsigned *Column) const;
+
+  const char *getPassName() const { return PassName; }
+  const Function &getFunction() const { return Fn; }
+  const DebugLoc &getDebugLoc() const { return DLoc; }
+  const Twine &getMsg() const { return Msg; }
+
+private:
+  /// Name of the pass that triggers this report. If this matches the
+  /// regular expression given in -Rpass=regexp, then the remark will
+  /// be emitted.
+  const char *PassName;
+
+  /// Function where this diagnostic is triggered.
+  const Function &Fn;
+
+  /// Debug location where this diagnostic is triggered.
+  const DebugLoc &DLoc;
+
+  /// Message to report.
+  const Twine &Msg;
+};
+
 } // End namespace llvm
 
 #endif
index ae4859aaccfe23e07be90a9493e4263775a0965e..5c698f81de40e0db3e7f8ee7ed693206d6427d97 100644 (file)
@@ -29,6 +29,8 @@ class Module;
 class SMDiagnostic;
 class DiagnosticInfo;
 template <typename T> class SmallVectorImpl;
+class Function;
+class DebugLoc;
 
 /// This is an important class for using LLVM in a threaded context.  It
 /// (opaquely) owns and manages the core "global" data of LLVM's core
@@ -125,6 +127,15 @@ public:
   void emitError(const Instruction *I, const Twine &ErrorStr);
   void emitError(const Twine &ErrorStr);
 
+  /// emitOptimizationRemark - Emit an optimization remark message. \p PassName
+  /// is the name of the pass emitting the message. If -Rpass= is given
+  /// and \p PassName matches the regular expression in -Rpass, then the
+  /// remark will be emitted. \p Fn is the function triggering the remark,
+  /// \p DLoc is the debug location where the diagnostic is generated.
+  /// \p Msg is the message string to use.
+  void emitOptimizationRemark(const char *PassName, const Function &Fn,
+                              const DebugLoc &DLoc, const Twine &Msg);
+
 private:
   LLVMContext(LLVMContext&) LLVM_DELETED_FUNCTION;
   void operator=(LLVMContext&) LLVM_DELETED_FUNCTION;
index d59d4cf0b5077bf17d2991155672187c5279d9fc..fe289af111367a9056d1b5902750224a1c6946ba 100644 (file)
 
 #include "llvm/ADT/Twine.h"
 #include "llvm/IR/Constants.h"
+#include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/DiagnosticPrinter.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/Instruction.h"
 #include "llvm/IR/Metadata.h"
+#include "llvm/IR/Module.h"
 #include "llvm/Support/Atomic.h"
 #include <string>
 
@@ -64,3 +66,29 @@ void DiagnosticInfoSampleProfile::print(DiagnosticPrinter &DP) const {
     DP << getFileName() << ": ";
   DP << getMsg();
 }
+
+bool DiagnosticInfoOptimizationRemark::isLocationAvailable() const {
+  return getFunction().getParent()->getNamedMetadata("llvm.dbg.cu") != 0;
+}
+
+void DiagnosticInfoOptimizationRemark::getLocation(StringRef *Filename,
+                                                   unsigned *Line,
+                                                   unsigned *Column) const {
+  DILocation DIL(getDebugLoc().getAsMDNode(getFunction().getContext()));
+  *Filename = DIL.getFilename();
+  *Line = DIL.getLineNumber();
+  *Column = DIL.getColumnNumber();
+}
+
+const StringRef DiagnosticInfoOptimizationRemark::getLocationStr() const {
+  StringRef Filename("<unknown>");
+  unsigned Line = 0;
+  unsigned Column = 0;
+  if (isLocationAvailable())
+    getLocation(&Filename, &Line, &Column);
+  return Twine(Filename + ":" + Twine(Line) + ":" + Twine(Column)).str();
+}
+
+void DiagnosticInfoOptimizationRemark::print(DiagnosticPrinter &DP) const {
+  DP << getLocationStr() << ": " << getMsg();
+}
index 1bfc51527735d795c6231b39e7d7fba17ebe8ff0..3f05561a2cb1f95ff6ae8dc11e4f232096b60931 100644 (file)
@@ -15,6 +15,7 @@
 #include "llvm/IR/LLVMContext.h"
 #include "LLVMContextImpl.h"
 #include "llvm/IR/Constants.h"
+#include "llvm/IR/DebugLoc.h"
 #include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/DiagnosticPrinter.h"
 #include "llvm/IR/Instruction.h"
@@ -155,6 +156,13 @@ void LLVMContext::emitError(unsigned LocCookie, const Twine &ErrorStr) {
   diagnose(DiagnosticInfoInlineAsm(LocCookie, ErrorStr));
 }
 
+void LLVMContext::emitOptimizationRemark(const char *PassName,
+                                         const Function &Fn,
+                                         const DebugLoc &DLoc,
+                                         const Twine &Msg) {
+  diagnose(DiagnosticInfoOptimizationRemark(PassName, Fn, DLoc, Msg));
+}
+
 //===----------------------------------------------------------------------===//
 // Metadata Kind Uniquing
 //===----------------------------------------------------------------------===//
index e97fb834f8d298c886e98bce91d15d444a3f7786..17be3b2b4472b7281cf835c5cba31cd61a2cb448 100644 (file)
@@ -21,6 +21,7 @@
 #include "llvm/Analysis/InlineCost.h"
 #include "llvm/IR/CallSite.h"
 #include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/Module.h"
@@ -522,7 +523,12 @@ bool Inliner::runOnSCC(CallGraphSCC &SCC) {
                                   InlineHistoryID, InsertLifetime, DL))
           continue;
         ++NumInlined;
-        
+
+        // Report the inline decision.
+        Caller->getContext().emitOptimizationRemark(
+            DEBUG_TYPE, *Caller, CS.getInstruction()->getDebugLoc(),
+            Twine(Callee->getName() + " inlined into " + Caller->getName()));
+
         // If inlining this function gave us any new call sites, throw them
         // onto our worklist to process.  They are useful inline candidates.
         if (!InlineInfo.InlinedCalls.empty()) {