97#define DEBUG_TYPE "dse"
99STATISTIC(NumRemainingStores,
"Number of stores remaining after DSE");
100STATISTIC(NumRedundantStores,
"Number of redundant stores deleted");
102STATISTIC(NumFastOther,
"Number of other instrs removed");
103STATISTIC(NumCompletePartials,
"Number of stores dead by later partials");
104STATISTIC(NumModifiedStores,
"Number of stores modified");
109 "Number of times a valid candidate is returned from getDomMemoryDef");
111 "Number iterations check for reads in getDomMemoryDef");
114 "Controls which MemoryDefs are eliminated.");
130 switch (
II->getIntrinsicID()) {
131 default:
return false;
132 case Intrinsic::memset:
133 case Intrinsic::memcpy:
134 case Intrinsic::memcpy_element_unordered_atomic:
135 case Intrinsic::memset_element_unordered_atomic:
170enum OverwriteResult {
174 OW_PartialEarlierWithFullLater,
190 if (KillingII ==
nullptr || DeadII ==
nullptr)
192 if (KillingII->getIntrinsicID() != DeadII->getIntrinsicID())
195 switch (KillingII->getIntrinsicID()) {
196 case Intrinsic::masked_store:
197 case Intrinsic::vp_store: {
199 auto *KillingTy = KillingII->getArgOperand(0)->getType();
200 auto *DeadTy = DeadII->getArgOperand(0)->getType();
201 if (
DL.getTypeSizeInBits(KillingTy) !=
DL.getTypeSizeInBits(DeadTy))
208 Value *KillingPtr = KillingII->getArgOperand(1);
209 Value *DeadPtr = DeadII->getArgOperand(1);
210 if (KillingPtr != DeadPtr && !
AA.isMustAlias(KillingPtr, DeadPtr))
212 if (KillingII->getIntrinsicID() == Intrinsic::masked_store) {
215 if (KillingII->getArgOperand(2) != DeadII->getArgOperand(2))
217 }
else if (KillingII->getIntrinsicID() == Intrinsic::vp_store) {
220 if (KillingII->getArgOperand(2) != DeadII->getArgOperand(2))
223 if (KillingII->getArgOperand(3) != DeadII->getArgOperand(3))
246 int64_t KillingOff, int64_t DeadOff,
256 if (Opts.enable_dse_partial_overwrite_tracking &&
257 KillingOff < int64_t(DeadOff + DeadSize) &&
258 int64_t(KillingOff + KillingSize) >= DeadOff) {
261 auto &IM = IOL[DeadI];
262 LLVM_DEBUG(
dbgs() <<
"DSE: Partial overwrite: DeadLoc [" << DeadOff <<
", "
263 << int64_t(DeadOff + DeadSize) <<
") KillingLoc ["
264 << KillingOff <<
", " << int64_t(KillingOff + KillingSize)
271 int64_t KillingIntStart = KillingOff;
272 int64_t KillingIntEnd = KillingOff + KillingSize;
276 auto ILI = IM.lower_bound(KillingIntStart);
277 if (ILI != IM.end() && ILI->second <= KillingIntEnd) {
281 KillingIntStart = std::min(KillingIntStart, ILI->second);
282 KillingIntEnd = std::max(KillingIntEnd, ILI->first);
291 while (ILI != IM.end() && ILI->second <= KillingIntEnd) {
292 assert(ILI->second > KillingIntStart &&
"Unexpected interval");
293 KillingIntEnd = std::max(KillingIntEnd, ILI->first);
298 IM[KillingIntEnd] = KillingIntStart;
301 if (ILI->second <= DeadOff && ILI->first >= int64_t(DeadOff + DeadSize)) {
302 LLVM_DEBUG(
dbgs() <<
"DSE: Full overwrite from partials: DeadLoc ["
303 << DeadOff <<
", " << int64_t(DeadOff + DeadSize)
304 <<
") Composite KillingLoc [" << ILI->second <<
", "
305 << ILI->first <<
")\n");
306 ++NumCompletePartials;
313 if (Opts.enable_dse_partial_store_merging && KillingOff >= DeadOff &&
314 int64_t(DeadOff + DeadSize) > KillingOff &&
315 uint64_t(KillingOff - DeadOff) + KillingSize <= DeadSize) {
316 LLVM_DEBUG(
dbgs() <<
"DSE: Partial overwrite a dead load [" << DeadOff
317 <<
", " << int64_t(DeadOff + DeadSize)
318 <<
") by a killing store [" << KillingOff <<
", "
319 << int64_t(KillingOff + KillingSize) <<
")\n");
321 return OW_PartialEarlierWithFullLater;
333 if (!Opts.enable_dse_partial_overwrite_tracking &&
334 (KillingOff > DeadOff && KillingOff < int64_t(DeadOff + DeadSize) &&
335 int64_t(KillingOff + KillingSize) >= int64_t(DeadOff + DeadSize)))
347 if (!Opts.enable_dse_partial_overwrite_tracking &&
348 (KillingOff <= DeadOff && int64_t(KillingOff + KillingSize) > DeadOff)) {
349 assert(int64_t(KillingOff + KillingSize) < int64_t(DeadOff + DeadSize) &&
350 "Expect to be handled as OW_Complete");
370 using BlockAddressPair = std::pair<BasicBlock *, PHITransAddr>;
387 auto *MemLocPtr =
const_cast<Value *
>(MemLoc.
Ptr);
392 bool isFirstBlock =
true;
395 while (!WorkList.
empty()) {
407 assert(
B == SecondBB &&
"first block is not the store block");
409 isFirstBlock =
false;
415 for (; BI != EI; ++BI) {
417 if (
I->mayWriteToMemory() &&
I != SecondI)
423 "Should not hit the entry block because SI must be dominated by LI");
433 auto Inserted = Visited.
insert(std::make_pair(Pred, TranslatedPtr));
434 if (!Inserted.second) {
437 if (TranslatedPtr != Inserted.first->second)
442 WorkList.
push_back(std::make_pair(Pred, PredAddr));
451 bool IsOverwriteEnd) {
453 uint64_t DeadSliceSizeInBits = OldSizeInBits - NewSizeInBits;
460 uint64_t DeadSliceOffsetInBits = IsOverwriteEnd ? NewSizeInBits : 0;
461 auto SetDeadFragExpr = [](
auto *Assign,
465 uint64_t RelativeOffset = DeadFragment.OffsetInBits -
466 Assign->getExpression()
471 Assign->getExpression(), RelativeOffset, DeadFragment.SizeInBits)) {
472 Assign->setExpression(*
NewExpr);
479 DeadFragment.SizeInBits);
480 Assign->setExpression(Expr);
481 Assign->setKillLocation();
488 auto GetDeadLink = [&Ctx, &LinkToNothing]() {
491 return LinkToNothing;
497 std::optional<DIExpression::FragmentInfo> NewFragment;
499 DeadSliceSizeInBits, Assign,
506 Assign->setKillAddress();
507 Assign->setAssignId(GetDeadLink());
511 if (NewFragment->SizeInBits == 0)
515 auto *NewAssign =
static_cast<decltype(Assign)
>(Assign->clone());
516 NewAssign->insertAfter(Assign->getIterator());
517 NewAssign->setAssignId(GetDeadLink());
519 SetDeadFragExpr(NewAssign, *NewFragment);
520 NewAssign->setKillAddress();
534 for (
auto &Attr : OldAttrs) {
535 if (Attr.hasKindAsEnum()) {
536 switch (Attr.getKindAsEnum()) {
539 case Attribute::Alignment:
541 if (
isAligned(Attr.getAlignment().valueOrOne(), PtrOffset))
544 case Attribute::Dereferenceable:
545 case Attribute::DereferenceableOrNull:
549 case Attribute::NonNull:
550 case Attribute::NoUndef:
558 Intrinsic->removeParamAttrs(ArgNo, AttrsToRemove);
562 uint64_t &DeadSize, int64_t KillingStart,
563 uint64_t KillingSize,
bool IsOverwriteEnd) {
565 Align PrefAlign = DeadIntrinsic->getDestAlign().valueOrOne();
581 int64_t ToRemoveStart = 0;
585 if (IsOverwriteEnd) {
590 ToRemoveStart = KillingStart +
Off;
591 if (DeadSize <=
uint64_t(ToRemoveStart - DeadStart))
593 ToRemoveSize = DeadSize -
uint64_t(ToRemoveStart - DeadStart);
595 ToRemoveStart = DeadStart;
597 "Not overlapping accesses?");
598 ToRemoveSize = KillingSize -
uint64_t(DeadStart - KillingStart);
603 if (ToRemoveSize <= (PrefAlign.
value() -
Off))
605 ToRemoveSize -= PrefAlign.
value() -
Off;
608 "Should preserve selected alignment");
611 assert(ToRemoveSize > 0 &&
"Shouldn't reach here if nothing to remove");
612 assert(DeadSize > ToRemoveSize &&
"Can't remove more than original size");
614 uint64_t NewSize = DeadSize - ToRemoveSize;
615 if (DeadIntrinsic->isAtomic()) {
618 const uint32_t ElementSize = DeadIntrinsic->getElementSizeInBytes();
619 if (0 != NewSize % ElementSize)
624 << (IsOverwriteEnd ?
"END" :
"BEGIN") <<
": " << *DeadI
625 <<
"\n KILLER [" << ToRemoveStart <<
", "
626 << int64_t(ToRemoveStart + ToRemoveSize) <<
")\n");
628 DeadIntrinsic->setLength(NewSize);
629 DeadIntrinsic->setDestAlignment(PrefAlign);
631 Value *OrigDest = DeadIntrinsic->getRawDest();
632 if (!IsOverwriteEnd) {
633 Value *Indices[1] = {
634 ConstantInt::get(DeadIntrinsic->getLength()->getType(), ToRemoveSize)};
638 NewDestGEP->
setDebugLoc(DeadIntrinsic->getDebugLoc());
639 DeadIntrinsic->setDest(NewDestGEP);
648 DeadStart += ToRemoveSize;
655 int64_t &DeadStart,
uint64_t &DeadSize) {
660 int64_t KillingStart = OII->second;
661 uint64_t KillingSize = OII->first - KillingStart;
663 assert(OII->first - KillingStart >= 0 &&
"Size expected to be positive");
665 if (KillingStart > DeadStart &&
668 (
uint64_t)(KillingStart - DeadStart) < DeadSize &&
671 KillingSize >= DeadSize - (
uint64_t)(KillingStart - DeadStart)) {
672 if (
tryToShorten(DeadI, DeadStart, DeadSize, KillingStart, KillingSize,
683 int64_t &DeadStart,
uint64_t &DeadSize) {
688 int64_t KillingStart = OII->second;
689 uint64_t KillingSize = OII->first - KillingStart;
691 assert(OII->first - KillingStart >= 0 &&
"Size expected to be positive");
693 if (KillingStart <= DeadStart &&
696 KillingSize > (
uint64_t)(DeadStart - KillingStart)) {
699 assert(KillingSize - (
uint64_t)(DeadStart - KillingStart) < DeadSize &&
700 "Should have been handled as OW_Complete");
701 if (
tryToShorten(DeadI, DeadStart, DeadSize, KillingStart, KillingSize,
712 int64_t KillingOffset, int64_t DeadOffset,
756 unsigned BitOffsetDiff = (KillingOffset - DeadOffset) * 8;
757 unsigned LShiftAmount =
758 DL.isBigEndian() ? DeadValue.
getBitWidth() - BitOffsetDiff - KillingBits
761 LShiftAmount + KillingBits);
764 APInt Merged = (DeadValue & ~Mask) | (KillingValue << LShiftAmount);
766 <<
"\n Killing: " << *KillingI
767 <<
"\n Merged Value: " << Merged <<
'\n');
774 switch (
II->getIntrinsicID()) {
775 case Intrinsic::lifetime_start:
776 case Intrinsic::lifetime_end:
777 case Intrinsic::invariant_end:
778 case Intrinsic::launder_invariant_group:
779 case Intrinsic::assume:
794 if (CB->onlyAccessesInaccessibleMemory())
799 if (DI->
mayThrow() && !DefVisibleToCaller)
821struct MemoryLocationWrapper {
822 MemoryLocationWrapper(MemoryLocation MemLoc, MemoryDef *MemDef,
823 bool DefByInitializesAttr)
824 : MemLoc(MemLoc), MemDef(MemDef),
825 DefByInitializesAttr(DefByInitializesAttr) {
826 assert(MemLoc.Ptr &&
"MemLoc should be not null");
828 DefInst = MemDef->getMemoryInst();
831 MemoryLocation MemLoc;
832 const Value *UnderlyingObject;
835 bool DefByInitializesAttr =
false;
840struct MemoryDefWrapper {
841 MemoryDefWrapper(MemoryDef *MemDef,
842 ArrayRef<std::pair<MemoryLocation, bool>> MemLocations) {
844 for (
auto &[MemLoc, DefByInitializesAttr] : MemLocations)
845 DefinedLocations.push_back(
846 MemoryLocationWrapper(MemLoc, MemDef, DefByInitializesAttr));
852struct ArgumentInitInfo {
854 bool IsDeadOrInvisibleOnUnwind;
855 ConstantRangeList Inits;
870 bool CallHasNoUnwindAttr) {
876 for (
const auto &Arg : Args) {
877 if (!CallHasNoUnwindAttr && !Arg.IsDeadOrInvisibleOnUnwind)
879 if (Arg.Inits.empty())
884 for (
auto &Arg : Args.drop_front())
885 IntersectedIntervals = IntersectedIntervals.
intersectWith(Arg.Inits);
887 return IntersectedIntervals;
893 const ScalarOptions &Opts;
896 EarliestEscapeAnalysis EA;
905 BatchAAResults BatchAA;
909 PostDominatorTree &PDT;
910 const TargetLibraryInfo &TLI;
911 const DataLayout &DL;
917 SmallPtrSet<MemoryAccess *, 4> SkipStores;
919 DenseMap<const Value *, bool> CapturedBeforeReturn;
922 DenseMap<const Value *, bool> InvisibleToCallerAfterRet;
923 DenseMap<const Value *, uint64_t> InvisibleToCallerAfterRetBounded;
925 SmallPtrSet<BasicBlock *, 16> ThrowingBlocks;
928 DenseMap<BasicBlock *, unsigned> PostOrderNumbers;
932 MapVector<BasicBlock *, InstOverlapIntervalsTy> IOLs;
936 bool AnyUnreachableExit;
941 bool ShouldIterateEndOfFunctionDSE;
944 SmallVector<Instruction *> ToRemove;
948 MemorySSA &MSSA, DominatorTree &DT, PostDominatorTree &PDT,
949 const TargetLibraryInfo &TLI,
const CycleInfo &CI);
950 DSEState(
const DSEState &) =
delete;
951 DSEState &operator=(
const DSEState &) =
delete;
953 LocationSize strengthenLocationSize(
const Instruction *
I,
954 LocationSize
Size)
const;
964 OverwriteResult isOverwrite(
const Instruction *KillingI,
965 const Instruction *DeadI,
966 const MemoryLocation &KillingLoc,
967 const MemoryLocation &DeadLoc,
968 int64_t &KillingOff, int64_t &DeadOff);
970 bool isInvisibleToCallerAfterRet(
const Value *V,
const Value *Ptr,
971 const LocationSize StoreSize);
973 bool isInvisibleToCallerOnUnwind(
const Value *V);
975 std::optional<MemoryLocation> getLocForWrite(Instruction *
I)
const;
980 getLocForInst(Instruction *
I,
bool ConsiderInitializesAttr);
984 bool isRemovable(Instruction *
I);
988 bool isCompleteOverwrite(
const MemoryLocation &DefLoc, Instruction *DefInst,
989 Instruction *UseInst);
992 bool isWriteAtEndOfFunction(MemoryDef *Def,
const MemoryLocation &DefLoc);
997 std::optional<std::pair<MemoryLocation, bool>>
998 getLocForTerminator(Instruction *
I)
const;
1002 bool isMemTerminatorInst(Instruction *
I)
const;
1006 bool isMemTerminator(
const MemoryLocation &Loc, Instruction *AccessI,
1007 Instruction *MaybeTerm);
1010 bool isReadClobber(
const MemoryLocation &DefLoc, Instruction *UseInst);
1017 bool isGuaranteedLoopIndependent(
const Instruction *Current,
1018 const Instruction *KillingDef,
1019 const MemoryLocation &CurrentLoc);
1024 bool isGuaranteedLoopInvariant(
const Value *Ptr);
1032 std::optional<MemoryAccess *>
1033 getDomMemoryDef(MemoryDef *KillingDef, MemoryAccess *StartAccess,
1034 const MemoryLocation &KillingLoc,
const Value *KillingUndObj,
1035 unsigned &ScanLimit,
unsigned &WalkerStepLimit,
1036 bool IsMemTerm,
unsigned &PartialLimit,
1037 bool IsInitializesAttrMemLoc);
1043 SmallPtrSetImpl<MemoryAccess *> *
Deleted =
nullptr);
1049 bool mayThrowBetween(Instruction *KillingI, Instruction *DeadI,
1050 const Value *KillingUndObj);
1057 bool isDSEBarrier(
const Value *KillingUndObj, Instruction *DeadI);
1061 bool eliminateDeadWritesAtEndOfFunction();
1065 bool tryFoldIntoCalloc(MemoryDef *Def,
const Value *DefUO);
1069 bool storeIsNoop(MemoryDef *Def,
const Value *DefUO);
1075 bool eliminateRedundantStoresOfExistingValues();
1080 bool eliminateRedundantStoresViaDominatingConditions();
1095 std::pair<bool, bool>
1096 eliminateDeadDefs(
const MemoryLocationWrapper &KillingLocWrapper);
1100 bool eliminateDeadDefs(
const MemoryDefWrapper &KillingDefWrapper);
1110 if (Visited.
insert(MA).second)
1127 : Opts(Opts),
F(
F),
AA(
AA), EA(DT, nullptr, &CI), BatchAA(
AA, &EA),
1128 MSSA(MSSA), DT(DT), PDT(PDT), TLI(TLI),
DL(
F.getDataLayout()), CI(CI) {
1133 PostOrderNumbers[BB] = PO++;
1136 if (
I.mayThrow() && !MA)
1137 ThrowingBlocks.insert(
I.getParent());
1140 if (MD && MemDefs.size() < Opts.dse_memoryssa_defs_per_block_limit &&
1141 (getLocForWrite(&
I) || isMemTerminatorInst(&
I) ||
1142 (Opts.enable_dse_initializes_attr_improvement &&
1144 MemDefs.push_back(MD);
1151 if (AI.hasPassPointeeByValueCopyAttr()) {
1152 InvisibleToCallerAfterRet.insert({&AI, true});
1156 if (!AI.getType()->isPointerTy())
1160 if (Info.coversAllReachableMemory())
1161 InvisibleToCallerAfterRet.insert({&AI, true});
1162 else if (
uint64_t DeadBytes = Info.getNumberOfDeadBytes())
1163 InvisibleToCallerAfterRetBounded.insert({&AI, DeadBytes});
1167 return isa<UnreachableInst>(E->getTerminator());
1175 if (TLI.
has(
F) && (
F == LibFunc_memset_chk ||
F == LibFunc_memcpy_chk)) {
1191OverwriteResult DSEState::isOverwrite(
const Instruction *KillingI,
1192 const Instruction *DeadI,
1193 const MemoryLocation &KillingLoc,
1194 const MemoryLocation &DeadLoc,
1195 int64_t &KillingOff, int64_t &DeadOff) {
1199 if (!isGuaranteedLoopIndependent(DeadI, KillingI, DeadLoc))
1202 LocationSize KillingLocSize =
1203 strengthenLocationSize(KillingI, KillingLoc.
Size);
1211 if (DeadUndObj == KillingUndObj && KillingLocSize.
isPrecise() &&
1213 std::optional<TypeSize> KillingUndObjSize =
1215 if (KillingUndObjSize && *KillingUndObjSize == KillingLocSize.
getValue())
1226 if (KillingMemI && DeadMemI) {
1227 const Value *KillingV = KillingMemI->getLength();
1228 const Value *DeadV = DeadMemI->getLength();
1229 if (KillingV == DeadV && BatchAA.
isMustAlias(DeadLoc, KillingLoc))
1238 const TypeSize KillingSize = KillingLocSize.
getValue();
1247 auto CheckAA = [&]() {
1249 AliasResult AAR = BatchAA.
alias(KillingLoc, DeadLoc);
1255 if (KillingSize >= DeadSize)
1278 if (DeadUndObj != KillingUndObj)
1282 unsigned IdxWidth =
DL.getIndexTypeSizeInBits(DeadPtr->
getType());
1283 if (IdxWidth !=
DL.getIndexTypeSizeInBits(KillingPtr->
getType()))
1291 APInt DeadBaseOff(IdxWidth, 0);
1292 APInt KillingBaseOff(IdxWidth, 0);
1294 DL, DeadBaseOff,
true);
1296 DL, KillingBaseOff,
true);
1300 if (DeadBasePtr != KillingBasePtr)
1316 if (KillingSize == 0)
1320 APInt Delta = DeadBaseOff - KillingBaseOff;
1321 if (Delta.
ult(KillingSize)) {
1328 return OW_MaybePartial;
1332 if ((-Delta).ult(DeadSize)) {
1333 KillingOff = (-Delta).getZExtValue();
1334 return OW_MaybePartial;
1341bool DSEState::isInvisibleToCallerAfterRet(
const Value *V,
const Value *Ptr,
1342 const LocationSize StoreSize) {
1346 auto IBounded = InvisibleToCallerAfterRetBounded.find(V);
1347 if (IBounded != InvisibleToCallerAfterRetBounded.end()) {
1348 int64_t ValueOffset;
1349 [[maybe_unused]]
const Value *BaseValue =
1359 ValueOffset + StoreSize.
getValue() <= IBounded->second &&
1363 auto I = InvisibleToCallerAfterRet.insert({
V,
false});
1364 if (
I.second && isInvisibleToCallerOnUnwind(V) &&
isNoAliasCall(V))
1367 return I.first->second;
1370bool DSEState::isInvisibleToCallerOnUnwind(
const Value *V) {
1371 bool RequiresNoCaptureBeforeUnwind;
1374 if (!RequiresNoCaptureBeforeUnwind)
1377 auto I = CapturedBeforeReturn.insert({
V,
true});
1385 return !
I.first->second;
1388std::optional<MemoryLocation> DSEState::getLocForWrite(Instruction *
I)
const {
1389 if (!
I->mayWriteToMemory())
1390 return std::nullopt;
1399DSEState::getLocForInst(Instruction *
I,
bool ConsiderInitializesAttr) {
1401 if (isMemTerminatorInst(
I)) {
1402 if (
auto Loc = getLocForTerminator(
I))
1403 Locations.push_back(std::make_pair(Loc->first,
false));
1407 if (
auto Loc = getLocForWrite(
I))
1408 Locations.push_back(std::make_pair(*Loc,
false));
1410 if (ConsiderInitializesAttr) {
1411 for (
auto &MemLoc : getInitializesArgMemLoc(
I)) {
1412 Locations.push_back(std::make_pair(MemLoc,
true));
1418bool DSEState::isRemovable(Instruction *
I) {
1419 assert(getLocForWrite(
I) &&
"Must have analyzable write");
1423 return SI->isUnordered();
1428 return !
MI->isVolatile();
1432 if (CB->isLifetimeStartOrEnd())
1435 return CB->use_empty() && CB->willReturn() && CB->doesNotThrow() &&
1436 !CB->isTerminator();
1442bool DSEState::isCompleteOverwrite(
const MemoryLocation &DefLoc,
1443 Instruction *DefInst, Instruction *UseInst) {
1451 if (CB->onlyAccessesInaccessibleMemory())
1454 int64_t InstWriteOffset, DepWriteOffset;
1455 if (
auto CC = getLocForWrite(UseInst))
1456 return isOverwrite(UseInst, DefInst, *
CC, DefLoc, InstWriteOffset,
1457 DepWriteOffset) == OW_Complete;
1461bool DSEState::isWriteAtEndOfFunction(MemoryDef *Def,
1462 const MemoryLocation &DefLoc) {
1464 << *
Def->getMemoryInst()
1465 <<
") is at the end the function \n");
1467 SmallPtrSet<MemoryAccess *, 8> Visited;
1470 for (
unsigned I = 0;
I < WorkList.
size();
I++) {
1471 if (WorkList.
size() >= Opts.dse_memoryssa_scanlimit) {
1476 MemoryAccess *UseAccess = WorkList[
I];
1481 if (!isGuaranteedLoopInvariant(DefLoc.
Ptr))
1490 if (isReadClobber(DefLoc, UseInst)) {
1491 LLVM_DEBUG(
dbgs() <<
" ... hit read clobber " << *UseInst <<
".\n");
1501std::optional<std::pair<MemoryLocation, bool>>
1502DSEState::getLocForTerminator(Instruction *
I)
const {
1504 if (CB->getIntrinsicID() == Intrinsic::lifetime_end)
1511 return std::nullopt;
1514bool DSEState::isMemTerminatorInst(Instruction *
I)
const {
1516 return CB && (CB->getIntrinsicID() == Intrinsic::lifetime_end ||
1520bool DSEState::isMemTerminator(
const MemoryLocation &Loc, Instruction *AccessI,
1521 Instruction *MaybeTerm) {
1522 std::optional<std::pair<MemoryLocation, bool>> MaybeTermLoc =
1523 getLocForTerminator(MaybeTerm);
1534 auto TermLoc = MaybeTermLoc->first;
1535 if (MaybeTermLoc->second) {
1539 int64_t InstWriteOffset = 0;
1540 int64_t DepWriteOffset = 0;
1541 return isOverwrite(MaybeTerm, AccessI, TermLoc, Loc, InstWriteOffset,
1542 DepWriteOffset) == OW_Complete;
1545bool DSEState::isReadClobber(
const MemoryLocation &DefLoc,
1546 Instruction *UseInst) {
1559 if (CB->onlyAccessesInaccessibleMemory())
1565bool DSEState::isGuaranteedLoopIndependent(
const Instruction *Current,
1566 const Instruction *KillingDef,
1567 const MemoryLocation &CurrentLoc) {
1578 return isGuaranteedLoopInvariant(CurrentLoc.
Ptr);
1581bool DSEState::isGuaranteedLoopInvariant(
const Value *Ptr) {
1584 if (
GEP->hasAllConstantIndices())
1588 return I->getParent()->isEntryBlock() || !CI.
getCycle(
I->getParent());
1593std::optional<MemoryAccess *> DSEState::getDomMemoryDef(
1594 MemoryDef *KillingDef, MemoryAccess *StartAccess,
1595 const MemoryLocation &KillingLoc,
const Value *KillingUndObj,
1596 unsigned &ScanLimit,
unsigned &WalkerStepLimit,
bool IsMemTerm,
1597 unsigned &PartialLimit,
bool IsInitializesAttrMemLoc) {
1598 if (ScanLimit == 0 || WalkerStepLimit == 0) {
1600 return std::nullopt;
1603 MemoryAccess *Current = StartAccess;
1612 bool CanOptimize = Opts.dse_optimize_memoryssa &&
1617 std::optional<MemoryLocation> CurrentLoc;
1620 dbgs() <<
" visiting " << *Current;
1633 return std::nullopt;
1639 ? Opts.dse_memoryssa_samebb_cost
1640 : Opts.dse_memoryssa_otherbb_cost;
1641 if (WalkerStepLimit <= StepCost) {
1643 return std::nullopt;
1645 WalkerStepLimit -= StepCost;
1659 if (
canSkipDef(CurrentDef, !isInvisibleToCallerOnUnwind(KillingUndObj))) {
1660 CanOptimize =
false;
1666 if (mayThrowBetween(KillingI, CurrentI, KillingUndObj)) {
1668 return std::nullopt;
1673 if (isDSEBarrier(KillingUndObj, CurrentI)) {
1675 return std::nullopt;
1683 return std::nullopt;
1686 if (
any_of(Current->
uses(), [
this, &KillingLoc, StartAccess](Use &U) {
1687 if (auto *UseOrDef = dyn_cast<MemoryUseOrDef>(U.getUser()))
1688 return !MSSA.dominates(StartAccess, UseOrDef) &&
1689 isReadClobber(KillingLoc, UseOrDef->getMemoryInst());
1693 return std::nullopt;
1698 CurrentLoc = getLocForWrite(CurrentI);
1699 if (!CurrentLoc || !isRemovable(CurrentI)) {
1700 CanOptimize =
false;
1707 if (!isGuaranteedLoopIndependent(CurrentI, KillingI, *CurrentLoc)) {
1709 CanOptimize =
false;
1717 if (!isMemTerminator(*CurrentLoc, CurrentI, KillingI)) {
1718 CanOptimize =
false;
1722 int64_t KillingOffset = 0;
1723 int64_t DeadOffset = 0;
1724 auto OR = isOverwrite(KillingI, CurrentI, KillingLoc, *CurrentLoc,
1725 KillingOffset, DeadOffset);
1731 (OR == OW_Complete || OR == OW_MaybePartial))
1737 CanOptimize =
false;
1742 if (OR == OW_Unknown || OR == OW_None)
1744 else if (OR == OW_MaybePartial) {
1749 if (PartialLimit <= 1) {
1750 WalkerStepLimit -= 1;
1751 LLVM_DEBUG(
dbgs() <<
" ... reached partial limit ... continue with "
1765 SmallPtrSet<Instruction *, 16> KillingDefs;
1767 MemoryAccess *MaybeDeadAccess = Current;
1768 MemoryLocation MaybeDeadLoc = *CurrentLoc;
1770 LLVM_DEBUG(
dbgs() <<
" Checking for reads of " << *MaybeDeadAccess <<
" ("
1771 << *MaybeDeadI <<
")\n");
1774 SmallPtrSet<MemoryAccess *, 32> Visited;
1778 for (
unsigned I = 0;
I < WorkList.
size();
I++) {
1779 MemoryAccess *UseAccess = WorkList[
I];
1783 if (ScanLimit < (WorkList.
size() -
I)) {
1785 return std::nullopt;
1788 NumDomMemDefChecks++;
1791 if (
any_of(KillingDefs, [
this, UseAccess](Instruction *KI) {
1794 LLVM_DEBUG(
dbgs() <<
" ... skipping, dominated by killing block\n");
1805 if (
any_of(KillingDefs, [
this, UseInst](Instruction *KI) {
1808 LLVM_DEBUG(
dbgs() <<
" ... skipping, dominated by killing def\n");
1814 if (isMemTerminator(MaybeDeadLoc, MaybeDeadI, UseInst)) {
1817 <<
" ... skipping, memterminator invalidates following accesses\n");
1827 if (UseInst->
mayThrow() && !isInvisibleToCallerOnUnwind(KillingUndObj)) {
1829 return std::nullopt;
1836 bool IsKillingDefFromInitAttr =
false;
1837 if (IsInitializesAttrMemLoc) {
1838 if (KillingI == UseInst &&
1840 IsKillingDefFromInitAttr =
true;
1843 if (isReadClobber(MaybeDeadLoc, UseInst) && !IsKillingDefFromInitAttr) {
1845 return std::nullopt;
1851 if (MaybeDeadAccess == UseAccess &&
1852 !isGuaranteedLoopInvariant(MaybeDeadLoc.
Ptr)) {
1853 LLVM_DEBUG(
dbgs() <<
" ... found not loop invariant self access\n");
1854 return std::nullopt;
1860 if (KillingDef == UseAccess || MaybeDeadAccess == UseAccess) {
1876 if (isCompleteOverwrite(MaybeDeadLoc, MaybeDeadI, UseInst)) {
1878 if (PostOrderNumbers.
find(MaybeKillingBlock)->second <
1879 PostOrderNumbers.
find(MaybeDeadAccess->
getBlock())->second) {
1880 if (!isInvisibleToCallerAfterRet(KillingUndObj, KillingLoc.
Ptr,
1883 <<
" ... found killing def " << *UseInst <<
"\n");
1884 KillingDefs.
insert(UseInst);
1888 <<
" ... found preceeding def " << *UseInst <<
"\n");
1889 return std::nullopt;
1899 if (!isInvisibleToCallerAfterRet(KillingUndObj, KillingLoc.
Ptr,
1901 SmallPtrSet<BasicBlock *, 16> KillingBlocks;
1902 for (Instruction *KD : KillingDefs)
1903 KillingBlocks.
insert(KD->getParent());
1905 "Expected at least a single killing block");
1919 if (!AnyUnreachableExit)
1920 return std::nullopt;
1924 CommonPred =
nullptr;
1928 if (KillingBlocks.
count(CommonPred))
1929 return {MaybeDeadAccess};
1931 SetVector<BasicBlock *> WorkList;
1935 WorkList.
insert(CommonPred);
1937 for (BasicBlock *R : PDT.
roots()) {
1945 for (
unsigned I = 0;
I < WorkList.
size();
I++) {
1948 if (KillingBlocks.
count(Current))
1950 if (Current == MaybeDeadAccess->
getBlock())
1951 return std::nullopt;
1960 if (WorkList.
size() >= Opts.dse_memoryssa_path_check_limit)
1961 return std::nullopt;
1968 return {MaybeDeadAccess};
1971void DSEState::deleteDeadInstruction(Instruction *SI,
1972 SmallPtrSetImpl<MemoryAccess *> *
Deleted) {
1973 MemorySSAUpdater Updater(&MSSA);
1978 while (!NowDeadInsts.
empty()) {
1992 SkipStores.insert(MD);
1996 if (
SI->getValueOperand()->getType()->isPointerTy()) {
1998 if (CapturedBeforeReturn.erase(UO))
1999 ShouldIterateEndOfFunctionDSE =
true;
2000 InvisibleToCallerAfterRet.erase(UO);
2001 InvisibleToCallerAfterRetBounded.erase(UO);
2006 Updater.removeMemoryAccess(MA);
2010 if (
I != IOLs.end())
2011 I->second.erase(DeadInst);
2013 for (Use &O : DeadInst->
operands())
2033bool DSEState::mayThrowBetween(Instruction *KillingI, Instruction *DeadI,
2034 const Value *KillingUndObj) {
2038 if (KillingUndObj && isInvisibleToCallerOnUnwind(KillingUndObj))
2042 return ThrowingBlocks.count(KillingI->
getParent());
2043 return !ThrowingBlocks.empty();
2046bool DSEState::isDSEBarrier(
const Value *KillingUndObj, Instruction *DeadI) {
2049 if (DeadI->
mayThrow() && !isInvisibleToCallerOnUnwind(KillingUndObj))
2069bool DSEState::eliminateDeadWritesAtEndOfFunction() {
2070 bool MadeChange =
false;
2072 dbgs() <<
"Trying to eliminate MemoryDefs at the end of the function\n");
2074 ShouldIterateEndOfFunctionDSE =
false;
2076 if (SkipStores.contains(Def))
2080 auto DefLoc = getLocForWrite(DefI);
2081 if (!DefLoc || !isRemovable(DefI)) {
2083 "instruction not removable.\n");
2093 if (!isInvisibleToCallerAfterRet(UO, DefLoc->
Ptr, DefLoc->
Size))
2096 if (isWriteAtEndOfFunction(Def, *DefLoc)) {
2098 LLVM_DEBUG(
dbgs() <<
" ... MemoryDef is not accessed until the end "
2099 "of the function\n");
2105 }
while (ShouldIterateEndOfFunctionDSE);
2109bool DSEState::eliminateRedundantStoresViaDominatingConditions() {
2110 bool MadeChange =
false;
2111 LLVM_DEBUG(
dbgs() <<
"Trying to eliminate MemoryDefs whose value being "
2112 "written is implied by a dominating condition\n");
2114 using ConditionInfo = std::pair<Value *, Value *>;
2115 using ScopedHTType = ScopedHashTable<ConditionInfo, Instruction *>;
2119 ScopedHTType ActiveConditions;
2120 auto GetDominatingCondition = [&](
BasicBlock *BB)
2121 -> std::optional<std::tuple<ConditionInfo, Instruction *, BasicBlock *>> {
2124 return std::nullopt;
2129 if (BI->getSuccessor(0) == BI->getSuccessor(1))
2130 return std::nullopt;
2134 Value *StorePtr, *StoreVal;
2135 if (!
match(BI->getCondition(),
2139 return std::nullopt;
2145 return std::nullopt;
2147 unsigned ImpliedSuccIdx = Pred == ICmpInst::ICMP_EQ ? 0 : 1;
2148 BasicBlock *ImpliedSucc = BI->getSuccessor(ImpliedSuccIdx);
2149 return {{ConditionInfo(StorePtr, StoreVal), ICmpL, ImpliedSucc}};
2153 if (
Depth > Opts.dse_max_dom_cond_depth)
2159 for (MemoryDef &Def :
2162 if (!SI || !
SI->isUnordered())
2166 {
SI->getPointerOperand(),
SI->getValueOperand()});
2174 MemoryAccess *ClobberingAccess =
2176 if (MSSA.
dominates(ClobberingAccess, LoadAccess)) {
2178 <<
"Removing No-Op Store:\n DEAD: " << *SI <<
'\n');
2180 NumRedundantStores++;
2187 auto MaybeCondition = GetDominatingCondition(BB);
2191 ScopedHTType::ScopeTy
Scope(ActiveConditions);
2192 if (MaybeCondition) {
2193 const auto &[
Cond, LI, ImpliedSucc] = *MaybeCondition;
2194 if (DT.
dominates(BasicBlockEdge(BB, ImpliedSucc), Child->getBlock())) {
2198 ActiveConditions.insert(
Cond, LI);
2205 Self(Child,
Depth + 1, Self);
2215bool DSEState::tryFoldIntoCalloc(MemoryDef *Def,
const Value *DefUO) {
2222 if (!StoredConstant || !StoredConstant->
isNullValue())
2225 if (!isRemovable(DefI))
2229 if (
F.hasFnAttribute(Attribute::SanitizeMemory) ||
2230 F.hasFnAttribute(Attribute::SanitizeAddress) ||
2231 F.hasFnAttribute(Attribute::SanitizeHWAddress) ||
F.getName() ==
"calloc")
2236 auto *InnerCallee =
Malloc->getCalledFunction();
2240 StringRef ZeroedVariantName;
2241 if (Func != LibFunc_malloc || !TLI.
has(Func)) {
2246 if (ZeroedVariantName.
empty())
2255 auto shouldCreateCalloc = [](CallInst *
Malloc, CallInst *Memset) {
2258 auto *MallocBB =
Malloc->getParent(), *MemsetBB = Memset->getParent();
2259 if (MallocBB == MemsetBB)
2261 auto *Ptr = Memset->getArgOperand(0);
2262 auto *TI = MallocBB->getTerminator();
2268 if (MemsetBB != FalseBB)
2279 assert(Func == LibFunc_malloc || !ZeroedVariantName.
empty());
2280 Value *Calloc =
nullptr;
2281 if (!ZeroedVariantName.
empty()) {
2282 LLVMContext &Ctx =
Malloc->getContext();
2283 AttributeList
Attrs = InnerCallee->getAttributes();
2285 Attrs.getFnAttr(Attribute::AllocKind).getAllocKind() |
2286 AllocFnKind::Zeroed;
2289 Attrs.addFnAttribute(Ctx, Attribute::getWithAllocKind(Ctx, AllocKind))
2290 .removeFnAttribute(Ctx,
"alloc-variant-zeroed");
2291 FunctionCallee ZeroedVariant =
Malloc->getModule()->getOrInsertFunction(
2292 ZeroedVariantName, InnerCallee->getFunctionType(), Attrs);
2294 ->setCallingConv(
Malloc->getCallingConv());
2297 CallInst *CI = IRB.CreateCall(ZeroedVariant, Args, ZeroedVariantName);
2301 Type *SizeTTy =
Malloc->getArgOperand(0)->getType();
2302 Calloc =
emitCalloc(ConstantInt::get(SizeTTy, 1),
Malloc->getArgOperand(0),
2303 IRB, TLI,
Malloc->getType()->getPointerAddressSpace());
2308 if (MDNode *MD =
Malloc->getMetadata(LLVMContext::MD_alloc_token))
2311 MemorySSAUpdater Updater(&MSSA);
2313 nullptr, MallocDef);
2315 Updater.insertDef(NewAccessMD,
true);
2316 Malloc->replaceAllUsesWith(Calloc);
2321bool DSEState::storeIsNoop(MemoryDef *Def,
const Value *DefUO) {
2325 Constant *StoredConstant =
nullptr;
2333 if (!isRemovable(DefI))
2336 if (StoredConstant) {
2341 if (InitC && InitC == StoredConstant)
2350 if (LoadI->getPointerOperand() ==
Store->getOperand(1)) {
2354 if (LoadAccess ==
Def->getDefiningAccess())
2360 SetVector<MemoryAccess *> ToCheck;
2361 MemoryAccess *Current =
2369 for (
unsigned I = 1;
I < ToCheck.
size(); ++
I) {
2370 Current = ToCheck[
I];
2373 for (
auto &Use : PhiAccess->incoming_values())
2385 if (LoadAccess != Current)
2397 for (
auto OI : IOL) {
2399 MemoryLocation Loc = *getLocForWrite(DeadI);
2400 assert(isRemovable(DeadI) &&
"Expect only removable instruction");
2403 int64_t DeadStart = 0;
2407 if (IntervalMap.empty())
2414bool DSEState::eliminateRedundantStoresOfExistingValues() {
2415 bool MadeChange =
false;
2416 LLVM_DEBUG(
dbgs() <<
"Trying to eliminate MemoryDefs that write the "
2417 "already existing value\n");
2418 for (
auto *Def : MemDefs) {
2423 auto MaybeDefLoc = getLocForWrite(DefInst);
2424 if (!MaybeDefLoc || !isRemovable(DefInst))
2427 MemoryDef *UpperDef;
2431 if (
Def->isOptimized())
2439 auto IsRedundantStore = [&]() {
2447 auto UpperLoc = getLocForWrite(UpperInst);
2450 int64_t InstWriteOffset = 0;
2451 int64_t DepWriteOffset = 0;
2452 auto OR = isOverwrite(UpperInst, DefInst, *UpperLoc, *MaybeDefLoc,
2453 InstWriteOffset, DepWriteOffset);
2455 return StoredByte && StoredByte == MemSetI->getOperand(1) &&
2462 if (!IsRedundantStore() || isReadClobber(*MaybeDefLoc, DefInst))
2464 LLVM_DEBUG(
dbgs() <<
"DSE: Remove No-Op Store:\n DEAD: " << *DefInst
2467 NumRedundantStores++;
2474DSEState::getInitializesArgMemLoc(
const Instruction *
I) {
2480 SmallMapVector<Value *, SmallVector<ArgumentInitInfo, 2>, 2>
Arguments;
2486 ConstantRangeList Inits;
2498 Inits = ConstantRangeList();
2506 bool IsDeadOrInvisibleOnUnwind =
2509 ArgumentInitInfo InitInfo{
Idx, IsDeadOrInvisibleOnUnwind, Inits};
2510 bool FoundAliasing =
false;
2511 for (
auto &[Arg, AliasList] :
Arguments) {
2517 FoundAliasing =
true;
2518 AliasList.push_back(InitInfo);
2523 FoundAliasing =
true;
2524 AliasList.push_back(ArgumentInitInfo{
Idx, IsDeadOrInvisibleOnUnwind,
2525 ConstantRangeList()});
2534 auto IntersectedRanges =
2536 if (IntersectedRanges.empty())
2539 for (
const auto &Arg : Args) {
2540 for (
const auto &
Range : IntersectedRanges) {
2554std::pair<bool, bool>
2555DSEState::eliminateDeadDefs(
const MemoryLocationWrapper &KillingLocWrapper) {
2557 bool DeletedKillingLoc =
false;
2558 unsigned ScanLimit = Opts.dse_memoryssa_scanlimit;
2559 unsigned WalkerStepLimit = Opts.dse_memoryssa_walklimit;
2560 unsigned PartialLimit = Opts.dse_memoryssa_partial_store_limit;
2563 SmallSetVector<MemoryAccess *, 8> ToCheck;
2567 SmallPtrSet<MemoryAccess *, 8>
Deleted;
2568 [[maybe_unused]]
unsigned OrigNumSkipStores = SkipStores.size();
2573 for (
unsigned I = 0;
I < ToCheck.
size();
I++) {
2574 MemoryAccess *Current = ToCheck[
I];
2575 if (
Deleted.contains(Current))
2577 std::optional<MemoryAccess *> MaybeDeadAccess = getDomMemoryDef(
2578 KillingLocWrapper.MemDef, Current, KillingLocWrapper.MemLoc,
2579 KillingLocWrapper.UnderlyingObject, ScanLimit, WalkerStepLimit,
2580 isMemTerminatorInst(KillingLocWrapper.DefInst), PartialLimit,
2581 KillingLocWrapper.DefByInitializesAttr);
2583 if (!MaybeDeadAccess) {
2587 MemoryAccess *DeadAccess = *MaybeDeadAccess;
2588 LLVM_DEBUG(
dbgs() <<
" Checking if we can kill " << *DeadAccess);
2590 LLVM_DEBUG(
dbgs() <<
"\n ... adding incoming values to worklist\n");
2599 if (PostOrderNumbers[IncomingBlock] > PostOrderNumbers[PhiBlock])
2600 ToCheck.
insert(IncomingAccess);
2611 MemoryDefWrapper DeadDefWrapper(
2615 assert(DeadDefWrapper.DefinedLocations.size() == 1);
2616 MemoryLocationWrapper &DeadLocWrapper =
2617 DeadDefWrapper.DefinedLocations.front();
2620 NumGetDomMemoryDefPassed++;
2624 if (isMemTerminatorInst(KillingLocWrapper.DefInst)) {
2625 if (KillingLocWrapper.UnderlyingObject != DeadLocWrapper.UnderlyingObject)
2628 << *DeadLocWrapper.DefInst <<
"\n KILLER: "
2629 << *KillingLocWrapper.DefInst <<
'\n');
2635 int64_t KillingOffset = 0;
2636 int64_t DeadOffset = 0;
2637 OverwriteResult
OR =
2638 isOverwrite(KillingLocWrapper.DefInst, DeadLocWrapper.DefInst,
2639 KillingLocWrapper.MemLoc, DeadLocWrapper.MemLoc,
2640 KillingOffset, DeadOffset);
2641 if (OR == OW_MaybePartial) {
2642 auto &IOL = IOLs[DeadLocWrapper.DefInst->
getParent()];
2644 DeadLocWrapper.MemLoc, KillingOffset,
2645 DeadOffset, DeadLocWrapper.DefInst, IOL);
2647 if (Opts.enable_dse_partial_store_merging &&
2648 OR == OW_PartialEarlierWithFullLater) {
2654 if (DeadSI && KillingSI && DT.
dominates(DeadSI, KillingSI)) {
2656 KillingSI, DeadSI, KillingOffset, DeadOffset,
DL, BatchAA,
2660 DeadSI->setOperand(0, Merged);
2661 ++NumModifiedStores;
2663 DeletedKillingLoc =
true;
2668 auto I = IOLs.find(DeadSI->getParent());
2669 if (
I != IOLs.end())
2670 I->second.erase(DeadSI);
2675 if (OR == OW_Complete) {
2677 << *DeadLocWrapper.DefInst <<
"\n KILLER: "
2678 << *KillingLocWrapper.DefInst <<
'\n');
2686 assert(SkipStores.size() - OrigNumSkipStores ==
Deleted.size() &&
2687 "SkipStores and Deleted out of sync?");
2689 return {
Changed, DeletedKillingLoc};
2692bool DSEState::eliminateDeadDefs(
const MemoryDefWrapper &KillingDefWrapper) {
2693 if (KillingDefWrapper.DefinedLocations.empty()) {
2694 LLVM_DEBUG(
dbgs() <<
"Failed to find analyzable write location for "
2695 << *KillingDefWrapper.DefInst <<
"\n");
2699 bool MadeChange =
false;
2700 for (
auto &KillingLocWrapper : KillingDefWrapper.DefinedLocations) {
2702 << *KillingLocWrapper.MemDef <<
" ("
2703 << *KillingLocWrapper.DefInst <<
")\n");
2704 auto [
Changed, DeletedKillingLoc] = eliminateDeadDefs(KillingLocWrapper);
2708 if (!DeletedKillingLoc && storeIsNoop(KillingLocWrapper.MemDef,
2709 KillingLocWrapper.UnderlyingObject)) {
2711 << *KillingLocWrapper.DefInst <<
'\n');
2713 NumRedundantStores++;
2718 if (!DeletedKillingLoc &&
2719 tryFoldIntoCalloc(KillingLocWrapper.MemDef,
2720 KillingLocWrapper.UnderlyingObject)) {
2721 LLVM_DEBUG(
dbgs() <<
"DSE: Remove memset after forming calloc:\n"
2722 <<
" DEAD: " << *KillingLocWrapper.DefInst <<
'\n');
2736 bool MadeChange =
false;
2737 DSEState State(Opts,
F,
AA, MSSA, DT, PDT, TLI, CI);
2739 for (
unsigned I = 0;
I < State.MemDefs.size();
I++) {
2741 if (State.SkipStores.count(KillingDef))
2744 MemoryDefWrapper KillingDefWrapper(
2747 Opts.enable_dse_initializes_attr_improvement));
2748 MadeChange |= State.eliminateDeadDefs(KillingDefWrapper);
2751 if (Opts.enable_dse_partial_overwrite_tracking)
2752 for (
auto &KV : State.IOLs)
2753 MadeChange |= State.removePartiallyOverlappedStores(KV.second);
2755 MadeChange |= State.eliminateRedundantStoresOfExistingValues();
2756 MadeChange |= State.eliminateDeadWritesAtEndOfFunction();
2757 MadeChange |= State.eliminateRedundantStoresViaDominatingConditions();
2759 while (!State.ToRemove.empty()) {
2760 Instruction *DeadInst = State.ToRemove.pop_back_val();
2780#ifdef LLVM_ENABLE_STATS
2807 if (skipFunction(
F))
2810 AliasAnalysis &
AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
2811 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
2813 getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F);
2814 MemorySSA &MSSA = getAnalysis<MemorySSAWrapperPass>().getMSSA();
2816 getAnalysis<PostDominatorTreeWrapperPass>().getPostDomTree();
2817 CycleInfo &CI = getAnalysis<CycleInfoWrapperPass>().getResult();
2821#ifdef LLVM_ENABLE_STATS
2830 void getAnalysisUsage(AnalysisUsage &AU)
const override {
2846char DSELegacyPass::ID = 0;
2863 return new DSELegacyPass();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Lower Kernel Arguments
This file implements a class to represent arbitrary precision integral constant values and operations...
ReachingDefInfo InstSet & ToRemove
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
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 an analysis pass that computes CycleInfo for LLVM IR, specialized from GenericCycl...
DXIL Forward Handle Accesses
static void shortenAssignment(Instruction *Inst, Value *OriginalDest, uint64_t OldSizeInBits, uint64_t NewSizeInBits, bool IsOverwriteEnd)
static bool eliminateDeadStores(Function &F, AliasAnalysis &AA, MemorySSA &MSSA, DominatorTree &DT, PostDominatorTree &PDT, const TargetLibraryInfo &TLI, const CycleInfo &CI)
MapVector< Instruction *, OverlapIntervalsTy > InstOverlapIntervalsTy
static bool canSkipDef(MemoryDef *D, bool DefVisibleToCaller)
static bool isShortenableAtTheEnd(Instruction *I)
Returns true if the end of this instruction can be safely shortened in length.
static bool isNoopIntrinsic(Instruction *I)
static ConstantRangeList getIntersectedInitRangeList(ArrayRef< ArgumentInitInfo > Args, bool CallHasNoUnwindAttr)
static bool tryToShortenBegin(Instruction *DeadI, OverlapIntervalsTy &IntervalMap, int64_t &DeadStart, uint64_t &DeadSize)
std::map< int64_t, int64_t > OverlapIntervalsTy
static void pushMemUses(MemoryAccess *Acc, SmallVectorImpl< MemoryAccess * > &WorkList, SmallPtrSetImpl< MemoryAccess * > &Visited)
static bool isShortenableAtTheBeginning(Instruction *I)
Returns true if the beginning of this instruction can be safely shortened in length.
static Constant * tryToMergePartialOverlappingStores(StoreInst *KillingI, StoreInst *DeadI, int64_t KillingOffset, int64_t DeadOffset, const DataLayout &DL, BatchAAResults &AA, DominatorTree *DT)
static OverwriteResult isPartialOverwrite(const ScalarOptions &Opts, const MemoryLocation &KillingLoc, const MemoryLocation &DeadLoc, int64_t KillingOff, int64_t DeadOff, Instruction *DeadI, InstOverlapIntervalsTy &IOL)
Return 'OW_Complete' if a store to the 'KillingLoc' location completely overwrites a store to the 'De...
static bool memoryIsNotModifiedBetween(Instruction *FirstI, Instruction *SecondI, BatchAAResults &AA, const DataLayout &DL, DominatorTree *DT)
Returns true if the memory which is accessed by the second instruction is not modified between the fi...
static OverwriteResult isMaskedStoreOverwrite(const Instruction *KillingI, const Instruction *DeadI, BatchAAResults &AA)
Check if two instruction are masked stores that completely overwrite one another.
static bool tryToShorten(Instruction *DeadI, int64_t &DeadStart, uint64_t &DeadSize, int64_t KillingStart, uint64_t KillingSize, bool IsOverwriteEnd)
static bool isFuncLocalAndNotCaptured(Value *Arg, const CallBase *CB, EarliestEscapeAnalysis &EA)
static std::optional< TypeSize > getPointerSize(const Value *V, const DataLayout &DL, const TargetLibraryInfo &TLI, const Function *F)
static bool tryToShortenEnd(Instruction *DeadI, OverlapIntervalsTy &IntervalMap, int64_t &DeadStart, uint64_t &DeadSize)
static void adjustArgAttributes(AnyMemIntrinsic *Intrinsic, unsigned ArgNo, uint64_t PtrOffset)
Update the attributes given that a memory access is updated (the dereferenced pointer could be moved ...
static bool hasInitializesAttr(Instruction *I)
This file provides an implementation of debug counters.
#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC)
This file defines the DenseMap class.
early cse Early CSE w MemorySSA
static bool runOnFunction(Function &F, bool PostInlining)
This is the interface for a simple mod/ref and alias analysis over globals.
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
static void deleteDeadInstruction(Instruction *I)
This file implements a map that provides insertion order iteration.
This file provides utility analysis objects describing memory locations.
This file exposes an interface to building/using memory SSA to walk memory instructions using a use/d...
Contains a collection of routines for determining if a given instruction is guaranteed to execute if ...
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
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 builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
SmallVector< MachineOperand, 4 > Cond
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static bool VisitNode(MachineDomTreeNode *Node, Register TLSBaseAddrReg)
A manager for alias analyses.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
Class for arbitrary precision integers.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
uint64_t getZExtValue() const
Get zero extended value.
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool ult(const APInt &RHS) const
Unsigned less than comparison.
int64_t getSExtValue() const
Get sign extended value.
@ 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.
constexpr int32_t getOffset() const
constexpr bool hasOffset() const
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
This class represents an incoming formal argument to a Function.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
An immutable pass that tracks lazily created AssumptionCache objects.
This class stores enough information to efficiently remove some attributes from an existing AttrBuild...
AttributeMask & addAttribute(Attribute::AttrKind Val)
Add an attribute to the mask.
This class holds the attributes for a particular argument, parameter, function, or return value.
LLVM_ABI ArrayRef< ConstantRange > getValueAsConstantRangeList() const
Return the attribute's value as a ConstantRange array.
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
bool isValid() const
Return true if the attribute is any kind of attribute.
LLVM Basic Block Representation.
const Function * getParent() const
Return the enclosing method, or null if none.
InstListType::iterator iterator
Instruction iterators...
This class is a wrapper over an AAResults, and it is intended to be used only when there are no IR ch...
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB)
bool isMustAlias(const MemoryLocation &LocA, const MemoryLocation &LocB)
ModRefInfo getModRefInfo(const Instruction *I, const std::optional< MemoryLocation > &OptLoc)
Represents analyses that only rely on functions' control flow.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
void setCallingConv(CallingConv::ID CC)
LLVM_ABI bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const
Determine whether the argument or parameter has the given attribute.
Attribute getParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) const
Get the attribute of a given kind from a given arg.
bool isByValArgument(unsigned ArgNo) const
Determine whether this argument is passed by value.
LLVM_ABI bool onlyAccessesInaccessibleMemOrArgMem() const
Determine if the function may only access memory that is either inaccessible from the IR or pointed t...
bool doesNotThrow() const
Determine if the call cannot unwind.
Value * getArgOperand(unsigned i) const
LLVM_ABI Value * getArgOperandWithAttribute(Attribute::AttrKind Kind) const
If one of the arguments has the specified attribute, returns its operand value.
unsigned arg_size() const
This class represents a list of constant ranges.
bool empty() const
Return true if this list contains no members.
LLVM_ABI ConstantRangeList intersectWith(const ConstantRangeList &CRL) const
Return the range list that results from the intersection of this ConstantRangeList with another Const...
const APInt & getLower() const
Return the lower value for this range.
const APInt & getUpper() const
Return the upper value for this range.
This is an important base class in LLVM.
bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
Analysis pass which computes a CycleInfo.
Legacy analysis pass which computes a CycleInfo.
static DIAssignID * getDistinct(LLVMContext &Context)
DbgVariableFragmentInfo FragmentInfo
static LLVM_ABI std::optional< DIExpression * > createFragmentExpression(const DIExpression *Expr, unsigned OffsetInBits, unsigned SizeInBits)
Create a DIExpression to describe one part of an aggregate variable that is fragmented across multipl...
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
A parsed version of the target data layout string in and methods for querying it.
Record of a variable value-assignment, aka a non instruction representation of the dbg....
static bool shouldExecute(CounterInfo &Counter)
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Analysis pass which computes a DominatorTree.
DomTreeNodeBase< NodeT > * getRootNode()
getRootNode - This returns the entry node for the CFG of the function.
NodeT * findNearestCommonDominator(NodeT *A, NodeT *B) const
Find nearest common dominator basic block for basic block A and B.
iterator_range< root_iterator > roots()
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
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.
Context-sensitive CaptureAnalysis provider, which computes and caches the earliest common dominator c...
void removeInstruction(Instruction *I)
CaptureComponents getCapturesBefore(const Value *Object, const Instruction *I, bool OrAt, bool ReturnCaptures) 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.
const BasicBlock & getEntryBlock() const
CycleRef getCycle(const BlockT *Block) const
Find the innermost cycle containing Block.
static GetElementPtrInst * CreateInBounds(Type *PointeeType, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Create an "inbounds" getelementptr.
Legacy wrapper pass to provide the GlobalsAAResult object.
bool isEquality() const
Return true if this predicate is either EQ or NE.
LLVM_ABI bool mayThrow(bool IncludePhaseOneUnwind=false) const LLVM_READONLY
Return true if this instruction may throw an exception.
LLVM_ABI bool mayWriteToMemory() const LLVM_READONLY
Return true if this instruction may modify memory.
LLVM_ABI bool isAtomic() const LLVM_READONLY
Return true if this instruction has an AtomicOrdering of unordered or higher.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI bool isIdenticalToWhenDefined(const Instruction *I, bool IntersectAttrs=false) const LLVM_READONLY
This is like isIdenticalTo, except that it ignores the SubclassOptionalData flags,...
LLVM_ABI bool mayReadFromMemory() const LLVM_READONLY
Return true if this instruction may read memory.
LLVM_ABI AAMDNodes getAAMetadata() const
Returns the AA metadata for this instruction.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
const_iterator begin() const
bool empty() const
empty - Return true when no intervals are mapped.
const_iterator end() const
A wrapper class for inspecting calls to intrinsic functions.
This is an important class for using LLVM in a threaded context.
static LocationSize precise(uint64_t Value)
TypeSize getValue() const
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
This class implements a map that also provides access to all stored values in a deterministic order.
Value * getLength() const
BasicBlock * getBlock() const
Represents a read-write access to memory, whether it is a must-alias, or a may-alias.
void setOptimized(MemoryAccess *MA)
A wrapper analysis pass for the legacy pass manager that exposes a MemoryDepnedenceResults instance.
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.
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...
static MemoryLocation getAfter(const Value *Ptr, const AAMDNodes &AATags=AAMDNodes())
Return a location that may access any location after Ptr, while remaining within the underlying objec...
MemoryLocation getWithNewPtr(const Value *NewPtr) const
const Value * Ptr
The address of the start of the location.
static LLVM_ABI MemoryLocation getForDest(const MemIntrinsic *MI)
Return a location representing the destination of a memory set or transfer.
static LLVM_ABI std::optional< MemoryLocation > getOrNone(const Instruction *Inst)
static LLVM_ABI MemoryLocation getForArgument(const CallBase *Call, unsigned ArgIdx, const TargetLibraryInfo *TLI)
Return a location representing a particular argument of a call.
An analysis that produces MemorySSA for a function.
MemoryAccess * getClobberingMemoryAccess(const Instruction *I, BatchAAResults &AA)
Given a memory Mod/Ref/ModRef'ing instruction, calling this will give you the nearest dominating Memo...
Legacy analysis pass which computes MemorySSA.
Encapsulates MemorySSA, including all data associated with memory accesses.
DefsList * getBlockDefs(const BasicBlock *BB) const
Return the list of MemoryDef's and MemoryPhi's for a given basic block.
LLVM_ABI MemorySSAWalker * getSkipSelfWalker()
LLVM_ABI bool dominates(const MemoryAccess *A, const MemoryAccess *B) const
Given two memory accesses in potentially different blocks, determine whether MemoryAccess A dominates...
LLVM_ABI MemorySSAWalker * getWalker()
MemoryUseOrDef * getMemoryAccess(const Instruction *I) const
Given a memory Mod/Ref'ing instruction, get the MemorySSA access associated with it.
bool isLiveOnEntryDef(const MemoryAccess *MA) const
Return true if MA represents the live on entry value.
MemoryAccess * getDefiningAccess() const
Get the access that produces the memory state used by this Use.
Instruction * getMemoryInst() const
Get the instruction that this MemoryUse represents.
PHITransAddr - An address value which tracks and handles phi translation.
LLVM_ABI Value * translateValue(BasicBlock *CurBB, BasicBlock *PredBB, const DominatorTree *DT, bool MustDominate)
translateValue - PHI translate the current address up the CFG from CurBB to Pred, updating our state ...
LLVM_ABI bool isPotentiallyPHITranslatable() const
isPotentiallyPHITranslatable - If this needs PHI translation, return true if we have some hope of doi...
bool needsPHITranslationFromBlock(BasicBlock *BB) const
needsPHITranslationFromBlock - Return true if moving from the specified BasicBlock to its predecessor...
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Analysis pass which computes a PostDominatorTree.
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
LLVM_ABI bool dominates(const Instruction *I1, const Instruction *I2) const
Return true if I1 dominates I2.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
size_type size() const
Determine the number of elements in the SetVector.
void insert_range(Range &&R)
bool insert(const value_type &X)
Insert a new element into the SetVector.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
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.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this store instruction.
Value * getValueOperand()
constexpr bool empty() const
Check if the string is empty.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
bool has(LibFunc F) const
Tests whether a library function is available.
LibFunc getLibFunc(StringRef funcName) const
Searches for a particular function name.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
bool isPointerTy() const
True if this is an instance of PointerType.
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
bool isVoidTy() const
Return true if this is 'void'.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVMContext & getContext() const
All values hold a context through their type.
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 const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
iterator_range< use_iterator > uses()
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
const ParentTy * getParent() const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
@ BasicBlock
Various leaf nodes.
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
bool match(Val *V, const Pattern &P)
match_bind< Instruction > m_Instruction(Instruction *&I)
Match an instruction, capturing it if we match.
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
CmpClass_match< LHS, RHS, ICmpInst, true > m_c_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
Matches an ICmp with a predicate over LHS and RHS in either order.
auto m_Value()
Match an arbitrary value and ignore it.
SpecificCmpClass_match< LHS, RHS, ICmpInst > m_SpecificICmp(CmpPredicate MatchPred, const LHS &L, const RHS &R)
OneOps_match< OpTy, Instruction::Load > m_Load(const OpTy &Op)
Matches LoadInst.
is_zero< true > m_Zero()
Match any null constant or a vector with all elements equal to 0.
brc_match< Cond_t, match_bind< BasicBlock >, match_bind< BasicBlock > > m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F)
SmallVector< DbgVariableRecord * > getDVRAssignmentMarkers(const Instruction *Inst)
Return a range of dbg_assign records for which Inst performs the assignment they encode.
LLVM_ABI bool calculateFragmentIntersect(const DataLayout &DL, const Value *Dest, uint64_t SliceOffsetInBits, uint64_t SliceSizeInBits, const DbgVariableRecord *DVRAssign, std::optional< DIExpression::FragmentInfo > &Result)
Calculate the fragment of the variable in DAI covered from (Dest + SliceOffsetInBits) to to (Dest + S...
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
NodeAddr< DefNode * > Def
NodeAddr< NodeBase * > Node
NodeAddr< FuncNode * > Func
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
LLVM_ABI void initializeDSELegacyPassPass(PassRegistry &)
LLVM_ABI Constant * getInitialValueOfAllocation(const Value *V, const TargetLibraryInfo *TLI, Type *Ty)
If this is a call to an allocation function that initializes memory to a fixed value,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isStrongerThanMonotonic(AtomicOrdering AO)
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
LLVM_ABI void salvageDebugInfo(const MachineRegisterInfo &MRI, MachineInstr &MI)
Assuming the instruction MI is going to be deleted, attempt to salvage debug users of MI by writing t...
@ Store
The extracted value is stored (ExtractElement only).
Value * GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, const DataLayout &DL, bool AllowNonInbounds=true)
Analyze the specified pointer to see if it can be expressed as a base pointer plus a constant offset.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
LLVM_ABI bool isNoAliasCall(const Value *V)
Return true if this pointer is returned by a noalias function.
const ScalarOptions & getScalarOptions(const LLVMContext &C)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
DomTreeNodeBase< BasicBlock > DomTreeNode
auto make_isa_range(RangeT &&Range)
Return a range over Range containing only elements for which isa<T> holds, casting each of them to T.
auto dyn_cast_or_null(const Y &Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction is not used, and the instruction will return.
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.
auto reverse(ContainerTy &&C)
LLVM_ABI bool canReplacePointersIfEqual(const Value *From, const Value *To, const DataLayout &DL)
Returns true if a pointer value From can be replaced with another pointer value \To if they are deeme...
bool isModSet(const ModRefInfo MRI)
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.
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI bool AreStatisticsEnabled()
Check if statistics are enabled.
LLVM_ABI bool isNotVisibleOnUnwind(const Value *Object, bool &RequiresNoCaptureBeforeUnwind)
Return true if Object memory is not visible after an unwind, in the sense that program semantics cann...
LLVM_ABI Value * emitCalloc(Value *Num, Value *Size, IRBuilderBase &B, const TargetLibraryInfo &TLI, unsigned AddrSpace)
Emit a call to the calloc function.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
auto post_order(const T &G)
Post-order traversal of a graph.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
uint64_t offsetToAlignment(uint64_t Value, Align Alignment)
Returns the offset to the next integer (mod 2**64) that is greater than or equal to Value and is a mu...
LLVM_ABI bool salvageKnowledge(Instruction *I, AssumptionCache *AC=nullptr, DominatorTree *DT=nullptr)
Calls BuildAssumeFromInst and if the resulting llvm.assume is valid insert if before I.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
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...
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI Value * getFreedOperand(const CallBase *CB, const TargetLibraryInfo *TLI)
If this if a call to a free function, return the freed operand.
LLVM_ABI bool isIdentifiedFunctionLocal(const Value *V)
Return true if V is umabigously identified at the function-level.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI FunctionPass * createDeadStoreEliminationPass()
LLVM_ABI Value * isBytewiseValue(Value *V, const DataLayout &DL)
If the specified value can be set by repeating the same byte in memory, return the i8 value that it i...
auto predecessors(const MachineBasicBlock *BB)
bool capturesAnything(CaptureComponents CC)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
@ End
Run the machine verifier once, at the end of the pipeline.
AAResults AliasAnalysis
Temporary typedef for legacy code that uses a generic AliasAnalysis pointer or reference.
bool capturesNothing(CaptureComponents CC)
LLVM_ABI bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
bool isStrongerThan(AtomicOrdering AO, AtomicOrdering Other)
Returns true if ao is stronger than other as defined by the AtomicOrdering lattice,...
bool isRefSet(const ModRefInfo MRI)
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
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.