65#define DEBUG_TYPE "basicaa"
79STATISTIC(SearchLimitReached,
"Number of times the limit to "
80 "decompose GEPs is reached");
81STATISTIC(SearchTimes,
"Number of times a GEP is decomposed");
84 FunctionAnalysisManager::Invalidator &Inv) {
107 bool RoundToAlign =
false) {
113 if (
Size->isScalable())
126 bool NullIsValidLoc) {
152 std::optional<TypeSize> ObjectSize =
getObjectSize(V,
DL, TLI, NullIsValidLoc,
164 bool NullIsValidLoc) {
169 bool CanBeNull, CanBeFreed;
171 V.getPointerDereferenceableBytes(
DL, CanBeNull, CanBeFreed);
172 DerefBytes = (CanBeNull && NullIsValidLoc) ? 0 : DerefBytes;
183 std::optional<TypeSize> ObjectSize =
185 return ObjectSize && *ObjectSize ==
Size;
206 auto [CacheIt, Inserted] =
209 return CacheIt->second;
214 CacheIt->second = Ret;
225 return Succs.
empty() ||
235 auto Iter = EarliestEscapes.try_emplace(Object);
237 std::pair<Instruction *, CaptureComponents> EarliestCapture =
241 if (EarliestCapture.first)
242 Inst2Obj[EarliestCapture.first].push_back(Object);
243 Iter.first->second = EarliestCapture;
246 auto IsNotCapturedBefore = [&]() {
248 Instruction *CaptureInst = Iter.first->second.first;
256 if (
I == CaptureInst) {
264 if (IsNotCapturedBefore())
266 return Iter.first->second.second;
270 auto Iter = Inst2Obj.find(
I);
271 if (Iter != Inst2Obj.end()) {
272 for (
const Value *Obj : Iter->second)
273 EarliestEscapes.erase(Obj);
286 unsigned ZExtBits = 0;
287 unsigned SExtBits = 0;
288 unsigned TruncBits = 0;
290 bool IsNonNegative =
false;
292 explicit CastedValue(
const Value *V) : V(V) {}
293 explicit CastedValue(
const Value *V,
unsigned ZExtBits,
unsigned SExtBits,
294 unsigned TruncBits,
bool IsNonNegative)
295 : V(V), ZExtBits(ZExtBits), SExtBits(SExtBits), TruncBits(TruncBits),
296 IsNonNegative(IsNonNegative) {}
299 return V->getType()->getPrimitiveSizeInBits() - TruncBits + ZExtBits +
303 CastedValue withValue(
const Value *NewV,
bool PreserveNonNeg)
const {
304 return CastedValue(NewV, ZExtBits, SExtBits, TruncBits,
305 IsNonNegative && PreserveNonNeg);
309 CastedValue withZExtOfValue(
const Value *NewV,
bool ZExtNonNegative)
const {
310 unsigned ExtendBy =
V->getType()->getPrimitiveSizeInBits() -
312 if (ExtendBy <= TruncBits)
315 return CastedValue(NewV, ZExtBits, SExtBits, TruncBits - ExtendBy,
319 ExtendBy -= TruncBits;
324 return CastedValue(NewV, ZExtBits + SExtBits + ExtendBy, 0, 0,
329 CastedValue withSExtOfValue(
const Value *NewV)
const {
330 unsigned ExtendBy =
V->getType()->getPrimitiveSizeInBits() -
332 if (ExtendBy <= TruncBits)
335 return CastedValue(NewV, ZExtBits, SExtBits, TruncBits - ExtendBy,
339 ExtendBy -= TruncBits;
342 return CastedValue(NewV, ZExtBits, SExtBits + ExtendBy, 0, IsNonNegative);
345 APInt evaluateWith(APInt
N)
const {
346 assert(
N.getBitWidth() ==
V->getType()->getPrimitiveSizeInBits() &&
347 "Incompatible bit width");
348 if (TruncBits)
N =
N.trunc(
N.getBitWidth() - TruncBits);
349 if (SExtBits)
N =
N.sext(
N.getBitWidth() + SExtBits);
350 if (ZExtBits)
N =
N.zext(
N.getBitWidth() + ZExtBits);
354 ConstantRange evaluateWith(ConstantRange
N)
const {
355 assert(
N.getBitWidth() ==
V->getType()->getPrimitiveSizeInBits() &&
356 "Incompatible bit width");
357 if (TruncBits)
N =
N.truncate(
N.getBitWidth() - TruncBits);
358 if (IsNonNegative && !
N.isAllNonNegative())
362 if (SExtBits)
N =
N.signExtend(
N.getBitWidth() + SExtBits);
363 if (ZExtBits)
N =
N.zeroExtend(
N.getBitWidth() + ZExtBits);
367 bool canDistributeOver(
bool NUW,
bool NSW)
const {
371 return (!ZExtBits || NUW) && (!SExtBits || NSW);
374 bool hasSameCastsAs(
const CastedValue &
Other)
const {
375 if (
V->getType() !=
Other.V->getType())
378 if (ZExtBits ==
Other.ZExtBits && SExtBits ==
Other.SExtBits &&
379 TruncBits ==
Other.TruncBits)
383 if (IsNonNegative ||
Other.IsNonNegative)
384 return (ZExtBits + SExtBits ==
Other.ZExtBits +
Other.SExtBits &&
385 TruncBits ==
Other.TruncBits);
402 const APInt &
Offset,
bool IsNUW,
bool IsNSW)
406 : Val(Val), IsNUW(
true), IsNSW(
true) {
407 unsigned BitWidth = Val.getBitWidth();
415 bool NSW = IsNSW && (
Other.isOne() || (MulIsNSW &&
Offset.isZero()));
416 bool NUW = IsNUW && (
Other.isOne() || MulIsNUW);
433 Val.evaluateWith(Const->getValue()),
true,
true);
437 APInt RHS = Val.evaluateWith(RHSC->getValue());
440 bool NUW =
true, NSW =
true;
442 NUW &= BOp->hasNoUnsignedWrap();
443 NSW &= BOp->hasNoSignedWrap();
445 if (!Val.canDistributeOver(NUW, NSW))
454 switch (BOp->getOpcode()) {
459 case Instruction::Or:
465 case Instruction::Add: {
473 case Instruction::Sub: {
481 case Instruction::Mul:
486 case Instruction::Shl:
492 if (
RHS.getLimitedValue() > Val.getBitWidth())
497 E.Offset <<=
RHS.getLimitedValue();
498 E.Scale <<=
RHS.getLimitedValue();
509 Val.withZExtOfValue(ZExt->getOperand(0), ZExt->hasNonNeg()),
DL,
523struct VariableGEPIndex {
538 bool hasNegatedScaleOf(
const VariableGEPIndex &
Other)
const {
539 if (IsNegated ==
Other.IsNegated)
540 return Scale == -
Other.Scale;
541 return Scale ==
Other.Scale;
548 void print(raw_ostream &OS)
const {
549 OS <<
"(V=" << Val.V->
getName()
550 <<
", zextbits=" << Val.ZExtBits
551 <<
", sextbits=" << Val.SExtBits
552 <<
", truncbits=" << Val.TruncBits
553 <<
", scale=" << Scale
555 <<
", negated=" << IsNegated <<
")";
577 OS <<
", inbounds=" << (
NWFlags.isInBounds() ?
"1" :
"0")
578 <<
", nuw=" << (
NWFlags.hasNoUnsignedWrap() ?
"1" :
"0")
579 <<
"(DecomposedGEP Base=" <<
Base->getName() <<
", Offset=" <<
Offset
581 for (
size_t i = 0; i <
VarIndices.size(); i++) {
606 unsigned IndexSize =
DL.getIndexTypeSizeInBits(V->getType());
607 DecomposedGEP Decomposed;
608 Decomposed.Offset =
APInt(IndexSize, 0);
615 if (!GA->isInterposable()) {
616 V = GA->getAliasee();
624 if (
Op->getOpcode() == Instruction::BitCast ||
625 Op->getOpcode() == Instruction::AddrSpaceCast) {
626 Value *NewV =
Op->getOperand(0);
629 if (DL.getIndexTypeSizeInBits(NewV->
getType()) != IndexSize) {
641 if (
PHI->getNumIncomingValues() == 1) {
642 V =
PHI->getIncomingValue(0);
673 I !=
E; ++
I, ++GTI) {
682 Decomposed.Offset += DL.getStructLayout(STy)->getElementOffset(FieldNo);
699 CIdx->getValue().sextOrTrunc(IndexSize);
713 bool NonNeg = NUSW && NUW;
714 unsigned Width =
Index->getType()->getIntegerBitWidth();
715 unsigned SExtBits = IndexSize > Width ? IndexSize - Width : 0;
716 unsigned TruncBits = IndexSize < Width ? Width - IndexSize : 0;
718 CastedValue(Index, 0, SExtBits, TruncBits, NonNeg), DL, 0, AC, DT);
722 LE =
LE.mul(APInt(IndexSize, TypeSize), NUW, NUSW);
723 Decomposed.Offset +=
LE.Offset;
724 APInt Scale =
LE.Scale;
726 Decomposed.NWFlags = Decomposed.NWFlags.withoutNoUnsignedWrap();
732 for (
unsigned i = 0, e = Decomposed.VarIndices.size(); i != e; ++i) {
733 if ((Decomposed.VarIndices[i].Val.V ==
LE.Val.V ||
735 Decomposed.VarIndices[i].Val.hasSameCastsAs(
LE.Val)) {
736 Scale += Decomposed.VarIndices[i].Scale;
738 LE.IsNSW =
LE.IsNUW =
false;
739 Decomposed.VarIndices.erase(Decomposed.VarIndices.begin() + i);
745 VariableGEPIndex
Entry = {
LE.Val, Scale, CxtI,
LE.IsNSW,
747 Decomposed.VarIndices.push_back(Entry);
753 }
while (--MaxLookup);
757 SearchLimitReached++;
764 assert(Visited.empty() &&
"Visited must be cleared after use!");
767 unsigned MaxLookup = 8;
774 if (!Visited.insert(V).second)
788 if (Arg->hasNoAliasAttr() && Arg->onlyReadsMemory()) {
799 if (!GV->isConstant())
815 if (PN->getNumIncomingValues() > MaxLookup)
823 }
while (!Worklist.
empty() && --MaxLookup);
826 if (!Worklist.
empty())
834 return II &&
II->getIntrinsicID() == IID;
846 if (
Call->hasReadingOperandBundles())
848 if (
Call->hasClobberingOperandBundles())
850 if (
Call->isVolatile()) {
863 switch (F->getIntrinsicID()) {
864 case Intrinsic::experimental_guard:
865 case Intrinsic::experimental_deoptimize:
872 return F->getMemoryEffects();
877 if (
Call->doesNotAccessMemory(ArgIdx))
880 if (
Call->onlyWritesMemory(ArgIdx))
883 if (
Call->onlyReadsMemory(ArgIdx))
892 if (!inst->getParent())
894 return inst->getParent()->getParent();
908 return !F1 || !F2 || F1 == F2;
916 "BasicAliasAnalysis doesn't support interprocedural queries.");
917 return aliasCheck(LocA.
Ptr, LocA.
Size, LocB.
Ptr, LocB.
Size, AAQI, CtxI);
930 "AliasAnalysis query involving multiple functions!");
941 if (CI->isTailCall() &&
942 !CI->getAttributes().hasAttrSomewhere(Attribute::ByVal))
955 if (ME.doesNotAccessMemory())
983 if ((ArgMR | OtherMR) != OtherMR) {
985 for (
const Use &U :
Call->data_ops()) {
986 const Value *Arg = U;
989 unsigned ArgIdx =
Call->getDataOperandNo(&U);
991 Call->isArgOperand(&U)
999 if (NewArgMR == ArgMR)
1008 if ((ErrnoMR | Result) != Result) {
1100 auto BaseObjectsAlias = [&]() {
1116 return BaseObjectsAlias();
1119 DominatorTree *DT = getDT(AAQI);
1120 DecomposedGEP DecompGEP1 = DecomposeGEPExpression(GEP1, DL, &AC, DT);
1121 DecomposedGEP DecompGEP2 = DecomposeGEPExpression(V2, DL, &AC, DT);
1124 if (DecompGEP1.Base == GEP1 && DecompGEP2.Base == V2)
1128 if (DecompGEP1.Offset.getBitWidth() != DecompGEP2.Offset.getBitWidth())
1129 return BaseObjectsAlias();
1132 if (DecompGEP1.VarIndices.size() < DecompGEP2.VarIndices.size()) {
1140 subtractDecomposedGEPs(DecompGEP1, DecompGEP2, AAQI);
1147 if (DecompGEP1.NWFlags.isInBounds() && DecompGEP1.VarIndices.empty() &&
1149 DecompGEP1.Offset.sge(V2Size.
getValue()) &&
1154 if (DecompGEP2.NWFlags.isInBounds() && DecompGEP1.VarIndices.empty() &&
1156 DecompGEP1.Offset.sle(-V1Size.
getValue()) &&
1162 if (DecompGEP1.Offset == 0 && DecompGEP1.VarIndices.empty())
1163 return AAQI.
AAR.
alias(MemoryLocation(DecompGEP1.Base, V1Size),
1164 MemoryLocation(DecompGEP2.Base, V2Size), AAQI);
1167 AliasResult BaseAlias =
1183 if (DecompGEP1.VarIndices.empty()) {
1184 APInt &
Off = DecompGEP1.Offset;
1187 LocationSize VLeftSize = V2Size;
1188 LocationSize VRightSize = V1Size;
1189 const bool Swapped =
Off.isNegative();
1205 const TypeSize LSize = VLeftSize.
getValue();
1207 if (
Off.ult(LSize)) {
1212 Off.ule(INT32_MAX) && (Off + VRightSize.
getValue()).ule(LSize)) {
1228 if (!Overflow &&
Off.uge(UpperRange))
1236 if (DecompGEP1.VarIndices.size() == 1 &&
1237 DecompGEP1.VarIndices[0].Val.TruncBits == 0 &&
1238 DecompGEP1.Offset.isZero() &&
1241 const VariableGEPIndex &ScalableVar = DecompGEP1.VarIndices[0];
1243 ScalableVar.IsNegated ? -ScalableVar.Scale : ScalableVar.Scale;
1244 LocationSize VLeftSize = Scale.
isNegative() ? V1Size : V2Size;
1248 bool Overflows = !DecompGEP1.VarIndices[0].IsNSW;
1273 if (!DecompGEP1.VarIndices.empty() &&
1274 DecompGEP1.NWFlags.hasNoUnsignedWrap() && V2Size.
hasValue() &&
1284 unsigned BW = DecompGEP1.Offset.getBitWidth();
1290 ConstantRange OffsetRange = ConstantRange(DecompGEP1.Offset);
1291 for (
unsigned i = 0, e = DecompGEP1.VarIndices.size(); i != e; ++i) {
1292 const VariableGEPIndex &
Index = DecompGEP1.VarIndices[i];
1293 const APInt &Scale =
Index.Scale;
1297 APInt ScaleForGCD = Scale;
1310 ScaleForGCD <<= std::min(VarTZ, MaxShift);
1314 GCD = ScaleForGCD.
abs();
1319 true, &AC,
Index.CxtI);
1326 "Bit widths are normalized to MaxIndexSize");
1328 CR = CR.
smul_sat(ConstantRange(Scale));
1330 CR = CR.
smul_fast(ConstantRange(Scale));
1332 if (
Index.IsNegated)
1333 OffsetRange = OffsetRange.
sub(CR);
1335 OffsetRange = OffsetRange.
add(CR);
1344 APInt ModOffset = DecompGEP1.Offset.srem(GCD);
1348 (GCD - ModOffset).uge(V1Size.
getValue()))
1353 ConstantRange Range1 = OffsetRange.
add(
1354 ConstantRange(APInt(BW, 0), APInt(BW, V1Size.
getValue())));
1355 ConstantRange Range2 =
1356 ConstantRange(APInt(BW, 0), APInt(BW, V2Size.
getValue()));
1362 auto MultiplyByScaleNoWrap = [](
const VariableGEPIndex &Var) {
1366 int ValOrigBW = Var.Val.V->getType()->getPrimitiveSizeInBits();
1370 int MaxScaleValueBW = Var.Val.getBitWidth() - ValOrigBW;
1371 if (MaxScaleValueBW <= 0)
1373 return Var.Scale.ule(
1379 std::optional<APInt> MinAbsVarIndex;
1380 if (DecompGEP1.VarIndices.size() == 1) {
1382 const VariableGEPIndex &Var = DecompGEP1.VarIndices[0];
1383 if (Var.Val.TruncBits == 0 &&
1384 isKnownNonZero(Var.Val.V, SimplifyQuery(DL, DT, &AC, Var.CxtI))) {
1387 if (MultiplyByScaleNoWrap(Var)) {
1389 MinAbsVarIndex = Var.Scale.
abs();
1392 }
else if (DecompGEP1.VarIndices.size() == 2) {
1397 const VariableGEPIndex &Var0 = DecompGEP1.VarIndices[0];
1398 const VariableGEPIndex &Var1 = DecompGEP1.VarIndices[1];
1399 if (Var0.hasNegatedScaleOf(Var1) && Var0.Val.TruncBits == 0 &&
1401 MultiplyByScaleNoWrap(Var0) && MultiplyByScaleNoWrap(Var1) &&
1403 SimplifyQuery(DL, DT, &AC, Var0.CxtI
1406 MinAbsVarIndex = Var0.Scale.
abs();
1409 if (MinAbsVarIndex) {
1411 APInt OffsetLo = DecompGEP1.Offset - *MinAbsVarIndex;
1412 APInt OffsetHi = DecompGEP1.Offset + *MinAbsVarIndex;
1419 if (constantOffsetHeuristic(DecompGEP1, V1Size, V2Size, &AC, DT, AAQI))
1449 if (isValueEqualInPotentialCycles(
SI->getCondition(), SI2->getCondition(),
1452 AAQI.
AAR.
alias(MemoryLocation(
SI->getTrueValue(), SISize),
1453 MemoryLocation(SI2->getTrueValue(), V2Size), AAQI);
1456 AliasResult ThisAlias =
1457 AAQI.
AAR.
alias(MemoryLocation(
SI->getFalseValue(), SISize),
1458 MemoryLocation(SI2->getFalseValue(), V2Size), AAQI);
1464 AliasResult Alias = AAQI.
AAR.
alias(MemoryLocation(
SI->getTrueValue(), SISize),
1465 MemoryLocation(V2, V2Size), AAQI);
1469 AliasResult ThisAlias =
1470 AAQI.
AAR.
alias(MemoryLocation(
SI->getFalseValue(), SISize),
1471 MemoryLocation(V2, V2Size), AAQI);
1488 std::optional<AliasResult> Alias;
1490 AliasResult ThisAlias = AAQI.
AAR.
alias(
1505 SmallVector<Value *, 4> V1Srcs;
1509 bool isRecursive =
false;
1510 auto CheckForRecPhi = [&](
Value *PV) {
1520 SmallPtrSet<Value *, 4> UniqueSrc;
1521 Value *OnePhi =
nullptr;
1528 if (OnePhi && OnePhi != PV1) {
1539 if (CheckForRecPhi(PV1))
1542 if (UniqueSrc.
insert(PV1).second)
1546 if (OnePhi && UniqueSrc.
size() > 1)
1567 AliasResult Alias = AAQI.
AAR.
alias(MemoryLocation(V1Srcs[0], PNSize),
1568 MemoryLocation(V2, V2Size), AAQI);
1581 for (
unsigned i = 1, e = V1Srcs.
size(); i != e; ++i) {
1584 AliasResult ThisAlias = AAQI.
AAR.
alias(
1585 MemoryLocation(V, PNSize), MemoryLocation(V2, V2Size), AAQI);
1630 if (isValueEqualInPotentialCycles(V1, V2, AAQI))
1681 TLI, NullIsValidLocation)) ||
1684 TLI, NullIsValidLocation)))
1688 for (AssumptionCache::ResultElem &Elem : AC.assumptionsFor(O1)) {
1693 OperandBundleUse OBU =
Assume->getOperandBundleAt(Elem.Index);
1694 if (OBU.
getTagName() ==
"separate_storage") {
1703 DominatorTree *DT = getDT(AAQI);
1704 auto ValidAssumeForPtrContext = [&](
const Value *Ptr) {
1711 &*PtrA->getParent()->getEntryBlock().begin();
1718 if ((O1 == HintO1 && O2 == HintO2) || (O1 == HintO2 && O2 == HintO1)) {
1724 ValidAssumeForPtrContext(V1) || ValidAssumeForPtrContext(V2)) {
1748 if (AAQI.
Depth >= 512)
1757 const bool Swapped = V1 > V2;
1763 auto &
Entry = Pair.first->second;
1764 if (!
Entry.isDefinitive()) {
1769 if (
Entry.isAssumption())
1770 ++
Entry.NumAssumptionUses;
1781 aliasCheckRecursive(V1, V1Size, V2, V2Size, AAQI, O1, O2);
1785 auto &
Entry = It->second;
1788 bool AssumptionDisproven =
1790 if (AssumptionDisproven)
1797 Entry.Result.swap(Swapped);
1802 if (AssumptionDisproven)
1818 if (AAQI.
Depth == 1) {
1837 AliasResult
Result = aliasGEP(GV1, V1Size, V2, V2Size, O1, O2, AAQI);
1841 AliasResult
Result = aliasGEP(GV2, V2Size, V1, V1Size, O2, O1, AAQI);
1848 AliasResult
Result = aliasPHI(PN, V1Size, V2, V2Size, AAQI);
1852 AliasResult
Result = aliasPHI(PN, V2Size, V1, V1Size, AAQI);
1859 AliasResult
Result = aliasSelect(
S1, V1Size, V2, V2Size, AAQI);
1863 AliasResult
Result = aliasSelect(S2, V2Size, V1, V1Size, AAQI);
1887 if (
Loc.Size.hasValue() &&
1888 Loc.Size.getValue().getKnownMinValue() * 8 > TLI.getIntSize())
1902bool BasicAAResult::isValueEqualInPotentialCycles(
const Value *V,
1914 if (!Inst || Inst->
getParent()->isEntryBlock())
1917 return isNotInCycle(Inst, getDT(AAQI),
nullptr,
nullptr);
1921void BasicAAResult::subtractDecomposedGEPs(DecomposedGEP &DestGEP,
1922 const DecomposedGEP &SrcGEP,
1926 if (DestGEP.Offset.ult(SrcGEP.Offset))
1927 DestGEP.NWFlags = DestGEP.NWFlags.withoutNoUnsignedWrap();
1929 DestGEP.Offset -= SrcGEP.Offset;
1930 for (
const VariableGEPIndex &Src : SrcGEP.VarIndices) {
1934 for (
auto I :
enumerate(DestGEP.VarIndices)) {
1935 VariableGEPIndex &Dest =
I.value();
1936 if ((!isValueEqualInPotentialCycles(Dest.Val.V, Src.Val.V, AAQI) &&
1938 !Dest.Val.hasSameCastsAs(Src.Val))
1942 if (Dest.IsNegated) {
1943 Dest.Scale = -Dest.Scale;
1944 Dest.IsNegated =
false;
1950 if (Dest.Scale != Src.Scale) {
1953 if (Dest.Scale.
ult(Src.Scale))
1954 DestGEP.NWFlags = DestGEP.NWFlags.withoutNoUnsignedWrap();
1956 Dest.Scale -= Src.Scale;
1959 DestGEP.VarIndices.erase(DestGEP.VarIndices.begin() +
I.index());
1967 VariableGEPIndex
Entry = {Src.Val, Src.Scale, Src.CxtI, Src.IsNSW,
1969 DestGEP.VarIndices.push_back(Entry);
1972 DestGEP.NWFlags = DestGEP.NWFlags.withoutNoUnsignedWrap();
1977bool BasicAAResult::constantOffsetHeuristic(
const DecomposedGEP &
GEP,
1983 if (
GEP.VarIndices.size() != 2 || !MaybeV1Size.
hasValue() ||
1987 const uint64_t V1Size = MaybeV1Size.
getValue();
1988 const uint64_t V2Size = MaybeV2Size.
getValue();
1990 const VariableGEPIndex &Var0 =
GEP.VarIndices[0], &Var1 =
GEP.VarIndices[1];
1992 if (Var0.Val.TruncBits != 0 || !Var0.Val.hasSameCastsAs(Var1.Val) ||
1993 !Var0.hasNegatedScaleOf(Var1) ||
2001 LinearExpression E0 =
2003 LinearExpression E1 =
2005 if (E0.
Scale != E1.
Scale || !E0.Val.hasSameCastsAs(E1.Val) ||
2006 !isValueEqualInPotentialCycles(E0.Val.V, E1.Val.V, AAQI))
2016 APInt MinDiff = E0.
Offset - E1.
Offset, Wrapped = -MinDiff;
2018 APInt MinDiffBytes =
2025 return MinDiffBytes.
uge(V1Size +
GEP.Offset.abs()) &&
2026 MinDiffBytes.
uge(V2Size +
GEP.Offset.abs());
2046void BasicAAWrapperPass::anchor() {}
2049 "Basic Alias Analysis (stateless AA impl)",
true,
true)
2054 "Basic Alias Analysis (stateless AA impl)",
true,
true)
2066 TLIWP.getTLI(
F), ACT.getAssumptionCache(
F),
2067 &DTWP.getDomTree()));
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 void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
This file contains the simple types necessary to represent the attributes associated with functions a...
static cl::opt< bool > EnableRecPhiAnalysis("basic-aa-recphi", cl::Hidden, cl::init(true))
Enable analysis of recursive PHI nodes.
static const Function * getParent(const Value *V)
static bool isObjectSmallerThan(const Value *V, TypeSize Size, const DataLayout &DL, const TargetLibraryInfo &TLI, bool NullIsValidLoc)
Returns true if we can prove that the object specified by V is smaller than Size.
static bool isObjectSize(const Value *V, TypeSize Size, const DataLayout &DL, const TargetLibraryInfo &TLI, bool NullIsValidLoc)
Returns true if we can prove that the object specified by V has size Size.
static cl::opt< bool > EnableSeparateStorageAnalysis("basic-aa-separate-storage", cl::Hidden, cl::init(true))
static bool isArgumentOrArgumentLike(const Value *V)
static bool notDifferentParent(const Value *O1, const Value *O2)
static LinearExpression GetLinearExpression(const CastedValue &Val, const DataLayout &DL, unsigned Depth, AssumptionCache *AC, DominatorTree *DT)
Analyzes the specified value as a linear expression: "A*V + B", where A and B are constant integers.
static bool isNotInCycle(const Instruction *I, const DominatorTree *DT, const LoopInfo *LI, const CycleInfo *CI)
static bool areBothVScale(const Value *V1, const Value *V2)
Return true if both V1 and V2 are VScale.
static TypeSize getMinimalExtentFrom(const Value &V, const LocationSize &LocSize, const DataLayout &DL, bool NullIsValidLoc)
Return the minimal extent from V to the end of the underlying object, assuming the result is used in ...
static AliasResult MergeAliasResults(AliasResult A, AliasResult B)
static bool isIntrinsicCall(const CallBase *Call, Intrinsic::ID IID)
This is the interface for LLVM's primary stateless and local alias analysis.
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 declares the LLVM IR specialization of the GenericCycle templates.
This file provides utility analysis objects describing memory locations.
uint64_t IntrinsicInst * II
#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 provides utility classes that use RAII to save and restore values.
This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...
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 unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
This class stores info we want to provide to or retain within an alias query.
SmallVector< AAQueryInfo::LocPair, 4 > AssumptionBasedResults
Location pairs for which an assumption based result is currently stored.
unsigned Depth
Query depth used to distinguish recursive queries.
int NumAssumptionUses
How many active NoAlias assumption uses there are.
std::pair< AACacheLoc, AACacheLoc > LocPair
bool MayBeCrossIteration
Tracks whether the accesses may be on different cycle iterations.
LLVM_ABI AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB)
The main low level interface to the alias analysis implementation.
LLVM_ABI MemoryEffects getMemoryEffects(const CallBase *Call)
Return the behavior of the given call site.
LLVM_ABI ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx)
Get the ModRef info associated with a pointer argument of a call.
LLVM_ABI AliasResult aliasErrno(const MemoryLocation &Loc, const Module *M)
Class for arbitrary precision integers.
LLVM_ABI APInt umul_ov(const APInt &RHS, bool &Overflow) const
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 ult(const APInt &RHS) const
Unsigned less than comparison.
bool isNegative() const
Determine sign of this APInt.
unsigned countr_zero() const
Count the number of trailing zero bits.
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
unsigned getSignificantBits() const
Get the minimum bit size for this signed APInt.
LLVM_ABI APInt smul_ov(const APInt &RHS, bool &Overflow) const
bool isNonNegative() const
Determine if this APInt Value is non-negative (>= 0)
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
The possible results of an alias query.
void swap(bool DoSwap=true)
Helper for processing AliasResult for swapped memory location pairs.
@ MayAlias
The two locations may or may not alias.
@ NoAlias
The two locations do not alias at all.
@ PartialAlias
The two locations alias, but only due to a partial overlap.
@ MustAlias
The two locations precisely alias each other.
void setOffset(int32_t NewOffset)
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
AnalysisUsage & addRequiredTransitive()
This class represents an incoming formal argument to a Function.
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.
This is the AA result object for the basic, local, and stateless alias analysis.
LLVM_ABI AliasResult aliasErrno(const MemoryLocation &Loc, const Module *M)
LLVM_ABI ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc, AAQueryInfo &AAQI)
Checks to see if the specified callsite can clobber the specified memory object.
LLVM_ABI ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx)
Get the location associated with a pointer argument of a callsite.
LLVM_ABI MemoryEffects getMemoryEffects(const CallBase *Call, AAQueryInfo &AAQI)
Returns the behavior when calling the given call site.
LLVM_ABI ModRefInfo getModRefInfoMask(const MemoryLocation &Loc, AAQueryInfo &AAQI, bool IgnoreLocals=false)
Returns a bitmask that should be unconditionally applied to the ModRef info of a memory location.
LLVM_ABI bool invalidate(Function &Fn, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &Inv)
Handle invalidation events in the new pass manager.
LLVM_ABI AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, AAQueryInfo &AAQI, const Instruction *CtxI)
Legacy wrapper pass to provide the BasicAAResult object.
bool runOnFunction(Function &F) override
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
LLVM_ABI BasicAAResult run(Function &F, FunctionAnalysisManager &AM)
LLVM Basic Block Representation.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
This class represents a function call, abstracting a target machine's calling convention.
This is the shared class of boolean and integer constants.
LLVM_ABI ConstantRange add(const ConstantRange &Other) const
Return a new range representing the possible values resulting from an addition of a value in this ran...
static LLVM_ABI ConstantRange fromKnownBits(const KnownBits &Known, bool IsSigned)
Initialize a range based on a known bits constraint.
LLVM_ABI ConstantRange smul_fast(const ConstantRange &Other) const
Return range of possible values for a signed multiplication of this and Other.
LLVM_ABI bool isEmptySet() const
Return true if this set contains no members.
LLVM_ABI ConstantRange smul_sat(const ConstantRange &Other) const
Perform a signed saturating multiplication of two constant ranges.
LLVM_ABI APInt getUnsignedMax() const
Return the largest unsigned value contained in the ConstantRange.
LLVM_ABI ConstantRange intersectWith(const ConstantRange &CR, PreferredRangeType Type=Smallest) const
Return the range that results from the intersection of this range with another range.
LLVM_ABI APInt getSignedMax() const
Return the largest signed value contained in the ConstantRange.
uint32_t getBitWidth() const
Get the bit width of this ConstantRange.
LLVM_ABI ConstantRange sub(const ConstantRange &Other) const
Return a new range representing the possible values resulting from a subtraction of a value in this r...
A parsed version of the target data layout string in and methods for querying it.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
bool erase(const 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.
void removeInstruction(Instruction *I)
CaptureComponents getCapturesBefore(const Value *Object, const Instruction *I, bool OrAt) override
Return how Object may be captured before instruction I, considering only provenance captures.
FunctionPass class - This class is used to implement most global optimizations.
Represents flags for the getelementptr instruction/expression.
static GEPNoWrapFlags all()
bool hasNoUnsignedSignedWrap() const
bool hasNoUnsignedWrap() const
LLVM_ABI Type * getSourceElementType() const
GEPNoWrapFlags getNoWrapFlags() const
CycleT * getCycle(const BlockT *Block) const
Find the innermost cycle containing a given block.
Module * getParent()
Get the module that this global value is contained inside of...
A wrapper class for inspecting calls to intrinsic functions.
bool mayBeBeforePointer() const
Whether accesses before the base pointer are possible.
static constexpr LocationSize beforeOrAfterPointer()
Any location before or after the base pointer (but still within the underlying object).
TypeSize getValue() const
static constexpr LocationSize afterPointer()
Any location after the base pointer (but still within the underlying object).
static MemoryEffectsBase readOnly()
MemoryEffectsBase getWithoutLoc(Location Loc) const
Get new MemoryEffectsBase with NoModRef on the given Loc.
static MemoryEffectsBase inaccessibleMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
static MemoryEffectsBase writeOnly()
Representation for a specific memory location.
LocationSize Size
The maximum size of the location, in address-units, or UnknownSize if the size is not known.
static MemoryLocation getBeforeOrAfter(const Value *Ptr, const AAMDNodes &AATags=AAMDNodes())
Return a location that may access any location before or after Ptr, while remaining within the underl...
const Value * Ptr
The address of the start of the location.
static LLVM_ABI MemoryLocation getForArgument(const CallBase *Call, unsigned ArgIdx, const TargetLibraryInfo *TLI)
Return a location representing a particular argument of a call.
A Module instance is used to store all the information related to an LLVM module.
This is a utility class that provides an abstraction for the common functionality between Instruction...
op_range incoming_values()
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
A set of analyses that are preserved following a run of a transformation pass.
This class represents the LLVM 'select' instruction.
CaptureComponents getCapturesBefore(const Value *Object, const Instruction *I, bool OrAt) override
Return how Object may be captured before instruction I, considering only provenance captures.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
bool isPointerTy() const
True if this is an instance of PointerType.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
A Use represents the edge between a Value definition and its users.
const Use * const_op_iterator
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI const Value * stripPointerCastsForAliasAnalysis() const
Strip off pointer casts, all-zero GEPs, single-argument phi nodes and invariant group info.
constexpr ScalarTy getFixedValue() const
static constexpr bool isKnownLT(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
StructType * getStructTypeOrNull() const
TypeSize getSequentialElementStride(const DataLayout &DL) const
const ParentTy * getParent() const
This class implements an extremely fast bulk output stream that can only output to a stream.
const APInt & umin(const APInt &A, const APInt &B)
Determine the smaller of two APInts considered to be unsigned.
LLVM_ABI APInt GreatestCommonDivisor(APInt A, APInt B)
Compute GCD of two unsigned APInt values.
bool match(Val *V, const Pattern &P)
IntrinsicID_match m_VScale()
Matches a call to llvm.vscale().
initializer< Ty > init(const Ty &Val)
@ Assume
Do not drop type tests (default).
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
bool capturesReadProvenanceOnly(CaptureComponents CC)
FunctionAddr VTableAddr Value
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,...
SaveAndRestore(T &) -> SaveAndRestore< T >
LLVM_ABI const Value * getArgumentAliasingToReturnedPointer(const CallBase *Call, bool MustPreserveNullness)
This function returns call pointer argument that is considered the same by aliasing rules.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto successors(const MachineBasicBlock *BB)
LLVM_ABI bool isBaseOfObject(const Value *V)
Return true if we know V to the base address of the corresponding memory object.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
LLVM_ABI std::pair< Instruction *, CaptureComponents > FindEarliestCapture(const Value *V, Function &F, bool ReturnCaptures, const DominatorTree &DT, CaptureComponents Mask, unsigned MaxUsesToExplore=0)
MemoryEffectsBase< IRMemLocation > MemoryEffects
Summary of how a function affects memory in the program.
LLVM_ABI std::optional< TypeSize > getBaseObjectSize(const Value *Ptr, const DataLayout &DL, const TargetLibraryInfo *TLI, ObjectSizeOpts Opts={})
Like getObjectSize(), but only returns the size of base objects (like allocas, global variables and a...
LLVM_ABI ConstantRange computeConstantRange(const Value *V, bool ForSigned, bool UseInstrInfo=true, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Determine the possible constant range of an integer or vector of integer value.
LLVM_ABI bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL, const TargetLibraryInfo *TLI, ObjectSizeOpts Opts={})
Compute the size of the object pointed by Ptr.
bool capturesFullProvenance(CaptureComponents CC)
bool isModSet(const ModRefInfo MRI)
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 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.
generic_gep_type_iterator<> gep_type_iterator
bool isModOrRefSet(const ModRefInfo MRI)
constexpr unsigned MaxLookupSearchDepth
The max limit of the search depth in DecomposeGEPExpression() and getUnderlyingObject().
LLVM_ABI ConstantRange getVScaleRange(const Function *F, unsigned BitWidth)
Determine the possible constant range of vscale with the given bit width, based on the vscale_range f...
LLVM_ABI FunctionPass * createBasicAAWrapperPass()
LLVM_ABI bool isMallocOrCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI)
Tests if a value is a call or invoke to a library function that allocates memory similar to malloc or...
CaptureComponents
Components of the pointer that may be captured.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI bool isKnownNonZero(const Value *V, const SimplifyQuery &Q, unsigned Depth=0)
Return true if the given value is known to be non-zero when defined.
ModRefInfo
Flags indicating whether a memory access modifies or references memory.
@ Ref
The access may reference the value stored in memory.
@ ModRef
The access may reference and may modify the value stored in memory.
@ Mod
The access may modify the value stored in memory.
@ NoModRef
The access neither references nor modifies the value stored in memory.
@ ArgMem
Access to memory via argument pointers.
@ InaccessibleMem
Memory that is inaccessible via LLVM IR.
LLVM_ABI bool isPotentiallyReachable(const Instruction *From, const Instruction *To, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet=nullptr, const DominatorTree *DT=nullptr, const LoopInfo *LI=nullptr, const CycleInfo *CI=nullptr)
Determine whether instruction 'To' is reachable from 'From', without passing through any blocks in Ex...
LLVM_ABI bool isKnownNonEqual(const Value *V1, const Value *V2, const SimplifyQuery &SQ, unsigned Depth=0)
Return true if the given values are known to be non-equal when defined.
DWARFExpression::Operation Op
LLVM_ABI bool PointerMayBeCaptured(const Value *V, bool ReturnCaptures, unsigned MaxUsesToExplore=0)
PointerMayBeCaptured - Return true if this pointer value may be captured by the enclosing function (w...
LLVM_ABI bool isPotentiallyReachableFromMany(SmallVectorImpl< BasicBlock * > &Worklist, const BasicBlock *StopBB, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet, const DominatorTree *DT=nullptr, const LoopInfo *LI=nullptr, const CycleInfo *CI=nullptr)
Determine whether there is at least one path from a block in 'Worklist' to 'StopBB' without passing t...
bool isModAndRefSet(const ModRefInfo MRI)
LLVM_ABI bool isIdentifiedFunctionLocal(const Value *V)
Return true if V is umabigously identified at the function-level.
constexpr unsigned BitWidth
LLVM_ABI bool isEscapeSource(const Value *V)
Returns true if the pointer is one which would have been considered an escape by isNotCapturedBefore.
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)
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....
bool capturesNothing(CaptureComponents CC)
LLVM_ABI bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
SmallVector< VariableGEPIndex, 4 > VarIndices
void print(raw_ostream &OS) const
static constexpr int Definitive
Cache entry is neither an assumption nor does it use a (non-definitive) assumption.
static constexpr int AssumptionBased
Cache entry is not an assumption itself, but may be using an assumption from higher up the stack.
A special type used by analysis passes to provide an address that identifies that particular analysis...
virtual CaptureComponents getCapturesBefore(const Value *Object, const Instruction *I, bool OrAt)=0
Return how Object may be captured before instruction I, considering only provenance captures.
virtual ~CaptureAnalysis()=0
unsigned countMinTrailingZeros() const
Returns the minimum number of trailing zero bits.
Linear expression BasePtr + Index * Scale + Offset.
LinearExpression(Value *BasePtr, unsigned BitWidth)
Various options to control the behavior of getObjectSize.
bool NullIsUnknownSize
If this is true, null pointers in address space 0 will be treated as though they can't be evaluated.
bool RoundToAlign
Whether to round the result up to the alignment of allocas, byval arguments, and global variables.
StringRef getTagName() const
Return the tag of this operand bundle as a string.