1 //===-- ProfileGenerator.cpp - Profile Generator  ---------------*- 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 #include "ProfileGenerator.h"
9 #include "ErrorHandling.h"
10 #include "PerfReader.h"
11 #include "ProfiledBinary.h"
12 #include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"
13 #include "llvm/ProfileData/ProfileCommon.h"
14 #include <algorithm>
15 #include <float.h>
16 #include <unordered_set>
17 #include <utility>
18 
19 cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
20                                     cl::Required,
21                                     cl::desc("Output profile file"));
22 static cl::alias OutputA("o", cl::desc("Alias for --output"),
23                          cl::aliasopt(OutputFilename));
24 
25 static cl::opt<SampleProfileFormat> OutputFormat(
26     "format", cl::desc("Format of output profile"), cl::init(SPF_Ext_Binary),
27     cl::values(
28         clEnumValN(SPF_Binary, "binary", "Binary encoding (default)"),
29         clEnumValN(SPF_Compact_Binary, "compbinary", "Compact binary encoding"),
30         clEnumValN(SPF_Ext_Binary, "extbinary", "Extensible binary encoding"),
31         clEnumValN(SPF_Text, "text", "Text encoding"),
32         clEnumValN(SPF_GCC, "gcc",
33                    "GCC encoding (only meaningful for -sample)")));
34 
35 cl::opt<bool> UseMD5(
36     "use-md5", cl::init(false), cl::Hidden,
37     cl::desc("Use md5 to represent function names in the output profile (only "
38              "meaningful for -extbinary)"));
39 
40 static cl::opt<bool> PopulateProfileSymbolList(
41     "populate-profile-symbol-list", cl::init(false), cl::Hidden,
42     cl::desc("Populate profile symbol list (only meaningful for -extbinary)"));
43 
44 static cl::opt<bool> FillZeroForAllFuncs(
45     "fill-zero-for-all-funcs", cl::init(false), cl::Hidden,
46     cl::desc("Attribute all functions' range with zero count "
47              "even it's not hit by any samples."));
48 
49 static cl::opt<int32_t, true> RecursionCompression(
50     "compress-recursion",
51     cl::desc("Compressing recursion by deduplicating adjacent frame "
52              "sequences up to the specified size. -1 means no size limit."),
53     cl::Hidden,
54     cl::location(llvm::sampleprof::CSProfileGenerator::MaxCompressionSize));
55 
56 static cl::opt<bool>
57     TrimColdProfile("trim-cold-profile", cl::init(false), cl::ZeroOrMore,
58                     cl::desc("If the total count of the profile is smaller "
59                              "than threshold, it will be trimmed."));
60 
61 static cl::opt<bool> CSProfMergeColdContext(
62     "csprof-merge-cold-context", cl::init(true), cl::ZeroOrMore,
63     cl::desc("If the total count of context profile is smaller than "
64              "the threshold, it will be merged into context-less base "
65              "profile."));
66 
67 static cl::opt<uint32_t> CSProfMaxColdContextDepth(
68     "csprof-max-cold-context-depth", cl::init(1), cl::ZeroOrMore,
69     cl::desc("Keep the last K contexts while merging cold profile. 1 means the "
70              "context-less base profile"));
71 
72 static cl::opt<int, true> CSProfMaxContextDepth(
73     "csprof-max-context-depth", cl::ZeroOrMore,
74     cl::desc("Keep the last K contexts while merging profile. -1 means no "
75              "depth limit."),
76     cl::location(llvm::sampleprof::CSProfileGenerator::MaxContextDepth));
77 
78 static cl::opt<double> HotFunctionDensityThreshold(
79     "hot-function-density-threshold", llvm::cl::init(1000),
80     llvm::cl::desc(
81         "specify density threshold for hot functions (default: 1000)"),
82     llvm::cl::Optional);
83 static cl::opt<bool> ShowDensity("show-density", llvm::cl::init(false),
84                                  llvm::cl::desc("show profile density details"),
85                                  llvm::cl::Optional);
86 
87 static cl::opt<bool> UpdateTotalSamples(
88     "update-total-samples", llvm::cl::init(false),
89     llvm::cl::desc(
90         "Update total samples by accumulating all its body samples."),
91     llvm::cl::Optional);
92 
93 extern cl::opt<int> ProfileSummaryCutoffHot;
94 
95 static cl::opt<bool> GenCSNestedProfile(
96     "gen-cs-nested-profile", cl::Hidden, cl::init(true),
97     cl::desc("Generate nested function profiles for CSSPGO"));
98 
99 using namespace llvm;
100 using namespace sampleprof;
101 
102 namespace llvm {
103 namespace sampleprof {
104 
105 // Initialize the MaxCompressionSize to -1 which means no size limit
106 int32_t CSProfileGenerator::MaxCompressionSize = -1;
107 
108 int CSProfileGenerator::MaxContextDepth = -1;
109 
110 bool ProfileGeneratorBase::UseFSDiscriminator = false;
111 
112 std::unique_ptr<ProfileGeneratorBase>
113 ProfileGeneratorBase::create(ProfiledBinary *Binary,
114                              const ContextSampleCounterMap *SampleCounters,
115                              bool ProfileIsCSFlat) {
116   std::unique_ptr<ProfileGeneratorBase> Generator;
117   if (ProfileIsCSFlat) {
118     if (Binary->useFSDiscriminator())
119       exitWithError("FS discriminator is not supported in CS profile.");
120     Generator.reset(new CSProfileGenerator(Binary, SampleCounters));
121   } else {
122     Generator.reset(new ProfileGenerator(Binary, SampleCounters));
123   }
124   ProfileGeneratorBase::UseFSDiscriminator = Binary->useFSDiscriminator();
125   FunctionSamples::ProfileIsFS = Binary->useFSDiscriminator();
126 
127   return Generator;
128 }
129 
130 std::unique_ptr<ProfileGeneratorBase>
131 ProfileGeneratorBase::create(ProfiledBinary *Binary,
132                              const SampleProfileMap &&Profiles,
133                              bool ProfileIsCSFlat) {
134   std::unique_ptr<ProfileGeneratorBase> Generator;
135   if (ProfileIsCSFlat) {
136     if (Binary->useFSDiscriminator())
137       exitWithError("FS discriminator is not supported in CS profile.");
138     Generator.reset(new CSProfileGenerator(Binary, std::move(Profiles)));
139   } else {
140     Generator.reset(new ProfileGenerator(Binary, std::move(Profiles)));
141   }
142   ProfileGeneratorBase::UseFSDiscriminator = Binary->useFSDiscriminator();
143   FunctionSamples::ProfileIsFS = Binary->useFSDiscriminator();
144 
145   return Generator;
146 }
147 
148 void ProfileGeneratorBase::write(std::unique_ptr<SampleProfileWriter> Writer,
149                                  SampleProfileMap &ProfileMap) {
150   // Populate profile symbol list if extended binary format is used.
151   ProfileSymbolList SymbolList;
152 
153   if (PopulateProfileSymbolList && OutputFormat == SPF_Ext_Binary) {
154     Binary->populateSymbolListFromDWARF(SymbolList);
155     Writer->setProfileSymbolList(&SymbolList);
156   }
157 
158   if (std::error_code EC = Writer->write(ProfileMap))
159     exitWithError(std::move(EC));
160 }
161 
162 void ProfileGeneratorBase::write() {
163   auto WriterOrErr = SampleProfileWriter::create(OutputFilename, OutputFormat);
164   if (std::error_code EC = WriterOrErr.getError())
165     exitWithError(EC, OutputFilename);
166 
167   if (UseMD5) {
168     if (OutputFormat != SPF_Ext_Binary)
169       WithColor::warning() << "-use-md5 is ignored. Specify "
170                               "--format=extbinary to enable it\n";
171     else
172       WriterOrErr.get()->setUseMD5();
173   }
174 
175   write(std::move(WriterOrErr.get()), ProfileMap);
176 }
177 
178 void ProfileGeneratorBase::showDensitySuggestion(double Density) {
179   if (Density == 0.0)
180     WithColor::warning() << "The --profile-summary-cutoff-hot option may be "
181                             "set too low. Please check your command.\n";
182   else if (Density < HotFunctionDensityThreshold)
183     WithColor::warning()
184         << "AutoFDO is estimated to optimize better with "
185         << format("%.1f", HotFunctionDensityThreshold / Density)
186         << "x more samples. Please consider increasing sampling rate or "
187            "profiling for longer duration to get more samples.\n";
188 
189   if (ShowDensity)
190     outs() << "Minimum profile density for hot functions with top "
191            << format("%.2f",
192                      static_cast<double>(ProfileSummaryCutoffHot.getValue()) /
193                          10000)
194            << "% total samples: " << format("%.1f", Density) << "\n";
195 }
196 
197 double ProfileGeneratorBase::calculateDensity(const SampleProfileMap &Profiles,
198                                               uint64_t HotCntThreshold) {
199   double Density = DBL_MAX;
200   std::vector<const FunctionSamples *> HotFuncs;
201   for (auto &I : Profiles) {
202     auto &FuncSamples = I.second;
203     if (FuncSamples.getTotalSamples() < HotCntThreshold)
204       continue;
205     HotFuncs.emplace_back(&FuncSamples);
206   }
207 
208   for (auto *FuncSamples : HotFuncs) {
209     auto *Func = Binary->getBinaryFunction(FuncSamples->getName());
210     if (!Func)
211       continue;
212     uint64_t FuncSize = Func->getFuncSize();
213     if (FuncSize == 0)
214       continue;
215     Density =
216         std::min(Density, static_cast<double>(FuncSamples->getTotalSamples()) /
217                               FuncSize);
218   }
219 
220   return Density == DBL_MAX ? 0.0 : Density;
221 }
222 
223 void ProfileGeneratorBase::findDisjointRanges(RangeSample &DisjointRanges,
224                                               const RangeSample &Ranges) {
225 
226   /*
227   Regions may overlap with each other. Using the boundary info, find all
228   disjoint ranges and their sample count. BoundaryPoint contains the count
229   multiple samples begin/end at this points.
230 
231   |<--100-->|           Sample1
232   |<------200------>|   Sample2
233   A         B       C
234 
235   In the example above,
236   Sample1 begins at A, ends at B, its value is 100.
237   Sample2 beings at A, ends at C, its value is 200.
238   For A, BeginCount is the sum of sample begins at A, which is 300 and no
239   samples ends at A, so EndCount is 0.
240   Then boundary points A, B, and C with begin/end counts are:
241   A: (300, 0)
242   B: (0, 100)
243   C: (0, 200)
244   */
245   struct BoundaryPoint {
246     // Sum of sample counts beginning at this point
247     uint64_t BeginCount = UINT64_MAX;
248     // Sum of sample counts ending at this point
249     uint64_t EndCount = UINT64_MAX;
250     // Is the begin point of a zero range.
251     bool IsZeroRangeBegin = false;
252     // Is the end point of a zero range.
253     bool IsZeroRangeEnd = false;
254 
255     void addBeginCount(uint64_t Count) {
256       if (BeginCount == UINT64_MAX)
257         BeginCount = 0;
258       BeginCount += Count;
259     }
260 
261     void addEndCount(uint64_t Count) {
262       if (EndCount == UINT64_MAX)
263         EndCount = 0;
264       EndCount += Count;
265     }
266   };
267 
268   /*
269   For the above example. With boundary points, follwing logic finds two
270   disjoint region of
271 
272   [A,B]:   300
273   [B+1,C]: 200
274 
275   If there is a boundary point that both begin and end, the point itself
276   becomes a separate disjoint region. For example, if we have original
277   ranges of
278 
279   |<--- 100 --->|
280                 |<--- 200 --->|
281   A             B             C
282 
283   there are three boundary points with their begin/end counts of
284 
285   A: (100, 0)
286   B: (200, 100)
287   C: (0, 200)
288 
289   the disjoint ranges would be
290 
291   [A, B-1]: 100
292   [B, B]:   300
293   [B+1, C]: 200.
294 
295   Example for zero value range:
296 
297     |<--- 100 --->|
298                        |<--- 200 --->|
299   |<---------------  0 ----------------->|
300   A  B            C    D             E   F
301 
302   [A, B-1]  : 0
303   [B, C]    : 100
304   [C+1, D-1]: 0
305   [D, E]    : 200
306   [E+1, F]  : 0
307   */
308   std::map<uint64_t, BoundaryPoint> Boundaries;
309 
310   for (const auto &Item : Ranges) {
311     assert(Item.first.first <= Item.first.second &&
312            "Invalid instruction range");
313     auto &BeginPoint = Boundaries[Item.first.first];
314     auto &EndPoint = Boundaries[Item.first.second];
315     uint64_t Count = Item.second;
316 
317     BeginPoint.addBeginCount(Count);
318     EndPoint.addEndCount(Count);
319     if (Count == 0) {
320       BeginPoint.IsZeroRangeBegin = true;
321       EndPoint.IsZeroRangeEnd = true;
322     }
323   }
324 
325   // Use UINT64_MAX to indicate there is no existing range between BeginAddress
326   // and the next valid address
327   uint64_t BeginAddress = UINT64_MAX;
328   int ZeroRangeDepth = 0;
329   uint64_t Count = 0;
330   for (const auto &Item : Boundaries) {
331     uint64_t Address = Item.first;
332     const BoundaryPoint &Point = Item.second;
333     if (Point.BeginCount != UINT64_MAX) {
334       if (BeginAddress != UINT64_MAX)
335         DisjointRanges[{BeginAddress, Address - 1}] = Count;
336       Count += Point.BeginCount;
337       BeginAddress = Address;
338       ZeroRangeDepth += Point.IsZeroRangeBegin;
339     }
340     if (Point.EndCount != UINT64_MAX) {
341       assert((BeginAddress != UINT64_MAX) &&
342              "First boundary point cannot be 'end' point");
343       DisjointRanges[{BeginAddress, Address}] = Count;
344       assert(Count >= Point.EndCount && "Mismatched live ranges");
345       Count -= Point.EndCount;
346       BeginAddress = Address + 1;
347       ZeroRangeDepth -= Point.IsZeroRangeEnd;
348       // If the remaining count is zero and it's no longer in a zero range, this
349       // means we consume all the ranges before, thus mark BeginAddress as
350       // UINT64_MAX. e.g. supposing we have two non-overlapping ranges:
351       //  [<---- 10 ---->]
352       //                       [<---- 20 ---->]
353       //   A             B     C              D
354       // The BeginAddress(B+1) will reset to invalid(UINT64_MAX), so we won't
355       // have the [B+1, C-1] zero range.
356       if (Count == 0 && ZeroRangeDepth == 0)
357         BeginAddress = UINT64_MAX;
358     }
359   }
360 }
361 
362 void ProfileGeneratorBase::updateBodySamplesforFunctionProfile(
363     FunctionSamples &FunctionProfile, const SampleContextFrame &LeafLoc,
364     uint64_t Count) {
365   // Use the maximum count of samples with same line location
366   uint32_t Discriminator = getBaseDiscriminator(LeafLoc.Location.Discriminator);
367 
368   // Use duplication factor to compensated for loop unroll/vectorization.
369   // Note that this is only needed when we're taking MAX of the counts at
370   // the location instead of SUM.
371   Count *= getDuplicationFactor(LeafLoc.Location.Discriminator);
372 
373   ErrorOr<uint64_t> R =
374       FunctionProfile.findSamplesAt(LeafLoc.Location.LineOffset, Discriminator);
375 
376   uint64_t PreviousCount = R ? R.get() : 0;
377   if (PreviousCount <= Count) {
378     FunctionProfile.addBodySamples(LeafLoc.Location.LineOffset, Discriminator,
379                                    Count - PreviousCount);
380   }
381 }
382 
383 void ProfileGeneratorBase::updateTotalSamples() {
384   if (!UpdateTotalSamples)
385     return;
386 
387   for (auto &Item : ProfileMap) {
388     FunctionSamples &FunctionProfile = Item.second;
389     FunctionProfile.updateTotalSamples();
390   }
391 }
392 
393 void ProfileGeneratorBase::collectProfiledFunctions() {
394   std::unordered_set<const BinaryFunction *> ProfiledFunctions;
395   if (SampleCounters) {
396     // Go through all the stacks, ranges and branches in sample counters, use
397     // the start of the range to look up the function it belongs and record the
398     // function.
399     for (const auto &CI : *SampleCounters) {
400       if (const auto *CtxKey = dyn_cast<AddrBasedCtxKey>(CI.first.getPtr())) {
401         for (auto Addr : CtxKey->Context) {
402           if (FuncRange *FRange = Binary->findFuncRangeForOffset(
403                   Binary->virtualAddrToOffset(Addr)))
404             ProfiledFunctions.insert(FRange->Func);
405         }
406       }
407 
408       for (auto Item : CI.second.RangeCounter) {
409         uint64_t StartOffset = Item.first.first;
410         if (FuncRange *FRange = Binary->findFuncRangeForOffset(StartOffset))
411           ProfiledFunctions.insert(FRange->Func);
412       }
413 
414       for (auto Item : CI.second.BranchCounter) {
415         uint64_t SourceOffset = Item.first.first;
416         uint64_t TargetOffset = Item.first.first;
417         if (FuncRange *FRange = Binary->findFuncRangeForOffset(SourceOffset))
418           ProfiledFunctions.insert(FRange->Func);
419         if (FuncRange *FRange = Binary->findFuncRangeForOffset(TargetOffset))
420           ProfiledFunctions.insert(FRange->Func);
421       }
422     }
423   } else {
424     // This is for the case the input is a llvm sample profile.
425     for (const auto &FS : ProfileMap) {
426       if (auto *Func = Binary->getBinaryFunction(FS.first.getName()))
427         ProfiledFunctions.insert(Func);
428     }
429   }
430 
431   Binary->setProfiledFunctions(ProfiledFunctions);
432 }
433 
434 FunctionSamples &
435 ProfileGenerator::getTopLevelFunctionProfile(StringRef FuncName) {
436   SampleContext Context(FuncName);
437   auto Ret = ProfileMap.emplace(Context, FunctionSamples());
438   if (Ret.second) {
439     FunctionSamples &FProfile = Ret.first->second;
440     FProfile.setContext(Context);
441   }
442   return Ret.first->second;
443 }
444 
445 void ProfileGenerator::generateProfile() {
446   collectProfiledFunctions();
447 
448   if (Binary->usePseudoProbes())
449     Binary->decodePseudoProbe();
450 
451   if (SampleCounters) {
452     if (Binary->usePseudoProbes()) {
453       generateProbeBasedProfile();
454     } else {
455       generateLineNumBasedProfile();
456     }
457   }
458 
459   postProcessProfiles();
460 }
461 
462 void ProfileGenerator::postProcessProfiles() {
463   computeSummaryAndThreshold();
464   trimColdProfiles(ProfileMap, ColdCountThreshold);
465   calculateAndShowDensity(ProfileMap);
466 }
467 
468 void ProfileGenerator::trimColdProfiles(const SampleProfileMap &Profiles,
469                                         uint64_t ColdCntThreshold) {
470   if (!TrimColdProfile)
471     return;
472 
473   // Move cold profiles into a tmp container.
474   std::vector<SampleContext> ColdProfiles;
475   for (const auto &I : ProfileMap) {
476     if (I.second.getTotalSamples() < ColdCntThreshold)
477       ColdProfiles.emplace_back(I.first);
478   }
479 
480   // Remove the cold profile from ProfileMap.
481   for (const auto &I : ColdProfiles)
482     ProfileMap.erase(I);
483 }
484 
485 void ProfileGenerator::generateLineNumBasedProfile() {
486   assert(SampleCounters->size() == 1 &&
487          "Must have one entry for profile generation.");
488   const SampleCounter &SC = SampleCounters->begin()->second;
489   // Fill in function body samples
490   populateBodySamplesForAllFunctions(SC.RangeCounter);
491   // Fill in boundary sample counts as well as call site samples for calls
492   populateBoundarySamplesForAllFunctions(SC.BranchCounter);
493 
494   updateTotalSamples();
495 }
496 
497 void ProfileGenerator::generateProbeBasedProfile() {
498   assert(SampleCounters->size() == 1 &&
499          "Must have one entry for profile generation.");
500   // Enable pseudo probe functionalities in SampleProf
501   FunctionSamples::ProfileIsProbeBased = true;
502   const SampleCounter &SC = SampleCounters->begin()->second;
503   // Fill in function body samples
504   populateBodySamplesWithProbesForAllFunctions(SC.RangeCounter);
505   // Fill in boundary sample counts as well as call site samples for calls
506   populateBoundarySamplesWithProbesForAllFunctions(SC.BranchCounter);
507 
508   updateTotalSamples();
509 }
510 
511 void ProfileGenerator::populateBodySamplesWithProbesForAllFunctions(
512     const RangeSample &RangeCounter) {
513   ProbeCounterMap ProbeCounter;
514   // preprocessRangeCounter returns disjoint ranges, so no longer to redo it
515   // inside extractProbesFromRange.
516   extractProbesFromRange(preprocessRangeCounter(RangeCounter), ProbeCounter,
517                          false);
518 
519   for (const auto &PI : ProbeCounter) {
520     const MCDecodedPseudoProbe *Probe = PI.first;
521     uint64_t Count = PI.second;
522     SampleContextFrameVector FrameVec;
523     Binary->getInlineContextForProbe(Probe, FrameVec, true);
524     FunctionSamples &FunctionProfile =
525         getLeafProfileAndAddTotalSamples(FrameVec, Count);
526     FunctionProfile.addBodySamplesForProbe(Probe->getIndex(), Count);
527     if (Probe->isEntry())
528       FunctionProfile.addHeadSamples(Count);
529   }
530 }
531 
532 void ProfileGenerator::populateBoundarySamplesWithProbesForAllFunctions(
533     const BranchSample &BranchCounters) {
534   for (const auto &Entry : BranchCounters) {
535     uint64_t SourceOffset = Entry.first.first;
536     uint64_t TargetOffset = Entry.first.second;
537     uint64_t Count = Entry.second;
538     assert(Count != 0 && "Unexpected zero weight branch");
539 
540     StringRef CalleeName = getCalleeNameForOffset(TargetOffset);
541     if (CalleeName.size() == 0)
542       continue;
543 
544     uint64_t SourceAddress = Binary->offsetToVirtualAddr(SourceOffset);
545     const MCDecodedPseudoProbe *CallProbe =
546         Binary->getCallProbeForAddr(SourceAddress);
547     if (CallProbe == nullptr)
548       continue;
549 
550     // Record called target sample and its count.
551     SampleContextFrameVector FrameVec;
552     Binary->getInlineContextForProbe(CallProbe, FrameVec, true);
553 
554     if (!FrameVec.empty()) {
555       FunctionSamples &FunctionProfile =
556           getLeafProfileAndAddTotalSamples(FrameVec, 0);
557       FunctionProfile.addCalledTargetSamples(
558           FrameVec.back().Location.LineOffset, 0, CalleeName, Count);
559     }
560   }
561 }
562 
563 FunctionSamples &ProfileGenerator::getLeafProfileAndAddTotalSamples(
564     const SampleContextFrameVector &FrameVec, uint64_t Count) {
565   // Get top level profile
566   FunctionSamples *FunctionProfile =
567       &getTopLevelFunctionProfile(FrameVec[0].FuncName);
568   FunctionProfile->addTotalSamples(Count);
569   if (Binary->usePseudoProbes()) {
570     const auto *FuncDesc = Binary->getFuncDescForGUID(
571         Function::getGUID(FunctionProfile->getName()));
572     FunctionProfile->setFunctionHash(FuncDesc->FuncHash);
573   }
574 
575   for (size_t I = 1; I < FrameVec.size(); I++) {
576     LineLocation Callsite(
577         FrameVec[I - 1].Location.LineOffset,
578         getBaseDiscriminator(FrameVec[I - 1].Location.Discriminator));
579     FunctionSamplesMap &SamplesMap =
580         FunctionProfile->functionSamplesAt(Callsite);
581     auto Ret =
582         SamplesMap.emplace(FrameVec[I].FuncName.str(), FunctionSamples());
583     if (Ret.second) {
584       SampleContext Context(FrameVec[I].FuncName);
585       Ret.first->second.setContext(Context);
586     }
587     FunctionProfile = &Ret.first->second;
588     FunctionProfile->addTotalSamples(Count);
589     if (Binary->usePseudoProbes()) {
590       const auto *FuncDesc = Binary->getFuncDescForGUID(
591           Function::getGUID(FunctionProfile->getName()));
592       FunctionProfile->setFunctionHash(FuncDesc->FuncHash);
593     }
594   }
595 
596   return *FunctionProfile;
597 }
598 
599 RangeSample
600 ProfileGenerator::preprocessRangeCounter(const RangeSample &RangeCounter) {
601   RangeSample Ranges(RangeCounter.begin(), RangeCounter.end());
602   if (FillZeroForAllFuncs) {
603     for (auto &FuncI : Binary->getAllBinaryFunctions()) {
604       for (auto &R : FuncI.second.Ranges) {
605         Ranges[{R.first, R.second - 1}] += 0;
606       }
607     }
608   } else {
609     // For each range, we search for all ranges of the function it belongs to
610     // and initialize it with zero count, so it remains zero if doesn't hit any
611     // samples. This is to be consistent with compiler that interpret zero count
612     // as unexecuted(cold).
613     for (const auto &I : RangeCounter) {
614       uint64_t StartOffset = I.first.first;
615       for (const auto &Range : Binary->getRangesForOffset(StartOffset))
616         Ranges[{Range.first, Range.second - 1}] += 0;
617     }
618   }
619   RangeSample DisjointRanges;
620   findDisjointRanges(DisjointRanges, Ranges);
621   return DisjointRanges;
622 }
623 
624 void ProfileGenerator::populateBodySamplesForAllFunctions(
625     const RangeSample &RangeCounter) {
626   for (const auto &Range : preprocessRangeCounter(RangeCounter)) {
627     uint64_t RangeBegin = Binary->offsetToVirtualAddr(Range.first.first);
628     uint64_t RangeEnd = Binary->offsetToVirtualAddr(Range.first.second);
629     uint64_t Count = Range.second;
630 
631     InstructionPointer IP(Binary, RangeBegin, true);
632     // Disjoint ranges may have range in the middle of two instr,
633     // e.g. If Instr1 at Addr1, and Instr2 at Addr2, disjoint range
634     // can be Addr1+1 to Addr2-1. We should ignore such range.
635     if (IP.Address > RangeEnd)
636       continue;
637 
638     do {
639       uint64_t Offset = Binary->virtualAddrToOffset(IP.Address);
640       const SampleContextFrameVector &FrameVec =
641           Binary->getFrameLocationStack(Offset);
642       if (!FrameVec.empty()) {
643         // FIXME: As accumulating total count per instruction caused some
644         // regression, we changed to accumulate total count per byte as a
645         // workaround. Tuning hotness threshold on the compiler side might be
646         // necessary in the future.
647         FunctionSamples &FunctionProfile = getLeafProfileAndAddTotalSamples(
648             FrameVec, Count * Binary->getInstSize(Offset));
649         updateBodySamplesforFunctionProfile(FunctionProfile, FrameVec.back(),
650                                             Count);
651       }
652     } while (IP.advance() && IP.Address <= RangeEnd);
653   }
654 }
655 
656 StringRef ProfileGeneratorBase::getCalleeNameForOffset(uint64_t TargetOffset) {
657   // Get the function range by branch target if it's a call branch.
658   auto *FRange = Binary->findFuncRangeForStartOffset(TargetOffset);
659 
660   // We won't accumulate sample count for a range whose start is not the real
661   // function entry such as outlined function or inner labels.
662   if (!FRange || !FRange->IsFuncEntry)
663     return StringRef();
664 
665   return FunctionSamples::getCanonicalFnName(FRange->getFuncName());
666 }
667 
668 void ProfileGenerator::populateBoundarySamplesForAllFunctions(
669     const BranchSample &BranchCounters) {
670   for (const auto &Entry : BranchCounters) {
671     uint64_t SourceOffset = Entry.first.first;
672     uint64_t TargetOffset = Entry.first.second;
673     uint64_t Count = Entry.second;
674     assert(Count != 0 && "Unexpected zero weight branch");
675 
676     StringRef CalleeName = getCalleeNameForOffset(TargetOffset);
677     if (CalleeName.size() == 0)
678       continue;
679     // Record called target sample and its count.
680     const SampleContextFrameVector &FrameVec =
681         Binary->getFrameLocationStack(SourceOffset);
682     if (!FrameVec.empty()) {
683       FunctionSamples &FunctionProfile =
684           getLeafProfileAndAddTotalSamples(FrameVec, 0);
685       FunctionProfile.addCalledTargetSamples(
686           FrameVec.back().Location.LineOffset,
687           getBaseDiscriminator(FrameVec.back().Location.Discriminator),
688           CalleeName, Count);
689     }
690     // Add head samples for callee.
691     FunctionSamples &CalleeProfile = getTopLevelFunctionProfile(CalleeName);
692     CalleeProfile.addHeadSamples(Count);
693   }
694 }
695 
696 void ProfileGeneratorBase::calculateAndShowDensity(
697     const SampleProfileMap &Profiles) {
698   double Density = calculateDensity(Profiles, HotCountThreshold);
699   showDensitySuggestion(Density);
700 }
701 
702 FunctionSamples &CSProfileGenerator::getFunctionProfileForContext(
703     const SampleContextFrameVector &Context, bool WasLeafInlined) {
704   auto I = ProfileMap.find(SampleContext(Context));
705   if (I == ProfileMap.end()) {
706     // Save the new context for future references.
707     SampleContextFrames NewContext = *Contexts.insert(Context).first;
708     SampleContext FContext(NewContext, RawContext);
709     auto Ret = ProfileMap.emplace(FContext, FunctionSamples());
710     if (WasLeafInlined)
711       FContext.setAttribute(ContextWasInlined);
712     FunctionSamples &FProfile = Ret.first->second;
713     FProfile.setContext(FContext);
714     return Ret.first->second;
715   }
716   return I->second;
717 }
718 
719 void CSProfileGenerator::generateProfile() {
720   FunctionSamples::ProfileIsCSFlat = true;
721 
722   collectProfiledFunctions();
723 
724   if (Binary->usePseudoProbes())
725     Binary->decodePseudoProbe();
726 
727   if (SampleCounters) {
728     if (Binary->usePseudoProbes()) {
729       generateProbeBasedProfile();
730     } else {
731       generateLineNumBasedProfile();
732     }
733   }
734 
735   if (Binary->getTrackFuncContextSize())
736     computeSizeForProfiledFunctions();
737 
738   postProcessProfiles();
739 }
740 
741 void CSProfileGenerator::computeSizeForProfiledFunctions() {
742   std::unordered_set<const BinaryFunction *> ProfiledFunctions;
743   for (auto *Func : Binary->getProfiledFunctions())
744     Binary->computeInlinedContextSizeForFunc(Func);
745 
746   // Flush the symbolizer to save memory.
747   Binary->flushSymbolizer();
748 }
749 
750 void CSProfileGenerator::generateLineNumBasedProfile() {
751   for (const auto &CI : *SampleCounters) {
752     const auto *CtxKey = cast<StringBasedCtxKey>(CI.first.getPtr());
753 
754     // Get or create function profile for the range
755     FunctionSamples &FunctionProfile =
756         getFunctionProfileForContext(CtxKey->Context, CtxKey->WasLeafInlined);
757 
758     // Fill in function body samples
759     populateBodySamplesForFunction(FunctionProfile, CI.second.RangeCounter);
760     // Fill in boundary sample counts as well as call site samples for calls
761     populateBoundarySamplesForFunction(CtxKey->Context, FunctionProfile,
762                                        CI.second.BranchCounter);
763   }
764   // Fill in call site value sample for inlined calls and also use context to
765   // infer missing samples. Since we don't have call count for inlined
766   // functions, we estimate it from inlinee's profile using the entry of the
767   // body sample.
768   populateInferredFunctionSamples();
769 
770   updateTotalSamples();
771 }
772 
773 void CSProfileGenerator::populateBodySamplesForFunction(
774     FunctionSamples &FunctionProfile, const RangeSample &RangeCounter) {
775   // Compute disjoint ranges first, so we can use MAX
776   // for calculating count for each location.
777   RangeSample Ranges;
778   findDisjointRanges(Ranges, RangeCounter);
779   for (const auto &Range : Ranges) {
780     uint64_t RangeBegin = Binary->offsetToVirtualAddr(Range.first.first);
781     uint64_t RangeEnd = Binary->offsetToVirtualAddr(Range.first.second);
782     uint64_t Count = Range.second;
783     // Disjoint ranges have introduce zero-filled gap that
784     // doesn't belong to current context, filter them out.
785     if (Count == 0)
786       continue;
787 
788     InstructionPointer IP(Binary, RangeBegin, true);
789     // Disjoint ranges may have range in the middle of two instr,
790     // e.g. If Instr1 at Addr1, and Instr2 at Addr2, disjoint range
791     // can be Addr1+1 to Addr2-1. We should ignore such range.
792     if (IP.Address > RangeEnd)
793       continue;
794 
795     do {
796       uint64_t Offset = Binary->virtualAddrToOffset(IP.Address);
797       auto LeafLoc = Binary->getInlineLeafFrameLoc(Offset);
798       if (LeafLoc.hasValue()) {
799         // Recording body sample for this specific context
800         updateBodySamplesforFunctionProfile(FunctionProfile, *LeafLoc, Count);
801         FunctionProfile.addTotalSamples(Count);
802       }
803     } while (IP.advance() && IP.Address <= RangeEnd);
804   }
805 }
806 
807 void CSProfileGenerator::populateBoundarySamplesForFunction(
808     SampleContextFrames ContextId, FunctionSamples &FunctionProfile,
809     const BranchSample &BranchCounters) {
810 
811   for (const auto &Entry : BranchCounters) {
812     uint64_t SourceOffset = Entry.first.first;
813     uint64_t TargetOffset = Entry.first.second;
814     uint64_t Count = Entry.second;
815     assert(Count != 0 && "Unexpected zero weight branch");
816 
817     StringRef CalleeName = getCalleeNameForOffset(TargetOffset);
818     if (CalleeName.size() == 0)
819       continue;
820 
821     // Record called target sample and its count
822     auto LeafLoc = Binary->getInlineLeafFrameLoc(SourceOffset);
823     if (!LeafLoc.hasValue())
824       continue;
825     FunctionProfile.addCalledTargetSamples(
826         LeafLoc->Location.LineOffset,
827         getBaseDiscriminator(LeafLoc->Location.Discriminator), CalleeName,
828         Count);
829 
830     // Record head sample for called target(callee)
831     SampleContextFrameVector CalleeCtx(ContextId.begin(), ContextId.end());
832     assert(CalleeCtx.back().FuncName == LeafLoc->FuncName &&
833            "Leaf function name doesn't match");
834     CalleeCtx.back() = *LeafLoc;
835     CalleeCtx.emplace_back(CalleeName, LineLocation(0, 0));
836     FunctionSamples &CalleeProfile = getFunctionProfileForContext(CalleeCtx);
837     CalleeProfile.addHeadSamples(Count);
838   }
839 }
840 
841 static SampleContextFrame
842 getCallerContext(SampleContextFrames CalleeContext,
843                  SampleContextFrameVector &CallerContext) {
844   assert(CalleeContext.size() > 1 && "Unexpected empty context");
845   CalleeContext = CalleeContext.drop_back();
846   CallerContext.assign(CalleeContext.begin(), CalleeContext.end());
847   SampleContextFrame CallerFrame = CallerContext.back();
848   CallerContext.back().Location = LineLocation(0, 0);
849   return CallerFrame;
850 }
851 
852 void CSProfileGenerator::populateInferredFunctionSamples() {
853   for (const auto &Item : ProfileMap) {
854     const auto &CalleeContext = Item.first;
855     const FunctionSamples &CalleeProfile = Item.second;
856 
857     // If we already have head sample counts, we must have value profile
858     // for call sites added already. Skip to avoid double counting.
859     if (CalleeProfile.getHeadSamples())
860       continue;
861     // If we don't have context, nothing to do for caller's call site.
862     // This could happen for entry point function.
863     if (CalleeContext.isBaseContext())
864       continue;
865 
866     // Infer Caller's frame loc and context ID through string splitting
867     SampleContextFrameVector CallerContextId;
868     SampleContextFrame &&CallerLeafFrameLoc =
869         getCallerContext(CalleeContext.getContextFrames(), CallerContextId);
870     SampleContextFrames CallerContext(CallerContextId);
871 
872     // It's possible that we haven't seen any sample directly in the caller,
873     // in which case CallerProfile will not exist. But we can't modify
874     // ProfileMap while iterating it.
875     // TODO: created function profile for those callers too
876     if (ProfileMap.find(CallerContext) == ProfileMap.end())
877       continue;
878     FunctionSamples &CallerProfile = ProfileMap[CallerContext];
879 
880     // Since we don't have call count for inlined functions, we
881     // estimate it from inlinee's profile using entry body sample.
882     uint64_t EstimatedCallCount = CalleeProfile.getEntrySamples();
883     // If we don't have samples with location, use 1 to indicate live.
884     if (!EstimatedCallCount && !CalleeProfile.getBodySamples().size())
885       EstimatedCallCount = 1;
886     CallerProfile.addCalledTargetSamples(
887         CallerLeafFrameLoc.Location.LineOffset,
888         CallerLeafFrameLoc.Location.Discriminator,
889         CalleeProfile.getContext().getName(), EstimatedCallCount);
890     CallerProfile.addBodySamples(CallerLeafFrameLoc.Location.LineOffset,
891                                  CallerLeafFrameLoc.Location.Discriminator,
892                                  EstimatedCallCount);
893     CallerProfile.addTotalSamples(EstimatedCallCount);
894   }
895 }
896 
897 void CSProfileGenerator::postProcessProfiles() {
898   // Compute hot/cold threshold based on profile. This will be used for cold
899   // context profile merging/trimming.
900   computeSummaryAndThreshold();
901 
902   // Run global pre-inliner to adjust/merge context profile based on estimated
903   // inline decisions.
904   if (EnableCSPreInliner) {
905     CSPreInliner(ProfileMap, *Binary, HotCountThreshold, ColdCountThreshold)
906         .run();
907     // Turn off the profile merger by default unless it is explicitly enabled.
908     if (!CSProfMergeColdContext.getNumOccurrences())
909       CSProfMergeColdContext = false;
910   }
911 
912   // Trim and merge cold context profile using cold threshold above.
913   if (TrimColdProfile || CSProfMergeColdContext) {
914     SampleContextTrimmer(ProfileMap)
915         .trimAndMergeColdContextProfiles(
916             HotCountThreshold, TrimColdProfile, CSProfMergeColdContext,
917             CSProfMaxColdContextDepth, EnableCSPreInliner);
918   }
919 
920   // Merge function samples of CS profile to calculate profile density.
921   sampleprof::SampleProfileMap ContextLessProfiles;
922   for (const auto &I : ProfileMap) {
923     ContextLessProfiles[I.second.getName()].merge(I.second);
924   }
925 
926   calculateAndShowDensity(ContextLessProfiles);
927   if (GenCSNestedProfile) {
928     CSProfileConverter CSConverter(ProfileMap);
929     CSConverter.convertProfiles();
930     FunctionSamples::ProfileIsCSFlat = false;
931     FunctionSamples::ProfileIsCSNested = EnableCSPreInliner;
932   }
933 }
934 
935 void ProfileGeneratorBase::computeSummaryAndThreshold() {
936   SampleProfileSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs);
937   auto Summary = Builder.computeSummaryForProfiles(ProfileMap);
938   HotCountThreshold = ProfileSummaryBuilder::getHotCountThreshold(
939       (Summary->getDetailedSummary()));
940   ColdCountThreshold = ProfileSummaryBuilder::getColdCountThreshold(
941       (Summary->getDetailedSummary()));
942 }
943 
944 void ProfileGeneratorBase::extractProbesFromRange(
945     const RangeSample &RangeCounter, ProbeCounterMap &ProbeCounter,
946     bool FindDisjointRanges) {
947   const RangeSample *PRanges = &RangeCounter;
948   RangeSample Ranges;
949   if (FindDisjointRanges) {
950     findDisjointRanges(Ranges, RangeCounter);
951     PRanges = &Ranges;
952   }
953 
954   for (const auto &Range : *PRanges) {
955     uint64_t RangeBegin = Binary->offsetToVirtualAddr(Range.first.first);
956     uint64_t RangeEnd = Binary->offsetToVirtualAddr(Range.first.second);
957     uint64_t Count = Range.second;
958 
959     InstructionPointer IP(Binary, RangeBegin, true);
960     // Disjoint ranges may have range in the middle of two instr,
961     // e.g. If Instr1 at Addr1, and Instr2 at Addr2, disjoint range
962     // can be Addr1+1 to Addr2-1. We should ignore such range.
963     if (IP.Address > RangeEnd)
964       continue;
965 
966     do {
967       const AddressProbesMap &Address2ProbesMap =
968           Binary->getAddress2ProbesMap();
969       auto It = Address2ProbesMap.find(IP.Address);
970       if (It != Address2ProbesMap.end()) {
971         for (const auto &Probe : It->second) {
972           ProbeCounter[&Probe] += Count;
973         }
974       }
975     } while (IP.advance() && IP.Address <= RangeEnd);
976   }
977 }
978 
979 static void
980 extractPrefixContextStack(SampleContextFrameVector &ContextStack,
981                           const SmallVectorImpl<uint64_t> &Addresses,
982                           ProfiledBinary *Binary) {
983   SmallVector<const MCDecodedPseudoProbe *, 16> Probes;
984   for (auto Addr : reverse(Addresses)) {
985     const MCDecodedPseudoProbe *CallProbe = Binary->getCallProbeForAddr(Addr);
986     // These could be the cases when a probe is not found at a calliste. Cutting
987     // off the context from here since the inliner will not know how to consume
988     // a context with unknown callsites.
989     // 1. for functions that are not sampled when
990     // --decode-probe-for-profiled-functions-only is on.
991     // 2. for a merged callsite. Callsite merging may cause the loss of original
992     // probe IDs.
993     // 3. for an external callsite.
994     if (!CallProbe)
995       break;
996     Probes.push_back(CallProbe);
997   }
998 
999   std::reverse(Probes.begin(), Probes.end());
1000 
1001   // Extract context stack for reusing, leaf context stack will be added
1002   // compressed while looking up function profile.
1003   for (const auto *P : Probes) {
1004     Binary->getInlineContextForProbe(P, ContextStack, true);
1005   }
1006 }
1007 
1008 void CSProfileGenerator::generateProbeBasedProfile() {
1009   // Enable pseudo probe functionalities in SampleProf
1010   FunctionSamples::ProfileIsProbeBased = true;
1011   for (const auto &CI : *SampleCounters) {
1012     const AddrBasedCtxKey *CtxKey =
1013         dyn_cast<AddrBasedCtxKey>(CI.first.getPtr());
1014     SampleContextFrameVector ContextStack;
1015     extractPrefixContextStack(ContextStack, CtxKey->Context, Binary);
1016     // Fill in function body samples from probes, also infer caller's samples
1017     // from callee's probe
1018     populateBodySamplesWithProbes(CI.second.RangeCounter, ContextStack);
1019     // Fill in boundary samples for a call probe
1020     populateBoundarySamplesWithProbes(CI.second.BranchCounter, ContextStack);
1021   }
1022 }
1023 
1024 void CSProfileGenerator::populateBodySamplesWithProbes(
1025     const RangeSample &RangeCounter, SampleContextFrames ContextStack) {
1026   ProbeCounterMap ProbeCounter;
1027   // Extract the top frame probes by looking up each address among the range in
1028   // the Address2ProbeMap
1029   extractProbesFromRange(RangeCounter, ProbeCounter);
1030   std::unordered_map<MCDecodedPseudoProbeInlineTree *,
1031                      std::unordered_set<FunctionSamples *>>
1032       FrameSamples;
1033   for (const auto &PI : ProbeCounter) {
1034     const MCDecodedPseudoProbe *Probe = PI.first;
1035     uint64_t Count = PI.second;
1036     // Disjoint ranges have introduce zero-filled gap that
1037     // doesn't belong to current context, filter them out.
1038     if (!Probe->isBlock() || Count == 0)
1039       continue;
1040     FunctionSamples &FunctionProfile =
1041         getFunctionProfileForLeafProbe(ContextStack, Probe);
1042     // Record the current frame and FunctionProfile whenever samples are
1043     // collected for non-danglie probes. This is for reporting all of the
1044     // zero count probes of the frame later.
1045     FrameSamples[Probe->getInlineTreeNode()].insert(&FunctionProfile);
1046     FunctionProfile.addBodySamplesForProbe(Probe->getIndex(), Count);
1047     FunctionProfile.addTotalSamples(Count);
1048     if (Probe->isEntry()) {
1049       FunctionProfile.addHeadSamples(Count);
1050       // Look up for the caller's function profile
1051       const auto *InlinerDesc = Binary->getInlinerDescForProbe(Probe);
1052       SampleContextFrames CalleeContextId =
1053           FunctionProfile.getContext().getContextFrames();
1054       if (InlinerDesc != nullptr && CalleeContextId.size() > 1) {
1055         // Since the context id will be compressed, we have to use callee's
1056         // context id to infer caller's context id to ensure they share the
1057         // same context prefix.
1058         SampleContextFrameVector CallerContextId;
1059         SampleContextFrame &&CallerLeafFrameLoc =
1060             getCallerContext(CalleeContextId, CallerContextId);
1061         uint64_t CallerIndex = CallerLeafFrameLoc.Location.LineOffset;
1062         assert(CallerIndex &&
1063                "Inferred caller's location index shouldn't be zero!");
1064         FunctionSamples &CallerProfile =
1065             getFunctionProfileForContext(CallerContextId);
1066         CallerProfile.setFunctionHash(InlinerDesc->FuncHash);
1067         CallerProfile.addBodySamples(CallerIndex, 0, Count);
1068         CallerProfile.addTotalSamples(Count);
1069         CallerProfile.addCalledTargetSamples(
1070             CallerIndex, 0, FunctionProfile.getContext().getName(), Count);
1071       }
1072     }
1073   }
1074 
1075   // Assign zero count for remaining probes without sample hits to
1076   // differentiate from probes optimized away, of which the counts are unknown
1077   // and will be inferred by the compiler.
1078   for (auto &I : FrameSamples) {
1079     for (auto *FunctionProfile : I.second) {
1080       for (auto *Probe : I.first->getProbes()) {
1081         FunctionProfile->addBodySamplesForProbe(Probe->getIndex(), 0);
1082       }
1083     }
1084   }
1085 }
1086 
1087 void CSProfileGenerator::populateBoundarySamplesWithProbes(
1088     const BranchSample &BranchCounter, SampleContextFrames ContextStack) {
1089   for (const auto &BI : BranchCounter) {
1090     uint64_t SourceOffset = BI.first.first;
1091     uint64_t TargetOffset = BI.first.second;
1092     uint64_t Count = BI.second;
1093     uint64_t SourceAddress = Binary->offsetToVirtualAddr(SourceOffset);
1094     const MCDecodedPseudoProbe *CallProbe =
1095         Binary->getCallProbeForAddr(SourceAddress);
1096     if (CallProbe == nullptr)
1097       continue;
1098     FunctionSamples &FunctionProfile =
1099         getFunctionProfileForLeafProbe(ContextStack, CallProbe);
1100     FunctionProfile.addBodySamples(CallProbe->getIndex(), 0, Count);
1101     FunctionProfile.addTotalSamples(Count);
1102     StringRef CalleeName = getCalleeNameForOffset(TargetOffset);
1103     if (CalleeName.size() == 0)
1104       continue;
1105     FunctionProfile.addCalledTargetSamples(CallProbe->getIndex(), 0, CalleeName,
1106                                            Count);
1107   }
1108 }
1109 
1110 FunctionSamples &CSProfileGenerator::getFunctionProfileForLeafProbe(
1111     SampleContextFrames ContextStack, const MCDecodedPseudoProbe *LeafProbe) {
1112 
1113   // Explicitly copy the context for appending the leaf context
1114   SampleContextFrameVector NewContextStack(ContextStack.begin(),
1115                                            ContextStack.end());
1116   Binary->getInlineContextForProbe(LeafProbe, NewContextStack, true);
1117   // For leaf inlined context with the top frame, we should strip off the top
1118   // frame's probe id, like:
1119   // Inlined stack: [foo:1, bar:2], the ContextId will be "foo:1 @ bar"
1120   auto LeafFrame = NewContextStack.back();
1121   LeafFrame.Location = LineLocation(0, 0);
1122   NewContextStack.pop_back();
1123   // Compress the context string except for the leaf frame
1124   CSProfileGenerator::compressRecursionContext(NewContextStack);
1125   CSProfileGenerator::trimContext(NewContextStack);
1126   NewContextStack.push_back(LeafFrame);
1127 
1128   const auto *FuncDesc = Binary->getFuncDescForGUID(LeafProbe->getGuid());
1129   bool WasLeafInlined = LeafProbe->getInlineTreeNode()->hasInlineSite();
1130   FunctionSamples &FunctionProile =
1131       getFunctionProfileForContext(NewContextStack, WasLeafInlined);
1132   FunctionProile.setFunctionHash(FuncDesc->FuncHash);
1133   return FunctionProile;
1134 }
1135 
1136 } // end namespace sampleprof
1137 } // end namespace llvm
1138