Index: include/llvm/Analysis/OptimizationDiagnosticInfo.h =================================================================== --- include/llvm/Analysis/OptimizationDiagnosticInfo.h +++ include/llvm/Analysis/OptimizationDiagnosticInfo.h @@ -91,21 +91,23 @@ /// -Rpass-missed= is given and the name matches the regular expression in /// -Rpass, then the remark will be emitted. \p DLoc is the debug location /// where the diagnostic is generated. \p V is the IR Value that identifies - /// the code region. \p Msg is the message string to use. + /// the code region. \p Msg is the message string to use. If \p Verbose is on + /// a large number of these remarks could be generated. void emitOptimizationRemarkMissed(const char *PassName, const DebugLoc &DLoc, - const Value *V, const Twine &Msg); + const Value *V, const Twine &Msg, + bool Verbose = false); /// \brief Same as above but derives the IR Value for the code region and the /// debug location from the Loop parameter \p L. void emitOptimizationRemarkMissed(const char *PassName, Loop *L, - const Twine &Msg); + const Twine &Msg, bool Verbose = false); /// \brief Same as above but derives the debug location and the code region /// from the debug location and the basic block of \p Inst, respectively. void emitOptimizationRemarkMissed(const char *PassName, Instruction *Inst, - const Twine &Msg) { + const Twine &Msg, bool Verbose = false) { emitOptimizationRemarkMissed(PassName, Inst->getDebugLoc(), - Inst->getParent(), Msg); + Inst->getParent(), Msg, Verbose); } /// Emit an optimization analysis remark message. @@ -114,22 +116,43 @@ /// -Rpass-analysis= is given and \p PassName matches the regular expression /// in -Rpass, then the remark will be emitted. \p DLoc is the debug location /// where the diagnostic is generated. \p V is the IR Value that identifies - /// the code region. \p Msg is the message string to use. + /// the code region. \p Msg is the message string to use. If \p Verbose is on + /// a large number of these remarks could be generated. void emitOptimizationRemarkAnalysis(const char *PassName, const DebugLoc &DLoc, const Value *V, - const Twine &Msg); + const Twine &Msg, bool Verbose = false); /// \brief Same as above but derives the IR Value for the code region and the /// debug location from the Loop parameter \p L. void emitOptimizationRemarkAnalysis(const char *PassName, Loop *L, - const Twine &Msg); + const Twine &Msg, bool Verbose = false); /// \brief Same as above but derives the debug location and the code region /// from the debug location and the basic block of \p Inst, respectively. void emitOptimizationRemarkAnalysis(const char *PassName, Instruction *Inst, - const Twine &Msg) { + const Twine &Msg, bool Verbose = false) { emitOptimizationRemarkAnalysis(PassName, Inst->getDebugLoc(), - Inst->getParent(), Msg); + Inst->getParent(), Msg, Verbose); + } + + /// \brief This variant allows specifying what should be emitted for missed + /// and analysis remarks in one call. + /// + /// \p PassName is the name of the pass emitting the message. If + /// -Rpass-missed= is given and \p PassName matches the regular expression, \p + /// MsgForMissedRemark is emitted. + /// + /// If -Rpass-analysis= is given and \p PassName matches the regular + /// expression, \p MsgForAnalysisRemark is emitted. + /// + /// The debug location and the code region is derived from \p Inst. If \p + /// Verbose is on a large number of these remarks could be generated. + void emitOptimizationRemarkMissedAndAnalysis( + const char *PassName, Instruction *Inst, const Twine &MsgForMissedRemark, + const Twine &MsgForAnalysisRemark, bool Verbose = false) { + emitOptimizationRemarkAnalysis(PassName, Inst, MsgForAnalysisRemark, + Verbose); + emitOptimizationRemarkMissed(PassName, Inst, MsgForMissedRemark, Verbose); } /// \brief Emit an optimization analysis remark related to floating-point @@ -173,6 +196,10 @@ Optional computeHotness(const Value *V); + /// \brief Only allow verbose messages if we know we're filtering by hotness + /// (BFI is only set in this case). + bool shouldEmitVerbose() { return BFI != nullptr; } + OptimizationRemarkEmitter(const OptimizationRemarkEmitter &) = delete; void operator=(const OptimizationRemarkEmitter &) = delete; }; Index: lib/Analysis/OptimizationDiagnosticInfo.cpp =================================================================== --- lib/Analysis/OptimizationDiagnosticInfo.cpp +++ lib/Analysis/OptimizationDiagnosticInfo.cpp @@ -68,29 +68,32 @@ void OptimizationRemarkEmitter::emitOptimizationRemarkMissed( const char *PassName, const DebugLoc &DLoc, const Value *V, - const Twine &Msg) { + const Twine &Msg, bool Verbose) { LLVMContext &Ctx = F->getContext(); - Ctx.diagnose(DiagnosticInfoOptimizationRemarkMissed(PassName, *F, DLoc, Msg, - computeHotness(V))); + if (!Verbose || shouldEmitVerbose()) + Ctx.diagnose(DiagnosticInfoOptimizationRemarkMissed(PassName, *F, DLoc, Msg, + computeHotness(V))); } void OptimizationRemarkEmitter::emitOptimizationRemarkMissed( - const char *PassName, Loop *L, const Twine &Msg) { - emitOptimizationRemarkMissed(PassName, L->getStartLoc(), L->getHeader(), Msg); + const char *PassName, Loop *L, const Twine &Msg, bool Verbose) { + emitOptimizationRemarkMissed(PassName, L->getStartLoc(), L->getHeader(), Msg, + Verbose); } void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysis( const char *PassName, const DebugLoc &DLoc, const Value *V, - const Twine &Msg) { + const Twine &Msg, bool Verbose) { LLVMContext &Ctx = F->getContext(); - Ctx.diagnose(DiagnosticInfoOptimizationRemarkAnalysis(PassName, *F, DLoc, Msg, - computeHotness(V))); + if (!Verbose || shouldEmitVerbose()) + Ctx.diagnose(DiagnosticInfoOptimizationRemarkAnalysis( + PassName, *F, DLoc, Msg, computeHotness(V))); } void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysis( - const char *PassName, Loop *L, const Twine &Msg) { + const char *PassName, Loop *L, const Twine &Msg, bool Verbose) { emitOptimizationRemarkAnalysis(PassName, L->getStartLoc(), L->getHeader(), - Msg); + Msg, Verbose); } void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysisFPCommute( Index: lib/Transforms/IPO/Inliner.cpp =================================================================== --- lib/Transforms/IPO/Inliner.cpp +++ lib/Transforms/IPO/Inliner.cpp @@ -435,9 +435,10 @@ for (CallGraphNode *Node : SCC) { Function *F = Node->getFunction(); - if (!F) + if (!F || F->isDeclaration()) continue; + OptimizationRemarkEmitter ORE(F); for (BasicBlock &BB : *F) for (Instruction &I : BB) { CallSite CS(cast(&I)); @@ -450,8 +451,16 @@ // it. If it is an indirect call, inlining may resolve it to be a // direct call, so we keep it. if (Function *Callee = CS.getCalledFunction()) - if (Callee->isDeclaration()) + if (Callee->isDeclaration()) { + ORE.emitOptimizationRemarkMissedAndAnalysis( + DEBUG_TYPE, &I, + Twine(Callee->getName()) + " will not be inlined into " + + CS.getCaller()->getName(), + Twine("definition of ") + Callee->getName() + + " is not available", + /*Verbose=*/true); continue; + } CallSites.push_back(std::make_pair(CS, -1)); } Index: test/Transforms/Inline/optimization-remarks.ll =================================================================== --- test/Transforms/Inline/optimization-remarks.ll +++ test/Transforms/Inline/optimization-remarks.ll @@ -1,5 +1,14 @@ -; RUN: opt < %s -inline -pass-remarks=inline -pass-remarks-missed=inline -pass-remarks-analysis=inline -S 2>&1 | FileCheck %s +; RUN: opt < %s -inline -pass-remarks=inline -pass-remarks-missed=inline \ +; RUN: -pass-remarks-analysis=inline -S 2>&1 | \ +; RUN: FileCheck -check-prefix=CHECK -check-prefix=NO_HOTNESS %s +; RUN: opt < %s -inline -pass-remarks=inline -pass-remarks-missed=inline \ +; RUN: -pass-remarks-analysis=inline -pass-remarks-with-hotness -S 2>&1 | \ +; RUN: FileCheck -check-prefix=CHECK -check-prefix=HOTNESS %s +; HOTNESS: definition of fox is not available +; HOTNESS: fox will not be inlined into bar +; NO_HOTNESS-NOT: definition of fox is not available +; NO_HOTNESS-NOT: fox will not be inlined into bar ; CHECK: foo should always be inlined (cost=always) ; CHECK: foo inlined into bar ; CHECK: foz should never be inlined (cost=never) @@ -32,6 +41,8 @@ ret float %conv } +declare i32 @fox() + ; Function Attrs: nounwind uwtable define i32 @bar(i32 %j) #2 { entry: @@ -48,7 +59,9 @@ %call2 = call float @foz(i32 %sub1, i32 %3) %mul = fmul float %conv, %call2 %conv3 = fptosi float %mul to i32 - ret i32 %conv3 + %call3 = call i32 @fox() + %add = add i32 %conv3, %call + ret i32 %add } 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" }