109467b48Spatrick //===- IndirectCallPromotion.cpp - Optimizations based on value profiling -===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This file implements the transformation that promotes indirect calls to
1009467b48Spatrick // conditional direct calls when the indirect-call value profile metadata is
1109467b48Spatrick // available.
1209467b48Spatrick //
1309467b48Spatrick //===----------------------------------------------------------------------===//
1409467b48Spatrick
1509467b48Spatrick #include "llvm/ADT/ArrayRef.h"
1609467b48Spatrick #include "llvm/ADT/Statistic.h"
1709467b48Spatrick #include "llvm/ADT/StringRef.h"
1809467b48Spatrick #include "llvm/Analysis/IndirectCallPromotionAnalysis.h"
1909467b48Spatrick #include "llvm/Analysis/IndirectCallVisitor.h"
2009467b48Spatrick #include "llvm/Analysis/OptimizationRemarkEmitter.h"
2109467b48Spatrick #include "llvm/Analysis/ProfileSummaryInfo.h"
2209467b48Spatrick #include "llvm/IR/DiagnosticInfo.h"
2309467b48Spatrick #include "llvm/IR/Function.h"
2409467b48Spatrick #include "llvm/IR/InstrTypes.h"
2509467b48Spatrick #include "llvm/IR/Instructions.h"
2609467b48Spatrick #include "llvm/IR/LLVMContext.h"
2709467b48Spatrick #include "llvm/IR/MDBuilder.h"
2809467b48Spatrick #include "llvm/IR/PassManager.h"
2909467b48Spatrick #include "llvm/IR/Value.h"
3009467b48Spatrick #include "llvm/ProfileData/InstrProf.h"
3109467b48Spatrick #include "llvm/Support/Casting.h"
3209467b48Spatrick #include "llvm/Support/CommandLine.h"
3309467b48Spatrick #include "llvm/Support/Debug.h"
3409467b48Spatrick #include "llvm/Support/Error.h"
3509467b48Spatrick #include "llvm/Support/raw_ostream.h"
3609467b48Spatrick #include "llvm/Transforms/Instrumentation.h"
3709467b48Spatrick #include "llvm/Transforms/Instrumentation/PGOInstrumentation.h"
3809467b48Spatrick #include "llvm/Transforms/Utils/CallPromotionUtils.h"
3909467b48Spatrick #include <cassert>
4009467b48Spatrick #include <cstdint>
4109467b48Spatrick #include <memory>
4209467b48Spatrick #include <string>
4309467b48Spatrick #include <utility>
4409467b48Spatrick #include <vector>
4509467b48Spatrick
4609467b48Spatrick using namespace llvm;
4709467b48Spatrick
4809467b48Spatrick #define DEBUG_TYPE "pgo-icall-prom"
4909467b48Spatrick
5009467b48Spatrick STATISTIC(NumOfPGOICallPromotion, "Number of indirect call promotions.");
5109467b48Spatrick STATISTIC(NumOfPGOICallsites, "Number of indirect call candidate sites.");
5209467b48Spatrick
5309467b48Spatrick // Command line option to disable indirect-call promotion with the default as
5409467b48Spatrick // false. This is for debug purpose.
5509467b48Spatrick static cl::opt<bool> DisableICP("disable-icp", cl::init(false), cl::Hidden,
5609467b48Spatrick cl::desc("Disable indirect call promotion"));
5709467b48Spatrick
5809467b48Spatrick // Set the cutoff value for the promotion. If the value is other than 0, we
5909467b48Spatrick // stop the transformation once the total number of promotions equals the cutoff
6009467b48Spatrick // value.
6109467b48Spatrick // For debug use only.
6209467b48Spatrick static cl::opt<unsigned>
63*d415bd75Srobert ICPCutOff("icp-cutoff", cl::init(0), cl::Hidden,
6409467b48Spatrick cl::desc("Max number of promotions for this compilation"));
6509467b48Spatrick
6609467b48Spatrick // If ICPCSSkip is non zero, the first ICPCSSkip callsites will be skipped.
6709467b48Spatrick // For debug use only.
6809467b48Spatrick static cl::opt<unsigned>
69*d415bd75Srobert ICPCSSkip("icp-csskip", cl::init(0), cl::Hidden,
7009467b48Spatrick cl::desc("Skip Callsite up to this number for this compilation"));
7109467b48Spatrick
7209467b48Spatrick // Set if the pass is called in LTO optimization. The difference for LTO mode
7309467b48Spatrick // is the pass won't prefix the source module name to the internal linkage
7409467b48Spatrick // symbols.
7509467b48Spatrick static cl::opt<bool> ICPLTOMode("icp-lto", cl::init(false), cl::Hidden,
7609467b48Spatrick cl::desc("Run indirect-call promotion in LTO "
7709467b48Spatrick "mode"));
7809467b48Spatrick
7909467b48Spatrick // Set if the pass is called in SamplePGO mode. The difference for SamplePGO
8009467b48Spatrick // mode is it will add prof metadatato the created direct call.
8109467b48Spatrick static cl::opt<bool>
8209467b48Spatrick ICPSamplePGOMode("icp-samplepgo", cl::init(false), cl::Hidden,
8309467b48Spatrick cl::desc("Run indirect-call promotion in SamplePGO mode"));
8409467b48Spatrick
8509467b48Spatrick // If the option is set to true, only call instructions will be considered for
8609467b48Spatrick // transformation -- invoke instructions will be ignored.
8709467b48Spatrick static cl::opt<bool>
8809467b48Spatrick ICPCallOnly("icp-call-only", cl::init(false), cl::Hidden,
8909467b48Spatrick cl::desc("Run indirect-call promotion for call instructions "
9009467b48Spatrick "only"));
9109467b48Spatrick
9209467b48Spatrick // If the option is set to true, only invoke instructions will be considered for
9309467b48Spatrick // transformation -- call instructions will be ignored.
9409467b48Spatrick static cl::opt<bool> ICPInvokeOnly("icp-invoke-only", cl::init(false),
9509467b48Spatrick cl::Hidden,
9609467b48Spatrick cl::desc("Run indirect-call promotion for "
9709467b48Spatrick "invoke instruction only"));
9809467b48Spatrick
9909467b48Spatrick // Dump the function level IR if the transformation happened in this
10009467b48Spatrick // function. For debug use only.
10109467b48Spatrick static cl::opt<bool>
10209467b48Spatrick ICPDUMPAFTER("icp-dumpafter", cl::init(false), cl::Hidden,
10309467b48Spatrick cl::desc("Dump IR after transformation happens"));
10409467b48Spatrick
10509467b48Spatrick namespace {
10609467b48Spatrick
10709467b48Spatrick // The class for main data structure to promote indirect calls to conditional
10809467b48Spatrick // direct calls.
10909467b48Spatrick class ICallPromotionFunc {
11009467b48Spatrick private:
11109467b48Spatrick Function &F;
11209467b48Spatrick Module *M;
11309467b48Spatrick
11409467b48Spatrick // Symtab that maps indirect call profile values to function names and
11509467b48Spatrick // defines.
11609467b48Spatrick InstrProfSymtab *Symtab;
11709467b48Spatrick
11809467b48Spatrick bool SamplePGO;
11909467b48Spatrick
12009467b48Spatrick OptimizationRemarkEmitter &ORE;
12109467b48Spatrick
12209467b48Spatrick // A struct that records the direct target and it's call count.
12309467b48Spatrick struct PromotionCandidate {
12409467b48Spatrick Function *TargetFunction;
12509467b48Spatrick uint64_t Count;
12609467b48Spatrick
PromotionCandidate__anond2a4b99d0111::ICallPromotionFunc::PromotionCandidate12709467b48Spatrick PromotionCandidate(Function *F, uint64_t C) : TargetFunction(F), Count(C) {}
12809467b48Spatrick };
12909467b48Spatrick
13009467b48Spatrick // Check if the indirect-call call site should be promoted. Return the number
13109467b48Spatrick // of promotions. Inst is the candidate indirect call, ValueDataRef
13209467b48Spatrick // contains the array of value profile data for profiled targets,
13309467b48Spatrick // TotalCount is the total profiled count of call executions, and
13409467b48Spatrick // NumCandidates is the number of candidate entries in ValueDataRef.
13509467b48Spatrick std::vector<PromotionCandidate> getPromotionCandidatesForCallSite(
136097a140dSpatrick const CallBase &CB, const ArrayRef<InstrProfValueData> &ValueDataRef,
13709467b48Spatrick uint64_t TotalCount, uint32_t NumCandidates);
13809467b48Spatrick
13909467b48Spatrick // Promote a list of targets for one indirect-call callsite. Return
14009467b48Spatrick // the number of promotions.
141097a140dSpatrick uint32_t tryToPromote(CallBase &CB,
14209467b48Spatrick const std::vector<PromotionCandidate> &Candidates,
14309467b48Spatrick uint64_t &TotalCount);
14409467b48Spatrick
14509467b48Spatrick public:
ICallPromotionFunc(Function & Func,Module * Modu,InstrProfSymtab * Symtab,bool SamplePGO,OptimizationRemarkEmitter & ORE)14609467b48Spatrick ICallPromotionFunc(Function &Func, Module *Modu, InstrProfSymtab *Symtab,
14709467b48Spatrick bool SamplePGO, OptimizationRemarkEmitter &ORE)
14809467b48Spatrick : F(Func), M(Modu), Symtab(Symtab), SamplePGO(SamplePGO), ORE(ORE) {}
14909467b48Spatrick ICallPromotionFunc(const ICallPromotionFunc &) = delete;
15009467b48Spatrick ICallPromotionFunc &operator=(const ICallPromotionFunc &) = delete;
15109467b48Spatrick
15209467b48Spatrick bool processFunction(ProfileSummaryInfo *PSI);
15309467b48Spatrick };
15409467b48Spatrick
15509467b48Spatrick } // end anonymous namespace
15609467b48Spatrick
15709467b48Spatrick // Indirect-call promotion heuristic. The direct targets are sorted based on
15809467b48Spatrick // the count. Stop at the first target that is not promoted.
15909467b48Spatrick std::vector<ICallPromotionFunc::PromotionCandidate>
getPromotionCandidatesForCallSite(const CallBase & CB,const ArrayRef<InstrProfValueData> & ValueDataRef,uint64_t TotalCount,uint32_t NumCandidates)16009467b48Spatrick ICallPromotionFunc::getPromotionCandidatesForCallSite(
161097a140dSpatrick const CallBase &CB, const ArrayRef<InstrProfValueData> &ValueDataRef,
16209467b48Spatrick uint64_t TotalCount, uint32_t NumCandidates) {
16309467b48Spatrick std::vector<PromotionCandidate> Ret;
16409467b48Spatrick
165097a140dSpatrick LLVM_DEBUG(dbgs() << " \nWork on callsite #" << NumOfPGOICallsites << CB
16609467b48Spatrick << " Num_targets: " << ValueDataRef.size()
16709467b48Spatrick << " Num_candidates: " << NumCandidates << "\n");
16809467b48Spatrick NumOfPGOICallsites++;
16909467b48Spatrick if (ICPCSSkip != 0 && NumOfPGOICallsites <= ICPCSSkip) {
17009467b48Spatrick LLVM_DEBUG(dbgs() << " Skip: User options.\n");
17109467b48Spatrick return Ret;
17209467b48Spatrick }
17309467b48Spatrick
17409467b48Spatrick for (uint32_t I = 0; I < NumCandidates; I++) {
17509467b48Spatrick uint64_t Count = ValueDataRef[I].Count;
17609467b48Spatrick assert(Count <= TotalCount);
17773471bf0Spatrick (void)TotalCount;
17809467b48Spatrick uint64_t Target = ValueDataRef[I].Value;
17909467b48Spatrick LLVM_DEBUG(dbgs() << " Candidate " << I << " Count=" << Count
18009467b48Spatrick << " Target_func: " << Target << "\n");
18109467b48Spatrick
182097a140dSpatrick if (ICPInvokeOnly && isa<CallInst>(CB)) {
18309467b48Spatrick LLVM_DEBUG(dbgs() << " Not promote: User options.\n");
18409467b48Spatrick ORE.emit([&]() {
185097a140dSpatrick return OptimizationRemarkMissed(DEBUG_TYPE, "UserOptions", &CB)
18609467b48Spatrick << " Not promote: User options";
18709467b48Spatrick });
18809467b48Spatrick break;
18909467b48Spatrick }
190097a140dSpatrick if (ICPCallOnly && isa<InvokeInst>(CB)) {
19109467b48Spatrick LLVM_DEBUG(dbgs() << " Not promote: User option.\n");
19209467b48Spatrick ORE.emit([&]() {
193097a140dSpatrick return OptimizationRemarkMissed(DEBUG_TYPE, "UserOptions", &CB)
19409467b48Spatrick << " Not promote: User options";
19509467b48Spatrick });
19609467b48Spatrick break;
19709467b48Spatrick }
19809467b48Spatrick if (ICPCutOff != 0 && NumOfPGOICallPromotion >= ICPCutOff) {
19909467b48Spatrick LLVM_DEBUG(dbgs() << " Not promote: Cutoff reached.\n");
20009467b48Spatrick ORE.emit([&]() {
201097a140dSpatrick return OptimizationRemarkMissed(DEBUG_TYPE, "CutOffReached", &CB)
20209467b48Spatrick << " Not promote: Cutoff reached";
20309467b48Spatrick });
20409467b48Spatrick break;
20509467b48Spatrick }
20609467b48Spatrick
20773471bf0Spatrick // Don't promote if the symbol is not defined in the module. This avoids
20873471bf0Spatrick // creating a reference to a symbol that doesn't exist in the module
20973471bf0Spatrick // This can happen when we compile with a sample profile collected from
21073471bf0Spatrick // one binary but used for another, which may have profiled targets that
21173471bf0Spatrick // aren't used in the new binary. We might have a declaration initially in
21273471bf0Spatrick // the case where the symbol is globally dead in the binary and removed by
21373471bf0Spatrick // ThinLTO.
21409467b48Spatrick Function *TargetFunction = Symtab->getFunction(Target);
21573471bf0Spatrick if (TargetFunction == nullptr || TargetFunction->isDeclaration()) {
21609467b48Spatrick LLVM_DEBUG(dbgs() << " Not promote: Cannot find the target\n");
21709467b48Spatrick ORE.emit([&]() {
218097a140dSpatrick return OptimizationRemarkMissed(DEBUG_TYPE, "UnableToFindTarget", &CB)
21909467b48Spatrick << "Cannot promote indirect call: target with md5sum "
22009467b48Spatrick << ore::NV("target md5sum", Target) << " not found";
22109467b48Spatrick });
22209467b48Spatrick break;
22309467b48Spatrick }
22409467b48Spatrick
22509467b48Spatrick const char *Reason = nullptr;
226097a140dSpatrick if (!isLegalToPromote(CB, TargetFunction, &Reason)) {
22709467b48Spatrick using namespace ore;
22809467b48Spatrick
22909467b48Spatrick ORE.emit([&]() {
230097a140dSpatrick return OptimizationRemarkMissed(DEBUG_TYPE, "UnableToPromote", &CB)
23109467b48Spatrick << "Cannot promote indirect call to "
23209467b48Spatrick << NV("TargetFunction", TargetFunction) << " with count of "
23309467b48Spatrick << NV("Count", Count) << ": " << Reason;
23409467b48Spatrick });
23509467b48Spatrick break;
23609467b48Spatrick }
23709467b48Spatrick
23809467b48Spatrick Ret.push_back(PromotionCandidate(TargetFunction, Count));
23909467b48Spatrick TotalCount -= Count;
24009467b48Spatrick }
24109467b48Spatrick return Ret;
24209467b48Spatrick }
24309467b48Spatrick
promoteIndirectCall(CallBase & CB,Function * DirectCallee,uint64_t Count,uint64_t TotalCount,bool AttachProfToDirectCall,OptimizationRemarkEmitter * ORE)244097a140dSpatrick CallBase &llvm::pgo::promoteIndirectCall(CallBase &CB, Function *DirectCallee,
24509467b48Spatrick uint64_t Count, uint64_t TotalCount,
24609467b48Spatrick bool AttachProfToDirectCall,
24709467b48Spatrick OptimizationRemarkEmitter *ORE) {
24809467b48Spatrick
24909467b48Spatrick uint64_t ElseCount = TotalCount - Count;
25009467b48Spatrick uint64_t MaxCount = (Count >= ElseCount ? Count : ElseCount);
25109467b48Spatrick uint64_t Scale = calculateCountScale(MaxCount);
252097a140dSpatrick MDBuilder MDB(CB.getContext());
25309467b48Spatrick MDNode *BranchWeights = MDB.createBranchWeights(
25409467b48Spatrick scaleBranchCount(Count, Scale), scaleBranchCount(ElseCount, Scale));
25509467b48Spatrick
256097a140dSpatrick CallBase &NewInst =
257097a140dSpatrick promoteCallWithIfThenElse(CB, DirectCallee, BranchWeights);
25809467b48Spatrick
25909467b48Spatrick if (AttachProfToDirectCall) {
260097a140dSpatrick MDBuilder MDB(NewInst.getContext());
261097a140dSpatrick NewInst.setMetadata(
26209467b48Spatrick LLVMContext::MD_prof,
26309467b48Spatrick MDB.createBranchWeights({static_cast<uint32_t>(Count)}));
26409467b48Spatrick }
26509467b48Spatrick
26609467b48Spatrick using namespace ore;
26709467b48Spatrick
26809467b48Spatrick if (ORE)
26909467b48Spatrick ORE->emit([&]() {
270097a140dSpatrick return OptimizationRemark(DEBUG_TYPE, "Promoted", &CB)
27109467b48Spatrick << "Promote indirect call to " << NV("DirectCallee", DirectCallee)
27209467b48Spatrick << " with count " << NV("Count", Count) << " out of "
27309467b48Spatrick << NV("TotalCount", TotalCount);
27409467b48Spatrick });
27509467b48Spatrick return NewInst;
27609467b48Spatrick }
27709467b48Spatrick
27809467b48Spatrick // Promote indirect-call to conditional direct-call for one callsite.
tryToPromote(CallBase & CB,const std::vector<PromotionCandidate> & Candidates,uint64_t & TotalCount)27909467b48Spatrick uint32_t ICallPromotionFunc::tryToPromote(
280097a140dSpatrick CallBase &CB, const std::vector<PromotionCandidate> &Candidates,
28109467b48Spatrick uint64_t &TotalCount) {
28209467b48Spatrick uint32_t NumPromoted = 0;
28309467b48Spatrick
284*d415bd75Srobert for (const auto &C : Candidates) {
28509467b48Spatrick uint64_t Count = C.Count;
286097a140dSpatrick pgo::promoteIndirectCall(CB, C.TargetFunction, Count, TotalCount, SamplePGO,
287097a140dSpatrick &ORE);
28809467b48Spatrick assert(TotalCount >= Count);
28909467b48Spatrick TotalCount -= Count;
29009467b48Spatrick NumOfPGOICallPromotion++;
29109467b48Spatrick NumPromoted++;
29209467b48Spatrick }
29309467b48Spatrick return NumPromoted;
29409467b48Spatrick }
29509467b48Spatrick
29609467b48Spatrick // Traverse all the indirect-call callsite and get the value profile
29709467b48Spatrick // annotation to perform indirect-call promotion.
processFunction(ProfileSummaryInfo * PSI)29809467b48Spatrick bool ICallPromotionFunc::processFunction(ProfileSummaryInfo *PSI) {
29909467b48Spatrick bool Changed = false;
30009467b48Spatrick ICallPromotionAnalysis ICallAnalysis;
301097a140dSpatrick for (auto *CB : findIndirectCalls(F)) {
30209467b48Spatrick uint32_t NumVals, NumCandidates;
30309467b48Spatrick uint64_t TotalCount;
30409467b48Spatrick auto ICallProfDataRef = ICallAnalysis.getPromotionCandidatesForInstruction(
305097a140dSpatrick CB, NumVals, TotalCount, NumCandidates);
30609467b48Spatrick if (!NumCandidates ||
30709467b48Spatrick (PSI && PSI->hasProfileSummary() && !PSI->isHotCount(TotalCount)))
30809467b48Spatrick continue;
30909467b48Spatrick auto PromotionCandidates = getPromotionCandidatesForCallSite(
310097a140dSpatrick *CB, ICallProfDataRef, TotalCount, NumCandidates);
311097a140dSpatrick uint32_t NumPromoted = tryToPromote(*CB, PromotionCandidates, TotalCount);
31209467b48Spatrick if (NumPromoted == 0)
31309467b48Spatrick continue;
31409467b48Spatrick
31509467b48Spatrick Changed = true;
31609467b48Spatrick // Adjust the MD.prof metadata. First delete the old one.
317097a140dSpatrick CB->setMetadata(LLVMContext::MD_prof, nullptr);
31809467b48Spatrick // If all promoted, we don't need the MD.prof metadata.
31909467b48Spatrick if (TotalCount == 0 || NumPromoted == NumVals)
32009467b48Spatrick continue;
32109467b48Spatrick // Otherwise we need update with the un-promoted records back.
322097a140dSpatrick annotateValueSite(*M, *CB, ICallProfDataRef.slice(NumPromoted), TotalCount,
32309467b48Spatrick IPVK_IndirectCallTarget, NumCandidates);
32409467b48Spatrick }
32509467b48Spatrick return Changed;
32609467b48Spatrick }
32709467b48Spatrick
32809467b48Spatrick // A wrapper function that does the actual work.
promoteIndirectCalls(Module & M,ProfileSummaryInfo * PSI,bool InLTO,bool SamplePGO,ModuleAnalysisManager * AM=nullptr)32909467b48Spatrick static bool promoteIndirectCalls(Module &M, ProfileSummaryInfo *PSI,
33009467b48Spatrick bool InLTO, bool SamplePGO,
33109467b48Spatrick ModuleAnalysisManager *AM = nullptr) {
33209467b48Spatrick if (DisableICP)
33309467b48Spatrick return false;
33409467b48Spatrick InstrProfSymtab Symtab;
33509467b48Spatrick if (Error E = Symtab.create(M, InLTO)) {
33609467b48Spatrick std::string SymtabFailure = toString(std::move(E));
33773471bf0Spatrick M.getContext().emitError("Failed to create symtab: " + SymtabFailure);
33809467b48Spatrick return false;
33909467b48Spatrick }
34009467b48Spatrick bool Changed = false;
34109467b48Spatrick for (auto &F : M) {
34209467b48Spatrick if (F.isDeclaration() || F.hasOptNone())
34309467b48Spatrick continue;
34409467b48Spatrick
34509467b48Spatrick std::unique_ptr<OptimizationRemarkEmitter> OwnedORE;
34609467b48Spatrick OptimizationRemarkEmitter *ORE;
34709467b48Spatrick if (AM) {
34809467b48Spatrick auto &FAM =
34909467b48Spatrick AM->getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
35009467b48Spatrick ORE = &FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
35109467b48Spatrick } else {
35209467b48Spatrick OwnedORE = std::make_unique<OptimizationRemarkEmitter>(&F);
35309467b48Spatrick ORE = OwnedORE.get();
35409467b48Spatrick }
35509467b48Spatrick
35609467b48Spatrick ICallPromotionFunc ICallPromotion(F, &M, &Symtab, SamplePGO, *ORE);
35709467b48Spatrick bool FuncChanged = ICallPromotion.processFunction(PSI);
35809467b48Spatrick if (ICPDUMPAFTER && FuncChanged) {
35909467b48Spatrick LLVM_DEBUG(dbgs() << "\n== IR Dump After =="; F.print(dbgs()));
36009467b48Spatrick LLVM_DEBUG(dbgs() << "\n");
36109467b48Spatrick }
36209467b48Spatrick Changed |= FuncChanged;
36309467b48Spatrick if (ICPCutOff != 0 && NumOfPGOICallPromotion >= ICPCutOff) {
36409467b48Spatrick LLVM_DEBUG(dbgs() << " Stop: Cutoff reached.\n");
36509467b48Spatrick break;
36609467b48Spatrick }
36709467b48Spatrick }
36809467b48Spatrick return Changed;
36909467b48Spatrick }
37009467b48Spatrick
run(Module & M,ModuleAnalysisManager & AM)37109467b48Spatrick PreservedAnalyses PGOIndirectCallPromotion::run(Module &M,
37209467b48Spatrick ModuleAnalysisManager &AM) {
37309467b48Spatrick ProfileSummaryInfo *PSI = &AM.getResult<ProfileSummaryAnalysis>(M);
37409467b48Spatrick
37509467b48Spatrick if (!promoteIndirectCalls(M, PSI, InLTO | ICPLTOMode,
37609467b48Spatrick SamplePGO | ICPSamplePGOMode, &AM))
37709467b48Spatrick return PreservedAnalyses::all();
37809467b48Spatrick
37909467b48Spatrick return PreservedAnalyses::none();
38009467b48Spatrick }
381