Index: include/llvm/Analysis/OptimizationDiagnosticInfo.h =================================================================== --- include/llvm/Analysis/OptimizationDiagnosticInfo.h +++ include/llvm/Analysis/OptimizationDiagnosticInfo.h @@ -132,6 +132,24 @@ Inst->getParent(), Msg); } + /// \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. + void emitOptimizationRemarkMissedAndAnalysis( + const char *PassName, Instruction *Inst, const Twine &MsgForMissedRemark, + const Twine &MsgForAnalysisRemark) { + emitOptimizationRemarkAnalysis(PassName, Inst, MsgForAnalysisRemark); + emitOptimizationRemarkMissed(PassName, Inst, MsgForMissedRemark); + } + /// \brief Emit an optimization analysis remark related to floating-point /// non-commutativity. /// 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,15 @@ // 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"); 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,7 @@ ; RUN: opt < %s -inline -pass-remarks=inline -pass-remarks-missed=inline -pass-remarks-analysis=inline -S 2>&1 | FileCheck %s +; CHECK: definition of fox is not available +; CHECK: 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 +34,8 @@ ret float %conv } +declare i32 @fox() + ; Function Attrs: nounwind uwtable define i32 @bar(i32 %j) #2 { entry: @@ -48,7 +52,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" }