xref: /freebsd/contrib/llvm-project/llvm/lib/Analysis/IndirectCallPromotionAnalysis.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- IndirectCallPromotionAnalysis.cpp - Find promotion candidates ===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // Helper methods for identifying profitable indirect call promotion
100b57cec5SDimitry Andric // candidates for an instruction when the indirect-call value profile metadata
110b57cec5SDimitry Andric // is available.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "llvm/Analysis/IndirectCallPromotionAnalysis.h"
1681ad6265SDimitry Andric #include "llvm/IR/Instruction.h"
170b57cec5SDimitry Andric #include "llvm/ProfileData/InstrProf.h"
18480093f4SDimitry Andric #include "llvm/Support/CommandLine.h"
190b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
20e8d8bef9SDimitry Andric #include <memory>
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric using namespace llvm;
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric #define DEBUG_TYPE "pgo-icall-prom-analysis"
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric // The percent threshold for the direct-call target (this call site vs the
270b57cec5SDimitry Andric // remaining call count) for it to be considered as the promotion target.
280b57cec5SDimitry Andric static cl::opt<unsigned> ICPRemainingPercentThreshold(
2981ad6265SDimitry Andric     "icp-remaining-percent-threshold", cl::init(30), cl::Hidden,
300b57cec5SDimitry Andric     cl::desc("The percentage threshold against remaining unpromoted indirect "
310b57cec5SDimitry Andric              "call count for the promotion"));
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric // The percent threshold for the direct-call target (this call site vs the
340b57cec5SDimitry Andric // total call count) for it to be considered as the promotion target.
350b57cec5SDimitry Andric static cl::opt<unsigned>
360b57cec5SDimitry Andric     ICPTotalPercentThreshold("icp-total-percent-threshold", cl::init(5),
3781ad6265SDimitry Andric                              cl::Hidden,
380b57cec5SDimitry Andric                              cl::desc("The percentage threshold against total "
390b57cec5SDimitry Andric                                       "count for the promotion"));
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric // Set the maximum number of targets to promote for a single indirect-call
420b57cec5SDimitry Andric // callsite.
430b57cec5SDimitry Andric static cl::opt<unsigned>
4481ad6265SDimitry Andric     MaxNumPromotions("icp-max-prom", cl::init(3), cl::Hidden,
450b57cec5SDimitry Andric                      cl::desc("Max number of promotions for a single indirect "
460b57cec5SDimitry Andric                               "call callsite"));
470b57cec5SDimitry Andric 
48*0fca6ea1SDimitry Andric cl::opt<unsigned> MaxNumVTableAnnotations(
49*0fca6ea1SDimitry Andric     "icp-max-num-vtables", cl::init(6), cl::Hidden,
50*0fca6ea1SDimitry Andric     cl::desc("Max number of vtables annotated for a vtable load instruction."));
510b57cec5SDimitry Andric 
isPromotionProfitable(uint64_t Count,uint64_t TotalCount,uint64_t RemainingCount)520b57cec5SDimitry Andric bool ICallPromotionAnalysis::isPromotionProfitable(uint64_t Count,
530b57cec5SDimitry Andric                                                    uint64_t TotalCount,
540b57cec5SDimitry Andric                                                    uint64_t RemainingCount) {
550b57cec5SDimitry Andric   return Count * 100 >= ICPRemainingPercentThreshold * RemainingCount &&
560b57cec5SDimitry Andric          Count * 100 >= ICPTotalPercentThreshold * TotalCount;
570b57cec5SDimitry Andric }
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric // Indirect-call promotion heuristic. The direct targets are sorted based on
600b57cec5SDimitry Andric // the count. Stop at the first target that is not promoted. Returns the
610b57cec5SDimitry Andric // number of candidates deemed profitable.
getProfitablePromotionCandidates(const Instruction * Inst,uint64_t TotalCount)620b57cec5SDimitry Andric uint32_t ICallPromotionAnalysis::getProfitablePromotionCandidates(
63*0fca6ea1SDimitry Andric     const Instruction *Inst, uint64_t TotalCount) {
640b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << " \nWork on callsite " << *Inst
65*0fca6ea1SDimitry Andric                     << " Num_targets: " << ValueDataArray.size() << "\n");
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric   uint32_t I = 0;
680b57cec5SDimitry Andric   uint64_t RemainingCount = TotalCount;
69*0fca6ea1SDimitry Andric   for (; I < MaxNumPromotions && I < ValueDataArray.size(); I++) {
70*0fca6ea1SDimitry Andric     uint64_t Count = ValueDataArray[I].Count;
710b57cec5SDimitry Andric     assert(Count <= RemainingCount);
720b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << " Candidate " << I << " Count=" << Count
73*0fca6ea1SDimitry Andric                       << "  Target_func: " << ValueDataArray[I].Value << "\n");
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric     if (!isPromotionProfitable(Count, TotalCount, RemainingCount)) {
760b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << " Not promote: Cold target.\n");
770b57cec5SDimitry Andric       return I;
780b57cec5SDimitry Andric     }
790b57cec5SDimitry Andric     RemainingCount -= Count;
800b57cec5SDimitry Andric   }
810b57cec5SDimitry Andric   return I;
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric 
84*0fca6ea1SDimitry Andric MutableArrayRef<InstrProfValueData>
getPromotionCandidatesForInstruction(const Instruction * I,uint64_t & TotalCount,uint32_t & NumCandidates)850b57cec5SDimitry Andric ICallPromotionAnalysis::getPromotionCandidatesForInstruction(
86*0fca6ea1SDimitry Andric     const Instruction *I, uint64_t &TotalCount, uint32_t &NumCandidates) {
87*0fca6ea1SDimitry Andric   ValueDataArray = getValueProfDataFromInst(*I, IPVK_IndirectCallTarget,
88*0fca6ea1SDimitry Andric                                             MaxNumPromotions, TotalCount);
89*0fca6ea1SDimitry Andric   if (ValueDataArray.empty()) {
900b57cec5SDimitry Andric     NumCandidates = 0;
91*0fca6ea1SDimitry Andric     return MutableArrayRef<InstrProfValueData>();
920b57cec5SDimitry Andric   }
93*0fca6ea1SDimitry Andric   NumCandidates = getProfitablePromotionCandidates(I, TotalCount);
94*0fca6ea1SDimitry Andric   return ValueDataArray;
950b57cec5SDimitry Andric }
96