xref: /llvm-project/llvm/tools/llvm-profgen/CSPreInliner.h (revision ef0e0adccd94ffdb10546491ef2719669754d3c9)
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 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_TOOLS_LLVM_PROFGEN_PGOINLINEADVISOR_H
10 #define LLVM_TOOLS_LLVM_PROFGEN_PGOINLINEADVISOR_H
11 
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"
18 
19 using namespace llvm;
20 using namespace sampleprof;
21 
22 namespace llvm {
23 namespace sampleprof {
24 
25 // Inline candidate seen from profile
26 struct ProfiledInlineCandidate {
ProfiledInlineCandidateProfiledInlineCandidate27   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;
38 };
39 
40 // Inline candidate comparer using call site weight
41 struct ProfiledCandidateComparer {
operatorProfiledCandidateComparer42   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;
50 
51     if (LHS.CallsiteCount != RHS.CallsiteCount)
52       return LHS.CallsiteCount < RHS.CallsiteCount;
53 
54     if (LHS.SizeCost != RHS.SizeCost)
55       return LHS.SizeCost > RHS.SizeCost;
56 
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();
61   }
62 };
63 
64 using ProfiledCandidateQueue =
65     PriorityQueue<ProfiledInlineCandidate, std::vector<ProfiledInlineCandidate>,
66                   ProfiledCandidateComparer>;
67 
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.
74 class CSPreInliner {
75 public:
76   CSPreInliner(SampleContextTracker &Tracker, ProfiledBinary &Binary,
77                ProfileSummary *Summary);
78   void run();
79 
80 private:
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);
87   bool UseContextCost;
88   SampleContextTracker &ContextTracker;
89   ProfiledBinary &Binary;
90   ProfileSummary *Summary;
91 };
92 
93 } // end namespace sampleprof
94 } // end namespace llvm
95 
96 #endif
97