1fce43576SEugene Zelenko //===- IndirectCallPromotion.cpp - Optimizations based on value profiling -===//
26e34c490SRong Xu //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66e34c490SRong Xu //
76e34c490SRong Xu //===----------------------------------------------------------------------===//
86e34c490SRong Xu //
96e34c490SRong Xu // This file implements the transformation that promotes indirect calls to
106e34c490SRong Xu // conditional direct calls when the indirect-call value profile metadata is
116e34c490SRong Xu // available.
126e34c490SRong Xu //
136e34c490SRong Xu //===----------------------------------------------------------------------===//
146e34c490SRong Xu
15cdc71612SEugene Zelenko #include "llvm/ADT/ArrayRef.h"
166e34c490SRong Xu #include "llvm/ADT/Statistic.h"
17cdc71612SEugene Zelenko #include "llvm/ADT/StringRef.h"
181e44b5d3STeresa Johnson #include "llvm/Analysis/IndirectCallPromotionAnalysis.h"
1957578aafSChandler Carruth #include "llvm/Analysis/IndirectCallVisitor.h"
200965da20SAdam Nemet #include "llvm/Analysis/OptimizationRemarkEmitter.h"
2134cfcb29SDehao Chen #include "llvm/Analysis/ProfileSummaryInfo.h"
226e34c490SRong Xu #include "llvm/IR/DiagnosticInfo.h"
23cdc71612SEugene Zelenko #include "llvm/IR/Function.h"
24cdc71612SEugene Zelenko #include "llvm/IR/InstrTypes.h"
256e34c490SRong Xu #include "llvm/IR/Instructions.h"
26cdc71612SEugene Zelenko #include "llvm/IR/LLVMContext.h"
276e34c490SRong Xu #include "llvm/IR/MDBuilder.h"
28cdc71612SEugene Zelenko #include "llvm/IR/PassManager.h"
29fce43576SEugene Zelenko #include "llvm/IR/Value.h"
30cdc71612SEugene Zelenko #include "llvm/ProfileData/InstrProf.h"
31cdc71612SEugene Zelenko #include "llvm/Support/Casting.h"
32cdc71612SEugene Zelenko #include "llvm/Support/CommandLine.h"
336e34c490SRong Xu #include "llvm/Support/Debug.h"
3457578aafSChandler Carruth #include "llvm/Support/Error.h"
35fce43576SEugene Zelenko #include "llvm/Support/raw_ostream.h"
366e34c490SRong Xu #include "llvm/Transforms/Instrumentation.h"
374fe1fe14SDavid Blaikie #include "llvm/Transforms/Instrumentation/PGOInstrumentation.h"
38e363d2ceSMatthew Simpson #include "llvm/Transforms/Utils/CallPromotionUtils.h"
39cdc71612SEugene Zelenko #include <cassert>
40cdc71612SEugene Zelenko #include <cstdint>
41fce43576SEugene Zelenko #include <memory>
42fce43576SEugene Zelenko #include <string>
43fce43576SEugene Zelenko #include <utility>
446e34c490SRong Xu #include <vector>
456e34c490SRong Xu
466e34c490SRong Xu using namespace llvm;
476e34c490SRong Xu
480b293306SXinliang David Li #define DEBUG_TYPE "pgo-icall-prom"
496e34c490SRong Xu
506e34c490SRong Xu STATISTIC(NumOfPGOICallPromotion, "Number of indirect call promotions.");
516e34c490SRong Xu STATISTIC(NumOfPGOICallsites, "Number of indirect call candidate sites.");
526e34c490SRong Xu
536e34c490SRong Xu // Command line option to disable indirect-call promotion with the default as
546e34c490SRong Xu // false. This is for debug purpose.
556e34c490SRong Xu static cl::opt<bool> DisableICP("disable-icp", cl::init(false), cl::Hidden,
566e34c490SRong Xu cl::desc("Disable indirect call promotion"));
576e34c490SRong Xu
586e34c490SRong Xu // Set the cutoff value for the promotion. If the value is other than 0, we
596e34c490SRong Xu // stop the transformation once the total number of promotions equals the cutoff
606e34c490SRong Xu // value.
616e34c490SRong Xu // For debug use only.
626e34c490SRong Xu static cl::opt<unsigned>
63*557efc9aSFangrui Song ICPCutOff("icp-cutoff", cl::init(0), cl::Hidden,
64a49e7689SCraig Topper cl::desc("Max number of promotions for this compilation"));
656e34c490SRong Xu
666e34c490SRong Xu // If ICPCSSkip is non zero, the first ICPCSSkip callsites will be skipped.
676e34c490SRong Xu // For debug use only.
686e34c490SRong Xu static cl::opt<unsigned>
69*557efc9aSFangrui Song ICPCSSkip("icp-csskip", cl::init(0), cl::Hidden,
70a49e7689SCraig Topper cl::desc("Skip Callsite up to this number for this compilation"));
716e34c490SRong Xu
726e34c490SRong Xu // Set if the pass is called in LTO optimization. The difference for LTO mode
736e34c490SRong Xu // is the pass won't prefix the source module name to the internal linkage
746e34c490SRong Xu // symbols.
756e34c490SRong Xu static cl::opt<bool> ICPLTOMode("icp-lto", cl::init(false), cl::Hidden,
766e34c490SRong Xu cl::desc("Run indirect-call promotion in LTO "
776e34c490SRong Xu "mode"));
781e44b5d3STeresa Johnson
79cc75d244SDehao Chen // Set if the pass is called in SamplePGO mode. The difference for SamplePGO
80cc75d244SDehao Chen // mode is it will add prof metadatato the created direct call.
81cc75d244SDehao Chen static cl::opt<bool>
82cc75d244SDehao Chen ICPSamplePGOMode("icp-samplepgo", cl::init(false), cl::Hidden,
83cc75d244SDehao Chen cl::desc("Run indirect-call promotion in SamplePGO mode"));
84cc75d244SDehao Chen
856e34c490SRong Xu // If the option is set to true, only call instructions will be considered for
866e34c490SRong Xu // transformation -- invoke instructions will be ignored.
876e34c490SRong Xu static cl::opt<bool>
886e34c490SRong Xu ICPCallOnly("icp-call-only", cl::init(false), cl::Hidden,
896e34c490SRong Xu cl::desc("Run indirect-call promotion for call instructions "
906e34c490SRong Xu "only"));
916e34c490SRong Xu
926e34c490SRong Xu // If the option is set to true, only invoke instructions will be considered for
936e34c490SRong Xu // transformation -- call instructions will be ignored.
946e34c490SRong Xu static cl::opt<bool> ICPInvokeOnly("icp-invoke-only", cl::init(false),
956e34c490SRong Xu cl::Hidden,
966e34c490SRong Xu cl::desc("Run indirect-call promotion for "
976e34c490SRong Xu "invoke instruction only"));
986e34c490SRong Xu
996e34c490SRong Xu // Dump the function level IR if the transformation happened in this
1006e34c490SRong Xu // function. For debug use only.
1016e34c490SRong Xu static cl::opt<bool>
1026e34c490SRong Xu ICPDUMPAFTER("icp-dumpafter", cl::init(false), cl::Hidden,
1036e34c490SRong Xu cl::desc("Dump IR after transformation happens"));
1046e34c490SRong Xu
1056e34c490SRong Xu namespace {
106fce43576SEugene Zelenko
1076e34c490SRong Xu // The class for main data structure to promote indirect calls to conditional
1086e34c490SRong Xu // direct calls.
1096e34c490SRong Xu class ICallPromotionFunc {
1106e34c490SRong Xu private:
1116e34c490SRong Xu Function &F;
1126e34c490SRong Xu Module *M;
1136e34c490SRong Xu
1146e34c490SRong Xu // Symtab that maps indirect call profile values to function names and
1156e34c490SRong Xu // defines.
1166e34c490SRong Xu InstrProfSymtab *Symtab;
1176e34c490SRong Xu
118cc75d244SDehao Chen bool SamplePGO;
119cc75d244SDehao Chen
1200d8b5d6fSAdam Nemet OptimizationRemarkEmitter &ORE;
1216e34c490SRong Xu
1226e34c490SRong Xu // A struct that records the direct target and it's call count.
1236e34c490SRong Xu struct PromotionCandidate {
1246e34c490SRong Xu Function *TargetFunction;
1256e34c490SRong Xu uint64_t Count;
126fce43576SEugene Zelenko
PromotionCandidate__anonb11395b60111::ICallPromotionFunc::PromotionCandidate1276e34c490SRong Xu PromotionCandidate(Function *F, uint64_t C) : TargetFunction(F), Count(C) {}
1286e34c490SRong Xu };
1296e34c490SRong Xu
1306e34c490SRong Xu // Check if the indirect-call call site should be promoted. Return the number
1311e44b5d3STeresa Johnson // of promotions. Inst is the candidate indirect call, ValueDataRef
1321e44b5d3STeresa Johnson // contains the array of value profile data for profiled targets,
1331e44b5d3STeresa Johnson // TotalCount is the total profiled count of call executions, and
1341e44b5d3STeresa Johnson // NumCandidates is the number of candidate entries in ValueDataRef.
1356e34c490SRong Xu std::vector<PromotionCandidate> getPromotionCandidatesForCallSite(
136e61247c0SMircea Trofin const CallBase &CB, const ArrayRef<InstrProfValueData> &ValueDataRef,
1371e44b5d3STeresa Johnson uint64_t TotalCount, uint32_t NumCandidates);
1386e34c490SRong Xu
1396e34c490SRong Xu // Promote a list of targets for one indirect-call callsite. Return
1406e34c490SRong Xu // the number of promotions.
1418a7cf11fSMircea Trofin uint32_t tryToPromote(CallBase &CB,
1426e34c490SRong Xu const std::vector<PromotionCandidate> &Candidates,
1436e34c490SRong Xu uint64_t &TotalCount);
1446e34c490SRong Xu
1456e34c490SRong Xu public:
ICallPromotionFunc(Function & Func,Module * Modu,InstrProfSymtab * Symtab,bool SamplePGO,OptimizationRemarkEmitter & ORE)146cc75d244SDehao Chen ICallPromotionFunc(Function &Func, Module *Modu, InstrProfSymtab *Symtab,
1470d8b5d6fSAdam Nemet bool SamplePGO, OptimizationRemarkEmitter &ORE)
1480d8b5d6fSAdam Nemet : F(Func), M(Modu), Symtab(Symtab), SamplePGO(SamplePGO), ORE(ORE) {}
149fce43576SEugene Zelenko ICallPromotionFunc(const ICallPromotionFunc &) = delete;
150fce43576SEugene Zelenko ICallPromotionFunc &operator=(const ICallPromotionFunc &) = delete;
151cdc71612SEugene Zelenko
15234cfcb29SDehao Chen bool processFunction(ProfileSummaryInfo *PSI);
1536e34c490SRong Xu };
154fce43576SEugene Zelenko
155a65b610bSBenjamin Kramer } // end anonymous namespace
1566e34c490SRong Xu
1576e34c490SRong Xu // Indirect-call promotion heuristic. The direct targets are sorted based on
1586e34c490SRong Xu // the count. Stop at the first target that is not promoted.
1596e34c490SRong Xu std::vector<ICallPromotionFunc::PromotionCandidate>
getPromotionCandidatesForCallSite(const CallBase & CB,const ArrayRef<InstrProfValueData> & ValueDataRef,uint64_t TotalCount,uint32_t NumCandidates)1606e34c490SRong Xu ICallPromotionFunc::getPromotionCandidatesForCallSite(
161e61247c0SMircea Trofin const CallBase &CB, const ArrayRef<InstrProfValueData> &ValueDataRef,
1621e44b5d3STeresa Johnson uint64_t TotalCount, uint32_t NumCandidates) {
1636e34c490SRong Xu std::vector<PromotionCandidate> Ret;
1646e34c490SRong Xu
165e61247c0SMircea Trofin LLVM_DEBUG(dbgs() << " \nWork on callsite #" << NumOfPGOICallsites << CB
1668950ad12STeresa Johnson << " Num_targets: " << ValueDataRef.size()
1671e44b5d3STeresa Johnson << " Num_candidates: " << NumCandidates << "\n");
1686e34c490SRong Xu NumOfPGOICallsites++;
1696e34c490SRong Xu if (ICPCSSkip != 0 && NumOfPGOICallsites <= ICPCSSkip) {
170d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " Skip: User options.\n");
1716e34c490SRong Xu return Ret;
1726e34c490SRong Xu }
1736e34c490SRong Xu
1741e44b5d3STeresa Johnson for (uint32_t I = 0; I < NumCandidates; I++) {
1756e34c490SRong Xu uint64_t Count = ValueDataRef[I].Count;
1766e34c490SRong Xu assert(Count <= TotalCount);
17706e7de79SFangrui Song (void)TotalCount;
1786e34c490SRong Xu uint64_t Target = ValueDataRef[I].Value;
179d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " Candidate " << I << " Count=" << Count
1806e34c490SRong Xu << " Target_func: " << Target << "\n");
1816e34c490SRong Xu
182e61247c0SMircea Trofin if (ICPInvokeOnly && isa<CallInst>(CB)) {
183d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " Not promote: User options.\n");
1849590658fSVivek Pandya ORE.emit([&]() {
185e61247c0SMircea Trofin return OptimizationRemarkMissed(DEBUG_TYPE, "UserOptions", &CB)
1869590658fSVivek Pandya << " Not promote: User options";
1879590658fSVivek Pandya });
188ce7de9b6STeresa Johnson break;
189ce7de9b6STeresa Johnson }
190e61247c0SMircea Trofin if (ICPCallOnly && isa<InvokeInst>(CB)) {
191d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " Not promote: User option.\n");
1929590658fSVivek Pandya ORE.emit([&]() {
193e61247c0SMircea Trofin return OptimizationRemarkMissed(DEBUG_TYPE, "UserOptions", &CB)
1949590658fSVivek Pandya << " Not promote: User options";
1959590658fSVivek Pandya });
196ce7de9b6STeresa Johnson break;
197ce7de9b6STeresa Johnson }
1986e34c490SRong Xu if (ICPCutOff != 0 && NumOfPGOICallPromotion >= ICPCutOff) {
199d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " Not promote: Cutoff reached.\n");
2009590658fSVivek Pandya ORE.emit([&]() {
201e61247c0SMircea Trofin return OptimizationRemarkMissed(DEBUG_TYPE, "CutOffReached", &CB)
2029590658fSVivek Pandya << " Not promote: Cutoff reached";
2039590658fSVivek Pandya });
2046e34c490SRong Xu break;
2056e34c490SRong Xu }
2060d8b5d6fSAdam Nemet
20777b50971STeresa Johnson // Don't promote if the symbol is not defined in the module. This avoids
20877b50971STeresa Johnson // creating a reference to a symbol that doesn't exist in the module
20977b50971STeresa Johnson // This can happen when we compile with a sample profile collected from
21077b50971STeresa Johnson // one binary but used for another, which may have profiled targets that
21177b50971STeresa Johnson // aren't used in the new binary. We might have a declaration initially in
21277b50971STeresa Johnson // the case where the symbol is globally dead in the binary and removed by
21377b50971STeresa Johnson // ThinLTO.
2140d8b5d6fSAdam Nemet Function *TargetFunction = Symtab->getFunction(Target);
21577b50971STeresa Johnson if (TargetFunction == nullptr || TargetFunction->isDeclaration()) {
216d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " Not promote: Cannot find the target\n");
2179590658fSVivek Pandya ORE.emit([&]() {
218e61247c0SMircea Trofin return OptimizationRemarkMissed(DEBUG_TYPE, "UnableToFindTarget", &CB)
219bcf726a3SXinliang David Li << "Cannot promote indirect call: target with md5sum "
220bcf726a3SXinliang David Li << ore::NV("target md5sum", Target) << " not found";
2219590658fSVivek Pandya });
2220d8b5d6fSAdam Nemet break;
2230d8b5d6fSAdam Nemet }
2240d8b5d6fSAdam Nemet
2256775f5d6SDehao Chen const char *Reason = nullptr;
226e61247c0SMircea Trofin if (!isLegalToPromote(CB, TargetFunction, &Reason)) {
2270d8b5d6fSAdam Nemet using namespace ore;
228fce43576SEugene Zelenko
2299590658fSVivek Pandya ORE.emit([&]() {
230e61247c0SMircea Trofin return OptimizationRemarkMissed(DEBUG_TYPE, "UnableToPromote", &CB)
2310d8b5d6fSAdam Nemet << "Cannot promote indirect call to "
2320d8b5d6fSAdam Nemet << NV("TargetFunction", TargetFunction) << " with count of "
2339590658fSVivek Pandya << NV("Count", Count) << ": " << Reason;
2349590658fSVivek Pandya });
2356e34c490SRong Xu break;
2366e34c490SRong Xu }
2370d8b5d6fSAdam Nemet
2386e34c490SRong Xu Ret.push_back(PromotionCandidate(TargetFunction, Count));
2396e34c490SRong Xu TotalCount -= Count;
2406e34c490SRong Xu }
2416e34c490SRong Xu return Ret;
2426e34c490SRong Xu }
2436e34c490SRong Xu
promoteIndirectCall(CallBase & CB,Function * DirectCallee,uint64_t Count,uint64_t TotalCount,bool AttachProfToDirectCall,OptimizationRemarkEmitter * ORE)2448a7cf11fSMircea Trofin CallBase &llvm::pgo::promoteIndirectCall(CallBase &CB, Function *DirectCallee,
2456e34c490SRong Xu uint64_t Count, uint64_t TotalCount,
246e363d2ceSMatthew Simpson bool AttachProfToDirectCall,
247e363d2ceSMatthew Simpson OptimizationRemarkEmitter *ORE) {
2486e34c490SRong Xu
2496e34c490SRong Xu uint64_t ElseCount = TotalCount - Count;
2506e34c490SRong Xu uint64_t MaxCount = (Count >= ElseCount ? Count : ElseCount);
2516e34c490SRong Xu uint64_t Scale = calculateCountScale(MaxCount);
2528a7cf11fSMircea Trofin MDBuilder MDB(CB.getContext());
2536e34c490SRong Xu MDNode *BranchWeights = MDB.createBranchWeights(
2546e34c490SRong Xu scaleBranchCount(Count, Scale), scaleBranchCount(ElseCount, Scale));
2556e34c490SRong Xu
2568a7cf11fSMircea Trofin CallBase &NewInst =
2578a7cf11fSMircea Trofin promoteCallWithIfThenElse(CB, DirectCallee, BranchWeights);
2586e34c490SRong Xu
259cc75d244SDehao Chen if (AttachProfToDirectCall) {
260d2f1cd5dSMircea Trofin MDBuilder MDB(NewInst.getContext());
261d2f1cd5dSMircea Trofin NewInst.setMetadata(
2624bdf82ceSTeresa Johnson LLVMContext::MD_prof,
2634bdf82ceSTeresa Johnson MDB.createBranchWeights({static_cast<uint32_t>(Count)}));
264cc75d244SDehao Chen }
265cc75d244SDehao Chen
2660d8b5d6fSAdam Nemet using namespace ore;
267fce43576SEugene Zelenko
2680d8b5d6fSAdam Nemet if (ORE)
2699590658fSVivek Pandya ORE->emit([&]() {
2708a7cf11fSMircea Trofin return OptimizationRemark(DEBUG_TYPE, "Promoted", &CB)
2710d8b5d6fSAdam Nemet << "Promote indirect call to " << NV("DirectCallee", DirectCallee)
2720d8b5d6fSAdam Nemet << " with count " << NV("Count", Count) << " out of "
2739590658fSVivek Pandya << NV("TotalCount", TotalCount);
2749590658fSVivek Pandya });
2758a7cf11fSMircea Trofin return NewInst;
2766e34c490SRong Xu }
2776e34c490SRong Xu
2786e34c490SRong Xu // Promote indirect-call to conditional direct-call for one callsite.
tryToPromote(CallBase & CB,const std::vector<PromotionCandidate> & Candidates,uint64_t & TotalCount)2796e34c490SRong Xu uint32_t ICallPromotionFunc::tryToPromote(
2808a7cf11fSMircea Trofin CallBase &CB, const std::vector<PromotionCandidate> &Candidates,
2816e34c490SRong Xu uint64_t &TotalCount) {
2826e34c490SRong Xu uint32_t NumPromoted = 0;
2836e34c490SRong Xu
2846e34c490SRong Xu for (auto &C : Candidates) {
2856e34c490SRong Xu uint64_t Count = C.Count;
2868a7cf11fSMircea Trofin pgo::promoteIndirectCall(CB, C.TargetFunction, Count, TotalCount, SamplePGO,
2878a7cf11fSMircea Trofin &ORE);
2886e34c490SRong Xu assert(TotalCount >= Count);
2896e34c490SRong Xu TotalCount -= Count;
2906e34c490SRong Xu NumOfPGOICallPromotion++;
2916e34c490SRong Xu NumPromoted++;
2926e34c490SRong Xu }
2936e34c490SRong Xu return NumPromoted;
2946e34c490SRong Xu }
2956e34c490SRong Xu
2966e34c490SRong Xu // Traverse all the indirect-call callsite and get the value profile
2976e34c490SRong Xu // annotation to perform indirect-call promotion.
processFunction(ProfileSummaryInfo * PSI)29834cfcb29SDehao Chen bool ICallPromotionFunc::processFunction(ProfileSummaryInfo *PSI) {
2996e34c490SRong Xu bool Changed = false;
3001e44b5d3STeresa Johnson ICallPromotionAnalysis ICallAnalysis;
3018a7cf11fSMircea Trofin for (auto *CB : findIndirectCalls(F)) {
3021e44b5d3STeresa Johnson uint32_t NumVals, NumCandidates;
3036e34c490SRong Xu uint64_t TotalCount;
3041e44b5d3STeresa Johnson auto ICallProfDataRef = ICallAnalysis.getPromotionCandidatesForInstruction(
3058a7cf11fSMircea Trofin CB, NumVals, TotalCount, NumCandidates);
30634cfcb29SDehao Chen if (!NumCandidates ||
30734cfcb29SDehao Chen (PSI && PSI->hasProfileSummary() && !PSI->isHotCount(TotalCount)))
3086e34c490SRong Xu continue;
3091e44b5d3STeresa Johnson auto PromotionCandidates = getPromotionCandidatesForCallSite(
310e61247c0SMircea Trofin *CB, ICallProfDataRef, TotalCount, NumCandidates);
3118a7cf11fSMircea Trofin uint32_t NumPromoted = tryToPromote(*CB, PromotionCandidates, TotalCount);
3126e34c490SRong Xu if (NumPromoted == 0)
3136e34c490SRong Xu continue;
3146e34c490SRong Xu
3156e34c490SRong Xu Changed = true;
3166e34c490SRong Xu // Adjust the MD.prof metadata. First delete the old one.
3178a7cf11fSMircea Trofin CB->setMetadata(LLVMContext::MD_prof, nullptr);
3186e34c490SRong Xu // If all promoted, we don't need the MD.prof metadata.
3196e34c490SRong Xu if (TotalCount == 0 || NumPromoted == NumVals)
3206e34c490SRong Xu continue;
3216e34c490SRong Xu // Otherwise we need update with the un-promoted records back.
3228a7cf11fSMircea Trofin annotateValueSite(*M, *CB, ICallProfDataRef.slice(NumPromoted), TotalCount,
3231e44b5d3STeresa Johnson IPVK_IndirectCallTarget, NumCandidates);
3246e34c490SRong Xu }
3256e34c490SRong Xu return Changed;
3266e34c490SRong Xu }
3276e34c490SRong Xu
3286e34c490SRong Xu // A wrapper function that does the actual work.
promoteIndirectCalls(Module & M,ProfileSummaryInfo * PSI,bool InLTO,bool SamplePGO,ModuleAnalysisManager * AM=nullptr)32934cfcb29SDehao Chen static bool promoteIndirectCalls(Module &M, ProfileSummaryInfo *PSI,
33034cfcb29SDehao Chen bool InLTO, bool SamplePGO,
3310d8b5d6fSAdam Nemet ModuleAnalysisManager *AM = nullptr) {
3326e34c490SRong Xu if (DisableICP)
3336e34c490SRong Xu return false;
3346e34c490SRong Xu InstrProfSymtab Symtab;
335b5794ca9SVedant Kumar if (Error E = Symtab.create(M, InLTO)) {
336b5794ca9SVedant Kumar std::string SymtabFailure = toString(std::move(E));
337ef9d7db7SWei Mi M.getContext().emitError("Failed to create symtab: " + SymtabFailure);
338b5794ca9SVedant Kumar return false;
339b5794ca9SVedant Kumar }
3406e34c490SRong Xu bool Changed = false;
3416e34c490SRong Xu for (auto &F : M) {
34285bd3978SEvandro Menezes if (F.isDeclaration() || F.hasOptNone())
3436e34c490SRong Xu continue;
3440d8b5d6fSAdam Nemet
3450d8b5d6fSAdam Nemet std::unique_ptr<OptimizationRemarkEmitter> OwnedORE;
3460d8b5d6fSAdam Nemet OptimizationRemarkEmitter *ORE;
3470d8b5d6fSAdam Nemet if (AM) {
3480d8b5d6fSAdam Nemet auto &FAM =
3490d8b5d6fSAdam Nemet AM->getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
3500d8b5d6fSAdam Nemet ORE = &FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
3510d8b5d6fSAdam Nemet } else {
3520eaee545SJonas Devlieghere OwnedORE = std::make_unique<OptimizationRemarkEmitter>(&F);
3530d8b5d6fSAdam Nemet ORE = OwnedORE.get();
3540d8b5d6fSAdam Nemet }
3550d8b5d6fSAdam Nemet
3560d8b5d6fSAdam Nemet ICallPromotionFunc ICallPromotion(F, &M, &Symtab, SamplePGO, *ORE);
35734cfcb29SDehao Chen bool FuncChanged = ICallPromotion.processFunction(PSI);
3586e34c490SRong Xu if (ICPDUMPAFTER && FuncChanged) {
359d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "\n== IR Dump After =="; F.print(dbgs()));
360d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "\n");
3616e34c490SRong Xu }
3626e34c490SRong Xu Changed |= FuncChanged;
3636e34c490SRong Xu if (ICPCutOff != 0 && NumOfPGOICallPromotion >= ICPCutOff) {
364d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " Stop: Cutoff reached.\n");
3656e34c490SRong Xu break;
3666e34c490SRong Xu }
3676e34c490SRong Xu }
3686e34c490SRong Xu return Changed;
3696e34c490SRong Xu }
3706e34c490SRong Xu
run(Module & M,ModuleAnalysisManager & AM)371cc75d244SDehao Chen PreservedAnalyses PGOIndirectCallPromotion::run(Module &M,
372cc75d244SDehao Chen ModuleAnalysisManager &AM) {
37334cfcb29SDehao Chen ProfileSummaryInfo *PSI = &AM.getResult<ProfileSummaryAnalysis>(M);
37434cfcb29SDehao Chen
37534cfcb29SDehao Chen if (!promoteIndirectCalls(M, PSI, InLTO | ICPLTOMode,
37634cfcb29SDehao Chen SamplePGO | ICPSamplePGOMode, &AM))
377f3c7a352SXinliang David Li return PreservedAnalyses::all();
378f3c7a352SXinliang David Li
379f3c7a352SXinliang David Li return PreservedAnalyses::none();
380f3c7a352SXinliang David Li }
381