11e44b5d3STeresa Johnson //===-- IndirectCallPromotionAnalysis.cpp - Find promotion candidates ===//
21e44b5d3STeresa Johnson //
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
61e44b5d3STeresa Johnson //
71e44b5d3STeresa Johnson //===----------------------------------------------------------------------===//
81e44b5d3STeresa Johnson //
91e44b5d3STeresa Johnson // Helper methods for identifying profitable indirect call promotion
101e44b5d3STeresa Johnson // candidates for an instruction when the indirect-call value profile metadata
111e44b5d3STeresa Johnson // is available.
121e44b5d3STeresa Johnson //
131e44b5d3STeresa Johnson //===----------------------------------------------------------------------===//
141e44b5d3STeresa Johnson 
151e44b5d3STeresa Johnson #include "llvm/Analysis/IndirectCallPromotionAnalysis.h"
1671c3a551Sserge-sans-paille #include "llvm/IR/Instruction.h"
171e44b5d3STeresa Johnson #include "llvm/ProfileData/InstrProf.h"
184c1a1d3cSReid Kleckner #include "llvm/Support/CommandLine.h"
191e44b5d3STeresa Johnson #include "llvm/Support/Debug.h"
2024d6e604SSimon Pilgrim #include <memory>
211e44b5d3STeresa Johnson 
221e44b5d3STeresa Johnson using namespace llvm;
231e44b5d3STeresa Johnson 
241e44b5d3STeresa Johnson #define DEBUG_TYPE "pgo-icall-prom-analysis"
251e44b5d3STeresa Johnson 
261e44b5d3STeresa Johnson // The percent threshold for the direct-call target (this call site vs the
27f4240b5bSDehao Chen // remaining call count) for it to be considered as the promotion target.
28f4240b5bSDehao Chen static cl::opt<unsigned> ICPRemainingPercentThreshold(
29557efc9aSFangrui Song     "icp-remaining-percent-threshold", cl::init(30), cl::Hidden,
30f4240b5bSDehao Chen     cl::desc("The percentage threshold against remaining unpromoted indirect "
31f4240b5bSDehao Chen              "call count for the promotion"));
32f4240b5bSDehao Chen 
33f4240b5bSDehao Chen // The percent threshold for the direct-call target (this call site vs the
341e44b5d3STeresa Johnson // total call count) for it to be considered as the promotion target.
351e44b5d3STeresa Johnson static cl::opt<unsigned>
36f4240b5bSDehao Chen     ICPTotalPercentThreshold("icp-total-percent-threshold", cl::init(5),
37*36c7d79dSFangrui Song                              cl::Hidden,
38f4240b5bSDehao Chen                              cl::desc("The percentage threshold against total "
39f4240b5bSDehao Chen                                       "count for the promotion"));
401e44b5d3STeresa Johnson 
411e44b5d3STeresa Johnson // Set the maximum number of targets to promote for a single indirect-call
421e44b5d3STeresa Johnson // callsite.
432357d293SWei Mi static cl::opt<unsigned>
44557efc9aSFangrui Song     MaxNumPromotions("icp-max-prom", cl::init(3), cl::Hidden,
451e44b5d3STeresa Johnson                      cl::desc("Max number of promotions for a single indirect "
461e44b5d3STeresa Johnson                               "call callsite"));
471e44b5d3STeresa Johnson 
ICallPromotionAnalysis()481e44b5d3STeresa Johnson ICallPromotionAnalysis::ICallPromotionAnalysis() {
490eaee545SJonas Devlieghere   ValueDataArray = std::make_unique<InstrProfValueData[]>(MaxNumPromotions);
501e44b5d3STeresa Johnson }
511e44b5d3STeresa Johnson 
isPromotionProfitable(uint64_t Count,uint64_t TotalCount,uint64_t RemainingCount)521e44b5d3STeresa Johnson bool ICallPromotionAnalysis::isPromotionProfitable(uint64_t Count,
53f4240b5bSDehao Chen                                                    uint64_t TotalCount,
54f4240b5bSDehao Chen                                                    uint64_t RemainingCount) {
5534cfcb29SDehao Chen   return Count * 100 >= ICPRemainingPercentThreshold * RemainingCount &&
56f4240b5bSDehao Chen          Count * 100 >= ICPTotalPercentThreshold * TotalCount;
571e44b5d3STeresa Johnson }
581e44b5d3STeresa Johnson 
591e44b5d3STeresa Johnson // Indirect-call promotion heuristic. The direct targets are sorted based on
601e44b5d3STeresa Johnson // the count. Stop at the first target that is not promoted. Returns the
611e44b5d3STeresa Johnson // number of candidates deemed profitable.
getProfitablePromotionCandidates(const Instruction * Inst,uint32_t NumVals,uint64_t TotalCount)621e44b5d3STeresa Johnson uint32_t ICallPromotionAnalysis::getProfitablePromotionCandidates(
631e44b5d3STeresa Johnson     const Instruction *Inst, uint32_t NumVals, uint64_t TotalCount) {
641e44b5d3STeresa Johnson   ArrayRef<InstrProfValueData> ValueDataRef(ValueDataArray.get(), NumVals);
651e44b5d3STeresa Johnson 
66d34e60caSNicola Zaghen   LLVM_DEBUG(dbgs() << " \nWork on callsite " << *Inst
67d34e60caSNicola Zaghen                     << " Num_targets: " << NumVals << "\n");
681e44b5d3STeresa Johnson 
691e44b5d3STeresa Johnson   uint32_t I = 0;
70f4240b5bSDehao Chen   uint64_t RemainingCount = TotalCount;
711e44b5d3STeresa Johnson   for (; I < MaxNumPromotions && I < NumVals; I++) {
721e44b5d3STeresa Johnson     uint64_t Count = ValueDataRef[I].Count;
73f4240b5bSDehao Chen     assert(Count <= RemainingCount);
74d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << " Candidate " << I << " Count=" << Count
75835df56cSTeresa Johnson                       << "  Target_func: " << ValueDataRef[I].Value << "\n");
761e44b5d3STeresa Johnson 
77f4240b5bSDehao Chen     if (!isPromotionProfitable(Count, TotalCount, RemainingCount)) {
78d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << " Not promote: Cold target.\n");
791e44b5d3STeresa Johnson       return I;
801e44b5d3STeresa Johnson     }
81f4240b5bSDehao Chen     RemainingCount -= Count;
821e44b5d3STeresa Johnson   }
831e44b5d3STeresa Johnson   return I;
841e44b5d3STeresa Johnson }
851e44b5d3STeresa Johnson 
861e44b5d3STeresa Johnson ArrayRef<InstrProfValueData>
getPromotionCandidatesForInstruction(const Instruction * I,uint32_t & NumVals,uint64_t & TotalCount,uint32_t & NumCandidates)871e44b5d3STeresa Johnson ICallPromotionAnalysis::getPromotionCandidatesForInstruction(
881e44b5d3STeresa Johnson     const Instruction *I, uint32_t &NumVals, uint64_t &TotalCount,
891e44b5d3STeresa Johnson     uint32_t &NumCandidates) {
901e44b5d3STeresa Johnson   bool Res =
911e44b5d3STeresa Johnson       getValueProfDataFromInst(*I, IPVK_IndirectCallTarget, MaxNumPromotions,
921e44b5d3STeresa Johnson                                ValueDataArray.get(), NumVals, TotalCount);
931e44b5d3STeresa Johnson   if (!Res) {
941e44b5d3STeresa Johnson     NumCandidates = 0;
951e44b5d3STeresa Johnson     return ArrayRef<InstrProfValueData>();
961e44b5d3STeresa Johnson   }
971e44b5d3STeresa Johnson   NumCandidates = getProfitablePromotionCandidates(I, NumVals, TotalCount);
981e44b5d3STeresa Johnson   return ArrayRef<InstrProfValueData>(ValueDataArray.get(), NumVals);
991e44b5d3STeresa Johnson }
100