forked from OSchip/llvm-project
[Remarks] Add callsite locations to inline remarks
Summary: Add call site location info into inline remarks so we can differentiate inline sites. This can be useful for inliner tuning. We can also reconstruct full hierarchical inline tree from parsing such remarks. The messege of inline remark is also tweaked so we can differentiate SampleProfileLoader inline from CGSCC inline. Reviewers: wmi, davidxl, hoy Subscribers: hiraditya, cfe-commits, llvm-commits Tags: #clang, #llvm Differential Revision: https://reviews.llvm.org/D82213
This commit is contained in:
parent
6e3faaeb44
commit
7c8a6936bf
|
@ -73,7 +73,7 @@ void bar(int x) {
|
|||
// THRESHOLD-NOT: hotness
|
||||
// NO_PGO: '-fdiagnostics-show-hotness' requires profile-guided optimization information
|
||||
// NO_PGO: '-fdiagnostics-hotness-threshold=' requires profile-guided optimization information
|
||||
// expected-remark@+1 {{foo inlined into bar with (cost=always): always inline attribute (hotness:}}
|
||||
// expected-remark@+1 {{foo inlined into bar with (cost=always): always inline attribute at callsite bar:8 (hotness:}}
|
||||
sum += foo(x, x - 2);
|
||||
}
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ void bar(int x) {
|
|||
// THRESHOLD-NOT: hotness
|
||||
// NO_PGO: '-fdiagnostics-show-hotness' requires profile-guided optimization information
|
||||
// NO_PGO: '-fdiagnostics-hotness-threshold=' requires profile-guided optimization information
|
||||
// expected-remark@+1 {{foo inlined into bar with (cost=always): always inliner (hotness:}}
|
||||
// expected-remark@+1 {{foo inlined into bar with (cost=always): always inliner at callsite bar:8 (hotness:}}
|
||||
sum += foo(x, x - 2);
|
||||
}
|
||||
|
||||
|
|
|
@ -217,7 +217,12 @@ shouldInline(CallBase &CB, function_ref<InlineCost(CallBase &CB)> GetInlineCost,
|
|||
/// Emit ORE message.
|
||||
void emitInlinedInto(OptimizationRemarkEmitter &ORE, DebugLoc DLoc,
|
||||
const BasicBlock *Block, const Function &Callee,
|
||||
const Function &Caller, const InlineCost &IC);
|
||||
const Function &Caller, const InlineCost &IC,
|
||||
bool ForProfileContext = false,
|
||||
const char *PassName = nullptr);
|
||||
|
||||
/// Add location info to ORE message.
|
||||
void addLocationToRemarks(OptimizationRemark &Remark, DebugLoc DLoc);
|
||||
|
||||
/// Set the inline-remark attribute.
|
||||
void setInlineRemark(CallBase &CB, StringRef Message);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "llvm/Analysis/ProfileSummaryInfo.h"
|
||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
#include "llvm/Analysis/TargetTransformInfo.h"
|
||||
#include "llvm/IR/DebugInfoMetadata.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
|
@ -354,14 +355,43 @@ llvm::shouldInline(CallBase &CB,
|
|||
return IC;
|
||||
}
|
||||
|
||||
void llvm::addLocationToRemarks(OptimizationRemark &Remark, DebugLoc DLoc) {
|
||||
if (!DLoc.get())
|
||||
return;
|
||||
|
||||
bool First = true;
|
||||
Remark << " at callsite ";
|
||||
for (DILocation *DIL = DLoc.get(); DIL; DIL = DIL->getInlinedAt()) {
|
||||
if (!First)
|
||||
Remark << " @ ";
|
||||
unsigned int Offset = DIL->getLine();
|
||||
Offset -= DIL->getScope()->getSubprogram()->getLine();
|
||||
unsigned int Discriminator = DIL->getBaseDiscriminator();
|
||||
StringRef Name = DIL->getScope()->getSubprogram()->getLinkageName();
|
||||
if (Name.empty())
|
||||
Name = DIL->getScope()->getSubprogram()->getName();
|
||||
Remark << Name << ":" << ore::NV("Line", Offset);
|
||||
if (Discriminator)
|
||||
Remark << "." << ore::NV("Disc", Discriminator);
|
||||
First = false;
|
||||
}
|
||||
}
|
||||
|
||||
void llvm::emitInlinedInto(OptimizationRemarkEmitter &ORE, DebugLoc DLoc,
|
||||
const BasicBlock *Block, const Function &Callee,
|
||||
const Function &Caller, const InlineCost &IC) {
|
||||
const Function &Caller, const InlineCost &IC,
|
||||
bool ForProfileContext, const char *PassName) {
|
||||
ORE.emit([&]() {
|
||||
bool AlwaysInline = IC.isAlways();
|
||||
StringRef RemarkName = AlwaysInline ? "AlwaysInline" : "Inlined";
|
||||
return OptimizationRemark(DEBUG_TYPE, RemarkName, DLoc, Block)
|
||||
<< ore::NV("Callee", &Callee) << " inlined into "
|
||||
<< ore::NV("Caller", &Caller) << " with " << IC;
|
||||
OptimizationRemark Remark(PassName ? PassName : DEBUG_TYPE, RemarkName,
|
||||
DLoc, Block);
|
||||
Remark << ore::NV("Callee", &Callee) << " inlined into ";
|
||||
Remark << ore::NV("Caller", &Caller);
|
||||
if (ForProfileContext)
|
||||
Remark << " to match profiling context";
|
||||
Remark << " with " << IC;
|
||||
addLocationToRemarks(Remark, DLoc);
|
||||
return Remark;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "llvm/Analysis/AssumptionCache.h"
|
||||
#include "llvm/Analysis/CallGraph.h"
|
||||
#include "llvm/Analysis/CallGraphSCCPass.h"
|
||||
#include "llvm/Analysis/InlineAdvisor.h"
|
||||
#include "llvm/Analysis/InlineCost.h"
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
|
||||
|
@ -916,9 +917,8 @@ bool SampleProfileLoader::inlineCallInstruction(CallBase &CB) {
|
|||
InlineFunctionInfo IFI(nullptr, GetAC);
|
||||
if (InlineFunction(CB, IFI).isSuccess()) {
|
||||
// The call to InlineFunction erases I, so we can't pass it here.
|
||||
ORE->emit(OptimizationRemark(CSINLINE_DEBUG, "InlineSuccess", DLoc, BB)
|
||||
<< "inlined callee '" << ore::NV("Callee", CalledFunction)
|
||||
<< "' into '" << ore::NV("Caller", BB->getParent()) << "'");
|
||||
emitInlinedInto(*ORE, DLoc, BB, *CalledFunction, *BB->getParent(), Cost,
|
||||
true, CSINLINE_DEBUG);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
; 4 return foo();
|
||||
; 5 }
|
||||
|
||||
; CHECK: remark: /tmp/s.c:4:10: foo inlined into bar with (cost={{[0-9\-]+}}, threshold={{[0-9]+}}) (hotness: 30)
|
||||
; CHECK: remark: /tmp/s.c:4:10: foo inlined into bar with (cost={{[0-9\-]+}}, threshold={{[0-9]+}}) at callsite bar:1 (hotness: 30)
|
||||
|
||||
; YAML: --- !Passed
|
||||
; YAML-NEXT: Pass: inline
|
||||
|
@ -42,6 +42,10 @@
|
|||
; YAML-NEXT: - String: ', threshold='
|
||||
; YAML-NEXT: - Threshold: '{{[0-9]+}}'
|
||||
; YAML-NEXT: - String: ')'
|
||||
; YAML-NEXT: - String: ' at callsite '
|
||||
; YAML-NEXT: - String: bar
|
||||
; YAML-NEXT: - String: ':'
|
||||
; YAML-NEXT: - Line: '1'
|
||||
; YAML-NEXT: ...
|
||||
|
||||
; ModuleID = '/tmp/s.c'
|
||||
|
|
|
@ -4,4 +4,6 @@ main:623868:0
|
|||
3: 18346
|
||||
4: 0
|
||||
6: 19475
|
||||
6: rand:12093
|
||||
0: 11203
|
||||
2: 18305
|
||||
|
|
|
@ -21,7 +21,8 @@
|
|||
|
||||
; We are expecting foo() to be inlined in main() (almost all the cycles are
|
||||
; spent inside foo).
|
||||
; CHECK: remark: remarks.cc:13:21: inlined callee '_Z3foov' into 'main'
|
||||
; CHECK: remark: remarks.cc:13:21: _Z3foov inlined into main to match profiling context with (cost=130, threshold=225) at callsite main:0
|
||||
; CHECK: remark: remarks.cc:9:19: rand inlined into main to match profiling context with (cost=always): always inline attribute at callsite _Z3foov:6 @ main:0
|
||||
|
||||
; The back edge for the loop is the hottest edge in the loop subgraph.
|
||||
; CHECK: remark: remarks.cc:6:9: most popular destination for conditional branches at remarks.cc:5:3
|
||||
|
@ -32,18 +33,51 @@
|
|||
; Checking to see if YAML file is generated and contains remarks
|
||||
;YAML: --- !Passed
|
||||
;YAML-NEXT: Pass: sample-profile-inline
|
||||
;YAML-NEXT: Name: InlineSuccess
|
||||
;YAML-NEXT: Name: Inlined
|
||||
;YAML-NEXT: DebugLoc: { File: remarks.cc, Line: 13, Column: 21 }
|
||||
;YAML-NEXT: Function: main
|
||||
;YAML-NEXT: Args:
|
||||
;YAML-NEXT: - String: 'inlined callee '''
|
||||
;YAML-NEXT: - Callee: _Z3foov
|
||||
;YAML-NEXT: DebugLoc: { File: remarks.cc, Line: 3, Column: 0 }
|
||||
;YAML-NEXT: - String: ''' into '''
|
||||
;YAML-NEXT: - String: ' inlined into '
|
||||
;YAML-NEXT: - Caller: main
|
||||
;YAML-NEXT: DebugLoc: { File: remarks.cc, Line: 13, Column: 0 }
|
||||
;YAML-NEXT: - String: ''''
|
||||
;YAML-NEXT: - String: ' to match profiling context'
|
||||
;YAML-NEXT: - String: ' with '
|
||||
;YAML-NEXT: - String: '(cost='
|
||||
;YAML-NEXT: - Cost: '130'
|
||||
;YAML-NEXT: - String: ', threshold='
|
||||
;YAML-NEXT: - Threshold: '225'
|
||||
;YAML-NEXT: - String: ')'
|
||||
;YAML-NEXT: - String: ' at callsite '
|
||||
;YAML-NEXT: - String: main
|
||||
;YAML-NEXT: - String: ':'
|
||||
;YAML-NEXT: - Line: '0'
|
||||
;YAML-NEXT: ...
|
||||
;YAML: --- !Passed
|
||||
;YAML-NEXT: Pass: sample-profile-inline
|
||||
;YAML-NEXT: Name: AlwaysInline
|
||||
;YAML-NEXT: DebugLoc: { File: remarks.cc, Line: 9, Column: 19 }
|
||||
;YAML-NEXT: Function: main
|
||||
;YAML-NEXT: Args:
|
||||
;YAML-NEXT: - Callee: rand
|
||||
;YAML-NEXT: DebugLoc: { File: remarks.cc, Line: 90, Column: 0 }
|
||||
;YAML-NEXT: - String: ' inlined into '
|
||||
;YAML-NEXT: - Caller: main
|
||||
;YAML-NEXT: DebugLoc: { File: remarks.cc, Line: 13, Column: 0 }
|
||||
;YAML-NEXT: - String: ' to match profiling context'
|
||||
;YAML-NEXT: - String: ' with '
|
||||
;YAML-NEXT: - String: '(cost=always)'
|
||||
;YAML-NEXT: - String: ': '
|
||||
;YAML-NEXT: - Reason: always inline attribute
|
||||
;YAML-NEXT: - String: ' at callsite '
|
||||
;YAML-NEXT: - String: _Z3foov
|
||||
;YAML-NEXT: - String: ':'
|
||||
;YAML-NEXT: - Line: '6'
|
||||
;YAML-NEXT: - String: ' @ '
|
||||
;YAML-NEXT: - String: main
|
||||
;YAML-NEXT: - String: ':'
|
||||
;YAML-NEXT: - Line: '0'
|
||||
;YAML: --- !Analysis
|
||||
;YAML-NEXT: Pass: sample-profile
|
||||
;YAML-NEXT: Name: AppliedSamples
|
||||
|
@ -139,7 +173,9 @@ declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1
|
|||
declare void @llvm.dbg.declare(metadata, metadata, metadata) #2
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare i32 @rand() #3
|
||||
define i32 @rand() #3 !dbg !59 {
|
||||
ret i32 1
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind argmemonly
|
||||
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1
|
||||
|
@ -158,7 +194,7 @@ entry:
|
|||
attributes #0 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "frame-pointer"="none" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" "use-sample-profile" }
|
||||
attributes #1 = { nounwind argmemonly }
|
||||
attributes #2 = { nounwind readnone }
|
||||
attributes #3 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "frame-pointer"="none" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
||||
attributes #3 = { nounwind alwaysinline "disable-tail-calls"="false" "less-precise-fpmad"="false" "frame-pointer"="none" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
||||
attributes #4 = { nounwind }
|
||||
|
||||
!llvm.dbg.cu = !{!0}
|
||||
|
@ -223,3 +259,4 @@ attributes #4 = { nounwind }
|
|||
!56 = !DILocation(line: 13, column: 21, scope: !13)
|
||||
!57 = !DILocation(line: 13, column: 27, scope: !13)
|
||||
!58 = !DILocation(line: 13, column: 14, scope: !13)
|
||||
!59 = distinct !DISubprogram(name: "rand", linkageName: "rand", scope: !1, file: !1, line: 90, type: !5, isLocal: false, isDefinition: true, scopeLine: 90, flags: DIFlagPrototyped, isOptimized: true, unit: !0)
|
||||
|
|
Loading…
Reference in New Issue