/// -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 IsVerbose is
+ /// true, the message is considered verbose and will only be emitted when
+ /// verbose output is turned on.
void emitOptimizationRemarkMissed(const char *PassName, const DebugLoc &DLoc,
- const Value *V, const Twine &Msg);
+ const Value *V, const Twine &Msg,
+ bool IsVerbose = 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 IsVerbose = 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 IsVerbose = false) {
emitOptimizationRemarkMissed(PassName, Inst->getDebugLoc(),
- Inst->getParent(), Msg);
+ Inst->getParent(), Msg, IsVerbose);
}
/// Emit an optimization analysis remark message.
/// -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 IsVerbose is
+ /// true, the message is considered verbose and will only be emitted when
+ /// verbose output is turned on.
void emitOptimizationRemarkAnalysis(const char *PassName,
const DebugLoc &DLoc, const Value *V,
- const Twine &Msg);
+ const Twine &Msg, bool IsVerbose = 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 IsVerbose = 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 IsVerbose = false) {
emitOptimizationRemarkAnalysis(PassName, Inst->getDebugLoc(),
- Inst->getParent(), Msg);
+ Inst->getParent(), Msg, IsVerbose);
+ }
+
+ /// \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
+ /// IsVerbose is true, the message is considered verbose and will only be
+ /// emitted when verbose output is turned on.
+ void emitOptimizationRemarkMissedAndAnalysis(
+ const char *PassName, Instruction *Inst, const Twine &MsgForMissedRemark,
+ const Twine &MsgForAnalysisRemark, bool IsVerbose = false) {
+ emitOptimizationRemarkAnalysis(PassName, Inst, MsgForAnalysisRemark,
+ IsVerbose);
+ emitOptimizationRemarkMissed(PassName, Inst, MsgForMissedRemark, IsVerbose);
}
/// \brief Emit an optimization analysis remark related to floating-point
Optional<uint64_t> 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;
};
void OptimizationRemarkEmitter::emitOptimizationRemarkMissed(
const char *PassName, const DebugLoc &DLoc, const Value *V,
- const Twine &Msg) {
+ const Twine &Msg, bool IsVerbose) {
LLVMContext &Ctx = F->getContext();
- Ctx.diagnose(DiagnosticInfoOptimizationRemarkMissed(PassName, *F, DLoc, Msg,
- computeHotness(V)));
+ if (!IsVerbose || 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 IsVerbose) {
+ emitOptimizationRemarkMissed(PassName, L->getStartLoc(), L->getHeader(), Msg,
+ IsVerbose);
}
void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysis(
const char *PassName, const DebugLoc &DLoc, const Value *V,
- const Twine &Msg) {
+ const Twine &Msg, bool IsVerbose) {
LLVMContext &Ctx = F->getContext();
- Ctx.diagnose(DiagnosticInfoOptimizationRemarkAnalysis(PassName, *F, DLoc, Msg,
- computeHotness(V)));
+ if (!IsVerbose || 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 IsVerbose) {
emitOptimizationRemarkAnalysis(PassName, L->getStartLoc(), L->getHeader(),
- Msg);
+ Msg, IsVerbose);
}
void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysisFPCommute(
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<Value>(&I));
// 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));
}
-; 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)
ret float %conv
}
+declare i32 @fox()
+
; Function Attrs: nounwind uwtable
define i32 @bar(i32 %j) #2 {
entry:
%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" }