CSPreInliner.h 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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. #ifndef LLVM_TOOLS_LLVM_PROFGEN_PGOINLINEADVISOR_H
  9. #define LLVM_TOOLS_LLVM_PROFGEN_PGOINLINEADVISOR_H
  10. #include "ProfiledBinary.h"
  11. #include "llvm/ADT/PriorityQueue.h"
  12. #include "llvm/ProfileData/ProfileCommon.h"
  13. #include "llvm/ProfileData/SampleProf.h"
  14. #include "llvm/Transforms/IPO/ProfiledCallGraph.h"
  15. #include "llvm/Transforms/IPO/SampleContextTracker.h"
  16. using namespace llvm;
  17. using namespace sampleprof;
  18. namespace llvm {
  19. namespace sampleprof {
  20. // Inline candidate seen from profile
  21. struct ProfiledInlineCandidate {
  22. ProfiledInlineCandidate(const FunctionSamples *Samples, uint64_t Count,
  23. uint32_t Size)
  24. : CalleeSamples(Samples), CallsiteCount(Count), SizeCost(Size) {}
  25. // Context-sensitive function profile for inline candidate
  26. const FunctionSamples *CalleeSamples;
  27. // Call site count for an inline candidate
  28. // TODO: make sure entry count for context profile and call site
  29. // target count for corresponding call are consistent.
  30. uint64_t CallsiteCount;
  31. // Size proxy for function under particular call context.
  32. uint64_t SizeCost;
  33. };
  34. // Inline candidate comparer using call site weight
  35. struct ProfiledCandidateComparer {
  36. bool operator()(const ProfiledInlineCandidate &LHS,
  37. const ProfiledInlineCandidate &RHS) {
  38. if (LHS.CallsiteCount != RHS.CallsiteCount)
  39. return LHS.CallsiteCount < RHS.CallsiteCount;
  40. if (LHS.SizeCost != RHS.SizeCost)
  41. return LHS.SizeCost > RHS.SizeCost;
  42. // Tie breaker using GUID so we have stable/deterministic inlining order
  43. assert(LHS.CalleeSamples && RHS.CalleeSamples &&
  44. "Expect non-null FunctionSamples");
  45. return LHS.CalleeSamples->getGUID(LHS.CalleeSamples->getName()) <
  46. RHS.CalleeSamples->getGUID(RHS.CalleeSamples->getName());
  47. }
  48. };
  49. using ProfiledCandidateQueue =
  50. PriorityQueue<ProfiledInlineCandidate, std::vector<ProfiledInlineCandidate>,
  51. ProfiledCandidateComparer>;
  52. // Pre-compilation inliner based on context-sensitive profile.
  53. // The PreInliner estimates inline decision using hotness from profile
  54. // and cost estimation from machine code size. It helps merges context
  55. // profile globally and achieves better post-inine profile quality, which
  56. // otherwise won't be possible for ThinLTO. It also reduce context profile
  57. // size by only keep context that is estimated to be inlined.
  58. class CSPreInliner {
  59. public:
  60. CSPreInliner(SampleProfileMap &Profiles, ProfiledBinary &Binary,
  61. uint64_t HotThreshold, uint64_t ColdThreshold);
  62. void run();
  63. private:
  64. bool getInlineCandidates(ProfiledCandidateQueue &CQueue,
  65. const FunctionSamples *FCallerContextSamples);
  66. std::vector<StringRef> buildTopDownOrder();
  67. void processFunction(StringRef Name);
  68. bool shouldInline(ProfiledInlineCandidate &Candidate);
  69. uint32_t getFuncSize(const FunctionSamples &FSamples);
  70. bool UseContextCost;
  71. SampleContextTracker ContextTracker;
  72. SampleProfileMap &ProfileMap;
  73. ProfiledBinary &Binary;
  74. // Count thresholds to answer isHotCount and isColdCount queries.
  75. // Mirrors the threshold in ProfileSummaryInfo.
  76. uint64_t HotCountThreshold;
  77. uint64_t ColdCountThreshold;
  78. };
  79. } // end namespace sampleprof
  80. } // end namespace llvm
  81. #endif