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);
395 const VTableSlot &RHS) {
396 return LHS.TypeID == RHS.TypeID && LHS.ByteOffset == RHS.ByteOffset;
411 return LHS.TypeID == RHS.TypeID && LHS.ByteOffset == RHS.ByteOffset;
435 if (!Summary->isLive())
438 if (!FS->fflags().MustBeUnreachable)
453struct VirtualCallSite {
460 unsigned *NumUnsafeUses =
nullptr;
463 emitRemark(
const StringRef OptName,
const StringRef TargetName,
464 function_ref<OptimizationRemarkEmitter &(Function &)> OREGetter) {
470 OREGetter(*F).emit(OptimizationRemark(
DEBUG_TYPE, OptName, DLoc,
Block)
471 <<
NV(
"Optimization", OptName)
472 <<
": devirtualized a call to "
473 <<
NV(
"FunctionName", TargetName));
476 void replaceAndErase(
477 const StringRef OptName,
const StringRef TargetName,
bool RemarksEnabled,
478 function_ref<OptimizationRemarkEmitter &(Function &)> OREGetter,
485 II->getUnwindDest()->removePredecessor(
II->getParent());
502 std::vector<VirtualCallSite> CallSites;
511 bool AllCallSitesDevirted =
true;
520 std::vector<FunctionSummary *> SummaryTypeCheckedLoadUsers;
524 std::vector<FunctionSummary *> SummaryTypeTestAssumeUsers;
526 bool isExported()
const {
527 return !SummaryTypeCheckedLoadUsers.empty() ||
528 !SummaryTypeTestAssumeUsers.empty();
531 void addSummaryTypeCheckedLoadUser(FunctionSummary *FS) {
532 SummaryTypeCheckedLoadUsers.push_back(FS);
533 AllCallSitesDevirted =
false;
536 void addSummaryTypeTestAssumeUser(FunctionSummary *FS) {
537 SummaryTypeTestAssumeUsers.push_back(FS);
538 AllCallSitesDevirted =
false;
541 void markDevirt() { AllCallSitesDevirted =
true; }
545struct VTableSlotInfo {
552 std::map<std::vector<uint64_t>,
CallSiteInfo> ConstCSInfo;
554 void addCallSite(
Value *VTable, CallBase &CB,
unsigned *NumUnsafeUses);
560CallSiteInfo &VTableSlotInfo::findCallSiteInfo(CallBase &CB) {
561 std::vector<uint64_t>
Args;
563 if (!CBType || CBType->getBitWidth() > 64 || CB.
arg_empty())
567 if (!CI || CI->getBitWidth() > 64)
569 Args.push_back(CI->getZExtValue());
571 return ConstCSInfo[
Args];
574void VTableSlotInfo::addCallSite(
Value *VTable, CallBase &CB,
575 unsigned *NumUnsafeUses) {
576 auto &CSI = findCallSiteInfo(CB);
577 CSI.AllCallSitesDevirted =
false;
578 CSI.CallSites.push_back({
VTable, CB, NumUnsafeUses});
586 ModuleSummaryIndex *
const ExportSummary;
587 const ModuleSummaryIndex *
const ImportSummary;
589 IntegerType *
const Int8Ty;
592 IntegerType *
const Int64Ty;
593 IntegerType *
const IntPtrTy;
599 const bool RemarksEnabled;
600 std::function<OptimizationRemarkEmitter &(
Function &)> OREGetter;
601 MapVector<VTableSlot, VTableSlotInfo> CallSlots;
606 SmallPtrSet<CallBase *, 8> OptimizedCalls;
620 std::map<CallInst *, unsigned> NumUnsafeUsesForTypeTest;
621 PatternList FunctionsToSkip;
623 const bool DevirtSpeculatively;
625 ModuleSummaryIndex *ExportSummary,
626 const ModuleSummaryIndex *ImportSummary,
627 bool DevirtSpeculatively)
630 ExportSummary(ExportSummary), ImportSummary(ImportSummary),
635 IntPtrTy(
M.getDataLayout().getIntPtrType(
M.
getContext(), 0)),
637 RemarksEnabled(areRemarksEnabled()),
638 OREGetter([&](
Function &
F) -> OptimizationRemarkEmitter & {
641 DevirtSpeculatively(DevirtSpeculatively) {
642 assert(!(ExportSummary && ImportSummary));
646 bool areRemarksEnabled();
649 scanTypeTestUsers(Function *TypeTestFunc,
650 DenseMap<
Metadata *, std::set<TypeMemberInfo>> &TypeIdMap);
651 void scanTypeCheckedLoadUsers(Function *TypeCheckedLoadFunc);
653 void buildTypeIdentifierMap(
654 std::vector<VTableBits> &Bits,
655 DenseMap<
Metadata *, std::set<TypeMemberInfo>> &TypeIdMap);
658 tryFindVirtualCallTargets(std::vector<VirtualCallTarget> &TargetsForSlot,
659 const std::set<TypeMemberInfo> &TypeMemberInfos,
661 ModuleSummaryIndex *ExportSummary);
663 void applySingleImplDevirt(VTableSlotInfo &SlotInfo, Constant *TheFn,
665 bool trySingleImplDevirt(ModuleSummaryIndex *ExportSummary,
667 VTableSlotInfo &SlotInfo,
668 WholeProgramDevirtResolution *Res);
670 void applyICallBranchFunnel(VTableSlotInfo &SlotInfo, Function &JT,
673 VTableSlotInfo &SlotInfo,
674 WholeProgramDevirtResolution *Res, VTableSlot Slot);
676 bool tryEvaluateFunctionsWithArgs(
678 ArrayRef<uint64_t> Args);
680 void applyUniformRetValOpt(
CallSiteInfo &CSInfo, StringRef FnName,
684 WholeProgramDevirtResolution::ByArg *Res);
688 std::string getGlobalName(VTableSlot Slot, ArrayRef<uint64_t> Args,
691 bool shouldExportConstantsAsAbsoluteSymbols();
696 void exportGlobal(VTableSlot Slot, ArrayRef<uint64_t> Args, StringRef Name,
698 void exportConstant(VTableSlot Slot, ArrayRef<uint64_t> Args, StringRef Name,
699 uint32_t Const, uint32_t &Storage);
703 Constant *importGlobal(VTableSlot Slot, ArrayRef<uint64_t> Args,
705 Constant *importConstant(VTableSlot Slot, ArrayRef<uint64_t> Args,
706 StringRef Name, IntegerType *IntTy,
709 Constant *getMemberAddr(
const TypeMemberInfo *M);
711 void applyUniqueRetValOpt(
CallSiteInfo &CSInfo, StringRef FnName,
bool IsOne,
712 Constant *UniqueMemberAddr);
713 bool tryUniqueRetValOpt(
unsigned BitWidth,
716 WholeProgramDevirtResolution::ByArg *Res,
717 VTableSlot Slot, ArrayRef<uint64_t> Args);
719 void applyVirtualConstProp(
CallSiteInfo &CSInfo, StringRef FnName,
720 Constant *Byte, Constant *Bit);
722 VTableSlotInfo &SlotInfo,
723 WholeProgramDevirtResolution *Res, VTableSlot Slot);
725 void rebuildGlobal(VTableBits &
B);
728 void importResolution(VTableSlot Slot, VTableSlotInfo &SlotInfo);
732 void removeRedundantTypeTests();
739 static ValueInfo lookUpFunctionValueInfo(Function *TheFn,
740 ModuleSummaryIndex *ExportSummary);
751 ModuleSummaryIndex *ExportSummary);
756 bool DevirtSpeculatively);
760 ModuleSummaryIndex &ExportSummary;
763 std::set<GlobalValue::GUID> &ExportedGUIDs;
767 std::map<ValueInfo, std::vector<VTableSlotSummary>> &LocalWPDTargetsMap;
772 DenseSet<StringRef> *ExternallyVisibleSymbolNamesPtr;
774 MapVector<VTableSlotSummary, VTableSlotInfo> CallSlots;
776 PatternList FunctionsToSkip;
779 ModuleSummaryIndex &ExportSummary,
780 std::set<GlobalValue::GUID> &ExportedGUIDs,
781 std::map<ValueInfo, std::vector<VTableSlotSummary>> &LocalWPDTargetsMap,
782 DenseSet<StringRef> *ExternallyVisibleSymbolNamesPtr)
783 : ExportSummary(ExportSummary), ExportedGUIDs(ExportedGUIDs),
784 LocalWPDTargetsMap(LocalWPDTargetsMap),
785 ExternallyVisibleSymbolNamesPtr(ExternallyVisibleSymbolNamesPtr) {
789 bool tryFindVirtualCallTargets(std::vector<ValueInfo> &TargetsForSlot,
791 uint64_t ByteOffset);
794 VTableSlotSummary &SlotSummary,
795 VTableSlotInfo &SlotInfo,
796 WholeProgramDevirtResolution *Res,
797 std::set<ValueInfo> &DevirtTargets);
811 std::optional<ModuleSummaryIndex> Index;
815 "ExportSummary is expected to be empty in non-LTO mode");
818 ExportSummary = Index.has_value() ? &Index.value() :
nullptr;
839 if (
TypeID.ends_with(
".virtual"))
845 if (!
TypeID.consume_front(
"_ZTS"))
853 std::string TypeInfo = (
"_ZTI" +
TypeID).str();
854 return IsVisibleToRegularObj(TypeInfo);
863 for (
auto *
Type : Types)
866 IsVisibleToRegularObj);
875 Module &M,
bool WholeProgramVisibilityEnabledInLTO,
877 bool ValidateAllVtablesHaveTypeInfos,
895 !(ValidateAllVtablesHaveTypeInfos &&
902 bool WholeProgramVisibilityEnabledInLTO) {
906 if (!PublicTypeTestFunc)
914 TypeTestFunc, {CI->getArgOperand(0), CI->getArgOperand(1)}, {},
"",
916 CI->replaceAllUsesWith(NewCI);
917 CI->eraseFromParent();
925 CI->replaceAllUsesWith(True);
926 CI->eraseFromParent();
937 for (
const auto &TypeID : Index.typeIdCompatibleVtableMap()) {
940 VisibleToRegularObjSymbols.
insert(
P.VTableVI.getGUID());
953 for (
auto &
P : Index) {
956 if (DynamicExportSymbols.
count(
P.first))
962 if (VisibleToRegularObjSymbols.
count(
P.first))
964 for (
auto &S :
P.second.getSummaryList()) {
976 std::map<
ValueInfo, std::vector<VTableSlotSummary>> &LocalWPDTargetsMap,
978 DevirtIndex(Summary, ExportedGUIDs, LocalWPDTargetsMap,
979 ExternallyVisibleSymbolNamesPtr)
986 std::map<
ValueInfo, std::vector<VTableSlotSummary>> &LocalWPDTargetsMap,
988 for (
auto &
T : LocalWPDTargetsMap) {
991 assert(VI.getSummaryList().size() == 1 &&
992 "Devirt of local target has more than one copy");
993 auto &S = VI.getSummaryList()[0];
994 if (!IsExported(S->modulePath(), VI))
998 for (
auto &SlotSummary :
T.second) {
999 auto *TIdSum = Summary.getTypeIdSummary(SlotSummary.TypeID);
1001 auto WPDRes = TIdSum->WPDRes.find(SlotSummary.ByteOffset);
1002 assert(WPDRes != TIdSum->WPDRes.end());
1003 if (ExternallyVisibleSymbolNamesPtr)
1004 ExternallyVisibleSymbolNamesPtr->
insert(WPDRes->second.SingleImplName);
1006 WPDRes->second.SingleImplName,
1007 Summary.getModuleHash(S->modulePath()));
1017 const auto &ModPaths = Summary->modulePaths();
1022 "combined summary should contain Regular LTO module");
1027 bool DevirtSpeculatively) {
1028 std::unique_ptr<ModuleSummaryIndex>
Summary =
1029 std::make_unique<ModuleSummaryIndex>(
false);
1034 ExitOnError ExitOnErr(
"-wholeprogramdevirt-read-summary: " +
ClReadSummary +
1036 auto ReadSummaryFile =
1038 if (Expected<std::unique_ptr<ModuleSummaryIndex>> SummaryOrErr =
1040 Summary = std::move(*SummaryOrErr);
1045 yaml::Input
In(ReadSummaryFile->getBuffer());
1052 DevirtModule(M,
MAM,
1057 DevirtSpeculatively)
1061 ExitOnError ExitOnErr(
1071 yaml::Output Out(OS);
1079void DevirtModule::buildTypeIdentifierMap(
1080 std::vector<VTableBits> &Bits,
1081 DenseMap<
Metadata *, std::set<TypeMemberInfo>> &TypeIdMap) {
1082 DenseMap<GlobalVariable *, VTableBits *> GVToBits;
1083 Bits.reserve(
M.global_size());
1085 for (GlobalVariable &GV :
M.globals()) {
1093 Bits.emplace_back();
1094 Bits.back().GV = &GV;
1095 Bits.back().ObjectSize =
1097 BitsPtr = &
Bits.back();
1100 for (MDNode *
Type : Types) {
1113bool DevirtModule::tryFindVirtualCallTargets(
1114 std::vector<VirtualCallTarget> &TargetsForSlot,
1115 const std::set<TypeMemberInfo> &TypeMemberInfos, uint64_t ByteOffset,
1116 ModuleSummaryIndex *ExportSummary) {
1118 if (!TM.Bits->GV->isConstant())
1123 if (!DevirtSpeculatively && TM.Bits->GV->getVCallVisibility() ==
1135 if (FunctionsToSkip.match(Fn->
getName()))
1140 if (Fn->
getName() ==
"__cxa_pure_virtual")
1158 TargetsForSlot.push_back({GV, &TM});
1162 return !TargetsForSlot.empty();
1165bool DevirtIndex::tryFindVirtualCallTargets(
1166 std::vector<ValueInfo> &TargetsForSlot,
1168 for (
const TypeIdOffsetVtableInfo &
P : TIdInfo) {
1179 if (
P.VTableVI.hasLocal() &&
P.VTableVI.getSummaryList().size() > 1)
1181 const GlobalVarSummary *
VS =
nullptr;
1182 for (
const auto &S :
P.VTableVI.getSummaryList()) {
1184 if (!CurVS->vTableFuncs().empty() ||
1207 for (
auto VTP :
VS->vTableFuncs()) {
1208 if (VTP.VTableOffset !=
P.AddressPointOffset + ByteOffset)
1214 TargetsForSlot.push_back(VTP.FuncVI);
1219 return !TargetsForSlot.empty();
1222void DevirtModule::applySingleImplDevirt(VTableSlotInfo &SlotInfo,
1223 Constant *TheFn,
bool &IsExported) {
1229 for (
auto &&VCallSite : CSInfo.CallSites) {
1230 if (!OptimizedCalls.
insert(&VCallSite.CB).second)
1238 VCallSite.emitRemark(
"single-impl",
1241 auto &CB = VCallSite.CB;
1254 MDBuilder(
M.getContext()).createUnlikelyBranchWeights());
1255 Builder.SetInsertPoint(ThenTerm);
1258 auto *CallTrap = Builder.CreateCall(TrapFn);
1267 MDNode *Weights = MDBuilder(
M.getContext()).createLikelyBranchWeights();
1276 NewInst.
setMetadata(LLVMContext::MD_prof,
nullptr);
1277 NewInst.
setMetadata(LLVMContext::MD_callees,
nullptr);
1299 CallsWithPtrAuthBundleRemoved.
push_back(&CB);
1304 if (VCallSite.NumUnsafeUses)
1305 --*VCallSite.NumUnsafeUses;
1307 if (CSInfo.isExported())
1309 CSInfo.markDevirt();
1311 Apply(SlotInfo.CSInfo);
1312 for (
auto &
P : SlotInfo.ConstCSInfo)
1318 if (Callee.getSummaryList().empty())
1325 bool IsExported =
false;
1326 auto &S = Callee.getSummaryList()[0];
1328 auto AddCalls = [&](CallSiteInfo &CSInfo) {
1329 for (
auto *FS : CSInfo.SummaryTypeCheckedLoadUsers) {
1330 FS->addCall({Callee, CI});
1331 IsExported |= S->modulePath() != FS->modulePath();
1333 for (
auto *FS : CSInfo.SummaryTypeTestAssumeUsers) {
1334 FS->addCall({Callee, CI});
1335 IsExported |= S->modulePath() != FS->modulePath();
1338 AddCalls(SlotInfo.CSInfo);
1339 for (
auto &
P : SlotInfo.ConstCSInfo)
1344bool DevirtModule::trySingleImplDevirt(
1345 ModuleSummaryIndex *ExportSummary,
1347 WholeProgramDevirtResolution *Res) {
1350 auto *TheFn = TargetsForSlot[0].Fn;
1351 for (
auto &&Target : TargetsForSlot)
1357 TargetsForSlot[0].WasDevirt =
true;
1359 bool IsExported =
false;
1360 applySingleImplDevirt(SlotInfo, TheFn, IsExported);
1367 if (TheFn->hasLocalLinkage()) {
1368 std::string NewName = (TheFn->
getName() +
".llvm.merged").str();
1373 if (Comdat *
C = TheFn->getComdat()) {
1374 if (
C->getName() == TheFn->
getName()) {
1375 Comdat *NewC =
M.getOrInsertComdat(NewName);
1377 for (GlobalObject &GO :
M.global_objects())
1378 if (GO.getComdat() ==
C)
1387 if (ValueInfo TheFnVI = ExportSummary->
getValueInfo(TheFn->getGUID()))
1399 VTableSlotSummary &SlotSummary,
1400 VTableSlotInfo &SlotInfo,
1401 WholeProgramDevirtResolution *Res,
1402 std::set<ValueInfo> &DevirtTargets) {
1405 auto TheFn = TargetsForSlot[0];
1406 for (
auto &&Target : TargetsForSlot)
1407 if (TheFn != Target)
1411 auto Size = TheFn.getSummaryList().size();
1417 if (FunctionsToSkip.match(TheFn.name()))
1422 if (TheFn.hasLocal() &&
Size > 1)
1427 DevirtTargets.insert(TheFn);
1429 auto &S = TheFn.getSummaryList()[0];
1430 bool IsExported =
addCalls(SlotInfo, TheFn);
1432 ExportedGUIDs.insert(TheFn.getGUID());
1442 if (ExternallyVisibleSymbolNamesPtr)
1443 ExternallyVisibleSymbolNamesPtr->insert(TheFn.name());
1445 TheFn.name(), ExportSummary.
getModuleHash(S->modulePath()));
1447 LocalWPDTargetsMap[TheFn].push_back(SlotSummary);
1461void DevirtModule::tryICallBranchFunnel(
1463 WholeProgramDevirtResolution *Res, VTableSlot Slot) {
1464 Triple
T(
M.getTargetTriple());
1471 bool HasNonDevirt = !SlotInfo.CSInfo.AllCallSitesDevirted;
1473 for (
auto &
P : SlotInfo.ConstCSInfo)
1474 if (!
P.second.AllCallSitesDevirted) {
1475 HasNonDevirt =
true;
1493 for (
auto &
T : TargetsForSlot) {
1494 if (
T.TM->Bits->GV->hasAvailableExternallyLinkage())
1503 M.getDataLayout().getProgramAddressSpace(),
1504 getGlobalName(Slot, {},
"branch_funnel"), &
M);
1508 M.getDataLayout().getProgramAddressSpace(),
1509 "branch_funnel", &M);
1513 std::vector<Value *> JTArgs;
1515 for (
auto &
T : TargetsForSlot) {
1516 JTArgs.push_back(getMemberAddr(
T.TM));
1517 JTArgs.push_back(
T.Fn);
1522 &M, llvm::Intrinsic::icall_branch_funnel, {});
1528 bool IsExported =
false;
1529 applyICallBranchFunnel(SlotInfo, *JT, IsExported);
1539void DevirtModule::applyICallBranchFunnel(VTableSlotInfo &SlotInfo,
1540 Function &JT,
bool &IsExported) {
1541 DenseMap<Function *, double> FunctionEntryCounts;
1543 if (CSInfo.isExported())
1545 if (CSInfo.AllCallSitesDevirted)
1548 std::map<CallBase *, CallBase *> CallBases;
1549 for (
auto &&VCallSite : CSInfo.CallSites) {
1550 CallBase &CB = VCallSite.CB;
1552 if (CallBases.find(&CB) != CallBases.end()) {
1569 VCallSite.emitRemark(
"branch-funnel", JT.
getName(), OREGetter);
1573 std::vector<Type *> NewArgs;
1574 NewArgs.push_back(Int8PtrTy);
1576 FunctionType *NewFT =
1580 std::vector<Value *>
Args;
1581 Args.push_back(VCallSite.VTable);
1584 CallBase *NewCS =
nullptr;
1590 auto EC = BFI.getBlockFreq(&
F.getEntryBlock());
1591 auto CC =
F.getEntryCount(
true);
1592 double CallCount = 0.0;
1593 if (
EC.getFrequency() != 0 && CC && CC->getCount() != 0) {
1595 static_cast<double>(
1596 BFI.getBlockFreq(CB.
getParent()).getFrequency()) /
1598 CallCount = CallFreq * CC->getCount();
1600 FunctionEntryCounts[&JT] += CallCount;
1603 NewCS = IRB.CreateCall(NewFT, &JT, Args);
1611 std::vector<AttributeSet> NewArgAttrs;
1614 M.getContext(), Attribute::Nest)}));
1615 for (
unsigned I = 0;
I + 2 <
Attrs.getNumAttrSets(); ++
I)
1616 NewArgAttrs.push_back(
Attrs.getParamAttrs(
I));
1618 AttributeList::get(
M.getContext(),
Attrs.getFnAttrs(),
1619 Attrs.getRetAttrs(), NewArgAttrs));
1621 CallBases[&CB] = NewCS;
1624 if (VCallSite.NumUnsafeUses)
1625 --*VCallSite.NumUnsafeUses;
1632 for (
auto &[Old, New] : CallBases) {
1633 Old->replaceAllUsesWith(New);
1634 Old->eraseFromParent();
1637 Apply(SlotInfo.CSInfo);
1638 for (
auto &
P : SlotInfo.ConstCSInfo)
1640 for (
auto &[
F,
C] : FunctionEntryCounts) {
1641 assert(!
F->getEntryCount(
true) &&
1642 "Unexpected entry count for funnel that was freshly synthesized");
1643 F->setEntryCount(
static_cast<uint64_t
>(std::round(
C)));
1647bool DevirtModule::tryEvaluateFunctionsWithArgs(
1649 ArrayRef<uint64_t> Args) {
1663 Evaluator Eval(
M.getDataLayout(),
nullptr);
1667 for (
unsigned I = 0;
I !=
Args.size(); ++
I) {
1672 EvalArgs.
push_back(ConstantInt::get(ArgTy, Args[
I]));
1676 if (!Eval.EvaluateFunction(Fn, RetVal, EvalArgs) ||
1684void DevirtModule::applyUniformRetValOpt(
CallSiteInfo &CSInfo, StringRef FnName,
1685 uint64_t TheRetVal) {
1686 for (
auto Call : CSInfo.CallSites) {
1690 Call.replaceAndErase(
1691 "uniform-ret-val", FnName, RemarksEnabled, OREGetter,
1694 CSInfo.markDevirt();
1697bool DevirtModule::tryUniformRetValOpt(
1699 WholeProgramDevirtResolution::ByArg *Res) {
1702 uint64_t TheRetVal = TargetsForSlot[0].RetVal;
1704 if (
Target.RetVal != TheRetVal)
1707 if (CSInfo.isExported()) {
1709 Res->
Info = TheRetVal;
1712 applyUniformRetValOpt(CSInfo, TargetsForSlot[0].Fn->
getName(), TheRetVal);
1714 for (
auto &&Target : TargetsForSlot)
1719std::string DevirtModule::getGlobalName(VTableSlot Slot,
1720 ArrayRef<uint64_t> Args,
1722 std::string FullName =
"__typeid_";
1723 raw_string_ostream OS(FullName);
1724 OS << cast<MDString>(
Slot.TypeID)->getString() <<
'_' <<
Slot.ByteOffset;
1725 for (uint64_t Arg : Args)
1731bool DevirtModule::shouldExportConstantsAsAbsoluteSymbols() {
1732 Triple
T(
M.getTargetTriple());
1736void DevirtModule::exportGlobal(VTableSlot Slot, ArrayRef<uint64_t> Args,
1737 StringRef Name, Constant *
C) {
1739 getGlobalName(Slot, Args, Name),
C, &M);
1743void DevirtModule::exportConstant(VTableSlot Slot, ArrayRef<uint64_t> Args,
1744 StringRef Name, uint32_t Const,
1745 uint32_t &Storage) {
1746 if (shouldExportConstantsAsAbsoluteSymbols()) {
1756Constant *DevirtModule::importGlobal(VTableSlot Slot, ArrayRef<uint64_t> Args,
1758 GlobalVariable *GV =
1759 M.getOrInsertGlobal(getGlobalName(Slot, Args, Name), Int8Arr0Ty);
1764Constant *DevirtModule::importConstant(VTableSlot Slot, ArrayRef<uint64_t> Args,
1765 StringRef Name, IntegerType *IntTy,
1767 if (!shouldExportConstantsAsAbsoluteSymbols())
1768 return ConstantInt::get(IntTy, Storage);
1770 Constant *
C = importGlobal(Slot, Args, Name);
1776 if (GV->
hasMetadata(LLVMContext::MD_absolute_symbol))
1779 auto SetAbsRange = [&](uint64_t Min, uint64_t
Max) {
1790 SetAbsRange(0, 1ull << AbsWidth);
1795void DevirtModule::applyUniqueRetValOpt(
CallSiteInfo &CSInfo, StringRef FnName,
1797 Constant *UniqueMemberAddr) {
1798 for (
auto &&
Call : CSInfo.CallSites) {
1804 B.CreateBitCast(UniqueMemberAddr,
Call.VTable->
getType()));
1807 Call.replaceAndErase(
"unique-ret-val", FnName, RemarksEnabled, OREGetter,
1810 CSInfo.markDevirt();
1815 ConstantInt::get(Int64Ty,
M->Offset));
1818bool DevirtModule::tryUniqueRetValOpt(
1820 CallSiteInfo &CSInfo, WholeProgramDevirtResolution::ByArg *Res,
1821 VTableSlot Slot, ArrayRef<uint64_t> Args) {
1823 auto tryUniqueRetValOptFor = [&](
bool IsOne) {
1826 if (
Target.RetVal == (IsOne ? 1 : 0)) {
1829 UniqueMember =
Target.TM;
1837 Constant *UniqueMemberAddr = getMemberAddr(UniqueMember);
1838 if (CSInfo.isExported()) {
1842 exportGlobal(Slot, Args,
"unique_member", UniqueMemberAddr);
1846 applyUniqueRetValOpt(CSInfo, TargetsForSlot[0].Fn->
getName(), IsOne,
1851 for (
auto &&Target : TargetsForSlot)
1858 if (tryUniqueRetValOptFor(
true))
1860 if (tryUniqueRetValOptFor(
false))
1866void DevirtModule::applyVirtualConstProp(
CallSiteInfo &CSInfo, StringRef FnName,
1867 Constant *Byte, Constant *Bit) {
1868 for (
auto Call : CSInfo.CallSites) {
1873 Value *Addr =
B.CreatePtrAdd(
Call.VTable, Byte);
1874 if (RetType->getBitWidth() == 1) {
1876 Value *BitsAndBit =
B.CreateAnd(Bits, Bit);
1877 auto IsBitSet =
B.CreateICmpNE(BitsAndBit, ConstantInt::get(Int8Ty, 0));
1878 NumVirtConstProp1Bit++;
1879 Call.replaceAndErase(
"virtual-const-prop-1-bit", FnName, RemarksEnabled,
1880 OREGetter, IsBitSet);
1882 Value *Val =
B.CreateLoad(RetType, Addr);
1884 Call.replaceAndErase(
"virtual-const-prop", FnName, RemarksEnabled,
1888 CSInfo.markDevirt();
1891bool DevirtModule::tryVirtualConstProp(
1893 WholeProgramDevirtResolution *Res, VTableSlot Slot) {
1904 unsigned BitWidth = RetType->getBitWidth();
1916 Align TypeAlignment =
M.getDataLayout().getABIIntegerTypeAlignment(
BitWidth);
1949 GlobalVariable *GV =
Target.TM->Bits->GV;
1950 Align TableAlignment =
M.getDataLayout().getValueOrABITypeAlignment(
1952 if (TypeAlignment > TableAlignment)
1956 for (
auto &&CSByConstantArg : SlotInfo.ConstCSInfo) {
1957 if (!tryEvaluateFunctionsWithArgs(TargetsForSlot, CSByConstantArg.first))
1960 WholeProgramDevirtResolution::ByArg *ResByArg =
nullptr;
1962 ResByArg = &Res->
ResByArg[CSByConstantArg.first];
1964 if (tryUniformRetValOpt(TargetsForSlot, CSByConstantArg.second, ResByArg))
1967 if (tryUniqueRetValOpt(
BitWidth, TargetsForSlot, CSByConstantArg.second,
1968 ResByArg, Slot, CSByConstantArg.first))
1976 uint64_t AllocBefore =
1978 uint64_t AllocAfter =
1983 uint64_t TotalPaddingBefore = 0, TotalPaddingAfter = 0;
1984 for (
auto &&Target : TargetsForSlot) {
1985 TotalPaddingBefore += std::max<int64_t>(
1986 (AllocBefore + 7) / 8 -
Target.allocatedBeforeBytes() - 1, 0);
1987 TotalPaddingAfter += std::max<int64_t>(
1988 (AllocAfter + 7) / 8 -
Target.allocatedAfterBytes() - 1, 0);
1993 if (std::min(TotalPaddingBefore, TotalPaddingAfter) > 128)
2000 if (TotalPaddingBefore <= TotalPaddingAfter)
2016 for (
auto &&Target : TargetsForSlot)
2020 if (CSByConstantArg.second.isExported()) {
2022 ResByArg->
Byte = OffsetByte;
2023 exportConstant(Slot, CSByConstantArg.first,
"bit", 1ULL << OffsetBit,
2029 Constant *BitConst = ConstantInt::get(Int8Ty, 1ULL << OffsetBit);
2030 applyVirtualConstProp(CSByConstantArg.second,
2031 TargetsForSlot[0].Fn->getName(), ByteConst, BitConst);
2037 if (
B.Before.Bytes.empty() &&
B.After.Bytes.empty())
2042 Align Alignment =
M.getDataLayout().getValueOrABITypeAlignment(
2043 B.GV->getAlign(),
B.GV->getValueType());
2044 B.Before.Bytes.resize(
alignTo(
B.Before.Bytes.size(), Alignment));
2047 for (
size_t I = 0,
Size =
B.Before.Bytes.size();
I !=
Size / 2; ++
I)
2054 B.GV->getInitializer(),
2057 new GlobalVariable(M, NewInit->getType(),
B.GV->isConstant(),
2059 NewGV->setSection(
B.GV->getSection());
2060 NewGV->setComdat(
B.GV->getComdat());
2061 NewGV->setAlignment(
B.GV->getAlign());
2065 NewGV->copyMetadata(
B.GV,
B.Before.Bytes.size());
2070 B.GV->getInitializer()->getType(), 0,
B.GV->getLinkage(),
"",
2072 NewInit->getType(), NewGV,
2074 ConstantInt::get(Int32Ty, 1)}),
2076 Alias->setVisibility(
B.GV->getVisibility());
2077 Alias->takeName(
B.GV);
2079 B.GV->replaceAllUsesWith(Alias);
2080 B.GV->eraseFromParent();
2083bool DevirtModule::areRemarksEnabled() {
2084 const auto &FL =
M.getFunctionList();
2085 for (
const Function &Fn : FL) {
2089 return DI.isEnabled();
2094void DevirtModule::scanTypeTestUsers(
2095 Function *TypeTestFunc,
2096 DenseMap<
Metadata *, std::set<TypeMemberInfo>> &TypeIdMap) {
2110 auto &DT =
FAM.
getResult<DominatorTreeAnalysis>(*CI->getFunction());
2116 if (!Assumes.
empty()) {
2117 Value *Ptr = CI->getArgOperand(0)->stripPointerCasts();
2118 for (DevirtCallSite
Call : DevirtCalls)
2119 CallSlots[{TypeId,
Call.Offset}].addCallSite(Ptr,
Call.CB,
nullptr);
2122 auto RemoveTypeTestAssumes = [&]() {
2124 for (
auto *Assume : Assumes)
2125 Assume->eraseFromParent();
2128 if (CI->use_empty())
2129 CI->eraseFromParent();
2144 if (!TypeIdMap.count(TypeId))
2145 RemoveTypeTestAssumes();
2157 const TypeIdSummary *TidSummary =
2160 RemoveTypeTestAssumes();
2169void DevirtModule::scanTypeCheckedLoadUsers(Function *TypeCheckedLoadFunc) {
2178 Value *Ptr = CI->getArgOperand(0);
2180 Value *TypeIdValue = CI->getArgOperand(2);
2186 bool HasNonCallUses =
false;
2187 auto &DT =
FAM.
getResult<DominatorTreeAnalysis>(*CI->getFunction());
2189 HasNonCallUses, CI, DT);
2198 (LoadedPtrs.
size() == 1 && !HasNonCallUses) ? LoadedPtrs[0] : CI);
2200 Value *LoadedValue =
nullptr;
2202 Intrinsic::type_checked_load_relative) {
2204 &M, Intrinsic::load_relative, {
Int32Ty});
2205 LoadedValue = LoadB.CreateCall(LoadRelFunc, {Ptr,
Offset});
2208 LoadedValue = LoadB.CreateLoad(Int8PtrTy,
GEP);
2211 for (Instruction *LoadedPtr : LoadedPtrs) {
2212 LoadedPtr->replaceAllUsesWith(LoadedValue);
2213 LoadedPtr->eraseFromParent();
2217 IRBuilder<> CallB((Preds.
size() == 1 && !HasNonCallUses) ? Preds[0] : CI);
2218 CallInst *TypeTestCall = CallB.CreateCall(TypeTestFunc, {Ptr, TypeIdValue});
2220 for (Instruction *Pred : Preds) {
2221 Pred->replaceAllUsesWith(TypeTestCall);
2222 Pred->eraseFromParent();
2229 if (!CI->use_empty()) {
2232 Pair =
B.CreateInsertValue(Pair, LoadedValue, {0});
2233 Pair =
B.CreateInsertValue(Pair, TypeTestCall, {1});
2238 auto &NumUnsafeUses = NumUnsafeUsesForTypeTest[TypeTestCall];
2239 NumUnsafeUses = DevirtCalls.
size();
2246 for (DevirtCallSite
Call : DevirtCalls) {
2247 CallSlots[{TypeId,
Call.Offset}].addCallSite(Ptr,
Call.CB,
2251 CI->eraseFromParent();
2255void DevirtModule::importResolution(VTableSlot Slot, VTableSlotInfo &SlotInfo) {
2259 const TypeIdSummary *TidSummary =
2263 auto ResI = TidSummary->
WPDRes.find(
Slot.ByteOffset);
2264 if (ResI == TidSummary->
WPDRes.end())
2266 const WholeProgramDevirtResolution &Res = ResI->second;
2278 bool IsExported =
false;
2279 applySingleImplDevirt(SlotInfo, SingleImpl, IsExported);
2283 for (
auto &CSByConstantArg : SlotInfo.ConstCSInfo) {
2284 auto I = Res.
ResByArg.find(CSByConstantArg.first);
2287 auto &ResByArg =
I->second;
2294 applyUniformRetValOpt(CSByConstantArg.second,
"", ResByArg.
Info);
2298 importGlobal(Slot, CSByConstantArg.first,
"unique_member");
2299 applyUniqueRetValOpt(CSByConstantArg.second,
"", ResByArg.
Info,
2305 Constant *
Bit = importConstant(Slot, CSByConstantArg.first,
"bit", Int8Ty,
2307 applyVirtualConstProp(CSByConstantArg.second,
"", Byte, Bit);
2319 M.getOrInsertFunction(getGlobalName(Slot, {},
"branch_funnel"),
2322 bool IsExported =
false;
2323 applyICallBranchFunnel(SlotInfo, *JT, IsExported);
2328void DevirtModule::removeRedundantTypeTests() {
2330 for (
auto &&U : NumUnsafeUsesForTypeTest) {
2331 if (
U.second == 0) {
2332 U.first->replaceAllUsesWith(True);
2333 U.first->eraseFromParent();
2339DevirtModule::lookUpFunctionValueInfo(Function *TheFn,
2340 ModuleSummaryIndex *ExportSummary) {
2341 assert((ExportSummary !=
nullptr) &&
2342 "Caller guarantees ExportSummary is not nullptr");
2344 const auto TheFnGUID = TheFn->
getGUID();
2345 const auto TheFnGUIDWithExportedName =
2348 ValueInfo TheFnVI = ExportSummary->
getValueInfo(TheFnGUID);
2357 if ((!TheFnVI) && (TheFnGUID != TheFnGUIDWithExportedName)) {
2358 TheFnVI = ExportSummary->
getValueInfo(TheFnGUIDWithExportedName);
2363bool DevirtModule::mustBeUnreachableFunction(
2364 Function *
const F, ModuleSummaryIndex *ExportSummary) {
2368 if (!
F->isDeclaration()) {
2374 return ExportSummary &&
2376 DevirtModule::lookUpFunctionValueInfo(
F, ExportSummary));
2379bool DevirtModule::run() {
2388 Function *PublicTypeTestFunc =
nullptr;
2391 if (DevirtSpeculatively)
2392 PublicTypeTestFunc =
2399 &M, Intrinsic::type_checked_load_relative);
2406 if (!ExportSummary &&
2407 (((!PublicTypeTestFunc || PublicTypeTestFunc->
use_empty()) &&
2408 (!TypeTestFunc || TypeTestFunc->
use_empty())) ||
2409 !AssumeFunc || AssumeFunc->
use_empty()) &&
2410 (!TypeCheckedLoadFunc || TypeCheckedLoadFunc->
use_empty()) &&
2411 (!TypeCheckedLoadRelativeFunc ||
2412 TypeCheckedLoadRelativeFunc->
use_empty()))
2416 std::vector<VTableBits>
Bits;
2417 DenseMap<Metadata *, std::set<TypeMemberInfo>> TypeIdMap;
2418 buildTypeIdentifierMap(Bits, TypeIdMap);
2420 if (PublicTypeTestFunc && AssumeFunc)
2421 scanTypeTestUsers(PublicTypeTestFunc, TypeIdMap);
2423 if (TypeTestFunc && AssumeFunc)
2424 scanTypeTestUsers(TypeTestFunc, TypeIdMap);
2426 if (TypeCheckedLoadFunc)
2427 scanTypeCheckedLoadUsers(TypeCheckedLoadFunc);
2429 if (TypeCheckedLoadRelativeFunc)
2430 scanTypeCheckedLoadUsers(TypeCheckedLoadRelativeFunc);
2432 if (ImportSummary) {
2433 for (
auto &S : CallSlots)
2434 importResolution(S.first, S.second);
2436 removeRedundantTypeTests();
2441 for (GlobalVariable &GV :
M.globals())
2449 if (TypeIdMap.
empty())
2453 if (ExportSummary) {
2454 DenseMap<GlobalValue::GUID, TinyPtrVector<Metadata *>> MetadataByGUID;
2455 for (
auto &
P : TypeIdMap) {
2458 TypeId->getString())]
2462 for (
auto &
P : *ExportSummary) {
2463 for (
auto &S :
P.second.getSummaryList()) {
2468 for (FunctionSummary::VFuncId VF :
FS->type_test_assume_vcalls()) {
2469 for (
Metadata *MD : MetadataByGUID[VF.GUID]) {
2470 CallSlots[{MD, VF.Offset}].CSInfo.addSummaryTypeTestAssumeUser(FS);
2473 for (FunctionSummary::VFuncId VF :
FS->type_checked_load_vcalls()) {
2474 for (
Metadata *MD : MetadataByGUID[VF.GUID]) {
2475 CallSlots[{MD, VF.Offset}].CSInfo.addSummaryTypeCheckedLoadUser(FS);
2478 for (
const FunctionSummary::ConstVCall &VC :
2479 FS->type_test_assume_const_vcalls()) {
2480 for (
Metadata *MD : MetadataByGUID[
VC.VFunc.GUID]) {
2481 CallSlots[{MD,
VC.VFunc.Offset}]
2482 .ConstCSInfo[
VC.Args]
2483 .addSummaryTypeTestAssumeUser(FS);
2486 for (
const FunctionSummary::ConstVCall &VC :
2487 FS->type_checked_load_const_vcalls()) {
2488 for (
Metadata *MD : MetadataByGUID[
VC.VFunc.GUID]) {
2489 CallSlots[{MD,
VC.VFunc.Offset}]
2490 .ConstCSInfo[
VC.Args]
2491 .addSummaryTypeCheckedLoadUser(FS);
2499 bool DidVirtualConstProp =
false;
2500 std::map<std::string, GlobalValue *> DevirtTargets;
2501 for (
auto &S : CallSlots) {
2505 std::vector<VirtualCallTarget> TargetsForSlot;
2506 WholeProgramDevirtResolution *Res =
nullptr;
2507 const std::set<TypeMemberInfo> &TypeMemberInfos = TypeIdMap[S.first.TypeID];
2509 TypeMemberInfos.size())
2516 Res = &ExportSummary
2517 ->getOrInsertTypeIdSummary(
2519 .WPDRes[S.first.ByteOffset];
2520 if (tryFindVirtualCallTargets(TargetsForSlot, TypeMemberInfos,
2521 S.first.ByteOffset, ExportSummary)) {
2522 bool SingleImplDevirt =
2523 trySingleImplDevirt(ExportSummary, TargetsForSlot, S.second, Res);
2527 if (!SingleImplDevirt && !DevirtSpeculatively) {
2528 DidVirtualConstProp |=
2529 tryVirtualConstProp(TargetsForSlot, S.second, Res, S.first);
2531 tryICallBranchFunnel(TargetsForSlot, S.second, Res, S.first);
2536 for (
const auto &
T : TargetsForSlot)
2538 DevirtTargets[std::string(
T.Fn->getName())] =
T.Fn;
2548 auto AddTypeTestsForTypeCheckedLoads = [&](
CallSiteInfo &CSI) {
2549 if (!CSI.AllCallSitesDevirted)
2550 for (
auto *FS : CSI.SummaryTypeCheckedLoadUsers)
2551 FS->addTypeTest(GUID);
2553 AddTypeTestsForTypeCheckedLoads(S.second.CSInfo);
2554 for (
auto &CCS : S.second.ConstCSInfo)
2555 AddTypeTestsForTypeCheckedLoads(CCS.second);
2559 if (RemarksEnabled) {
2561 for (
const auto &DT : DevirtTargets) {
2562 GlobalValue *GV = DT.second;
2571 using namespace ore;
2572 OREGetter(*F).emit(OptimizationRemark(
DEBUG_TYPE,
"Devirtualized",
F)
2573 <<
"devirtualized " <<
NV(
"FunctionName", DT.first));
2577 NumDevirtTargets += DevirtTargets.size();
2579 removeRedundantTypeTests();
2583 if (DidVirtualConstProp)
2590 for (GlobalVariable &GV :
M.globals())
2593 for (
auto *CI : CallsWithPtrAuthBundleRemoved)
2594 CI->eraseFromParent();
2599void DevirtIndex::run() {
2600 if (ExportSummary.typeIdCompatibleVtableMap().empty())
2605 assert(!ExportSummary.withInternalizeAndPromote() &&
2606 "Expect index-based WPD to run before internalization and promotion");
2608 DenseMap<GlobalValue::GUID, std::vector<StringRef>> NameByGUID;
2609 for (
const auto &
P : ExportSummary.typeIdCompatibleVtableMap()) {
2618 ExportSummary.getOrInsertTypeIdSummary(
P.first);
2622 for (
auto &
P : ExportSummary) {
2623 for (
auto &S :
P.second.getSummaryList()) {
2628 for (FunctionSummary::VFuncId VF :
FS->type_test_assume_vcalls()) {
2629 for (StringRef Name : NameByGUID[VF.GUID]) {
2630 CallSlots[{
Name, VF.Offset}].CSInfo.addSummaryTypeTestAssumeUser(FS);
2633 for (FunctionSummary::VFuncId VF :
FS->type_checked_load_vcalls()) {
2634 for (StringRef Name : NameByGUID[VF.GUID]) {
2635 CallSlots[{
Name, VF.Offset}].CSInfo.addSummaryTypeCheckedLoadUser(FS);
2638 for (
const FunctionSummary::ConstVCall &VC :
2639 FS->type_test_assume_const_vcalls()) {
2640 for (StringRef Name : NameByGUID[
VC.VFunc.GUID]) {
2641 CallSlots[{
Name,
VC.VFunc.Offset}]
2642 .ConstCSInfo[
VC.Args]
2643 .addSummaryTypeTestAssumeUser(FS);
2646 for (
const FunctionSummary::ConstVCall &VC :
2647 FS->type_checked_load_const_vcalls()) {
2648 for (StringRef Name : NameByGUID[
VC.VFunc.GUID]) {
2649 CallSlots[{
Name,
VC.VFunc.Offset}]
2650 .ConstCSInfo[
VC.Args]
2651 .addSummaryTypeCheckedLoadUser(FS);
2657 std::set<ValueInfo> DevirtTargets;
2659 for (
auto &S : CallSlots) {
2663 std::vector<ValueInfo> TargetsForSlot;
2664 auto TidSummary = ExportSummary.getTypeIdCompatibleVtableSummary(S.first.TypeID);
2668 WholeProgramDevirtResolution *Res =
2669 &ExportSummary.getTypeIdSummary(S.first.TypeID)
2670 ->WPDRes[S.first.ByteOffset];
2671 if (tryFindVirtualCallTargets(TargetsForSlot, *TidSummary,
2672 S.first.ByteOffset)) {
2674 if (!trySingleImplDevirt(TargetsForSlot, S.first, S.second, Res,
2683 for (
const auto &DT : DevirtTargets)
2684 errs() <<
"Devirtualized call to " << DT <<
"\n";
2686 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 for this value.
@ 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 VTableSlotSummary getEmptyKey()
static VTableSlot getEmptyKey()
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