94 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_TOOLS_LLVM_PROFGEN_PGOINLINEADVISOR_H10#define LLVM_TOOLS_LLVM_PROFGEN_PGOINLINEADVISOR_H11 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 19namespace llvm {20namespace sampleprof {21 22// Inline candidate seen from profile23struct ProfiledInlineCandidate {24 ProfiledInlineCandidate(const FunctionSamples *Samples, uint64_t Count,25 uint32_t Size)26 : CalleeSamples(Samples), CallsiteCount(Count), SizeCost(Size) {}27 // Context-sensitive function profile for inline candidate28 const FunctionSamples *CalleeSamples;29 // Call site count for an inline candidate30 // TODO: make sure entry count for context profile and call site31 // target count for corresponding call are consistent.32 uint64_t CallsiteCount;33 // Size proxy for function under particular call context.34 uint64_t SizeCost;35};36 37// Inline candidate comparer using call site weight38struct ProfiledCandidateComparer {39 bool operator()(const ProfiledInlineCandidate &LHS,40 const ProfiledInlineCandidate &RHS) {41 // Always prioritize inlining zero-sized functions as they do not affect the42 // size budget. This could happen when all of the callee's code is gone and43 // only pseudo probes are left.44 if ((LHS.SizeCost == 0 || RHS.SizeCost == 0) &&45 (LHS.SizeCost != RHS.SizeCost))46 return RHS.SizeCost == 0;47 48 if (LHS.CallsiteCount != RHS.CallsiteCount)49 return LHS.CallsiteCount < RHS.CallsiteCount;50 51 if (LHS.SizeCost != RHS.SizeCost)52 return LHS.SizeCost > RHS.SizeCost;53 54 // Tie breaker using GUID so we have stable/deterministic inlining order55 assert(LHS.CalleeSamples && RHS.CalleeSamples &&56 "Expect non-null FunctionSamples");57 return LHS.CalleeSamples->getGUID() < RHS.CalleeSamples->getGUID();58 }59};60 61using ProfiledCandidateQueue =62 PriorityQueue<ProfiledInlineCandidate, std::vector<ProfiledInlineCandidate>,63 ProfiledCandidateComparer>;64 65// Pre-compilation inliner based on context-sensitive profile.66// The PreInliner estimates inline decision using hotness from profile67// and cost estimation from machine code size. It helps merges context68// profile globally and achieves better post-inine profile quality, which69// otherwise won't be possible for ThinLTO. It also reduce context profile70// size by only keep context that is estimated to be inlined.71class CSPreInliner {72public:73 CSPreInliner(SampleContextTracker &Tracker, ProfiledBinary &Binary,74 ProfileSummary *Summary);75 void run();76 77private:78 bool getInlineCandidates(ProfiledCandidateQueue &CQueue,79 const FunctionSamples *FCallerContextSamples);80 std::vector<FunctionId> buildTopDownOrder();81 void processFunction(FunctionId Name);82 bool shouldInline(ProfiledInlineCandidate &Candidate);83 uint32_t getFuncSize(const ContextTrieNode *ContextNode);84 bool UseContextCost;85 SampleContextTracker &ContextTracker;86 ProfiledBinary &Binary;87 ProfileSummary *Summary;88};89 90} // end namespace sampleprof91} // end namespace llvm92 93#endif94