diff --git a/clang/test/Frontend/optimization-remark-with-hotness-new-pm.c b/clang/test/Frontend/optimization-remark-with-hotness-new-pm.c --- a/clang/test/Frontend/optimization-remark-with-hotness-new-pm.c +++ b/clang/test/Frontend/optimization-remark-with-hotness-new-pm.c @@ -73,7 +73,7 @@ // 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); } diff --git a/clang/test/Frontend/optimization-remark-with-hotness.c b/clang/test/Frontend/optimization-remark-with-hotness.c --- a/clang/test/Frontend/optimization-remark-with-hotness.c +++ b/clang/test/Frontend/optimization-remark-with-hotness.c @@ -66,7 +66,7 @@ // 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); } diff --git a/llvm/include/llvm/Analysis/InlineAdvisor.h b/llvm/include/llvm/Analysis/InlineAdvisor.h --- a/llvm/include/llvm/Analysis/InlineAdvisor.h +++ b/llvm/include/llvm/Analysis/InlineAdvisor.h @@ -217,7 +217,12 @@ /// 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); diff --git a/llvm/lib/Analysis/InlineAdvisor.cpp b/llvm/lib/Analysis/InlineAdvisor.cpp --- a/llvm/lib/Analysis/InlineAdvisor.cpp +++ b/llvm/lib/Analysis/InlineAdvisor.cpp @@ -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 @@ 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; }); } diff --git a/llvm/lib/Transforms/IPO/SampleProfile.cpp b/llvm/lib/Transforms/IPO/SampleProfile.cpp --- a/llvm/lib/Transforms/IPO/SampleProfile.cpp +++ b/llvm/lib/Transforms/IPO/SampleProfile.cpp @@ -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 @@ 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; diff --git a/llvm/test/Transforms/Inline/optimization-remarks-passed-yaml.ll b/llvm/test/Transforms/Inline/optimization-remarks-passed-yaml.ll --- a/llvm/test/Transforms/Inline/optimization-remarks-passed-yaml.ll +++ b/llvm/test/Transforms/Inline/optimization-remarks-passed-yaml.ll @@ -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' diff --git a/llvm/test/Transforms/SampleProfile/Inputs/remarks.prof b/llvm/test/Transforms/SampleProfile/Inputs/remarks.prof --- a/llvm/test/Transforms/SampleProfile/Inputs/remarks.prof +++ b/llvm/test/Transforms/SampleProfile/Inputs/remarks.prof @@ -4,4 +4,6 @@ 3: 18346 4: 0 6: 19475 + 6: rand:12093 + 0: 11203 2: 18305 diff --git a/llvm/test/Transforms/SampleProfile/remarks.ll b/llvm/test/Transforms/SampleProfile/remarks.ll --- a/llvm/test/Transforms/SampleProfile/remarks.ll +++ b/llvm/test/Transforms/SampleProfile/remarks.ll @@ -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.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 @@ 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 @@ !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)