47#include <unordered_map>
53#define DEBUG_TYPE "pgo-icall-prom"
55STATISTIC(NumOfPGOICallPromotion,
"Number of indirect call promotions.");
56STATISTIC(NumOfPGOICallsites,
"Number of indirect call candidate sites.");
67 cl::desc(
"Disable indirect call promotion"));
75 cl::desc(
"Max number of promotions for this compilation"));
81 cl::desc(
"Skip Callsite up to this number for this compilation"));
87 cl::desc(
"Run indirect-call promotion in LTO "
94 cl::desc(
"Run indirect-call promotion in SamplePGO mode"));
100 cl::desc(
"Run indirect-call promotion for call instructions "
107 cl::desc(
"Run indirect-call promotion for "
108 "invoke instruction only"));
114 cl::desc(
"Dump IR after transformation happens"));
120 cl::desc(
"The percentage threshold of vtable-count / function-count for "
121 "cost-benefit analysis."));
132 cl::desc(
"The maximum number of vtable for the last candidate."));
137 "A list of mangled vtable type info names. Classes specified by the "
138 "type info names and their derived ones will not be vtable-ICP'ed. "
139 "Useful when the profiled types and actual types in the optimized "
140 "binary could be different due to profiling limitations. Type info "
141 "names are those string literals used in LLVM type metadata"));
148using VTableAddressPointOffsetValMap =
152struct VirtualCallSiteInfo {
162using VirtualCallSiteTypeInfoMap =
173static std::optional<uint64_t>
177 VTableVar.
getMetadata(LLVMContext::MD_type, Types);
180 if (
auto *TypeId = dyn_cast<MDString>(
Type->getOperand(1).get());
181 TypeId && TypeId->getString() == CompatibleType)
182 return cast<ConstantInt>(
183 cast<ConstantAsMetadata>(
Type->getOperand(0))->getValue())
195 assert(AddressPointOffset <
196 M.getDataLayout().getTypeAllocSize(
VTable->getValueType()) &&
197 "Out-of-bound access");
206 if (
PHINode *PN = dyn_cast<PHINode>(UserInst))
207 return PN->getIncomingBlock(U);
222 "Guaranteed by ICP transformation");
233 UserBB = getUserBasicBlock(
Use, UserInst);
236 if (UserBB != DestBB)
239 return UserBB !=
nullptr;
247 if (!isDestBBSuitableForSink(
I, DestBlock))
252 if (isa<PHINode>(
I) ||
I->isEHPad() ||
I->mayThrow() || !
I->willReturn() ||
257 if (
const auto *
C = dyn_cast<CallBase>(
I))
258 if (
C->isInlineAsm() ||
C->cannotMerge() ||
C->isConvergent())
262 if (
I->mayWriteToMemory())
267 if (
I->mayReadFromMemory()) {
270 E =
I->getParent()->end();
275 if (Scan->mayWriteToMemory())
281 I->moveBefore(*DestBlock, InsertPos);
292static int tryToSinkInstructions(
BasicBlock *OriginalBB,
301 if (tryToSinkInstruction(&
I, IndirectCallBB))
309class IndirectCallPromoter {
318 const bool SamplePGO;
321 const VirtualCallSiteTypeInfoMap &VirtualCSInfo;
323 VTableAddressPointOffsetValMap &VTableAddressPointOffsetVal;
330 struct PromotionCandidate {
341 VTableGUIDCountsMap VTableGUIDAndCounts;
352 std::vector<PromotionCandidate> getPromotionCandidatesForCallSite(
364 VTableGUIDCountsMap &VTableGUIDCounts);
369 bool tryToPromoteWithVTableCmp(
373 VTableGUIDCountsMap &VTableGUIDCounts);
376 bool isProfitableToCompareVTables(
const CallBase &CB,
381 bool shouldSkipVTable(
uint64_t VTableGUID);
391 VTableGUIDCountsMap &VTableGUIDCounts,
392 std::vector<PromotionCandidate> &Candidates);
401 VTableGUIDCountsMap &VTableGUIDCounts);
404 IndirectCallPromoter(
406 const VirtualCallSiteTypeInfoMap &VirtualCSInfo,
407 VTableAddressPointOffsetValMap &VTableAddressPointOffsetVal,
410 :
F(
Func),
M(
M), Symtab(Symtab), SamplePGO(SamplePGO),
411 VirtualCSInfo(VirtualCSInfo),
412 VTableAddressPointOffsetVal(VTableAddressPointOffsetVal), ORE(ORE),
413 IgnoredBaseTypes(IgnoredBaseTypes) {}
414 IndirectCallPromoter(
const IndirectCallPromoter &) =
delete;
415 IndirectCallPromoter &operator=(
const IndirectCallPromoter &) =
delete;
424std::vector<IndirectCallPromoter::PromotionCandidate>
425IndirectCallPromoter::getPromotionCandidatesForCallSite(
428 std::vector<PromotionCandidate>
Ret;
430 LLVM_DEBUG(
dbgs() <<
" \nWork on callsite #" << NumOfPGOICallsites << CB
431 <<
" Num_targets: " << ValueDataRef.
size()
432 <<
" Num_candidates: " << NumCandidates <<
"\n");
433 NumOfPGOICallsites++;
441 assert(Count <= TotalCount);
445 <<
" Target_func: " <<
Target <<
"\n");
451 <<
" Not promote: User options";
459 <<
" Not promote: User options";
467 <<
" Not promote: Cutoff reached";
480 if (TargetFunction ==
nullptr || TargetFunction->
isDeclaration()) {
484 <<
"Cannot promote indirect call: target with md5sum "
490 const char *Reason =
nullptr;
496 <<
"Cannot promote indirect call to "
497 <<
NV(
"TargetFunction", TargetFunction) <<
" with count of "
498 <<
NV(
"Count", Count) <<
": " << Reason;
503 Ret.push_back(PromotionCandidate(TargetFunction, Count));
509Constant *IndirectCallPromoter::getOrCreateVTableAddressPointVar(
512 VTableAddressPointOffsetVal[GV].try_emplace(AddressPointOffset,
nullptr);
514 Iter->second = getVTableAddressPointOffset(GV, AddressPointOffset);
518Instruction *IndirectCallPromoter::computeVTableInfos(
519 const CallBase *CB, VTableGUIDCountsMap &GUIDCountsMap,
520 std::vector<PromotionCandidate> &Candidates) {
548 auto Iter = VirtualCSInfo.find(CB);
549 if (Iter == VirtualCSInfo.end())
553 << NumOfPGOICallsites <<
"\n");
555 const auto &VirtualCallInfo = Iter->second;
559 for (
size_t I = 0;
I < Candidates.size();
I++)
560 CalleeIndexMap[Candidates[
I].TargetFunction] =
I;
563 auto VTableValueDataArray =
566 if (VTableValueDataArray.empty())
570 for (
const auto &V : VTableValueDataArray) {
572 GUIDCountsMap[VTableVal] =
V.Count;
575 LLVM_DEBUG(
dbgs() <<
" Cannot find vtable definition for " << VTableVal
576 <<
"; maybe the vtable isn't imported\n");
580 std::optional<uint64_t> MaybeAddressPointOffset =
581 getAddressPointOffset(*VTableVar, VirtualCallInfo.CompatibleTypeStr);
582 if (!MaybeAddressPointOffset)
585 const uint64_t AddressPointOffset = *MaybeAddressPointOffset;
589 VTableVar, AddressPointOffset + VirtualCallInfo.FunctionOffset, M);
592 auto CalleeIndexIter = CalleeIndexMap.
find(Callee);
593 if (CalleeIndexIter == CalleeIndexMap.
end())
596 auto &Candidate = Candidates[CalleeIndexIter->second];
600 Candidate.VTableGUIDAndCounts[VTableVal] =
V.Count;
601 Candidate.AddressPoints.push_back(
602 getOrCreateVTableAddressPointVar(VTableVar, AddressPointOffset));
620 bool AttachProfToDirectCall,
626 if (AttachProfToDirectCall)
635 <<
"Promote indirect call to " << NV(
"DirectCallee", DirectCallee)
636 <<
" with count " << NV(
"Count", Count) <<
" out of "
637 << NV(
"TotalCount", TotalCount);
643bool IndirectCallPromoter::tryToPromoteWithFuncCmp(
646 uint32_t NumCandidates, VTableGUIDCountsMap &VTableGUIDCounts) {
649 for (
const auto &
C : Candidates) {
653 assert(TotalCount >= FuncCount);
654 TotalCount -= FuncCount;
655 NumOfPGOICallPromotion++;
666 for (
const auto &[GUID, VTableCount] :
C.VTableGUIDAndCounts)
667 SumVTableCount += VTableCount;
669 for (
const auto &[GUID, VTableCount] :
C.VTableGUIDAndCounts) {
670 APInt APFuncCount((
unsigned)128, FuncCount,
false );
671 APFuncCount *= VTableCount;
672 VTableGUIDCounts[GUID] -= APFuncCount.udiv(SumVTableCount).getZExtValue();
675 if (NumPromoted == 0)
678 assert(NumPromoted <= ICallProfDataRef.
size() &&
679 "Number of promoted functions should not be greater than the number "
680 "of values in profile metadata");
683 updateFuncValueProfiles(CB, ICallProfDataRef.
slice(NumPromoted), TotalCount,
685 updateVPtrValueProfiles(VPtr, VTableGUIDCounts);
689void IndirectCallPromoter::updateFuncValueProfiles(
700void IndirectCallPromoter::updateVPtrValueProfiles(
701 Instruction *VPtr, VTableGUIDCountsMap &VTableGUIDCounts) {
706 std::vector<InstrProfValueData> VTableValueProfiles;
708 for (
auto [GUID, Count] : VTableGUIDCounts) {
712 VTableValueProfiles.push_back({
GUID, Count});
713 TotalVTableCount += Count;
716 [](
const InstrProfValueData &LHS,
const InstrProfValueData &RHS) {
717 return LHS.Count >
RHS.Count;
721 IPVK_VTableTarget, VTableValueProfiles.size());
724bool IndirectCallPromoter::tryToPromoteWithVTableCmp(
728 VTableGUIDCountsMap &VTableGUIDCounts) {
731 for (
const auto &Candidate : Candidates) {
732 for (
auto &[GUID, Count] : Candidate.VTableGUIDAndCounts)
733 VTableGUIDCounts[
GUID] -= Count;
740 CB, VPtr, Candidate.TargetFunction, Candidate.AddressPoints,
742 TotalFuncCount - Candidate.Count));
744 int SinkCount = tryToSinkInstructions(OriginalBB, CB.
getParent());
749 const auto &VTableGUIDAndCounts = Candidate.VTableGUIDAndCounts;
750 Remark <<
"Promote indirect call to "
751 <<
ore::NV(
"DirectCallee", Candidate.TargetFunction)
752 <<
" with count " <<
ore::NV(
"Count", Candidate.Count)
753 <<
" out of " <<
ore::NV(
"TotalCount", TotalFuncCount) <<
", sink "
754 <<
ore::NV(
"SinkCount", SinkCount)
755 <<
" instruction(s) and compare "
756 <<
ore::NV(
"VTable", VTableGUIDAndCounts.size())
760 std::set<uint64_t> GUIDSet;
761 for (
auto [GUID, Count] : VTableGUIDAndCounts)
762 GUIDSet.insert(GUID);
763 for (
auto Iter = GUIDSet.begin(); Iter != GUIDSet.end(); Iter++) {
764 if (Iter != GUIDSet.begin())
766 Remark <<
ore::NV(
"VTable", Symtab->getGlobalVariable(*Iter));
774 PromotedFuncCount.
push_back(Candidate.Count);
776 assert(TotalFuncCount >= Candidate.Count &&
777 "Within one prof metadata, total count is the sum of counts from "
778 "individual <target, count> pairs");
782 TotalFuncCount -= std::min(TotalFuncCount, Candidate.Count);
783 NumOfPGOICallPromotion++;
786 if (PromotedFuncCount.
empty())
795 for (
size_t I = 0;
I < PromotedFuncCount.
size();
I++)
796 ICallProfDataRef[
I].Count -=
797 std::max(PromotedFuncCount[
I], ICallProfDataRef[
I].Count);
800 const InstrProfValueData &RHS) {
801 return LHS.Count >
RHS.Count;
805 ICallProfDataRef.
begin(),
807 [](
uint64_t Count,
const InstrProfValueData &ProfData) {
808 return ProfData.Count <= Count;
810 updateFuncValueProfiles(CB, VDs, TotalFuncCount, NumCandidates);
811 updateVPtrValueProfiles(VPtr, VTableGUIDCounts);
818 bool Changed =
false;
824 CB, TotalCount, NumCandidates);
825 if (!NumCandidates ||
829 auto PromotionCandidates = getPromotionCandidatesForCallSite(
830 *CB, ICallProfDataRef, TotalCount, NumCandidates);
832 VTableGUIDCountsMap VTableGUIDCounts;
834 computeVTableInfos(CB, VTableGUIDCounts, PromotionCandidates);
836 if (isProfitableToCompareVTables(*CB, PromotionCandidates))
837 Changed |= tryToPromoteWithVTableCmp(*CB, VPtr, PromotionCandidates,
838 TotalCount, NumCandidates,
839 ICallProfDataRef, VTableGUIDCounts);
841 Changed |= tryToPromoteWithFuncCmp(*CB, VPtr, PromotionCandidates,
842 TotalCount, ICallProfDataRef,
843 NumCandidates, VTableGUIDCounts);
850bool IndirectCallPromoter::isProfitableToCompareVTables(
854 LLVM_DEBUG(
dbgs() <<
"\nEvaluating vtable profitability for callsite #"
855 << NumOfPGOICallsites << CB <<
"\n");
856 const size_t CandidateSize = Candidates.
size();
857 for (
size_t I = 0;
I < CandidateSize;
I++) {
858 auto &Candidate = Candidates[
I];
859 auto &VTableGUIDAndCounts = Candidate.VTableGUIDAndCounts;
862 << Candidate.Count <<
", VTableCounts:");
864 for ([[maybe_unused]]
auto &[GUID, Count] : VTableGUIDAndCounts)
865 LLVM_DEBUG(
dbgs() <<
" {" << Symtab->getGlobalVariable(GUID)->getName()
866 <<
", " << Count <<
"}");
871 for (
auto &[GUID, Count] : VTableGUIDAndCounts) {
872 CandidateVTableCount += Count;
874 if (shouldSkipVTable(GUID))
880 dbgs() <<
" function count " << Candidate.Count
881 <<
" and its vtable sum count " << CandidateVTableCount
882 <<
" have discrepancies. Bail out vtable comparison.\n");
892 int MaxNumVTable = 1;
893 if (
I == CandidateSize - 1)
896 if ((
int)Candidate.AddressPoints.size() > MaxNumVTable) {
897 LLVM_DEBUG(
dbgs() <<
" allow at most " << MaxNumVTable <<
" and got "
898 << Candidate.AddressPoints.size()
899 <<
" vtables. Bail out for vtable comparison.\n");
907bool IndirectCallPromoter::shouldSkipVTable(
uint64_t VTableGUID) {
908 if (IgnoredBaseTypes.empty())
911 auto *VTableVar = Symtab->getGlobalVariable(VTableGUID);
913 assert(VTableVar &&
"VTableVar must exist for GUID in VTableGUIDAndCounts");
916 VTableVar->
getMetadata(LLVMContext::MD_type, Types);
918 for (
auto *
Type : Types)
919 if (
auto *TypeId = dyn_cast<MDString>(
Type->getOperand(1).get()))
920 if (IgnoredBaseTypes.contains(TypeId->getString())) {
922 "out of vtable comparison.");
936 VirtualCallSiteTypeInfoMap &VirtualCSInfo) {
947 if (!TypeTestFunc || TypeTestFunc->
use_empty())
956 auto *CI = dyn_cast<CallInst>(U.getUser());
959 auto *TypeMDVal = cast<MetadataAsValue>(CI->getArgOperand(1));
962 auto *CompatibleTypeId = dyn_cast<MDString>(TypeMDVal->getMetadata());
963 if (!CompatibleTypeId)
970 auto &DT = LookupDomTree(*CI->getFunction());
973 for (
auto &DevirtCall : DevirtCalls) {
981 VirtualCSInfo[&CB] = {DevirtCall.Offset, VTablePtr,
982 CompatibleTypeId->getString()};
994 std::string SymtabFailure =
toString(std::move(E));
995 M.getContext().emitError(
"Failed to create symtab: " + SymtabFailure);
998 bool Changed =
false;
999 VirtualCallSiteTypeInfoMap VirtualCSInfo;
1007 IgnoredBaseTypes.
insert(Str);
1017 VTableAddressPointOffsetValMap VTableAddressPointOffsetVal;
1020 if (
F.isDeclaration() ||
F.hasOptNone())
1027 IndirectCallPromoter CallPromoter(
F, M, &Symtab, SamplePGO, VirtualCSInfo,
1028 VTableAddressPointOffsetVal,
1029 IgnoredBaseTypes, ORE);
1030 bool FuncChanged = CallPromoter.processFunction(PSI);
1035 Changed |= FuncChanged;
This file defines the DenseMap class.
This header defines various interfaces for pass management in LLVM.
This file provides the interface for IR based instrumentation passes ( (profile-gen,...
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
This file contains the declarations for profiling metadata utility functions.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Class for arbitrary precision integers.
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.
LLVM Basic Block Representation.
const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
const BasicBlock * getUniquePredecessor() const
Return the predecessor of this block if it has a unique predecessor block.
InstListType::iterator iterator
Instruction iterators...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
static Constant * getInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef< Constant * > IdxList)
Create an "inbounds" getelementptr.
This is an important base class in LLVM.
iterator find(const_arg_type_t< KeyT > Val)
Implements a dense probed hash-table based set.
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Lightweight error class with error context and mandatory checking.
const Function & getFunction() const
MDNode * getMetadata(unsigned KindID) const
Get the current metadata attachments for the given kind, if any.
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
A symbol table used for function [IR]PGO name look-up with keys (such as pointers,...
Error create(object::SectionRef &Section)
Create InstrProfSymtab from an object file section which contains function PGO names.
bool isDebugOrPseudoInst() const LLVM_READONLY
Return true if the instruction is a DbgInfoIntrinsic or PseudoProbeInst.
unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
This is an important class for using LLVM in a threaded context.
MDNode * createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight, bool IsExpected=false)
Return metadata containing two branch weights.
A Module instance is used to store all the information related to an LLVM module.
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
An analysis pass based on the new PM to deliver ProfileSummaryInfo.
Analysis providing profile information.
bool hasProfileSummary() const
Returns true if profile summary is available.
bool isHotCount(uint64_t C) const
Returns true if count C is considered hot.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Target - Wrapper for Target specific information.
The instances of the Type class are immutable: once they are created, they are never changed.
static IntegerType * getInt8Ty(LLVMContext &C)
static IntegerType * getInt32Ty(LLVMContext &C)
A Use represents the edge between a Value definition and its users.
User * getUser() const
Returns the User that contains this Use.
LLVMContext & getContext() const
All values hold a context through their type.
iterator_range< use_iterator > uses()
std::pair< iterator, bool > insert(const ValueT &V)
const ParentTy * getParent() const
@ C
The default llvm calling convention, compatible with C.
Function * getDeclarationIfExists(Module *M, ID id, ArrayRef< Type * > Tys, FunctionType *FT=nullptr)
This version supports overloaded intrinsics.
initializer< Ty > init(const Ty &Val)
DiagnosticInfoOptimizationBase::Argument NV
CallBase & promoteIndirectCall(CallBase &CB, Function *F, uint64_t Count, uint64_t TotalCount, bool AttachProfToDirectCall, OptimizationRemarkEmitter *ORE)
NodeAddr< FuncNode * > Func
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
void stable_sort(R &&Range)
bool isLegalToPromote(const CallBase &CB, Function *Callee, const char **FailureReason=nullptr)
Return true if the given indirect call site can be made to call Callee.
std::vector< CallBase * > findIndirectCalls(Function &F)
CallBase & promoteCallWithIfThenElse(CallBase &CB, Function *Callee, MDNode *BranchWeights=nullptr)
Promote the given indirect call site to conditionally call Callee.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
auto upper_bound(R &&Range, T &&Value)
Provide wrappers to std::upper_bound which take ranges instead of having to pass begin/end explicitly...
cl::opt< bool > EnableVTableProfileUse("enable-vtable-profile-use", cl::init(false), cl::desc("If ThinLTO and WPD is enabled and this option is true, vtable " "profiles will be used by ICP pass for more efficient indirect " "call sequence. If false, type profiles won't be used."))
void annotateValueSite(Module &M, Instruction &Inst, const InstrProfRecord &InstrProfR, InstrProfValueKind ValueKind, uint32_t SiteIndx, uint32_t MaxMDCount=3)
Get the value profile data for value site SiteIdx from InstrProfR and annotate the instruction Inst w...
auto reverse(ContainerTy &&C)
void setBranchWeights(Instruction &I, ArrayRef< uint32_t > Weights, bool IsExpected)
Create a new branch_weights metadata node and add or overwrite a prof metadata reference to instructi...
void sort(IteratorTy Start, IteratorTy End)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
SmallVector< InstrProfValueData, 4 > getValueProfDataFromInst(const Instruction &Inst, InstrProfValueKind ValueKind, uint32_t MaxNumValueData, uint64_t &TotalC, bool GetNoICPValue=false)
Extract the value profile data from Inst and returns them if Inst is annotated with value profile dat...
static uint32_t scaleBranchCount(uint64_t Count, uint64_t Scale)
Scale an individual branch count.
static uint64_t calculateCountScale(uint64_t MaxCount)
Calculate what to divide by to scale counts.
const char * toString(DWARFSectionKind Kind)
CallBase & promoteCallWithVTableCmp(CallBase &CB, Instruction *VPtr, Function *Callee, ArrayRef< Constant * > AddressPoints, MDNode *BranchWeights)
This is similar to promoteCallWithIfThenElse except that the condition to promote a virtual call is t...
void findDevirtualizableCallsForTypeTest(SmallVectorImpl< DevirtCallSite > &DevirtCalls, SmallVectorImpl< CallInst * > &Assumes, const CallInst *CI, DominatorTree &DT)
Given a call to the intrinsic @llvm.type.test, find all devirtualizable call sites based on the call ...
std::pair< Function *, Constant * > getFunctionAtVTableOffset(GlobalVariable *GV, uint64_t Offset, Module &M)
Given a vtable and a specified offset, returns the function and the trivial pointer at the specified ...
static Instruction * tryGetVTableInstruction(CallBase *CB)