124#define DEBUG_TYPE "wholeprogramdevirt"
126STATISTIC(NumDevirtTargets,
"Number of whole program devirtualization targets");
127STATISTIC(NumSingleImpl,
"Number of single implementation devirtualizations");
129STATISTIC(NumUniformRetVal,
"Number of uniform return value optimizations");
130STATISTIC(NumUniqueRetVal,
"Number of unique return value optimizations");
132 "Number of 1 bit virtual constant propagations");
133STATISTIC(NumVirtConstProp,
"Number of virtual constant propagations");
135 "Controls how many calls should be devirtualized.");
140 "wholeprogramdevirt-summary-action",
141 cl::desc(
"What to do with the summary when running this pass"),
144 "Import typeid resolutions from summary and globals"),
146 "Export typeid resolutions to summary and globals")),
150 "wholeprogramdevirt-read-summary",
152 "Read summary from given bitcode or YAML file before running pass"),
156 "wholeprogramdevirt-write-summary",
157 cl::desc(
"Write summary to given bitcode or YAML file after running pass. "
158 "Output file format is deduced from extension: *.bc means writing "
159 "bitcode, otherwise YAML"),
165 "devirtualize-speculatively",
166 cl::desc(
"Enable speculative devirtualization optimization"),
172 cl::desc(
"Maximum number of call targets per "
173 "call site to enable branch funnels"));
177 cl::desc(
"Print index-based devirtualization messages"));
185 cl::desc(
"Enable whole program visibility"));
190 "disable-whole-program-visibility",
cl::Hidden,
191 cl::desc(
"Disable whole program visibility (overrides enabling options)"));
196 cl::desc(
"Prevent function(s) from being devirtualized"),
221 "wholeprogramdevirt-keep-unreachable-function",
222 cl::desc(
"Regard unreachable functions as possible devirtualize targets."),
233 cl::desc(
"Type of checking for incorrect devirtualizations"),
237 "Fallback to indirect when incorrect")));
241 std::vector<GlobPattern> Patterns;
242 template <
class T>
void init(
const T &StringList) {
243 for (
const auto &S : StringList)
245 Patterns.push_back(std::move(*Pat));
247 bool match(StringRef S) {
248 for (
const GlobPattern &
P : Patterns)
266 MinByte = std::max(MinByte,
Target.minAfterBytes());
268 MinByte = std::max(MinByte,
Target.minBeforeBytes());
291 std::vector<ArrayRef<uint8_t>> Used;
294 :
Target.TM->Bits->Before.BytesUsed;
296 : MinByte -
Target.minBeforeBytes();
306 for (
unsigned I = 0;; ++
I) {
308 for (
auto &&
B : Used)
311 if (BitsUsed != 0xff)
317 for (
unsigned I = 0;; ++
I) {
318 for (
auto &&
B : Used) {
320 while ((
I + Byte) <
B.size() && Byte < (
Size / 8)) {
338 OffsetByte = -(AllocBefore / 8 + 1);
340 OffsetByte = -((AllocBefore + 7) / 8 + (
BitWidth + 7) / 8);
341 OffsetBit = AllocBefore % 8;
345 Target.setBeforeBit(AllocBefore);
355 OffsetByte = AllocAfter / 8;
357 OffsetByte = (AllocAfter + 7) / 8;
358 OffsetBit = AllocAfter % 8;
362 Target.setAfterBit(AllocAfter);
391 const VTableSlot &RHS) {
392 return LHS.TypeID == RHS.TypeID && LHS.ByteOffset == RHS.ByteOffset;
403 return LHS.TypeID == RHS.TypeID && LHS.ByteOffset == RHS.ByteOffset;
427 if (!Summary->isLive())
430 if (!FS->fflags().MustBeUnreachable)
445struct VirtualCallSite {
452 unsigned *NumUnsafeUses =
nullptr;
455 emitRemark(
const StringRef OptName,
const StringRef TargetName,
456 function_ref<OptimizationRemarkEmitter &(Function &)> OREGetter) {
462 OREGetter(*F).emit(OptimizationRemark(
DEBUG_TYPE, OptName, DLoc,
Block)
463 <<
NV(
"Optimization", OptName)
464 <<
": devirtualized a call to "
465 <<
NV(
"FunctionName", TargetName));
468 void replaceAndErase(
469 const StringRef OptName,
const StringRef TargetName,
bool RemarksEnabled,
470 function_ref<OptimizationRemarkEmitter &(Function &)> OREGetter,
477 II->getUnwindDest()->removePredecessor(
II->getParent());
494 std::vector<VirtualCallSite> CallSites;
503 bool AllCallSitesDevirted =
true;
512 std::vector<FunctionSummary *> SummaryTypeCheckedLoadUsers;
516 std::vector<FunctionSummary *> SummaryTypeTestAssumeUsers;
518 bool isExported()
const {
519 return !SummaryTypeCheckedLoadUsers.empty() ||
520 !SummaryTypeTestAssumeUsers.empty();
523 void addSummaryTypeCheckedLoadUser(FunctionSummary *FS) {
524 SummaryTypeCheckedLoadUsers.push_back(FS);
525 AllCallSitesDevirted =
false;
528 void addSummaryTypeTestAssumeUser(FunctionSummary *FS) {
529 SummaryTypeTestAssumeUsers.push_back(FS);
530 AllCallSitesDevirted =
false;
533 void markDevirt() { AllCallSitesDevirted =
true; }
537struct VTableSlotInfo {
544 std::map<std::vector<uint64_t>,
CallSiteInfo> ConstCSInfo;
546 void addCallSite(
Value *VTable, CallBase &CB,
unsigned *NumUnsafeUses);
552CallSiteInfo &VTableSlotInfo::findCallSiteInfo(CallBase &CB) {
553 std::vector<uint64_t>
Args;
555 if (!CBType || CBType->getBitWidth() > 64 || CB.
arg_empty())
559 if (!CI || CI->getBitWidth() > 64)
561 Args.push_back(CI->getZExtValue());
563 return ConstCSInfo[
Args];
566void VTableSlotInfo::addCallSite(
Value *VTable, CallBase &CB,
567 unsigned *NumUnsafeUses) {
568 auto &CSI = findCallSiteInfo(CB);
569 CSI.AllCallSitesDevirted =
false;
570 CSI.CallSites.push_back({
VTable, CB, NumUnsafeUses});
578 ModuleSummaryIndex *
const ExportSummary;
579 const ModuleSummaryIndex *
const ImportSummary;
581 IntegerType *
const Int8Ty;
584 IntegerType *
const Int64Ty;
585 IntegerType *
const IntPtrTy;
591 const bool RemarksEnabled;
592 std::function<OptimizationRemarkEmitter &(
Function &)> OREGetter;
593 MapVector<VTableSlot, VTableSlotInfo> CallSlots;
598 SmallPtrSet<CallBase *, 8> OptimizedCalls;
612 std::map<CallInst *, unsigned> NumUnsafeUsesForTypeTest;
613 PatternList FunctionsToSkip;
615 const bool DevirtSpeculatively;
617 ModuleSummaryIndex *ExportSummary,
618 const ModuleSummaryIndex *ImportSummary,
619 bool DevirtSpeculatively)
622 ExportSummary(ExportSummary), ImportSummary(ImportSummary),
627 IntPtrTy(
M.getDataLayout().getIntPtrType(
M.
getContext(), 0)),
629 RemarksEnabled(areRemarksEnabled()),
630 OREGetter([&](
Function &
F) -> OptimizationRemarkEmitter & {
633 DevirtSpeculatively(DevirtSpeculatively) {
634 assert(!(ExportSummary && ImportSummary));
638 bool areRemarksEnabled();
641 scanTypeTestUsers(Function *TypeTestFunc,
642 DenseMap<
Metadata *, std::set<TypeMemberInfo>> &TypeIdMap);
643 void scanTypeCheckedLoadUsers(Function *TypeCheckedLoadFunc);
645 void buildTypeIdentifierMap(
646 std::vector<VTableBits> &Bits,
647 DenseMap<
Metadata *, std::set<TypeMemberInfo>> &TypeIdMap);
650 tryFindVirtualCallTargets(std::vector<VirtualCallTarget> &TargetsForSlot,
651 const std::set<TypeMemberInfo> &TypeMemberInfos,
653 ModuleSummaryIndex *ExportSummary);
655 void applySingleImplDevirt(VTableSlotInfo &SlotInfo, Constant *TheFn,
657 bool trySingleImplDevirt(ModuleSummaryIndex *ExportSummary,
659 VTableSlotInfo &SlotInfo,
660 WholeProgramDevirtResolution *Res);
662 void applyICallBranchFunnel(VTableSlotInfo &SlotInfo, Function &JT,
665 VTableSlotInfo &SlotInfo,
666 WholeProgramDevirtResolution *Res, VTableSlot Slot);
668 bool tryEvaluateFunctionsWithArgs(
670 ArrayRef<uint64_t> Args);
672 void applyUniformRetValOpt(
CallSiteInfo &CSInfo, StringRef FnName,
676 WholeProgramDevirtResolution::ByArg *Res);
680 std::string getGlobalName(VTableSlot Slot, ArrayRef<uint64_t> Args,
683 bool shouldExportConstantsAsAbsoluteSymbols();
688 void exportGlobal(VTableSlot Slot, ArrayRef<uint64_t> Args, StringRef Name,
690 void exportConstant(VTableSlot Slot, ArrayRef<uint64_t> Args, StringRef Name,
691 uint32_t Const, uint32_t &Storage);
695 Constant *importGlobal(VTableSlot Slot, ArrayRef<uint64_t> Args,
697 Constant *importConstant(VTableSlot Slot, ArrayRef<uint64_t> Args,
698 StringRef Name, IntegerType *IntTy,
701 Constant *getMemberAddr(
const TypeMemberInfo *M);
703 void applyUniqueRetValOpt(
CallSiteInfo &CSInfo, StringRef FnName,
bool IsOne,
704 Constant *UniqueMemberAddr);
705 bool tryUniqueRetValOpt(
unsigned BitWidth,
708 WholeProgramDevirtResolution::ByArg *Res,
709 VTableSlot Slot, ArrayRef<uint64_t> Args);
711 void applyVirtualConstProp(
CallSiteInfo &CSInfo, StringRef FnName,
712 Constant *Byte, Constant *Bit);
714 VTableSlotInfo &SlotInfo,
715 WholeProgramDevirtResolution *Res, VTableSlot Slot);
717 void rebuildGlobal(VTableBits &
B);
720 void importResolution(VTableSlot Slot, VTableSlotInfo &SlotInfo);
724 void removeRedundantTypeTests();
731 static ValueInfo lookUpFunctionValueInfo(Function *TheFn,
732 ModuleSummaryIndex *ExportSummary);
743 ModuleSummaryIndex *ExportSummary);
748 bool DevirtSpeculatively);
752 ModuleSummaryIndex &ExportSummary;
755 std::set<GlobalValue::GUID> &ExportedGUIDs;
759 std::map<ValueInfo, std::vector<VTableSlotSummary>> &LocalWPDTargetsMap;
764 DenseSet<StringRef> *ExternallyVisibleSymbolNamesPtr;
766 MapVector<VTableSlotSummary, VTableSlotInfo> CallSlots;
768 PatternList FunctionsToSkip;
771 ModuleSummaryIndex &ExportSummary,
772 std::set<GlobalValue::GUID> &ExportedGUIDs,
773 std::map<ValueInfo, std::vector<VTableSlotSummary>> &LocalWPDTargetsMap,
774 DenseSet<StringRef> *ExternallyVisibleSymbolNamesPtr)
775 : ExportSummary(ExportSummary), ExportedGUIDs(ExportedGUIDs),
776 LocalWPDTargetsMap(LocalWPDTargetsMap),
777 ExternallyVisibleSymbolNamesPtr(ExternallyVisibleSymbolNamesPtr) {
781 bool tryFindVirtualCallTargets(std::vector<ValueInfo> &TargetsForSlot,
783 uint64_t ByteOffset);
786 VTableSlotSummary &SlotSummary,
787 VTableSlotInfo &SlotInfo,
788 WholeProgramDevirtResolution *Res,
789 std::set<ValueInfo> &DevirtTargets);
803 std::optional<ModuleSummaryIndex> Index;
807 "ExportSummary is expected to be empty in non-LTO mode");
810 ExportSummary = Index.has_value() ? &Index.value() :
nullptr;
831 if (
TypeID.ends_with(
".virtual"))
837 if (!
TypeID.consume_front(
"_ZTS"))
845 std::string TypeInfo = (
"_ZTI" +
TypeID).str();
846 return IsVisibleToRegularObj(TypeInfo);
855 for (
auto *
Type : Types)
858 IsVisibleToRegularObj);
867 Module &M,
bool WholeProgramVisibilityEnabledInLTO,
869 bool ValidateAllVtablesHaveTypeInfos,
886 !(ValidateAllVtablesHaveTypeInfos &&
893 bool WholeProgramVisibilityEnabledInLTO) {
897 if (!PublicTypeTestFunc)
905 TypeTestFunc, {CI->getArgOperand(0), CI->getArgOperand(1)}, {},
"",
907 CI->replaceAllUsesWith(NewCI);
908 CI->eraseFromParent();
916 CI->replaceAllUsesWith(True);
917 CI->eraseFromParent();
928 for (
const auto &TypeID : Index.typeIdCompatibleVtableMap()) {
931 VisibleToRegularObjSymbols.
insert(
P.VTableVI.getGUID());
944 for (
auto &
P : Index) {
947 if (DynamicExportSymbols.
count(
P.first))
953 if (VisibleToRegularObjSymbols.
count(
P.first))
955 for (
auto &S :
P.second.getSummaryList()) {
967 std::map<
ValueInfo, std::vector<VTableSlotSummary>> &LocalWPDTargetsMap,
969 DevirtIndex(Summary, ExportedGUIDs, LocalWPDTargetsMap,
970 ExternallyVisibleSymbolNamesPtr)
977 std::map<
ValueInfo, std::vector<VTableSlotSummary>> &LocalWPDTargetsMap,
979 for (
auto &
T : LocalWPDTargetsMap) {
982 assert(VI.getSummaryList().size() == 1 &&
983 "Devirt of local target has more than one copy");
984 auto &S = VI.getSummaryList()[0];
985 if (!IsExported(S->modulePath(), VI))
989 for (
auto &SlotSummary :
T.second) {
990 auto *TIdSum = Summary.getTypeIdSummary(SlotSummary.TypeID);
992 auto WPDRes = TIdSum->WPDRes.find(SlotSummary.ByteOffset);
993 assert(WPDRes != TIdSum->WPDRes.end());
994 if (ExternallyVisibleSymbolNamesPtr)
995 ExternallyVisibleSymbolNamesPtr->
insert(WPDRes->second.SingleImplName);
997 WPDRes->second.SingleImplName,
998 Summary.getModuleHash(S->modulePath()));
1008 const auto &ModPaths = Summary->modulePaths();
1013 "combined summary should contain Regular LTO module");
1018 bool DevirtSpeculatively) {
1019 std::unique_ptr<ModuleSummaryIndex>
Summary =
1020 std::make_unique<ModuleSummaryIndex>(
false);
1025 ExitOnError ExitOnErr(
"-wholeprogramdevirt-read-summary: " +
ClReadSummary +
1027 auto ReadSummaryFile =
1029 if (Expected<std::unique_ptr<ModuleSummaryIndex>> SummaryOrErr =
1031 Summary = std::move(*SummaryOrErr);
1036 yaml::Input
In(ReadSummaryFile->getBuffer());
1043 DevirtModule(M,
MAM,
1048 DevirtSpeculatively)
1052 ExitOnError ExitOnErr(
1062 yaml::Output Out(OS);
1070void DevirtModule::buildTypeIdentifierMap(
1071 std::vector<VTableBits> &Bits,
1072 DenseMap<
Metadata *, std::set<TypeMemberInfo>> &TypeIdMap) {
1073 DenseMap<GlobalVariable *, VTableBits *> GVToBits;
1074 Bits.reserve(
M.global_size());
1076 for (GlobalVariable &GV :
M.globals()) {
1084 Bits.emplace_back();
1085 Bits.back().GV = &GV;
1086 Bits.back().ObjectSize =
1088 BitsPtr = &
Bits.back();
1091 for (MDNode *
Type : Types) {
1104bool DevirtModule::tryFindVirtualCallTargets(
1105 std::vector<VirtualCallTarget> &TargetsForSlot,
1106 const std::set<TypeMemberInfo> &TypeMemberInfos, uint64_t ByteOffset,
1107 ModuleSummaryIndex *ExportSummary) {
1109 if (!TM.Bits->GV->isConstant())
1114 if (!DevirtSpeculatively && TM.Bits->GV->getVCallVisibility() ==
1126 if (FunctionsToSkip.match(Fn->
getName()))
1131 if (Fn->
getName() ==
"__cxa_pure_virtual")
1149 TargetsForSlot.push_back({GV, &TM});
1153 return !TargetsForSlot.empty();
1156bool DevirtIndex::tryFindVirtualCallTargets(
1157 std::vector<ValueInfo> &TargetsForSlot,
1159 for (
const TypeIdOffsetVtableInfo &
P : TIdInfo) {
1170 if (
P.VTableVI.hasLocal() &&
P.VTableVI.getSummaryList().size() > 1)
1172 const GlobalVarSummary *
VS =
nullptr;
1173 for (
const auto &S :
P.VTableVI.getSummaryList()) {
1175 if (!CurVS->vTableFuncs().empty() ||
1198 for (
auto VTP :
VS->vTableFuncs()) {
1199 if (VTP.VTableOffset !=
P.AddressPointOffset + ByteOffset)
1205 TargetsForSlot.push_back(VTP.FuncVI);
1210 return !TargetsForSlot.empty();
1213void DevirtModule::applySingleImplDevirt(VTableSlotInfo &SlotInfo,
1214 Constant *TheFn,
bool &IsExported) {
1220 for (
auto &&VCallSite : CSInfo.CallSites) {
1221 if (!OptimizedCalls.
insert(&VCallSite.CB).second)
1229 VCallSite.emitRemark(
"single-impl",
1232 auto &CB = VCallSite.CB;
1245 MDBuilder(
M.getContext()).createUnlikelyBranchWeights());
1246 Builder.SetInsertPoint(ThenTerm);
1249 auto *CallTrap = Builder.CreateCall(TrapFn);
1258 MDNode *Weights = MDBuilder(
M.getContext()).createLikelyBranchWeights();
1267 NewInst.
setMetadata(LLVMContext::MD_prof,
nullptr);
1268 NewInst.
setMetadata(LLVMContext::MD_callees,
nullptr);
1290 CallsWithPtrAuthBundleRemoved.
push_back(&CB);
1295 if (VCallSite.NumUnsafeUses)
1296 --*VCallSite.NumUnsafeUses;
1298 if (CSInfo.isExported())
1300 CSInfo.markDevirt();
1302 Apply(SlotInfo.CSInfo);
1303 for (
auto &
P : SlotInfo.ConstCSInfo)
1309 if (Callee.getSummaryList().empty())
1316 bool IsExported =
false;
1317 auto &S = Callee.getSummaryList()[0];
1319 auto AddCalls = [&](CallSiteInfo &CSInfo) {
1320 for (
auto *FS : CSInfo.SummaryTypeCheckedLoadUsers) {
1321 FS->addCall({Callee, CI});
1322 IsExported |= S->modulePath() != FS->modulePath();
1324 for (
auto *FS : CSInfo.SummaryTypeTestAssumeUsers) {
1325 FS->addCall({Callee, CI});
1326 IsExported |= S->modulePath() != FS->modulePath();
1329 AddCalls(SlotInfo.CSInfo);
1330 for (
auto &
P : SlotInfo.ConstCSInfo)
1335bool DevirtModule::trySingleImplDevirt(
1336 ModuleSummaryIndex *ExportSummary,
1338 WholeProgramDevirtResolution *Res) {
1341 auto *TheFn = TargetsForSlot[0].Fn;
1342 for (
auto &&Target : TargetsForSlot)
1348 TargetsForSlot[0].WasDevirt =
true;
1350 bool IsExported =
false;
1351 applySingleImplDevirt(SlotInfo, TheFn, IsExported);
1358 if (TheFn->hasLocalLinkage()) {
1359 std::string NewName = (TheFn->
getName() +
".llvm.merged").str();
1364 if (Comdat *
C = TheFn->getComdat()) {
1365 if (
C->getName() == TheFn->
getName()) {
1366 Comdat *NewC =
M.getOrInsertComdat(NewName);
1368 for (GlobalObject &GO :
M.global_objects())
1369 if (GO.getComdat() ==
C)
1378 if (ValueInfo TheFnVI = ExportSummary->
getValueInfo(TheFn->getGUID()))
1390 VTableSlotSummary &SlotSummary,
1391 VTableSlotInfo &SlotInfo,
1392 WholeProgramDevirtResolution *Res,
1393 std::set<ValueInfo> &DevirtTargets) {
1396 auto TheFn = TargetsForSlot[0];
1397 for (
auto &&Target : TargetsForSlot)
1398 if (TheFn != Target)
1402 auto Size = TheFn.getSummaryList().size();
1408 if (FunctionsToSkip.match(TheFn.name()))
1413 if (TheFn.hasLocal() &&
Size > 1)
1418 DevirtTargets.insert(TheFn);
1420 auto &S = TheFn.getSummaryList()[0];
1421 bool IsExported =
addCalls(SlotInfo, TheFn);
1423 ExportedGUIDs.insert(TheFn.getGUID());
1433 if (ExternallyVisibleSymbolNamesPtr)
1434 ExternallyVisibleSymbolNamesPtr->insert(TheFn.name());
1436 TheFn.name(), ExportSummary.
getModuleHash(S->modulePath()));
1438 LocalWPDTargetsMap[TheFn].push_back(SlotSummary);
1452void DevirtModule::tryICallBranchFunnel(
1454 WholeProgramDevirtResolution *Res, VTableSlot Slot) {
1455 Triple
T(
M.getTargetTriple());
1462 bool HasNonDevirt = !SlotInfo.CSInfo.AllCallSitesDevirted;
1464 for (
auto &
P : SlotInfo.ConstCSInfo)
1465 if (!
P.second.AllCallSitesDevirted) {
1466 HasNonDevirt =
true;
1484 for (
auto &
T : TargetsForSlot) {
1485 if (
T.TM->Bits->GV->hasAvailableExternallyLinkage())
1494 M.getDataLayout().getProgramAddressSpace(),
1495 getGlobalName(Slot, {},
"branch_funnel"), &
M);
1499 M.getDataLayout().getProgramAddressSpace(),
1500 "branch_funnel", &M);
1504 std::vector<Value *> JTArgs;
1506 for (
auto &
T : TargetsForSlot) {
1507 JTArgs.push_back(getMemberAddr(
T.TM));
1508 JTArgs.push_back(
T.Fn);
1513 &M, llvm::Intrinsic::icall_branch_funnel, {});
1519 bool IsExported =
false;
1520 applyICallBranchFunnel(SlotInfo, *JT, IsExported);
1530void DevirtModule::applyICallBranchFunnel(VTableSlotInfo &SlotInfo,
1531 Function &JT,
bool &IsExported) {
1532 DenseMap<Function *, double> FunctionEntryCounts;
1534 if (CSInfo.isExported())
1536 if (CSInfo.AllCallSitesDevirted)
1539 std::map<CallBase *, CallBase *> CallBases;
1540 for (
auto &&VCallSite : CSInfo.CallSites) {
1541 CallBase &CB = VCallSite.CB;
1543 if (CallBases.find(&CB) != CallBases.end()) {
1560 VCallSite.emitRemark(
"branch-funnel", JT.
getName(), OREGetter);
1564 std::vector<Type *> NewArgs;
1565 NewArgs.push_back(Int8PtrTy);
1567 FunctionType *NewFT =
1571 std::vector<Value *>
Args;
1572 Args.push_back(VCallSite.VTable);
1575 CallBase *NewCS =
nullptr;
1581 auto EC = BFI.getBlockFreq(&
F.getEntryBlock());
1582 auto CC =
F.getEntryCount(
true);
1583 double CallCount = 0.0;
1584 if (
EC.getFrequency() != 0 && CC && CC->getCount() != 0) {
1586 static_cast<double>(
1587 BFI.getBlockFreq(CB.
getParent()).getFrequency()) /
1589 CallCount = CallFreq * CC->getCount();
1591 FunctionEntryCounts[&JT] += CallCount;
1594 NewCS = IRB.CreateCall(NewFT, &JT, Args);
1602 std::vector<AttributeSet> NewArgAttrs;
1605 M.getContext(), Attribute::Nest)}));
1606 for (
unsigned I = 0;
I + 2 <
Attrs.getNumAttrSets(); ++
I)
1607 NewArgAttrs.push_back(
Attrs.getParamAttrs(
I));
1609 AttributeList::get(
M.getContext(),
Attrs.getFnAttrs(),
1610 Attrs.getRetAttrs(), NewArgAttrs));
1612 CallBases[&CB] = NewCS;
1615 if (VCallSite.NumUnsafeUses)
1616 --*VCallSite.NumUnsafeUses;
1623 for (
auto &[Old, New] : CallBases) {
1624 Old->replaceAllUsesWith(New);
1625 Old->eraseFromParent();
1628 Apply(SlotInfo.CSInfo);
1629 for (
auto &
P : SlotInfo.ConstCSInfo)
1631 for (
auto &[
F,
C] : FunctionEntryCounts) {
1632 assert(!
F->getEntryCount(
true) &&
1633 "Unexpected entry count for funnel that was freshly synthesized");
1634 F->setEntryCount(
static_cast<uint64_t
>(std::round(
C)));
1638bool DevirtModule::tryEvaluateFunctionsWithArgs(
1640 ArrayRef<uint64_t> Args) {
1654 Evaluator Eval(
M.getDataLayout(),
nullptr);
1658 for (
unsigned I = 0;
I !=
Args.size(); ++
I) {
1663 EvalArgs.
push_back(ConstantInt::get(ArgTy, Args[
I]));
1667 if (!Eval.EvaluateFunction(Fn, RetVal, EvalArgs) ||
1675void DevirtModule::applyUniformRetValOpt(
CallSiteInfo &CSInfo, StringRef FnName,
1676 uint64_t TheRetVal) {
1677 for (
auto Call : CSInfo.CallSites) {
1681 Call.replaceAndErase(
1682 "uniform-ret-val", FnName, RemarksEnabled, OREGetter,
1685 CSInfo.markDevirt();
1688bool DevirtModule::tryUniformRetValOpt(
1690 WholeProgramDevirtResolution::ByArg *Res) {
1693 uint64_t TheRetVal = TargetsForSlot[0].RetVal;
1695 if (
Target.RetVal != TheRetVal)
1698 if (CSInfo.isExported()) {
1700 Res->
Info = TheRetVal;
1703 applyUniformRetValOpt(CSInfo, TargetsForSlot[0].Fn->
getName(), TheRetVal);
1705 for (
auto &&Target : TargetsForSlot)
1710std::string DevirtModule::getGlobalName(VTableSlot Slot,
1711 ArrayRef<uint64_t> Args,
1713 std::string FullName =
"__typeid_";
1714 raw_string_ostream OS(FullName);
1715 OS << cast<MDString>(
Slot.TypeID)->getString() <<
'_' <<
Slot.ByteOffset;
1716 for (uint64_t Arg : Args)
1722bool DevirtModule::shouldExportConstantsAsAbsoluteSymbols() {
1723 Triple
T(
M.getTargetTriple());
1727void DevirtModule::exportGlobal(VTableSlot Slot, ArrayRef<uint64_t> Args,
1728 StringRef Name, Constant *
C) {
1730 getGlobalName(Slot, Args, Name),
C, &M);
1734void DevirtModule::exportConstant(VTableSlot Slot, ArrayRef<uint64_t> Args,
1735 StringRef Name, uint32_t Const,
1736 uint32_t &Storage) {
1737 if (shouldExportConstantsAsAbsoluteSymbols()) {
1747Constant *DevirtModule::importGlobal(VTableSlot Slot, ArrayRef<uint64_t> Args,
1749 GlobalVariable *GV =
1750 M.getOrInsertGlobal(getGlobalName(Slot, Args, Name), Int8Arr0Ty);
1755Constant *DevirtModule::importConstant(VTableSlot Slot, ArrayRef<uint64_t> Args,
1756 StringRef Name, IntegerType *IntTy,
1758 if (!shouldExportConstantsAsAbsoluteSymbols())
1759 return ConstantInt::get(IntTy, Storage);
1761 Constant *
C = importGlobal(Slot, Args, Name);
1767 if (GV->
hasMetadata(LLVMContext::MD_absolute_symbol))
1770 auto SetAbsRange = [&](uint64_t Min, uint64_t
Max) {
1781 SetAbsRange(0, 1ull << AbsWidth);
1786void DevirtModule::applyUniqueRetValOpt(
CallSiteInfo &CSInfo, StringRef FnName,
1788 Constant *UniqueMemberAddr) {
1789 for (
auto &&
Call : CSInfo.CallSites) {
1795 B.CreateBitCast(UniqueMemberAddr,
Call.VTable->
getType()));
1798 Call.replaceAndErase(
"unique-ret-val", FnName, RemarksEnabled, OREGetter,
1801 CSInfo.markDevirt();
1806 ConstantInt::get(Int64Ty,
M->Offset));
1809bool DevirtModule::tryUniqueRetValOpt(
1811 CallSiteInfo &CSInfo, WholeProgramDevirtResolution::ByArg *Res,
1812 VTableSlot Slot, ArrayRef<uint64_t> Args) {
1814 auto tryUniqueRetValOptFor = [&](
bool IsOne) {
1817 if (
Target.RetVal == (IsOne ? 1 : 0)) {
1820 UniqueMember =
Target.TM;
1828 Constant *UniqueMemberAddr = getMemberAddr(UniqueMember);
1829 if (CSInfo.isExported()) {
1833 exportGlobal(Slot, Args,
"unique_member", UniqueMemberAddr);
1837 applyUniqueRetValOpt(CSInfo, TargetsForSlot[0].Fn->
getName(), IsOne,
1842 for (
auto &&Target : TargetsForSlot)
1849 if (tryUniqueRetValOptFor(
true))
1851 if (tryUniqueRetValOptFor(
false))
1857void DevirtModule::applyVirtualConstProp(
CallSiteInfo &CSInfo, StringRef FnName,
1858 Constant *Byte, Constant *Bit) {
1859 for (
auto Call : CSInfo.CallSites) {
1864 Value *Addr =
B.CreatePtrAdd(
Call.VTable, Byte);
1865 if (RetType->getBitWidth() == 1) {
1867 Value *BitsAndBit =
B.CreateAnd(Bits, Bit);
1868 auto IsBitSet =
B.CreateICmpNE(BitsAndBit, ConstantInt::get(Int8Ty, 0));
1869 NumVirtConstProp1Bit++;
1870 Call.replaceAndErase(
"virtual-const-prop-1-bit", FnName, RemarksEnabled,
1871 OREGetter, IsBitSet);
1873 Value *Val =
B.CreateLoad(RetType, Addr);
1875 Call.replaceAndErase(
"virtual-const-prop", FnName, RemarksEnabled,
1879 CSInfo.markDevirt();
1882bool DevirtModule::tryVirtualConstProp(
1884 WholeProgramDevirtResolution *Res, VTableSlot Slot) {
1895 unsigned BitWidth = RetType->getBitWidth();
1907 Align TypeAlignment =
M.getDataLayout().getABIIntegerTypeAlignment(
BitWidth);
1940 GlobalVariable *GV =
Target.TM->Bits->GV;
1941 Align TableAlignment =
M.getDataLayout().getValueOrABITypeAlignment(
1943 if (TypeAlignment > TableAlignment)
1947 for (
auto &&CSByConstantArg : SlotInfo.ConstCSInfo) {
1948 if (!tryEvaluateFunctionsWithArgs(TargetsForSlot, CSByConstantArg.first))
1951 WholeProgramDevirtResolution::ByArg *ResByArg =
nullptr;
1953 ResByArg = &Res->
ResByArg[CSByConstantArg.first];
1955 if (tryUniformRetValOpt(TargetsForSlot, CSByConstantArg.second, ResByArg))
1958 if (tryUniqueRetValOpt(
BitWidth, TargetsForSlot, CSByConstantArg.second,
1959 ResByArg, Slot, CSByConstantArg.first))
1967 uint64_t AllocBefore =
1969 uint64_t AllocAfter =
1974 uint64_t TotalPaddingBefore = 0, TotalPaddingAfter = 0;
1975 for (
auto &&Target : TargetsForSlot) {
1976 TotalPaddingBefore += std::max<int64_t>(
1977 (AllocBefore + 7) / 8 -
Target.allocatedBeforeBytes() - 1, 0);
1978 TotalPaddingAfter += std::max<int64_t>(
1979 (AllocAfter + 7) / 8 -
Target.allocatedAfterBytes() - 1, 0);
1984 if (std::min(TotalPaddingBefore, TotalPaddingAfter) > 128)
1991 if (TotalPaddingBefore <= TotalPaddingAfter)
2007 for (
auto &&Target : TargetsForSlot)
2011 if (CSByConstantArg.second.isExported()) {
2013 ResByArg->
Byte = OffsetByte;
2014 exportConstant(Slot, CSByConstantArg.first,
"bit", 1ULL << OffsetBit,
2020 Constant *BitConst = ConstantInt::get(Int8Ty, 1ULL << OffsetBit);
2021 applyVirtualConstProp(CSByConstantArg.second,
2022 TargetsForSlot[0].Fn->getName(), ByteConst, BitConst);
2028 if (
B.Before.Bytes.empty() &&
B.After.Bytes.empty())
2033 Align Alignment =
M.getDataLayout().getValueOrABITypeAlignment(
2034 B.GV->getAlign(),
B.GV->getValueType());
2035 B.Before.Bytes.resize(
alignTo(
B.Before.Bytes.size(), Alignment));
2038 for (
size_t I = 0,
Size =
B.Before.Bytes.size();
I !=
Size / 2; ++
I)
2045 B.GV->getInitializer(),
2048 new GlobalVariable(M, NewInit->getType(),
B.GV->isConstant(),
2050 NewGV->setSection(
B.GV->getSection());
2051 NewGV->setComdat(
B.GV->getComdat());
2052 NewGV->setAlignment(
B.GV->getAlign());
2056 NewGV->copyMetadata(
B.GV,
B.Before.Bytes.size());
2061 B.GV->getInitializer()->getType(), 0,
B.GV->getLinkage(),
"",
2063 NewInit->getType(), NewGV,
2065 ConstantInt::get(Int32Ty, 1)}),
2067 Alias->setVisibility(
B.GV->getVisibility());
2068 Alias->takeName(
B.GV);
2070 B.GV->replaceAllUsesWith(Alias);
2071 B.GV->eraseFromParent();
2074bool DevirtModule::areRemarksEnabled() {
2075 const auto &FL =
M.getFunctionList();
2076 for (
const Function &Fn : FL) {
2080 return DI.isEnabled();
2085void DevirtModule::scanTypeTestUsers(
2086 Function *TypeTestFunc,
2087 DenseMap<
Metadata *, std::set<TypeMemberInfo>> &TypeIdMap) {
2101 auto &DT =
FAM.
getResult<DominatorTreeAnalysis>(*CI->getFunction());
2107 if (!Assumes.
empty()) {
2108 Value *Ptr = CI->getArgOperand(0)->stripPointerCasts();
2109 for (DevirtCallSite
Call : DevirtCalls)
2110 CallSlots[{TypeId,
Call.Offset}].addCallSite(Ptr,
Call.CB,
nullptr);
2113 auto RemoveTypeTestAssumes = [&]() {
2115 for (
auto *Assume : Assumes)
2116 Assume->eraseFromParent();
2119 if (CI->use_empty())
2120 CI->eraseFromParent();
2135 if (!TypeIdMap.count(TypeId))
2136 RemoveTypeTestAssumes();
2148 const TypeIdSummary *TidSummary =
2151 RemoveTypeTestAssumes();
2160void DevirtModule::scanTypeCheckedLoadUsers(Function *TypeCheckedLoadFunc) {
2169 Value *Ptr = CI->getArgOperand(0);
2171 Value *TypeIdValue = CI->getArgOperand(2);
2177 bool HasNonCallUses =
false;
2178 auto &DT =
FAM.
getResult<DominatorTreeAnalysis>(*CI->getFunction());
2180 HasNonCallUses, CI, DT);
2189 (LoadedPtrs.
size() == 1 && !HasNonCallUses) ? LoadedPtrs[0] : CI);
2191 Value *LoadedValue =
nullptr;
2193 Intrinsic::type_checked_load_relative) {
2195 &M, Intrinsic::load_relative, {
Int32Ty});
2196 LoadedValue = LoadB.CreateCall(LoadRelFunc, {Ptr,
Offset});
2199 LoadedValue = LoadB.CreateLoad(Int8PtrTy,
GEP);
2202 for (Instruction *LoadedPtr : LoadedPtrs) {
2203 LoadedPtr->replaceAllUsesWith(LoadedValue);
2204 LoadedPtr->eraseFromParent();
2208 IRBuilder<> CallB((Preds.
size() == 1 && !HasNonCallUses) ? Preds[0] : CI);
2209 CallInst *TypeTestCall = CallB.CreateCall(TypeTestFunc, {Ptr, TypeIdValue});
2211 for (Instruction *Pred : Preds) {
2212 Pred->replaceAllUsesWith(TypeTestCall);
2213 Pred->eraseFromParent();
2220 if (!CI->use_empty()) {
2223 Pair =
B.CreateInsertValue(Pair, LoadedValue, {0});
2224 Pair =
B.CreateInsertValue(Pair, TypeTestCall, {1});
2229 auto &NumUnsafeUses = NumUnsafeUsesForTypeTest[TypeTestCall];
2230 NumUnsafeUses = DevirtCalls.
size();
2237 for (DevirtCallSite
Call : DevirtCalls) {
2238 CallSlots[{TypeId,
Call.Offset}].addCallSite(Ptr,
Call.CB,
2242 CI->eraseFromParent();
2246void DevirtModule::importResolution(VTableSlot Slot, VTableSlotInfo &SlotInfo) {
2250 const TypeIdSummary *TidSummary =
2254 auto ResI = TidSummary->
WPDRes.find(
Slot.ByteOffset);
2255 if (ResI == TidSummary->
WPDRes.end())
2257 const WholeProgramDevirtResolution &Res = ResI->second;
2269 bool IsExported =
false;
2270 applySingleImplDevirt(SlotInfo, SingleImpl, IsExported);
2274 for (
auto &CSByConstantArg : SlotInfo.ConstCSInfo) {
2275 auto I = Res.
ResByArg.find(CSByConstantArg.first);
2278 auto &ResByArg =
I->second;
2285 applyUniformRetValOpt(CSByConstantArg.second,
"", ResByArg.
Info);
2289 importGlobal(Slot, CSByConstantArg.first,
"unique_member");
2290 applyUniqueRetValOpt(CSByConstantArg.second,
"", ResByArg.
Info,
2296 Constant *
Bit = importConstant(Slot, CSByConstantArg.first,
"bit", Int8Ty,
2298 applyVirtualConstProp(CSByConstantArg.second,
"", Byte, Bit);
2310 M.getOrInsertFunction(getGlobalName(Slot, {},
"branch_funnel"),
2313 bool IsExported =
false;
2314 applyICallBranchFunnel(SlotInfo, *JT, IsExported);
2319void DevirtModule::removeRedundantTypeTests() {
2321 for (
auto &&U : NumUnsafeUsesForTypeTest) {
2322 if (
U.second == 0) {
2323 U.first->replaceAllUsesWith(True);
2324 U.first->eraseFromParent();
2330DevirtModule::lookUpFunctionValueInfo(Function *TheFn,
2331 ModuleSummaryIndex *ExportSummary) {
2332 assert((ExportSummary !=
nullptr) &&
2333 "Caller guarantees ExportSummary is not nullptr");
2335 const auto TheFnGUID = TheFn->
getGUID();
2336 const auto TheFnGUIDWithExportedName =
2339 ValueInfo TheFnVI = ExportSummary->
getValueInfo(TheFnGUID);
2348 if ((!TheFnVI) && (TheFnGUID != TheFnGUIDWithExportedName)) {
2349 TheFnVI = ExportSummary->
getValueInfo(TheFnGUIDWithExportedName);
2354bool DevirtModule::mustBeUnreachableFunction(
2355 Function *
const F, ModuleSummaryIndex *ExportSummary) {
2359 if (!
F->isDeclaration()) {
2365 return ExportSummary &&
2367 DevirtModule::lookUpFunctionValueInfo(
F, ExportSummary));
2370bool DevirtModule::run() {
2379 Function *PublicTypeTestFunc =
nullptr;
2382 if (DevirtSpeculatively)
2383 PublicTypeTestFunc =
2390 &M, Intrinsic::type_checked_load_relative);
2397 if (!ExportSummary &&
2398 (((!PublicTypeTestFunc || PublicTypeTestFunc->
use_empty()) &&
2399 (!TypeTestFunc || TypeTestFunc->
use_empty())) ||
2400 !AssumeFunc || AssumeFunc->
use_empty()) &&
2401 (!TypeCheckedLoadFunc || TypeCheckedLoadFunc->
use_empty()) &&
2402 (!TypeCheckedLoadRelativeFunc ||
2403 TypeCheckedLoadRelativeFunc->
use_empty()))
2407 std::vector<VTableBits>
Bits;
2408 DenseMap<Metadata *, std::set<TypeMemberInfo>> TypeIdMap;
2409 buildTypeIdentifierMap(Bits, TypeIdMap);
2411 if (PublicTypeTestFunc && AssumeFunc)
2412 scanTypeTestUsers(PublicTypeTestFunc, TypeIdMap);
2414 if (TypeTestFunc && AssumeFunc)
2415 scanTypeTestUsers(TypeTestFunc, TypeIdMap);
2417 if (TypeCheckedLoadFunc)
2418 scanTypeCheckedLoadUsers(TypeCheckedLoadFunc);
2420 if (TypeCheckedLoadRelativeFunc)
2421 scanTypeCheckedLoadUsers(TypeCheckedLoadRelativeFunc);
2423 if (ImportSummary) {
2424 for (
auto &S : CallSlots)
2425 importResolution(S.first, S.second);
2427 removeRedundantTypeTests();
2432 for (GlobalVariable &GV :
M.globals())
2440 if (TypeIdMap.
empty())
2444 if (ExportSummary) {
2445 DenseMap<GlobalValue::GUID, TinyPtrVector<Metadata *>> MetadataByGUID;
2446 for (
auto &
P : TypeIdMap) {
2449 TypeId->getString())]
2453 for (
auto &
P : *ExportSummary) {
2454 for (
auto &S :
P.second.getSummaryList()) {
2459 for (FunctionSummary::VFuncId VF :
FS->type_test_assume_vcalls()) {
2460 for (
Metadata *MD : MetadataByGUID[VF.GUID]) {
2461 CallSlots[{MD, VF.Offset}].CSInfo.addSummaryTypeTestAssumeUser(FS);
2464 for (FunctionSummary::VFuncId VF :
FS->type_checked_load_vcalls()) {
2465 for (
Metadata *MD : MetadataByGUID[VF.GUID]) {
2466 CallSlots[{MD, VF.Offset}].CSInfo.addSummaryTypeCheckedLoadUser(FS);
2469 for (
const FunctionSummary::ConstVCall &VC :
2470 FS->type_test_assume_const_vcalls()) {
2471 for (
Metadata *MD : MetadataByGUID[
VC.VFunc.GUID]) {
2472 CallSlots[{MD,
VC.VFunc.Offset}]
2473 .ConstCSInfo[
VC.Args]
2474 .addSummaryTypeTestAssumeUser(FS);
2477 for (
const FunctionSummary::ConstVCall &VC :
2478 FS->type_checked_load_const_vcalls()) {
2479 for (
Metadata *MD : MetadataByGUID[
VC.VFunc.GUID]) {
2480 CallSlots[{MD,
VC.VFunc.Offset}]
2481 .ConstCSInfo[
VC.Args]
2482 .addSummaryTypeCheckedLoadUser(FS);
2490 bool DidVirtualConstProp =
false;
2491 std::map<std::string, GlobalValue *> DevirtTargets;
2492 for (
auto &S : CallSlots) {
2496 std::vector<VirtualCallTarget> TargetsForSlot;
2497 WholeProgramDevirtResolution *Res =
nullptr;
2498 const std::set<TypeMemberInfo> &TypeMemberInfos = TypeIdMap[S.first.TypeID];
2500 TypeMemberInfos.size())
2507 Res = &ExportSummary
2508 ->getOrInsertTypeIdSummary(
2510 .WPDRes[S.first.ByteOffset];
2511 if (tryFindVirtualCallTargets(TargetsForSlot, TypeMemberInfos,
2512 S.first.ByteOffset, ExportSummary)) {
2513 bool SingleImplDevirt =
2514 trySingleImplDevirt(ExportSummary, TargetsForSlot, S.second, Res);
2518 if (!SingleImplDevirt && !DevirtSpeculatively) {
2519 DidVirtualConstProp |=
2520 tryVirtualConstProp(TargetsForSlot, S.second, Res, S.first);
2522 tryICallBranchFunnel(TargetsForSlot, S.second, Res, S.first);
2527 for (
const auto &
T : TargetsForSlot)
2529 DevirtTargets[std::string(
T.Fn->getName())] =
T.Fn;
2539 auto AddTypeTestsForTypeCheckedLoads = [&](
CallSiteInfo &CSI) {
2540 if (!CSI.AllCallSitesDevirted)
2541 for (
auto *FS : CSI.SummaryTypeCheckedLoadUsers)
2542 FS->addTypeTest(GUID);
2544 AddTypeTestsForTypeCheckedLoads(S.second.CSInfo);
2545 for (
auto &CCS : S.second.ConstCSInfo)
2546 AddTypeTestsForTypeCheckedLoads(CCS.second);
2550 if (RemarksEnabled) {
2552 for (
const auto &DT : DevirtTargets) {
2553 GlobalValue *GV = DT.second;
2562 using namespace ore;
2563 OREGetter(*F).emit(OptimizationRemark(
DEBUG_TYPE,
"Devirtualized",
F)
2564 <<
"devirtualized " <<
NV(
"FunctionName", DT.first));
2568 NumDevirtTargets += DevirtTargets.size();
2570 removeRedundantTypeTests();
2574 if (DidVirtualConstProp)
2581 for (GlobalVariable &GV :
M.globals())
2584 for (
auto *CI : CallsWithPtrAuthBundleRemoved)
2585 CI->eraseFromParent();
2590void DevirtIndex::run() {
2591 if (ExportSummary.typeIdCompatibleVtableMap().empty())
2596 assert(!ExportSummary.withInternalizeAndPromote() &&
2597 "Expect index-based WPD to run before internalization and promotion");
2599 DenseMap<GlobalValue::GUID, std::vector<StringRef>> NameByGUID;
2600 for (
const auto &
P : ExportSummary.typeIdCompatibleVtableMap()) {
2609 ExportSummary.getOrInsertTypeIdSummary(
P.first);
2613 for (
auto &
P : ExportSummary) {
2614 for (
auto &S :
P.second.getSummaryList()) {
2619 for (FunctionSummary::VFuncId VF :
FS->type_test_assume_vcalls()) {
2620 for (StringRef Name : NameByGUID[VF.GUID]) {
2621 CallSlots[{
Name, VF.Offset}].CSInfo.addSummaryTypeTestAssumeUser(FS);
2624 for (FunctionSummary::VFuncId VF :
FS->type_checked_load_vcalls()) {
2625 for (StringRef Name : NameByGUID[VF.GUID]) {
2626 CallSlots[{
Name, VF.Offset}].CSInfo.addSummaryTypeCheckedLoadUser(FS);
2629 for (
const FunctionSummary::ConstVCall &VC :
2630 FS->type_test_assume_const_vcalls()) {
2631 for (StringRef Name : NameByGUID[
VC.VFunc.GUID]) {
2632 CallSlots[{
Name,
VC.VFunc.Offset}]
2633 .ConstCSInfo[
VC.Args]
2634 .addSummaryTypeTestAssumeUser(FS);
2637 for (
const FunctionSummary::ConstVCall &VC :
2638 FS->type_checked_load_const_vcalls()) {
2639 for (StringRef Name : NameByGUID[
VC.VFunc.GUID]) {
2640 CallSlots[{
Name,
VC.VFunc.Offset}]
2641 .ConstCSInfo[
VC.Args]
2642 .addSummaryTypeCheckedLoadUser(FS);
2648 std::set<ValueInfo> DevirtTargets;
2650 for (
auto &S : CallSlots) {
2654 std::vector<ValueInfo> TargetsForSlot;
2655 auto TidSummary = ExportSummary.getTypeIdCompatibleVtableSummary(S.first.TypeID);
2659 WholeProgramDevirtResolution *Res =
2660 &ExportSummary.getTypeIdSummary(S.first.TypeID)
2661 ->WPDRes[S.first.ByteOffset];
2662 if (tryFindVirtualCallTargets(TargetsForSlot, *TidSummary,
2663 S.first.ByteOffset)) {
2665 if (!trySingleImplDevirt(TargetsForSlot, S.first, S.second, Res,
2674 for (
const auto &DT : DevirtTargets)
2675 errs() <<
"Devirtualized call to " << DT <<
"\n";
2677 NumDevirtTargets += DevirtTargets.size();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This is the interface for LLVM's primary stateless and local alias analysis.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file provides an implementation of debug counters.
#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC)
This file defines DenseMapInfo traits for DenseMap.
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
Provides passes for computing function attributes based on interprocedural analyses.
static void emitRemark(const Function &F, OptimizationRemarkEmitter &ORE, bool Skip)
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
static cl::opt< PassSummaryAction > ClSummaryAction("lowertypetests-summary-action", cl::desc("What to do with the summary when running this pass"), cl::values(clEnumValN(PassSummaryAction::None, "none", "Do nothing"), clEnumValN(PassSummaryAction::Import, "import", "Import typeid resolutions from summary and globals"), clEnumValN(PassSummaryAction::Export, "export", "Export typeid resolutions to summary and globals")), cl::Hidden)
Machine Check Debug Module
This file implements a map that provides insertion order iteration.
static bool mustBeUnreachableFunction(const Function &F)
This is the interface to build a ModuleSummaryIndex for a module.
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
This file contains the declarations for profiling metadata utility functions.
const SmallVectorImpl< MachineOperand > & Cond
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
WPDCheckMode
Mechanism to add runtime checking of devirtualization decisions, optionally trapping or falling back ...
static bool typeIDVisibleToRegularObj(StringRef TypeID, function_ref< bool(StringRef)> IsVisibleToRegularObj)
static Error checkCombinedSummaryForTesting(ModuleSummaryIndex *Summary)
static bool addCalls(VTableSlotInfo &SlotInfo, const ValueInfo &Callee)
static cl::opt< WPDCheckMode > DevirtCheckMode("wholeprogramdevirt-check", cl::Hidden, cl::desc("Type of checking for incorrect devirtualizations"), cl::values(clEnumValN(WPDCheckMode::None, "none", "No checking"), clEnumValN(WPDCheckMode::Trap, "trap", "Trap when incorrect"), clEnumValN(WPDCheckMode::Fallback, "fallback", "Fallback to indirect when incorrect")))
static cl::opt< bool > WholeProgramDevirtKeepUnreachableFunction("wholeprogramdevirt-keep-unreachable-function", cl::desc("Regard unreachable functions as possible devirtualize targets."), cl::Hidden, cl::init(true))
With Clang, a pure virtual class's deleting destructor is emitted as a llvm.trap intrinsic followed b...
static bool skipUpdateDueToValidation(GlobalVariable &GV, function_ref< bool(StringRef)> IsVisibleToRegularObj)
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
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.
static LLVM_ABI AttributeSet get(LLVMContext &C, const AttrBuilder &B)
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
bool isValid() const
Return true if the attribute is any kind of attribute.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
void setCallingConv(CallingConv::ID CC)
std::optional< OperandBundleUse > getOperandBundle(StringRef Name) const
Return an operand bundle by name, if present.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
CallingConv::ID getCallingConv() const
Value * getCalledOperand() const
void setAttributes(AttributeList A)
Set the attributes for this call.
FunctionType * getFunctionType() const
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
void setCalledOperand(Value *V)
static LLVM_ABI CallBase * removeOperandBundle(CallBase *CB, uint32_t ID, InsertPosition InsertPt=nullptr)
Create a clone of CB with operand bundle ID removed.
AttributeList getAttributes() const
Return the attributes for this call.
LLVM_ABI Function * getCaller()
Helper to get the caller (the parent function).
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
void setSelectionKind(SelectionKind Val)
static Constant * get(LLVMContext &Context, ArrayRef< ElementTy > Elts)
get() constructor - Return a constant with array type with an element count and element type matching...
static LLVM_ABI Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static Constant * getInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef< Constant * > IdxList)
Create an "inbounds" getelementptr.
static Constant * getPtrAdd(Constant *Ptr, Constant *Offset, GEPNoWrapFlags NW=GEPNoWrapFlags::none(), std::optional< ConstantRange > InRange=std::nullopt, Type *OnlyIfReduced=nullptr)
Create a getelementptr i8, ptr, offset constant expression.
static LLVM_ABI Constant * getPtrToInt(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
static ConstantInt * getSigned(IntegerType *Ty, int64_t V, bool ImplicitTrunc=false)
Return a ConstantInt with the specified value for the specified type.
static Constant * getAnon(ArrayRef< Constant * > V, bool Packed=false)
Return an anonymous struct that has the specified elements.
const Constant * stripPointerCasts() const
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
static bool shouldExecute(CounterInfo &Counter)
Implements a dense probed hash-table based set.
Subclass of Error for the sole purpose of identifying the success path in the type system.
Lightweight error class with error context and mandatory checking.
Tagged union holding either a T or a Error.
Type * getParamType(unsigned i) const
Parameter type accessors.
ArrayRef< Type * > params() const
Type * getReturnType() const
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
FunctionType * getFunctionType() const
Returns the FunctionType for me.
const BasicBlock & front() const
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
adds the attribute to the list of attributes for the given arg.
std::optional< ProfileCount > getEntryCount(bool AllowSynthetic=false) const
Get the entry count for this function.
Type * getReturnType() const
Returns the type of the ret val.
unsigned getInstructionCount() const
Returns the number of non-debug IR instructions in this function.
static LLVM_ABI Expected< GlobPattern > create(StringRef Pat, std::optional< size_t > MaxSubPatterns={})
static LLVM_ABI GlobalAlias * create(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, Constant *Aliasee, Module *Parent)
If a parent module is specified, the alias is automatically inserted into the end of the specified mo...
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set a particular kind of metadata attachment.
bool hasMetadata() const
Return true if this GlobalObject has any metadata attached to it.
LLVM_ABI VCallVisibility getVCallVisibility() const
LLVM_ABI bool eraseMetadata(unsigned KindID)
Erase all metadata attachments with the given kind.
@ VCallVisibilityLinkageUnit
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this GlobalObject.
LLVM_ABI void setVCallVisibilityMetadata(VCallVisibility Visibility)
static LLVM_ABI GUID getGUIDAssumingExternalLinkage(StringRef GlobalName)
Return a 64-bit global unique ID constructed from the name of a global symbol.
static bool isLocalLinkage(LinkageTypes Linkage)
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
static bool isAvailableExternallyLinkage(LinkageTypes Linkage)
GUID getGUID() const
Return a 64-bit global unique ID constructed from global value name (i.e.
@ HiddenVisibility
The GV is hidden.
void setVisibility(VisibilityTypes V)
@ PrivateLinkage
Like Internal, but omit from symbol table.
@ InternalLinkage
Rename collisions when linking (static functions).
@ ExternalLinkage
Externally visible function.
Type * getValueType() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
MaybeAlign getAlign() const
Returns the alignment of the given variable.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
uint64_t getBitMask() const
Return a bitmask with ones set for all of the bits that can be set by an unsigned version of this typ...
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
bool doesNotAccessMemory() const
Whether this function accesses no memory.
Class to hold module path string table and global value map, and encapsulate methods for operating on...
const TypeIdSummary * getTypeIdSummary(StringRef TypeId) const
This returns either a pointer to the type id summary (if present in the summary map) or null (if not ...
ValueInfo getValueInfo(const GlobalValueSummaryMapTy::value_type &R) const
Return a ValueInfo for the index value_type (convenient when iterating index).
const ModuleHash & getModuleHash(const StringRef ModPath) const
Get the module SHA1 hash recorded for the given module path.
static constexpr const char * getRegularLTOModuleName()
bool partiallySplitLTOUnits() const
static std::string getGlobalNameForLocal(StringRef Name, ModuleHash ModHash)
Convenience method for creating a promoted global name for the given value name of a local,...
A Module instance is used to store all the information related to an LLVM module.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
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.
Analysis providing profile information.
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, InsertPosition InsertBefore=nullptr)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
bool contains(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
Target - Wrapper for Target specific information.
The TimeTraceScope is a helper class to call the begin and end functions of the time trace profiler.
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
bool isVoidTy() const
Return true if this is 'void'.
static UncondBrInst * Create(BasicBlock *Target, InsertPosition InsertBefore=nullptr)
A Use represents the edge between a Value definition and its users.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVM_ABI bool eraseMetadata(unsigned KindID)
Erase all metadata attachments with the given kind.
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
LLVM_ABI Function * getDeclarationIfExists(const Module *M, ID id)
Look up the Function declaration of the intrinsic id in the Module M and return it if it exists.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
bool match(Val *V, const Pattern &P)
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
DXILDebugInfoMap run(Module &M)
DiagnosticInfoOptimizationBase::Argument NV
Context & getContext() const
friend class Instruction
Iterator for Instructions in a `BasicBlock.
@ OF_TextWithCRLF
The file should be opened in text mode and use a carriage linefeed '\r '.
LLVM_ABI uint64_t findLowestOffset(ArrayRef< VirtualCallTarget > Targets, bool IsAfter, uint64_t Size)
LLVM_ABI void setAfterReturnValues(MutableArrayRef< VirtualCallTarget > Targets, uint64_t AllocAfter, unsigned BitWidth, int64_t &OffsetByte, uint64_t &OffsetBit)
LLVM_ABI void setBeforeReturnValues(MutableArrayRef< VirtualCallTarget > Targets, uint64_t AllocBefore, unsigned BitWidth, int64_t &OffsetByte, uint64_t &OffsetBit)
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.
FunctionAddr VTableAddr Value
cl::opt< bool > ProfcheckDisableMetadataFixes
LLVM_ABI void runWholeProgramDevirtOnIndex(ModuleSummaryIndex &Summary, std::set< GlobalValue::GUID > &ExportedGUIDs, std::map< ValueInfo, std::vector< VTableSlotSummary > > &LocalWPDTargetsMap, DenseSet< StringRef > *ExternallyVisibleSymbolNamesPtr=nullptr)
Perform index-based whole program devirtualization on the Summary index.
LLVM_ABI MemoryEffects computeFunctionBodyMemoryAccess(Function &F, AAResults &AAR)
Returns the memory access properties of this copy of the function.
static cl::opt< bool > DisableWholeProgramVisibility("disable-whole-program-visibility", cl::Hidden, cl::desc("Disable whole program visibility (overrides enabling options)"))
Provide a way to force disable whole program for debugging or workarounds, when enabled via the linke...
static cl::opt< bool > WholeProgramVisibility("whole-program-visibility", cl::Hidden, cl::desc("Enable whole program visibility"))
Provide a way to force enable whole program visibility in tests.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
static cl::opt< unsigned > ClThreshold("wholeprogramdevirt-branch-funnel-threshold", cl::Hidden, cl::init(10), cl::desc("Maximum number of call targets per " "call site to enable branch funnels"))
@ Export
Export information to summary.
@ Import
Import information from summary.
static cl::opt< std::string > ClReadSummary("wholeprogramdevirt-read-summary", cl::desc("Read summary from given bitcode or YAML file before running pass"), cl::Hidden)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
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...
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
LLVM_ABI ModuleSummaryIndex buildModuleSummaryIndex(const Module &M, std::function< BlockFrequencyInfo *(const Function &F)> GetBFICallback, ProfileSummaryInfo *PSI, std::function< const StackSafetyInfo *(const Function &F)> GetSSICallback=[](const Function &F) -> const StackSafetyInfo *{ return nullptr;})
Direct function to compute a ModuleSummaryIndex from a given module.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
LLVM_ABI bool hasWholeProgramVisibility(bool WholeProgramVisibilityEnabledInLTO)
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
LLVM_ABI void writeIndexToFile(const ModuleSummaryIndex &Index, raw_ostream &Out, const ModuleToSummariesForIndexTy *ModuleToSummariesForIndex=nullptr, const GVSummaryPtrSet *DecSummaries=nullptr)
Write the specified module summary index to the given raw output stream, where it will be written in ...
LLVM_ABI Expected< std::unique_ptr< ModuleSummaryIndex > > getModuleSummaryIndex(MemoryBufferRef Buffer)
Parse the specified bitcode buffer, returning the module summary index.
LLVM_ABI void updateIndexWPDForExports(ModuleSummaryIndex &Summary, function_ref< bool(StringRef, ValueInfo)> isExported, std::map< ValueInfo, std::vector< VTableSlotSummary > > &LocalWPDTargetsMap, DenseSet< StringRef > *ExternallyVisibleSymbolNamesPtr=nullptr)
Call after cross-module importing to update the recorded single impl devirt target names for any loca...
static cl::opt< std::string > ClWriteSummary("wholeprogramdevirt-write-summary", cl::desc("Write summary to given bitcode or YAML file after running pass. " "Output file format is deduced from extension: *.bc means writing " "bitcode, otherwise YAML"), cl::Hidden)
LLVM_ABI void updatePublicTypeTestCalls(Module &M, bool WholeProgramVisibilityEnabledInLTO)
LLVM_ABI void getVisibleToRegularObjVtableGUIDs(ModuleSummaryIndex &Index, DenseSet< GlobalValue::GUID > &VisibleToRegularObjSymbols, function_ref< bool(StringRef)> IsVisibleToRegularObj)
Based on typeID string, get all associated vtable GUIDS that are visible to regular objects.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
LLVM_ABI void findDevirtualizableCallsForTypeCheckedLoad(SmallVectorImpl< DevirtCallSite > &DevirtCalls, SmallVectorImpl< Instruction * > &LoadedPtrs, SmallVectorImpl< Instruction * > &Preds, bool &HasNonCallUses, const CallInst *CI, DominatorTree &DT)
Given a call to the intrinsic @llvm.type.checked.load, find all devirtualizable call sites based on t...
LLVM_ABI CallBase & versionCallSite(CallBase &CB, Value *Callee, MDNode *BranchWeights)
Predicate and clone the given call site.
LLVM_ABI bool AreStatisticsEnabled()
Check if statistics are enabled.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI void setExplicitlyUnknownFunctionEntryCount(Function &F, StringRef PassName)
Analogous to setExplicitlyUnknownBranchWeights, but for functions and their entry counts.
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
static cl::list< std::string > SkipFunctionNames("wholeprogramdevirt-skip", cl::desc("Prevent function(s) from being devirtualized"), cl::Hidden, cl::CommaSeparated)
Provide way to prevent certain function from being devirtualized.
static cl::opt< PassSummaryAction > ClSummaryAction("wholeprogramdevirt-summary-action", cl::desc("What to do with the summary when running this pass"), cl::values(clEnumValN(PassSummaryAction::None, "none", "Do nothing"), clEnumValN(PassSummaryAction::Import, "import", "Import typeid resolutions from summary and globals"), clEnumValN(PassSummaryAction::Export, "export", "Export typeid resolutions to summary and globals")), cl::Hidden)
Expected< T > errorOrToExpected(ErrorOr< T > &&EO)
Convert an ErrorOr<T> to an Expected<T>.
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
static cl::opt< bool > ClDevirtualizeSpeculatively("devirtualize-speculatively", cl::desc("Enable speculative devirtualization optimization"), cl::init(false))
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
std::vector< TypeIdOffsetVtableInfo > TypeIdCompatibleVtableInfo
List of vtable definitions decorated by a particular type identifier, and their corresponding offsets...
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
static cl::opt< bool > PrintSummaryDevirt("wholeprogramdevirt-print-index-based", cl::Hidden, cl::desc("Print index-based devirtualization messages"))
void consumeError(Error Err)
Consume a Error without doing anything.
LLVM_ABI 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 ...
LLVM_ABI void updateVCallVisibilityInModule(Module &M, bool WholeProgramVisibilityEnabledInLTO, const DenseSet< GlobalValue::GUID > &DynamicExportSymbols, bool ValidateAllVtablesHaveTypeInfos, function_ref< bool(StringRef)> IsVisibleToRegularObj)
If whole program visibility asserted, then upgrade all public vcall visibility metadata on vtable def...
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
LLVM_ABI 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 ...
LLVM_ABI void updateVCallVisibilityInIndex(ModuleSummaryIndex &Index, bool WholeProgramVisibilityEnabledInLTO, const DenseSet< GlobalValue::GUID > &DynamicExportSymbols, const DenseSet< GlobalValue::GUID > &VisibleToRegularObjSymbols)
If whole program visibility asserted, then upgrade all public vcall visibility metadata on vtable def...
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Class to accumulate and hold information about a callee.
static unsigned getHashValue(const VTableSlotSummary &I)
static bool isEqual(const VTableSlotSummary &LHS, const VTableSlotSummary &RHS)
static bool isEqual(const VTableSlot &LHS, const VTableSlot &RHS)
static unsigned getHashValue(const VTableSlot &I)
An information struct used to provide DenseMap with the various necessary components for a given valu...
The following data structures summarize type metadata information.
std::map< uint64_t, WholeProgramDevirtResolution > WPDRes
Mapping from byte offset to whole-program devirt resolution for that (typeid, byte offset) pair.
@ Unsat
Unsatisfiable type (i.e. no global has this type metadata)
enum llvm::TypeTestResolution::Kind TheKind
Struct that holds a reference to a particular GUID in a global value summary.
ArrayRef< std::unique_ptr< GlobalValueSummary > > getSummaryList() const
const ModuleSummaryIndex * ImportSummary
ModuleSummaryIndex * ExportSummary
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
@ UniformRetVal
Uniform return value optimization.
@ VirtualConstProp
Virtual constant propagation.
@ UniqueRetVal
Unique return value optimization.
uint64_t Info
Additional information for the resolution:
enum llvm::WholeProgramDevirtResolution::ByArg::Kind TheKind
enum llvm::WholeProgramDevirtResolution::Kind TheKind
std::map< std::vector< uint64_t >, ByArg > ResByArg
Resolutions for calls with all constant integer arguments (excluding the first argument,...
std::string SingleImplName
@ SingleImpl
Single implementation devirtualization.
@ BranchFunnel
When retpoline mitigation is enabled, use a branch funnel that is defined in the merged module.
LLVM_ABI VirtualCallTarget(GlobalValue *Fn, const TypeMemberInfo *TM)
const TypeMemberInfo * TM