73#define DEBUG_TYPE "loop-accesses"
77 cl::desc(
"Sets the SIMD width. Zero is autoselect."),
83 cl::desc(
"Sets the vectorization interleave count. "
84 "Zero is autoselect."),
91 cl::desc(
"When performing memory disambiguation checks at runtime do not "
92 "generate more than this number of comparisons (default = 8)."),
99 cl::desc(
"Maximum number of comparisons done when trying to merge "
100 "runtime memory checks. (default = 100)"),
109 cl::desc(
"Maximum number of dependences collected by "
110 "loop-access analysis (default = 100)"),
126 cl::desc(
"Enable symbolic stride memory access versioning"));
131 "store-to-load-forwarding-conflict-detection",
cl::Hidden,
132 cl::desc(
"Enable conflict detection in loop-access analysis"),
137 cl::desc(
"Maximum recursion depth when finding forked SCEVs (default = 5)"),
142 cl::desc(
"Speculate that non-constant strides are unit in LAA"),
148 "Hoist inner loop runtime memory checks to outer loop if possible"),
153 return ::VectorizationInterleave.getNumOccurrences() > 0;
175 <<
" by: " << *Expr <<
"\n");
181 :
High(RtCheck.Pointers[Index].End),
Low(RtCheck.Pointers[Index].Start),
213 std::optional<ScalarEvolution::LoopGuards> &LoopGuards) {
219 bool CheckForNonNull;
220 Value *StartPtrV = StartPtr->getValue();
224 DL, CheckForNonNull,
nullptr);
228 if (DerefBytes && CheckForNonNull)
236 Instruction *CtxI = &*L->getHeader()->getFirstNonPHIIt();
237 if (
BasicBlock *LoopPred = L->getLoopPredecessor()) {
239 CtxI = LoopPred->getTerminator();
242 StartPtrV, Attribute::Dereferenceable, *AC,
251 DerefBytesSCEV = SE.
getUMaxExpr(DerefBytesSCEV, DerefRKSCEV);
256 if (DerefBytesSCEV->
isZero())
285 if (!DistToLastIter) {
306 const SCEV *MaxOffset;
307 if (IsKnownNonNegative) {
322 MaxOffset = StartOffset;
344 assert(AR->getLoop() == L &&
345 "trying to check for AddRec in different loop");
361static std::pair<const SCEV *, const SCEV *>
365 if (!PtrAdd || !PtrAdd->hasNoUnsignedWrap())
366 return {
nullptr,
nullptr};
369 return Op->getType()->isPointerTy();
372 return {
nullptr,
nullptr};
377 return {
nullptr,
nullptr};
383 return {
nullptr,
nullptr};
386 "Start must be provably <= End for monotonic expressions");
394 DenseMap<std::pair<const SCEV *, const SCEV *>,
397 std::optional<ScalarEvolution::LoopGuards> &LoopGuards) {
408 const Loop *Lp,
const SCEV *PtrExpr,
const SCEV *EltSizeSCEV,
410 DenseMap<std::pair<const SCEV *, const SCEV *>,
413 std::optional<ScalarEvolution::LoopGuards> &LoopGuards) {
414 std::pair<const SCEV *, const SCEV *> *PtrBoundsPair;
417 {{PtrExpr, EltSizeSCEV},
421 PtrBoundsPair = &Iter->second;
429 ScStart = ScEnd = PtrExpr;
431 ScStart = AR->getStart();
437 ScEnd = AR->evaluateAtIteration(BTC, *SE);
447 DT, AC, LoopGuards)) {
448 ScEnd = AR->evaluateAtIteration(MaxBTC, *SE);
457 const SCEV *Step = AR->getStepRecurrence(*SE);
462 if (CStep->getValue()->isNegative())
485 std::pair<const SCEV *, const SCEV *> Res = {ScStart, ScEnd};
487 *PtrBoundsPair = Res;
494 Type *AccessTy,
bool WritePtr,
495 unsigned DepSetId,
unsigned ASId,
501 Lp, PtrExpr, AccessTy, BTC, SymbolicMaxBTC, PSE.
getSE(),
502 &DC.getPointerBounds(), DC.getDT(), DC.getAC(), LoopGuards);
505 "must be able to compute both start and end expressions");
506 Pointers.emplace_back(Ptr, ScStart, ScEnd, WritePtr, DepSetId, ASId, PtrExpr,
510bool RuntimePointerChecking::tryToCreateDiffCheck(
533 if (AccSrc.
size() != 1 || AccSink.
size() != 1)
537 if (AccSink[0] < AccSrc[0])
541 const SCEV *SrcStart;
542 const SCEV *SinkStart;
544 if (!
match(Src->Expr,
563 std::max(
DL.getTypeAllocSize(SrcTy),
DL.getTypeAllocSize(DstTy));
589 const Loop *StartARLoop = SrcStartAR->getLoop();
590 if (StartARLoop == SinkStartAR->getLoop() &&
595 SrcStartAR->getStepRecurrence(*SE) !=
596 SinkStartAR->getStepRecurrence(*SE)) {
597 LLVM_DEBUG(
dbgs() <<
"LAA: Not creating diff runtime check, since these "
598 "cannot be hoisted out of the outer loop\n");
604 <<
"SrcStart: " << *SrcStartInt <<
'\n'
605 <<
"SinkStartInt: " << *SinkStartInt <<
'\n');
606 DiffChecks.emplace_back(SrcStartInt, SinkStartInt, AllocSize,
607 Src->NeedsFreeze ||
Sink->NeedsFreeze);
612 SmallVector<RuntimePointerCheck, 4> Checks;
620 CanUseDiffCheck = CanUseDiffCheck && tryToCreateDiffCheck(CGI, CGJ);
621 Checks.emplace_back(&CGI, &CGJ);
630 assert(Checks.empty() &&
"Checks is not empty");
631 groupChecks(DepCands);
637 for (
const auto &
I : M.Members)
638 for (
const auto &J :
N.Members)
651 return Diff->isNegative() ? J :
I;
658 RtCheck.
Pointers[Index].PointerValue->getType()->getPointerAddressSpace(),
659 RtCheck.
Pointers[Index].NeedsFreeze, *RtCheck.SE);
663 const SCEV *End,
unsigned AS,
667 "all pointers in a checking group must be in the same address space");
693void RuntimePointerChecking::groupChecks(
735 unsigned TotalComparisons = 0;
738 for (
unsigned Index = 0; Index <
Pointers.size(); ++Index)
739 PositionMap[
Pointers[Index].PointerValue].push_back(Index);
772 auto PointerI = PositionMap.
find(M.getPointer());
775 if (PointerI == PositionMap.
end())
777 for (
unsigned Pointer : PointerI->second) {
794 if (Group.addPointer(Pointer, *
this)) {
804 Groups.emplace_back(Pointer, *
this);
817 return (PtrToPartition[PtrIdx1] != -1 &&
818 PtrToPartition[PtrIdx1] == PtrToPartition[PtrIdx2]);
841 for (
const auto &[Idx, CG] :
enumerate(CheckingGroups))
842 PtrIndices[&CG] = Idx;
848 unsigned Depth)
const {
851 for (
const auto &[Check1, Check2] : Checks) {
852 const auto &
First = Check1->Members, &Second = Check2->Members;
854 OS.
indent(
Depth + 2) <<
"Comparing group GRP" << PtrIndices.at(Check1)
856 for (
unsigned K :
First)
858 OS.
indent(
Depth + 2) <<
"Against group GRP" << PtrIndices.at(Check2)
860 for (
unsigned K : Second)
873 OS.
indent(
Depth + 2) <<
"Group GRP" << PtrIndices.at(&CG) <<
":\n";
874 OS.
indent(
Depth + 4) <<
"(Low: " << *CG.Low <<
" High: " << *CG.High
876 for (
unsigned Member : CG.Members) {
888class AccessAnalysis {
890 using MemAccessInfo =
897 : TheLoop(TheLoop), BAA(*
AA), AST(BAA), LI(LI), DT(DT), DepCands(DA),
898 PSE(PSE), LoopAliasScopes(LoopAliasScopes) {
900 BAA.enableCrossIterationMode();
906 AST.add(adjustLoc(
Loc));
907 Accesses[MemAccessInfo(Ptr,
false)].insert(AccessTy);
909 ReadOnlyPtr.insert(Ptr);
913 void addStore(
const MemoryLocation &Loc,
Type *AccessTy) {
915 AST.add(adjustLoc(Loc));
916 Accesses[MemAccessInfo(Ptr,
true)].insert(AccessTy);
926 bool createCheckForAccess(RuntimePointerChecking &RtCheck,
929 DenseMap<Value *, unsigned> &DepSetId,
930 Loop *TheLoop,
unsigned &RunningDepId,
931 unsigned ASId,
bool Assume);
942 bool canCheckPtrAtRT(RuntimePointerChecking &RtCheck,
Loop *TheLoop,
944 Value *&UncomputablePtr,
bool AllowPartial,
945 const MemoryDepChecker &DepChecker);
949 void buildDependenceSets();
956 bool isDependencyCheckNeeded()
const {
return !CheckDeps.empty(); }
959 void resetDepChecks(MemoryDepChecker &DepChecker) {
967 using PtrAccessMap = MapVector<MemAccessInfo, SmallSetVector<Type *, 1>>;
971 MemoryLocation adjustLoc(MemoryLocation Loc)
const {
981 MDNode *adjustAliasScopeList(MDNode *ScopeList)
const {
988 return LoopAliasScopes.contains(cast<MDNode>(Scope));
1000 const Loop *TheLoop;
1006 SmallPtrSet<Value*, 16> ReadOnlyPtr;
1013 AliasSetTracker AST;
1033 bool IsRTCheckAnalysisNeeded =
false;
1036 PredicatedScalarEvolution &PSE;
1038 DenseMap<Value *, SmallVector<const Value *, 16>> UnderlyingObjects;
1042 SmallPtrSetImpl<MDNode *> &LoopAliasScopes;
1047std::optional<int64_t>
1052 LLVM_DEBUG(
dbgs() <<
"LAA: Bad stride - Scalable object: " << *AccessTy
1054 return std::nullopt;
1060 dbgs() <<
"LAA: Bad stride - Not striding over innermost loop ";
1062 dbgs() << *Ptr <<
" ";
1064 dbgs() <<
"SCEV: " << *AR <<
"\n";
1066 return std::nullopt;
1073 const APInt *APStepVal;
1076 dbgs() <<
"LAA: Bad stride - Not a constant strided ";
1078 dbgs() << *Ptr <<
" ";
1079 dbgs() <<
"SCEV: " << *AR <<
"\n";
1081 return std::nullopt;
1085 TypeSize AllocSize =
DL.getTypeAllocSize(AccessTy);
1089 std::optional<int64_t> StepVal = APStepVal->
trySExtValue();
1091 return std::nullopt;
1094 return *StepVal %
Size ? std::nullopt : std::make_optional(*StepVal /
Size);
1103 std::optional<int64_t> Stride = std::nullopt,
1118 GEP &&
GEP->hasNoUnsignedSignedWrap()) {
1121 if (L->getHeader() == L->getLoopLatch() ||
1123 if (getLoadStorePointerOperand(U) != GEP)
1125 BasicBlock *UserBB = cast<Instruction>(U)->getParent();
1126 if (!L->contains(UserBB))
1128 return !LoopAccessInfo::blockNeedsPredication(UserBB, L, &DT);
1141 (Stride == 1 || Stride == -1))
1145 if (Ptr && Predicates) {
1152 <<
"LAA: Pointer: " << *Ptr <<
"\n"
1153 <<
"LAA: SCEV: " << *AR <<
"\n"
1154 <<
"LAA: Added an overflow assumption\n");
1167 while (!WorkList.
empty()) {
1169 if (!Visited.
insert(Ptr).second)
1175 if (PN && InnermostLoop.
contains(PN->getParent()) &&
1176 PN->getParent() != InnermostLoop.
getHeader()) {
1221 auto GetBinOpExpr = [&SE](
unsigned Opcode,
const SCEV *L,
const SCEV *R) {
1223 case Instruction::Add:
1225 case Instruction::Sub:
1233 unsigned Opcode =
I->getOpcode();
1235 case Instruction::GetElementPtr: {
1237 Type *SourceTy =
GEP->getSourceElementType();
1240 if (
I->getNumOperands() != 2 || SourceTy->
isVectorTy()) {
1250 bool NeedsFreeze =
any_of(BaseScevs, UndefPoisonCheck) ||
1251 any_of(OffsetScevs, UndefPoisonCheck);
1256 if (OffsetScevs.
size() == 2 && BaseScevs.
size() == 1)
1258 else if (BaseScevs.
size() == 2 && OffsetScevs.
size() == 1)
1261 ScevList.emplace_back(Scev, NeedsFreeze);
1272 for (
auto [
B, O] :
zip(BaseScevs, OffsetScevs)) {
1283 case Instruction::Select: {
1290 if (ChildScevs.
size() == 2)
1296 case Instruction::PHI: {
1301 if (
I->getNumOperands() == 2) {
1305 if (ChildScevs.
size() == 2)
1311 case Instruction::Add:
1312 case Instruction::Sub: {
1320 any_of(LScevs, UndefPoisonCheck) ||
any_of(RScevs, UndefPoisonCheck);
1325 if (LScevs.
size() == 2 && RScevs.
size() == 1)
1327 else if (RScevs.
size() == 2 && LScevs.
size() == 1)
1330 ScevList.emplace_back(Scev, NeedsFreeze);
1334 for (
auto [L, R] :
zip(LScevs, RScevs))
1335 ScevList.emplace_back(GetBinOpExpr(Opcode,
get<0>(L),
get<0>(R)),
1341 LLVM_DEBUG(
dbgs() <<
"ForkedPtr unhandled instruction: " << *
I <<
"\n");
1351 Loop *TheLoop,
unsigned &RunningDepId,
1352 unsigned ASId,
bool Assume) {
1360 "Must have some runtime-check pointer candidates");
1364 auto IsLoopInvariantOrAR =
1369 if (RTCheckPtrs.
size() == 2 &&
all_of(RTCheckPtrs, IsLoopInvariantOrAR)) {
1370 LLVM_DEBUG(
dbgs() <<
"LAA: Found forked pointer: " << *Ptr <<
"\n";
1372 <<
"\t(" << Idx <<
") " << *Q.getPointer() <<
"\n");
1380 for (
auto &
P : RTCheckPtrs) {
1399 if (RTCheckPtrs.size() == 1) {
1408 if (!
isNoWrap(PSE, AR, RTCheckPtrs.size() == 1 ? Ptr :
nullptr, AccessTy,
1409 TheLoop, DT, std::nullopt,
1410 Assume ? &Predicates :
nullptr))
1415 for (
const auto &[PtrExpr, NeedsFreeze] : RTCheckPtrs) {
1421 unsigned &LeaderId = DepSetId[Leader];
1423 LeaderId = RunningDepId++;
1427 DepId = RunningDepId++;
1429 bool IsWrite =
Access.getInt();
1430 RtCheck.
insert(TheLoop, Ptr, PtrExpr, AccessTy, IsWrite, DepId, ASId, PSE,
1432 LLVM_DEBUG(
dbgs() <<
"LAA: Found a runtime check ptr:" << *Ptr <<
'\n');
1441 Value *&UncomputablePtr,
bool AllowPartial,
1445 bool CanDoRT =
true;
1447 bool MayNeedRTCheck =
false;
1448 if (!IsRTCheckAnalysisNeeded)
return true;
1456 for (
const auto &Dep : *Deps) {
1460 "Should only skip safe dependences");
1464 Instruction *Dst = Dep.getDestination(DepChecker);
1476 for (
const auto &AS : AST) {
1477 int NumReadPtrChecks = 0;
1478 int NumWritePtrChecks = 0;
1479 bool CanDoAliasSetRT =
true;
1481 auto ASPointers = AS.getPointers();
1485 unsigned RunningDepId = 1;
1493 for (
const Value *ConstPtr : ASPointers) {
1495 bool IsWrite =
Accesses.contains(MemAccessInfo(Ptr,
true));
1497 ++NumWritePtrChecks;
1505 if (NumWritePtrChecks == 0 ||
1506 (NumWritePtrChecks == 1 && NumReadPtrChecks == 0)) {
1507 assert((ASPointers.size() <= 1 ||
1509 [
this](
const Value *Ptr) {
1510 MemAccessInfo AccessWrite(
const_cast<Value *
>(Ptr),
1512 return !DepCands.
contains(AccessWrite);
1514 "Can only skip updating CanDoRT below, if all entries in AS "
1515 "are reads or there is at most 1 entry");
1519 for (
auto &
Access : AccessInfos) {
1521 if (!createCheckForAccess(RtCheck,
Access, AccessTy, StridesMap,
1522 DepSetId, TheLoop, RunningDepId, ASId,
1525 << *
Access.getPointer() <<
'\n');
1527 CanDoAliasSetRT =
false;
1541 bool NeedsAliasSetRTCheck = RunningDepId > 2 || !Retries.
empty();
1545 if (NeedsAliasSetRTCheck && !CanDoAliasSetRT) {
1549 CanDoAliasSetRT =
true;
1550 for (
const auto &[
Access, AccessTy] : Retries) {
1551 if (!createCheckForAccess(RtCheck,
Access, AccessTy, StridesMap,
1552 DepSetId, TheLoop, RunningDepId, ASId,
1554 CanDoAliasSetRT =
false;
1555 UncomputablePtr =
Access.getPointer();
1562 CanDoRT &= CanDoAliasSetRT;
1563 MayNeedRTCheck |= NeedsAliasSetRTCheck;
1572 unsigned NumPointers = RtCheck.
Pointers.size();
1573 for (
unsigned i = 0; i < NumPointers; ++i) {
1574 for (
unsigned j = i + 1;
j < NumPointers; ++
j) {
1576 if (RtCheck.
Pointers[i].DependencySetId ==
1577 RtCheck.
Pointers[j].DependencySetId)
1590 dbgs() <<
"LAA: Runtime check would require comparison between"
1591 " different address spaces\n");
1597 if (MayNeedRTCheck && (CanDoRT || AllowPartial))
1601 <<
" pointer comparisons.\n");
1608 bool CanDoRTIfNeeded = !RtCheck.
Need || CanDoRT;
1609 assert(CanDoRTIfNeeded == (CanDoRT || !MayNeedRTCheck) &&
1610 "CanDoRTIfNeeded depends on RtCheck.Need");
1611 if (!CanDoRTIfNeeded && !AllowPartial)
1613 return CanDoRTIfNeeded;
1616void AccessAnalysis::buildDependenceSets() {
1626 dbgs() <<
"\t" << *
A.getPointer() <<
" ("
1629 : (ReadOnlyPtr.contains(
A.getPointer()) ?
"read-only"
1638 for (
const auto &AS : AST) {
1639 bool AliasSetHasWrite =
false;
1643 using UnderlyingObjToAccessMap =
1645 UnderlyingObjToAccessMap ObjToLastAccess;
1648 PtrAccessMap DeferredAccesses;
1653 auto ProcessAccesses = [&](
bool UseDeferred) {
1654 PtrAccessMap &S = UseDeferred ? DeferredAccesses :
Accesses;
1659 for (
const Value *ConstPtr : AS.getPointers()) {
1664 for (
auto [AccessPtr, IsWrite] : S.keys()) {
1665 if (AccessPtr != Ptr)
1670 bool IsReadOnlyPtr = ReadOnlyPtr.contains(Ptr) && !IsWrite;
1671 if (UseDeferred && !IsReadOnlyPtr)
1675 assert(((IsReadOnlyPtr && UseDeferred) || IsWrite ||
1676 S.contains(MemAccessInfo(Ptr,
false))) &&
1677 "Alias-set pointer not in the access set?");
1679 MemAccessInfo
Access(Ptr, IsWrite);
1687 if (!UseDeferred && IsReadOnlyPtr) {
1690 DeferredAccesses.insert({
Access, {}});
1698 if ((IsWrite || IsReadOnlyPtr) && AliasSetHasWrite) {
1699 CheckDeps.push_back(
Access);
1700 IsRTCheckAnalysisNeeded =
true;
1704 AliasSetHasWrite =
true;
1712 <<
"Underlying objects for pointer " << *Ptr <<
"\n");
1713 for (
const Value *UnderlyingObj : UOs) {
1722 auto [It,
Inserted] = ObjToLastAccess.try_emplace(
1737 ProcessAccesses(
false);
1738 ProcessAccesses(
true);
1743std::optional<int64_t>
1755 if (Predicates && !AR) {
1761 LLVM_DEBUG(
dbgs() <<
"LAA: Bad stride - Not an AddRecExpr pointer " << *Ptr
1762 <<
" SCEV: " << *PtrScev <<
"\n");
1763 return std::nullopt;
1766 std::optional<int64_t> Stride =
1768 if (!ShouldCheckWrap || !Stride)
1771 if (
isNoWrap(PSE, AR, Ptr, AccessTy, Lp, DT, Stride, Predicates))
1775 dbgs() <<
"LAA: Bad stride - Pointer may wrap in the address space "
1776 << *Ptr <<
" SCEV: " << *AR <<
"\n");
1777 return std::nullopt;
1786 bool Assume,
bool ShouldCheckWrap) {
1788 std::optional<int64_t> Stride =
1789 getPtrStride(PSE, AccessTy, Ptr, Lp, DT, StridesMap, ShouldCheckWrap,
1790 Assume ? &Predicates :
nullptr);
1800 assert(PtrA && PtrB &&
"Expected non-nullptr pointers.");
1808 return std::nullopt;
1815 return std::nullopt;
1816 unsigned IdxWidth =
DL.getIndexSizeInBits(ASA);
1818 APInt OffsetA(IdxWidth, 0), OffsetB(IdxWidth, 0);
1824 std::optional<int64_t> Val;
1825 if (PtrA1 == PtrB1) {
1832 return std::nullopt;
1834 IdxWidth =
DL.getIndexSizeInBits(ASA);
1835 OffsetA = OffsetA.sextOrTrunc(IdxWidth);
1844 std::optional<APInt> Diff =
1847 return std::nullopt;
1848 Val = Diff->trySExtValue();
1852 return std::nullopt;
1854 int64_t
Size =
DL.getTypeStoreSize(ElemTyA);
1855 int64_t Dist = *Val /
Size;
1859 if (!StrictCheck || Dist *
Size == Val)
1861 return std::nullopt;
1868 VL, [](
const Value *V) {
return V->getType()->isPointerTy(); }) &&
1869 "Expected list of pointer operands.");
1872 Value *Ptr0 = VL[0];
1874 using DistOrdPair = std::pair<int64_t, unsigned>;
1876 std::set<DistOrdPair,
decltype(Compare)> Offsets(Compare);
1877 Offsets.emplace(0, 0);
1878 bool IsConsecutive =
true;
1880 std::optional<int64_t> Diff =
1888 auto [It, IsInserted] = Offsets.emplace(
Offset, Idx);
1892 IsConsecutive &= std::next(It) == Offsets.end();
1894 SortedIndices.
clear();
1895 if (!IsConsecutive) {
1898 for (
auto [Idx, Off] :
enumerate(Offsets))
1899 SortedIndices[Idx] = Off.second;
1913 std::optional<int64_t> Diff =
1922 Accesses[MemAccessInfo(Ptr, true)].push_back(AccessIdx);
1923 InstMap.push_back(SI);
1930 [
this, LI](
Value *Ptr) {
1931 Accesses[MemAccessInfo(Ptr, false)].push_back(AccessIdx);
1932 InstMap.push_back(LI);
1998bool MemoryDepChecker::couldPreventStoreLoadForward(uint64_t Distance,
1999 uint64_t TypeByteSize,
2000 unsigned CommonStride) {
2012 uint64_t MaxVFWithoutSLForwardIssuesPowerOf2 =
2014 MaxStoreLoadForwardSafeDistanceInBits);
2018 for (uint64_t VF = 2 * TypeByteSize;
2019 VF <= MaxVFWithoutSLForwardIssuesPowerOf2; VF *= 2) {
2021 MaxVFWithoutSLForwardIssuesPowerOf2 = (VF >> 1);
2026 if (MaxVFWithoutSLForwardIssuesPowerOf2 < 2 * TypeByteSize) {
2028 dbgs() <<
"LAA: Distance " << Distance
2029 <<
" that could cause a store-load forwarding conflict\n");
2034 MaxVFWithoutSLForwardIssuesPowerOf2 <
2035 MaxStoreLoadForwardSafeDistanceInBits &&
2036 MaxVFWithoutSLForwardIssuesPowerOf2 !=
2039 bit_floor(MaxVFWithoutSLForwardIssuesPowerOf2 / CommonStride);
2040 uint64_t MaxVFInBits = MaxVF * TypeByteSize * 8;
2041 MaxStoreLoadForwardSafeDistanceInBits =
2042 std::min(MaxStoreLoadForwardSafeDistanceInBits, MaxVFInBits);
2046 dbgs() <<
"LAA: strided access with Distance " << Distance
2047 <<
" that could cause a store-load forwarding conflict\n");
2072 const SCEV &MaxBTC,
const SCEV &Dist,
2095 const SCEV *CastedDist = &Dist;
2096 const SCEV *CastedProduct = Product;
2103 if (DistTypeSizeBits > ProductTypeSizeBits)
2128 assert(Stride > 1 &&
"The stride must be greater than 1");
2129 assert(TypeByteSize > 0 &&
"The type size in byte must be non-zero");
2130 assert(Distance > 0 &&
"The distance must be non-zero");
2133 if (Distance % TypeByteSize)
2152 return Distance % Stride;
2155bool MemoryDepChecker::areAccessesCompletelyBeforeOrAfter(
const SCEV *Src,
2159 const SCEV *BTC = PSE.getBackedgeTakenCount();
2160 const SCEV *SymbolicMaxBTC = PSE.getSymbolicMaxBackedgeTakenCount();
2161 ScalarEvolution &SE = *PSE.getSE();
2162 const auto &[SrcStart_, SrcEnd_] =
2164 &SE, &PointerBounds, DT, AC, LoopGuards);
2168 const auto &[SinkStart_, SinkEnd_] =
2170 &SE, &PointerBounds, DT, AC, LoopGuards);
2189 MemoryDepChecker::DepDistanceStrideAndSizeInfo>
2190MemoryDepChecker::getDependenceDistanceStrideAndSize(
2191 const AccessAnalysis::MemAccessInfo &
A, Instruction *AInst,
2192 const AccessAnalysis::MemAccessInfo &
B, Instruction *BInst) {
2193 const auto &
DL = InnermostLoop->getHeader()->getDataLayout();
2194 auto &SE = *PSE.getSE();
2195 const auto &[APtr, AIsWrite] =
A;
2196 const auto &[BPtr, BIsWrite] =
B;
2199 if (!AIsWrite && !BIsWrite)
2206 if (APtr->getType()->getPointerAddressSpace() !=
2207 BPtr->getType()->getPointerAddressSpace())
2211 std::optional<int64_t> StrideAPtr =
2212 getPtrStride(PSE, ATy, APtr, InnermostLoop, *DT, SymbolicStrides,
2214 std::optional<int64_t> StrideBPtr =
2215 getPtrStride(PSE, BTy, BPtr, InnermostLoop, *DT, SymbolicStrides,
2217 PSE.addPredicates(Predicates);
2219 const SCEV *Src = PSE.getSCEV(APtr);
2220 const SCEV *
Sink = PSE.getSCEV(BPtr);
2225 if (StrideAPtr && *StrideAPtr < 0) {
2234 LLVM_DEBUG(
dbgs() <<
"LAA: Src Scev: " << *Src <<
"Sink Scev: " << *Sink
2236 LLVM_DEBUG(
dbgs() <<
"LAA: Distance for " << *AInst <<
" to " << *BInst
2237 <<
": " << *Dist <<
"\n");
2246 if (!StrideAPtr || !StrideBPtr) {
2247 LLVM_DEBUG(
dbgs() <<
"Pointer access with non-constant stride\n");
2251 int64_t StrideAPtrInt = *StrideAPtr;
2252 int64_t StrideBPtrInt = *StrideBPtr;
2253 LLVM_DEBUG(
dbgs() <<
"LAA: Src induction step: " << StrideAPtrInt
2254 <<
" Sink induction step: " << StrideBPtrInt <<
"\n");
2257 if (!StrideAPtrInt || !StrideBPtrInt) {
2260 if (!StrideAPtrInt && !StrideBPtrInt && Dist->
isZero())
2268 if ((StrideAPtrInt > 0) != (StrideBPtrInt > 0)) {
2270 dbgs() <<
"Pointer access with strides in different directions\n");
2274 TypeSize AStoreSz =
DL.getTypeStoreSize(ATy);
2275 TypeSize BStoreSz =
DL.getTypeStoreSize(BTy);
2281 uint64_t TypeByteSize = (AStoreSz == BStoreSz) ? BSz : 0;
2286 uint64_t MaxStride = std::max(StrideAScaled, StrideBScaled);
2288 std::optional<uint64_t> CommonStride;
2289 if (StrideAScaled == StrideBScaled)
2290 CommonStride = StrideAScaled;
2295 ShouldRetryWithRuntimeChecks |= StrideAPtrInt == StrideBPtrInt;
2303 return DepDistanceStrideAndSizeInfo(Dist, MaxStride, CommonStride,
2304 TypeByteSize, AIsWrite, BIsWrite);
2308MemoryDepChecker::isDependent(
const MemAccessInfo &
A,
unsigned AIdx,
2310 assert(AIdx < BIdx &&
"Must pass arguments in program order");
2315 auto CheckCompletelyBeforeOrAfter = [&]() {
2316 auto *APtr =
A.getPointer();
2317 auto *BPtr =
B.getPointer();
2320 const SCEV *Src = PSE.getSCEV(APtr);
2321 const SCEV *
Sink = PSE.getSCEV(BPtr);
2322 return areAccessesCompletelyBeforeOrAfter(Src, ATy, Sink, BTy);
2328 getDependenceDistanceStrideAndSize(
A, InstMap[AIdx],
B, InstMap[BIdx]);
2329 if (std::holds_alternative<Dependence::DepType>(Res)) {
2331 CheckCompletelyBeforeOrAfter())
2333 return std::get<Dependence::DepType>(Res);
2336 auto &[Dist, MaxStride, CommonStride, TypeByteSize, AIsWrite, BIsWrite] =
2337 std::get<DepDistanceStrideAndSizeInfo>(Res);
2338 bool HasSameSize = TypeByteSize > 0;
2340 ScalarEvolution &SE = *PSE.getSE();
2341 auto &
DL = InnermostLoop->getHeader()->getDataLayout();
2350 DL, SE, *(PSE.getSymbolicMaxBackedgeTakenCount()), *Dist, MaxStride))
2353 const APInt *APDist =
nullptr;
2358 LLVM_DEBUG(
dbgs() <<
"LAA: Constant distance does not fit in 64 bits.\n");
2368 if (ConstDist > 0 && CommonStride && CommonStride > 1 && HasSameSize &&
2387 LLVM_DEBUG(
dbgs() <<
"LAA: possibly zero dependence difference but "
2388 "different type sizes\n");
2392 bool IsTrueDataDependence = (AIsWrite && !BIsWrite);
2407 couldPreventStoreLoadForward(ConstDist, TypeByteSize)) {
2409 dbgs() <<
"LAA: Forward but may prevent st->ld forwarding\n");
2418 std::optional<int64_t> MinDistanceOpt =
2420 if (!MinDistanceOpt) {
2421 LLVM_DEBUG(
dbgs() <<
"LAA: Minimum distance does not fit in 64 bits.\n");
2424 int64_t MinDistance = *MinDistanceOpt;
2426 if (MinDistance <= 0) {
2432 if (CheckCompletelyBeforeOrAfter())
2434 LLVM_DEBUG(
dbgs() <<
"LAA: ReadWrite-Write positive dependency with "
2435 "different type sizes\n");
2439 unsigned MinForcedFactor =
2444 unsigned MinNumIter = std::max(MinForcedFactor * ForcedUnroll, 2U);
2479 uint64_t MinDistanceNeeded = MaxStride * (MinNumIter - 1) + TypeByteSize;
2480 if (MinDistanceNeeded >
static_cast<uint64_t>(MinDistance)) {
2489 LLVM_DEBUG(
dbgs() <<
"LAA: Failure because of positive minimum distance "
2490 << MinDistance <<
'\n');
2496 if (MinDistanceNeeded > MinDepDistBytes) {
2498 << MinDistanceNeeded <<
" size in bytes\n");
2503 std::min(
static_cast<uint64_t>(MinDistance), MinDepDistBytes);
2505 bool IsTrueDataDependence = (!AIsWrite && BIsWrite);
2507 couldPreventStoreLoadForward(MinDistance, TypeByteSize, *CommonStride))
2510 uint64_t MaxVF = MinDepDistBytes / MaxStride;
2511 LLVM_DEBUG(
dbgs() <<
"LAA: Positive min distance " << MinDistance
2512 <<
" with max VF = " << MaxVF <<
'\n');
2514 uint64_t MaxVFInBits = MaxVF * TypeByteSize * 8;
2515 if (!ConstDist && MaxVFInBits < MaxTargetVectorWidthInBits) {
2524 if (CheckCompletelyBeforeOrAfter())
2527 MaxSafeVectorWidthInBits = std::min(MaxSafeVectorWidthInBits, MaxVFInBits);
2534 MinDepDistBytes = -1;
2549 bool AIIsWrite = AI->getInt();
2553 (AIIsWrite ? AI : std::next(AI));
2556 auto &Acc = Accesses[*AI];
2557 for (std::vector<unsigned>::iterator I1 = Acc.begin(), I1E = Acc.end();
2562 for (std::vector<unsigned>::iterator
2563 I2 = (OI == AI ? std::next(I1) : Accesses[*OI].begin()),
2564 I2E = (OI == AI ? I1E : Accesses[*OI].end());
2566 auto A = std::make_pair(&*AI, *I1);
2567 auto B = std::make_pair(&*OI, *I2);
2574 isDependent(*
A.first,
A.second, *
B.first,
B.second);
2581 if (RecordDependences) {
2583 Dependences.emplace_back(
A.second,
B.second,
Type);
2586 RecordDependences =
false;
2587 Dependences.clear();
2589 <<
"Too many dependences, stopped recording\n");
2601 LLVM_DEBUG(
dbgs() <<
"Total Dependences: " << Dependences.size() <<
"\n");
2608 auto I = Accesses.find(
Access);
2610 if (
I != Accesses.end()) {
2611 transform(
I->second, std::back_inserter(Insts),
2612 [&](
unsigned Idx) { return this->InstMap[Idx]; });
2624 "ForwardButPreventsForwarding",
2626 "BackwardVectorizable",
2627 "BackwardVectorizableButPreventsForwarding"};
2637bool LoopAccessInfo::canAnalyzeLoop() {
2646 recordAnalysis(
"NotInnerMostLoop") <<
"loop is not the innermost loop";
2653 dbgs() <<
"LAA: loop control flow is not understood by analyzer\n");
2654 recordAnalysis(
"CFGNotUnderstood")
2655 <<
"loop control flow is not understood by analyzer";
2664 recordAnalysis(
"CantComputeNumberOfIterations")
2665 <<
"could not determine number of loop iterations";
2666 LLVM_DEBUG(
dbgs() <<
"LAA: SCEV could not compute the loop exit count.\n");
2675bool LoopAccessInfo::analyzeLoop(AAResults *AA,
const LoopInfo *LI,
2676 const TargetLibraryInfo *TLI,
2677 DominatorTree *DT) {
2681 SmallPtrSet<MDNode *, 8> LoopAliasScopes;
2684 unsigned NumReads = 0;
2685 unsigned NumReadWrites = 0;
2687 bool HasComplexMemInst =
false;
2690 HasConvergentOp =
false;
2692 PtrRtChecking->Pointers.
clear();
2693 PtrRtChecking->Need =
false;
2697 const bool EnableMemAccessVersioningOfLoop =
2703 LoopBlocksRPO RPOT(TheLoop);
2709 for (BasicBlock *BB : RPOT) {
2712 for (Instruction &
I : *BB) {
2715 HasConvergentOp =
true;
2720 if (HasComplexMemInst && HasConvergentOp)
2724 if (HasComplexMemInst)
2729 for (
Metadata *
Op : Decl->getScopeList()->operands())
2742 if (
I.mayReadFromMemory()) {
2743 auto hasPointerArgs = [](CallBase *CB) {
2745 return Arg->getType()->isPointerTy();
2758 recordAnalysis(
"CantVectorizeInstruction", &
I)
2759 <<
"instruction cannot be vectorized";
2760 HasComplexMemInst =
true;
2763 if (!Ld->isSimple() && !IsAnnotatedParallel) {
2764 recordAnalysis(
"NonSimpleLoad", Ld)
2765 <<
"read with atomic ordering or volatile read";
2767 HasComplexMemInst =
true;
2773 if (EnableMemAccessVersioningOfLoop)
2774 collectStridedAccess(Ld);
2779 if (
I.mayWriteToMemory()) {
2782 recordAnalysis(
"CantVectorizeInstruction", &
I)
2783 <<
"instruction cannot be vectorized";
2784 HasComplexMemInst =
true;
2787 if (!St->isSimple() && !IsAnnotatedParallel) {
2788 recordAnalysis(
"NonSimpleStore", St)
2789 <<
"write with atomic ordering or volatile write";
2791 HasComplexMemInst =
true;
2797 if (EnableMemAccessVersioningOfLoop)
2798 collectStridedAccess(St);
2803 if (HasComplexMemInst)
2811 if (!Stores.
size()) {
2817 AccessAnalysis
Accesses(TheLoop, AA, LI, *DT, DepCands, *PSE,
2825 SmallSet<std::pair<Value *, Type *>, 16> Seen;
2829 SmallPtrSet<Value *, 16> UniformStores;
2831 for (StoreInst *ST : Stores) {
2832 Value *Ptr =
ST->getPointerOperand();
2834 if (isInvariant(Ptr)) {
2836 StoresToInvariantAddresses.push_back(ST);
2837 HasStoreStoreDependenceInvolvingLoopInvariantAddress |=
2838 !UniformStores.
insert(Ptr).second;
2844 if (Seen.
insert({Ptr, AccessTy}).second) {
2851 if (blockNeedsPredication(
ST->getParent(), TheLoop, DT))
2857 [&Accesses, AccessTy, Loc](
Value *Ptr) {
2858 MemoryLocation NewLoc = Loc.getWithNewPtr(Ptr);
2859 Accesses.addStore(NewLoc, AccessTy);
2864 if (IsAnnotatedParallel) {
2866 dbgs() <<
"LAA: A loop annotated parallel, ignore memory dependency "
2871 for (LoadInst *LD : Loads) {
2872 Value *Ptr =
LD->getPointerOperand();
2881 bool IsReadOnlyPtr =
false;
2883 if (Seen.
insert({Ptr, AccessTy}).second ||
2884 !
getPtrStride(*PSE, AccessTy, Ptr, TheLoop, *DT, SymbolicStrides,
false,
2887 IsReadOnlyPtr =
true;
2893 LLVM_DEBUG(
dbgs() <<
"LAA: Found an unsafe dependency between a uniform "
2894 "load and uniform store to the same address!\n");
2895 HasLoadStoreDependenceInvolvingLoopInvariantAddress =
true;
2902 if (blockNeedsPredication(
LD->getParent(), TheLoop, DT))
2908 [&Accesses, AccessTy, Loc, IsReadOnlyPtr](
Value *Ptr) {
2909 MemoryLocation NewLoc = Loc.getWithNewPtr(Ptr);
2910 Accesses.addLoad(NewLoc, AccessTy, IsReadOnlyPtr);
2917 if (NumReadWrites == 1 && NumReads == 0) {
2924 Accesses.buildDependenceSets();
2928 Value *UncomputablePtr =
nullptr;
2929 HasCompletePtrRtChecking =
2930 Accesses.canCheckPtrAtRT(*PtrRtChecking, TheLoop, SymbolicStrides,
2931 UncomputablePtr, AllowPartial, getDepChecker());
2932 if (!HasCompletePtrRtChecking) {
2934 recordAnalysis(
"CantIdentifyArrayBounds",
I)
2935 <<
"cannot identify array bounds";
2936 LLVM_DEBUG(
dbgs() <<
"LAA: We can't vectorize because we can't find "
2937 <<
"the array bounds.\n");
2942 dbgs() <<
"LAA: May be able to perform a memory runtime check if needed.\n");
2944 bool DepsAreSafe =
true;
2945 if (Accesses.isDependencyCheckNeeded()) {
2948 DepChecker->
areDepsSafe(DepCands, Accesses.getDependenciesToCheck());
2953 PtrRtChecking->reset();
2954 PtrRtChecking->Need =
true;
2956 UncomputablePtr =
nullptr;
2957 HasCompletePtrRtChecking = Accesses.canCheckPtrAtRT(
2958 *PtrRtChecking, TheLoop, SymbolicStrides, UncomputablePtr,
2959 AllowPartial, getDepChecker());
2962 if (!HasCompletePtrRtChecking) {
2964 recordAnalysis(
"CantCheckMemDepsAtRunTime",
I)
2965 <<
"cannot check memory dependencies at runtime";
2966 LLVM_DEBUG(
dbgs() <<
"LAA: Can't vectorize with memory checks\n");
2971 Accesses.resetDepChecks(*DepChecker);
2981 for (
const auto &Dep : *Deps) {
2985 Instruction *Dst = Dep.getDestination(*DepChecker);
2987 HasLoadStoreDependenceInvolvingLoopInvariantAddress =
true;
2990 "Expected both to be stores");
2991 HasStoreStoreDependenceInvolvingLoopInvariantAddress =
true;
2996 if (HasConvergentOp) {
2997 recordAnalysis(
"CantInsertRuntimeCheckWithConvergent")
2998 <<
"cannot add control dependency to convergent operation";
2999 LLVM_DEBUG(
dbgs() <<
"LAA: We can't vectorize because a runtime check "
3000 "would be needed with a convergent operation\n");
3006 dbgs() <<
"LAA: No unsafe dependent memory operations in loop. We"
3007 << (PtrRtChecking->Need ?
"" :
" don't")
3008 <<
" need runtime memory checks.\n");
3012 emitUnsafeDependenceRemark();
3016void LoopAccessInfo::emitUnsafeDependenceRemark() {
3017 const auto *Deps = getDepChecker().getDependences();
3025 if (Found == Deps->end())
3027 MemoryDepChecker::Dependence Dep = *Found;
3029 LLVM_DEBUG(
dbgs() <<
"LAA: unsafe dependent memory operations in loop\n");
3032 bool HasForcedDistribution =
3035 const std::string
Info =
3036 HasForcedDistribution
3037 ?
"unsafe dependent memory operations in loop."
3038 :
"unsafe dependent memory operations in loop. Use "
3039 "#pragma clang loop distribute(enable) to allow loop distribution "
3040 "to attempt to isolate the offending operations into a separate "
3042 OptimizationRemarkAnalysis &
R =
3051 R <<
"\nBackward loop carried data dependence.";
3054 R <<
"\nForward loop carried data dependence that prevents "
3055 "store-to-load forwarding.";
3058 R <<
"\nBackward loop carried data dependence that prevents "
3059 "store-to-load forwarding.";
3062 R <<
"\nUnsafe indirect dependence.";
3065 R <<
"\nUnsafe dependence on loop-invariant address.";
3068 R <<
"\nUnknown data dependence.";
3072 if (Instruction *
I = Dep.
getSource(getDepChecker())) {
3075 SourceLoc = DD->getDebugLoc();
3077 R <<
" Memory location is the same as accessed at "
3078 <<
ore::NV(
"Location", SourceLoc);
3083 const Loop *TheLoop,
3085 assert(TheLoop->contains(BB) &&
"Unknown block used");
3088 const BasicBlock *Latch = TheLoop->getLoopLatch();
3089 assert(Latch &&
"Loop expected to have a single latch.");
3095 assert(!Report &&
"Multiple reports generated");
3101 CodeRegion =
I->getParent();
3104 if (
I->getDebugLoc())
3105 DL =
I->getDebugLoc();
3108 Report = std::make_unique<OptimizationRemarkAnalysis>(
DEBUG_TYPE, RemarkName,
3114 auto *SE = PSE->getSE();
3115 if (TheLoop->isLoopInvariant(V))
3132 for (
const Use &U :
GEP->operands()) {
3154 Value *OrigPtr = Ptr;
3162 V =
C->getOperand();
3185void LoopAccessInfo::collectStridedAccess(
Value *MemAccess) {
3203 LLVM_DEBUG(
dbgs() <<
"LAA: Found a strided access that is a candidate for "
3205 LLVM_DEBUG(
dbgs() <<
" Ptr: " << *Ptr <<
" Stride: " << *StrideExpr <<
"\n");
3208 LLVM_DEBUG(
dbgs() <<
" Chose not to due to -laa-speculate-unit-stride\n");
3225 const SCEV *MaxBTC = PSE->getSymbolicMaxBackedgeTakenCount();
3233 const SCEV *CastedStride = StrideExpr;
3234 const SCEV *CastedBECount = MaxBTC;
3235 ScalarEvolution *SE = PSE->getSE();
3236 if (BETypeSizeBits >= StrideTypeSizeBits)
3240 const SCEV *StrideMinusBETaken = SE->
getMinusSCEV(CastedStride, CastedBECount);
3246 dbgs() <<
"LAA: Stride>=TripCount; No point in versioning as the "
3247 "Stride==1 predicate will imply that the loop executes "
3251 LLVM_DEBUG(
dbgs() <<
"LAA: Found a strided access that we can version.\n");
3255 const SCEV *StrideBase = StrideExpr;
3257 StrideBase =
C->getOperand();
3259 "users of the map rely on the stride being loop invariant");
3269 PtrRtChecking(nullptr), TheLoop(L), AllowPartial(AllowPartial) {
3270 unsigned MaxTargetVectorWidthInBits = std::numeric_limits<unsigned>::max();
3271 if (
TTI && !
TTI->enableScalableVectorization())
3274 MaxTargetVectorWidthInBits =
3277 DepChecker = std::make_unique<MemoryDepChecker>(
3278 *PSE, AC, DT, L, SymbolicStrides, MaxTargetVectorWidthInBits, LoopGuards);
3280 std::make_unique<RuntimePointerChecking>(*DepChecker, SE, LoopGuards);
3281 if (canAnalyzeLoop())
3282 CanVecMem = analyzeLoop(
AA, LI, TLI, DT);
3287 OS.
indent(
Depth) <<
"Memory dependences are safe";
3290 OS <<
" with a maximum safe vector width of "
3294 OS <<
", with a maximum safe store-load forward width of " << SLDist
3297 if (PtrRtChecking->Need)
3298 OS <<
" with run-time checks";
3302 if (HasConvergentOp)
3303 OS.
indent(
Depth) <<
"Has convergent operation in loop\n";
3306 OS.
indent(
Depth) <<
"Report: " << Report->getMsg() <<
"\n";
3308 if (
auto *Dependences = DepChecker->getDependences()) {
3310 for (
const auto &Dep : *Dependences) {
3311 Dep.
print(OS,
Depth + 2, DepChecker->getMemoryInstructions());
3315 OS.
indent(
Depth) <<
"Too many dependences, not recorded\n";
3318 PtrRtChecking->print(OS,
Depth);
3319 if (PtrRtChecking->Need && !HasCompletePtrRtChecking)
3320 OS.
indent(
Depth) <<
"Generated run-time checks are incomplete\n";
3324 <<
"Non vectorizable stores to invariant address were "
3325 << (HasStoreStoreDependenceInvolvingLoopInvariantAddress ||
3326 HasLoadStoreDependenceInvolvingLoopInvariantAddress
3329 <<
"found in loop.\n";
3332 PSE->getPredicate().print(OS,
Depth);
3337 PSE->print(OS,
Depth);
3341 bool AllowPartial) {
3342 const auto &[It, Inserted] = LoopAccessInfoMap.try_emplace(&L);
3346 if (Inserted || It->second->hasAllowPartial() != AllowPartial)
3347 It->second = std::make_unique<LoopAccessInfo>(&L, &SE, TTI, TLI, &AA, &DT,
3348 &LI, AC, AllowPartial);
3357 LoopAccessInfoMap.remove_if([](
const auto &Entry) {
3358 const auto &LAI = Entry.second;
3359 return !(LAI->getRuntimePointerChecking()->getChecks().empty() &&
3360 LAI->getPSE().getPredicate().isAlwaysTrue());
3366 FunctionAnalysisManager::Invalidator &Inv) {
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 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< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
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...
DXIL Forward Handle Accesses
This file defines the DenseMap class.
Generic implementation of equivalence classes through the use Tarjan's efficient union-find algorithm...
This header defines various interfaces for pass management in LLVM.
static cl::opt< unsigned > MaxDependences("max-dependences", cl::Hidden, cl::desc("Maximum number of dependences collected by " "loop-access analysis (default = 100)"), cl::init(100))
We collect dependences up to this threshold.
static cl::opt< bool > EnableForwardingConflictDetection("store-to-load-forwarding-conflict-detection", cl::Hidden, cl::desc("Enable conflict detection in loop-access analysis"), cl::init(true))
Enable store-to-load forwarding conflict detection.
static void findForkedSCEVs(ScalarEvolution *SE, const Loop *L, Value *Ptr, SmallVectorImpl< PointerIntPair< const SCEV *, 1, bool > > &ScevList, unsigned Depth)
static const SCEV * mulSCEVNoOverflow(const SCEV *A, const SCEV *B, ScalarEvolution &SE)
Returns A * B, if it is guaranteed not to unsigned wrap.
static bool isNoWrap(PredicatedScalarEvolution &PSE, const SCEVAddRecExpr *AR, Value *Ptr, Type *AccessTy, const Loop *L, const DominatorTree &DT, std::optional< int64_t > Stride=std::nullopt, SmallVectorImpl< const SCEVPredicate * > *Predicates=nullptr)
Check whether AR is a non-wrapping AddRec.
static cl::opt< unsigned > MemoryCheckMergeThreshold("memory-check-merge-threshold", cl::Hidden, cl::desc("Maximum number of comparisons done when trying to merge " "runtime memory checks. (default = 100)"), cl::init(100))
The maximum iterations used to merge memory checks.
static const SCEV * getStrideFromPointer(Value *Ptr, ScalarEvolution *SE, Loop *Lp)
Get the stride of a pointer access in a loop.
static bool isKnownNonDecreasingInLoop(const SCEV *S, const Loop *L, ScalarEvolution &SE)
Return true if S is known to be monotonically non-decreasing (in the unsigned sense,...
static cl::opt< ElementCount, true > VectorizationFactor("force-vector-width", cl::Hidden, cl::desc("Sets the SIMD width. Zero is autoselect."), cl::location(VectorizerParams::VectorizationFactor))
static bool evaluatePtrAddRecAtMaxBTCWillNotWrap(const SCEVAddRecExpr *AR, const SCEV *MaxBTC, const SCEV *EltSize, ScalarEvolution &SE, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC, std::optional< ScalarEvolution::LoopGuards > &LoopGuards)
Return true, if evaluating AR at MaxBTC cannot wrap, because AR at MaxBTC is guaranteed inbounds of t...
static cl::opt< unsigned, true > VectorizationInterleave("force-vector-interleave", cl::Hidden, cl::desc("Sets the vectorization interleave count. " "Zero is autoselect."), cl::location(VectorizerParams::VectorizationInterleave))
static cl::opt< bool, true > HoistRuntimeChecks("hoist-runtime-checks", cl::Hidden, cl::desc("Hoist inner loop runtime memory checks to outer loop if possible"), cl::location(VectorizerParams::HoistRuntimeChecks), cl::init(true))
static DenseMap< const RuntimeCheckingPtrGroup *, unsigned > getPtrToIdxMap(ArrayRef< RuntimeCheckingPtrGroup > CheckingGroups)
Assign each RuntimeCheckingPtrGroup pointer an index for stable UTC output.
static cl::opt< unsigned, true > RuntimeMemoryCheckThreshold("runtime-memory-check-threshold", cl::Hidden, cl::desc("When performing memory disambiguation checks at runtime do not " "generate more than this number of comparisons (default = 8)."), cl::location(VectorizerParams::RuntimeMemoryCheckThreshold), cl::init(8))
static void visitPointers(Value *StartPtr, const Loop &InnermostLoop, function_ref< void(Value *)> AddPointer)
static bool isSafeDependenceDistance(const DataLayout &DL, ScalarEvolution &SE, const SCEV &MaxBTC, const SCEV &Dist, uint64_t MaxStride)
Given a dependence-distance Dist between two memory accesses, that have strides in the same direction...
static std::pair< const SCEV *, const SCEV * > getNonAffineMonotonicBounds(const Loop *Lp, const SCEV *PtrExpr, ScalarEvolution *SE)
Try to bound a loop-variant pointer that is not an affine AddRec.
static bool areStridedAccessesIndependent(uint64_t Distance, uint64_t Stride, uint64_t TypeByteSize)
Check the dependence for two accesses with the same stride Stride.
static const SCEV * getMinFromExprs(const SCEV *I, const SCEV *J, ScalarEvolution *SE)
Compare I and J and return the minimum.
static Value * getLoopVariantGEPOperand(Value *Ptr, ScalarEvolution *SE, Loop *Lp)
If Ptr is a GEP, which has a loop-variant operand, return that operand.
static cl::opt< unsigned > MaxForkedSCEVDepth("max-forked-scev-depth", cl::Hidden, cl::desc("Maximum recursion depth when finding forked SCEVs (default = 5)"), cl::init(5))
static cl::opt< bool > SpeculateUnitStride("laa-speculate-unit-stride", cl::Hidden, cl::desc("Speculate that non-constant strides are unit in LAA"), cl::init(true))
static cl::opt< bool > EnableMemAccessVersioning("enable-mem-access-versioning", cl::init(true), cl::Hidden, cl::desc("Enable symbolic stride memory access versioning"))
This enables versioning on the strides of symbolically striding memory accesses in code like the foll...
static const SCEV * addSCEVNoOverflow(const SCEV *A, const SCEV *B, ScalarEvolution &SE)
Returns A + B, if it is guaranteed not to unsigned wrap.
This header provides classes for managing per-loop analyses.
This file provides utility analysis objects describing memory locations.
FunctionAnalysisManager FAM
This file defines the PointerIntPair class.
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
This file defines the SmallSet class.
This file defines the SmallVector class.
static SymbolRef::Type getType(const Symbol *Sym)
static const X86InstrFMA3Group Groups[]
A manager for alias analyses.
Class for arbitrary precision integers.
std::optional< uint64_t > tryZExtValue() const
Get zero extended value if possible.
APInt abs() const
Get the absolute value.
LLVM_ABI APInt sextOrTrunc(unsigned width) const
Sign extend or truncate to width.
std::optional< int64_t > trySExtValue() const
Get sign extended value if possible.
This templated class represents "all analyses that operate over <aparticular IR unit>" (e....
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.
A cache of @llvm.assume calls within a function.
LLVM Basic Block Representation.
const Function * getParent() const
Return the enclosing method, or null if none.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this basic block belongs to.
bool isNoBuiltin() const
Return true if the call should not be treated as a call to a builtin.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
bool isConvergent() const
Determine if the invoke is convergent.
@ ICMP_UGE
unsigned greater or equal
@ ICMP_SGE
signed greater or equal
@ ICMP_ULE
unsigned less or equal
static LLVM_ABI Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
A parsed version of the target data layout string in and methods for querying it.
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
iterator find(const_arg_type_t< KeyT > Val)
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
iterator_range< member_iterator > members(const ECValue &ECV) const
bool contains(const ElemTy &V) const
Returns true if V is contained an equivalence class.
const ECValue & insert(const ElemTy &Data)
Insert a new value into the union/find set, ignoring the request if the value already exists.
member_iterator member_end() const
const ElemTy & getLeaderValue(const ElemTy &V) const
Return the leader for the specified value that is in the set.
member_iterator findLeader(const ElemTy &V) const
Given a value in the set, return a member iterator for the equivalence class it is in.
void eraseClass(const ElemTy &V)
Erase the class containing V, i.e.
member_iterator unionSets(const ElemTy &V1, const ElemTy &V2)
Merge the two equivalence sets for the specified values, inserting them if they do not already exist ...
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
PointerType * getType() const
Global values are always pointers.
An instruction for reading from memory.
Value * getPointerOperand()
static constexpr LocationSize beforeOrAfterPointer()
Any location before or after the base pointer (but still within the underlying object).
This analysis provides dependence information for the memory accesses of a loop.
LLVM_ABI Result run(Function &F, FunctionAnalysisManager &AM)
LLVM_ABI bool invalidate(Function &F, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &Inv)
LLVM_ABI const LoopAccessInfo & getInfo(Loop &L, bool AllowPartial=false)
Drive the analysis of memory accesses in the loop.
const MemoryDepChecker & getDepChecker() const
the Memory Dependence Checker which can determine the loop-independent and loop-carried dependences b...
LLVM_ABI bool isInvariant(Value *V) const
Returns true if value V is loop invariant.
LLVM_ABI void print(raw_ostream &OS, unsigned Depth=0) const
Print the information about the memory accesses in the loop.
static LLVM_ABI bool blockNeedsPredication(const BasicBlock *BB, const Loop *TheLoop, const DominatorTree *DT)
Return true if the block BB needs to be predicated in order for the loop to be vectorized.
LLVM_ABI LoopAccessInfo(Loop *L, ScalarEvolution *SE, const TargetTransformInfo *TTI, const TargetLibraryInfo *TLI, AAResults *AA, DominatorTree *DT, LoopInfo *LI, AssumptionCache *AC, bool AllowPartial=false)
Analysis pass that exposes the LoopInfo for a function.
bool contains(const LoopT *L) const
Return true if the specified loop is contained within this loop.
bool isInnermost() const
Return true if the loop does not contain any (natural) loops.
unsigned getNumBackEdges() const
Calculate the number of back edges to the loop header.
BlockT * getHeader() const
LoopT * getParentLoop() const
Return the parent loop if it exists or nullptr for top level loops.
Represents a single loop in the control flow graph.
std::string getLocStr() const
Return a string containing the debug location of the loop (file name + line number if present,...
bool isAnnotatedParallel() const
Returns true if the loop is annotated parallel.
DebugLoc getStartLoc() const
Return the debug location of the start of this loop.
ArrayRef< MDOperand > operands() const
Checks memory dependences among accesses to the same underlying object to determine whether there vec...
ArrayRef< unsigned > getOrderForAccess(Value *Ptr, bool IsWrite) const
Return the program order indices for the access location (Ptr, IsWrite).
bool isSafeForAnyStoreLoadForwardDistances() const
Return true if there are no store-load forwarding dependencies.
LLVM_ABI bool areDepsSafe(const DepCandidates &AccessSets, ArrayRef< MemAccessInfo > CheckDeps)
Check whether the dependencies between the accesses are safe, and records the dependence information ...
bool isSafeForAnyVectorWidth() const
Return true if the number of elements that are safe to operate on simultaneously is not bounded.
static bool isStoreLoadForwardingConflict(uint64_t Distance, uint64_t VectorStoreSize, uint64_t TypeByteSize, uint64_t LoadElementSize=0)
Returns true if a memory dependence at byte distance Distance between a store (with element size Type...
PointerIntPair< Value *, 1, bool > MemAccessInfo
EquivalenceClasses< MemAccessInfo > DepCandidates
Set of potential dependent memory accesses.
bool shouldRetryWithRuntimeChecks() const
In same cases when the dependency check fails we can still vectorize the loop with a dynamic array ac...
const Loop * getInnermostLoop() const
uint64_t getMaxSafeVectorWidthInBits() const
Return the number of elements that are safe to operate on simultaneously, multiplied by the size of t...
bool isSafeForVectorization() const
No memory dependence was encountered that would inhibit vectorization.
const SmallVectorImpl< Dependence > * getDependences() const
Returns the memory dependences.
LLVM_ABI SmallVector< Instruction *, 4 > getInstructionsForAccess(Value *Ptr, bool isWrite) const
Find the set of instructions that read or write via Ptr.
VectorizationSafetyStatus
Type to keep track of the status of the dependence check.
@ PossiblySafeWithRtChecks
LLVM_ABI void addAccess(StoreInst *SI)
Register the location (instructions are given increasing numbers) of a write access.
uint64_t getStoreLoadForwardSafeDistanceInBits() const
Return safe power-of-2 number of elements, which do not prevent store-load forwarding,...
Representation for a specific memory location.
static LLVM_ABI MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
LocationSize Size
The maximum size of the location, in address-units, or UnknownSize if the size is not known.
AAMDNodes AATags
The metadata nodes which describes the aliasing of the location (each member is null if that kind of ...
const Value * Ptr
The address of the start of the location.
PointerIntPair - This class implements a pair of a pointer and small integer.
An interface layer with SCEV used to manage how we see SCEV expressions for values in the context of ...
LLVM_ABI void addPredicate(const SCEVPredicate &Pred)
Adds a new predicate.
ScalarEvolution * getSE() const
Returns the ScalarEvolution analysis used.
LLVM_ABI bool hasNoOverflow(Value *V, SCEVWrapPredicate::IncrementWrapFlags Flags)
Returns true if we've statically proved that V doesn't wrap.
LLVM_ABI const SCEVAddRecExpr * getAsAddRec(Value *V, SmallVectorImpl< const SCEVPredicate * > *WrapPredsAdded=nullptr)
Attempts to produce an AddRecExpr for V by adding additional SCEV predicates.
LLVM_ABI void addPredicates(ArrayRef< const SCEVPredicate * > Preds)
Adds all predicates in Preds.
LLVM_ABI const SCEV * getBackedgeTakenCount()
Get the (predicated) backedge count for the analyzed loop.
LLVM_ABI const SCEV * getSymbolicMaxBackedgeTakenCount()
Get the (predicated) symbolic max backedge count for the analyzed loop.
LLVM_ABI const SCEV * getSCEV(Value *V)
Returns the SCEV expression of V, in the context of the current SCEV predicate.
A set of analyses that are preserved following a run of a transformation pass.
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
Holds information about the memory runtime legality checks to verify that a group of pointers do not ...
bool Need
This flag indicates if we need to add the runtime check.
void reset()
Reset the state of the pointer runtime information.
unsigned getNumberOfChecks() const
Returns the number of run-time checks required according to needsChecking.
LLVM_ABI void printChecks(raw_ostream &OS, const SmallVectorImpl< RuntimePointerCheck > &Checks, unsigned Depth=0) const
Print Checks.
LLVM_ABI bool needsChecking(const RuntimeCheckingPtrGroup &M, const RuntimeCheckingPtrGroup &N) const
Decide if we need to add a check between two groups of pointers, according to needsChecking.
LLVM_ABI void print(raw_ostream &OS, unsigned Depth=0) const
Print the list run-time memory checks necessary.
SmallVector< RuntimeCheckingPtrGroup, 2 > CheckingGroups
Holds a partitioning of pointers into "check groups".
friend struct RuntimeCheckingPtrGroup
static LLVM_ABI bool arePointersInSamePartition(const SmallVectorImpl< int > &PtrToPartition, unsigned PtrIdx1, unsigned PtrIdx2)
Check if pointers are in the same partition.
LLVM_ABI void generateChecks(MemoryDepChecker::DepCandidates &DepCands)
Generate the checks and store it.
SmallVector< PointerInfo, 2 > Pointers
Information about the pointers that may require checking.
LLVM_ABI void insert(Loop *Lp, Value *Ptr, const SCEV *PtrExpr, Type *AccessTy, bool WritePtr, unsigned DepSetId, unsigned ASId, PredicatedScalarEvolution &PSE, bool NeedsFreeze)
Insert a pointer and calculate the start and end SCEVs.
This node represents a polynomial recurrence on the trip count of the specified loop.
bool isAffine() const
Return true if this represents an expression A + B*x where A and B are loop invariant values.
const Loop * getLoop() const
SCEVUse getStepRecurrence(ScalarEvolution &SE) const
Constructs and returns the recurrence indicating how much this expression steps by.
This class represents a constant integer value.
ConstantInt * getValue() const
const APInt & getAPInt() const
NoWrapFlags getNoWrapFlags(NoWrapFlags Mask=NoWrapMask) const
This means that we are dealing with an entirely unknown SCEV value, and only represent it as its LLVM...
IncrementWrapFlags
Similar to SCEV::NoWrapFlags, but with slightly different semantics for FlagNUSW.
static SCEVWrapPredicate::IncrementWrapFlags clearFlags(SCEVWrapPredicate::IncrementWrapFlags Flags, SCEVWrapPredicate::IncrementWrapFlags OffFlags)
Convenient IncrementWrapFlags manipulation methods.
static SCEVWrapPredicate::IncrementWrapFlags getImpliedFlags(const SCEVAddRecExpr *AR, ScalarEvolution &SE)
Returns the set of SCEVWrapPredicate no wrap flags implied by a SCEVAddRecExpr.
This class represents an analyzed expression in the program.
static constexpr auto NoWrapMask
LLVM_ABI bool isZero() const
Return true if the expression is a constant zero.
Type * getType() const
Return the LLVM type of this SCEV expression.
SCEVTypes getSCEVType() const
Analysis pass that exposes the ScalarEvolution for a function.
static LLVM_ABI LoopGuards collect(const Loop *L, ScalarEvolution &SE)
Collect rewrite map for loop guards for loop L, together with flags indicating if NUW and NSW can be ...
The main scalar evolution driver.
const SCEV * getConstantMaxBackedgeTakenCount(const Loop *L)
When successful, this returns a SCEVConstant that is greater than or equal to (i.e.
LLVM_ABI bool isKnownNonNegative(const SCEV *S)
Test if the given expression is known to be non-negative.
LLVM_ABI const SCEV * getNegativeSCEV(const SCEV *V, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap)
Return the SCEV object corresponding to -V.
LLVM_ABI const SCEV * getZeroExtendExpr(SCEVUse Op, Type *Ty, unsigned Depth=0)
LLVM_ABI Type * getWiderType(Type *Ty1, Type *Ty2) const
LLVM_ABI const SCEV * getAbsExpr(const SCEV *Op, bool IsNSW)
LLVM_ABI bool isKnownNonPositive(const SCEV *S)
Test if the given expression is known to be non-positive.
LLVM_ABI bool isKnownNegative(const SCEV *S)
Test if the given expression is known to be negative.
LLVM_ABI const SCEV * getSCEVAtScope(const SCEV *S, const Loop *L)
Return a SCEV expression for the specified value at the specified scope in the program.
LLVM_ABI bool willNotOverflow(Instruction::BinaryOps BinOp, bool Signed, const SCEV *LHS, const SCEV *RHS, const Instruction *CtxI=nullptr)
Is operation BinOp between LHS and RHS provably does not have a signed/unsigned overflow (Signed)?
LLVM_ABI const SCEVPredicate * getEqualPredicate(const SCEV *LHS, const SCEV *RHS)
LLVM_ABI const SCEV * getConstant(ConstantInt *V)
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.
LLVM_ABI const SCEV * getNoopOrSignExtend(const SCEV *V, Type *Ty)
Return a SCEV corresponding to a conversion of the input value to the specified type.
const SCEV * getOne(Type *Ty)
Return a SCEV for the constant 1 of a specific type.
LLVM_ABI bool isLoopInvariant(const SCEV *S, const Loop *L)
Return true if the value of the given SCEV is unchanging in the specified loop.
LLVM_ABI bool isKnownPositive(const SCEV *S)
Test if the given expression is known to be positive.
LLVM_ABI bool isSCEVable(Type *Ty) const
Test if values of the given type are analyzable within the SCEV framework.
LLVM_ABI Type * getEffectiveSCEVType(Type *Ty) const
Return a type with the same bitwidth as the given type and which represents how SCEV will treat the g...
APInt getSignedRangeMin(const SCEV *S)
Determine the min of the signed range for a particular SCEV.
LLVM_ABI const SCEV * getUMaxExpr(SCEVUse LHS, SCEVUse RHS)
@ MonotonicallyIncreasing
LLVM_ABI const SCEV * getStoreSizeOfExpr(Type *IntTy, Type *StoreTy)
Return an expression for the store size of StoreTy that is type IntTy.
LLVM_ABI const SCEVPredicate * getWrapPredicate(const SCEVAddRecExpr *AR, SCEVWrapPredicate::IncrementWrapFlags AddedFlags)
LLVM_ABI const SCEV * getNoopOrZeroExtend(const SCEV *V, Type *Ty)
Return a SCEV corresponding to a conversion of the input value to the specified type.
LLVM_ABI std::optional< MonotonicPredicateType > getMonotonicPredicateType(const SCEVAddRecExpr *LHS, ICmpInst::Predicate Pred)
If, for all loop invariant X, the predicate "LHS `Pred` X" is monotonically increasing or decreasing,...
LLVM_ABI const SCEV * getCouldNotCompute()
LLVM_ABI const SCEV * getMulExpr(SmallVectorImpl< SCEVUse > &Ops, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Get a canonical multiply expression, or something simpler if possible.
LLVM_ABI const SCEV * getPointerBase(const SCEV *V)
Transitively follow the chain of pointer-type operands until reaching a SCEV that does not have a sin...
LLVM_ABI const SCEV * getAddExpr(SmallVectorImpl< SCEVUse > &Ops, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Get a canonical add expression, or something simpler if possible.
LLVM_ABI bool isKnownPredicate(CmpPredicate Pred, SCEVUse LHS, SCEVUse RHS)
Test if the given expression is known to satisfy the condition described by Pred, LHS,...
LLVM_ABI const SCEV * applyLoopGuards(const SCEV *Expr, const Loop *L)
Try to apply information from loop guards for L to Expr.
LLVM_ABI const SCEV * getPtrToAddrExpr(const SCEV *Op)
LLVM_ABI const SCEVAddRecExpr * convertSCEVToAddRecWithPredicates(const SCEV *S, const Loop *L, SmallVectorImpl< const SCEVPredicate * > &Preds)
Tries to convert the S expression to an AddRec expression, adding additional predicates to Preds as r...
LLVM_ABI const SCEV * getSizeOfExpr(Type *IntTy, TypeSize Size)
Return an expression for a TypeSize.
LLVM_ABI std::optional< APInt > computeConstantDifference(const SCEV *LHS, const SCEV *RHS)
Compute LHS - RHS and returns the result as an APInt if it is a constant, and std::nullopt if it isn'...
LLVM_ABI std::pair< const SCEV *, const SCEV * > SplitIntoInitAndPostInc(const Loop *L, const SCEV *S)
Splits SCEV expression S into two SCEVs.
LLVM_ABI const SCEV * getUMinExpr(SCEVUse LHS, SCEVUse RHS, bool Sequential=false)
LLVM_ABI const SCEV * getTruncateOrSignExtend(const SCEV *V, Type *Ty, unsigned Depth=0)
Return a SCEV corresponding to a conversion of the input value to the specified type.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
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.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
bool contains(const T &V) const
Check if the SmallSet contains the given element.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
Represent a constant reference to a string, i.e.
Analysis pass providing the TargetTransformInfo.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
The instances of the Type class are immutable: once they are created, they are never changed.
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.
A Use represents the edge between a Value definition and its users.
static SmallVector< VFInfo, 8 > getMappings(const CallInst &CI)
Retrieve all the VFInfo instances associated to the CallInst CI.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI const Value * stripAndAccumulateConstantOffsets(const DataLayout &DL, APInt &Offset, bool AllowNonInbounds, bool AllowInvariantGroup=false, function_ref< bool(Value &Value, APInt &Offset)> ExternalAnalysis=nullptr, bool LookThroughIntToPtr=false) const
Accumulate the constant offset this value has compared to a base pointer.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI uint64_t getPointerDereferenceableBytes(const DataLayout &DL, bool &CanBeNull, bool *CanBeFreed) const
Returns the number of bytes known to be dereferenceable for the pointer value.
constexpr ScalarTy getFixedValue() const
An efficient, type-erasing, non-owning reference to a callable.
This class implements an extremely fast bulk output stream that can only output to a stream.
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
bool match(Val *V, const Pattern &P)
bind_cst_ty m_scev_APInt(const APInt *&C)
Match an SCEV constant and bind it to an APInt.
is_undef_or_poison m_scev_UndefOrPoison()
Match an SCEVUnknown wrapping undef or poison.
specificloop_ty m_SpecificLoop(const Loop *L)
match_bind< const SCEVMulExpr > m_scev_Mul(const SCEVMulExpr *&V)
specificscev_ty m_scev_Specific(const SCEV *S)
Match if we have a specific specified SCEV.
SCEVAffineAddRec_match< Op0_t, Op1_t, match_isa< const Loop > > m_scev_AffineAddRec(const Op0_t &Op0, const Op1_t &Op1)
initializer< Ty > init(const Ty &Val)
LocationClass< Ty > location(Ty &L)
DiagnosticInfoOptimizationBase::Argument NV
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI std::pair< const SCEV *, const SCEV * > getStartAndEndForAccess(const Loop *Lp, const SCEV *PtrExpr, Type *AccessTy, const SCEV *BTC, const SCEV *MaxBTC, ScalarEvolution *SE, DenseMap< std::pair< const SCEV *, const SCEV * >, std::pair< const SCEV *, const SCEV * > > *PointerBounds, DominatorTree *DT, AssumptionCache *AC, std::optional< ScalarEvolution::LoopGuards > &LoopGuards)
Calculate Start and End points of memory access using exact backedge taken count BTC if computable or...
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI RetainedKnowledge getKnowledgeForValue(const Value *V, ArrayRef< Attribute::AttrKind > AttrKinds, AssumptionCache &AC, function_ref< bool(RetainedKnowledge, Instruction *, const CallBase::BundleOpInfo *)> Filter=[](auto...) { return true;})
Return a valid Knowledge associated to the Value V if its Attribute kind is in AttrKinds and it match...
LLVM_ABI bool isValidAssumeForContext(const Instruction *I, const Instruction *CxtI, const DominatorTree *DT=nullptr, bool AllowEphemerals=false)
Return true if it is valid to use the assumptions provided by an assume intrinsic,...
LLVM_ABI bool getBooleanLoopAttribute(const Loop *TheLoop, StringRef Name)
Returns true if Name is applied to TheLoop and enabled.
LLVM_ABI Intrinsic::ID getVectorIntrinsicIDForCall(const CallInst *CI, const TargetLibraryInfo *TLI)
Returns intrinsic ID for call.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
unsigned getPointerAddressSpace(const Type *T)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
const Value * getLoadStorePointerOperand(const Value *V)
A helper function that returns the pointer operand of a load or store instruction.
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
LLVM_ABI const SCEV * replaceSymbolicStrideSCEV(PredicatedScalarEvolution &PSE, const SymbolicStrideMap &PtrToStride, Value *Ptr)
Return the SCEV corresponding to a pointer with the symbolic stride replaced with constant one,...
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
LLVM_ABI std::optional< int64_t > getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr, const Loop *Lp, const DominatorTree &DT, const SymbolicStrideMap &StridesMap=SymbolicStrideMap(), bool ShouldCheckWrap=true, SmallVectorImpl< const SCEVPredicate * > *Predicates=nullptr)
If the pointer has a constant stride return it in units of the access type size.
const Value * getPointerOperand(const Value *V)
A helper function that returns the pointer operand of a load, store or GEP instruction.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
auto dyn_cast_or_null(const Y &Val)
OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
DenseMap< Value *, const SCEVUnknown * > SymbolicStrideMap
Maps a pointer to its symbolic (non-constant) stride.
LLVM_ABI bool NullPointerIsDefined(const Function *F, unsigned AS=0)
Check whether null pointer dereferencing is considered undefined behavior for a given function or an ...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI std::optional< int64_t > getPointersDiff(Type *ElemTyA, Value *PtrA, Type *ElemTyB, Value *PtrB, const DataLayout &DL, ScalarEvolution &SE, bool StrictCheck=false, bool CheckType=true)
Returns the distance between the pointers PtrA and PtrB iff they are compatible and it is possible to...
LLVM_ABI bool sortPtrAccesses(ArrayRef< Value * > VL, Type *ElemTy, const DataLayout &DL, ScalarEvolution &SE, SmallVectorImpl< unsigned > &SortedIndices)
Attempt to sort the pointers in VL and return the sorted indices in SortedIndices,...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
LLVM_ABI bool isConsecutiveAccess(Value *A, Value *B, const DataLayout &DL, ScalarEvolution &SE, bool CheckType=true)
Returns true if the memory operations A and B are consecutive.
DWARFExpression::Operation Op
LLVM_ABI bool isGuaranteedNotToBeUndefOrPoison(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Return true if this function can prove that V does not have undef bits and is never poison.
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr U AbsoluteValue(T X)
Return the absolute value of a signed integer, converted to the corresponding unsigned integer type.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
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 std::optional< int64_t > getStrideFromAddRec(const SCEVAddRecExpr *AR, const Loop *Lp, Type *AccessTy, Value *Ptr, PredicatedScalarEvolution &PSE)
If AR is an affine AddRec for Lp with a constant step, return the step in units of AccessTy's allocat...
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
LLVM_ABI void getUnderlyingObjects(const Value *V, SmallVectorImpl< const Value * > &Objects, const LoopInfo *LI=nullptr, unsigned MaxLookup=MaxLookupSearchDepth)
This method is similar to getUnderlyingObject except that it can look through phi and select instruct...
Implement std::hash so that hash_code can be used in STL containers.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
IR Values for the lower and upper bounds of a pointer evolution.
MDNode * Scope
The tag for alias scope specification (used with noalias).
MDNode * TBAA
The tag for type-based alias analysis.
MDNode * NoAlias
The tag specifying the noalias scope.
A special type used by analysis passes to provide an address that identifies that particular analysis...
Instruction * getDestination(const MemoryDepChecker &DepChecker) const
Return the destination instruction of the dependence.
DepType Type
The type of the dependence.
unsigned Destination
Index of the destination of the dependence in the InstMap vector.
LLVM_ABI bool isPossiblyBackward() const
May be a lexically backward dependence type (includes Unknown).
Instruction * getSource(const MemoryDepChecker &DepChecker) const
Return the source instruction of the dependence.
LLVM_ABI bool isForward() const
Lexically forward dependence.
LLVM_ABI bool isBackward() const
Lexically backward dependence.
LLVM_ABI void print(raw_ostream &OS, unsigned Depth, const SmallVectorImpl< Instruction * > &Instrs) const
Print the dependence.
unsigned Source
Index of the source of the dependence in the InstMap vector.
DepType
The type of the dependence.
@ BackwardVectorizableButPreventsForwarding
@ ForwardButPreventsForwarding
static LLVM_ABI const char * DepName[]
String version of the types.
static LLVM_ABI VectorizationSafetyStatus isSafeForVectorization(DepType Type)
Dependence types that don't prevent vectorization.
Represent one information held inside an operand bundle of an llvm.assume.
unsigned AddressSpace
Address space of the involved pointers.
LLVM_ABI bool addPointer(unsigned Index, const RuntimePointerChecking &RtCheck)
Tries to add the pointer recorded in RtCheck at index Index to this pointer checking group.
bool NeedsFreeze
Whether the pointer needs to be frozen after expansion, e.g.
LLVM_ABI RuntimeCheckingPtrGroup(unsigned Index, const RuntimePointerChecking &RtCheck)
Create a new pointer checking group containing a single pointer, with index Index in RtCheck.
const SCEV * High
The SCEV expression which represents the upper bound of all the pointers in this group.
SmallVector< unsigned, 2 > Members
Indices of all the pointers that constitute this grouping.
const SCEV * Low
The SCEV expression which represents the lower bound of all the pointers in this group.
bool IsWritePtr
Holds the information if this pointer is used for writing to memory.
unsigned DependencySetId
Holds the id of the set of pointers that could be dependent because of a shared underlying object.
unsigned AliasSetId
Holds the id of the disjoint alias set to which this pointer belongs.
static LLVM_ABI const unsigned MaxVectorWidth
Maximum SIMD width.
static LLVM_ABI unsigned RuntimeMemoryCheckThreshold
\When performing memory disambiguation checks at runtime do not make more than this number of compari...
static LLVM_ABI bool isInterleaveForced()
True if force-vector-interleave was specified by the user.
static LLVM_ABI unsigned VectorizationInterleave
Interleave factor as overridden by the user.
static LLVM_ABI ElementCount VectorizationFactor
VF as overridden by the user.
static LLVM_ABI bool HoistRuntimeChecks
Function object to check whether the first component of a container supported by std::get (like std::...