xref: /llvm-project/llvm/tools/llvm-profgen/ProfileGenerator.h (revision b9d40a7ae4b3e5b9829eca8a497637c9fab6dd3e)
11f05b1a9Swlei //===-- ProfileGenerator.h - Profile Generator -----------------*- C++ -*-===//
21f05b1a9Swlei //
31f05b1a9Swlei // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41f05b1a9Swlei // See https://llvm.org/LICENSE.txt for license information.
51f05b1a9Swlei // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61f05b1a9Swlei //
71f05b1a9Swlei //===----------------------------------------------------------------------===//
81f05b1a9Swlei 
91f05b1a9Swlei #ifndef LLVM_TOOLS_LLVM_PROGEN_PROFILEGENERATOR_H
101f05b1a9Swlei #define LLVM_TOOLS_LLVM_PROGEN_PROFILEGENERATOR_H
1130b02323SWenlei He #include "CSPreInliner.h"
121f05b1a9Swlei #include "ErrorHandling.h"
131f05b1a9Swlei #include "PerfReader.h"
141f05b1a9Swlei #include "ProfiledBinary.h"
15f1985a3fSserge-sans-paille #include "llvm/IR/DebugInfoMetadata.h"
161f05b1a9Swlei #include "llvm/ProfileData/SampleProfWriter.h"
17ce6bfe94SWenlei He #include <memory>
1800ef28efSWenlei He #include <unordered_set>
191f05b1a9Swlei 
201f05b1a9Swlei using namespace llvm;
211f05b1a9Swlei using namespace sampleprof;
221f05b1a9Swlei 
231f05b1a9Swlei namespace llvm {
241f05b1a9Swlei namespace sampleprof {
251f05b1a9Swlei 
2623391febSHongtao Yu using ProbeCounterMap =
2723391febSHongtao Yu     std::unordered_map<const MCDecodedPseudoProbe *, uint64_t>;
2823391febSHongtao Yu 
29d5f20130Swlei // This base class for profile generation of sample-based PGO. We reuse all
30d5f20130Swlei // structures relating to function profiles and profile writers as seen in
31d5f20130Swlei // /ProfileData/SampleProf.h.
32d5f20130Swlei class ProfileGeneratorBase {
331f05b1a9Swlei 
341f05b1a9Swlei public:
ProfileGeneratorBase(ProfiledBinary * Binary)35aa58b7b1Swlei   ProfileGeneratorBase(ProfiledBinary *Binary) : Binary(Binary){};
ProfileGeneratorBase(ProfiledBinary * Binary,const ContextSampleCounterMap * Counters)36d5f20130Swlei   ProfileGeneratorBase(ProfiledBinary *Binary,
37937924ebSHongtao Yu                        const ContextSampleCounterMap *Counters)
38d5f20130Swlei       : Binary(Binary), SampleCounters(Counters){};
ProfileGeneratorBase(ProfiledBinary * Binary,const SampleProfileMap && Profiles)39937924ebSHongtao Yu   ProfileGeneratorBase(ProfiledBinary *Binary,
40937924ebSHongtao Yu                        const SampleProfileMap &&Profiles)
41937924ebSHongtao Yu       : Binary(Binary), ProfileMap(std::move(Profiles)){};
42937924ebSHongtao Yu 
43d5f20130Swlei   virtual ~ProfileGeneratorBase() = default;
44d5f20130Swlei   static std::unique_ptr<ProfileGeneratorBase>
45937924ebSHongtao Yu   create(ProfiledBinary *Binary, const ContextSampleCounterMap *Counters,
46e36786d1SHongtao Yu          bool profileIsCS);
47937924ebSHongtao Yu   static std::unique_ptr<ProfileGeneratorBase>
48aa58b7b1Swlei   create(ProfiledBinary *Binary, SampleProfileMap &ProfileMap,
49e36786d1SHongtao Yu          bool profileIsCS);
501f05b1a9Swlei   virtual void generateProfile() = 0;
511f05b1a9Swlei   void write();
521f05b1a9Swlei 
5341a681ceSwlei   static uint32_t
5441a681ceSwlei   getDuplicationFactor(unsigned Discriminator,
5541a681ceSwlei                        bool UseFSD = ProfileGeneratorBase::UseFSDiscriminator) {
5641a681ceSwlei     return UseFSD ? 1
5741a681ceSwlei                   : llvm::DILocation::getDuplicationFactorFromDiscriminator(
5846cf7d75Swlei                         Discriminator);
5946cf7d75Swlei   }
6046cf7d75Swlei 
6141a681ceSwlei   static uint32_t
6241a681ceSwlei   getBaseDiscriminator(unsigned Discriminator,
6341a681ceSwlei                        bool UseFSD = ProfileGeneratorBase::UseFSDiscriminator) {
6441a681ceSwlei     return UseFSD ? Discriminator
6541a681ceSwlei                   : DILocation::getBaseDiscriminatorFromDiscriminator(
6646cf7d75Swlei                         Discriminator, /* IsFSDiscriminator */ false);
6746cf7d75Swlei   }
6846cf7d75Swlei 
6941a681ceSwlei   static bool UseFSDiscriminator;
7041a681ceSwlei 
711f05b1a9Swlei protected:
72d5f20130Swlei   // Use SampleProfileWriter to serialize profile map
73d5f20130Swlei   void write(std::unique_ptr<SampleProfileWriter> Writer,
74d5f20130Swlei              SampleProfileMap &ProfileMap);
751f05b1a9Swlei   /*
761f05b1a9Swlei   For each region boundary point, mark if it is begin or end (or both) of
771f05b1a9Swlei   the region. Boundary points are inclusive. Log the sample count as well
781f05b1a9Swlei   so we can use it when we compute the sample count of each disjoint region
791f05b1a9Swlei   later. Note that there might be multiple ranges with different sample
801f05b1a9Swlei   count that share same begin/end point. We need to accumulate the sample
811f05b1a9Swlei   count for the boundary point for such case, because for the example
821f05b1a9Swlei   below,
831f05b1a9Swlei 
841f05b1a9Swlei   |<--100-->|
851f05b1a9Swlei   |<------200------>|
861f05b1a9Swlei   A         B       C
871f05b1a9Swlei 
881f05b1a9Swlei   sample count for disjoint region [A,B] would be 300.
891f05b1a9Swlei   */
901f05b1a9Swlei   void findDisjointRanges(RangeSample &DisjointRanges,
911f05b1a9Swlei                           const RangeSample &Ranges);
9223391febSHongtao Yu 
9323391febSHongtao Yu   // Go through each address from range to extract the top frame probe by
9423391febSHongtao Yu   // looking up in the Address2ProbeMap
9523391febSHongtao Yu   void extractProbesFromRange(const RangeSample &RangeCounter,
9623391febSHongtao Yu                               ProbeCounterMap &ProbeCounter,
9723391febSHongtao Yu                               bool FindDisjointRanges = true);
9823391febSHongtao Yu 
99d5f20130Swlei   // Helper function for updating body sample for a leaf location in
100d5f20130Swlei   // FunctionProfile
101d5f20130Swlei   void updateBodySamplesforFunctionProfile(FunctionSamples &FunctionProfile,
102d5f20130Swlei                                            const SampleContextFrame &LeafLoc,
103d5f20130Swlei                                            uint64_t Count);
104acfd0a34SHongtao Yu 
105acfd0a34SHongtao Yu   void updateFunctionSamples();
106acfd0a34SHongtao Yu 
107f5537643Swlei   void updateTotalSamples();
108c2e08abaSwlei 
109acfd0a34SHongtao Yu   void updateCallsiteSamples();
110acfd0a34SHongtao Yu 
11124f02517SLei Wang   void filterAmbiguousProfile(SampleProfileMap &Profiles);
11224f02517SLei Wang 
11324f02517SLei Wang   bool filterAmbiguousProfile(FunctionSamples &FS);
11424f02517SLei Wang 
11546765248Swlei   StringRef getCalleeNameForAddress(uint64_t TargetAddress);
116c2e08abaSwlei 
117aa58b7b1Swlei   void computeSummaryAndThreshold(SampleProfileMap &ProfileMap);
118c2e08abaSwlei 
119*b9d40a7aSLei Wang   void calculateBodySamplesAndSize(const FunctionSamples &FSamples,
120*b9d40a7aSLei Wang                                    uint64_t &TotalBodySamples,
121*b9d40a7aSLei Wang                                    uint64_t &FuncBodySize);
122c2e08abaSwlei 
123*b9d40a7aSLei Wang   double calculateDensity(const SampleProfileMap &Profiles);
124*b9d40a7aSLei Wang 
125*b9d40a7aSLei Wang   void calculateAndShowDensity(const SampleProfileMap &Profiles);
126c2e08abaSwlei 
127c2e08abaSwlei   void showDensitySuggestion(double Density);
128c2e08abaSwlei 
1293f970168SHongtao Yu   void collectProfiledFunctions();
1303f970168SHongtao Yu 
131aa58b7b1Swlei   bool collectFunctionsFromRawProfile(
132aa58b7b1Swlei       std::unordered_set<const BinaryFunction *> &ProfiledFunctions);
133aa58b7b1Swlei 
134aa58b7b1Swlei   // Collect profiled Functions for llvm sample profile input.
135aa58b7b1Swlei   virtual bool collectFunctionsFromLLVMProfile(
136aa58b7b1Swlei       std::unordered_set<const BinaryFunction *> &ProfiledFunctions) = 0;
137aa58b7b1Swlei 
13824f02517SLei Wang   // List of function prefix to filter out.
13924f02517SLei Wang   static constexpr const char *FuncPrefixsToFilter[] = {"__cxx_global_var_init",
14024f02517SLei Wang                                                         "__tls_init"};
14124f02517SLei Wang 
142c2e08abaSwlei   // Thresholds from profile summary to answer isHotCount/isColdCount queries.
143c2e08abaSwlei   uint64_t HotCountThreshold;
144c2e08abaSwlei 
145c2e08abaSwlei   uint64_t ColdCountThreshold;
146c2e08abaSwlei 
147937924ebSHongtao Yu   ProfiledBinary *Binary = nullptr;
148937924ebSHongtao Yu 
149a4190037SHongtao Yu   std::unique_ptr<ProfileSummary> Summary;
150a4190037SHongtao Yu 
1511f05b1a9Swlei   // Used by SampleProfileWriter
152b9db7036SHongtao Yu   SampleProfileMap ProfileMap;
153f812c192Swlei 
154937924ebSHongtao Yu   const ContextSampleCounterMap *SampleCounters = nullptr;
1551f05b1a9Swlei };
1561f05b1a9Swlei 
157d5f20130Swlei class ProfileGenerator : public ProfileGeneratorBase {
1581f05b1a9Swlei 
1591f05b1a9Swlei public:
ProfileGenerator(ProfiledBinary * Binary,const ContextSampleCounterMap * Counters)160d5f20130Swlei   ProfileGenerator(ProfiledBinary *Binary,
161937924ebSHongtao Yu                    const ContextSampleCounterMap *Counters)
162d5f20130Swlei       : ProfileGeneratorBase(Binary, Counters){};
ProfileGenerator(ProfiledBinary * Binary,const SampleProfileMap && Profiles)163937924ebSHongtao Yu   ProfileGenerator(ProfiledBinary *Binary, const SampleProfileMap &&Profiles)
164937924ebSHongtao Yu       : ProfileGeneratorBase(Binary, std::move(Profiles)){};
165d5f20130Swlei   void generateProfile() override;
166d5f20130Swlei 
167d5f20130Swlei private:
168d5f20130Swlei   void generateLineNumBasedProfile();
16923391febSHongtao Yu   void generateProbeBasedProfile();
17028277e9bSwlei   RangeSample preprocessRangeCounter(const RangeSample &RangeCounter);
171ef0e0adcSWilliam Junda Huang   FunctionSamples &getTopLevelFunctionProfile(FunctionId FuncName);
172d5f20130Swlei   // Helper function to get the leaf frame's FunctionProfile by traversing the
173d5f20130Swlei   // inline stack and meanwhile it adds the total samples for each frame's
174d5f20130Swlei   // function profile.
175d5f20130Swlei   FunctionSamples &
176484a569eSwlei   getLeafProfileAndAddTotalSamples(const SampleContextFrameVector &FrameVec,
177484a569eSwlei                                    uint64_t Count);
178d5f20130Swlei   void populateBodySamplesForAllFunctions(const RangeSample &RangeCounter);
179d5f20130Swlei   void
180d5f20130Swlei   populateBoundarySamplesForAllFunctions(const BranchSample &BranchCounters);
18123391febSHongtao Yu   void
182937924ebSHongtao Yu   populateBodySamplesWithProbesForAllFunctions(const RangeSample &RangeCounter);
183937924ebSHongtao Yu   void populateBoundarySamplesWithProbesForAllFunctions(
184937924ebSHongtao Yu       const BranchSample &BranchCounters);
185c2e08abaSwlei   void postProcessProfiles();
18627cb3707Swlei   void trimColdProfiles(const SampleProfileMap &Profiles,
18727cb3707Swlei                         uint64_t ColdCntThreshold);
188aa58b7b1Swlei   bool collectFunctionsFromLLVMProfile(
189aa58b7b1Swlei       std::unordered_set<const BinaryFunction *> &ProfiledFunctions) override;
190d5f20130Swlei };
191d5f20130Swlei 
192d5f20130Swlei class CSProfileGenerator : public ProfileGeneratorBase {
193d5f20130Swlei public:
CSProfileGenerator(ProfiledBinary * Binary,const ContextSampleCounterMap * Counters)194f812c192Swlei   CSProfileGenerator(ProfiledBinary *Binary,
195937924ebSHongtao Yu                      const ContextSampleCounterMap *Counters)
196d5f20130Swlei       : ProfileGeneratorBase(Binary, Counters){};
CSProfileGenerator(ProfiledBinary * Binary,SampleProfileMap & Profiles)197aa58b7b1Swlei   CSProfileGenerator(ProfiledBinary *Binary, SampleProfileMap &Profiles)
198aa58b7b1Swlei       : ProfileGeneratorBase(Binary), ContextTracker(Profiles, nullptr){};
199a5d30421SWenlei He   void generateProfile() override;
2001f05b1a9Swlei 
201856a6a50Swlei   // Trim the context stack at a given depth.
202856a6a50Swlei   template <typename T>
203856a6a50Swlei   static void trimContext(SmallVectorImpl<T> &S, int Depth = MaxContextDepth) {
204856a6a50Swlei     if (Depth < 0 || static_cast<size_t>(Depth) >= S.size())
205856a6a50Swlei       return;
206856a6a50Swlei     std::copy(S.begin() + S.size() - static_cast<size_t>(Depth), S.end(),
207856a6a50Swlei               S.begin());
208856a6a50Swlei     S.resize(Depth);
209856a6a50Swlei   }
210856a6a50Swlei 
211ac14bb14Swlei   // Remove adjacent repeated context sequences up to a given sequence length,
212ac14bb14Swlei   // -1 means no size limit. Note that repeated sequences are identified based
213ac14bb14Swlei   // on the exact call site, this is finer granularity than function recursion.
214ac14bb14Swlei   template <typename T>
215ac14bb14Swlei   static void compressRecursionContext(SmallVectorImpl<T> &Context,
216ac14bb14Swlei                                        int32_t CSize = MaxCompressionSize) {
217ac14bb14Swlei     uint32_t I = 1;
218ac14bb14Swlei     uint32_t HS = static_cast<uint32_t>(Context.size() / 2);
219ac14bb14Swlei     uint32_t MaxDedupSize =
220ac14bb14Swlei         CSize == -1 ? HS : std::min(static_cast<uint32_t>(CSize), HS);
221ac14bb14Swlei     auto BeginIter = Context.begin();
222ac14bb14Swlei     // Use an in-place algorithm to save memory copy
223ac14bb14Swlei     // End indicates the end location of current iteration's data
224ac14bb14Swlei     uint32_t End = 0;
225ac14bb14Swlei     // Deduplicate from length 1 to the max possible size of a repeated
226ac14bb14Swlei     // sequence.
227ac14bb14Swlei     while (I <= MaxDedupSize) {
228ac14bb14Swlei       // This is a linear algorithm that deduplicates adjacent repeated
229ac14bb14Swlei       // sequences of size I. The deduplication detection runs on a sliding
230ac14bb14Swlei       // window whose size is 2*I and it keeps sliding the window to deduplicate
231ac14bb14Swlei       // the data inside. Once duplication is detected, deduplicate it by
232ac14bb14Swlei       // skipping the right half part of the window, otherwise just copy back
233ac14bb14Swlei       // the new one by appending them at the back of End pointer(for the next
234ac14bb14Swlei       // iteration).
235ac14bb14Swlei       //
236ac14bb14Swlei       // For example:
237ac14bb14Swlei       // Input: [a1, a2, b1, b2]
238ac14bb14Swlei       // (Added index to distinguish the same char, the origin is [a, a, b,
239ac14bb14Swlei       // b], the size of the dedup window is 2(I = 1) at the beginning)
240ac14bb14Swlei       //
241ac14bb14Swlei       // 1) The initial status is a dummy window[null, a1], then just copy the
242ac14bb14Swlei       // right half of the window(End = 0), then slide the window.
243ac14bb14Swlei       // Result: [a1], a2, b1, b2 (End points to the element right before ],
244ac14bb14Swlei       // after ] is the data of the previous iteration)
245ac14bb14Swlei       //
246ac14bb14Swlei       // 2) Next window is [a1, a2]. Since a1 == a2, then skip the right half of
247ac14bb14Swlei       // the window i.e the duplication happen. Only slide the window.
248ac14bb14Swlei       // Result: [a1], a2, b1, b2
249ac14bb14Swlei       //
250ac14bb14Swlei       // 3) Next window is [a2, b1], copy the right half of the window(b1 is
251ac14bb14Swlei       // new) to the End and slide the window.
252ac14bb14Swlei       // Result: [a1, b1], b1, b2
253ac14bb14Swlei       //
254ac14bb14Swlei       // 4) Next window is [b1, b2], same to 2), skip b2.
255ac14bb14Swlei       // Result: [a1, b1], b1, b2
256ac14bb14Swlei       // After resize, it will be [a, b]
257ac14bb14Swlei 
258ac14bb14Swlei       // Use pointers like below to do comparison inside the window
259ac14bb14Swlei       //    [a         b         c        a       b        c]
260ac14bb14Swlei       //     |         |         |                |        |
261ac14bb14Swlei       // LeftBoundary Left     Right           Left+I    Right+I
262ac14bb14Swlei       // A duplication found if Left < LeftBoundry.
263ac14bb14Swlei 
264ac14bb14Swlei       int32_t Right = I - 1;
265ac14bb14Swlei       End = I;
266ac14bb14Swlei       int32_t LeftBoundary = 0;
267ac14bb14Swlei       while (Right + I < Context.size()) {
268ac14bb14Swlei         // To avoids scanning a part of a sequence repeatedly, it finds out
269ac14bb14Swlei         // the common suffix of two hald in the window. The common suffix will
270ac14bb14Swlei         // serve as the common prefix of next possible pair of duplicate
271ac14bb14Swlei         // sequences. The non-common part will be ignored and never scanned
272ac14bb14Swlei         // again.
273ac14bb14Swlei 
274ac14bb14Swlei         // For example.
275ac14bb14Swlei         // Input: [a, b1], c1, b2, c2
276ac14bb14Swlei         // I = 2
277ac14bb14Swlei         //
278ac14bb14Swlei         // 1) For the window [a, b1, c1, b2], non-common-suffix for the right
279ac14bb14Swlei         // part is 'c1', copy it and only slide the window 1 step.
280ac14bb14Swlei         // Result: [a, b1, c1], b2, c2
281ac14bb14Swlei         //
282ac14bb14Swlei         // 2) Next window is [b1, c1, b2, c2], so duplication happen.
283ac14bb14Swlei         // Result after resize: [a, b, c]
284ac14bb14Swlei 
285ac14bb14Swlei         int32_t Left = Right;
286ac14bb14Swlei         while (Left >= LeftBoundary && Context[Left] == Context[Left + I]) {
287ac14bb14Swlei           // Find the longest suffix inside the window. When stops, Left points
288ac14bb14Swlei           // at the diverging point in the current sequence.
289ac14bb14Swlei           Left--;
290ac14bb14Swlei         }
291ac14bb14Swlei 
292ac14bb14Swlei         bool DuplicationFound = (Left < LeftBoundary);
293ac14bb14Swlei         // Don't need to recheck the data before Right
294ac14bb14Swlei         LeftBoundary = Right + 1;
295ac14bb14Swlei         if (DuplicationFound) {
296ac14bb14Swlei           // Duplication found, skip right half of the window.
297ac14bb14Swlei           Right += I;
298ac14bb14Swlei         } else {
299ac14bb14Swlei           // Copy the non-common-suffix part of the adjacent sequence.
300ac14bb14Swlei           std::copy(BeginIter + Right + 1, BeginIter + Left + I + 1,
301ac14bb14Swlei                     BeginIter + End);
302ac14bb14Swlei           End += Left + I - Right;
303ac14bb14Swlei           // Only slide the window by the size of non-common-suffix
304ac14bb14Swlei           Right = Left + I;
305ac14bb14Swlei         }
306ac14bb14Swlei       }
307ac14bb14Swlei       // Don't forget the remaining part that's not scanned.
308ac14bb14Swlei       std::copy(BeginIter + Right + 1, Context.end(), BeginIter + End);
309ac14bb14Swlei       End += Context.size() - Right - 1;
310ac14bb14Swlei       I++;
311ac14bb14Swlei       Context.resize(End);
312ac14bb14Swlei       MaxDedupSize = std::min(static_cast<uint32_t>(End / 2), MaxDedupSize);
313ac14bb14Swlei     }
314ac14bb14Swlei   }
315ac14bb14Swlei 
316d5f20130Swlei private:
317d5f20130Swlei   void generateLineNumBasedProfile();
318eba57492Swlei 
319eba57492Swlei   FunctionSamples *getOrCreateFunctionSamples(ContextTrieNode *ContextNode,
3201410db70SWenlei He                                               bool WasLeafInlined = false);
321eba57492Swlei 
322eba57492Swlei   // Lookup or create ContextTrieNode for the context, FunctionSamples is
323eba57492Swlei   // created inside this function.
324eba57492Swlei   ContextTrieNode *getOrCreateContextNode(const SampleContextFrames Context,
325eba57492Swlei                                           bool WasLeafInlined = false);
326eba57492Swlei 
327ce40843aSwlei   // For profiled only functions, on-demand compute their inline context
328ce40843aSwlei   // function byte size which is used by the pre-inliner.
329ce40843aSwlei   void computeSizeForProfiledFunctions();
33030b02323SWenlei He   // Post processing for profiles before writing out, such as mermining
33130b02323SWenlei He   // and trimming cold profiles, running preinliner on profiles.
33230b02323SWenlei He   void postProcessProfiles();
333d5f20130Swlei 
334d5f20130Swlei   void populateBodySamplesForFunction(FunctionSamples &FunctionProfile,
335f812c192Swlei                                       const RangeSample &RangeCounters);
336eba57492Swlei 
337eba57492Swlei   void populateBoundarySamplesForFunction(ContextTrieNode *CallerNode,
338f812c192Swlei                                           const BranchSample &BranchCounters);
339eba57492Swlei 
340eba57492Swlei   void populateInferredFunctionSamples(ContextTrieNode &Node);
341eba57492Swlei 
342eba57492Swlei   void updateFunctionSamples();
343ac14bb14Swlei 
344d5f20130Swlei   void generateProbeBasedProfile();
34523391febSHongtao Yu 
346c82b24f4Swlei   // Fill in function body samples from probes
347b9db7036SHongtao Yu   void populateBodySamplesWithProbes(const RangeSample &RangeCounter,
3485d7950a4SHongtao Yu                                      const AddrBasedCtxKey *CtxKey);
349c82b24f4Swlei   // Fill in boundary samples for a call probe
350b9db7036SHongtao Yu   void populateBoundarySamplesWithProbes(const BranchSample &BranchCounter,
3515d7950a4SHongtao Yu                                          const AddrBasedCtxKey *CtxKey);
352eba57492Swlei 
353eba57492Swlei   ContextTrieNode *
3545d7950a4SHongtao Yu   getContextNodeForLeafProbe(const AddrBasedCtxKey *CtxKey,
355eba57492Swlei                              const MCDecodedPseudoProbe *LeafProbe);
356eba57492Swlei 
357c82b24f4Swlei   // Helper function to get FunctionSamples for the leaf probe
358ac14bb14Swlei   FunctionSamples &
3595d7950a4SHongtao Yu   getFunctionProfileForLeafProbe(const AddrBasedCtxKey *CtxKey,
360f812c192Swlei                                  const MCDecodedPseudoProbe *LeafProbe);
361d5f20130Swlei 
362eba57492Swlei   void convertToProfileMap(ContextTrieNode &Node,
363eba57492Swlei                            SampleContextFrameVector &Context);
364eba57492Swlei 
365eba57492Swlei   void convertToProfileMap();
366eba57492Swlei 
367aa58b7b1Swlei   void computeSummaryAndThreshold();
368aa58b7b1Swlei 
369aa58b7b1Swlei   bool collectFunctionsFromLLVMProfile(
370aa58b7b1Swlei       std::unordered_set<const BinaryFunction *> &ProfiledFunctions) override;
371aa58b7b1Swlei 
3725d7950a4SHongtao Yu   void initializeMissingFrameInferrer();
3735d7950a4SHongtao Yu 
3745d7950a4SHongtao Yu   // Given an input `Context`, output `NewContext` with inferred missing tail
3755d7950a4SHongtao Yu   // call frames.
3765d7950a4SHongtao Yu   void inferMissingFrames(const SmallVectorImpl<uint64_t> &Context,
3775d7950a4SHongtao Yu                           SmallVectorImpl<uint64_t> &NewContext);
3785d7950a4SHongtao Yu 
getRootContext()379eba57492Swlei   ContextTrieNode &getRootContext() { return ContextTracker.getRootContext(); };
380eba57492Swlei 
381eba57492Swlei   // The container for holding the FunctionSamples used by context trie.
382eba57492Swlei   std::list<FunctionSamples> FSamplesList;
383eba57492Swlei 
384d5f20130Swlei   // Underlying context table serves for sample profile writer.
385d5f20130Swlei   std::unordered_set<SampleContextFrameVector, SampleContextFrameHash> Contexts;
386d5f20130Swlei 
387eba57492Swlei   SampleContextTracker ContextTracker;
388eba57492Swlei 
389eba57492Swlei   bool IsProfileValidOnTrie = true;
390eba57492Swlei 
391d5f20130Swlei public:
392d5f20130Swlei   // Deduplicate adjacent repeated context sequences up to a given sequence
393d5f20130Swlei   // length. -1 means no size limit.
394d5f20130Swlei   static int32_t MaxCompressionSize;
395d5f20130Swlei   static int MaxContextDepth;
396c681400bSwlei };
397c681400bSwlei 
3981f05b1a9Swlei } // end namespace sampleprof
3991f05b1a9Swlei } // end namespace llvm
4001f05b1a9Swlei 
4011f05b1a9Swlei #endif
402