Index: llvm/trunk/include/llvm/IR/DiagnosticInfo.h =================================================================== --- llvm/trunk/include/llvm/IR/DiagnosticInfo.h +++ llvm/trunk/include/llvm/IR/DiagnosticInfo.h @@ -26,6 +26,7 @@ class DiagnosticPrinter; class Function; class Instruction; +class LLVMContextImpl; class Twine; class Value; class DebugLoc; @@ -48,6 +49,8 @@ DK_DebugMetadataVersion, DK_SampleProfile, DK_OptimizationRemark, + DK_OptimizationRemarkMissed, + DK_OptimizationRemarkAnalysis, DK_FirstPluginKind }; @@ -239,21 +242,21 @@ const Twine &Msg; }; -/// Diagnostic information for optimization remarks. -class DiagnosticInfoOptimizationRemark : public DiagnosticInfo { +/// Common features for diagnostics dealing with optimization remarks. +class DiagnosticInfoOptimizationRemarkBase : 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) {} + /// \p PassName is the name of the pass emitting this diagnostic. + /// \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. + DiagnosticInfoOptimizationRemarkBase(enum DiagnosticKind Kind, + const char *PassName, const Function &Fn, + const DebugLoc &DLoc, const Twine &Msg) + : DiagnosticInfo(Kind, DS_Remark), PassName(PassName), Fn(Fn), DLoc(DLoc), + Msg(Msg) {} /// \see DiagnosticInfo::print. void print(DiagnosticPrinter &DP) const override; @@ -263,6 +266,16 @@ return DI->getKind() == DK_OptimizationRemark; } + /// Return true if this optimization remark is enabled by one of + /// of the LLVM command line flags (-pass-remarks, -pass-remarks-missed, + /// or -pass-remarks-analysis). Note that this only handles the LLVM + /// flags. We cannot access Clang flags from here (they are handled + /// in BackendConsumer::OptimizationRemarkHandler). + /// + /// \p pImpl points to the current LLVM context. It is needed to query the + /// value of the command line flag associated with this remark. + virtual bool isEnabled(LLVMContextImpl *pImpl) const = 0; + /// Return true if location information is available for this diagnostic. bool isLocationAvailable() const; @@ -296,9 +309,119 @@ const Twine &Msg; }; +/// Diagnostic information for applied optimization remarks. +class DiagnosticInfoOptimizationRemark + : public DiagnosticInfoOptimizationRemarkBase { +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) + : DiagnosticInfoOptimizationRemarkBase(DK_OptimizationRemark, PassName, + Fn, DLoc, Msg) {} + + /// Hand rolled RTTI + static bool classof(const DiagnosticInfo *DI) { + return DI->getKind() == DK_OptimizationRemark; + } + + /// \see DiagnosticInfoOptimizationRemarkBase::isEnabled. + virtual bool isEnabled(LLVMContextImpl *pImpl) const override; +}; + +/// Diagnostic information for missed-optimization remarks. +class DiagnosticInfoOptimizationRemarkMissed + : public DiagnosticInfoOptimizationRemarkBase { +public: + /// \p PassName is the name of the pass emitting this diagnostic. If + /// this name matches the regular expression given in -Rpass-missed=, 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. + DiagnosticInfoOptimizationRemarkMissed(const char *PassName, + const Function &Fn, + const DebugLoc &DLoc, const Twine &Msg) + : DiagnosticInfoOptimizationRemarkBase(DK_OptimizationRemarkMissed, + PassName, Fn, DLoc, Msg) {} + + /// Hand rolled RTTI + static bool classof(const DiagnosticInfo *DI) { + return DI->getKind() == DK_OptimizationRemarkMissed; + } + + /// \see DiagnosticInfoOptimizationRemarkBase::isEnabled. + virtual bool isEnabled(LLVMContextImpl *pImpl) const override; +}; + +/// Diagnostic information for optimization analysis remarks. +class DiagnosticInfoOptimizationRemarkAnalysis + : public DiagnosticInfoOptimizationRemarkBase { +public: + /// \p PassName is the name of the pass emitting this diagnostic. If + /// this name matches the regular expression given in -Rpass-analysis=, 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. + DiagnosticInfoOptimizationRemarkAnalysis(const char *PassName, + const Function &Fn, + const DebugLoc &DLoc, + const Twine &Msg) + : DiagnosticInfoOptimizationRemarkBase(DK_OptimizationRemarkAnalysis, + PassName, Fn, DLoc, Msg) {} + + /// Hand rolled RTTI + static bool classof(const DiagnosticInfo *DI) { + return DI->getKind() == DK_OptimizationRemarkAnalysis; + } + + /// \see DiagnosticInfoOptimizationRemarkBase::isEnabled. + virtual bool isEnabled(LLVMContextImpl *pImpl) const override; +}; + // Create wrappers for C Binding types (see CBindingWrapping.h). DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DiagnosticInfo, LLVMDiagnosticInfoRef) +/// Emit an optimization-applied 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(LLVMContext &Ctx, const char *PassName, + const Function &Fn, const DebugLoc &DLoc, + const Twine &Msg); + +/// Emit an optimization-missed message. \p PassName is the name of the +/// pass emitting the message. If -Rpass-missed= 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 emitOptimizationRemarkMissed(LLVMContext &Ctx, const char *PassName, + const Function &Fn, const DebugLoc &DLoc, + const Twine &Msg); + +/// Emit an optimization analysis remark message. \p PassName is the name of +/// the pass emitting the message. If -Rpass-analysis= 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 emitOptimizationRemarkAnalysis(LLVMContext &Ctx, const char *PassName, + const Function &Fn, const DebugLoc &DLoc, + const Twine &Msg); + } // End namespace llvm #endif Index: llvm/trunk/include/llvm/IR/LLVMContext.h =================================================================== --- llvm/trunk/include/llvm/IR/LLVMContext.h +++ llvm/trunk/include/llvm/IR/LLVMContext.h @@ -157,15 +157,6 @@ 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: llvm/trunk/lib/IR/DiagnosticInfo.cpp =================================================================== --- llvm/trunk/lib/IR/DiagnosticInfo.cpp +++ llvm/trunk/lib/IR/DiagnosticInfo.cpp @@ -12,6 +12,7 @@ // Diagnostics reporting is still done as part of the LLVMContext. //===----------------------------------------------------------------------===// +#include "LLVMContextImpl.h" #include "llvm/ADT/Twine.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DebugInfo.h" @@ -67,20 +68,20 @@ DP << getMsg(); } -bool DiagnosticInfoOptimizationRemark::isLocationAvailable() const { +bool DiagnosticInfoOptimizationRemarkBase::isLocationAvailable() const { return getFunction().getParent()->getNamedMetadata("llvm.dbg.cu") != nullptr; } -void DiagnosticInfoOptimizationRemark::getLocation(StringRef *Filename, - unsigned *Line, - unsigned *Column) const { +void DiagnosticInfoOptimizationRemarkBase::getLocation(StringRef *Filename, + unsigned *Line, + unsigned *Column) const { DILocation DIL(getDebugLoc().getAsMDNode(getFunction().getContext())); *Filename = DIL.getFilename(); *Line = DIL.getLineNumber(); *Column = DIL.getColumnNumber(); } -const std::string DiagnosticInfoOptimizationRemark::getLocationStr() const { +const std::string DiagnosticInfoOptimizationRemarkBase::getLocationStr() const { StringRef Filename(""); unsigned Line = 0; unsigned Column = 0; @@ -89,6 +90,43 @@ return Twine(Filename + ":" + Twine(Line) + ":" + Twine(Column)).str(); } -void DiagnosticInfoOptimizationRemark::print(DiagnosticPrinter &DP) const { +void DiagnosticInfoOptimizationRemarkBase::print(DiagnosticPrinter &DP) const { DP << getLocationStr() << ": " << getMsg(); } + +bool +DiagnosticInfoOptimizationRemark::isEnabled(LLVMContextImpl *pImpl) const { + return pImpl->optimizationRemarkEnabledFor(this); +} + +bool DiagnosticInfoOptimizationRemarkMissed::isEnabled( + LLVMContextImpl *pImpl) const { + return pImpl->optimizationRemarkEnabledFor(this); +} + +bool DiagnosticInfoOptimizationRemarkAnalysis::isEnabled( + LLVMContextImpl *pImpl) const { + return pImpl->optimizationRemarkEnabledFor(this); +} + +void llvm::emitOptimizationRemark(LLVMContext &Ctx, const char *PassName, + const Function &Fn, const DebugLoc &DLoc, + const Twine &Msg) { + Ctx.diagnose(DiagnosticInfoOptimizationRemark(PassName, Fn, DLoc, Msg)); +} + +void llvm::emitOptimizationRemarkMissed(LLVMContext &Ctx, const char *PassName, + const Function &Fn, + const DebugLoc &DLoc, + const Twine &Msg) { + Ctx.diagnose(DiagnosticInfoOptimizationRemarkMissed(PassName, Fn, DLoc, Msg)); +} + +void llvm::emitOptimizationRemarkAnalysis(LLVMContext &Ctx, + const char *PassName, + const Function &Fn, + const DebugLoc &DLoc, + const Twine &Msg) { + Ctx.diagnose( + DiagnosticInfoOptimizationRemarkAnalysis(PassName, Fn, DLoc, Msg)); +} Index: llvm/trunk/lib/IR/LLVMContext.cpp =================================================================== --- llvm/trunk/lib/IR/LLVMContext.cpp +++ llvm/trunk/lib/IR/LLVMContext.cpp @@ -142,14 +142,26 @@ return; } - // Optimization remarks are selective. They need to check whether - // the regexp pattern, passed via -pass-remarks, matches the name - // of the pass that is emitting the diagnostic. If there is no match, - // ignore the diagnostic and return. - if (DI.getKind() == llvm::DK_OptimizationRemark && - !pImpl->optimizationRemarksEnabledFor( - cast(DI).getPassName())) - return; + // Optimization remarks are selective. They need to check whether the regexp + // pattern, passed via one of the -pass-remarks* flags, matches the name of + // the pass that is emitting the diagnostic. If there is no match, ignore the + // diagnostic and return. + switch (DI.getKind()) { + case llvm::DK_OptimizationRemark: + if (!cast(DI).isEnabled(pImpl)) + return; + break; + case llvm::DK_OptimizationRemarkMissed: + if (!cast(DI).isEnabled(pImpl)) + return; + break; + case llvm::DK_OptimizationRemarkAnalysis: + if (!cast(DI).isEnabled(pImpl)) + return; + break; + default: + break; + } // Otherwise, print the message with a prefix based on the severity. std::string MsgStorage; @@ -177,13 +189,6 @@ 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: llvm/trunk/lib/IR/LLVMContextImpl.h =================================================================== --- llvm/trunk/lib/IR/LLVMContextImpl.h +++ llvm/trunk/lib/IR/LLVMContextImpl.h @@ -37,6 +37,9 @@ class ConstantInt; class ConstantFP; +class DiagnosticInfoOptimizationRemark; +class DiagnosticInfoOptimizationRemarkMissed; +class DiagnosticInfoOptimizationRemarkAnalysis; class LLVMContext; class Type; class Value; @@ -373,7 +376,12 @@ /// \brief Return true if the given pass name should emit optimization /// remarks. - bool optimizationRemarksEnabledFor(const char *PassName) const; + bool optimizationRemarkEnabledFor( + const DiagnosticInfoOptimizationRemark *DI) const; + bool optimizationRemarkEnabledFor( + const DiagnosticInfoOptimizationRemarkMissed *DI) const; + bool optimizationRemarkEnabledFor( + const DiagnosticInfoOptimizationRemarkAnalysis *DI) const; int getOrAddScopeRecordIdxEntry(MDNode *N, int ExistingIdx); int getOrAddScopeInlinedAtIdxEntry(MDNode *Scope, MDNode *IA,int ExistingIdx); Index: llvm/trunk/lib/IR/LLVMContextImpl.cpp =================================================================== --- llvm/trunk/lib/IR/LLVMContextImpl.cpp +++ llvm/trunk/lib/IR/LLVMContextImpl.cpp @@ -14,6 +14,7 @@ #include "LLVMContextImpl.h" #include "llvm/ADT/STLExtras.h" #include "llvm/IR/Attributes.h" +#include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/Module.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Regex.h" @@ -48,20 +49,20 @@ namespace { -/// \brief Regular expression corresponding to the value given in the -/// command line flag -pass-remarks. Passes whose name matches this -/// regexp will emit a diagnostic when calling -/// LLVMContext::emitOptimizationRemark. -static Regex *OptimizationRemarkPattern = nullptr; - +/// \brief Regular expression corresponding to the value given in one of the +/// -pass-remarks* command line flags. Passes whose name matches this regexp +/// will emit a diagnostic when calling the associated diagnostic function +/// (emitOptimizationRemark, emitOptimizationRemarkMissed or +/// emitOptimizationRemarkAnalysis). struct PassRemarksOpt { - void operator=(const std::string &Val) const { + std::shared_ptr Pattern; + + void operator=(const std::string &Val) { // Create a regexp object to match pass names for emitOptimizationRemark. if (!Val.empty()) { - delete OptimizationRemarkPattern; - OptimizationRemarkPattern = new Regex(Val); + Pattern = std::make_shared(Val); std::string RegexError; - if (!OptimizationRemarkPattern->isValid(RegexError)) + if (!Pattern->isValid(RegexError)) report_fatal_error("Invalid regular expression '" + Val + "' in -pass-remarks: " + RegexError, false); @@ -70,31 +71,62 @@ }; static PassRemarksOpt PassRemarksOptLoc; +static PassRemarksOpt PassRemarksMissedOptLoc; +static PassRemarksOpt PassRemarksAnalysisOptLoc; // -pass-remarks -// Command line flag to enable LLVMContext::emitOptimizationRemark() -// and LLVMContext::emitOptimizationNote() calls. +// Command line flag to enable emitOptimizationRemark() static cl::opt> PassRemarks("pass-remarks", cl::value_desc("pattern"), cl::desc("Enable optimization remarks from passes whose name match " "the given regular expression"), cl::Hidden, cl::location(PassRemarksOptLoc), cl::ValueRequired, cl::ZeroOrMore); + +// -pass-remarks-missed +// Command line flag to enable emitOptimizationRemarkMissed() +static cl::opt> PassRemarksMissed( + "pass-remarks-missed", cl::value_desc("pattern"), + cl::desc("Enable missed optimization remarks from passes whose name match " + "the given regular expression"), + cl::Hidden, cl::location(PassRemarksMissedOptLoc), cl::ValueRequired, + cl::ZeroOrMore); + +// -pass-remarks-analysis +// Command line flag to enable emitOptimizationRemarkAnalysis() +static cl::opt> +PassRemarksAnalysis( + "pass-remarks-analysis", cl::value_desc("pattern"), + cl::desc( + "Enable optimization analysis remarks from passes whose name match " + "the given regular expression"), + cl::Hidden, cl::location(PassRemarksAnalysisOptLoc), cl::ValueRequired, + cl::ZeroOrMore); } -bool -LLVMContextImpl::optimizationRemarksEnabledFor(const char *PassName) const { - return OptimizationRemarkPattern && - OptimizationRemarkPattern->match(PassName); +bool LLVMContextImpl::optimizationRemarkEnabledFor( + const DiagnosticInfoOptimizationRemark *DI) const { + return PassRemarksOptLoc.Pattern && + PassRemarksOptLoc.Pattern->match(DI->getPassName()); } +bool LLVMContextImpl::optimizationRemarkEnabledFor( + const DiagnosticInfoOptimizationRemarkMissed *DI) const { + return PassRemarksMissedOptLoc.Pattern && + PassRemarksMissedOptLoc.Pattern->match(DI->getPassName()); +} + +bool LLVMContextImpl::optimizationRemarkEnabledFor( + const DiagnosticInfoOptimizationRemarkAnalysis *DI) const { + return PassRemarksAnalysisOptLoc.Pattern && + PassRemarksAnalysisOptLoc.Pattern->match(DI->getPassName()); +} namespace { struct DropReferences { // Takes the value_type of a ConstantUniqueMap's internal map, whose 'second' // is a Constant*. - template - void operator()(const PairT &P) { + template void operator()(const PairT &P) { P.second->dropAllReferences(); } }; Index: llvm/trunk/lib/Transforms/IPO/Inliner.cpp =================================================================== --- llvm/trunk/lib/Transforms/IPO/Inliner.cpp +++ llvm/trunk/lib/Transforms/IPO/Inliner.cpp @@ -301,6 +301,13 @@ return thres; } +static void emitAnalysis(CallSite CS, const Twine &Msg) { + Function *Caller = CS.getCaller(); + LLVMContext &Ctx = Caller->getContext(); + DebugLoc DLoc = CS.getInstruction()->getDebugLoc(); + emitOptimizationRemarkAnalysis(Ctx, DEBUG_TYPE, *Caller, DLoc, Msg); +} + /// shouldInline - Return true if the inliner should attempt to inline /// at the given CallSite. bool Inliner::shouldInline(CallSite CS) { @@ -309,12 +316,16 @@ if (IC.isAlways()) { DEBUG(dbgs() << " Inlining: cost=always" << ", Call: " << *CS.getInstruction() << "\n"); + emitAnalysis(CS, Twine(CS.getCalledFunction()->getName()) + + " should always be inlined (cost=always)"); return true; } if (IC.isNever()) { DEBUG(dbgs() << " NOT Inlining: cost=never" << ", Call: " << *CS.getInstruction() << "\n"); + emitAnalysis(CS, Twine(CS.getCalledFunction()->getName() + + " should never be inlined (cost=never)")); return false; } @@ -323,6 +334,10 @@ DEBUG(dbgs() << " NOT Inlining: cost=" << IC.getCost() << ", thres=" << (IC.getCostDelta() + IC.getCost()) << ", Call: " << *CS.getInstruction() << "\n"); + emitAnalysis(CS, Twine(CS.getCalledFunction()->getName() + + " too costly to inline (cost=") + + Twine(IC.getCost()) + ", threshold=" + + Twine(IC.getCostDelta() + IC.getCost()) + ")"); return false; } @@ -390,6 +405,11 @@ DEBUG(dbgs() << " NOT Inlining: " << *CS.getInstruction() << " Cost = " << IC.getCost() << ", outer Cost = " << TotalSecondaryCost << '\n'); + emitAnalysis( + CS, Twine("Not inlining. Cost of inlining " + + CS.getCalledFunction()->getName() + + " increases the cost of inlining " + + CS.getCaller()->getName() + " in other contexts")); return false; } } @@ -397,6 +417,10 @@ DEBUG(dbgs() << " Inlining: cost=" << IC.getCost() << ", thres=" << (IC.getCostDelta() + IC.getCost()) << ", Call: " << *CS.getInstruction() << '\n'); + emitAnalysis( + CS, CS.getCalledFunction()->getName() + Twine(" can be inlined into ") + + CS.getCaller()->getName() + " with cost=" + Twine(IC.getCost()) + + " (threshold=" + Twine(IC.getCostDelta() + IC.getCost()) + ")"); return true; } @@ -518,24 +542,35 @@ InlineHistoryIncludes(Callee, InlineHistoryID, InlineHistory)) continue; - - // If the policy determines that we should inline this function, - // try to do so. - if (!shouldInline(CS)) - continue; + LLVMContext &CallerCtx = Caller->getContext(); // Get DebugLoc to report. CS will be invalid after Inliner. DebugLoc DLoc = CS.getInstruction()->getDebugLoc(); + // If the policy determines that we should inline this function, + // try to do so. + if (!shouldInline(CS)) { + emitOptimizationRemarkMissed(CallerCtx, DEBUG_TYPE, *Caller, DLoc, + Twine(Callee->getName() + + " will not be inlined into " + + Caller->getName())); + continue; + } + // Attempt to inline the function. if (!InlineCallIfPossible(CS, InlineInfo, InlinedArrayAllocas, - InlineHistoryID, InsertLifetime, DL)) + InlineHistoryID, InsertLifetime, DL)) { + emitOptimizationRemarkMissed(CallerCtx, DEBUG_TYPE, *Caller, DLoc, + Twine(Callee->getName() + + " will not be inlined into " + + Caller->getName())); continue; + } ++NumInlined; // Report the inline decision. - Caller->getContext().emitOptimizationRemark( - DEBUG_TYPE, *Caller, DLoc, + emitOptimizationRemark( + CallerCtx, DEBUG_TYPE, *Caller, DLoc, Twine(Callee->getName() + " inlined into " + Caller->getName())); // If inlining this function gave us any new call sites, throw them Index: llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp =================================================================== --- llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp +++ llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp @@ -64,6 +64,7 @@ #include "llvm/IR/CallSite.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" @@ -318,8 +319,8 @@ break; } if (SafeToTail) { - F.getContext().emitOptimizationRemark( - "tailcallelim", F, CI->getDebugLoc(), + emitOptimizationRemark( + F.getContext(), "tailcallelim", F, CI->getDebugLoc(), "marked this readnone call a tail call candidate"); CI->setTailCall(); Modified = true; @@ -365,9 +366,9 @@ if (Visited[CI->getParent()] != ESCAPED) { // If the escape point was part way through the block, calls after the // escape point wouldn't have been put into DeferredTails. - F.getContext().emitOptimizationRemark( - "tailcallelim", F, CI->getDebugLoc(), - "marked this call a tail call candidate"); + emitOptimizationRemark(F.getContext(), "tailcallelim", F, + CI->getDebugLoc(), + "marked this call a tail call candidate"); CI->setTailCall(); Modified = true; } else { @@ -678,9 +679,8 @@ BasicBlock *BB = Ret->getParent(); Function *F = BB->getParent(); - F->getContext().emitOptimizationRemark( - "tailcallelim", *F, CI->getDebugLoc(), - "transforming tail recursion to loop"); + emitOptimizationRemark(F->getContext(), "tailcallelim", *F, CI->getDebugLoc(), + "transforming tail recursion to loop"); // OK! We can transform this tail call. If this is the first one found, // create the new entry block, allowing us to branch back to the old entry. Index: llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp =================================================================== --- llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp +++ llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp @@ -24,6 +24,7 @@ #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Dominators.h" +#include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/LLVMContext.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -237,9 +238,9 @@ if (CompletelyUnroll) { DEBUG(dbgs() << "COMPLETELY UNROLLING loop %" << Header->getName() << " with trip count " << TripCount << "!\n"); - Ctx.emitOptimizationRemark(DEBUG_TYPE, *F, LoopLoc, - Twine("completely unrolled loop with ") + - Twine(TripCount) + " iterations"); + emitOptimizationRemark(Ctx, DEBUG_TYPE, *F, LoopLoc, + Twine("completely unrolled loop with ") + + Twine(TripCount) + " iterations"); } else { DEBUG(dbgs() << "UNROLLING loop %" << Header->getName() << " by " << Count); @@ -255,7 +256,7 @@ DiagMsg.concat(" with run-time trip count"); } DEBUG(dbgs() << "!\n"); - Ctx.emitOptimizationRemark(DEBUG_TYPE, *F, LoopLoc, DiagMsg); + emitOptimizationRemark(Ctx, DEBUG_TYPE, *F, LoopLoc, DiagMsg); } bool ContinueOnTrue = L->contains(BI->getSuccessor(0)); Index: llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp =================================================================== --- llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -20,6 +20,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/IntrinsicInst.h" @@ -789,9 +790,9 @@ uint64_t LenTrue = GetStringLength(SI->getTrueValue()); uint64_t LenFalse = GetStringLength(SI->getFalseValue()); if (LenTrue && LenFalse) { - Context->emitOptimizationRemark( - "simplify-libcalls", *Caller, SI->getDebugLoc(), - "folded strlen(select) to select of constants"); + emitOptimizationRemark(*Context, "simplify-libcalls", *Caller, + SI->getDebugLoc(), + "folded strlen(select) to select of constants"); return B.CreateSelect(SI->getCondition(), ConstantInt::get(CI->getType(), LenTrue-1), ConstantInt::get(CI->getType(), LenFalse-1)); Index: llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp =================================================================== --- llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp +++ llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -67,6 +67,7 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" @@ -1213,10 +1214,10 @@ DEBUG(dbgs() << "LV: Trying to at least unroll the loops.\n"); // Report the unrolling decision. - F->getContext().emitOptimizationRemark( - DEBUG_TYPE, *F, L->getStartLoc(), - Twine("unrolled with interleaving factor " + Twine(UF) + - " (vectorization not beneficial)")); + emitOptimizationRemark(F->getContext(), DEBUG_TYPE, *F, L->getStartLoc(), + Twine("unrolled with interleaving factor " + + Twine(UF) + + " (vectorization not beneficial)")); // We decided not to vectorize, but we may want to unroll. InnerLoopUnroller Unroller(L, SE, LI, DT, DL, TLI, UF); @@ -1228,8 +1229,8 @@ ++LoopsVectorized; // Report the vectorization decision. - F->getContext().emitOptimizationRemark( - DEBUG_TYPE, *F, L->getStartLoc(), + emitOptimizationRemark( + F->getContext(), DEBUG_TYPE, *F, L->getStartLoc(), Twine("vectorized loop (vectorization factor: ") + Twine(VF.Width) + ", unrolling interleave factor: " + Twine(UF) + ")"); } Index: llvm/trunk/test/Transforms/Inline/optimization-remarks.ll =================================================================== --- llvm/trunk/test/Transforms/Inline/optimization-remarks.ll +++ llvm/trunk/test/Transforms/Inline/optimization-remarks.ll @@ -0,0 +1,60 @@ +; RUN: opt < %s -inline -pass-remarks=inline -pass-remarks-missed=inline -pass-remarks-analysis=inline -S 2>&1 | FileCheck %s + +; CHECK: foo should always be inlined (cost=always) +; CHECK: foo inlined into bar +; CHECK: foz should never be inlined (cost=never) +; CHECK: foz will not be inlined into bar + +; Function Attrs: alwaysinline nounwind uwtable +define i32 @foo(i32 %x, i32 %y) #0 { +entry: + %x.addr = alloca i32, align 4 + %y.addr = alloca i32, align 4 + store i32 %x, i32* %x.addr, align 4 + store i32 %y, i32* %y.addr, align 4 + %0 = load i32* %x.addr, align 4 + %1 = load i32* %y.addr, align 4 + %add = add nsw i32 %0, %1 + ret i32 %add +} + +; Function Attrs: noinline nounwind uwtable +define float @foz(i32 %x, i32 %y) #1 { +entry: + %x.addr = alloca i32, align 4 + %y.addr = alloca i32, align 4 + store i32 %x, i32* %x.addr, align 4 + store i32 %y, i32* %y.addr, align 4 + %0 = load i32* %x.addr, align 4 + %1 = load i32* %y.addr, align 4 + %mul = mul nsw i32 %0, %1 + %conv = sitofp i32 %mul to float + ret float %conv +} + +; Function Attrs: nounwind uwtable +define i32 @bar(i32 %j) #2 { +entry: + %j.addr = alloca i32, align 4 + store i32 %j, i32* %j.addr, align 4 + %0 = load i32* %j.addr, align 4 + %1 = load i32* %j.addr, align 4 + %sub = sub nsw i32 %1, 2 + %call = call i32 @foo(i32 %0, i32 %sub) + %conv = sitofp i32 %call to float + %2 = load i32* %j.addr, align 4 + %sub1 = sub nsw i32 %2, 2 + %3 = load i32* %j.addr, align 4 + %call2 = call float @foz(i32 %sub1, i32 %3) + %mul = fmul float %conv, %call2 + %conv3 = fptosi float %mul to i32 + ret i32 %conv3 +} + +attributes #0 = { alwaysinline nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { noinline nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #2 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } + +!llvm.ident = !{!0} + +!0 = metadata !{metadata !"clang version 3.5.0 "}