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) {
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),
262 DL(F.getDataLayout()), Builder(SE.
getContext()) {}
267 static const unsigned MaxDepth = 3;
276 bool runOnEquivalenceClass(
const EqClassKey &EqClassKey,
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;
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,
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);
1418 if (OtherInstrB &&
isAddLike(OtherInstrB) &&
1423 if (OtherInstrB->
getOperand(0) == OtherOperandA &&
1428 if (OtherInstrA &&
isAddLike(OtherInstrA) &&
1433 if (OtherInstrA->
getOperand(0) == OtherOperandB &&
1439 if (OtherInstrA && OtherInstrB &&
isAddLike(OtherInstrA) &&
1456std::optional<APInt> Vectorizer::getConstantOffsetComplexAddrs(
1458 LLVM_DEBUG(
dbgs() <<
"LSV: getConstantOffsetComplexAddrs PtrA=" << *PtrA
1459 <<
" PtrB=" << *PtrB <<
" ContextInst=" << *ContextInst
1460 <<
" Depth=" <<
Depth <<
"\n");
1464 return getConstantOffsetSelects(PtrA, PtrB, ContextInst,
Depth);
1468 if (GEPA->getNumOperands() != GEPB->getNumOperands() ||
1469 GEPA->getPointerOperand() != GEPB->getPointerOperand() ||
1470 GEPA->getSourceElementType() != GEPB->getSourceElementType())
1471 return std::nullopt;
1474 for (
unsigned I = 0,
E = GEPA->getNumIndices() - 1;
I <
E; ++
I) {
1476 return std::nullopt;
1485 return std::nullopt;
1491 return std::nullopt;
1499 return std::nullopt;
1501 const SCEV *OffsetSCEVA = SE.
getSCEV(ValA);
1502 const SCEV *OffsetSCEVB = SE.
getSCEV(OpB);
1503 const SCEV *IdxDiffSCEV = SE.
getMinusSCEV(OffsetSCEVB, OffsetSCEVA);
1505 return std::nullopt;
1509 return std::nullopt;
1512 LLVM_DEBUG(
dbgs() <<
"LSV: getConstantOffsetComplexAddrs IdxDiff=" << IdxDiff
1533 for (
unsigned MatchingOpIdxA : {0, 1})
1534 for (
unsigned MatchingOpIdxB : {0, 1})
1558 Safe = BitsAllowedToBeSet.
uge(IdxDiff.
abs());
1566 Value *CheckVal = IdxDiff.
sge(0) ? ValA : OpB;
1574 return IdxDiff * Stride;
1575 return std::nullopt;
1578std::optional<APInt> Vectorizer::getConstantOffsetSelects(
1580 if (
Depth++ == MaxDepth)
1581 return std::nullopt;
1585 if (SelectA->getCondition() != SelectB->getCondition())
1586 return std::nullopt;
1587 LLVM_DEBUG(
dbgs() <<
"LSV: getConstantOffsetSelects, PtrA=" << *PtrA
1588 <<
", PtrB=" << *PtrB <<
", ContextInst="
1589 << *ContextInst <<
", Depth=" <<
Depth <<
"\n");
1590 std::optional<APInt> TrueDiff = getConstantOffset(
1591 SelectA->getTrueValue(), SelectB->getTrueValue(), ContextInst,
Depth);
1593 return std::nullopt;
1594 std::optional<APInt> FalseDiff =
1595 getConstantOffset(SelectA->getFalseValue(), SelectB->getFalseValue(),
1596 ContextInst,
Depth);
1597 if (TrueDiff == FalseDiff)
1601 return std::nullopt;
1604void Vectorizer::mergeEquivalenceClasses(EquivalenceClassMap &EQClasses)
const {
1605 if (EQClasses.size() < 2)
1610 static_assert(std::tuple_size_v<EqClassKey> == 4,
1611 "EqClassKey has changed - EqClassReducedKey needs changes too");
1612 using EqClassReducedKey =
1613 std::tuple<std::tuple_element_t<1, EqClassKey> ,
1614 std::tuple_element_t<2, EqClassKey> ,
1615 std::tuple_element_t<3, EqClassKey> >;
1616 using ECReducedKeyToUnderlyingObjectMap =
1617 MapVector<EqClassReducedKey,
1618 SmallPtrSet<std::tuple_element_t<0, EqClassKey>, 4>>;
1623 ECReducedKeyToUnderlyingObjectMap RedKeyToUOMap;
1624 bool FoundPotentiallyOptimizableEC =
false;
1625 for (
const auto &EC : EQClasses) {
1626 const auto &
Key =
EC.first;
1627 EqClassReducedKey RedKey{std::get<1>(
Key), std::get<2>(
Key),
1629 auto &UOMap = RedKeyToUOMap[RedKey];
1631 if (UOMap.size() > 1)
1632 FoundPotentiallyOptimizableEC =
true;
1634 if (!FoundPotentiallyOptimizableEC)
1638 dbgs() <<
"LSV: mergeEquivalenceClasses: before merging:\n";
1639 for (
const auto &EC : EQClasses) {
1640 dbgs() <<
" Key: {" <<
EC.first <<
"}\n";
1641 for (
const auto &Inst :
EC.second)
1642 dbgs() <<
" Inst: " << *Inst <<
'\n';
1646 dbgs() <<
"LSV: mergeEquivalenceClasses: RedKeyToUOMap:\n";
1647 for (
const auto &RedKeyToUO : RedKeyToUOMap) {
1648 dbgs() <<
" Reduced key: {" << std::get<0>(RedKeyToUO.first) <<
", "
1649 << std::get<1>(RedKeyToUO.first) <<
", "
1650 <<
static_cast<int>(std::get<2>(RedKeyToUO.first)) <<
"} --> "
1651 << RedKeyToUO.second.size() <<
" underlying objects:\n";
1652 for (
auto UObject : RedKeyToUO.second)
1653 dbgs() <<
" " << *UObject <<
'\n';
1657 using UObjectToUObjectMap = DenseMap<const Value *, const Value *>;
1660 auto GetUltimateTargets =
1661 [](SmallPtrSetImpl<const Value *> &UObjects) -> UObjectToUObjectMap {
1662 UObjectToUObjectMap IndirectionMap;
1663 for (
const auto *UObject : UObjects) {
1664 const unsigned MaxLookupDepth = 1;
1666 if (UltimateTarget != UObject)
1667 IndirectionMap[UObject] = UltimateTarget;
1669 UObjectToUObjectMap UltimateTargetsMap;
1670 for (
const auto *UObject : UObjects) {
1672 auto It = IndirectionMap.find(Target);
1673 for (; It != IndirectionMap.end(); It = IndirectionMap.find(Target))
1675 UltimateTargetsMap[UObject] =
Target;
1677 return UltimateTargetsMap;
1682 for (
auto &[RedKey, UObjects] : RedKeyToUOMap) {
1683 if (UObjects.size() < 2)
1685 auto UTMap = GetUltimateTargets(UObjects);
1686 for (
const auto &[UObject, UltimateTarget] : UTMap) {
1687 if (UObject == UltimateTarget)
1690 EqClassKey KeyFrom{UObject, std::get<0>(RedKey), std::get<1>(RedKey),
1691 std::get<2>(RedKey)};
1692 EqClassKey KeyTo{UltimateTarget, std::get<0>(RedKey), std::get<1>(RedKey),
1693 std::get<2>(RedKey)};
1696 const auto &VecTo = EQClasses[KeyTo];
1697 const auto &VecFrom = EQClasses[KeyFrom];
1698 SmallVector<Instruction *, 8> MergedVec;
1699 std::merge(VecFrom.begin(), VecFrom.end(), VecTo.begin(), VecTo.end(),
1700 std::back_inserter(MergedVec),
1701 [](Instruction *
A, Instruction *
B) {
1702 return A && B && A->comesBefore(B);
1704 EQClasses[KeyTo] = std::move(MergedVec);
1705 EQClasses.erase(KeyFrom);
1709 dbgs() <<
"LSV: mergeEquivalenceClasses: after merging:\n";
1710 for (
const auto &EC : EQClasses) {
1711 dbgs() <<
" Key: {" <<
EC.first <<
"}\n";
1712 for (
const auto &Inst :
EC.second)
1713 dbgs() <<
" Inst: " << *Inst <<
'\n';
1721 EquivalenceClassMap Ret;
1723 auto GetUnderlyingObject = [](
const Value *Ptr) ->
const Value * {
1732 return Sel->getCondition();
1743 if ((LI && !LI->
isSimple()) || (SI && !
SI->isSimple()))
1757 if (
DL.hasExternalState(Ty))
1762 unsigned TySize =
DL.getTypeSizeInBits(Ty);
1763 if ((TySize % 8) != 0)
1777 unsigned VF = VecRegSize / TySize;
1782 (VecTy && !
isPowerOf2_32(
DL.getTypeSizeInBits(VecTy->getScalarType()))))
1786 if (TySize > VecRegSize / 2 ||
1790 Ret[{GetUnderlyingObject(Ptr), AS,
1796 mergeEquivalenceClasses(Ret);
1805 unsigned ASPtrBits =
DL.getIndexSizeInBits(AS);
1809 for (
size_t I = 1;
I < Instrs.
size(); ++
I) {
1810 assert(Instrs[
I - 1]->comesBefore(Instrs[
I]));
1819 struct InstrListElem : ilist_node<InstrListElem>,
1820 std::pair<Instruction *, Chain> {
1821 explicit InstrListElem(Instruction *
I)
1824 struct InstrListElemDenseMapInfo {
1825 using IInfo = DenseMapInfo<Instruction *>;
1826 static unsigned getHashValue(
const InstrListElem *
E) {
1827 return IInfo::getHashValue(
E->first);
1829 static bool isEqual(
const InstrListElem *
A,
const InstrListElem *
B) {
1830 return IInfo::isEqual(
A->first,
B->first);
1833 SpecificBumpPtrAllocator<InstrListElem>
Allocator;
1834 simple_ilist<InstrListElem> MRU;
1835 DenseSet<InstrListElem *, InstrListElemDenseMapInfo> Chains;
1840 for (Instruction *
I : Instrs) {
1841 constexpr int MaxChainsToTry = 64;
1843 bool MatchFound =
false;
1844 auto ChainIter = MRU.
begin();
1845 for (
size_t J = 0; J < MaxChainsToTry && ChainIter != MRU.
end();
1847 if (std::optional<APInt>
Offset = getConstantOffset(
1851 (ChainIter->first->comesBefore(
I) ?
I : ChainIter->first))) {
1854 ChainIter->second.emplace_back(
I,
Offset.value());
1864 APInt ZeroOffset(ASPtrBits, 0);
1865 InstrListElem *
E =
new (
Allocator.Allocate()) InstrListElem(
I);
1866 E->second.emplace_back(
I, ZeroOffset);
1872 std::vector<Chain> Ret;
1873 Ret.reserve(Chains.
size());
1876 if (
E.second.size() > 1)
1877 Ret.emplace_back(std::move(
E.second));
1881std::optional<APInt> Vectorizer::getConstantOffset(
Value *PtrA,
Value *PtrB,
1882 Instruction *ContextInst,
1885 <<
", PtrB=" << *PtrB <<
", ContextInst= " << *ContextInst
1886 <<
", Depth=" <<
Depth <<
"\n");
1889 unsigned OrigBitWidth =
DL.getIndexTypeSizeInBits(PtrA->
getType());
1890 APInt OffsetA(OrigBitWidth, 0);
1891 APInt OffsetB(OrigBitWidth, 0);
1894 unsigned NewPtrBitWidth =
DL.getTypeStoreSizeInBits(PtrA->
getType());
1895 if (NewPtrBitWidth !=
DL.getTypeStoreSizeInBits(PtrB->
getType()))
1896 return std::nullopt;
1901 assert(OffsetA.getSignificantBits() <= NewPtrBitWidth &&
1902 OffsetB.getSignificantBits() <= NewPtrBitWidth);
1904 OffsetA = OffsetA.sextOrTrunc(NewPtrBitWidth);
1905 OffsetB = OffsetB.sextOrTrunc(NewPtrBitWidth);
1907 return (OffsetB - OffsetA).sextOrTrunc(OrigBitWidth);
1912 LLVM_DEBUG(
dbgs() <<
"LSV: SCEV PtrB - PtrA =" << *DistScev <<
"\n");
1918 return (OffsetB - OffsetA + Dist).
sextOrTrunc(OrigBitWidth);
1921 if (std::optional<APInt> Diff =
1922 getConstantOffsetComplexAddrs(PtrA, PtrB, ContextInst,
Depth))
1923 return (OffsetB - OffsetA + Diff->sext(OffsetB.getBitWidth()))
1924 .sextOrTrunc(OrigBitWidth);
1925 return std::nullopt;
1928bool Vectorizer::accessIsAllowedAndFast(
unsigned SizeBytes,
unsigned AS,
1930 unsigned VecElemBits)
const {
1936 unsigned VectorizedSpeed = 0;
1938 F.getContext(), SizeBytes * 8, AS, Alignment, &VectorizedSpeed);
1939 if (!AllowsMisaligned) {
1941 dbgs() <<
"LSV: Access of " << SizeBytes <<
"B in addrspace " << AS
1942 <<
" with alignment " <<
Alignment.value()
1943 <<
" is misaligned, and therefore can't be vectorized.\n");
1947 unsigned ElementwiseSpeed = 0;
1948 (
TTI).allowsMisalignedMemoryAccesses((
F).
getContext(), VecElemBits, AS,
1949 Alignment, &ElementwiseSpeed);
1950 if (VectorizedSpeed < ElementwiseSpeed) {
1951 LLVM_DEBUG(
dbgs() <<
"LSV: Access of " << SizeBytes <<
"B in addrspace "
1952 << AS <<
" with alignment " <<
Alignment.value()
1953 <<
" has relative speed " << VectorizedSpeed
1954 <<
", which is lower than the elementwise speed of "
1956 <<
". Therefore this access won't be vectorized.\n");
1962ChainElem Vectorizer::createExtraElementAfter(
const ChainElem &Prev,
Type *Ty,
1963 APInt
Offset, StringRef Prefix,
1969 PrevLoad->getPointerOperand(), Builder.
getInt(
Offset), Prefix +
"GEP");
1970 LLVM_DEBUG(
dbgs() <<
"LSV: Extra GEP Created: \n" << *NewGep <<
"\n");
1977 LLVM_DEBUG(
dbgs() <<
"LSV: Extra GEP Created: \n" << *NewGep <<
"\n");
1987 ExtraElements.
insert(NewElement);
1989 APInt NewOffsetFromLeader = Prev.OffsetFromLeader +
Offset;
1992 <<
" OffsetFromLeader: " << NewOffsetFromLeader <<
"\n");
1993 return ChainElem{NewElement, NewOffsetFromLeader};
1997 FixedVectorType *VecTy) {
2003 for (
const ChainElem &
E :
C) {
2007 (
E.OffsetFromLeader -
C[0].OffsetFromLeader).getZExtValue();
2010 if (FixedVectorType *VT =
2012 for (
unsigned J = 0; J < VT->getNumElements(); ++J)
2013 MaskElts[VecIdx + J] = Builder.
getInt1(
true);
2015 MaskElts[VecIdx] = Builder.
getInt1(
true);
2020void Vectorizer::deleteExtraElements() {
2021 for (
auto *ExtraElement : ExtraElements) {
2023 [[maybe_unused]]
bool Deleted =
2025 assert(
Deleted &&
"Extra Load should always be trivially dead");
2031 ExtraElement->eraseFromParent();
2036 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 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 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.
bool sge(const APInt &RHS) const
Signed greater or equal comparison.
int64_t getSExtValue() const
Get sign extended value.
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.
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)
ValueT & at(const_arg_type_t< KeyT > Val)
Return the entry for the specified key, or abort if no such entry exists.
iterator find(const_arg_type_t< KeyT > Val)
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 * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
LLVM_ABI const SCEV * getMinusSCEV(SCEVUse LHS, SCEVUse RHS, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Return LHS-RHS.
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.
DXILDebugInfoMap run(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.
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.
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.
LLVM_ABI Align getOrEnforceKnownAlignment(Value *V, MaybeAlign PrefAlign, const DataLayout &DL, const Instruction *CxtI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr)
Try to ensure that the alignment of V is at least PrefAlign bytes.
bool isModSet(const ModRefInfo MRI)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CxtI=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...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
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.
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.
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
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.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
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.