#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/IndirectCallPromotionAnalysis.h"
#include "llvm/Analysis/IndirectCallVisitor.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/Analysis/ProfileSummaryInfo.h"
#include "llvm/Analysis/TypeMetadataUtils.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/ProfDataUtils.h"
#include "llvm/IR/Value.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Instrumentation/PGOInstrumentation.h"
#include "llvm/Transforms/Utils/CallPromotionUtils.h"
#include "llvm/Transforms/Utils/Instrumentation.h"
#include <cassert>
#include <cstdint>
#include <memory>
#include <set>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
usingnamespacellvm;
#define DEBUG_TYPE …
STATISTIC(NumOfPGOICallPromotion, "Number of indirect call promotions.");
STATISTIC(NumOfPGOICallsites, "Number of indirect call candidate sites.");
extern cl::opt<unsigned> MaxNumVTableAnnotations;
namespace llvm {
extern cl::opt<bool> EnableVTableProfileUse;
}
static cl::opt<bool> DisableICP("disable-icp", cl::init(false), cl::Hidden,
cl::desc("Disable indirect call promotion"));
static cl::opt<unsigned>
ICPCutOff("icp-cutoff", cl::init(0), cl::Hidden,
cl::desc("Max number of promotions for this compilation"));
static cl::opt<unsigned>
ICPCSSkip("icp-csskip", cl::init(0), cl::Hidden,
cl::desc("Skip Callsite up to this number for this compilation"));
static cl::opt<bool> ICPLTOMode("icp-lto", cl::init(false), cl::Hidden,
cl::desc("Run indirect-call promotion in LTO "
"mode"));
static cl::opt<bool>
ICPSamplePGOMode("icp-samplepgo", cl::init(false), cl::Hidden,
cl::desc("Run indirect-call promotion in SamplePGO mode"));
static cl::opt<bool>
ICPCallOnly("icp-call-only", cl::init(false), cl::Hidden,
cl::desc("Run indirect-call promotion for call instructions "
"only"));
static cl::opt<bool> ICPInvokeOnly("icp-invoke-only", cl::init(false),
cl::Hidden,
cl::desc("Run indirect-call promotion for "
"invoke instruction only"));
static cl::opt<bool>
ICPDUMPAFTER("icp-dumpafter", cl::init(false), cl::Hidden,
cl::desc("Dump IR after transformation happens"));
static cl::opt<float> ICPVTablePercentageThreshold(
"icp-vtable-percentage-threshold", cl::init(0.995), cl::Hidden,
cl::desc("The percentage threshold of vtable-count / function-count for "
"cost-benefit analysis."));
static cl::opt<int> ICPMaxNumVTableLastCandidate(
"icp-max-num-vtable-last-candidate", cl::init(1), cl::Hidden,
cl::desc("The maximum number of vtable for the last candidate."));
static cl::list<std::string> ICPIgnoredBaseTypes(
"icp-ignored-base-types", cl::Hidden,
cl::desc(
"A list of mangled vtable type info names. Classes specified by the "
"type info names and their derived ones will not be vtable-ICP'ed. "
"Useful when the profiled types and actual types in the optimized "
"binary could be different due to profiling limitations. Type info "
"names are those string literals used in LLVM type metadata"));
namespace {
VTableAddressPointOffsetValMap;
struct VirtualCallSiteInfo { … };
VirtualCallSiteTypeInfoMap;
VTableGUIDCountsMap;
static std::optional<uint64_t>
getAddressPointOffset(const GlobalVariable &VTableVar,
StringRef CompatibleType) { … }
static Constant *getVTableAddressPointOffset(GlobalVariable *VTable,
uint32_t AddressPointOffset) { … }
static BasicBlock *getUserBasicBlock(Use &U, Instruction *UserInst) { … }
static bool isDestBBSuitableForSink(Instruction *Inst, BasicBlock *DestBB) { … }
static bool tryToSinkInstruction(Instruction *I, BasicBlock *DestBlock) { … }
static int tryToSinkInstructions(BasicBlock *OriginalBB,
BasicBlock *IndirectCallBB) { … }
class IndirectCallPromoter { … };
}
std::vector<IndirectCallPromoter::PromotionCandidate>
IndirectCallPromoter::getPromotionCandidatesForCallSite(
const CallBase &CB, ArrayRef<InstrProfValueData> ValueDataRef,
uint64_t TotalCount, uint32_t NumCandidates) { … }
Constant *IndirectCallPromoter::getOrCreateVTableAddressPointVar(
GlobalVariable *GV, uint64_t AddressPointOffset) { … }
Instruction *IndirectCallPromoter::computeVTableInfos(
const CallBase *CB, VTableGUIDCountsMap &GUIDCountsMap,
std::vector<PromotionCandidate> &Candidates) { … }
static MDNode *createBranchWeights(LLVMContext &Context, uint64_t TrueWeight,
uint64_t FalseWeight) { … }
CallBase &llvm::pgo::promoteIndirectCall(CallBase &CB, Function *DirectCallee,
uint64_t Count, uint64_t TotalCount,
bool AttachProfToDirectCall,
OptimizationRemarkEmitter *ORE) { … }
bool IndirectCallPromoter::tryToPromoteWithFuncCmp(
CallBase &CB, Instruction *VPtr, ArrayRef<PromotionCandidate> Candidates,
uint64_t TotalCount, ArrayRef<InstrProfValueData> ICallProfDataRef,
uint32_t NumCandidates, VTableGUIDCountsMap &VTableGUIDCounts) { … }
void IndirectCallPromoter::updateFuncValueProfiles(
CallBase &CB, ArrayRef<InstrProfValueData> CallVDs, uint64_t TotalCount,
uint32_t MaxMDCount) { … }
void IndirectCallPromoter::updateVPtrValueProfiles(
Instruction *VPtr, VTableGUIDCountsMap &VTableGUIDCounts) { … }
bool IndirectCallPromoter::tryToPromoteWithVTableCmp(
CallBase &CB, Instruction *VPtr, ArrayRef<PromotionCandidate> Candidates,
uint64_t TotalFuncCount, uint32_t NumCandidates,
MutableArrayRef<InstrProfValueData> ICallProfDataRef,
VTableGUIDCountsMap &VTableGUIDCounts) { … }
bool IndirectCallPromoter::processFunction(ProfileSummaryInfo *PSI) { … }
bool IndirectCallPromoter::isProfitableToCompareVTables(
const CallBase &CB, ArrayRef<PromotionCandidate> Candidates) { … }
bool IndirectCallPromoter::shouldSkipVTable(uint64_t VTableGUID) { … }
static void
computeVirtualCallSiteTypeInfoMap(Module &M, ModuleAnalysisManager &MAM,
VirtualCallSiteTypeInfoMap &VirtualCSInfo) { … }
static bool promoteIndirectCalls(Module &M, ProfileSummaryInfo *PSI, bool InLTO,
bool SamplePGO, ModuleAnalysisManager &MAM) { … }
PreservedAnalyses PGOIndirectCallPromotion::run(Module &M,
ModuleAnalysisManager &MAM) { … }