Index: include/llvm/IR/DiagnosticInfo.h =================================================================== --- include/llvm/IR/DiagnosticInfo.h +++ include/llvm/IR/DiagnosticInfo.h @@ -26,6 +26,7 @@ class Instruction; class Twine; class Value; +class DebugLoc; /// \brief Defines the different supported severity of a diagnostic. enum DiagnosticSeverity { @@ -44,6 +45,7 @@ DK_StackSize, DK_DebugMetadataVersion, DK_SampleProfile, + DK_OptimizationReport, DK_FirstPluginKind }; @@ -235,6 +237,52 @@ const Twine &Msg; }; +/// Diagnostic information for optimization reports. +class DiagnosticInfoOptimizationReport : public DiagnosticInfo { +public: + DiagnosticInfoOptimizationReport(const char *PassName, const Function &Fn, + const DebugLoc &DLoc, const Twine &Msg) + : DiagnosticInfo(DK_OptimizationReport, 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_OptimizationReport; + } + + /// 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 ":0:0". + const StringRef getLocationStr() 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: include/llvm/Transforms/IPO/PassManagerBuilder.h =================================================================== --- include/llvm/Transforms/IPO/PassManagerBuilder.h +++ include/llvm/Transforms/IPO/PassManagerBuilder.h @@ -16,6 +16,7 @@ #define LLVM_TRANSFORMS_IPO_PASSMANAGERBUILDER_H #include +#include namespace llvm { class TargetLibraryInfo; Index: lib/IR/DiagnosticInfo.cpp =================================================================== --- lib/IR/DiagnosticInfo.cpp +++ lib/IR/DiagnosticInfo.cpp @@ -14,11 +14,13 @@ #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 @@ -64,3 +66,24 @@ DP << getFileName() << ": "; DP << getMsg(); } + +bool DiagnosticInfoOptimizationReport::isLocationAvailable() const { + return getFunction().getParent()->getNamedMetadata("llvm.dbg.cu") != 0; +} + +const StringRef DiagnosticInfoOptimizationReport::getLocationStr() const { + StringRef Filename(""); + unsigned Line = 0; + unsigned Column = 0; + if (isLocationAvailable()) { + DILocation DIL(getDebugLoc().getAsMDNode(getFunction().getContext())); + Filename = DIL.getFilename(); + Line = DIL.getLineNumber(); + Column = DIL.getColumnNumber(); + } + return Twine(Filename + ":" + Twine(Line) + ":" + Twine(Column)).str(); +} + +void DiagnosticInfoOptimizationReport::print(DiagnosticPrinter &DP) const { + DP << getLocationStr() << ": " << getMsg(); +} Index: lib/Transforms/IPO/Inliner.cpp =================================================================== --- lib/Transforms/IPO/Inliner.cpp +++ lib/Transforms/IPO/Inliner.cpp @@ -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,13 @@ InlineHistoryID, InsertLifetime, DL)) continue; ++NumInlined; - + + // Report the inline decision. + DiagnosticInfoOptimizationReport Diag( + DEBUG_TYPE, *Caller, CS.getInstruction()->getDebugLoc(), + Twine(Callee->getName() + " inlined into " + Caller->getName())); + Caller->getContext().diagnose(Diag); + // 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()) {