36#define DEBUG_TYPE "expand-memcmp"
39STATISTIC(NumMemCmpNotConstant,
"Number of memcmp calls without constant size");
41 "Number of memcmp calls with size greater than max size");
42STATISTIC(NumMemCmpInlined,
"Number of inlined memcmp calls");
46 cl::desc(
"The number of loads per basic block for inline expansion of "
51 cl::desc(
"Set maximum number of loads used in expanded memcmp"));
55 cl::desc(
"Set maximum number of loads used in expanded memcmp for -Os/Oz"));
62static Align getMemCmpArgAlignment(
const CallInst *CI,
unsigned ArgNo,
66 A = std::max(
A, *ParamAlign);
72class MemCmpExpansion {
80 PHINode *PhiSrc1 =
nullptr;
81 PHINode *PhiSrc2 =
nullptr;
83 ResultBlock() =
default;
86 CallInst *
const CI =
nullptr;
89 unsigned MaxLoadSize = 0;
91 const unsigned MaxBytesPerBlock;
92 unsigned MaxBlockSize = 0;
93 std::vector<BasicBlock *> LoadCmpBlocks;
95 PHINode *PhiRes =
nullptr;
96 const bool IsUsedForZeroCmp;
98 const TargetTransformInfo &TTI;
100 const Align CommonAlign;
101 DomTreeUpdater *DTU =
nullptr;
107 LoadEntry(
unsigned LoadSize,
uint64_t Offset)
108 : LoadSize(LoadSize), Offset(Offset) {
116 using LoadEntryVector = SmallVector<LoadEntry, 8>;
117 LoadEntryVector LoadSequence;
119 void createLoadCmpBlocks();
120 void createResultBlock();
121 void setupResultBlockPHINodes();
122 void setupEndBlockPHINodes();
123 Value *getCompareLoadPairs(
unsigned BlockIndex,
unsigned &LoadIndex);
124 LoadPair getPackedLoadPair(
unsigned BlockIndex,
unsigned &LoadIndex);
125 void emitLoadCompareBlock(
unsigned BlockIndex,
unsigned &LoadIndex);
126 void emitLoadCompareBlockMultipleLoads(
unsigned BlockIndex,
127 unsigned &LoadIndex);
128 void emitLoadCompareByteBlock(
unsigned BlockIndex,
unsigned OffsetBytes);
129 void emitMemCmpResultBlock();
130 Value *getMemCmpExpansionZeroCase();
131 Value *getMemCmpEqZeroOneBlock();
132 Value *getMemCmpOneBlock();
133 Value *getMemCmpOneBlockMultipleLoads();
134 Value *getMemCmpResult(
const LoadPair &Loads);
135 LoadPair getLoadPair(
Type *LoadSizeType,
Type *BSwapSizeType,
136 Type *CmpSizeType,
unsigned OffsetBytes);
144 static LoadEntryVector
145 computeGreedyLoadSequence(
uint64_t Size, llvm::ArrayRef<unsigned> LoadSizes,
146 unsigned MaxNumLoads);
147 LoadEntryVector computeOverlappingLoadSequence(
uint64_t Size,
148 unsigned MaxLoadSize,
149 unsigned MaxNumLoads)
const;
151 void optimiseLoadSequence(
152 LoadEntryVector &LoadSequence,
153 const TargetTransformInfo::MemCmpExpansionOptions &
Options,
154 bool IsUsedForZeroCmp)
const;
157 MemCmpExpansion(CallInst *CI,
uint64_t Size,
158 const TargetTransformInfo::MemCmpExpansionOptions &
Options,
159 const bool IsUsedForZeroCmp,
const DataLayout &TheDataLayout,
160 DomTreeUpdater *DTU,
const TargetTransformInfo &TTI,
161 Align CommonAlign,
unsigned MaxBytesPerBlock);
163 unsigned getNumBlocks();
164 unsigned getNumLoadsInBlock(
unsigned LoadIndex)
const;
165 unsigned getNumBytesInBlock(
unsigned LoadIndex,
unsigned NumLoads)
const;
166 uint64_t getNumLoads()
const {
return LoadSequence.size(); }
168 Value *getMemCmpExpansion();
178 Align CommonAlign,
unsigned LoadSize,
186 if (AccessAlign.
value() >= LoadSize)
189 return TTI.allowsMisalignedMemoryAccesses(CI->
getContext(), LoadSize * 8, AS,
197bool MemCmpExpansion::isAccessAllowed(
unsigned LoadSize,
199 return ::isAccessAllowed(CI,
TTI, CommonAlign, LoadSize,
Offset);
202MemCmpExpansion::LoadEntryVector
203MemCmpExpansion::computeGreedyLoadSequence(
uint64_t Size,
204 llvm::ArrayRef<unsigned> LoadSizes,
205 const unsigned MaxNumLoads) {
206 LoadEntryVector LoadSequence;
209 const unsigned LoadSize = LoadSizes.
front();
211 if (LoadSequence.size() + NumLoadsForThisSize > MaxNumLoads) {
218 if (NumLoadsForThisSize > 0) {
219 for (
uint64_t I = 0;
I < NumLoadsForThisSize; ++
I) {
220 LoadSequence.push_back({LoadSize,
Offset});
230MemCmpExpansion::LoadEntryVector
231MemCmpExpansion::computeOverlappingLoadSequence(
233 const unsigned MaxNumLoads)
const {
235 if (
Size < 2 || MaxLoadSize < 2)
240 const uint64_t NumNonOverlappingLoads =
Size / MaxLoadSize;
241 assert(NumNonOverlappingLoads &&
"there must be at least one load");
244 Size =
Size - NumNonOverlappingLoads * MaxLoadSize;
251 if ((NumNonOverlappingLoads + 1) > MaxNumLoads)
255 LoadEntryVector LoadSequence;
257 for (
uint64_t I = 0;
I < NumNonOverlappingLoads; ++
I) {
258 LoadSequence.push_back({MaxLoadSize,
Offset});
266 if (!isAccessAllowed(MaxLoadSize, OverlapOffset))
269 LoadSequence.push_back({MaxLoadSize, OverlapOffset});
273void MemCmpExpansion::optimiseLoadSequence(
274 LoadEntryVector &LoadSequence,
275 const TargetTransformInfo::MemCmpExpansionOptions &
Options,
276 bool IsUsedForZeroCmp)
const {
281 if (IsUsedForZeroCmp ||
Options.AllowedTailExpansions.empty())
284 while (LoadSequence.size() >= 2) {
285 auto Last = LoadSequence[LoadSequence.size() - 1];
286 auto PreLast = LoadSequence[LoadSequence.size() - 2];
289 if (PreLast.Offset + PreLast.LoadSize !=
Last.Offset)
292 auto LoadSize =
Last.LoadSize + PreLast.LoadSize;
293 if (
find(
Options.AllowedTailExpansions, LoadSize) ==
294 Options.AllowedTailExpansions.end())
303 if (LoadSize > MaxLoadSize && LoadSequence.size() > 2)
307 LoadSequence.pop_back();
308 LoadSequence.pop_back();
309 LoadSequence.emplace_back(LoadSize, PreLast.Offset);
321MemCmpExpansion::MemCmpExpansion(
323 const TargetTransformInfo::MemCmpExpansionOptions &
Options,
324 const bool IsUsedForZeroCmp,
const DataLayout &TheDataLayout,
325 DomTreeUpdater *DTU,
const TargetTransformInfo &
TTI, Align CommonAlign,
326 unsigned MaxBytesPerBlock)
328 MaxBytesPerBlock(MaxBytesPerBlock), IsUsedForZeroCmp(IsUsedForZeroCmp),
329 DL(TheDataLayout),
TTI(
TTI), CommonAlign(CommonAlign), DTU(DTU),
332 assert(NumLoadsPerBlock > 0 &&
"zero loads per block");
338 assert(!LoadSizes.
empty() &&
"cannot load Size bytes");
339 MaxLoadSize = LoadSizes.
front();
342 computeGreedyLoadSequence(
Size, LoadSizes,
Options.MaxNumLoads);
343 assert(LoadSequence.size() <=
Options.MaxNumLoads &&
"broken invariant");
346 if (
Options.AllowOverlappingLoads &&
347 (LoadSequence.empty() || LoadSequence.size() > 2)) {
348 auto OverlappingLoads =
349 computeOverlappingLoadSequence(
Size, MaxLoadSize,
Options.MaxNumLoads);
350 if (!OverlappingLoads.empty() &&
351 (LoadSequence.empty() ||
352 OverlappingLoads.size() < LoadSequence.size())) {
353 LoadSequence = OverlappingLoads;
356 assert(LoadSequence.size() <=
Options.MaxNumLoads &&
"broken invariant");
357 optimiseLoadSequence(LoadSequence,
Options, IsUsedForZeroCmp);
359 unsigned LoadIndex = 0;
360 while (LoadIndex < getNumLoads()) {
361 unsigned NumLoads = getNumLoadsInBlock(LoadIndex);
363 std::max(MaxBlockSize, getNumBytesInBlock(LoadIndex, NumLoads));
364 LoadIndex += NumLoads;
370unsigned MemCmpExpansion::getNumLoadsInBlock(
unsigned LoadIndex)
const {
371 if (IsUsedForZeroCmp)
372 return std::min<uint64_t>(getNumLoads() - LoadIndex, NumLoadsPerBlock);
374 unsigned NumLoads = 0;
375 unsigned NumBytes = 0;
376 while (LoadIndex + NumLoads < getNumLoads() && NumLoads < NumLoadsPerBlock &&
377 NumBytes + LoadSequence[LoadIndex + NumLoads].LoadSize <=
379 NumBytes += LoadSequence[LoadIndex + NumLoads].LoadSize;
382 assert(NumLoads &&
"at least one load must fit in a block");
386unsigned MemCmpExpansion::getNumBytesInBlock(
unsigned LoadIndex,
387 unsigned NumLoads)
const {
388 unsigned NumBytes = 0;
389 for (
unsigned I = 0;
I != NumLoads; ++
I)
390 NumBytes += LoadSequence[LoadIndex +
I].LoadSize;
394unsigned MemCmpExpansion::getNumBlocks() {
395 unsigned NumBlocks = 0;
396 for (
unsigned LoadIndex = 0; LoadIndex < getNumLoads(); ++NumBlocks)
397 LoadIndex += getNumLoadsInBlock(LoadIndex);
401void MemCmpExpansion::createLoadCmpBlocks() {
402 for (
unsigned i = 0; i < getNumBlocks(); i++) {
405 LoadCmpBlocks.push_back(BB);
409void MemCmpExpansion::createResultBlock() {
414MemCmpExpansion::LoadPair MemCmpExpansion::getLoadPair(
Type *LoadSizeType,
417 unsigned OffsetBytes) {
421 Align LhsAlign = getMemCmpArgAlignment(CI, 0,
DL);
422 Align RhsAlign = getMemCmpArgAlignment(CI, 1,
DL);
423 if (OffsetBytes > 0) {
424 auto *ByteType = Type::getInt8Ty(CI->
getContext());
432 Value *Lhs =
nullptr;
438 Value *Rhs =
nullptr;
445 if (BSwapSizeType && LoadSizeType != BSwapSizeType) {
453 CI->
getModule(), Intrinsic::bswap, BSwapSizeType);
459 if (CmpSizeType !=
nullptr && CmpSizeType != Lhs->
getType()) {
470void MemCmpExpansion::emitLoadCompareByteBlock(
unsigned BlockIndex,
471 unsigned OffsetBytes) {
474 const LoadPair Loads =
475 getLoadPair(Type::getInt8Ty(CI->
getContext()),
nullptr,
476 Type::getInt32Ty(CI->
getContext()), OffsetBytes);
481 if (BlockIndex < (LoadCmpBlocks.size() - 1)) {
485 ConstantInt::get(Diff->
getType(), 0));
486 Builder.
CreateCondBr(Cmp, EndBlock, LoadCmpBlocks[BlockIndex + 1]);
489 {{DominatorTree::Insert, BB, EndBlock},
490 {DominatorTree::Insert, BB, LoadCmpBlocks[BlockIndex + 1]}});
495 DTU->
applyUpdates({{DominatorTree::Insert, BB, EndBlock}});
502Value *MemCmpExpansion::getCompareLoadPairs(
unsigned BlockIndex,
503 unsigned &LoadIndex) {
504 assert(LoadIndex < getNumLoads() &&
505 "getCompareLoadPairs() called with no remaining loads");
506 std::vector<Value *> XorList, OrList;
507 Value *Diff =
nullptr;
509 const unsigned NumLoads = getNumLoadsInBlock(LoadIndex);
512 if (LoadCmpBlocks.empty())
521 IntegerType *
const MaxLoadType =
522 NumLoads == 1 ? nullptr
525 for (
unsigned i = 0; i < NumLoads; ++i, ++LoadIndex) {
526 const LoadEntry &CurLoadEntry = LoadSequence[LoadIndex];
527 const LoadPair Loads = getLoadPair(
529 MaxLoadType, CurLoadEntry.Offset);
534 Diff = Builder.
CreateXor(Loads.Lhs, Loads.Rhs);
536 XorList.push_back(Diff);
543 auto pairWiseOr = [&](std::vector<Value *> &InList) -> std::vector<Value *> {
544 std::vector<Value *> OutList;
545 for (
unsigned i = 0; i < InList.size() - 1; i = i + 2) {
547 OutList.push_back(
Or);
549 if (InList.size() % 2 != 0)
550 OutList.push_back(InList.back());
556 OrList = pairWiseOr(XorList);
559 while (OrList.size() != 1) {
560 OrList = pairWiseOr(OrList);
563 assert(Diff &&
"Failed to find comparison diff");
570MemCmpExpansion::LoadPair
571MemCmpExpansion::getPackedLoadPair(
unsigned BlockIndex,
unsigned &LoadIndex) {
572 assert(LoadIndex < getNumLoads() &&
573 "getPackedLoadPair() called with no remaining loads");
574 if (LoadCmpBlocks.empty())
579 const unsigned NumLoads = getNumLoadsInBlock(LoadIndex);
580 const unsigned NumBytes = getNumBytesInBlock(LoadIndex, NumLoads);
585 Value *PackedLhs = ConstantInt::get(BlockType, 0);
586 Value *PackedRhs = ConstantInt::get(BlockType, 0);
587 unsigned RemainingBytes = NumBytes;
589 for (
unsigned I = 0;
I != NumLoads; ++
I, ++LoadIndex) {
590 const LoadEntry &
Entry = LoadSequence[LoadIndex];
592 auto *BSwapType =
DL.isLittleEndian() &&
Entry.LoadSize != 1
596 LoadPair Loads = getLoadPair(LoadType, BSwapType, BlockType,
Entry.Offset);
598 if (BSwapType && BSwapType->getIntegerBitWidth() !=
Entry.LoadSize * 8) {
599 unsigned Padding = BSwapType->getIntegerBitWidth() -
Entry.LoadSize * 8;
600 Loads.Lhs = Builder.
CreateLShr(Loads.Lhs, Padding);
601 Loads.Rhs = Builder.
CreateLShr(Loads.Rhs, Padding);
604 RemainingBytes -=
Entry.LoadSize;
605 unsigned Shift = RemainingBytes * 8;
612 return {PackedLhs, PackedRhs};
615void MemCmpExpansion::emitLoadCompareBlockMultipleLoads(
unsigned BlockIndex,
616 unsigned &LoadIndex) {
617 Value *
Cmp = getCompareLoadPairs(BlockIndex, LoadIndex);
619 BasicBlock *NextBB = (BlockIndex == (LoadCmpBlocks.size() - 1))
621 : LoadCmpBlocks[BlockIndex + 1];
625 CondBrInst *CmpBr = Builder.
CreateCondBr(Cmp, ResBlock.BB, NextBB);
629 DTU->
applyUpdates({{DominatorTree::Insert, BB, ResBlock.BB},
630 {DominatorTree::Insert, BB, NextBB}});
635 if (BlockIndex == LoadCmpBlocks.size() - 1) {
637 PhiRes->
addIncoming(Zero, LoadCmpBlocks[BlockIndex]);
650void MemCmpExpansion::emitLoadCompareBlock(
unsigned BlockIndex,
651 unsigned &LoadIndex) {
652 const unsigned NumLoads = getNumLoadsInBlock(LoadIndex);
653 if (NumLoads == 1 && LoadSequence[LoadIndex].LoadSize == 1) {
654 MemCmpExpansion::emitLoadCompareByteBlock(BlockIndex,
655 LoadSequence[LoadIndex].
Offset);
662 const LoadEntry &
Entry = LoadSequence[LoadIndex++];
664 auto *BSwapType =
DL.isLittleEndian()
670 Loads = getLoadPair(LoadType, BSwapType, CmpType,
Entry.Offset);
672 Loads = getPackedLoadPair(BlockIndex, LoadIndex);
677 if (!IsUsedForZeroCmp) {
678 ResBlock.PhiSrc1->addIncoming(Loads.Lhs, LoadCmpBlocks[BlockIndex]);
679 ResBlock.PhiSrc2->addIncoming(Loads.Rhs, LoadCmpBlocks[BlockIndex]);
683 BasicBlock *NextBB = (BlockIndex == (LoadCmpBlocks.size() - 1))
685 : LoadCmpBlocks[BlockIndex + 1];
689 CondBrInst *CmpBr = Builder.
CreateCondBr(Cmp, NextBB, ResBlock.BB);
694 {DominatorTree::Insert, BB, ResBlock.BB}});
699 if (BlockIndex == LoadCmpBlocks.size() - 1) {
701 PhiRes->
addIncoming(Zero, LoadCmpBlocks[BlockIndex]);
708void MemCmpExpansion::emitMemCmpResultBlock() {
711 if (IsUsedForZeroCmp) {
718 DTU->
applyUpdates({{DominatorTree::Insert, ResBlock.BB, EndBlock}});
736 DTU->
applyUpdates({{DominatorTree::Insert, ResBlock.BB, EndBlock}});
739void MemCmpExpansion::setupResultBlockPHINodes() {
742 ResBlock.PhiSrc1 = Builder.
CreatePHI(MaxLoadType, getNumBlocks(),
"phi.src1");
743 ResBlock.PhiSrc2 = Builder.
CreatePHI(MaxLoadType, getNumBlocks(),
"phi.src2");
746void MemCmpExpansion::setupEndBlockPHINodes() {
751Value *MemCmpExpansion::getMemCmpExpansionZeroCase() {
752 unsigned LoadIndex = 0;
755 for (
unsigned I = 0;
I < getNumBlocks(); ++
I) {
756 emitLoadCompareBlockMultipleLoads(
I, LoadIndex);
759 emitMemCmpResultBlock();
766Value *MemCmpExpansion::getMemCmpEqZeroOneBlock() {
767 unsigned LoadIndex = 0;
768 Value *
Cmp = getCompareLoadPairs(0, LoadIndex);
769 assert(LoadIndex == getNumLoads() &&
"some entries were not consumed");
778Value *MemCmpExpansion::getMemCmpOneBlock() {
779 bool NeedsBSwap =
DL.isLittleEndian() &&
Size != 1;
781 Type *BSwapSizeType =
791 const LoadPair Loads = getLoadPair(LoadSizeType, BSwapSizeType,
793 return Builder.
CreateSub(Loads.Lhs, Loads.Rhs);
796 const LoadPair Loads = getLoadPair(LoadSizeType, BSwapSizeType, MaxLoadType,
799 return getMemCmpResult(Loads);
802Value *MemCmpExpansion::getMemCmpOneBlockMultipleLoads() {
803 unsigned LoadIndex = 0;
804 LoadPair Loads = getPackedLoadPair(0, LoadIndex);
805 assert(LoadIndex == getNumLoads() &&
"some entries were not consumed");
806 return getMemCmpResult(Loads);
809Value *MemCmpExpansion::getMemCmpResult(
const LoadPair &Loads) {
815 CmpPredicate Pred = ICmpInst::Predicate::BAD_ICMP_PREDICATE;
816 bool NeedsZExt =
false;
825 Pred = ICmpInst::ICMP_SLT;
830 Pred = ICmpInst::ICMP_SGE;
834 Pred = ICmpInst::ICMP_SLE;
840 if (ICmpInst::isSigned(Pred)) {
842 Loads.Lhs, Loads.Rhs);
844 UI->replaceAllUsesWith(Result);
845 UI->eraseFromParent();
853 {Loads.Lhs, Loads.Rhs});
858Value *MemCmpExpansion::getMemCmpExpansion() {
860 if (getNumBlocks() != 1) {
862 EndBlock =
SplitBlock(StartBlock, CI, DTU,
nullptr,
863 nullptr,
"endblock");
864 setupEndBlockPHINodes();
871 if (!IsUsedForZeroCmp) setupResultBlockPHINodes();
874 createLoadCmpBlocks();
880 DTU->
applyUpdates({{DominatorTree::Insert, StartBlock, LoadCmpBlocks[0]},
881 {DominatorTree::Delete, StartBlock, EndBlock}});
886 if (IsUsedForZeroCmp)
887 return getNumBlocks() == 1 ? getMemCmpEqZeroOneBlock()
888 : getMemCmpExpansionZeroCase();
890 if (getNumBlocks() == 1)
891 return getNumLoads() == 1 ? getMemCmpOneBlock()
892 : getMemCmpOneBlockMultipleLoads();
894 unsigned LoadIndex = 0;
895 for (
unsigned I = 0;
I < getNumBlocks(); ++
I) {
896 emitLoadCompareBlock(
I, LoadIndex);
899 emitMemCmpResultBlock();
976static bool expandMemCmp(CallInst *CI,
const TargetTransformInfo *
TTI,
977 const DataLayout *
DL, ProfileSummaryInfo *PSI,
978 BlockFrequencyInfo *BFI, DomTreeUpdater *DTU,
989 NumMemCmpNotConstant++;
999 const bool IsUsedForZeroCmp =
1025 const Align CommonAlign = std::min(getMemCmpArgAlignment(CI, 0, *
DL),
1026 getMemCmpArgAlignment(CI, 1, *
DL));
1030 const unsigned MaxBytesPerBlock =
Options.LoadSizes.front();
1032 return !isAccessAllowed(CI, *TTI, CommonAlign, LoadSize, 0);
1038 if (
Options.LoadSizes.empty())
1042 *
TTI, CommonAlign, MaxBytesPerBlock);
1046 NumMemCmpGreaterThanMax++;
1062 const TargetTransformInfo *
TTI,
1063 ProfileSummaryInfo *PSI,
1064 BlockFrequencyInfo *BFI, DominatorTree *DT) {
1065 std::optional<DomTreeUpdater> DTU;
1067 DTU.emplace(DT, DomTreeUpdater::UpdateStrategy::Lazy);
1069 const DataLayout&
DL =
F.getDataLayout();
1074 if (Func == LibFunc_memcmp || Func == LibFunc_bcmp)
1079 bool MadeChanges =
false;
1080 for (
const auto &[CI, Func] : MemCmpCalls) {
1081 if (expandMemCmp(CI,
TTI, &
DL, PSI, BFI, DTU ? &*DTU :
nullptr,
1082 Func == LibFunc_bcmp))
1087 for (BasicBlock &BB :
F)
1091 PreservedAnalyses PA;
1092 PA.
preserve<DominatorTreeAnalysis>();
1102 if (
F.hasFnAttribute(Attribute::SanitizeAddress) ||
1103 F.hasFnAttribute(Attribute::SanitizeMemory) ||
1104 F.hasFnAttribute(Attribute::SanitizeThread) ||
1105 F.hasFnAttribute(Attribute::SanitizeHWAddress))
1111 .getCachedResult<ProfileSummaryAnalysis>(*
F.getParent());
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
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 bool runImpl(MachineFunction &MF)
static cl::opt< unsigned > MemCmpNumLoadsPerBlock("memcmp-num-loads-per-block", cl::Hidden, cl::init(1), cl::desc("The number of loads per basic block for inline expansion of " "memcmp."))
static cl::opt< unsigned > MaxLoadsPerMemcmpOptSize("max-loads-per-memcmp-opt-size", cl::Hidden, cl::desc("Set maximum number of loads used in expanded memcmp for -Os/Oz"))
static cl::opt< unsigned > MaxLoadsPerMemcmp("max-loads-per-memcmp", cl::Hidden, cl::desc("Set maximum number of loads used in expanded memcmp"))
FunctionAnalysisManager FAM
This file contains the declarations for profiling metadata utility functions.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Represent a constant reference to an array (0 or more elements consecutively in memory),...
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
const T & front() const
Get the first element.
bool empty() const
Check if the array is empty.
iterator begin()
Instruction iterator methods.
const Function * getParent() const
Return the enclosing method, or null if none.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
InstListType::iterator iterator
Instruction iterators...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Analysis pass which computes BlockFrequencyInfo.
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
MaybeAlign getParamAlign(unsigned ArgNo) const
Extract the alignment for a call or parameter (0=unknown).
Value * getArgOperand(unsigned i) const
This class represents a function call, abstracting a target machine's calling convention.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
A parsed version of the target data layout string in and methods for querying it.
Analysis pass which computes a DominatorTree.
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
void applyUpdates(ArrayRef< UpdateT > Updates)
Submit updates to all available trees.
Predicate getUnsignedPredicate() const
For example, EQ->EQ, SLE->ULE, UGT->UGT, etc.
Value * CreateConstGEP1_64(Type *Ty, Value *Ptr, uint64_t Idx0, const Twine &Name="")
LoadInst * CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, const char *Name)
CondBrInst * CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a conditional 'br Cond, TrueDest, FalseDest' instruction.
LLVM_ABI Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
void SetCurrentDebugLocation(const DebugLoc &L)
Set location information used by debugging information.
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
BasicBlock * GetInsertBlock() const
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
UncondBrInst * CreateBr(BasicBlock *Dest)
Create an unconditional 'br label X' instruction.
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
LLVM_ABI Value * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={}, function_ref< void(CallInst *)> SetFn=[](CallInst *) {})
Variant to create a possibly constant-folded intrinsic.
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
LLVM_ABI void setSuccessor(unsigned Idx, BasicBlock *BB)
Update the specified successor to point at the provided block.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
void push_back(const T &Elt)
Analysis pass providing the TargetTransformInfo.
Analysis pass providing the TargetLibraryInfo.
LibFunc getLibFunc(StringRef funcName) const
Searches for a particular function name.
LLVM_ABI unsigned getIntegerBitWidth() const
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
Type * getType() const
All values are typed, get the type of this value.
user_iterator user_begin()
LLVM_ABI bool hasOneUser() const
Return true if there is exactly one user of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVMContext & getContext() const
All values hold a context through their type.
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
const ParentTy * getParent() const
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
@ BasicBlock
Various leaf nodes.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
AllOnesConstantMatch m_AllOnes()
specific_intval< false > m_SpecificInt(const APInt &V)
Match a specific integer value or vector with all elements equal to the value.
bool match(Val *V, const Pattern &P)
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
auto m_Value()
Match an arbitrary value and ignore it.
SpecificCmpClass_match< LHS, RHS, ICmpInst > m_SpecificICmp(CmpPredicate MatchPred, const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::LShr > m_LShr(const LHS &L, const RHS &R)
CmpClass_match< LHS, RHS, ICmpInst > m_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
BlockType
Used as immediate MachineOperands for block signatures.
initializer< Ty > init(const Ty &Val)
NodeAddr< FuncNode * > Func
This is an optimization pass for GlobalISel generic memory operations.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isOnlyUsedInZeroEqualityComparison(const Instruction *CxtI)
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.
OuterAnalysisManagerProxy< ModuleAnalysisManager, Function > ModuleAnalysisManagerFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
LLVM_ABI bool shouldOptimizeForSize(const MachineFunction *MF, ProfileSummaryInfo *PSI, const MachineBlockFrequencyInfo *BFI, PGSOQueryType QueryType=PGSOQueryType::Other)
Returns true if machine function MF is suggested to be size-optimized based on the profile.
LLVM_ABI bool SimplifyInstructionsInBlock(BasicBlock *BB, const TargetLibraryInfo *TLI=nullptr)
Scan the specified basic block and try to simplify any instructions in it and recursively delete dead...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
@ Or
Bitwise or logical OR of integers.
LLVM_ABI BasicBlock * SplitBlock(BasicBlock *Old, BasicBlock::iterator SplitPt, DominatorTree *DT, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, const Twine &BBName="")
Split the specified block at the specified instruction.
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...
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
LLVM_ABI Constant * ConstantFoldLoadFromConstPtr(Constant *C, Type *Ty, APInt Offset, const DataLayout &DL)
Return the value that a load from C with offset Offset would produce if it is constant and determinab...
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.