[NFC][Py Reformat] Reformat python files in llvm
[llvm-project.git] / llvm / tools / llvm-profgen / CSPreInliner.h
blob09dd2dec1149c599e7989e03a3868488a59bfbb1
1 //===-- CSPreInliner.h - Profile guided preinliner ---------------- C++ -*-===//
2 //
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
6 //
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"
19 using namespace llvm;
20 using namespace sampleprof;
22 namespace llvm {
23 namespace sampleprof {
25 // Inline candidate seen from profile
26 struct ProfiledInlineCandidate {
27 ProfiledInlineCandidate(const FunctionSamples *Samples, uint64_t Count,
28 uint32_t Size)
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.
37 uint64_t SizeCost;
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.
68 class CSPreInliner {
69 public:
70 CSPreInliner(SampleContextTracker &Tracker, ProfiledBinary &Binary,
71 ProfileSummary *Summary);
72 void run();
74 private:
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);
81 bool UseContextCost;
82 SampleContextTracker &ContextTracker;
83 ProfiledBinary &Binary;
84 ProfileSummary *Summary;
87 } // end namespace sampleprof
88 } // end namespace llvm
90 #endif