forked from OSchip/llvm-project
[Inliner] Port all opt remarks to new streaming API
llvm-svn: 282559
This commit is contained in:
parent
0427909434
commit
c507ac96f5
|
@ -497,6 +497,14 @@ public:
|
|||
: DiagnosticInfoOptimizationBase(DK_OptimizationRemark, DS_Remark,
|
||||
PassName, Fn, DLoc, Msg, Hotness) {}
|
||||
|
||||
/// \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 RemarkName is a textual identifier for the remark. \p
|
||||
/// DLoc is the debug location and \p CodeRegion is the region that the
|
||||
/// optimization operates on (currently on block is supported).
|
||||
OptimizationRemark(const char *PassName, StringRef RemarkName,
|
||||
const DebugLoc &DLoc, Value *CodeRegion);
|
||||
|
||||
static bool classof(const DiagnosticInfo *DI) {
|
||||
return DI->getKind() == DK_OptimizationRemark;
|
||||
}
|
||||
|
@ -525,7 +533,13 @@ 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 RemarkName is a textual identifier for the
|
||||
/// remark. \p Inst is the instruction that the optimization operates on.
|
||||
/// remark. \p DLoc is the debug location and \p CodeRegion is the region
|
||||
/// that the optimization operates on (currently on block is supported).
|
||||
OptimizationRemarkMissed(const char *PassName, StringRef RemarkName,
|
||||
const DebugLoc &DLoc, Value *CodeRegion);
|
||||
|
||||
/// \brief Same as above but \p Inst is used to derive code region and debug
|
||||
/// location.
|
||||
OptimizationRemarkMissed(const char *PassName, StringRef RemarkName,
|
||||
Instruction *Inst);
|
||||
|
||||
|
@ -554,6 +568,13 @@ public:
|
|||
: DiagnosticInfoOptimizationBase(DK_OptimizationRemarkAnalysis, DS_Remark,
|
||||
PassName, Fn, DLoc, Msg, Hotness) {}
|
||||
|
||||
/// \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 RemarkName is a textual identifier for the
|
||||
/// remark. \p Inst is the instruction that the optimization operates on.
|
||||
OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
|
||||
Instruction *Inst);
|
||||
|
||||
static bool classof(const DiagnosticInfo *DI) {
|
||||
return DI->getKind() == DK_OptimizationRemarkAnalysis;
|
||||
}
|
||||
|
|
|
@ -59,7 +59,13 @@ template <> struct MappingTraits<DiagnosticInfoOptimizationBase *> {
|
|||
static void mapping(IO &io, DiagnosticInfoOptimizationBase *&OptDiag) {
|
||||
assert(io.outputting() && "input not yet implemented");
|
||||
|
||||
if (io.mapTag("!Missed", OptDiag->getKind() == DK_OptimizationRemarkMissed))
|
||||
if (io.mapTag("!Passed", OptDiag->getKind() == DK_OptimizationRemark))
|
||||
;
|
||||
else if (io.mapTag("!Missed",
|
||||
OptDiag->getKind() == DK_OptimizationRemarkMissed))
|
||||
;
|
||||
else if (io.mapTag("!Analysis",
|
||||
OptDiag->getKind() == DK_OptimizationRemarkAnalysis))
|
||||
;
|
||||
else
|
||||
llvm_unreachable("todo");
|
||||
|
|
|
@ -180,11 +180,26 @@ void DiagnosticInfoOptimizationBase::print(DiagnosticPrinter &DP) const {
|
|||
DP << " (hotness: " << *Hotness << ")";
|
||||
}
|
||||
|
||||
OptimizationRemark::OptimizationRemark(const char *PassName,
|
||||
StringRef RemarkName,
|
||||
const DebugLoc &DLoc, Value *CodeRegion)
|
||||
: DiagnosticInfoOptimizationBase(
|
||||
DK_OptimizationRemark, DS_Remark, PassName, RemarkName,
|
||||
*cast<BasicBlock>(CodeRegion)->getParent(), DLoc, CodeRegion) {}
|
||||
|
||||
bool OptimizationRemark::isEnabled() const {
|
||||
return PassRemarksOptLoc.Pattern &&
|
||||
PassRemarksOptLoc.Pattern->match(getPassName());
|
||||
}
|
||||
|
||||
OptimizationRemarkMissed::OptimizationRemarkMissed(const char *PassName,
|
||||
StringRef RemarkName,
|
||||
const DebugLoc &DLoc,
|
||||
Value *CodeRegion)
|
||||
: DiagnosticInfoOptimizationBase(
|
||||
DK_OptimizationRemarkMissed, DS_Remark, PassName, RemarkName,
|
||||
*cast<BasicBlock>(CodeRegion)->getParent(), DLoc, CodeRegion) {}
|
||||
|
||||
OptimizationRemarkMissed::OptimizationRemarkMissed(const char *PassName,
|
||||
StringRef RemarkName,
|
||||
Instruction *Inst)
|
||||
|
@ -198,6 +213,14 @@ bool OptimizationRemarkMissed::isEnabled() const {
|
|||
PassRemarksMissedOptLoc.Pattern->match(getPassName());
|
||||
}
|
||||
|
||||
OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(const char *PassName,
|
||||
StringRef RemarkName,
|
||||
Instruction *Inst)
|
||||
: DiagnosticInfoOptimizationBase(DK_OptimizationRemarkAnalysis, DS_Remark,
|
||||
PassName, RemarkName,
|
||||
*Inst->getParent()->getParent(),
|
||||
Inst->getDebugLoc(), Inst->getParent()) {}
|
||||
|
||||
bool OptimizationRemarkAnalysis::isEnabled() const {
|
||||
return shouldAlwaysPrint() ||
|
||||
(PassRemarksAnalysisOptLoc.Pattern &&
|
||||
|
|
|
@ -255,11 +255,6 @@ static bool InlineCallIfPossible(
|
|||
return true;
|
||||
}
|
||||
|
||||
static void emitAnalysis(CallSite CS, OptimizationRemarkEmitter &ORE,
|
||||
const Twine &Msg) {
|
||||
ORE.emitOptimizationRemarkAnalysis(DEBUG_TYPE, CS.getInstruction(), Msg);
|
||||
}
|
||||
|
||||
/// Return true if inlining of CS can block the caller from being
|
||||
/// inlined which is proved to be more beneficial. \p IC is the
|
||||
/// estimated inline cost associated with callsite \p CS.
|
||||
|
@ -341,21 +336,26 @@ shouldBeDeferred(Function *Caller, CallSite CS, InlineCost IC,
|
|||
static bool shouldInline(CallSite CS,
|
||||
function_ref<InlineCost(CallSite CS)> GetInlineCost,
|
||||
OptimizationRemarkEmitter &ORE) {
|
||||
using namespace ore;
|
||||
InlineCost IC = GetInlineCost(CS);
|
||||
Instruction *Call = CS.getInstruction();
|
||||
Function *Callee = CS.getCalledFunction();
|
||||
|
||||
if (IC.isAlways()) {
|
||||
DEBUG(dbgs() << " Inlining: cost=always"
|
||||
<< ", Call: " << *CS.getInstruction() << "\n");
|
||||
emitAnalysis(CS, ORE, Twine(CS.getCalledFunction()->getName()) +
|
||||
" should always be inlined (cost=always)");
|
||||
ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "AlwaysInline", Call)
|
||||
<< NV("Callee", Callee)
|
||||
<< " should always be inlined (cost=always)");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IC.isNever()) {
|
||||
DEBUG(dbgs() << " NOT Inlining: cost=never"
|
||||
<< ", Call: " << *CS.getInstruction() << "\n");
|
||||
emitAnalysis(CS, ORE, Twine(CS.getCalledFunction()->getName() +
|
||||
" should never be inlined (cost=never)"));
|
||||
ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "NeverInline", Call)
|
||||
<< NV("Callee", Callee)
|
||||
<< " should never be inlined (cost=never)");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -364,10 +364,10 @@ static bool shouldInline(CallSite CS,
|
|||
DEBUG(dbgs() << " NOT Inlining: cost=" << IC.getCost()
|
||||
<< ", thres=" << (IC.getCostDelta() + IC.getCost())
|
||||
<< ", Call: " << *CS.getInstruction() << "\n");
|
||||
emitAnalysis(CS, ORE, Twine(CS.getCalledFunction()->getName() +
|
||||
" too costly to inline (cost=") +
|
||||
Twine(IC.getCost()) + ", threshold=" +
|
||||
Twine(IC.getCostDelta() + IC.getCost()) + ")");
|
||||
ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "TooCostly", Call)
|
||||
<< NV("Callee", Callee) << " too costly to inline (cost="
|
||||
<< NV("Cost", IC.getCost()) << ", threshold="
|
||||
<< NV("Threshold", IC.getCostDelta() + IC.getCost()) << ")");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -376,22 +376,22 @@ static bool shouldInline(CallSite CS,
|
|||
DEBUG(dbgs() << " NOT Inlining: " << *CS.getInstruction()
|
||||
<< " Cost = " << IC.getCost()
|
||||
<< ", outer Cost = " << TotalSecondaryCost << '\n');
|
||||
emitAnalysis(CS, ORE,
|
||||
Twine("Not inlining. Cost of inlining " +
|
||||
CS.getCalledFunction()->getName() +
|
||||
" increases the cost of inlining " +
|
||||
CS.getCaller()->getName() + " in other contexts"));
|
||||
ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE,
|
||||
"IncreaseCostInOtherContexts", Call)
|
||||
<< "Not inlining. Cost of inlining " << NV("Callee", Callee)
|
||||
<< " increases the cost of inlining " << NV("Caller", Caller)
|
||||
<< " in other contexts");
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG(dbgs() << " Inlining: cost=" << IC.getCost()
|
||||
<< ", thres=" << (IC.getCostDelta() + IC.getCost())
|
||||
<< ", Call: " << *CS.getInstruction() << '\n');
|
||||
emitAnalysis(CS, ORE, CS.getCalledFunction()->getName() +
|
||||
Twine(" can be inlined into ") +
|
||||
CS.getCaller()->getName() + " with cost=" +
|
||||
Twine(IC.getCost()) + " (threshold=" +
|
||||
Twine(IC.getCostDelta() + IC.getCost()) + ")");
|
||||
ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "CanBeInlined", Call)
|
||||
<< NV("Callee", Callee) << " can be inlined into "
|
||||
<< NV("Caller", Caller) << " with cost=" << NV("Cost", IC.getCost())
|
||||
<< " (threshold="
|
||||
<< NV("Threshold", IC.getCostDelta() + IC.getCost()) << ")");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -550,11 +550,12 @@ inlineCallsImpl(CallGraphSCC &SCC, CallGraph &CG,
|
|||
|
||||
// If the policy determines that we should inline this function,
|
||||
// try to do so.
|
||||
using namespace ore;
|
||||
if (!shouldInline(CS, GetInlineCost, ORE)) {
|
||||
ORE.emitOptimizationRemarkMissed(DEBUG_TYPE, DLoc, Block,
|
||||
Twine(Callee->getName() +
|
||||
" will not be inlined into " +
|
||||
Caller->getName()));
|
||||
ORE.emit(
|
||||
OptimizationRemarkMissed(DEBUG_TYPE, "NotInlined", DLoc, Block)
|
||||
<< NV("Callee", Callee) << " will not be inlined into "
|
||||
<< NV("Caller", Caller));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -562,18 +563,18 @@ inlineCallsImpl(CallGraphSCC &SCC, CallGraph &CG,
|
|||
if (!InlineCallIfPossible(CS, InlineInfo, InlinedArrayAllocas,
|
||||
InlineHistoryID, InsertLifetime, AARGetter,
|
||||
ImportedFunctionsStats)) {
|
||||
ORE.emitOptimizationRemarkMissed(DEBUG_TYPE, DLoc, Block,
|
||||
Twine(Callee->getName() +
|
||||
" will not be inlined into " +
|
||||
Caller->getName()));
|
||||
ORE.emit(
|
||||
OptimizationRemarkMissed(DEBUG_TYPE, "NotInlined", DLoc, Block)
|
||||
<< NV("Callee", Callee) << " will not be inlined into "
|
||||
<< NV("Caller", Caller));
|
||||
continue;
|
||||
}
|
||||
++NumInlined;
|
||||
|
||||
// Report the inline decision.
|
||||
ORE.emitOptimizationRemark(
|
||||
DEBUG_TYPE, DLoc, Block,
|
||||
Twine(Callee->getName() + " inlined into " + Caller->getName()));
|
||||
ORE.emit(OptimizationRemark(DEBUG_TYPE, "Inlined", DLoc, Block)
|
||||
<< NV("Callee", Callee) << " inlined into "
|
||||
<< NV("Caller", Caller));
|
||||
|
||||
// If inlining this function gave us any new call sites, throw them
|
||||
// onto our worklist to process. They are useful inline candidates.
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
; RUN: opt < %s -S -inline -pass-remarks-output=%t -pass-remarks=inline \
|
||||
; RUN: -pass-remarks-missed=inline -pass-remarks-analysis=inline \
|
||||
; RUN: -pass-remarks-with-hotness 2>&1 | FileCheck %s
|
||||
; RUN: cat %t | FileCheck -check-prefix=YAML %s
|
||||
|
||||
; Check the YAML file for inliner-generated passed and analysis remarks. This
|
||||
; is the input:
|
||||
|
||||
; 1 int foo() { return 1; }
|
||||
; 2
|
||||
; 3 int bar() {
|
||||
; 4 return foo();
|
||||
; 5 }
|
||||
|
||||
; CHECK: remark: /tmp/s.c:4:10: foo can be inlined into bar with cost={{[0-9]+}} (threshold={{[0-9]+}}) (hotness: 30)
|
||||
; CHECK-NEXT: remark: /tmp/s.c:4:10: foo inlined into bar (hotness: 30)
|
||||
|
||||
; YAML: --- !Analysis
|
||||
; YAML-NEXT: Pass: inline
|
||||
; YAML-NEXT: Name: CanBeInlined
|
||||
; YAML-NEXT: DebugLoc: { File: /tmp/s.c, Line: 4, Column: 10 }
|
||||
; YAML-NEXT: Function: bar
|
||||
; YAML-NEXT: Hotness: 30
|
||||
; YAML-NEXT: Args:
|
||||
; YAML-NEXT: - Callee: foo
|
||||
; YAML-NEXT: - String: can be inlined into
|
||||
; YAML-NEXT: - Caller: bar
|
||||
; YAML-NEXT: - String: with cost=
|
||||
; YAML-NEXT: - Cost: {{[0-9]+}}
|
||||
; YAML-NEXT: - String: (threshold=
|
||||
; YAML-NEXT: - Threshold: {{[0-9]+}}
|
||||
; YAML-NEXT: - String: )
|
||||
; YAML-NEXT: ...
|
||||
; YAML-NEXT: --- !Passed
|
||||
; YAML-NEXT: Pass: inline
|
||||
; YAML-NEXT: Name: Inlined
|
||||
; YAML-NEXT: DebugLoc: { File: /tmp/s.c, Line: 4, Column: 10 }
|
||||
; YAML-NEXT: Function: bar
|
||||
; YAML-NEXT: Hotness: 30
|
||||
; YAML-NEXT: Args:
|
||||
; YAML-NEXT: - Callee: foo
|
||||
; YAML-NEXT: - String: inlined into
|
||||
; YAML-NEXT: - Caller: bar
|
||||
; YAML-NEXT: ...
|
||||
|
||||
; ModuleID = '/tmp/s.c'
|
||||
source_filename = "/tmp/s.c"
|
||||
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-apple-macosx10.11.0"
|
||||
|
||||
; Function Attrs: nounwind ssp uwtable
|
||||
define i32 @foo() #0 !dbg !7 {
|
||||
entry:
|
||||
ret i32 1, !dbg !9
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind ssp uwtable
|
||||
define i32 @bar() #0 !dbg !10 !prof !13 {
|
||||
entry:
|
||||
%call = call i32 @foo(), !dbg !11
|
||||
ret i32 %call, !dbg !12
|
||||
}
|
||||
|
||||
attributes #0 = { nounwind ssp uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
||||
|
||||
!llvm.dbg.cu = !{!0}
|
||||
!llvm.module.flags = !{!3, !4, !5}
|
||||
!llvm.ident = !{!6}
|
||||
|
||||
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.0 (trunk 282540) (llvm/trunk 282542)", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2)
|
||||
!1 = !DIFile(filename: "/tmp/s.c", directory: "/tmp")
|
||||
!2 = !{}
|
||||
!3 = !{i32 2, !"Dwarf Version", i32 4}
|
||||
!4 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!5 = !{i32 1, !"PIC Level", i32 2}
|
||||
!6 = !{!"clang version 4.0.0 (trunk 282540) (llvm/trunk 282542)"}
|
||||
!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: true, unit: !0, variables: !2)
|
||||
!8 = !DISubroutineType(types: !2)
|
||||
!9 = !DILocation(line: 1, column: 13, scope: !7)
|
||||
!10 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 3, type: !8, isLocal: false, isDefinition: true, scopeLine: 3, isOptimized: true, unit: !0, variables: !2)
|
||||
!11 = !DILocation(line: 4, column: 10, scope: !10)
|
||||
!12 = !DILocation(line: 4, column: 3, scope: !10)
|
||||
!13 = !{!"function_entry_count", i64 30}
|
Loading…
Reference in New Issue