[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:
Wenlei He 2020-06-19 10:25:31 -07:00
parent 6e3faaeb44
commit 7c8a6936bf
8 changed files with 96 additions and 18 deletions

View File

@ -73,7 +73,7 @@ void bar(int x) {
// THRESHOLD-NOT: hotness // THRESHOLD-NOT: hotness
// NO_PGO: '-fdiagnostics-show-hotness' requires profile-guided optimization information // NO_PGO: '-fdiagnostics-show-hotness' requires profile-guided optimization information
// NO_PGO: '-fdiagnostics-hotness-threshold=' 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); sum += foo(x, x - 2);
} }

View File

@ -66,7 +66,7 @@ void bar(int x) {
// THRESHOLD-NOT: hotness // THRESHOLD-NOT: hotness
// NO_PGO: '-fdiagnostics-show-hotness' requires profile-guided optimization information // NO_PGO: '-fdiagnostics-show-hotness' requires profile-guided optimization information
// NO_PGO: '-fdiagnostics-hotness-threshold=' 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); sum += foo(x, x - 2);
} }

View File

@ -217,7 +217,12 @@ shouldInline(CallBase &CB, function_ref<InlineCost(CallBase &CB)> GetInlineCost,
/// Emit ORE message. /// Emit ORE message.
void emitInlinedInto(OptimizationRemarkEmitter &ORE, DebugLoc DLoc, void emitInlinedInto(OptimizationRemarkEmitter &ORE, DebugLoc DLoc,
const BasicBlock *Block, const Function &Callee, 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. /// Set the inline-remark attribute.
void setInlineRemark(CallBase &CB, StringRef Message); void setInlineRemark(CallBase &CB, StringRef Message);

View File

@ -18,6 +18,7 @@
#include "llvm/Analysis/ProfileSummaryInfo.h" #include "llvm/Analysis/ProfileSummaryInfo.h"
#include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/Instructions.h" #include "llvm/IR/Instructions.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
@ -354,14 +355,43 @@ llvm::shouldInline(CallBase &CB,
return IC; 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, void llvm::emitInlinedInto(OptimizationRemarkEmitter &ORE, DebugLoc DLoc,
const BasicBlock *Block, const Function &Callee, 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([&]() { ORE.emit([&]() {
bool AlwaysInline = IC.isAlways(); bool AlwaysInline = IC.isAlways();
StringRef RemarkName = AlwaysInline ? "AlwaysInline" : "Inlined"; StringRef RemarkName = AlwaysInline ? "AlwaysInline" : "Inlined";
return OptimizationRemark(DEBUG_TYPE, RemarkName, DLoc, Block) OptimizationRemark Remark(PassName ? PassName : DEBUG_TYPE, RemarkName,
<< ore::NV("Callee", &Callee) << " inlined into " DLoc, Block);
<< ore::NV("Caller", &Caller) << " with " << IC; 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;
}); });
} }

View File

@ -37,6 +37,7 @@
#include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/CallGraph.h" #include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/CallGraphSCCPass.h" #include "llvm/Analysis/CallGraphSCCPass.h"
#include "llvm/Analysis/InlineAdvisor.h"
#include "llvm/Analysis/InlineCost.h" #include "llvm/Analysis/InlineCost.h"
#include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h" #include "llvm/Analysis/OptimizationRemarkEmitter.h"
@ -916,9 +917,8 @@ bool SampleProfileLoader::inlineCallInstruction(CallBase &CB) {
InlineFunctionInfo IFI(nullptr, GetAC); InlineFunctionInfo IFI(nullptr, GetAC);
if (InlineFunction(CB, IFI).isSuccess()) { if (InlineFunction(CB, IFI).isSuccess()) {
// The call to InlineFunction erases I, so we can't pass it here. // The call to InlineFunction erases I, so we can't pass it here.
ORE->emit(OptimizationRemark(CSINLINE_DEBUG, "InlineSuccess", DLoc, BB) emitInlinedInto(*ORE, DLoc, BB, *CalledFunction, *BB->getParent(), Cost,
<< "inlined callee '" << ore::NV("Callee", CalledFunction) true, CSINLINE_DEBUG);
<< "' into '" << ore::NV("Caller", BB->getParent()) << "'");
return true; return true;
} }
return false; return false;

View File

@ -22,7 +22,7 @@
; 4 return foo(); ; 4 return foo();
; 5 } ; 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: --- !Passed
; YAML-NEXT: Pass: inline ; YAML-NEXT: Pass: inline
@ -42,6 +42,10 @@
; YAML-NEXT: - String: ', threshold=' ; YAML-NEXT: - String: ', threshold='
; YAML-NEXT: - Threshold: '{{[0-9]+}}' ; YAML-NEXT: - Threshold: '{{[0-9]+}}'
; YAML-NEXT: - String: ')' ; YAML-NEXT: - String: ')'
; YAML-NEXT: - String: ' at callsite '
; YAML-NEXT: - String: bar
; YAML-NEXT: - String: ':'
; YAML-NEXT: - Line: '1'
; YAML-NEXT: ... ; YAML-NEXT: ...
; ModuleID = '/tmp/s.c' ; ModuleID = '/tmp/s.c'

View File

@ -4,4 +4,6 @@ main:623868:0
3: 18346 3: 18346
4: 0 4: 0
6: 19475 6: 19475
6: rand:12093
0: 11203
2: 18305 2: 18305

View File

@ -21,7 +21,8 @@
; We are expecting foo() to be inlined in main() (almost all the cycles are ; We are expecting foo() to be inlined in main() (almost all the cycles are
; spent inside foo). ; 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. ; 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 ; 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 ; Checking to see if YAML file is generated and contains remarks
;YAML: --- !Passed ;YAML: --- !Passed
;YAML-NEXT: Pass: sample-profile-inline ;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: DebugLoc: { File: remarks.cc, Line: 13, Column: 21 }
;YAML-NEXT: Function: main ;YAML-NEXT: Function: main
;YAML-NEXT: Args: ;YAML-NEXT: Args:
;YAML-NEXT: - String: 'inlined callee '''
;YAML-NEXT: - Callee: _Z3foov ;YAML-NEXT: - Callee: _Z3foov
;YAML-NEXT: DebugLoc: { File: remarks.cc, Line: 3, Column: 0 } ;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: - Caller: main
;YAML-NEXT: DebugLoc: { File: remarks.cc, Line: 13, Column: 0 } ;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-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: --- !Analysis
;YAML-NEXT: Pass: sample-profile ;YAML-NEXT: Pass: sample-profile
;YAML-NEXT: Name: AppliedSamples ;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 declare void @llvm.dbg.declare(metadata, metadata, metadata) #2
; Function Attrs: nounwind ; Function Attrs: nounwind
declare i32 @rand() #3 define i32 @rand() #3 !dbg !59 {
ret i32 1
}
; Function Attrs: nounwind argmemonly ; Function Attrs: nounwind argmemonly
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1 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 #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 #1 = { nounwind argmemonly }
attributes #2 = { nounwind readnone } 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 } attributes #4 = { nounwind }
!llvm.dbg.cu = !{!0} !llvm.dbg.cu = !{!0}
@ -223,3 +259,4 @@ attributes #4 = { nounwind }
!56 = !DILocation(line: 13, column: 21, scope: !13) !56 = !DILocation(line: 13, column: 21, scope: !13)
!57 = !DILocation(line: 13, column: 27, scope: !13) !57 = !DILocation(line: 13, column: 27, scope: !13)
!58 = !DILocation(line: 13, column: 14, 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)