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 // Always prioritize inlining zero-sized functions as they do not affect the
45 // size budget. This could happen when all of the callee's code is gone and
46 // only pseudo probes are left.
47 if ((LHS
.SizeCost
== 0 || RHS
.SizeCost
== 0) &&
48 (LHS
.SizeCost
!= RHS
.SizeCost
))
49 return RHS
.SizeCost
== 0;
51 if (LHS
.CallsiteCount
!= RHS
.CallsiteCount
)
52 return LHS
.CallsiteCount
< RHS
.CallsiteCount
;
54 if (LHS
.SizeCost
!= RHS
.SizeCost
)
55 return LHS
.SizeCost
> RHS
.SizeCost
;
57 // Tie breaker using GUID so we have stable/deterministic inlining order
58 assert(LHS
.CalleeSamples
&& RHS
.CalleeSamples
&&
59 "Expect non-null FunctionSamples");
60 return LHS
.CalleeSamples
->getGUID() < RHS
.CalleeSamples
->getGUID();
64 using ProfiledCandidateQueue
=
65 PriorityQueue
<ProfiledInlineCandidate
, std::vector
<ProfiledInlineCandidate
>,
66 ProfiledCandidateComparer
>;
68 // Pre-compilation inliner based on context-sensitive profile.
69 // The PreInliner estimates inline decision using hotness from profile
70 // and cost estimation from machine code size. It helps merges context
71 // profile globally and achieves better post-inine profile quality, which
72 // otherwise won't be possible for ThinLTO. It also reduce context profile
73 // size by only keep context that is estimated to be inlined.
76 CSPreInliner(SampleContextTracker
&Tracker
, ProfiledBinary
&Binary
,
77 ProfileSummary
*Summary
);
81 bool getInlineCandidates(ProfiledCandidateQueue
&CQueue
,
82 const FunctionSamples
*FCallerContextSamples
);
83 std::vector
<FunctionId
> buildTopDownOrder();
84 void processFunction(FunctionId Name
);
85 bool shouldInline(ProfiledInlineCandidate
&Candidate
);
86 uint32_t getFuncSize(const ContextTrieNode
*ContextNode
);
88 SampleContextTracker
&ContextTracker
;
89 ProfiledBinary
&Binary
;
90 ProfileSummary
*Summary
;
93 } // end namespace sampleprof
94 } // end namespace llvm