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