113#include <type_traits>
119#define DEBUG_TYPE "load-store-vectorizer"
121STATISTIC(NumVectorInstructions,
"Number of vector accesses generated");
122STATISTIC(NumScalarsVectorized,
"Number of scalar accesses vectorized");
132 std::tuple<
const Value * ,
138 const EqClassKey &
K) {
139 const auto &[UnderlyingObject, AddrSpace, ElementSize, IsLoad] =
K;
140 return OS << (IsLoad ?
"load" :
"store") <<
" of " << *UnderlyingObject
141 <<
" of element size " << ElementSize <<
" bits in addrspace "
158 APInt OffsetFromLeader;
159 ChainElem(Instruction *Inst, APInt OffsetFromLeader)
160 : Inst(std::
move(Inst)), OffsetFromLeader(std::
move(OffsetFromLeader)) {}
164void sortChainInBBOrder(Chain &
C) {
165 sort(
C, [](
auto &
A,
auto &
B) {
return A.Inst->comesBefore(
B.Inst); });
168void sortChainInOffsetOrder(Chain &
C) {
169 sort(
C, [](
const auto &
A,
const auto &
B) {
170 if (
A.OffsetFromLeader !=
B.OffsetFromLeader)
171 return A.OffsetFromLeader.slt(
B.OffsetFromLeader);
172 return A.Inst->comesBefore(
B.Inst);
177 for (
const auto &
E :
C) {
178 dbgs() <<
" " << *
E.Inst <<
" (offset " <<
E.OffsetFromLeader <<
")\n";
182using EquivalenceClassMap =
186constexpr unsigned StackAdjustedAlignment = 4;
190 for (
const ChainElem &
E :
C)
197 return LI !=
nullptr && LI->
hasMetadata(LLVMContext::MD_invariant_load);
207 while (!Worklist.
empty()) {
210 for (
int Idx = 0;
Idx < NumOperands;
Idx++) {
212 if (!IM || IM->
getOpcode() == Instruction::PHI)
220 assert(IM !=
I &&
"Unexpected cycle while re-ordering instructions");
223 InstructionsToMove.
insert(IM);
230 for (
auto BBI =
I->getIterator(),
E =
I->getParent()->end(); BBI !=
E;) {
232 if (!InstructionsToMove.
contains(IM))
244 TargetTransformInfo &TTI;
245 const DataLayout &DL;
256 DenseSet<Instruction *> ExtraElements;
260 DominatorTree &DT, ScalarEvolution &SE, TargetTransformInfo &TTI)
261 : F(F), AA(AA), AC(AC), DT(DT), SE(SE), TTI(TTI), DL(F.getDataLayout()),
262 Builder(SE.getModule()) {}
267 static const unsigned MaxDepth = 3;
276 bool runOnEquivalenceClass(
const EqClassKey &EqClassKey,
277 ArrayRef<Instruction *> EqClass);
282 bool runOnChain(Chain &
C);
288 std::vector<Chain> splitChainByContiguity(Chain &
C);
294 std::vector<Chain> splitChainByMayAliasInstrs(Chain &
C);
298 std::vector<Chain> splitChainByAlignment(Chain &
C);
302 bool vectorizeChain(Chain &
C);
305 std::optional<APInt> getConstantOffset(
Value *PtrA,
Value *PtrB,
306 Instruction *ContextInst,
308 std::optional<APInt> getConstantOffsetComplexAddrs(
Value *PtrA,
Value *PtrB,
309 Instruction *ContextInst,
311 std::optional<APInt> getConstantOffsetSelects(
Value *PtrA,
Value *PtrB,
312 Instruction *ContextInst,
318 Type *getChainElemTy(
const Chain &
C);
327 template <
bool IsLoadChain>
329 Instruction *ChainElem, Instruction *ChainBegin,
330 const DenseMap<Instruction *, APInt /*OffsetFromLeader*/> &ChainOffsets,
331 BatchAAResults &BatchAA);
336 void mergeEquivalenceClasses(EquivalenceClassMap &EQClasses)
const;
351 std::vector<Chain> gatherChains(ArrayRef<Instruction *> Instrs);
357 bool accessIsAllowedAndFast(
unsigned SizeBytes,
unsigned AS, Align Alignment,
358 unsigned VecElemBits)
const;
364 ChainElem createExtraElementAfter(
const ChainElem &PrevElem,
Type *Ty,
365 APInt
Offset, StringRef Prefix,
366 Align Alignment =
Align());
371 FixedVectorType *VecTy);
375 void deleteExtraElements();
378class LoadStoreVectorizerLegacyPass :
public FunctionPass {
382 LoadStoreVectorizerLegacyPass() : FunctionPass(ID) {}
386 StringRef getPassName()
const override {
387 return "GPU Load and Store Vectorizer";
390 void getAnalysisUsage(AnalysisUsage &AU)
const override {
402char LoadStoreVectorizerLegacyPass::ID = 0;
405 "Vectorize load and Store instructions",
false,
false)
413 "Vectorize load and store instructions",
false,
false)
416 return new LoadStoreVectorizerLegacyPass();
419bool LoadStoreVectorizerLegacyPass::runOnFunction(
Function &
F) {
421 if (skipFunction(
F) ||
F.hasFnAttribute(Attribute::NoImplicitFloat))
424 AliasAnalysis &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
425 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
426 ScalarEvolution &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE();
427 TargetTransformInfo &
TTI =
428 getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
430 AssumptionCache &AC =
431 getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
433 return Vectorizer(
F, AA, AC, DT, SE,
TTI).run();
439 if (
F.hasFnAttribute(Attribute::NoImplicitFloat))
454bool Vectorizer::run() {
481 for (
auto It = Barriers.
begin(),
End = std::prev(Barriers.
end()); It !=
End;
483 Changed |= runOnPseudoBB(*It, *std::next(It));
496 I->eraseFromParent();
500 deleteExtraElements();
509 dbgs() <<
"LSV: Running on pseudo-BB [" << *Begin <<
" ... ";
510 if (
End != Begin->getParent()->end())
513 dbgs() <<
"<BB end>";
518 for (
const auto &[EqClassKey, EqClass] :
519 collectEquivalenceClasses(Begin,
End))
520 Changed |= runOnEquivalenceClass(EqClassKey, EqClass);
525bool Vectorizer::runOnEquivalenceClass(
const EqClassKey &EqClassKey,
526 ArrayRef<Instruction *> EqClass) {
530 dbgs() <<
"LSV: Running on equivalence class of size " << EqClass.
size()
531 <<
" keyed on " << EqClassKey <<
":\n";
532 for (Instruction *
I : EqClass)
533 dbgs() <<
" " << *
I <<
"\n";
536 std::vector<Chain> Chains = gatherChains(EqClass);
538 <<
" nontrivial chains.\n";);
539 for (Chain &
C : Chains)
544bool Vectorizer::runOnChain(Chain &
C) {
546 dbgs() <<
"LSV: Running on chain with " <<
C.size() <<
" instructions:\n";
557 for (
auto &
C : splitChainByMayAliasInstrs(
C))
558 for (
auto &
C : splitChainByContiguity(
C))
559 for (
auto &
C : splitChainByAlignment(
C))
564std::vector<Chain> Vectorizer::splitChainByMayAliasInstrs(Chain &
C) {
568 sortChainInBBOrder(
C);
571 dbgs() <<
"LSV: splitChainByMayAliasInstrs considering chain:\n";
579 for (
const auto &
E :
C)
580 ChainOffsets.insert({&*
E.Inst,
E.OffsetFromLeader});
584 BatchAAResults BatchAA(AA);
597 auto Impl = [&](
auto IsLoad) {
599 auto [ChainBegin, ChainEnd] = [&](
auto IsLoad) {
600 if constexpr (IsLoad())
601 return std::make_pair(
C.begin(),
C.end());
603 return std::make_pair(
C.rbegin(),
C.rend());
605 assert(ChainBegin != ChainEnd);
607 std::vector<Chain> Chains;
610 for (
auto ChainIt = std::next(ChainBegin); ChainIt != ChainEnd; ++ChainIt) {
612 ChainOffsets, BatchAA)) {
613 LLVM_DEBUG(
dbgs() <<
"LSV: No intervening may-alias instrs; can merge "
614 << *ChainIt->Inst <<
" into " << *ChainBegin->Inst
619 dbgs() <<
"LSV: Found intervening may-alias instrs; cannot merge "
620 << *ChainIt->Inst <<
" into " << *ChainBegin->Inst <<
"\n");
621 if (NewChain.
size() > 1) {
623 dbgs() <<
"LSV: got nontrivial chain without aliasing instrs:\n";
626 Chains.emplace_back(std::move(NewChain));
633 if (NewChain.
size() > 1) {
635 dbgs() <<
"LSV: got nontrivial chain without aliasing instrs:\n";
638 Chains.emplace_back(std::move(NewChain));
644 return Impl(std::bool_constant<true>());
647 return Impl(std::bool_constant<false>());
650std::vector<Chain> Vectorizer::splitChainByContiguity(Chain &
C) {
654 sortChainInOffsetOrder(
C);
657 dbgs() <<
"LSV: splitChainByContiguity considering chain:\n";
671 Align OptimisticAlign =
Align(MaxVecRegBits / 8);
672 unsigned int MaxVectorNumElems =
673 MaxVecRegBits /
DL.getTypeSizeInBits(ElementType);
680 FixedVectorType *OptimisticVectorType =
692 APInt OffsetOfBestAlignedElemFromLeader =
C[0].OffsetFromLeader;
693 for (
const auto &
E :
C) {
695 if (ElementAlignment > BestAlignedElemAlign) {
696 BestAlignedElemAlign = ElementAlignment;
697 OffsetOfBestAlignedElemFromLeader =
E.OffsetFromLeader;
701 auto DeriveAlignFromBestAlignedElem = [&](APInt NewElemOffsetFromLeader) {
703 BestAlignedElemAlign,
704 (NewElemOffsetFromLeader - OffsetOfBestAlignedElemFromLeader)
709 unsigned ASPtrBits =
DL.getIndexSizeInBits(AS);
711 std::vector<Chain> Ret;
712 Ret.push_back({
C.front()});
714 unsigned ChainElemTyBits =
DL.getTypeSizeInBits(getChainElemTy(
C));
715 ChainElem &Prev =
C[0];
716 for (
auto It = std::next(
C.begin()),
End =
C.end(); It !=
End; ++It) {
717 auto &CurChain = Ret.back();
721 APInt PrevReadEnd = Prev.OffsetFromLeader + PrevSzBytes;
726 8 * SzBytes % ChainElemTyBits == 0 &&
727 "Every chain-element size must be a multiple of the element size after "
729 APInt ReadEnd = It->OffsetFromLeader + SzBytes;
731 bool AreContiguous =
false;
732 if (It->OffsetFromLeader.sle(PrevReadEnd)) {
734 uint64_t Overlap = (PrevReadEnd - It->OffsetFromLeader).getZExtValue();
735 if (8 * Overlap % ChainElemTyBits == 0)
736 AreContiguous =
true;
740 << (AreContiguous ?
"contiguous" :
"chain-breaker")
741 << *It->Inst <<
" (starts at offset "
742 << It->OffsetFromLeader <<
")\n");
750 bool GapFilled =
false;
751 if (!AreContiguous && TryFillGaps && PrevSzBytes == SzBytes) {
752 APInt GapSzBytes = It->OffsetFromLeader - PrevReadEnd;
753 if (GapSzBytes == PrevSzBytes) {
755 ChainElem NewElem = createExtraElementAfter(
757 DeriveAlignFromBestAlignedElem(PrevReadEnd));
758 CurChain.push_back(NewElem);
764 if ((GapSzBytes == 2 * PrevSzBytes) && (CurChain.size() % 4 == 1)) {
765 ChainElem NewElem1 = createExtraElementAfter(
767 DeriveAlignFromBestAlignedElem(PrevReadEnd));
768 ChainElem NewElem2 = createExtraElementAfter(
770 DeriveAlignFromBestAlignedElem(PrevReadEnd + PrevSzBytes));
771 CurChain.push_back(NewElem1);
772 CurChain.push_back(NewElem2);
777 if (AreContiguous || GapFilled)
778 CurChain.push_back(*It);
780 Ret.push_back({*It});
784 if (ReadEnd.
sge(PrevReadEnd))
789 llvm::erase_if(Ret, [](
const auto &Chain) {
return Chain.size() <= 1; });
793Type *Vectorizer::getChainElemTy(
const Chain &
C) {
806 if (
any_of(
C, [](
const ChainElem &
E) {
809 return Type::getIntNTy(
814 for (
const ChainElem &
E :
C)
820std::vector<Chain> Vectorizer::splitChainByAlignment(Chain &
C) {
833 sortChainInOffsetOrder(
C);
836 dbgs() <<
"LSV: splitChainByAlignment considering chain:\n";
841 auto GetVectorFactor = [&](
unsigned VF,
unsigned LoadStoreSize,
844 ChainSizeBytes, VecTy)
846 ChainSizeBytes, VecTy);
850 for (
const auto &
E :
C) {
853 "Should have filtered out non-power-of-two elements in "
854 "collectEquivalenceClasses.");
864 bool CandidateChainsMayContainExtraLoadsStores =
any_of(
865 C, [
this](
const ChainElem &
E) {
return ExtraElements.
contains(
E.Inst); });
867 std::vector<Chain> Ret;
868 for (
unsigned CBegin = 0; CBegin <
C.size(); ++CBegin) {
876 APInt PrevReadEnd =
C[CBegin].OffsetFromLeader + Sz;
877 for (
unsigned CEnd = CBegin + 1,
Size =
C.size(); CEnd <
Size; ++CEnd) {
878 APInt ReadEnd =
C[CEnd].OffsetFromLeader +
880 unsigned BytesAdded =
881 PrevReadEnd.
sle(ReadEnd) ? (ReadEnd - PrevReadEnd).getSExtValue() : 0;
883 if (Sz > VecRegBytes)
885 CandidateChains.emplace_back(CEnd, Sz);
890 for (
auto It = CandidateChains.rbegin(),
End = CandidateChains.rend();
892 auto [CEnd, SizeBytes] = *It;
894 dbgs() <<
"LSV: splitChainByAlignment considering candidate chain ["
895 << *
C[CBegin].Inst <<
" ... " << *
C[CEnd].Inst <<
"]\n");
897 Type *VecElemTy = getChainElemTy(
C);
901 unsigned VecElemBits =
DL.getTypeSizeInBits(VecElemTy);
904 assert((8 * SizeBytes) % VecElemBits == 0);
905 unsigned NumVecElems = 8 * SizeBytes / VecElemBits;
907 unsigned VF = 8 * VecRegBytes / VecElemBits;
910 unsigned TargetVF = GetVectorFactor(VF, VecElemBits,
911 VecElemBits * NumVecElems / 8, VecTy);
912 if (TargetVF != VF && TargetVF < NumVecElems) {
914 dbgs() <<
"LSV: splitChainByAlignment discarding candidate chain "
916 << TargetVF <<
" != VF=" << VF
917 <<
" and TargetVF < NumVecElems=" << NumVecElems <<
"\n");
931 bool IsAllocaAccess = AS ==
DL.getAllocaAddrSpace() &&
934 Align PrefAlign =
Align(StackAdjustedAlignment);
935 if (IsAllocaAccess &&
Alignment.value() % SizeBytes != 0 &&
936 accessIsAllowedAndFast(SizeBytes, AS, PrefAlign, VecElemBits)) {
938 PtrOperand, PrefAlign,
DL,
C[CBegin].Inst,
nullptr, &DT);
939 if (NewAlign >= Alignment) {
941 <<
"LSV: splitByChain upgrading alloca alignment from "
948 Chain ExtendingLoadsStores;
949 if (!accessIsAllowedAndFast(SizeBytes, AS, Alignment, VecElemBits)) {
953 bool AllowedAndFast =
false;
958 assert(VecElemBits % 8 == 0);
959 unsigned VecElemBytes = VecElemBits / 8;
961 unsigned NewSizeBytes = VecElemBytes * NewNumVecElems;
964 "TargetVF expected to be a power of 2");
965 assert(NewNumVecElems <= TargetVF &&
966 "Should not extend past TargetVF");
969 <<
"LSV: attempting to extend chain of " << NumVecElems
970 <<
" " << (IsLoadChain ?
"loads" :
"stores") <<
" to "
971 << NewNumVecElems <<
" elements\n");
972 bool IsLegalToExtend =
982 if (IsLegalToExtend &&
983 accessIsAllowedAndFast(NewSizeBytes, AS, Alignment,
986 <<
"LSV: extending " << (IsLoadChain ?
"load" :
"store")
987 <<
" chain of " << NumVecElems <<
" "
988 << (IsLoadChain ?
"loads" :
"stores")
989 <<
" with total byte size of " << SizeBytes <<
" to "
990 << NewNumVecElems <<
" "
991 << (IsLoadChain ?
"loads" :
"stores")
992 <<
" with total byte size of " << NewSizeBytes
993 <<
", TargetVF=" << TargetVF <<
" \n");
999 unsigned ASPtrBits =
DL.getIndexSizeInBits(AS);
1000 for (
unsigned I = 0;
I < (NewNumVecElems - NumVecElems);
I++) {
1001 ChainElem NewElem = createExtraElementAfter(
1002 C[CBegin], VecElemTy,
1003 APInt(ASPtrBits, SizeBytes +
I * VecElemBytes),
"Extend");
1004 ExtendingLoadsStores.push_back(NewElem);
1008 SizeBytes = NewSizeBytes;
1009 NumVecElems = NewNumVecElems;
1010 AllowedAndFast =
true;
1013 if (!AllowedAndFast) {
1016 <<
"LSV: splitChainByAlignment discarding candidate chain "
1017 "because its alignment is not AllowedAndFast: "
1028 dbgs() <<
"LSV: splitChainByAlignment discarding candidate chain "
1029 "because !isLegalToVectorizeLoad/StoreChain.");
1033 if (CandidateChainsMayContainExtraLoadsStores) {
1045 [
this](
const ChainElem &
E) {
1049 if (CurrCandContainsExtraLoadsStores &&
1057 <<
"LSV: splitChainByAlignment discarding candidate chain "
1058 "because it contains extra loads/stores that we cannot "
1059 "legally vectorize into a masked load/store \n");
1066 for (
unsigned I = CBegin;
I <= CEnd; ++
I)
1067 NewChain.emplace_back(
C[
I]);
1068 for (ChainElem
E : ExtendingLoadsStores)
1069 NewChain.emplace_back(
E);
1077bool Vectorizer::vectorizeChain(Chain &
C) {
1082 C, [
this](
const ChainElem &
E) {
return ExtraElements.
contains(
E.Inst); });
1086 if (
C.size() == 2 && ChainContainsExtraLoadsStores)
1089 sortChainInOffsetOrder(
C);
1092 dbgs() <<
"LSV: Vectorizing chain of " <<
C.size() <<
" instructions:\n";
1096 Type *VecElemTy = getChainElemTy(
C);
1100 APInt PrevReadEnd =
C[0].OffsetFromLeader + BytesAdded;
1101 unsigned ChainBytes = BytesAdded;
1102 for (
auto It = std::next(
C.begin()),
End =
C.end(); It !=
End; ++It) {
1104 APInt ReadEnd = It->OffsetFromLeader + SzBytes;
1107 PrevReadEnd.
sle(ReadEnd) ? (ReadEnd - PrevReadEnd).getSExtValue() : 0;
1108 ChainBytes += BytesAdded;
1112 assert(8 * ChainBytes %
DL.getTypeSizeInBits(VecElemTy) == 0);
1115 unsigned NumElem = 8 * ChainBytes /
DL.getTypeSizeInBits(VecElemTy);
1121 if (AS ==
DL.getAllocaAddrSpace()) {
1125 MaybeAlign(),
DL,
C[0].Inst,
nullptr, &DT));
1130 for (
const ChainElem &
E :
C)
1132 DL.getTypeStoreSize(VecElemTy));
1141 return A.Inst->comesBefore(
B.Inst);
1146 if (ChainContainsExtraLoadsStores) {
1163 for (
const ChainElem &
E :
C) {
1168 (
E.OffsetFromLeader -
C[0].OffsetFromLeader).getZExtValue();
1169 unsigned VecIdx = 8 * EOffset /
DL.getTypeSizeInBits(VecElemTy);
1179 if (
V->getType() !=
I->getType())
1207 return A.Inst->comesBefore(
B.Inst);
1212 auto InsertElem = [&](
Value *
V,
unsigned VecIdx) {
1213 if (
V->getType() != VecElemTy)
1217 for (
const ChainElem &
E :
C) {
1220 (
E.OffsetFromLeader -
C[0].OffsetFromLeader).getZExtValue();
1221 unsigned VecIdx = 8 * EOffset /
DL.getTypeSizeInBits(VecElemTy);
1222 if (FixedVectorType *VT =
1224 for (
int J = 0, JE = VT->getNumElements(); J < JE; ++J) {
1229 InsertElem(
I->getValueOperand(), VecIdx);
1235 if (ChainContainsExtraLoadsStores) {
1252 for (
const ChainElem &
E :
C)
1253 ToErase.emplace_back(
E.Inst);
1255 ++NumVectorInstructions;
1256 NumScalarsVectorized +=
C.size();
1260template <
bool IsLoadChain>
1261bool Vectorizer::isSafeToMove(
1262 Instruction *ChainElem, Instruction *ChainBegin,
1263 const DenseMap<Instruction *, APInt /*OffsetFromLeader*/> &ChainOffsets,
1264 BatchAAResults &BatchAA) {
1265 LLVM_DEBUG(
dbgs() <<
"LSV: isSafeToMove(" << *ChainElem <<
" -> "
1266 << *ChainBegin <<
")\n");
1269 if (ChainElem == ChainBegin)
1277 auto BBIt = std::next([&] {
1278 if constexpr (IsLoadChain)
1283 auto BBItEnd = std::next([&] {
1284 if constexpr (IsLoadChain)
1290 const APInt &ChainElemOffset = ChainOffsets.
at(ChainElem);
1291 const unsigned ChainElemSize =
1294 for (; BBIt != BBItEnd; ++BBIt) {
1297 if (!
I->mayReadOrWriteMemory())
1316 if (
auto OffsetIt = ChainOffsets.
find(
I); OffsetIt != ChainOffsets.
end()) {
1323 const APInt &IOffset = OffsetIt->second;
1325 if (IOffset == ChainElemOffset ||
1326 (IOffset.
sle(ChainElemOffset) &&
1327 (IOffset + IElemSize).sgt(ChainElemOffset)) ||
1328 (ChainElemOffset.sle(IOffset) &&
1329 (ChainElemOffset + ChainElemSize).sgt(OffsetIt->second))) {
1336 dbgs() <<
"LSV: Found alias in chain: " << *
I <<
"\n";
1348 <<
" Aliasing instruction:\n"
1349 <<
" " << *
I <<
'\n'
1350 <<
" Aliased instruction and pointer:\n"
1351 <<
" " << *ChainElem <<
'\n'
1373 switch (
I->getOpcode()) {
1376 case Instruction::Add:
1378 case Instruction::Or:
1380 return PDI->isDisjoint();
1388 unsigned MatchingOpIdxB,
bool Signed) {
1389 LLVM_DEBUG(
dbgs() <<
"LSV: checkIfSafeAddSequence IdxDiff=" << IdxDiff
1390 <<
", AddOpA=" << *AddOpA <<
", MatchingOpIdxA="
1391 << MatchingOpIdxA <<
", AddOpB=" << *AddOpB
1392 <<
", MatchingOpIdxB=" << MatchingOpIdxB
1393 <<
", Signed=" <<
Signed <<
"\n");
1413 Value *OtherOperandA = AddOpA->
getOperand(MatchingOpIdxA == 1 ? 0 : 1);
1414 Value *OtherOperandB = AddOpB->
getOperand(MatchingOpIdxB == 1 ? 0 : 1);
1421 unsigned WideBitWidth = IdxDiff.
getBitWidth() + 1;
1422 APInt WideIdxDiff = IdxDiff.
sext(WideBitWidth);
1429 if (OtherInstrB &&
isAddLike(OtherInstrB) &&
1434 if (OtherInstrB->
getOperand(0) == OtherOperandA &&
1435 WideIdxDiff == WideCstVal)
1439 if (OtherInstrA &&
isAddLike(OtherInstrA) &&
1444 if (OtherInstrA->
getOperand(0) == OtherOperandB &&
1445 WideIdxDiff == -WideCstVal)
1450 if (OtherInstrA && OtherInstrB &&
isAddLike(OtherInstrA) &&
1460 WideIdxDiff == WideCstValB - WideCstValA)
1467std::optional<APInt> Vectorizer::getConstantOffsetComplexAddrs(
1469 LLVM_DEBUG(
dbgs() <<
"LSV: getConstantOffsetComplexAddrs PtrA=" << *PtrA
1470 <<
" PtrB=" << *PtrB <<
" ContextInst=" << *ContextInst
1471 <<
" Depth=" <<
Depth <<
"\n");
1475 return getConstantOffsetSelects(PtrA, PtrB, ContextInst,
Depth);
1479 if (GEPA->getNumOperands() != GEPB->getNumOperands() ||
1480 GEPA->getPointerOperand() != GEPB->getPointerOperand() ||
1481 GEPA->getSourceElementType() != GEPB->getSourceElementType())
1482 return std::nullopt;
1485 for (
unsigned I = 0,
E = GEPA->getNumIndices() - 1;
I <
E; ++
I) {
1487 return std::nullopt;
1496 return std::nullopt;
1502 return std::nullopt;
1510 return std::nullopt;
1512 const SCEV *OffsetSCEVA = SE.
getSCEV(ValA);
1513 const SCEV *OffsetSCEVB = SE.
getSCEV(OpB);
1514 const SCEV *IdxDiffSCEV = SE.
getMinusSCEV(OffsetSCEVB, OffsetSCEVA);
1516 return std::nullopt;
1520 return std::nullopt;
1523 LLVM_DEBUG(
dbgs() <<
"LSV: getConstantOffsetComplexAddrs IdxDiff=" << IdxDiff
1535 unsigned WideBitWidth = IdxDiff.
getBitWidth() + 1;
1536 APInt WideIdxDiff = IdxDiff.
sext(WideBitWidth);
1539 Safe = WideIdxDiff.
sge(WideC) && WideIdxDiff.
sle(0);
1541 Safe = WideIdxDiff.
sge(0) && WideIdxDiff.
sle(WideC);
1552 for (
unsigned MatchingOpIdxA : {0, 1})
1553 for (
unsigned MatchingOpIdxB : {0, 1})
1577 Safe = BitsAllowedToBeSet.
uge(IdxDiff.
abs());
1585 Value *CheckVal = IdxDiff.
sge(0) ? ValA : OpB;
1595 unsigned OffsetBitWidth =
DL.getIndexTypeSizeInBits(GEPA->getType());
1596 return IdxDiff.
sextOrTrunc(OffsetBitWidth) * Stride;
1598 return std::nullopt;
1601std::optional<APInt> Vectorizer::getConstantOffsetSelects(
1603 if (
Depth++ == MaxDepth)
1604 return std::nullopt;
1608 if (SelectA->getCondition() != SelectB->getCondition())
1609 return std::nullopt;
1610 LLVM_DEBUG(
dbgs() <<
"LSV: getConstantOffsetSelects, PtrA=" << *PtrA
1611 <<
", PtrB=" << *PtrB <<
", ContextInst="
1612 << *ContextInst <<
", Depth=" <<
Depth <<
"\n");
1613 std::optional<APInt> TrueDiff = getConstantOffset(
1614 SelectA->getTrueValue(), SelectB->getTrueValue(), ContextInst,
Depth);
1616 return std::nullopt;
1617 std::optional<APInt> FalseDiff =
1618 getConstantOffset(SelectA->getFalseValue(), SelectB->getFalseValue(),
1619 ContextInst,
Depth);
1620 if (TrueDiff == FalseDiff)
1624 return std::nullopt;
1627void Vectorizer::mergeEquivalenceClasses(EquivalenceClassMap &EQClasses)
const {
1628 if (EQClasses.size() < 2)
1633 static_assert(std::tuple_size_v<EqClassKey> == 4,
1634 "EqClassKey has changed - EqClassReducedKey needs changes too");
1635 using EqClassReducedKey =
1636 std::tuple<std::tuple_element_t<1, EqClassKey> ,
1637 std::tuple_element_t<2, EqClassKey> ,
1638 std::tuple_element_t<3, EqClassKey> >;
1639 using ECReducedKeyToUnderlyingObjectMap =
1640 MapVector<EqClassReducedKey,
1641 SmallPtrSet<std::tuple_element_t<0, EqClassKey>, 4>>;
1646 ECReducedKeyToUnderlyingObjectMap RedKeyToUOMap;
1647 bool FoundPotentiallyOptimizableEC =
false;
1648 for (
const auto &EC : EQClasses) {
1649 const auto &
Key =
EC.first;
1650 EqClassReducedKey RedKey{std::get<1>(
Key), std::get<2>(
Key),
1652 auto &UOMap = RedKeyToUOMap[RedKey];
1654 if (UOMap.size() > 1)
1655 FoundPotentiallyOptimizableEC =
true;
1657 if (!FoundPotentiallyOptimizableEC)
1661 dbgs() <<
"LSV: mergeEquivalenceClasses: before merging:\n";
1662 for (
const auto &EC : EQClasses) {
1663 dbgs() <<
" Key: {" <<
EC.first <<
"}\n";
1664 for (
const auto &Inst :
EC.second)
1665 dbgs() <<
" Inst: " << *Inst <<
'\n';
1669 dbgs() <<
"LSV: mergeEquivalenceClasses: RedKeyToUOMap:\n";
1670 for (
const auto &RedKeyToUO : RedKeyToUOMap) {
1671 dbgs() <<
" Reduced key: {" << std::get<0>(RedKeyToUO.first) <<
", "
1672 << std::get<1>(RedKeyToUO.first) <<
", "
1673 <<
static_cast<int>(std::get<2>(RedKeyToUO.first)) <<
"} --> "
1674 << RedKeyToUO.second.size() <<
" underlying objects:\n";
1675 for (
auto UObject : RedKeyToUO.second)
1676 dbgs() <<
" " << *UObject <<
'\n';
1680 using UObjectToUObjectMap = DenseMap<const Value *, const Value *>;
1683 auto GetUltimateTargets =
1684 [](SmallPtrSetImpl<const Value *> &UObjects) -> UObjectToUObjectMap {
1685 UObjectToUObjectMap IndirectionMap;
1686 for (
const auto *UObject : UObjects) {
1687 const unsigned MaxLookupDepth = 1;
1689 if (UltimateTarget != UObject)
1690 IndirectionMap[UObject] = UltimateTarget;
1692 UObjectToUObjectMap UltimateTargetsMap;
1693 for (
const auto *UObject : UObjects) {
1695 auto It = IndirectionMap.find(Target);
1696 for (; It != IndirectionMap.end(); It = IndirectionMap.find(Target))
1698 UltimateTargetsMap[UObject] =
Target;
1700 return UltimateTargetsMap;
1705 for (
auto &[RedKey, UObjects] : RedKeyToUOMap) {
1706 if (UObjects.size() < 2)
1708 auto UTMap = GetUltimateTargets(UObjects);
1709 for (
const auto &[UObject, UltimateTarget] : UTMap) {
1710 if (UObject == UltimateTarget)
1713 EqClassKey KeyFrom{UObject, std::get<0>(RedKey), std::get<1>(RedKey),
1714 std::get<2>(RedKey)};
1715 EqClassKey KeyTo{UltimateTarget, std::get<0>(RedKey), std::get<1>(RedKey),
1716 std::get<2>(RedKey)};
1719 const auto &VecTo = EQClasses[KeyTo];
1720 const auto &VecFrom = EQClasses[KeyFrom];
1721 SmallVector<Instruction *, 8> MergedVec;
1722 std::merge(VecFrom.begin(), VecFrom.end(), VecTo.begin(), VecTo.end(),
1723 std::back_inserter(MergedVec),
1724 [](Instruction *
A, Instruction *
B) {
1725 return A && B && A->comesBefore(B);
1727 EQClasses[KeyTo] = std::move(MergedVec);
1728 EQClasses.erase(KeyFrom);
1732 dbgs() <<
"LSV: mergeEquivalenceClasses: after merging:\n";
1733 for (
const auto &EC : EQClasses) {
1734 dbgs() <<
" Key: {" <<
EC.first <<
"}\n";
1735 for (
const auto &Inst :
EC.second)
1736 dbgs() <<
" Inst: " << *Inst <<
'\n';
1744 EquivalenceClassMap Ret;
1746 auto GetUnderlyingObject = [](
const Value *Ptr) ->
const Value * {
1755 return Sel->getCondition();
1766 if ((LI && !LI->
isSimple()) || (SI && !
SI->isSimple()))
1780 if (
DL.hasExternalState(Ty))
1785 unsigned TySize =
DL.getTypeSizeInBits(Ty);
1786 if ((TySize % 8) != 0)
1800 unsigned VF = VecRegSize / TySize;
1805 (VecTy && !
isPowerOf2_32(
DL.getTypeSizeInBits(VecTy->getScalarType()))))
1809 if (TySize > VecRegSize / 2 ||
1813 Ret[{GetUnderlyingObject(Ptr), AS,
1819 mergeEquivalenceClasses(Ret);
1823std::vector<Chain> Vectorizer::gatherChains(ArrayRef<Instruction *> Instrs) {
1828 unsigned ASPtrBits =
DL.getIndexSizeInBits(AS);
1832 for (
size_t I = 1;
I < Instrs.
size(); ++
I) {
1833 assert(Instrs[
I - 1]->comesBefore(Instrs[
I]));
1842 struct InstrListElem : ilist_node<InstrListElem>,
1843 std::pair<Instruction *, Chain> {
1844 explicit InstrListElem(Instruction *
I)
1847 struct InstrListElemDenseMapInfo {
1848 using IInfo = DenseMapInfo<Instruction *>;
1849 static unsigned getHashValue(
const InstrListElem *
E) {
1850 return IInfo::getHashValue(
E->first);
1852 static bool isEqual(
const InstrListElem *
A,
const InstrListElem *
B) {
1853 return IInfo::isEqual(
A->first,
B->first);
1856 SpecificBumpPtrAllocator<InstrListElem>
Allocator;
1857 simple_ilist<InstrListElem> MRU;
1858 DenseSet<InstrListElem *, InstrListElemDenseMapInfo> Chains;
1863 for (Instruction *
I : Instrs) {
1864 constexpr int MaxChainsToTry = 64;
1866 bool MatchFound =
false;
1867 auto ChainIter = MRU.
begin();
1868 for (
size_t J = 0; J < MaxChainsToTry && ChainIter != MRU.
end();
1870 if (std::optional<APInt>
Offset = getConstantOffset(
1874 (ChainIter->first->comesBefore(
I) ?
I : ChainIter->first))) {
1877 ChainIter->second.emplace_back(
I,
Offset.value());
1887 APInt ZeroOffset(ASPtrBits, 0);
1888 InstrListElem *
E =
new (
Allocator.Allocate()) InstrListElem(
I);
1889 E->second.emplace_back(
I, ZeroOffset);
1895 std::vector<Chain> Ret;
1896 Ret.reserve(Chains.
size());
1899 if (
E.second.size() > 1)
1900 Ret.emplace_back(std::move(
E.second));
1904std::optional<APInt> Vectorizer::getConstantOffset(
Value *PtrA,
Value *PtrB,
1905 Instruction *ContextInst,
1908 <<
", PtrB=" << *PtrB <<
", ContextInst= " << *ContextInst
1909 <<
", Depth=" <<
Depth <<
"\n");
1912 unsigned OrigBitWidth =
DL.getIndexTypeSizeInBits(PtrA->
getType());
1913 APInt OffsetA(OrigBitWidth, 0);
1914 APInt OffsetB(OrigBitWidth, 0);
1917 unsigned NewPtrBitWidth =
DL.getTypeStoreSizeInBits(PtrA->
getType());
1918 if (NewPtrBitWidth !=
DL.getTypeStoreSizeInBits(PtrB->
getType()))
1919 return std::nullopt;
1924 assert(OffsetA.getSignificantBits() <= NewPtrBitWidth &&
1925 OffsetB.getSignificantBits() <= NewPtrBitWidth);
1927 OffsetA = OffsetA.sextOrTrunc(NewPtrBitWidth);
1928 OffsetB = OffsetB.sextOrTrunc(NewPtrBitWidth);
1930 return (OffsetB - OffsetA).sextOrTrunc(OrigBitWidth);
1935 LLVM_DEBUG(
dbgs() <<
"LSV: SCEV PtrB - PtrA =" << *DistScev <<
"\n");
1941 return (OffsetB - OffsetA + Dist).
sextOrTrunc(OrigBitWidth);
1944 if (std::optional<APInt> Diff =
1945 getConstantOffsetComplexAddrs(PtrA, PtrB, ContextInst,
Depth))
1946 return (OffsetB - OffsetA + Diff->sext(OffsetB.getBitWidth()))
1947 .sextOrTrunc(OrigBitWidth);
1948 return std::nullopt;
1951bool Vectorizer::accessIsAllowedAndFast(
unsigned SizeBytes,
unsigned AS,
1953 unsigned VecElemBits)
const {
1959 unsigned VectorizedSpeed = 0;
1961 F.getContext(), SizeBytes * 8, AS, Alignment, &VectorizedSpeed);
1962 if (!AllowsMisaligned) {
1964 dbgs() <<
"LSV: Access of " << SizeBytes <<
"B in addrspace " << AS
1965 <<
" with alignment " <<
Alignment.value()
1966 <<
" is misaligned, and therefore can't be vectorized.\n");
1970 unsigned ElementwiseSpeed = 0;
1971 (
TTI).allowsMisalignedMemoryAccesses((
F).
getContext(), VecElemBits, AS,
1972 Alignment, &ElementwiseSpeed);
1973 if (VectorizedSpeed < ElementwiseSpeed) {
1974 LLVM_DEBUG(
dbgs() <<
"LSV: Access of " << SizeBytes <<
"B in addrspace "
1975 << AS <<
" with alignment " <<
Alignment.value()
1976 <<
" has relative speed " << VectorizedSpeed
1977 <<
", which is lower than the elementwise speed of "
1979 <<
". Therefore this access won't be vectorized.\n");
1985ChainElem Vectorizer::createExtraElementAfter(
const ChainElem &Prev,
Type *Ty,
1986 APInt
Offset, StringRef Prefix,
1992 PrevLoad->getPointerOperand(), Builder.
getInt(
Offset), Prefix +
"GEP");
1993 LLVM_DEBUG(
dbgs() <<
"LSV: Extra GEP Created: \n" << *NewGep <<
"\n");
2000 LLVM_DEBUG(
dbgs() <<
"LSV: Extra GEP Created: \n" << *NewGep <<
"\n");
2010 ExtraElements.
insert(NewElement);
2012 APInt NewOffsetFromLeader = Prev.OffsetFromLeader +
Offset;
2015 <<
" OffsetFromLeader: " << NewOffsetFromLeader <<
"\n");
2016 return ChainElem{NewElement, NewOffsetFromLeader};
2020 FixedVectorType *VecTy) {
2026 for (
const ChainElem &
E :
C) {
2030 (
E.OffsetFromLeader -
C[0].OffsetFromLeader).getZExtValue();
2033 if (FixedVectorType *VT =
2035 for (
unsigned J = 0; J < VT->getNumElements(); ++J)
2036 MaskElts[VecIdx + J] = Builder.
getInt1(
true);
2038 MaskElts[VecIdx] = Builder.
getInt1(
true);
2043void Vectorizer::deleteExtraElements() {
2044 for (
auto *ExtraElement : ExtraElements) {
2046 [[maybe_unused]]
bool Deleted =
2048 assert(
Deleted &&
"Extra Load should always be trivially dead");
2054 ExtraElement->eraseFromParent();
2059 ExtraElements.clear();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static bool isEqual(const Function &Caller, const Function &Callee)
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< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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.
static bool runOnFunction(Function &F, bool PostInlining)
Module.h This file contains the declarations for the Module class.
static bool checkNoWrapFlags(Instruction *I, bool Signed)
static bool checkIfSafeAddSequence(const APInt &IdxDiff, Instruction *AddOpA, unsigned MatchingOpIdxA, Instruction *AddOpB, unsigned MatchingOpIdxB, bool Signed)
This file implements a map that provides insertion order iteration.
This file provides utility analysis objects describing memory locations.
static bool isAddLike(const SDValue V)
static bool isInvariantLoad(const Instruction *I, const Value *Ptr, const bool IsKernelFn)
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
Provides some synthesis utilities to produce sequences of values.
This file defines the SmallPtrSet class.
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)
static bool isSafeToMove(const MachineOperand *Def, const MachineOperand *Use, const MachineInstr *Insert, const WebAssemblyFunctionInfo &MFI, const MachineRegisterInfo &MRI, bool Optimize)
A manager for alias analyses.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
Class for arbitrary precision integers.
void clearBit(unsigned BitPosition)
Set a given bit to 0.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
static APInt getMaxValue(unsigned numBits)
Gets maximum unsigned value of APInt for specific bit width.
APInt abs() const
Get the absolute value.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool isNegative() const
Determine sign of this APInt.
bool sle(const APInt &RHS) const
Signed less or equal comparison.
LLVM_ABI APInt sextOrTrunc(unsigned width) const
Sign extend or truncate to width.
bool ule(const APInt &RHS) const
Unsigned less or equal comparison.
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
bool sge(const APInt &RHS) const
Signed greater or equal comparison.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
AnalysisUsage & addRequired()
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
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.
A function analysis which provides an AssumptionCache.
An immutable pass that tracks lazily created AssumptionCache objects.
A cache of @llvm.assume calls within a function.
LLVM Basic Block Representation.
InstListType::reverse_iterator reverse_iterator
InstListType::iterator iterator
Instruction iterators...
ModRefInfo getModRefInfo(const Instruction *I, const std::optional< MemoryLocation > &OptLoc)
Represents analyses that only rely on functions' control flow.
This is the shared class of boolean and integer constants.
const APInt * getSingleElement() const
If this set contains a single element, return it, otherwise return null.
bool isSingleElement() const
Return true if this set contains exactly one member.
LLVM_ABI APInt getUnsignedMax() const
Return the largest unsigned value contained in the ConstantRange.
static LLVM_ABI Constant * get(ArrayRef< Constant * > V)
iterator find(const_arg_type_t< KeyT > Val)
ValueT & at(const_arg_type_t< KeyT > Val)
Return the entry for the specified key, or abort if no such entry exists.
Analysis pass which computes a DominatorTree.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
unsigned getNumElements() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
FunctionPass class - This class is used to implement most global optimizations.
Legacy wrapper pass to provide the GlobalsAAResult object.
ConstantInt * getInt1(bool V)
Get a constant value representing either true or false.
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
LoadInst * CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, const char *Name)
LLVM_ABI CallInst * CreateMaskedLoad(Type *Ty, Value *Ptr, Align Alignment, Value *Mask, Value *PassThru=nullptr, const Twine &Name="")
Create a call to Masked Load intrinsic.
Value * CreatePtrAdd(Value *Ptr, Value *Offset, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
Value * CreateBitOrPointerCast(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")
LLVM_ABI CallInst * CreateMaskedStore(Value *Val, Value *Ptr, Align Alignment, Value *Mask)
Create a call to Masked Store intrinsic.
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, bool isVolatile=false)
ConstantInt * getInt(const APInt &AI)
Get a constant integer value.
LLVM_ABI bool hasNoUnsignedWrap() const LLVM_READONLY
Determine whether the no unsigned wrap flag is set.
LLVM_ABI bool hasNoSignedWrap() const LLVM_READONLY
Determine whether the no signed wrap flag is set.
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
LLVM_ABI void moveBefore(InstListType::iterator InsertPos)
Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...
LLVM_ABI bool comesBefore(const Instruction *Other) const
Given an instruction Other in the same basic block as this instruction, return true if this instructi...
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
An instruction for reading from memory.
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
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 LLVM_ABI MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
Pass interface - Implemented by all 'passes'.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Legacy wrapper pass to provide the SCEVAAResult object.
Analysis pass that exposes the ScalarEvolution for a function.
The main scalar evolution driver.
LLVM_ABI const SCEV * getMinusSCEV(SCEVUse LHS, SCEVUse RHS, SCEVFlags Flags=SCEV::FlagNone, unsigned Depth=0)
Return LHS-RHS.
LLVM_ABI const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
ConstantRange getSignedRange(const SCEV *S)
Determine the signed range for a particular SCEV.
ConstantRange getUnsignedRange(const SCEV *S)
Determine the unsigned range for a particular SCEV.
LLVM_ABI const SCEV * getCouldNotCompute()
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
reference emplace_back(ArgTypes &&... Args)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Value * getPointerOperand()
Analysis pass providing the TargetTransformInfo.
bool isVectorTy() const
True if this is an instance of VectorType.
bool isPointerTy() const
True if this is an instance of PointerType.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isPtrOrPtrVectorTy() const
Return true if this is a pointer type or a vector of pointer types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
const Value * stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL, APInt &Offset) const
This is a wrapper around stripAndAccumulateConstantOffsets with the in-bounds requirement set to fals...
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
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.
TypeSize getSequentialElementStride(const DataLayout &DL) const
Value * getOperand() const
const ParentTy * getParent() const
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
This class implements an extremely fast bulk output stream that can only output to a stream.
void push_front(reference Node)
Insert a node at the front; never copies.
void remove(reference N)
Remove a node by reference; never deletes.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
Abstract Attribute helper functions.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
const APInt & smax(const APInt &A, const APInt &B)
Determine the larger of two APInts considered to be signed.
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.
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
ElementType
The element type of an SRV or UAV resource.
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
auto min_element(R &&Range)
Provide wrappers to std::min_element which take ranges instead of having to pass begin/end explicitly...
unsigned getLoadStoreAddressSpace(const Value *I)
A helper function that returns the address space of the pointer operand of load or store instruction.
LLVM_ABI bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, std::function< void(Value *)> AboutToDeleteCallback=std::function< void(Value *)>())
If the specified value is a trivially dead instruction, delete it.
RelativeUniformCounterPtr Values
@ Known
Known to have no common set bits.
LLVM_ABI Align getOrEnforceKnownAlignment(Value *V, MaybeAlign PrefAlign, const DataLayout &DL, const Instruction *CtxI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr)
Try to ensure that the alignment of V is at least PrefAlign bytes.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
APFloat abs(APFloat X)
Returns the absolute value of the argument.
const Value * getLoadStorePointerOperand(const Value *V)
A helper function that returns the pointer operand of a load or store instruction.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LLVM_ABI Pass * createLoadStoreVectorizerPass()
Create a legacy pass manager instance of the LoadStoreVectorizer pass.
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
Align getLoadStoreAlignment(const Value *I)
A helper function that returns the alignment of load or store instruction.
LLVM_ABI Instruction * propagateMetadata(Instruction *I, ArrayRef< Value * > VL)
Specifically, let Kinds = [MD_tbaa, MD_alias_scope, MD_noalias, MD_fpmath, MD_nontemporal,...
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.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
bool isModSet(const ModRefInfo MRI)
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 >
generic_gep_type_iterator<> gep_type_iterator
bool isModOrRefSet(const ModRefInfo MRI)
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
auto post_order(const T &G)
Post-order traversal of a graph.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
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_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
ModRefInfo
Flags indicating whether a memory access modifies or references memory.
auto max_element(R &&Range)
Provide wrappers to std::max_element which take ranges instead of having to pass begin/end explicitly...
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isGuaranteedToTransferExecutionToSuccessor(const Instruction *I)
Return true if this function can prove that the instruction I will always transfer execution to one o...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
gep_type_iterator gep_type_begin(const User *GEP)
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
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.
Type * getLoadStoreType(const Value *I)
A helper function that returns the type of a load or store instruction.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
@ End
Run the machine verifier once, at the end of the pipeline.
AAResults AliasAnalysis
Temporary typedef for legacy code that uses a generic AliasAnalysis pointer or reference.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.