1 //===-- CSPreInliner.h - Profile guided preinliner ---------------- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_TOOLS_LLVM_PROFGEN_PGOINLINEADVISOR_H
10 #define LLVM_TOOLS_LLVM_PROFGEN_PGOINLINEADVISOR_H
12 #include "ProfiledBinary.h"
13 #include "llvm/ADT/PriorityQueue.h"
14 #include "llvm/ProfileData/ProfileCommon.h"
15 #include "llvm/ProfileData/SampleProf.h"
16 #include "llvm/Transforms/IPO/ProfiledCallGraph.h"
17 #include "llvm/Transforms/IPO/SampleContextTracker.h"
20 using namespace sampleprof
;
23 namespace sampleprof
{
25 // Inline candidate seen from profile
26 struct ProfiledInlineCandidate
{
27 ProfiledInlineCandidate(const FunctionSamples
*Samples
, uint64_t Count
,
29 : CalleeSamples(Samples
), CallsiteCount(Count
), SizeCost(Size
) {}
30 // Context-sensitive function profile for inline candidate
31 const FunctionSamples
*CalleeSamples
;
32 // Call site count for an inline candidate
33 // TODO: make sure entry count for context profile and call site
34 // target count for corresponding call are consistent.
35 uint64_t CallsiteCount
;
36 // Size proxy for function under particular call context.
40 // Inline candidate comparer using call site weight
41 struct ProfiledCandidateComparer
{
42 bool operator()(const ProfiledInlineCandidate
&LHS
,
43 const ProfiledInlineCandidate
&RHS
) {
44 if (LHS
.CallsiteCount
!= RHS
.CallsiteCount
)
45 return LHS
.CallsiteCount
< RHS
.CallsiteCount
;
47 if (LHS
.SizeCost
!= RHS
.SizeCost
)
48 return LHS
.SizeCost
> RHS
.SizeCost
;
50 // Tie breaker using GUID so we have stable/deterministic inlining order
51 assert(LHS
.CalleeSamples
&& RHS
.CalleeSamples
&&
52 "Expect non-null FunctionSamples");
53 return LHS
.CalleeSamples
->getGUID(LHS
.CalleeSamples
->getName()) <
54 RHS
.CalleeSamples
->getGUID(RHS
.CalleeSamples
->getName());
58 using ProfiledCandidateQueue
=
59 PriorityQueue
<ProfiledInlineCandidate
, std::vector
<ProfiledInlineCandidate
>,
60 ProfiledCandidateComparer
>;
62 // Pre-compilation inliner based on context-sensitive profile.
63 // The PreInliner estimates inline decision using hotness from profile
64 // and cost estimation from machine code size. It helps merges context
65 // profile globally and achieves better post-inine profile quality, which
66 // otherwise won't be possible for ThinLTO. It also reduce context profile
67 // size by only keep context that is estimated to be inlined.
70 CSPreInliner(SampleContextTracker
&Tracker
, ProfiledBinary
&Binary
,
71 ProfileSummary
*Summary
);
75 bool getInlineCandidates(ProfiledCandidateQueue
&CQueue
,
76 const FunctionSamples
*FCallerContextSamples
);
77 std::vector
<StringRef
> buildTopDownOrder();
78 void processFunction(StringRef Name
);
79 bool shouldInline(ProfiledInlineCandidate
&Candidate
);
80 uint32_t getFuncSize(const ContextTrieNode
*ContextNode
);
82 SampleContextTracker
&ContextTracker
;
83 ProfiledBinary
&Binary
;
84 ProfileSummary
*Summary
;
87 } // end namespace sampleprof
88 } // end namespace llvm