95#include <system_error>
102#define DEBUG_TYPE "lowertypetests"
105STATISTIC(ByteArraySizeBytes,
"Byte array size in bytes");
106STATISTIC(NumByteArraysCreated,
"Number of byte arrays created");
107STATISTIC(NumTypeTestCallsLowered,
"Number of type test calls lowered");
108STATISTIC(NumTypeIdDisjointSets,
"Number of disjoint sets of type identifiers");
134 for (uint64_t
B :
Bits)
177 assert(Fragments.front().empty() &&
"Cannot add fragments after build()");
180 Fragments.emplace_back();
181 std::vector<uint64_t> &
Fragment = Fragments.back();
182 uint64_t FragmentIndex = Fragments.size() - 1;
184 std::vector<std::vector<uint64_t>> SubFragments;
185 for (
auto ObjIndex :
F) {
186 uint64_t OldFragmentIndex = FragmentMap[ObjIndex];
187 if (OldFragmentIndex == 0) {
190 SubFragments.push_back({ObjIndex});
191 }
else if (!Fragments[OldFragmentIndex].empty()) {
197 SubFragments.push_back(std::move(Fragments[OldFragmentIndex]));
203 const std::vector<uint64_t> &
B) {
204 return Less(
A.back(),
B.back());
208 for (
auto &SF : SubFragments)
213 FragmentMap[ObjIndex] = FragmentIndex;
222 [](
const std::vector<uint64_t> &
F) {
return F.empty(); });
224 const std::vector<uint64_t> &FB) {
225 return Less(FA.back(), FB.back());
229 std::vector<uint64_t> Layout;
230 Layout.reserve(FragmentMap.size());
231 for (
auto &&
F : Fragments)
234 Fragments.push_back(std::move(Layout));
235 return Fragments.front();
239 uint64_t BitSize, uint64_t &AllocByteOffset,
250 unsigned ReqSize = AllocByteOffset + BitSize;
252 if (
Bytes.size() < ReqSize)
253 Bytes.resize(ReqSize);
256 AllocMask = 1 << Bit;
257 for (uint64_t
B : Bits)
258 Bytes[AllocByteOffset +
B] |= AllocMask;
262 if (
F->isDeclarationForLinker())
265 F->getParent()->getModuleFlag(
"CFI Canonical Jump Tables"));
266 if (!CI || !CI->isZero())
268 return F->hasFnAttribute(
"cfi-canonical-jump-table");
275 if (AssocGO->hasMetadata(LLVMContext::MD_type))
285 for (
auto &
A : M.aliases())
302 if (
C->getBitWidth() != 64)
313 GO.getMetadata(LLVMContext::MD_type, Types);
316 TypeIds.
insert(TypeId->getZExtValue());
319 if (
NamedMDNode *CfiFunctionsMD = M.getNamedMetadata(
"cfi.functions")) {
320 for (
auto *Func : CfiFunctionsMD->operands()) {
321 assert(Func->getNumOperands() >= 3);
323 for (
unsigned I = 3;
I < Func->getNumOperands(); ++
I)
326 TypeIds.
insert(TypeId->getZExtValue());
335enum class CfiFunctionLinkage :
uint8_t {
342class CfiFunctionHotness {
355 CfiFunctionHotness() =
default;
364 static CfiFunctionHotness
365 fromFunction(
Function &
F, ProfileSummaryInfo &PSI,
366 function_ref<
const BlockFrequencyInfo &(
Function &)> BFIGetter) {
367 if (
F.isDeclaration())
368 return Kind::Unknown;
371 const BlockFrequencyInfo &BFI = BFIGetter(
F);
372 if (
F.hasFnAttribute(Attribute::Hot) ||
378 F.hasFnAttribute(Attribute::Cold)) {
387 static CfiFunctionHotness fromUint6(uint8_t
V) {
388 return CfiFunctionHotness(
static_cast<Kind>(
V & 0x3));
391 uint8_t asUint6()
const {
return static_cast<uint8_t
>(
Type) & 0x3; }
398 auto Rank = [](
Kind K) ->
int {
399 return (K == Kind::Cold) ? -1 :
static_cast<int>(
K);
408 return static_cast<CfiFunctionLinkage
>(Encoded & 0x3);
412 return CfiFunctionHotness::fromUint6(Encoded >> 2);
416 CfiFunctionHotness Hotness) {
431 for (
auto *
V : CfiFunctions) {
434 F.getMetadata(LLVMContext::MD_type, Types);
438 CfiFunctionLinkage
Linkage = CfiFunctionLinkage::Declaration;
440 Linkage = CfiFunctionLinkage::Definition;
441 else if (
F.hasExternalWeakLinkage())
442 Linkage = CfiFunctionLinkage::WeakDeclaration;
444 CfiFunctionHotness Hotness =
445 Opts.reorder_cfi_jump_tables_profiles
446 ? CfiFunctionHotness::fromFunction(
F, PSI, BFIGetter)
447 : CfiFunctionHotness();
460 if (!CfiFunctionMDs.
empty()) {
462 for (
auto *MD : CfiFunctionMDs)
470 for (
const auto &
A : SrcM.
aliases()) {
475 FunctionAliases[
F].push_back(&
A);
478 if (!FunctionAliases.
empty()) {
480 for (
auto &Alias : FunctionAliases) {
483 for (
auto *
A : Alias.second)
496 if (!
F ||
F->use_empty())
503 if (!Symvers.
empty()) {
505 for (
auto *MD : Symvers)
521struct ByteArrayInfo {
522 std::set<uint64_t> Bits;
534class GlobalTypeMember final :
TrailingObjects<GlobalTypeMember, MDNode *> {
545 bool IsJumpTableCanonical;
553 bool IsJumpTableCanonical,
bool IsExported,
555 auto *GTM =
static_cast<GlobalTypeMember *
>(
Alloc.Allocate(
556 totalSizeToAlloc<MDNode *>(Types.size()),
alignof(GlobalTypeMember)));
558 GTM->NTypes = Types.size();
559 GTM->IsJumpTableCanonical = IsJumpTableCanonical;
560 GTM->IsExported = IsExported;
565 GlobalObject *getGlobal()
const {
570 return IsJumpTableCanonical;
573 bool isExported()
const {
580struct ICallBranchFunnel final
581 : TrailingObjects<ICallBranchFunnel, GlobalTypeMember *> {
585 auto *
Call =
static_cast<ICallBranchFunnel *
>(
586 Alloc.Allocate(totalSizeToAlloc<GlobalTypeMember *>(Targets.
size()),
587 alignof(ICallBranchFunnel)));
589 Call->UniqueId = UniqueId;
597 return getTrailingObjects(NTargets);
606struct ScopedSaveAliaseesAndUsed {
609 std::vector<std::pair<GlobalAlias *, Function *>> FunctionAliases;
610 std::vector<std::pair<GlobalIFunc *, Function *>> ResolverIFuncs;
615 void collectAndEraseUsedFunctions(
Module &M,
616 SmallVectorImpl<GlobalValue *> &Vec,
624 GV->eraseFromParent();
626 std::stable_partition(Vec.
begin(), Vec.
end(), [](GlobalValue *GV) {
627 return isa<Function>(GV);
636 ScopedSaveAliaseesAndUsed(
Module &M) :
M(
M) {
649 collectAndEraseUsedFunctions(M, Used,
false);
650 collectAndEraseUsedFunctions(M, CompilerUsed,
true);
652 for (
auto &GA :
M.aliases()) {
656 FunctionAliases.push_back({&GA,
F});
659 for (
auto &GI :
M.ifuncs())
661 ResolverIFuncs.push_back({&GI,
F});
664 ~ScopedSaveAliaseesAndUsed() {
668 for (
auto P : FunctionAliases)
669 P.first->setAliasee(
P.second);
671 for (
auto P : ResolverIFuncs) {
675 P.first->setResolver(
P.second);
680class LowerTypeTestsModule {
681 const IPOOptions &Opts;
684 ModuleSummaryIndex *ExportSummary;
685 const ModuleSummaryIndex *ImportSummary;
694 bool CanUseArmJumpTable =
false, CanUseThumbBWJumpTable =
false;
697 int HasBranchTargetEnforcement = -1;
700 DenseMap<const Function *, CfiFunctionHotness> FunctionSummaryHotness;
702 IntegerType *Int1Ty = Type::getInt1Ty(
M.getContext());
703 IntegerType *Int8Ty = Type::getInt8Ty(
M.getContext());
704 PointerType *PtrTy = PointerType::getUnqual(
M.getContext());
705 ArrayType *Int8Arr0Ty = ArrayType::get(Type::getInt8Ty(
M.getContext()), 0);
706 IntegerType *Int32Ty = Type::getInt32Ty(
M.getContext());
707 IntegerType *Int64Ty = Type::getInt64Ty(
M.getContext());
708 IntegerType *
IntPtrTy =
M.getDataLayout().getIntPtrType(
M.getContext(), 0);
716 struct TypeIdUserInfo {
717 std::vector<CallInst *> CallSites;
718 bool IsExported =
false;
720 DenseMap<Metadata *, TypeIdUserInfo> TypeIdUsers;
726 struct TypeIdLowering {
751 std::vector<ByteArrayInfo> ByteArrayInfos;
753 Function *WeakInitializerFn =
nullptr;
755 GlobalVariable *GlobalAnnotation;
756 DenseSet<Value *> FunctionAnnotations;
760 bool CrossDsoCfi =
M.getModuleFlag(
"Cross-DSO CFI") !=
nullptr;
762 bool shouldExportConstantsAsAbsoluteSymbols();
763 uint8_t *exportTypeId(StringRef TypeId,
const TypeIdLowering &TIL);
764 TypeIdLowering importTypeId(StringRef TypeId);
765 void importTypeTest(CallInst *CI);
768 ByteArrayInfo *createByteArray(
const BitSetInfo &BSI);
769 void allocateByteArrays();
772 void lowerTypeTestCalls(
774 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout);
776 const TypeIdLowering &TIL);
782 bool hasBranchTargetEnforcement();
785 void verifyTypeMDNode(GlobalObject *GO, MDNode *
Type);
797 void replaceWeakDeclarationWithJumpTablePtr(
Function *
F, Constant *JT,
798 bool IsJumpTableCanonical);
799 void moveInitializerToModuleConstructor(GlobalVariable *GV);
800 void findGlobalVariableUsersOf(Constant *
C,
801 SmallSetVector<GlobalVariable *, 8> &Out);
810 void replaceCfiUses(
Function *Old,
Value *New,
bool IsJumpTableCanonical);
814 void replaceDirectCalls(
Value *Old,
Value *New);
816 bool isFunctionAnnotation(
Value *
V)
const {
820 void maybeReplaceComdat(
Function *
F, StringRef OriginalName);
824 ModuleSummaryIndex *ExportSummary,
825 const ModuleSummaryIndex *ImportSummary);
847 unsigned BitWidth = BitsType->getBitWidth();
849 BitOffset =
B.CreateZExtOrTrunc(BitOffset, BitsType);
851 B.CreateAnd(BitOffset, ConstantInt::get(BitsType,
BitWidth - 1));
852 Value *BitMask =
B.CreateShl(ConstantInt::get(BitsType, 1), BitIndex);
853 Value *MaskedBits =
B.CreateAnd(Bits, BitMask);
854 return B.CreateICmpNE(MaskedBits, ConstantInt::get(BitsType, 0));
857ByteArrayInfo *LowerTypeTestsModule::createByteArray(
const BitSetInfo &BSI) {
861 auto ByteArrayGlobal =
new GlobalVariable(
863 auto MaskGlobal =
new GlobalVariable(M, Int8Ty,
true,
866 ByteArrayInfos.emplace_back();
867 ByteArrayInfo *BAI = &ByteArrayInfos.back();
869 BAI->Bits = BSI.
Bits;
871 BAI->ByteArray = ByteArrayGlobal;
872 BAI->MaskGlobal = MaskGlobal;
876void LowerTypeTestsModule::allocateByteArrays() {
878 [](
const ByteArrayInfo &BAI1,
const ByteArrayInfo &BAI2) {
879 return BAI1.BitSize > BAI2.BitSize;
882 std::vector<uint64_t> ByteArrayOffsets(ByteArrayInfos.size());
885 for (
unsigned I = 0;
I != ByteArrayInfos.size(); ++
I) {
886 ByteArrayInfo *BAI = &ByteArrayInfos[
I];
889 BAB.
allocate(BAI->Bits, BAI->BitSize, ByteArrayOffsets[
I], Mask);
895 *BAI->MaskPtr =
Mask;
900 new GlobalVariable(M, ByteArrayConst->
getType(),
true,
903 for (
unsigned I = 0;
I != ByteArrayInfos.size(); ++
I) {
904 ByteArrayInfo *BAI = &ByteArrayInfos[
I];
906 ByteArray, ConstantInt::get(
IntPtrTy, ByteArrayOffsets[
I]));
920 ByteArraySizeBytes = BAB.
Bytes.size();
926 const TypeIdLowering &TIL,
934 if (Opts.lowertypetests_avoid_reuse && !ImportSummary) {
940 "bits_use", ByteArray, &M);
943 Value *ByteAddr =
B.CreateGEP(Int8Ty, ByteArray, BitOffset);
948 return B.CreateICmpNE(ByteAndMask, ConstantInt::get(Int8Ty, 0));
956 GV->getMetadata(LLVMContext::MD_type, Types);
958 if (
Type->getOperand(1) != TypeId)
971 APInt APOffset(
DL.getIndexSizeInBits(0), 0);
972 bool Result =
GEP->accumulateConstantOffset(
DL, APOffset);
980 if (
Op->getOpcode() == Instruction::BitCast)
983 if (
Op->getOpcode() == Instruction::Select)
993Value *LowerTypeTestsModule::lowerTypeTestCall(
Metadata *TypeId, CallInst *CI,
994 const TypeIdLowering &TIL) {
1002 const DataLayout &
DL =
M.getDataLayout();
1015 return B.CreateICmpEQ(PtrAsInt, OffsetedGlobalAsInt);
1021 Value *PtrOffset =
B.CreateSub(OffsetedGlobalAsInt, PtrAsInt);
1032 {PtrOffset, PtrOffset, TIL.AlignLog2});
1034 Value *OffsetInRange =
B.CreateICmpULE(BitOffset, TIL.SizeM1);
1038 return OffsetInRange;
1051 Br->getMetadata(LLVMContext::MD_prof));
1055 for (
auto &Phi :
Else->phis())
1056 Phi.addIncoming(
Phi.getIncomingValueForBlock(Then), InitialBB);
1059 return createBitSetTest(ThenB, TIL, BitOffset);
1062 MDBuilder MDB(
M.getContext());
1064 MDB.createLikelyBranchWeights()));
1068 Value *
Bit = createBitSetTest(ThenB, TIL, BitOffset);
1073 B.SetInsertPoint(CI);
1074 PHINode *
P =
B.CreatePHI(Int1Ty, 2);
1075 P->addIncoming(ConstantInt::get(Int1Ty, 0), InitialBB);
1076 P->addIncoming(Bit, ThenB.GetInsertBlock());
1082void LowerTypeTestsModule::buildBitSetsFromGlobalVariables(
1089 std::vector<Constant *> GlobalInits;
1090 const DataLayout &
DL =
M.getDataLayout();
1091 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
1095 for (GlobalTypeMember *
G : Globals) {
1098 DL.getValueOrABITypeAlignment(GV->getAlign(), GV->getValueType());
1099 MaxAlign = std::max(MaxAlign, Alignment);
1101 GlobalLayout[
G] = GVOffset;
1102 if (GVOffset != 0) {
1104 GlobalInits.push_back(
1108 GlobalInits.push_back(GV->getInitializer());
1110 CurOffset = GVOffset + InitSize;
1113 DesiredPadding =
NextPowerOf2(InitSize - 1) - InitSize;
1119 if (DesiredPadding > 32)
1120 DesiredPadding =
alignTo(InitSize, 32) - InitSize;
1124 auto *CombinedGlobal =
1125 new GlobalVariable(M, NewInit->
getType(),
true,
1127 CombinedGlobal->setAlignment(MaxAlign);
1130 lowerTypeTestCalls(TypeIds, CombinedGlobal, GlobalLayout);
1135 for (
unsigned I = 0;
I != Globals.size(); ++
I) {
1139 Constant *CombinedGlobalIdxs[] = {ConstantInt::get(Int32Ty, 0),
1140 ConstantInt::get(Int32Ty,
I * 2)};
1142 DL, NewInit->
getType(), CombinedGlobal, CombinedGlobalIdxs,
1145 GlobalAlias *GAlias =
1147 "", CombinedGlobalElemPtr, &M);
1155bool LowerTypeTestsModule::shouldExportConstantsAsAbsoluteSymbols() {
1168uint8_t *LowerTypeTestsModule::exportTypeId(StringRef TypeId,
1169 const TypeIdLowering &TIL) {
1170 TypeTestResolution &TTRes =
1177 "__typeid_" + TypeId +
"_" + Name,
C, &M);
1182 if (shouldExportConstantsAsAbsoluteSymbols())
1189 ExportGlobal(
"global_addr", TIL.OffsetedGlobal);
1194 ExportConstant(
"align", TTRes.
AlignLog2, TIL.AlignLog2);
1195 ExportConstant(
"size_m1", TTRes.
SizeM1, TIL.SizeM1);
1205 ExportGlobal(
"byte_array", TIL.TheByteArray);
1206 if (shouldExportConstantsAsAbsoluteSymbols())
1207 ExportGlobal(
"bit_mask", TIL.BitMask);
1213 ExportConstant(
"inline_bits", TTRes.
InlineBits, TIL.InlineBits);
1218LowerTypeTestsModule::TypeIdLowering
1219LowerTypeTestsModule::importTypeId(StringRef TypeId) {
1223 const TypeTestResolution &TTRes = TidSummary->
TTRes;
1228 auto ImportGlobal = [&](StringRef
Name) {
1231 GlobalVariable *GV =
M.getOrInsertGlobal(
1232 (
"__typeid_" + TypeId +
"_" + Name).str(), Int8Arr0Ty);
1239 if (!shouldExportConstantsAsAbsoluteSymbols()) {
1251 if (GV->
getMetadata(LLVMContext::MD_absolute_symbol))
1260 if (AbsWidth ==
IntPtrTy->getBitWidth()) {
1264 SetAbsRange(0, 1ull << AbsWidth);
1270 auto *GV = ImportGlobal(
"global_addr");
1283 TIL.OffsetedGlobal = GV;
1295 TIL.TheByteArray = ImportGlobal(
"byte_array");
1296 TIL.BitMask = ImportConstant(
"bit_mask", TTRes.
BitMask, 8, PtrTy);
1300 TIL.InlineBits = ImportConstant(
1307void LowerTypeTestsModule::importTypeTest(CallInst *CI) {
1319 TypeIdLowering TIL = importTypeId(TypeIdStr->getString());
1320 Value *Lowered = lowerTypeTestCall(TypeIdStr, CI, TIL);
1327void LowerTypeTestsModule::maybeReplaceComdat(
Function *
F,
1328 StringRef OriginalName) {
1334 F->getComdat()->getName() == OriginalName) {
1335 Comdat *OldComdat =
F->getComdat();
1336 Comdat *NewComdat =
M.getOrInsertComdat(
F->getName());
1337 for (GlobalObject &GO :
M.global_objects()) {
1346void LowerTypeTestsModule::importFunction(
Function *
F,
1348 assert(
F->getType()->getAddressSpace() == 0);
1351 std::string
Name = std::string(
F->getName());
1356 if (!
F->isDSOLocal())
1358 if (
F->isDeclaration()) {
1363 F->getAddressSpace(),
1366 replaceDirectCalls(
F, RealF);
1383 F->getAddressSpace(), Name +
".cfi_jt", &M);
1386 F->setName(Name +
".cfi");
1387 maybeReplaceComdat(
F, Name);
1389 F->getAddressSpace(), Name, &M);
1397 for (
auto &U :
F->uses()) {
1406 std::string AliasName =
A->getName().str() +
".cfi";
1409 F->getAddressSpace(),
"", &M);
1411 A->replaceAllUsesWith(AliasDecl);
1412 A->setName(AliasName);
1418 if (
F->hasExternalWeakLinkage())
1425 F->setVisibility(Visibility);
1434 OffsetsByTypeID[TypeId];
1435 for (
const auto &[Mem, MemOff] : GlobalLayout) {
1437 auto It = OffsetsByTypeID.
find(
Type->getOperand(1));
1438 if (It == OffsetsByTypeID.
end())
1444 It->second.push_back(MemOff +
Offset);
1454 dbgs() << MDS->getString() <<
": ";
1456 dbgs() <<
"<unnamed>: ";
1457 BitSets.
back().second.print(
dbgs());
1464void LowerTypeTestsModule::lowerTypeTestCalls(
1466 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout) {
1468 for (
const auto &[TypeId, BSI] :
buildBitSets(TypeIds, GlobalLayout)) {
1469 ByteArrayInfo *BAI =
nullptr;
1475 CombinedGlobalAddr, ConstantInt::get(
IntPtrTy, GlobalOffset)),
1480 : TypeTestResolution::
AllOnes;
1484 for (
auto Bit : BSI.
Bits)
1486 if (InlineBits == 0)
1489 TIL.InlineBits = ConstantInt::get(
1490 (BSI.
BitSize <= 32) ? Int32Ty : Int64Ty, InlineBits);
1493 ++NumByteArraysCreated;
1494 BAI = createByteArray(BSI);
1495 TIL.TheByteArray = BAI->ByteArray;
1496 TIL.BitMask = BAI->MaskGlobal;
1499 TypeIdUserInfo &TIUI = TypeIdUsers[TypeId];
1501 if (TIUI.IsExported) {
1502 uint8_t *MaskPtr = exportTypeId(
cast<MDString>(TypeId)->getString(), TIL);
1504 BAI->MaskPtr = MaskPtr;
1508 for (CallInst *CI : TIUI.CallSites) {
1509 ++NumTypeTestCallsLowered;
1510 Value *Lowered = lowerTypeTestCall(TypeId, CI, TIL);
1519void LowerTypeTestsModule::verifyTypeMDNode(GlobalObject *GO, MDNode *
Type) {
1520 if (
Type->getNumOperands() != 2)
1527 "A member of a type identifier may not have an explicit section");
1550bool LowerTypeTestsModule::hasBranchTargetEnforcement() {
1551 if (HasBranchTargetEnforcement == -1) {
1555 M.getModuleFlag(
"branch-target-enforcement")))
1556 HasBranchTargetEnforcement = !BTE->isZero();
1558 HasBranchTargetEnforcement = 0;
1560 return HasBranchTargetEnforcement;
1564LowerTypeTestsModule::getJumpTableEntrySize(
Triple::ArchType JumpTableArch) {
1565 switch (JumpTableArch) {
1569 M.getModuleFlag(
"cf-protection-branch")))
1570 if (MD->getZExtValue())
1576 if (CanUseThumbBWJumpTable) {
1577 if (hasBranchTargetEnforcement())
1584 if (hasBranchTargetEnforcement())
1603LowerTypeTestsModule::createJumpTableEntryAsm(
Triple::ArchType JumpTableArch) {
1605 raw_string_ostream AsmOS(Asm);
1610 M.getModuleFlag(
"cf-protection-branch")))
1611 Endbr = !MD->isZero();
1613 AsmOS << (JumpTableArch ==
Triple::x86 ?
"endbr32\n" :
"endbr64\n");
1614 AsmOS <<
"jmp ${0:c}@plt\n";
1616 AsmOS <<
".balign 16, 0xcc\n";
1618 AsmOS <<
"int3\nint3\nint3\n";
1622 if (hasBranchTargetEnforcement())
1626 if (!CanUseThumbBWJumpTable) {
1642 AsmOS <<
"push {r0,r1}\n"
1644 <<
"0: add r0, r0, pc\n"
1645 <<
"str r0, [sp, #4]\n"
1648 <<
"1: .word $0 - (0b + 4)\n";
1650 if (hasBranchTargetEnforcement())
1652 AsmOS <<
"b.w $0\n";
1656 AsmOS <<
"tail $0@plt\n";
1658 AsmOS <<
"pcalau12i $$t0, %pc_hi20($0)\n"
1659 <<
"jirl $$r0, $$t0, %pc_lo12($0)\n";
1661 AsmOS <<
"jump $0\n";
1674void LowerTypeTestsModule::buildBitSetsFromFunctions(
1680 buildBitSetsFromFunctionsNative(TypeIds, Functions);
1682 buildBitSetsFromFunctionsWASM(TypeIds, Functions);
1687void LowerTypeTestsModule::moveInitializerToModuleConstructor(
1688 GlobalVariable *GV) {
1689 if (WeakInitializerFn ==
nullptr) {
1694 M.getDataLayout().getProgramAddressSpace(),
1695 "__cfi_global_var_init", &M);
1701 ?
"__TEXT,__StaticInit,regular,pure_instructions"
1714void LowerTypeTestsModule::findGlobalVariableUsersOf(
1715 Constant *
C, SmallSetVector<GlobalVariable *, 8> &Out) {
1716 for (
auto *U :
C->users()){
1720 findGlobalVariableUsersOf(C2, Out);
1725void LowerTypeTestsModule::replaceWeakDeclarationWithJumpTablePtr(
1726 Function *
F, Constant *JT,
bool IsJumpTableCanonical) {
1729 SmallSetVector<GlobalVariable *, 8> GlobalVarUsers;
1730 findGlobalVariableUsersOf(
F, GlobalVarUsers);
1731 for (
auto *GV : GlobalVarUsers) {
1732 if (GV == GlobalAnnotation)
1734 moveInitializerToModuleConstructor(GV);
1741 F->getAddressSpace(),
"", &M);
1742 replaceCfiUses(
F, PlaceholderFn, IsJumpTableCanonical);
1749 assert(InsertPt &&
"Non-instruction users should have been eliminated");
1752 InsertPt = PN->getIncomingBlock(U)->getTerminator();
1764 PN->setIncomingValueForBlock(InsertPt->getParent(),
Select);
1772 Attribute TFAttr =
F->getFnAttribute(
"target-features");
1777 if (Feature ==
"-thumb-mode")
1779 else if (Feature ==
"+thumb-mode")
1795 if (!CanUseThumbBWJumpTable && CanUseArmJumpTable) {
1803 unsigned ArmCount = 0, ThumbCount = 0;
1804 for (
const auto GTM : Functions) {
1805 if (!GTM->isJumpTableCanonical()) {
1826 auto CUs = M.debug_compile_units();
1843 CU,
"__ubsan_check_cfi_icall_jt", {}, File, 0, DIFnTy, 0,
1844 DINode::FlagArtificial, DISubprogram::SPFlagDefinition);
1846 F->setSubprogram(UbsanSP);
1851 Locations.
reserve(Functions.size());
1853 for (
auto *Func : Functions) {
1854 StringRef FuncName = Func->getGlobal()->getName();
1857 CU, (FuncName +
".cfi_jt").str(), {}, File, 0, DIFnTy, 0,
1858 DINode::FlagArtificial, DISubprogram::SPFlagDefinition);
1863 Locations.push_back(EntryLoc);
1871void LowerTypeTestsModule::createJumpTable(
1880 F->setMetadata(LLVMContext::MD_elf_section_properties,
1883 ConstantAsMetadata::get(ConstantInt::get(
1884 Int64Ty, ELF::SHT_LLVM_CFI_JUMP_TABLE)),
1885 ConstantAsMetadata::get(ConstantInt::get(
1886 Int64Ty, JumpTableEntrySize))}));
1892 if (
M.getDwarfVersion() != 0 && Opts.lowertypetests_jump_table_debug_info)
1895 InlineAsm *JumpTableAsm = createJumpTableEntryAsm(JumpTableArch);
1901 bool areAllEntriesNounwind =
true;
1903 for (
auto [GTM, Loc] :
zip_longest(Functions, Locations)) {
1904 if (Loc.has_value())
1905 IRB.SetCurrentDebugLocation(*Loc);
1907 ->hasFnAttribute(Attribute::NoUnwind)) {
1908 areAllEntriesNounwind =
false;
1910 IRB.CreateCall(JumpTableAsm, (*GTM)->getGlobal());
1912 IRB.CreateUnreachable();
1915 F->setPreferredAlignment(
Align(JumpTableEntrySize));
1916 F->addFnAttr(Attribute::Naked);
1918 F->addFnAttr(
"target-features",
"-thumb-mode");
1920 if (hasBranchTargetEnforcement()) {
1923 F->addFnAttr(
"target-features",
"+thumb-mode,+pacbti");
1925 F->addFnAttr(
"target-features",
"+thumb-mode");
1926 if (CanUseThumbBWJumpTable) {
1929 F->addFnAttr(
"target-cpu",
"cortex-a8");
1937 if (
F->hasFnAttribute(
"branch-target-enforcement"))
1938 F->removeFnAttr(
"branch-target-enforcement");
1939 if (
F->hasFnAttribute(
"sign-return-address"))
1940 F->removeFnAttr(
"sign-return-address");
1945 F->addFnAttr(
"target-features",
"-c,-relax");
1951 F->addFnAttr(Attribute::NoCfCheck);
1954 if (areAllEntriesNounwind)
1955 F->addFnAttr(Attribute::NoUnwind);
1958 F->addFnAttr(Attribute::NoInline);
1963void LowerTypeTestsModule::buildBitSetsFromFunctionsNative(
2048 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
2049 unsigned EntrySize = getJumpTableEntrySize(JumpTableArch);
2050 for (
unsigned I = 0;
I != Functions.
size(); ++
I)
2051 GlobalLayout[Functions[
I]] =
I * EntrySize;
2057 M.getDataLayout().getProgramAddressSpace(),
2058 ".cfi.jumptable", &M);
2065 lowerTypeTestCalls(TypeIds, JumpTable, GlobalLayout);
2071 for (
unsigned I = 0;
I != Functions.
size(); ++
I) {
2073 bool IsJumpTableCanonical = Functions[
I]->isJumpTableCanonical();
2076 F->getDataLayout(), JumpTableType, JumpTable,
2077 {ConstantInt::get(IntPtrTy, 0), ConstantInt::get(IntPtrTy, I)},
2080 const bool IsExported = Functions[
I]->isExported();
2081 if (!IsJumpTableCanonical) {
2085 F->getName() +
".cfi_jt",
2086 CombinedGlobalElemPtr, &M);
2095 if (IsJumpTableCanonical)
2103 if (!IsJumpTableCanonical) {
2104 if (
F->hasExternalWeakLinkage())
2105 replaceWeakDeclarationWithJumpTablePtr(
F, CombinedGlobalElemPtr,
2106 IsJumpTableCanonical);
2108 replaceCfiUses(
F, CombinedGlobalElemPtr, IsJumpTableCanonical);
2110 assert(
F->getType()->getAddressSpace() == 0);
2112 GlobalAlias *FAlias =
2114 CombinedGlobalElemPtr, &M);
2119 F->setName(FAlias->
getName() +
".cfi");
2120 maybeReplaceComdat(
F, FAlias->
getName());
2122 replaceCfiUses(
F, FAlias, IsJumpTableCanonical);
2123 if (!
F->hasLocalLinkage())
2128 if (!UsedJtAliases.
empty())
2131 createJumpTable(JumpTableFn, Functions, JumpTableArch);
2140void LowerTypeTestsModule::buildBitSetsFromFunctionsWASM(
2145 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
2147 for (GlobalTypeMember *GTM : Functions) {
2151 if (!
F->hasAddressTaken())
2157 ConstantInt::get(Int64Ty, IndirectIndex))));
2158 F->setMetadata(
"wasm.index", MD);
2161 GlobalLayout[GTM] = IndirectIndex++;
2170void LowerTypeTestsModule::buildBitSetsFromDisjointSet(
2173 DenseMap<Metadata *, uint64_t> TypeIdIndices;
2174 for (
unsigned I = 0;
I != TypeIds.
size(); ++
I)
2175 TypeIdIndices[TypeIds[
I]] =
I;
2179 std::vector<std::set<uint64_t>> TypeMembers(TypeIds.
size());
2180 unsigned GlobalIndex = 0;
2181 DenseMap<GlobalTypeMember *, uint64_t> GlobalIndices;
2182 for (GlobalTypeMember *GTM : Globals) {
2183 for (MDNode *
Type : GTM->types()) {
2185 auto I = TypeIdIndices.
find(
Type->getOperand(1));
2186 if (
I != TypeIdIndices.
end())
2187 TypeMembers[
I->second].insert(GlobalIndex);
2189 GlobalIndices[GTM] = GlobalIndex;
2193 for (ICallBranchFunnel *JT : ICallBranchFunnels) {
2194 TypeMembers.emplace_back();
2195 std::set<uint64_t> &TMSet = TypeMembers.back();
2196 for (GlobalTypeMember *
T : JT->targets())
2197 TMSet.insert(GlobalIndices[
T]);
2203 const std::set<uint64_t> &
O2) {
2204 return O1.size() <
O2.size();
2211 if (!IsGlobalSet && !FunctionSummaryHotness.
empty() &&
2212 Opts.reorder_cfi_jump_tables_profiles) {
2214 std::vector<CfiFunctionHotness> GTMHotness;
2215 GTMHotness.reserve(Globals.size());
2216 for (GlobalTypeMember *GTM : Globals) {
2217 GTMHotness.push_back(
2234 return GTMHotness[
A] < GTMHotness[
B];
2242 for (
auto &&MemSet : TypeMembers)
2243 GLB.addFragment(MemSet);
2246 std::vector<GlobalTypeMember *> OrderedGTMs(Globals.size());
2247 auto OGTMI = OrderedGTMs.begin();
2251 "variables and functions");
2252 *OGTMI++ = Globals[
Offset];
2257 buildBitSetsFromGlobalVariables(TypeIds, OrderedGTMs);
2259 buildBitSetsFromFunctions(TypeIds, OrderedGTMs);
2263LowerTypeTestsModule::LowerTypeTestsModule(
2265 const ModuleSummaryIndex *ImportSummary)
2267 ImportSummary(ImportSummary) {
2268 assert(!(ExportSummary && ImportSummary));
2269 Triple TargetTriple(M.getTargetTriple());
2270 Arch = TargetTriple.getArch();
2274 CanUseArmJumpTable =
true;
2278 if (
F.isDeclaration())
2281 if (
TTI.hasArmWideBranch(
false))
2282 CanUseArmJumpTable =
true;
2283 if (
TTI.hasArmWideBranch(
true))
2284 CanUseThumbBWJumpTable =
true;
2287 OS = TargetTriple.getOS();
2288 ObjectFormat = TargetTriple.getObjectFormat();
2292 GlobalAnnotation = M.getGlobalVariable(
"llvm.global.annotations");
2302 StringRef ReadSummary = Opts.lowertypetests_read_summary;
2303 StringRef WriteSummary = Opts.lowertypetests_write_summary;
2305 std::unique_ptr<ModuleSummaryIndex>
Summary;
2309 if (!ReadSummary.
empty()) {
2310 ExitOnError ExitOnErr(
2311 (
"-lowertypetests-read-summary: " + ReadSummary +
": ").str());
2312 auto ReadSummaryFile = ExitOnErr(
2316 if (ReadSummaryFile->getBuffer().starts_with(
"---")) {
2317 Summary = std::make_unique<ModuleSummaryIndex>(
false);
2318 yaml::Input
In(ReadSummaryFile->getBuffer());
2331 Summary = std::make_unique<ModuleSummaryIndex>(
false);
2335 LowerTypeTestsModule(
2337 SummaryAction == PassSummaryAction::Export ?
Summary.get() :
nullptr,
2338 SummaryAction == PassSummaryAction::Import ?
Summary.get() :
nullptr)
2341 if (!WriteSummary.
empty()) {
2342 ExitOnError ExitOnErr(
2343 (
"-lowertypetests-write-summary: " + WriteSummary +
": ").str());
2348 yaml::Output
Out(OS);
2357 return Usr && Usr->isCallee(&U);
2360void LowerTypeTestsModule::replaceCfiUses(
Function *Old,
Value *New,
2361 bool IsJumpTableCanonical) {
2362 SmallSetVector<Constant *, 4>
Constants;
2374 if (isFunctionAnnotation(
U.getUser()))
2392 for (
auto *
C : Constants)
2393 C->handleOperandChange(Old, New);
2396void LowerTypeTestsModule::replaceDirectCalls(
Value *Old,
Value *New) {
2412 Value *Ptr =
I->getOperand(0);
2414 Type *PtrTy =
I->getType()->getStructElementType(0);
2419 Intrinsic::load_relative, {
Offset->getType()}, {Ptr,
Offset},
2420 nullptr,
"rel_load");
2429 I->replaceAllUsesWith(Replacement);
2432 I->eraseFromParent();
2441 bool ShouldDropAll) {
2447 Assume->eraseFromParent();
2456 return isa<PHINode>(U) || isa<SelectInst>(U);
2472 bool DroppedCheckedLoads =
false;
2473 if (ShouldDropAll) {
2476 DroppedCheckedLoads |=
2479 &M, Intrinsic::type_checked_load_relative))
2480 DroppedCheckedLoads |=
2488 if (PublicTypeTestFunc)
2490 if (TypeTestFunc || PublicTypeTestFunc || DroppedCheckedLoads) {
2501bool LowerTypeTestsModule::lower() {
2515 if ((!TypeTestFunc || TypeTestFunc->
use_empty()) &&
2516 (!ICallBranchFunnelFunc || ICallBranchFunnelFunc->
use_empty()) &&
2517 !ExportSummary && !ImportSummary)
2520 if (ImportSummary) {
2525 if (ICallBranchFunnelFunc && !ICallBranchFunnelFunc->
use_empty())
2527 "unexpected call to llvm.icall.branch.funnel during import phase");
2534 if (
A.hasLocalLinkage())
2539 if (
F->hasExternalLinkage()) {
2554 A.replaceAllUsesWith(
F);
2556 A.eraseFromParent();
2566 if (
F.hasLocalLinkage())
2575 ScopedSaveAliaseesAndUsed S(M);
2576 for (
auto *
F : Defs)
2577 importFunction(
F,
true);
2578 for (
auto *
F : Decls)
2579 importFunction(
F,
false);
2582 for (
auto &[
F, Name] : PromotedFuncs)
2591 using GlobalClassesTy = EquivalenceClasses<
2592 PointerUnion<GlobalTypeMember *, Metadata *, ICallBranchFunnel *>>;
2593 GlobalClassesTy GlobalClasses;
2605 std::vector<GlobalTypeMember *> RefGlobals;
2607 DenseMap<Metadata *, TIInfo> TypeIdInfo;
2608 unsigned CurUniqueId = 0;
2611 struct ExportedFunctionInfo {
2615 MapVector<StringRef, ExportedFunctionInfo> ExportedFunctions;
2616 if (ExportSummary) {
2617 NamedMDNode *CfiFunctionsMD =
M.getNamedMetadata(
"cfi.functions");
2618 if (CfiFunctionsMD) {
2620 DenseSet<GlobalValue::GUID> AddressTaken;
2621 for (
auto &
I : *ExportSummary)
2622 for (
auto &GVS :
I.second.getSummaryList())
2624 for (
const auto &
Ref : GVS->refs()) {
2626 for (
auto &RefGVS :
Ref.getSummaryList())
2628 AddressTaken.
insert(Alias->getAliaseeGUID());
2631 if (AddressTaken.
count(GUID))
2633 auto VI = ExportSummary->getValueInfo(GUID);
2636 for (
auto &
I :
VI.getSummaryList())
2638 if (AddressTaken.
count(Alias->getAliaseeGUID()))
2642 for (
auto *FuncMD : CfiFunctionsMD->
operands()) {
2643 assert(FuncMD->getNumOperands() >= 2);
2644 StringRef FunctionName =
2649 ->getUniqueInteger()
2654 ->getUniqueInteger()
2658 if (!ExportSummary->isGUIDLive(GUID))
2661 if (!CrossDsoCfi ||
Linkage != CfiFunctionLinkage::Definition)
2665 if (
auto VI = ExportSummary->getValueInfo(GUID))
2666 for (
const auto &GVS :
VI.getSummaryList())
2673 auto P = ExportedFunctions.
insert({FunctionName, {
Linkage, FuncMD}});
2675 P.first->second.Linkage != CfiFunctionLinkage::Definition)
2676 P.first->second = {
Linkage, FuncMD};
2679 for (
const auto &
P : ExportedFunctions) {
2680 StringRef FunctionName =
P.first;
2681 CfiFunctionLinkage
Linkage =
P.second.Linkage;
2682 MDNode *FuncMD =
P.second.FuncMD;
2684 if (
F &&
F->hasLocalLinkage()) {
2691 F->setName(
F->getName() +
".1");
2697 FunctionType::get(Type::getVoidTy(
M.getContext()),
false),
2698 GlobalVariable::ExternalLinkage,
2699 M.getDataLayout().getProgramAddressSpace(), FunctionName, &M);
2701 LLVMContext::MD_guid,
2702 MDTuple::get(
M.getContext(), {FuncMD->getOperand(2).get()}));
2703 if (ExportSummary) {
2707 ->getUniqueInteger()
2709 if (
auto VI = ExportSummary->getValueInfo(GUID))
2711 VI.isDSOLocal(ExportSummary->withDSOLocalPropagation()));
2719 if (
F->hasAvailableExternallyLinkage()) {
2721 auto *OrigGUIDMD =
F->getMetadata(LLVMContext::MD_guid);
2724 F->setComdat(
nullptr);
2726 F->setMetadata(LLVMContext::MD_guid, OrigGUIDMD);
2731 if (
Linkage == CfiFunctionLinkage::Definition &&
2732 F->hasExternalWeakLinkage())
2739 if (
F->isDeclaration()) {
2740 if (
Linkage == CfiFunctionLinkage::WeakDeclaration)
2743 F->eraseMetadata(LLVMContext::MD_type);
2745 F->addMetadata(LLVMContext::MD_type,
2750 ->getUniqueInteger()
2758 struct AliasToCreate {
2760 std::string TargetName;
2762 std::vector<AliasToCreate> AliasesToCreate;
2766 if (ExportSummary) {
2767 if (NamedMDNode *AliasesMD =
M.getNamedMetadata(
"aliases")) {
2768 for (
auto *AliasMD : AliasesMD->operands()) {
2771 StringRef AliasName = MDS->getString();
2772 if (!ExportedFunctions.count(AliasName))
2774 auto *AliasF =
M.getFunction(AliasName);
2779 if (Aliases.
empty())
2782 for (
unsigned I = 1;
I != Aliases.
size(); ++
I) {
2783 auto *AliasF = Aliases[
I];
2784 ExportedFunctions.
erase(AliasF->getName());
2785 AliasesToCreate.push_back(
2786 {AliasF, std::string(Aliases[0]->
getName())});
2792 DenseMap<GlobalObject *, GlobalTypeMember *> GlobalTypeMembers;
2793 for (GlobalObject &GO :
M.global_objects()) {
2800 bool IsJumpTableCanonical =
false;
2801 bool IsExported =
false;
2804 if (
auto It = ExportedFunctions.find(
F->getName());
2805 It != ExportedFunctions.end()) {
2806 IsJumpTableCanonical |=
2807 It->second.Linkage == CfiFunctionLinkage::Definition;
2813 }
else if (!
F->hasAddressTaken()) {
2814 if (!CrossDsoCfi || !IsJumpTableCanonical ||
F->hasLocalLinkage())
2823 auto *GTM = GlobalTypeMember::create(
Alloc, &GO, IsJumpTableCanonical,
2825 GlobalTypeMembers[&GO] = GTM;
2826 for (MDNode *
Type : Types) {
2827 verifyTypeMDNode(&GO,
Type);
2828 auto &
Info = TypeIdInfo[
Type->getOperand(1)];
2829 Info.UniqueId = ++CurUniqueId;
2830 Info.RefGlobals.push_back(GTM);
2834 auto AddTypeIdUse = [&](
Metadata *TypeId) -> TypeIdUserInfo & {
2839 auto Ins = TypeIdUsers.
insert({TypeId, {}});
2842 auto &GCI = GlobalClasses.insert(TypeId);
2843 GlobalClassesTy::member_iterator CurSet = GlobalClasses.findLeader(GCI);
2846 for (GlobalTypeMember *GTM : TypeIdInfo[TypeId].RefGlobals)
2847 CurSet = GlobalClasses.unionSets(
2848 CurSet, GlobalClasses.findLeader(GlobalClasses.insert(GTM)));
2851 return Ins.first->second;
2855 for (
const Use &U : TypeTestFunc->
uses()) {
2864 for (
const Use &CIU : CI->
uses()) {
2867 OnlyAssumeUses =
false;
2876 auto TypeId = TypeIdMDVal->getMetadata();
2877 AddTypeIdUse(TypeId).CallSites.push_back(CI);
2881 if (ICallBranchFunnelFunc) {
2882 for (
const Use &U : ICallBranchFunnelFunc->
uses()) {
2885 "llvm.icall.branch.funnel not supported on this target");
2889 std::vector<GlobalTypeMember *> Targets;
2893 GlobalClassesTy::member_iterator CurSet;
2894 for (
unsigned I = 1;
I != CI->
arg_size();
I += 2) {
2900 "Expected branch funnel operand to be global value");
2902 auto It = GlobalTypeMembers.
find(
Base);
2903 if (It == GlobalTypeMembers.
end())
2905 "defined global value with type metadata");
2906 GlobalTypeMember *GTM = It->second;
2907 Targets.push_back(GTM);
2908 GlobalClassesTy::member_iterator NewSet =
2909 GlobalClasses.findLeader(GlobalClasses.insert(GTM));
2913 CurSet = GlobalClasses.unionSets(CurSet, NewSet);
2916 GlobalClasses.unionSets(
2917 CurSet, GlobalClasses.findLeader(
2918 GlobalClasses.insert(ICallBranchFunnel::create(
2919 Alloc, CI, Targets, ++CurUniqueId))));
2923 if (ExportSummary) {
2924 DenseMap<GlobalValue::GUID, TinyPtrVector<Metadata *>> MetadataByGUID;
2925 for (
auto &
P : TypeIdInfo) {
2928 TypeId->getString())]
2932 for (
auto &
P : *ExportSummary) {
2933 for (
auto &S :
P.second.getSummaryList()) {
2934 if (!ExportSummary->isGlobalValueLive(S.get()))
2939 AddTypeIdUse(MD).IsExported =
true;
2944 if (GlobalClasses.empty())
2948 ScopedSaveAliaseesAndUsed S(M);
2950 for (
const auto &
C : GlobalClasses) {
2954 ++NumTypeIdDisjointSets;
2956 std::vector<Metadata *> TypeIds;
2957 std::vector<GlobalTypeMember *> Globals;
2958 std::vector<ICallBranchFunnel *> ICallBranchFunnels;
2959 for (
auto M : GlobalClasses.members(*
C)) {
2972 return TypeIdInfo[
M1].UniqueId < TypeIdInfo[M2].UniqueId;
2977 [&](ICallBranchFunnel *F1, ICallBranchFunnel *F2) {
2978 return F1->UniqueId < F2->UniqueId;
2982 buildBitSetsFromDisjointSet(TypeIds, Globals, ICallBranchFunnels);
2986 allocateByteArrays();
2988 for (
auto A : AliasesToCreate) {
2989 auto *
Target =
M.getNamedValue(
A.TargetName);
2993 AliasGA->setVisibility(
A.Alias->getVisibility());
2994 AliasGA->setLinkage(
A.Alias->getLinkage());
2995 AliasGA->setDSOLocal(
A.Alias->isDSOLocal());
2996 AliasGA->takeName(
A.Alias);
2997 A.Alias->replaceAllUsesWith(AliasGA);
2998 A.Alias->eraseFromParent();
3002 if (ExportSummary) {
3003 if (NamedMDNode *SymversMD =
M.getNamedMetadata(
"symvers")) {
3004 for (
auto *Symver : SymversMD->operands()) {
3005 assert(Symver->getNumOperands() >= 2);
3008 StringRef Alias =
cast<MDString>(Symver->getOperand(1))->getString();
3010 if (!ExportedFunctions.count(SymbolName))
3013 M.appendModuleInlineAsm(
3014 (llvm::Twine(
".symver ") + SymbolName +
", " + Alias).str());
3026 Changed = LowerTypeTestsModule::runForTesting(M, AM);
3028 Changed = LowerTypeTestsModule(M, AM, ExportSummary, ImportSummary).lower();
3036 static_cast<PassInfoMixin<DropTypeTestsPass> *
>(
this)->
printPipeline(
3037 OS, MapClassName2PassName);
3040 case DropTestKind::Assume:
3043 case DropTestKind::All:
3076 for (
auto &GV : M.globals()) {
3083 auto MaySimplifyPtr = [&](
Value *Ptr) {
3085 if (
auto *CFIGV = M.getNamedValue((GV->
getName() +
".cfi").str()))
3089 auto MaySimplifyInt = [&](
Value *
Op) {
3091 if (!PtrAsInt || PtrAsInt->getOpcode() != Instruction::PtrToInt)
3093 return MaySimplifyPtr(PtrAsInt->getOperand(0));
3109 if (!CE || CE->getOpcode() != Instruction::PtrToInt)
3113 if (U.getOperandNo() == 0 && CE &&
3114 CE->getOpcode() == Instruction::Sub &&
3115 MaySimplifyInt(CE->getOperand(1))) {
3121 CE->replaceAllUsesWith(ConstantInt::get(CE->getType(), 0));
3125 if (U.getOperandNo() == 1 && CI &&
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file defines the BumpPtrAllocator interface.
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
Generic implementation of equivalence classes through the use Tarjan's efficient union-find algorithm...
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
This defines the Use class.
static const unsigned kARMJumpTableEntrySize
static const unsigned kLOONGARCH64JumpTableEntrySize
static bool isKnownTypeIdMember(Metadata *TypeId, const DataLayout &DL, Value *V, uint64_t COffset)
static const unsigned kX86IBTJumpTableEntrySize
static SmallVector< DILocation * > createJumpTableDebugInfo(Function *F, ArrayRef< GlobalTypeMember * > Functions)
static ConstantInt * extractNumericTypeId(MDNode &MD)
Extracts a numeric type identifier from an MDNode containing type metadata.
static const unsigned kRISCVJumpTableEntrySize
static auto buildBitSets(ArrayRef< Metadata * > TypeIds, const DenseMap< GlobalTypeMember *, uint64_t > &GlobalLayout)
static void dropTypeTests(Module &M, Function &TypeTestFunc, bool ShouldDropAll)
static Value * createMaskedBitTest(IRBuilder<> &B, Value *Bits, Value *BitOffset)
Build a test that bit BitOffset mod sizeof(Bits)*8 is set in Bits.
static bool isThumbFunction(Function *F, Triple::ArchType ModuleArch)
static const unsigned kX86JumpTableEntrySize
static void createCfiSymversMetadata(Module &DestM, const Module &SrcM)
static const unsigned kARMBTIJumpTableEntrySize
static CfiFunctionLinkage decodeCfiFunctionLinkage(uint8_t Encoded)
static void createCfiFunctionsMetadata(Module &DestM, ArrayRef< GlobalValue * > CfiFunctions, ProfileSummaryInfo &PSI, function_ref< const BlockFrequencyInfo &(Function &)> BFIGetter)
static BitSetInfo buildBitSet(ArrayRef< uint64_t > Offsets)
Build a bit set for list of offsets.
static const unsigned kARMv6MJumpTableEntrySize
static uint8_t encodeCfiFunctionLinkage(CfiFunctionLinkage Linkage, CfiFunctionHotness Hotness)
static CfiFunctionHotness decodeCfiFunctionHotness(uint8_t Encoded)
static const unsigned kHexagonJumpTableEntrySize
static void createCfiAliasesMetadata(Module &DestM, const Module &SrcM)
Machine Check Debug Module
This file implements a map that provides insertion order iteration.
ModuleSummaryIndex.h This file contains the declarations the classes that hold the module index and s...
FunctionAnalysisManager FAM
This file defines the PointerUnion class, which is a discriminated union of pointer types.
This file contains the declarations for profiling metadata utility functions.
static StringRef getName(Value *V)
This file implements a set that has insertion order iteration characteristics.
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)
This header defines support for implementing classes that have some trailing object (or arrays of obj...
static bool isDirectCall(const MCInst &Inst)
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
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.
bool empty() const
Check if the array is empty.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
Functions, function parameters, and return types can have attributes to indicate how they should be t...
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.
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
Value * getArgOperand(unsigned i) const
unsigned arg_size() const
void addSymbolWithThinLTOGUID(StringRef Name, GlobalValue::GUID GUID)
Add the function name and the GUID that ThinLTO uses for it.
bool contains(StringRef Name) const
static CondBrInst * Create(Value *Cond, BasicBlock *IfTrue, BasicBlock *IfFalse, InsertPosition InsertBefore=nullptr)
static LLVM_ABI ConstantAggregateZero * get(Type *Ty)
ConstantArray - Constant Array Declarations.
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 LLVM_ABI Constant * getPointerCast(Constant *C, Type *Ty)
Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.
static LLVM_SUPPRESS_DEPRECATED_DECLARATIONS_POP Constant * getInBoundsPtrAdd(Constant *Ptr, Constant *Offset)
Create a getelementptr inbounds i8, ptr, offset constant expression.
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_SUPPRESS_DEPRECATED_DECLARATIONS_PUSH Constant * getGetElementPtr(Type *Ty, Constant *C, ArrayRef< Constant * > IdxList, GEPNoWrapFlags NW=GEPNoWrapFlags::none(), std::optional< ConstantRange > InRange=std::nullopt, Type *OnlyIfReducedTy=nullptr)
Getelementptr form.
This is the shared class of boolean and integer constants.
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
static LLVM_ABI ConstantInt * getFalse(LLVMContext &Context)
static LLVM_ABI ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
static Constant * getAnon(ArrayRef< Constant * > V, bool Packed=false)
Return an anonymous struct that has the specified elements.
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
LLVM_ABI void finalize()
Construct any deferred debug info descriptors.
LLVM_ABI DISubroutineType * createSubroutineType(DITypeArray ParameterTypes, DINode::DIFlags Flags=DINode::FlagZero, unsigned CC=0)
Create subroutine type.
LLVM_ABI DISubprogram * createFunction(DIScope *Scope, StringRef Name, StringRef LinkageName, DIFile *File, unsigned LineNo, DISubroutineType *Ty, unsigned ScopeLine, DINode::DIFlags Flags=DINode::FlagZero, DISubprogram::DISPFlags SPFlags=DISubprogram::SPFlagZero, DITemplateParameterArray TParams=nullptr, DISubprogram *Decl=nullptr, DITypeArray ThrownTypes=nullptr, DINodeArray Annotations=nullptr, StringRef TargetFuncName="", bool UseKeyInstructions=false)
Create a new descriptor for the specified subprogram.
LLVM_ABI DICompileUnit * createCompileUnit(DISourceLanguageName Lang, DIFile *File, StringRef Producer, bool isOptimized, StringRef Flags, unsigned RV, StringRef SplitName=StringRef(), DICompileUnit::DebugEmissionKind Kind=DICompileUnit::DebugEmissionKind::FullDebug, uint64_t DWOId=0, bool SplitDebugInlining=true, bool DebugInfoForProfiling=false, DICompileUnit::DebugNameTableKind NameTableKind=DICompileUnit::DebugNameTableKind::Default, bool RangesBaseAddress=false, StringRef SysRoot={}, StringRef SDK={})
A CompileUnit provides an anchor for all debugging information generated during this instance of comp...
LLVM_ABI DIFile * createFile(StringRef Filename, StringRef Directory, std::optional< DIFile::ChecksumInfo< StringRef > > Checksum=std::nullopt, std::optional< StringRef > Source=std::nullopt)
Create a file descriptor to hold debugging information for a file.
Wrapper structure that holds source language identity metadata that includes language name,...
Subprogram description. Uses SubclassData1.
Type array for a subprogram.
A parsed version of the target data layout string in and methods for querying it.
iterator find(const_arg_type_t< KeyT > Val)
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Analysis pass which computes a DominatorTree.
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
LLVM_ABI void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
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)
const BasicBlock & getEntryBlock() const
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
static GEPNoWrapFlags inBounds()
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 void setComdat(Comdat *C)
LLVM_ABI void setSection(StringRef S)
Change the section for this global.
const Comdat * getComdat() const
LLVM_ABI bool eraseMetadata(unsigned KindID)
Erase all metadata attachments with the given kind.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this GlobalObject.
bool hasSection() const
Check if this global has a custom object file section.
static LLVM_ABI GUID getGUIDAssumingExternalLinkage(StringRef GlobalName)
Return a 64-bit global unique ID constructed from the name of a global symbol.
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
VisibilityTypes getVisibility() const
static bool isLocalLinkage(LinkageTypes Linkage)
LinkageTypes getLinkage() const
uint64_t GUID
Declare a type to represent a global unique identifier for a global value.
bool isDeclarationForLinker() const
void setDSOLocal(bool Local)
PointerType * getType() const
Global values are always pointers.
VisibilityTypes
An enumeration for the kinds of visibility of global values.
@ HiddenVisibility
The GV is hidden.
void setVisibility(VisibilityTypes V)
LinkageTypes
An enumeration for the kinds of linkage for global values.
@ PrivateLinkage
Like Internal, but omit from symbol table.
@ InternalLinkage
Rename collisions when linking (static functions).
@ ExternalLinkage
Externally visible function.
@ ExternalWeakLinkage
ExternalWeak linkage description.
Type * getValueType() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
LLVM_ABI void setInitializer(Constant *InitVal)
setInitializer - Sets the initializer for this global variable, removing any existing initializer if ...
bool hasInitializer() const
Definitions have initializers, declarations don't.
MaybeAlign getAlign() const
Returns the alignment of the given variable.
void setConstant(bool Val)
LLVM_ABI void setCodeModel(CodeModel::Model CM)
Change the code model for this global.
LLVM_ABI void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
LLVM_ABI CallInst * CreateIntrinsicWithoutFolding(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={})
Create a call to intrinsic ID with Args, mangled using OverloadTypes.
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
Value * CreatePtrAddWithSExtOrTrunc(Value *Ptr, Value *Offset, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
Create a ptradd where the offset is sign-extended or truncated to the index type.
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
static LLVM_ABI InlineAsm * get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, bool isAlignStack=false, AsmDialect asmDialect=AD_ATT, bool canThrow=false)
InlineAsm::get - Return the specified uniqued inline asm string.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
iterator_range< user_iterator > users()
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
user_iterator user_begin()
Analysis pass that exposes the LoopInfo for a function.
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
const MDOperand & getOperand(unsigned I) const
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
unsigned getNumOperands() const
Return number of MDNode operands.
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
This class implements a map that also provides access to all stored values in a deterministic order.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
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,...
TypeIdSummary & getOrInsertTypeIdSummary(StringRef TypeId)
Return an existing or new TypeIdSummary entry for TypeId.
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 ...
CfiFunctionIndex & cfiFunctionDecls()
bool partiallySplitLTOUnits() const
CfiFunctionIndex & cfiFunctionDefs()
static LLVM_ABI void CollectAsmSymvers(const Module &M, function_ref< void(StringRef, StringRef)> AsmSymver)
Parse inline ASM and collect the symvers directives that are defined in the current module.
A Module instance is used to store all the information related to an LLVM module.
LLVMContext & getContext() const
Get the global data context.
Function * getFunction(StringRef Name) const
Look up the specified function in the module symbol table.
iterator_range< alias_iterator > aliases()
NamedMDNode * getOrInsertNamedMetadata(StringRef Name)
Return the named MDNode in the module with the specified name.
iterator_range< op_iterator > operands()
LLVM_ABI void addOperand(MDNode *M)
static PointerType * getUnqual(LLVMContext &C)
This constructs an opaque pointer to an object in the default address space (address space zero).
unsigned getAddressSpace() const
Return the address space of the Pointer type.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Analysis pass which computes a PostDominatorTree.
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.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
Analysis providing profile information.
bool isFunctionColdInCallGraph(const FuncT *F, BFIT &BFI) const
Returns true if F contains only cold code.
LLVM_ABI bool isFunctionHotnessUnknown(const Function &F) const
Returns true if the hotness of F is unknown.
bool isFunctionHotInCallGraph(const FuncT *F, BFIT &BFI) const
Returns true if F contains hot code.
LLVM_ABI bool hasPartialSampleProfile() const
Returns true if module M has partial-profile sample profile.
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, InsertPosition InsertBefore=nullptr)
LLVM_ABI void print(const char *ProgName, raw_ostream &S, bool ShowColors=true, bool ShowKindLabel=true, bool ShowLocation=true) const
A vector that has set insertion semantics.
bool insert(const value_type &X)
Insert a new element into the SetVector.
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
iterator erase(const_iterator CI)
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.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
bool consume_back(StringRef Suffix)
Returns true if this StringRef has the given suffix and removes that suffix.
std::string str() const
Get the contents as an std::string.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
Check if the string is empty.
constexpr size_t size() const
Get the string size.
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
Type * getElementType(unsigned N) const
Analysis pass providing the TargetTransformInfo.
See the file comment for details on the usage of the TrailingObjects type.
Triple - Helper class for working with autoconf configuration names.
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
A Use represents the edge between a Value definition and its users.
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
LLVM_ABI bool replaceUsesWithIf(Value *New, llvm::function_ref< bool(Use &U)> ShouldReplace)
Go through the uses list for this definition and make each use point to "V" if the callback ShouldRep...
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
void insert_range(Range &&R)
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()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
This class implements a layout algorithm for globals referenced by bit sets that tries to keep member...
LLVM_ABI const std::vector< uint64_t > & build()
Flatten fragments into a single layout and return it.
LLVM_ABI void addFragment(const std::set< uint64_t > &F)
Add F to the layout while trying to keep its indices contiguous.
This class implements an extremely fast bulk output stream that can only output to a stream.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ 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 SetVector< uint64_t > findCfiTypeIds(const Module &M)
Finds all 64-bit numeric type identifiers in M used for cross-DSO CFI.
LLVM_ABI bool cleanUpTypeCheckedLoad(Module &M, Function &CheckedLoadFn, bool IsRelative)
Lower @llvm.type.checked.load[.relative] calls to the guarded load with the check assumed true,...
LLVM_ABI void createCfiMetadata(Module &DestM, const Module &SrcM, ArrayRef< GlobalValue * > CfiFunctions, ProfileSummaryInfo &PSI, function_ref< const BlockFrequencyInfo &(Function &)> BFIGetter)
Creates cfi.functions, aliases, and symvers named metadata in DestM for CFI functions in CfiFunctions...
LLVM_ABI bool isJumpTableCanonical(Function *F)
LLVM_ABI bool hasTypeMetadata(const GlobalObject &GO)
Returns whether a global or its associated global has attached type metadata.
LLVM_ABI SetVector< GlobalValue * > findCfiFunctions(Module &M)
Finds all functions and aliases in M that may need CFI jump table entries.
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract_or_null(Y &&MD)
Extract a Value from Metadata, allowing null.
SmallVector< unsigned char, 0 > ByteArray
NodeAddr< PhiNode * > Phi
NodeAddr< UseNode * > Use
@ OF_TextWithCRLF
The file should be opened in text mode and use a carriage linefeed '\r '.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void ReplaceInstWithInst(BasicBlock *BB, BasicBlock::iterator &BI, Instruction *I)
Replace the instruction specified by BI with the instruction specified by I.
bool operator<(int64_t V1, const APSInt &V2)
void stable_sort(R &&Range)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
detail::zip_longest_range< T, U, Args... > zip_longest(T &&t, U &&u, Args &&... args)
Iterate over two or more iterators at the same time.
@ Unknown
Not known to have no common set bits.
LLVM_ABI void setExplicitlyUnknownBranchWeightsIfProfiled(Instruction &I, StringRef PassName, const Function *F=nullptr)
Like setExplicitlyUnknownBranchWeights(...), but only sets unknown branch weights in the new instruct...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
@ Load
The value being inserted comes from a load (InsertElement only).
PassSummaryAction
What to do with the summary when running passes that operate on it.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Value * GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, const DataLayout &DL, bool AllowNonInbounds=true)
Analyze the specified pointer to see if it can be expressed as a base pointer plus a constant offset.
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.
@ O1
Optimize quickly without destroying debuggability.
@ O2
Optimize for fast execution as much as possible without triggering significant incremental compile ti...
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
unsigned M1(unsigned Val)
auto make_isa_range(RangeT &&Range)
Return a range over Range containing only elements for which isa<T> holds, casting each of them to T.
auto dyn_cast_or_null(const Y &Val)
LLVM_ABI bool convertUsersOfConstantsToInstructions(ArrayRef< Constant * > Consts, Function *RestrictToFunc=nullptr, bool RemoveDeadConstants=true, bool IncludeSelf=false)
Replace constant expressions users of the given constants with instructions.
const IPOOptions & getIPOOptions(const LLVMContext &C)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
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 raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Ref
The access may reference the value stored in memory.
LLVM_ABI void appendToCompilerUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.compiler.used list.
DWARFExpression::Operation Op
bool isMemProfClone(const GlobalValue &GV)
Returns true if GV is a MemProf context-disambiguated clone.
Expected< T > errorOrToExpected(ErrorOr< T > &&EO)
Convert an ErrorOr<T> to an Expected<T>.
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
constexpr unsigned BitWidth
LLVM_ABI void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Append F to the list of global ctors of module M with the given Priority.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
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 ...
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
LLVM_ABI void appendToUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.used list.
LLVM_ABI std::unique_ptr< ModuleSummaryIndex > parseSummaryIndexAssembly(MemoryBufferRef F, SMDiagnostic &Err)
Parse LLVM Assembly for summary index from a MemoryBuffer.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
LLVM_ABI GlobalVariable * collectUsedGlobalVariables(const Module &M, SmallVectorImpl< GlobalValue * > &Vec, bool CompilerUsed)
Given "llvm.used" or "llvm.compiler.used" as a global name, collect the initializer elements of that ...
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Kind
Specifies which kind of type check we should emit for this byte array.
@ Unknown
Unknown (analysis not performed, don't lower)
@ Single
Single element (last example in "Short Inline Bit Vectors")
@ Inline
Inlined bit vector ("Short Inline Bit Vectors")
@ Unsat
Unsatisfiable type (i.e. no global has this type metadata)
@ AllOnes
All-ones bit vector ("Eliminating Bit Vector Checks for All-Ones Bit Vectors")
@ ByteArray
Test a byte array (first example)
unsigned SizeM1BitWidth
Range of size-1 expressed as a bit width.
enum llvm::TypeTestResolution::Kind TheKind
LLVM_ABI BitSetInfo build()
SmallVector< uint64_t, 16 > Offsets
LLVM_ABI bool containsGlobalOffset(uint64_t Offset) const
LLVM_ABI void print(raw_ostream &OS) const
std::set< uint64_t > Bits
This class is used to build a byte array containing overlapping bit sets.
uint64_t BitAllocs[BitsPerByte]
The number of bytes allocated so far for each of the bits.
std::vector< uint8_t > Bytes
The byte array built so far.
LLVM_ABI void allocate(const std::set< uint64_t > &Bits, uint64_t BitSize, uint64_t &AllocByteOffset, uint8_t &AllocMask)
Allocate BitSize bits in the byte array where Bits contains the bits to set.