96#define DEBUG_TYPE "dse"
98STATISTIC(NumRemainingStores,
"Number of stores remaining after DSE");
99STATISTIC(NumRedundantStores,
"Number of redundant stores deleted");
101STATISTIC(NumFastOther,
"Number of other instrs removed");
102STATISTIC(NumCompletePartials,
"Number of stores dead by later partials");
103STATISTIC(NumModifiedStores,
"Number of stores modified");
108 "Number of times a valid candidate is returned from getDomMemoryDef");
110 "Number iterations check for reads in getDomMemoryDef");
113 "Controls which MemoryDefs are eliminated.");
118 cl::desc(
"Enable partial-overwrite tracking in DSE"));
123 cl::desc(
"Enable partial store merging in DSE"));
127 cl::desc(
"The number of memory instructions to scan for "
128 "dead store elimination (default = 150)"));
131 cl::desc(
"The maximum number of steps while walking upwards to find "
132 "MemoryDefs that may be killed (default = 90)"));
136 cl::desc(
"The maximum number candidates that only partially overwrite the "
137 "killing MemoryDef to consider"
142 cl::desc(
"The number of MemoryDefs we consider as candidates to eliminated "
143 "other stores per basic block (default = 5000)"));
148 "The cost of a step in the same basic block as the killing MemoryDef"
154 cl::desc(
"The cost of a step in a different basic "
155 "block than the killing MemoryDef"
160 cl::desc(
"The maximum number of blocks to check when trying to prove that "
161 "all paths to an exit go through a killing block (default = 50)"));
171 cl::desc(
"Allow DSE to optimize memory accesses."));
176 cl::desc(
"Enable the initializes attr improvement in DSE"));
180 cl::desc(
"Max dominator tree recursion depth for eliminating redundant "
181 "stores via dominating conditions"));
197 switch (
II->getIntrinsicID()) {
198 default:
return false;
199 case Intrinsic::memset:
200 case Intrinsic::memcpy:
201 case Intrinsic::memcpy_element_unordered_atomic:
202 case Intrinsic::memset_element_unordered_atomic:
237enum OverwriteResult {
241 OW_PartialEarlierWithFullLater,
257 if (KillingII ==
nullptr || DeadII ==
nullptr)
259 if (KillingII->getIntrinsicID() != DeadII->getIntrinsicID())
262 switch (KillingII->getIntrinsicID()) {
263 case Intrinsic::masked_store:
264 case Intrinsic::vp_store: {
266 auto *KillingTy = KillingII->getArgOperand(0)->getType();
267 auto *DeadTy = DeadII->getArgOperand(0)->getType();
268 if (
DL.getTypeSizeInBits(KillingTy) !=
DL.getTypeSizeInBits(DeadTy))
275 Value *KillingPtr = KillingII->getArgOperand(1);
276 Value *DeadPtr = DeadII->getArgOperand(1);
277 if (KillingPtr != DeadPtr && !
AA.isMustAlias(KillingPtr, DeadPtr))
279 if (KillingII->getIntrinsicID() == Intrinsic::masked_store) {
282 if (KillingII->getArgOperand(2) != DeadII->getArgOperand(2))
284 }
else if (KillingII->getIntrinsicID() == Intrinsic::vp_store) {
287 if (KillingII->getArgOperand(2) != DeadII->getArgOperand(2))
290 if (KillingII->getArgOperand(3) != DeadII->getArgOperand(3))
312 int64_t KillingOff, int64_t DeadOff,
323 KillingOff < int64_t(DeadOff + DeadSize) &&
324 int64_t(KillingOff + KillingSize) >= DeadOff) {
327 auto &IM = IOL[DeadI];
328 LLVM_DEBUG(
dbgs() <<
"DSE: Partial overwrite: DeadLoc [" << DeadOff <<
", "
329 << int64_t(DeadOff + DeadSize) <<
") KillingLoc ["
330 << KillingOff <<
", " << int64_t(KillingOff + KillingSize)
337 int64_t KillingIntStart = KillingOff;
338 int64_t KillingIntEnd = KillingOff + KillingSize;
342 auto ILI = IM.lower_bound(KillingIntStart);
343 if (ILI != IM.end() && ILI->second <= KillingIntEnd) {
347 KillingIntStart = std::min(KillingIntStart, ILI->second);
348 KillingIntEnd = std::max(KillingIntEnd, ILI->first);
357 while (ILI != IM.end() && ILI->second <= KillingIntEnd) {
358 assert(ILI->second > KillingIntStart &&
"Unexpected interval");
359 KillingIntEnd = std::max(KillingIntEnd, ILI->first);
364 IM[KillingIntEnd] = KillingIntStart;
367 if (ILI->second <= DeadOff && ILI->first >= int64_t(DeadOff + DeadSize)) {
368 LLVM_DEBUG(
dbgs() <<
"DSE: Full overwrite from partials: DeadLoc ["
369 << DeadOff <<
", " << int64_t(DeadOff + DeadSize)
370 <<
") Composite KillingLoc [" << ILI->second <<
", "
371 << ILI->first <<
")\n");
372 ++NumCompletePartials;
380 int64_t(DeadOff + DeadSize) > KillingOff &&
381 uint64_t(KillingOff - DeadOff) + KillingSize <= DeadSize) {
382 LLVM_DEBUG(
dbgs() <<
"DSE: Partial overwrite a dead load [" << DeadOff
383 <<
", " << int64_t(DeadOff + DeadSize)
384 <<
") by a killing store [" << KillingOff <<
", "
385 << int64_t(KillingOff + KillingSize) <<
")\n");
387 return OW_PartialEarlierWithFullLater;
400 (KillingOff > DeadOff && KillingOff < int64_t(DeadOff + DeadSize) &&
401 int64_t(KillingOff + KillingSize) >= int64_t(DeadOff + DeadSize)))
414 (KillingOff <= DeadOff && int64_t(KillingOff + KillingSize) > DeadOff)) {
415 assert(int64_t(KillingOff + KillingSize) < int64_t(DeadOff + DeadSize) &&
416 "Expect to be handled as OW_Complete");
436 using BlockAddressPair = std::pair<BasicBlock *, PHITransAddr>;
453 auto *MemLocPtr =
const_cast<Value *
>(MemLoc.
Ptr);
458 bool isFirstBlock =
true;
461 while (!WorkList.
empty()) {
473 assert(
B == SecondBB &&
"first block is not the store block");
475 isFirstBlock =
false;
481 for (; BI != EI; ++BI) {
483 if (
I->mayWriteToMemory() &&
I != SecondI)
489 "Should not hit the entry block because SI must be dominated by LI");
499 auto Inserted = Visited.
insert(std::make_pair(Pred, TranslatedPtr));
500 if (!Inserted.second) {
503 if (TranslatedPtr != Inserted.first->second)
508 WorkList.
push_back(std::make_pair(Pred, PredAddr));
517 bool IsOverwriteEnd) {
519 uint64_t DeadSliceSizeInBits = OldSizeInBits - NewSizeInBits;
526 uint64_t DeadSliceOffsetInBits = IsOverwriteEnd ? NewSizeInBits : 0;
527 auto SetDeadFragExpr = [](
auto *Assign,
531 uint64_t RelativeOffset = DeadFragment.OffsetInBits -
532 Assign->getExpression()
537 Assign->getExpression(), RelativeOffset, DeadFragment.SizeInBits)) {
538 Assign->setExpression(*
NewExpr);
545 DeadFragment.SizeInBits);
546 Assign->setExpression(Expr);
547 Assign->setKillLocation();
554 auto GetDeadLink = [&Ctx, &LinkToNothing]() {
557 return LinkToNothing;
563 std::optional<DIExpression::FragmentInfo> NewFragment;
565 DeadSliceSizeInBits, Assign,
572 Assign->setKillAddress();
573 Assign->setAssignId(GetDeadLink());
577 if (NewFragment->SizeInBits == 0)
581 auto *NewAssign =
static_cast<decltype(Assign)
>(Assign->clone());
582 NewAssign->insertAfter(Assign->getIterator());
583 NewAssign->setAssignId(GetDeadLink());
585 SetDeadFragExpr(NewAssign, *NewFragment);
586 NewAssign->setKillAddress();
600 for (
auto &Attr : OldAttrs) {
601 if (Attr.hasKindAsEnum()) {
602 switch (Attr.getKindAsEnum()) {
605 case Attribute::Alignment:
607 if (
isAligned(Attr.getAlignment().valueOrOne(), PtrOffset))
610 case Attribute::Dereferenceable:
611 case Attribute::DereferenceableOrNull:
615 case Attribute::NonNull:
616 case Attribute::NoUndef:
624 Intrinsic->removeParamAttrs(ArgNo, AttrsToRemove);
628 uint64_t &DeadSize, int64_t KillingStart,
629 uint64_t KillingSize,
bool IsOverwriteEnd) {
631 Align PrefAlign = DeadIntrinsic->getDestAlign().valueOrOne();
647 int64_t ToRemoveStart = 0;
651 if (IsOverwriteEnd) {
656 ToRemoveStart = KillingStart + Off;
657 if (DeadSize <=
uint64_t(ToRemoveStart - DeadStart))
659 ToRemoveSize = DeadSize -
uint64_t(ToRemoveStart - DeadStart);
661 ToRemoveStart = DeadStart;
663 "Not overlapping accesses?");
664 ToRemoveSize = KillingSize -
uint64_t(DeadStart - KillingStart);
669 if (ToRemoveSize <= (PrefAlign.
value() - Off))
671 ToRemoveSize -= PrefAlign.
value() - Off;
674 "Should preserve selected alignment");
677 assert(ToRemoveSize > 0 &&
"Shouldn't reach here if nothing to remove");
678 assert(DeadSize > ToRemoveSize &&
"Can't remove more than original size");
680 uint64_t NewSize = DeadSize - ToRemoveSize;
681 if (DeadIntrinsic->isAtomic()) {
684 const uint32_t ElementSize = DeadIntrinsic->getElementSizeInBytes();
685 if (0 != NewSize % ElementSize)
690 << (IsOverwriteEnd ?
"END" :
"BEGIN") <<
": " << *DeadI
691 <<
"\n KILLER [" << ToRemoveStart <<
", "
692 << int64_t(ToRemoveStart + ToRemoveSize) <<
")\n");
694 DeadIntrinsic->setLength(NewSize);
695 DeadIntrinsic->setDestAlignment(PrefAlign);
697 Value *OrigDest = DeadIntrinsic->getRawDest();
698 if (!IsOverwriteEnd) {
699 Value *Indices[1] = {
700 ConstantInt::get(DeadIntrinsic->getLength()->getType(), ToRemoveSize)};
704 NewDestGEP->
setDebugLoc(DeadIntrinsic->getDebugLoc());
705 DeadIntrinsic->setDest(NewDestGEP);
714 DeadStart += ToRemoveSize;
721 int64_t &DeadStart,
uint64_t &DeadSize) {
726 int64_t KillingStart = OII->second;
727 uint64_t KillingSize = OII->first - KillingStart;
729 assert(OII->first - KillingStart >= 0 &&
"Size expected to be positive");
731 if (KillingStart > DeadStart &&
734 (
uint64_t)(KillingStart - DeadStart) < DeadSize &&
737 KillingSize >= DeadSize - (
uint64_t)(KillingStart - DeadStart)) {
738 if (
tryToShorten(DeadI, DeadStart, DeadSize, KillingStart, KillingSize,
749 int64_t &DeadStart,
uint64_t &DeadSize) {
754 int64_t KillingStart = OII->second;
755 uint64_t KillingSize = OII->first - KillingStart;
757 assert(OII->first - KillingStart >= 0 &&
"Size expected to be positive");
759 if (KillingStart <= DeadStart &&
762 KillingSize > (
uint64_t)(DeadStart - KillingStart)) {
765 assert(KillingSize - (
uint64_t)(DeadStart - KillingStart) < DeadSize &&
766 "Should have been handled as OW_Complete");
767 if (
tryToShorten(DeadI, DeadStart, DeadSize, KillingStart, KillingSize,
778 int64_t KillingOffset, int64_t DeadOffset,
822 unsigned BitOffsetDiff = (KillingOffset - DeadOffset) * 8;
823 unsigned LShiftAmount =
824 DL.isBigEndian() ? DeadValue.
getBitWidth() - BitOffsetDiff - KillingBits
827 LShiftAmount + KillingBits);
830 APInt Merged = (DeadValue & ~Mask) | (KillingValue << LShiftAmount);
832 <<
"\n Killing: " << *KillingI
833 <<
"\n Merged Value: " << Merged <<
'\n');
840 switch (
II->getIntrinsicID()) {
841 case Intrinsic::lifetime_start:
842 case Intrinsic::lifetime_end:
843 case Intrinsic::invariant_end:
844 case Intrinsic::launder_invariant_group:
845 case Intrinsic::assume:
847 case Intrinsic::dbg_declare:
848 case Intrinsic::dbg_label:
849 case Intrinsic::dbg_value:
864 if (CB->onlyAccessesInaccessibleMemory())
869 if (DI->
mayThrow() && !DefVisibleToCaller)
891struct MemoryLocationWrapper {
892 MemoryLocationWrapper(MemoryLocation MemLoc, MemoryDef *MemDef,
893 bool DefByInitializesAttr)
894 : MemLoc(MemLoc), MemDef(MemDef),
895 DefByInitializesAttr(DefByInitializesAttr) {
896 assert(MemLoc.Ptr &&
"MemLoc should be not null");
898 DefInst = MemDef->getMemoryInst();
901 MemoryLocation MemLoc;
902 const Value *UnderlyingObject;
905 bool DefByInitializesAttr =
false;
910struct MemoryDefWrapper {
911 MemoryDefWrapper(MemoryDef *MemDef,
912 ArrayRef<std::pair<MemoryLocation, bool>> MemLocations) {
914 for (
auto &[MemLoc, DefByInitializesAttr] : MemLocations)
915 DefinedLocations.push_back(
916 MemoryLocationWrapper(MemLoc, MemDef, DefByInitializesAttr));
922struct ArgumentInitInfo {
924 bool IsDeadOrInvisibleOnUnwind;
925 ConstantRangeList Inits;
940 bool CallHasNoUnwindAttr) {
946 for (
const auto &Arg : Args) {
947 if (!CallHasNoUnwindAttr && !Arg.IsDeadOrInvisibleOnUnwind)
949 if (Arg.Inits.empty())
954 for (
auto &Arg : Args.drop_front())
955 IntersectedIntervals = IntersectedIntervals.
intersectWith(Arg.Inits);
957 return IntersectedIntervals;
965 EarliestEscapeAnalysis EA;
974 BatchAAResults BatchAA;
978 PostDominatorTree &PDT;
979 const TargetLibraryInfo &TLI;
980 const DataLayout &DL;
986 SmallPtrSet<MemoryAccess *, 4> SkipStores;
988 DenseMap<const Value *, bool> CapturedBeforeReturn;
991 DenseMap<const Value *, bool> InvisibleToCallerAfterRet;
992 DenseMap<const Value *, uint64_t> InvisibleToCallerAfterRetBounded;
994 SmallPtrSet<BasicBlock *, 16> ThrowingBlocks;
997 DenseMap<BasicBlock *, unsigned> PostOrderNumbers;
1001 MapVector<BasicBlock *, InstOverlapIntervalsTy> IOLs;
1005 bool AnyUnreachableExit;
1010 bool ShouldIterateEndOfFunctionDSE;
1013 SmallVector<Instruction *> ToRemove;
1017 PostDominatorTree &PDT,
const TargetLibraryInfo &TLI,
1018 const CycleInfo &CI);
1019 DSEState(
const DSEState &) =
delete;
1020 DSEState &operator=(
const DSEState &) =
delete;
1022 LocationSize strengthenLocationSize(
const Instruction *
I,
1023 LocationSize
Size)
const;
1033 OverwriteResult isOverwrite(
const Instruction *KillingI,
1034 const Instruction *DeadI,
1035 const MemoryLocation &KillingLoc,
1036 const MemoryLocation &DeadLoc,
1037 int64_t &KillingOff, int64_t &DeadOff);
1039 bool isInvisibleToCallerAfterRet(
const Value *V,
const Value *Ptr,
1040 const LocationSize StoreSize);
1042 bool isInvisibleToCallerOnUnwind(
const Value *V);
1044 std::optional<MemoryLocation> getLocForWrite(Instruction *
I)
const;
1049 getLocForInst(Instruction *
I,
bool ConsiderInitializesAttr);
1053 bool isRemovable(Instruction *
I);
1057 bool isCompleteOverwrite(
const MemoryLocation &DefLoc, Instruction *DefInst,
1058 Instruction *UseInst);
1061 bool isWriteAtEndOfFunction(MemoryDef *Def,
const MemoryLocation &DefLoc);
1066 std::optional<std::pair<MemoryLocation, bool>>
1067 getLocForTerminator(Instruction *
I)
const;
1071 bool isMemTerminatorInst(Instruction *
I)
const;
1075 bool isMemTerminator(
const MemoryLocation &Loc, Instruction *AccessI,
1076 Instruction *MaybeTerm);
1079 bool isReadClobber(
const MemoryLocation &DefLoc, Instruction *UseInst);
1086 bool isGuaranteedLoopIndependent(
const Instruction *Current,
1087 const Instruction *KillingDef,
1088 const MemoryLocation &CurrentLoc);
1093 bool isGuaranteedLoopInvariant(
const Value *Ptr);
1101 std::optional<MemoryAccess *>
1102 getDomMemoryDef(MemoryDef *KillingDef, MemoryAccess *StartAccess,
1103 const MemoryLocation &KillingLoc,
const Value *KillingUndObj,
1104 unsigned &ScanLimit,
unsigned &WalkerStepLimit,
1105 bool IsMemTerm,
unsigned &PartialLimit,
1106 bool IsInitializesAttrMemLoc);
1112 SmallPtrSetImpl<MemoryAccess *> *
Deleted =
nullptr);
1118 bool mayThrowBetween(Instruction *KillingI, Instruction *DeadI,
1119 const Value *KillingUndObj);
1126 bool isDSEBarrier(
const Value *KillingUndObj, Instruction *DeadI);
1130 bool eliminateDeadWritesAtEndOfFunction();
1134 bool tryFoldIntoCalloc(MemoryDef *Def,
const Value *DefUO);
1138 bool storeIsNoop(MemoryDef *Def,
const Value *DefUO);
1144 bool eliminateRedundantStoresOfExistingValues();
1149 bool eliminateRedundantStoresViaDominatingConditions();
1164 std::pair<bool, bool>
1165 eliminateDeadDefs(
const MemoryLocationWrapper &KillingLocWrapper);
1169 bool eliminateDeadDefs(
const MemoryDefWrapper &KillingDefWrapper);
1179 if (Visited.
insert(MA).second)
1196 :
F(
F),
AA(
AA), EA(DT, nullptr, &CI), BatchAA(
AA, &EA), MSSA(MSSA), DT(DT),
1197 PDT(PDT), TLI(TLI),
DL(
F.getDataLayout()), CI(CI) {
1202 PostOrderNumbers[BB] = PO++;
1205 if (
I.mayThrow() && !MA)
1206 ThrowingBlocks.insert(
I.getParent());
1210 (getLocForWrite(&
I) || isMemTerminatorInst(&
I) ||
1212 MemDefs.push_back(MD);
1219 if (AI.hasPassPointeeByValueCopyAttr()) {
1220 InvisibleToCallerAfterRet.insert({&AI, true});
1224 if (!AI.getType()->isPointerTy())
1228 if (Info.coversAllReachableMemory())
1229 InvisibleToCallerAfterRet.insert({&AI, true});
1230 else if (
uint64_t DeadBytes = Info.getNumberOfDeadBytes())
1231 InvisibleToCallerAfterRetBounded.insert({&AI, DeadBytes});
1235 return isa<UnreachableInst>(E->getTerminator());
1243 if (TLI.
has(
F) && (
F == LibFunc_memset_chk ||
F == LibFunc_memcpy_chk)) {
1259OverwriteResult DSEState::isOverwrite(
const Instruction *KillingI,
1260 const Instruction *DeadI,
1261 const MemoryLocation &KillingLoc,
1262 const MemoryLocation &DeadLoc,
1263 int64_t &KillingOff, int64_t &DeadOff) {
1267 if (!isGuaranteedLoopIndependent(DeadI, KillingI, DeadLoc))
1270 LocationSize KillingLocSize =
1271 strengthenLocationSize(KillingI, KillingLoc.
Size);
1279 if (DeadUndObj == KillingUndObj && KillingLocSize.
isPrecise() &&
1281 std::optional<TypeSize> KillingUndObjSize =
1283 if (KillingUndObjSize && *KillingUndObjSize == KillingLocSize.
getValue())
1294 if (KillingMemI && DeadMemI) {
1295 const Value *KillingV = KillingMemI->getLength();
1296 const Value *DeadV = DeadMemI->getLength();
1297 if (KillingV == DeadV && BatchAA.
isMustAlias(DeadLoc, KillingLoc))
1306 const TypeSize KillingSize = KillingLocSize.
getValue();
1315 AliasResult AAR = BatchAA.
alias(KillingLoc, DeadLoc);
1321 if (KillingSize >= DeadSize)
1328 if (Off >= 0 && (
uint64_t)Off + DeadSize <= KillingSize)
1334 if (DeadUndObj != KillingUndObj) {
1350 const Value *DeadBasePtr =
1352 const Value *KillingBasePtr =
1357 if (DeadBasePtr != KillingBasePtr)
1375 if (DeadOff >= KillingOff) {
1378 if (
uint64_t(DeadOff - KillingOff) + DeadSize <= KillingSize)
1382 else if ((
uint64_t)(DeadOff - KillingOff) < KillingSize)
1383 return OW_MaybePartial;
1387 else if ((
uint64_t)(KillingOff - DeadOff) < DeadSize) {
1388 return OW_MaybePartial;
1395bool DSEState::isInvisibleToCallerAfterRet(
const Value *V,
const Value *Ptr,
1396 const LocationSize StoreSize) {
1400 auto IBounded = InvisibleToCallerAfterRetBounded.find(V);
1401 if (IBounded != InvisibleToCallerAfterRetBounded.end()) {
1402 int64_t ValueOffset;
1403 [[maybe_unused]]
const Value *BaseValue =
1413 ValueOffset + StoreSize.
getValue() <= IBounded->second &&
1417 auto I = InvisibleToCallerAfterRet.insert({
V,
false});
1418 if (
I.second && isInvisibleToCallerOnUnwind(V) &&
isNoAliasCall(V))
1421 return I.first->second;
1424bool DSEState::isInvisibleToCallerOnUnwind(
const Value *V) {
1425 bool RequiresNoCaptureBeforeUnwind;
1428 if (!RequiresNoCaptureBeforeUnwind)
1431 auto I = CapturedBeforeReturn.insert({
V,
true});
1439 return !
I.first->second;
1442std::optional<MemoryLocation> DSEState::getLocForWrite(Instruction *
I)
const {
1443 if (!
I->mayWriteToMemory())
1444 return std::nullopt;
1453DSEState::getLocForInst(Instruction *
I,
bool ConsiderInitializesAttr) {
1455 if (isMemTerminatorInst(
I)) {
1456 if (
auto Loc = getLocForTerminator(
I))
1457 Locations.push_back(std::make_pair(Loc->first,
false));
1461 if (
auto Loc = getLocForWrite(
I))
1462 Locations.push_back(std::make_pair(*Loc,
false));
1464 if (ConsiderInitializesAttr) {
1465 for (
auto &MemLoc : getInitializesArgMemLoc(
I)) {
1466 Locations.push_back(std::make_pair(MemLoc,
true));
1472bool DSEState::isRemovable(Instruction *
I) {
1473 assert(getLocForWrite(
I) &&
"Must have analyzable write");
1477 return SI->isUnordered();
1482 return !
MI->isVolatile();
1486 if (CB->isLifetimeStartOrEnd())
1489 return CB->use_empty() && CB->willReturn() && CB->doesNotThrow() &&
1490 !CB->isTerminator();
1496bool DSEState::isCompleteOverwrite(
const MemoryLocation &DefLoc,
1497 Instruction *DefInst, Instruction *UseInst) {
1505 if (CB->onlyAccessesInaccessibleMemory())
1508 int64_t InstWriteOffset, DepWriteOffset;
1509 if (
auto CC = getLocForWrite(UseInst))
1510 return isOverwrite(UseInst, DefInst, *CC, DefLoc, InstWriteOffset,
1511 DepWriteOffset) == OW_Complete;
1515bool DSEState::isWriteAtEndOfFunction(MemoryDef *Def,
1516 const MemoryLocation &DefLoc) {
1518 << *
Def->getMemoryInst()
1519 <<
") is at the end the function \n");
1521 SmallPtrSet<MemoryAccess *, 8> Visited;
1524 for (
unsigned I = 0;
I < WorkList.
size();
I++) {
1530 MemoryAccess *UseAccess = WorkList[
I];
1535 if (!isGuaranteedLoopInvariant(DefLoc.
Ptr))
1544 if (isReadClobber(DefLoc, UseInst)) {
1545 LLVM_DEBUG(
dbgs() <<
" ... hit read clobber " << *UseInst <<
".\n");
1555std::optional<std::pair<MemoryLocation, bool>>
1556DSEState::getLocForTerminator(Instruction *
I)
const {
1558 if (CB->getIntrinsicID() == Intrinsic::lifetime_end)
1565 return std::nullopt;
1568bool DSEState::isMemTerminatorInst(Instruction *
I)
const {
1570 return CB && (CB->getIntrinsicID() == Intrinsic::lifetime_end ||
1574bool DSEState::isMemTerminator(
const MemoryLocation &Loc, Instruction *AccessI,
1575 Instruction *MaybeTerm) {
1576 std::optional<std::pair<MemoryLocation, bool>> MaybeTermLoc =
1577 getLocForTerminator(MaybeTerm);
1588 auto TermLoc = MaybeTermLoc->first;
1589 if (MaybeTermLoc->second) {
1593 int64_t InstWriteOffset = 0;
1594 int64_t DepWriteOffset = 0;
1595 return isOverwrite(MaybeTerm, AccessI, TermLoc, Loc, InstWriteOffset,
1596 DepWriteOffset) == OW_Complete;
1599bool DSEState::isReadClobber(
const MemoryLocation &DefLoc,
1600 Instruction *UseInst) {
1613 if (CB->onlyAccessesInaccessibleMemory())
1619bool DSEState::isGuaranteedLoopIndependent(
const Instruction *Current,
1620 const Instruction *KillingDef,
1621 const MemoryLocation &CurrentLoc) {
1632 return isGuaranteedLoopInvariant(CurrentLoc.
Ptr);
1635bool DSEState::isGuaranteedLoopInvariant(
const Value *Ptr) {
1638 if (
GEP->hasAllConstantIndices())
1642 return I->getParent()->isEntryBlock() || !CI.
getCycle(
I->getParent());
1647std::optional<MemoryAccess *> DSEState::getDomMemoryDef(
1648 MemoryDef *KillingDef, MemoryAccess *StartAccess,
1649 const MemoryLocation &KillingLoc,
const Value *KillingUndObj,
1650 unsigned &ScanLimit,
unsigned &WalkerStepLimit,
bool IsMemTerm,
1651 unsigned &PartialLimit,
bool IsInitializesAttrMemLoc) {
1652 if (ScanLimit == 0 || WalkerStepLimit == 0) {
1654 return std::nullopt;
1657 MemoryAccess *Current = StartAccess;
1671 std::optional<MemoryLocation> CurrentLoc;
1674 dbgs() <<
" visiting " << *Current;
1687 return std::nullopt;
1695 if (WalkerStepLimit <= StepCost) {
1697 return std::nullopt;
1699 WalkerStepLimit -= StepCost;
1713 if (
canSkipDef(CurrentDef, !isInvisibleToCallerOnUnwind(KillingUndObj))) {
1714 CanOptimize =
false;
1720 if (mayThrowBetween(KillingI, CurrentI, KillingUndObj)) {
1722 return std::nullopt;
1727 if (isDSEBarrier(KillingUndObj, CurrentI)) {
1729 return std::nullopt;
1737 return std::nullopt;
1740 if (
any_of(Current->
uses(), [
this, &KillingLoc, StartAccess](Use &U) {
1741 if (auto *UseOrDef = dyn_cast<MemoryUseOrDef>(U.getUser()))
1742 return !MSSA.dominates(StartAccess, UseOrDef) &&
1743 isReadClobber(KillingLoc, UseOrDef->getMemoryInst());
1747 return std::nullopt;
1752 CurrentLoc = getLocForWrite(CurrentI);
1753 if (!CurrentLoc || !isRemovable(CurrentI)) {
1754 CanOptimize =
false;
1761 if (!isGuaranteedLoopIndependent(CurrentI, KillingI, *CurrentLoc)) {
1763 CanOptimize =
false;
1771 if (!isMemTerminator(*CurrentLoc, CurrentI, KillingI)) {
1772 CanOptimize =
false;
1776 int64_t KillingOffset = 0;
1777 int64_t DeadOffset = 0;
1778 auto OR = isOverwrite(KillingI, CurrentI, KillingLoc, *CurrentLoc,
1779 KillingOffset, DeadOffset);
1785 (OR == OW_Complete || OR == OW_MaybePartial))
1791 CanOptimize =
false;
1796 if (OR == OW_Unknown || OR == OW_None)
1798 else if (OR == OW_MaybePartial) {
1803 if (PartialLimit <= 1) {
1804 WalkerStepLimit -= 1;
1805 LLVM_DEBUG(
dbgs() <<
" ... reached partial limit ... continue with "
1819 SmallPtrSet<Instruction *, 16> KillingDefs;
1821 MemoryAccess *MaybeDeadAccess = Current;
1822 MemoryLocation MaybeDeadLoc = *CurrentLoc;
1824 LLVM_DEBUG(
dbgs() <<
" Checking for reads of " << *MaybeDeadAccess <<
" ("
1825 << *MaybeDeadI <<
")\n");
1828 SmallPtrSet<MemoryAccess *, 32> Visited;
1832 for (
unsigned I = 0;
I < WorkList.
size();
I++) {
1833 MemoryAccess *UseAccess = WorkList[
I];
1837 if (ScanLimit < (WorkList.
size() -
I)) {
1839 return std::nullopt;
1842 NumDomMemDefChecks++;
1845 if (
any_of(KillingDefs, [
this, UseAccess](Instruction *KI) {
1848 LLVM_DEBUG(
dbgs() <<
" ... skipping, dominated by killing block\n");
1859 if (
any_of(KillingDefs, [
this, UseInst](Instruction *KI) {
1862 LLVM_DEBUG(
dbgs() <<
" ... skipping, dominated by killing def\n");
1868 if (isMemTerminator(MaybeDeadLoc, MaybeDeadI, UseInst)) {
1871 <<
" ... skipping, memterminator invalidates following accesses\n");
1881 if (UseInst->
mayThrow() && !isInvisibleToCallerOnUnwind(KillingUndObj)) {
1883 return std::nullopt;
1890 bool IsKillingDefFromInitAttr =
false;
1891 if (IsInitializesAttrMemLoc) {
1892 if (KillingI == UseInst &&
1894 IsKillingDefFromInitAttr =
true;
1897 if (isReadClobber(MaybeDeadLoc, UseInst) && !IsKillingDefFromInitAttr) {
1899 return std::nullopt;
1905 if (MaybeDeadAccess == UseAccess &&
1906 !isGuaranteedLoopInvariant(MaybeDeadLoc.
Ptr)) {
1907 LLVM_DEBUG(
dbgs() <<
" ... found not loop invariant self access\n");
1908 return std::nullopt;
1914 if (KillingDef == UseAccess || MaybeDeadAccess == UseAccess) {
1930 if (isCompleteOverwrite(MaybeDeadLoc, MaybeDeadI, UseInst)) {
1932 if (PostOrderNumbers.
find(MaybeKillingBlock)->second <
1933 PostOrderNumbers.
find(MaybeDeadAccess->
getBlock())->second) {
1934 if (!isInvisibleToCallerAfterRet(KillingUndObj, KillingLoc.
Ptr,
1937 <<
" ... found killing def " << *UseInst <<
"\n");
1938 KillingDefs.
insert(UseInst);
1942 <<
" ... found preceeding def " << *UseInst <<
"\n");
1943 return std::nullopt;
1953 if (!isInvisibleToCallerAfterRet(KillingUndObj, KillingLoc.
Ptr,
1955 SmallPtrSet<BasicBlock *, 16> KillingBlocks;
1956 for (Instruction *KD : KillingDefs)
1957 KillingBlocks.
insert(KD->getParent());
1959 "Expected at least a single killing block");
1973 if (!AnyUnreachableExit)
1974 return std::nullopt;
1978 CommonPred =
nullptr;
1982 if (KillingBlocks.
count(CommonPred))
1983 return {MaybeDeadAccess};
1985 SetVector<BasicBlock *> WorkList;
1989 WorkList.
insert(CommonPred);
1991 for (BasicBlock *R : PDT.
roots()) {
1999 for (
unsigned I = 0;
I < WorkList.
size();
I++) {
2002 if (KillingBlocks.
count(Current))
2004 if (Current == MaybeDeadAccess->
getBlock())
2005 return std::nullopt;
2015 return std::nullopt;
2022 return {MaybeDeadAccess};
2025void DSEState::deleteDeadInstruction(Instruction *SI,
2026 SmallPtrSetImpl<MemoryAccess *> *
Deleted) {
2027 MemorySSAUpdater Updater(&MSSA);
2032 while (!NowDeadInsts.
empty()) {
2046 SkipStores.insert(MD);
2050 if (
SI->getValueOperand()->getType()->isPointerTy()) {
2052 if (CapturedBeforeReturn.erase(UO))
2053 ShouldIterateEndOfFunctionDSE =
true;
2054 InvisibleToCallerAfterRet.erase(UO);
2055 InvisibleToCallerAfterRetBounded.erase(UO);
2060 Updater.removeMemoryAccess(MA);
2064 if (
I != IOLs.end())
2065 I->second.erase(DeadInst);
2067 for (Use &O : DeadInst->
operands())
2087bool DSEState::mayThrowBetween(Instruction *KillingI, Instruction *DeadI,
2088 const Value *KillingUndObj) {
2092 if (KillingUndObj && isInvisibleToCallerOnUnwind(KillingUndObj))
2096 return ThrowingBlocks.count(KillingI->
getParent());
2097 return !ThrowingBlocks.empty();
2100bool DSEState::isDSEBarrier(
const Value *KillingUndObj, Instruction *DeadI) {
2103 if (DeadI->
mayThrow() && !isInvisibleToCallerOnUnwind(KillingUndObj))
2123bool DSEState::eliminateDeadWritesAtEndOfFunction() {
2124 bool MadeChange =
false;
2126 dbgs() <<
"Trying to eliminate MemoryDefs at the end of the function\n");
2128 ShouldIterateEndOfFunctionDSE =
false;
2130 if (SkipStores.contains(Def))
2134 auto DefLoc = getLocForWrite(DefI);
2135 if (!DefLoc || !isRemovable(DefI)) {
2137 "instruction not removable.\n");
2147 if (!isInvisibleToCallerAfterRet(UO, DefLoc->
Ptr, DefLoc->
Size))
2150 if (isWriteAtEndOfFunction(Def, *DefLoc)) {
2152 LLVM_DEBUG(
dbgs() <<
" ... MemoryDef is not accessed until the end "
2153 "of the function\n");
2159 }
while (ShouldIterateEndOfFunctionDSE);
2163bool DSEState::eliminateRedundantStoresViaDominatingConditions() {
2164 bool MadeChange =
false;
2165 LLVM_DEBUG(
dbgs() <<
"Trying to eliminate MemoryDefs whose value being "
2166 "written is implied by a dominating condition\n");
2168 using ConditionInfo = std::pair<Value *, Value *>;
2169 using ScopedHTType = ScopedHashTable<ConditionInfo, Instruction *>;
2173 ScopedHTType ActiveConditions;
2174 auto GetDominatingCondition = [&](
BasicBlock *BB)
2175 -> std::optional<std::tuple<ConditionInfo, Instruction *, BasicBlock *>> {
2178 return std::nullopt;
2183 if (BI->getSuccessor(0) == BI->getSuccessor(1))
2184 return std::nullopt;
2188 Value *StorePtr, *StoreVal;
2189 if (!
match(BI->getCondition(),
2193 return std::nullopt;
2199 return std::nullopt;
2201 unsigned ImpliedSuccIdx = Pred == ICmpInst::ICMP_EQ ? 0 : 1;
2202 BasicBlock *ImpliedSucc = BI->getSuccessor(ImpliedSuccIdx);
2203 return {{ConditionInfo(StorePtr, StoreVal), ICmpL, ImpliedSucc}};
2219 if (!SI || !
SI->isUnordered())
2223 {
SI->getPointerOperand(),
SI->getValueOperand()});
2231 MemoryAccess *ClobberingAccess =
2233 if (MSSA.
dominates(ClobberingAccess, LoadAccess)) {
2235 <<
"Removing No-Op Store:\n DEAD: " << *SI <<
'\n');
2237 NumRedundantStores++;
2244 auto MaybeCondition = GetDominatingCondition(BB);
2248 ScopedHTType::ScopeTy
Scope(ActiveConditions);
2249 if (MaybeCondition) {
2250 const auto &[
Cond, LI, ImpliedSucc] = *MaybeCondition;
2251 if (DT.
dominates(BasicBlockEdge(BB, ImpliedSucc), Child->getBlock())) {
2255 ActiveConditions.insert(
Cond, LI);
2262 Self(Child,
Depth + 1, Self);
2272bool DSEState::tryFoldIntoCalloc(MemoryDef *Def,
const Value *DefUO) {
2279 if (!StoredConstant || !StoredConstant->
isNullValue())
2282 if (!isRemovable(DefI))
2286 if (
F.hasFnAttribute(Attribute::SanitizeMemory) ||
2287 F.hasFnAttribute(Attribute::SanitizeAddress) ||
2288 F.hasFnAttribute(Attribute::SanitizeHWAddress) ||
F.getName() ==
"calloc")
2293 auto *InnerCallee =
Malloc->getCalledFunction();
2297 StringRef ZeroedVariantName;
2298 if (Func != LibFunc_malloc || !TLI.
has(Func)) {
2303 if (ZeroedVariantName.
empty())
2312 auto shouldCreateCalloc = [](CallInst *
Malloc, CallInst *Memset) {
2315 auto *MallocBB =
Malloc->getParent(), *MemsetBB = Memset->getParent();
2316 if (MallocBB == MemsetBB)
2318 auto *Ptr = Memset->getArgOperand(0);
2319 auto *TI = MallocBB->getTerminator();
2325 if (MemsetBB != FalseBB)
2336 assert(Func == LibFunc_malloc || !ZeroedVariantName.
empty());
2337 Value *Calloc =
nullptr;
2338 if (!ZeroedVariantName.
empty()) {
2339 LLVMContext &Ctx =
Malloc->getContext();
2340 AttributeList
Attrs = InnerCallee->getAttributes();
2342 Attrs.getFnAttr(Attribute::AllocKind).getAllocKind() |
2343 AllocFnKind::Zeroed;
2346 Attrs.addFnAttribute(Ctx, Attribute::getWithAllocKind(Ctx, AllocKind))
2347 .removeFnAttribute(Ctx,
"alloc-variant-zeroed");
2348 FunctionCallee ZeroedVariant =
Malloc->getModule()->getOrInsertFunction(
2349 ZeroedVariantName, InnerCallee->getFunctionType(), Attrs);
2351 ->setCallingConv(
Malloc->getCallingConv());
2354 CallInst *CI = IRB.CreateCall(ZeroedVariant, Args, ZeroedVariantName);
2358 Type *SizeTTy =
Malloc->getArgOperand(0)->getType();
2359 Calloc =
emitCalloc(ConstantInt::get(SizeTTy, 1),
Malloc->getArgOperand(0),
2360 IRB, TLI,
Malloc->getType()->getPointerAddressSpace());
2365 if (MDNode *MD =
Malloc->getMetadata(LLVMContext::MD_alloc_token))
2368 MemorySSAUpdater Updater(&MSSA);
2370 nullptr, MallocDef);
2372 Updater.insertDef(NewAccessMD,
true);
2373 Malloc->replaceAllUsesWith(Calloc);
2378bool DSEState::storeIsNoop(MemoryDef *Def,
const Value *DefUO) {
2382 Constant *StoredConstant =
nullptr;
2390 if (!isRemovable(DefI))
2393 if (StoredConstant) {
2398 if (InitC && InitC == StoredConstant)
2407 if (LoadI->getPointerOperand() ==
Store->getOperand(1)) {
2411 if (LoadAccess ==
Def->getDefiningAccess())
2417 SetVector<MemoryAccess *> ToCheck;
2418 MemoryAccess *Current =
2426 for (
unsigned I = 1;
I < ToCheck.
size(); ++
I) {
2427 Current = ToCheck[
I];
2430 for (
auto &Use : PhiAccess->incoming_values())
2442 if (LoadAccess != Current)
2454 for (
auto OI : IOL) {
2456 MemoryLocation Loc = *getLocForWrite(DeadI);
2457 assert(isRemovable(DeadI) &&
"Expect only removable instruction");
2460 int64_t DeadStart = 0;
2465 if (IntervalMap.empty())
2472bool DSEState::eliminateRedundantStoresOfExistingValues() {
2473 bool MadeChange =
false;
2474 LLVM_DEBUG(
dbgs() <<
"Trying to eliminate MemoryDefs that write the "
2475 "already existing value\n");
2476 for (
auto *Def : MemDefs) {
2481 auto MaybeDefLoc = getLocForWrite(DefInst);
2482 if (!MaybeDefLoc || !isRemovable(DefInst))
2485 MemoryDef *UpperDef;
2489 if (
Def->isOptimized())
2497 auto IsRedundantStore = [&]() {
2505 auto UpperLoc = getLocForWrite(UpperInst);
2508 int64_t InstWriteOffset = 0;
2509 int64_t DepWriteOffset = 0;
2510 auto OR = isOverwrite(UpperInst, DefInst, *UpperLoc, *MaybeDefLoc,
2511 InstWriteOffset, DepWriteOffset);
2513 return StoredByte && StoredByte == MemSetI->getOperand(1) &&
2520 if (!IsRedundantStore() || isReadClobber(*MaybeDefLoc, DefInst))
2522 LLVM_DEBUG(
dbgs() <<
"DSE: Remove No-Op Store:\n DEAD: " << *DefInst
2525 NumRedundantStores++;
2532DSEState::getInitializesArgMemLoc(
const Instruction *
I) {
2538 SmallMapVector<Value *, SmallVector<ArgumentInitInfo, 2>, 2>
Arguments;
2544 ConstantRangeList Inits;
2556 Inits = ConstantRangeList();
2564 bool IsDeadOrInvisibleOnUnwind =
2567 ArgumentInitInfo InitInfo{Idx, IsDeadOrInvisibleOnUnwind, Inits};
2568 bool FoundAliasing =
false;
2569 for (
auto &[Arg, AliasList] :
Arguments) {
2575 FoundAliasing =
true;
2576 AliasList.push_back(InitInfo);
2581 FoundAliasing =
true;
2582 AliasList.push_back(ArgumentInitInfo{Idx, IsDeadOrInvisibleOnUnwind,
2583 ConstantRangeList()});
2592 auto IntersectedRanges =
2594 if (IntersectedRanges.empty())
2597 for (
const auto &Arg : Args) {
2598 for (
const auto &
Range : IntersectedRanges) {
2612std::pair<bool, bool>
2613DSEState::eliminateDeadDefs(
const MemoryLocationWrapper &KillingLocWrapper) {
2615 bool DeletedKillingLoc =
false;
2621 SmallSetVector<MemoryAccess *, 8> ToCheck;
2625 SmallPtrSet<MemoryAccess *, 8>
Deleted;
2626 [[maybe_unused]]
unsigned OrigNumSkipStores = SkipStores.size();
2631 for (
unsigned I = 0;
I < ToCheck.
size();
I++) {
2632 MemoryAccess *Current = ToCheck[
I];
2633 if (
Deleted.contains(Current))
2635 std::optional<MemoryAccess *> MaybeDeadAccess = getDomMemoryDef(
2636 KillingLocWrapper.MemDef, Current, KillingLocWrapper.MemLoc,
2637 KillingLocWrapper.UnderlyingObject, ScanLimit, WalkerStepLimit,
2638 isMemTerminatorInst(KillingLocWrapper.DefInst), PartialLimit,
2639 KillingLocWrapper.DefByInitializesAttr);
2641 if (!MaybeDeadAccess) {
2645 MemoryAccess *DeadAccess = *MaybeDeadAccess;
2646 LLVM_DEBUG(
dbgs() <<
" Checking if we can kill " << *DeadAccess);
2648 LLVM_DEBUG(
dbgs() <<
"\n ... adding incoming values to worklist\n");
2657 if (PostOrderNumbers[IncomingBlock] > PostOrderNumbers[PhiBlock])
2658 ToCheck.
insert(IncomingAccess);
2669 MemoryDefWrapper DeadDefWrapper(
2673 assert(DeadDefWrapper.DefinedLocations.size() == 1);
2674 MemoryLocationWrapper &DeadLocWrapper =
2675 DeadDefWrapper.DefinedLocations.front();
2678 NumGetDomMemoryDefPassed++;
2682 if (isMemTerminatorInst(KillingLocWrapper.DefInst)) {
2683 if (KillingLocWrapper.UnderlyingObject != DeadLocWrapper.UnderlyingObject)
2686 << *DeadLocWrapper.DefInst <<
"\n KILLER: "
2687 << *KillingLocWrapper.DefInst <<
'\n');
2693 int64_t KillingOffset = 0;
2694 int64_t DeadOffset = 0;
2695 OverwriteResult
OR =
2696 isOverwrite(KillingLocWrapper.DefInst, DeadLocWrapper.DefInst,
2697 KillingLocWrapper.MemLoc, DeadLocWrapper.MemLoc,
2698 KillingOffset, DeadOffset);
2699 if (OR == OW_MaybePartial) {
2700 auto &IOL = IOLs[DeadLocWrapper.DefInst->
getParent()];
2702 KillingOffset, DeadOffset,
2703 DeadLocWrapper.DefInst, IOL);
2711 if (DeadSI && KillingSI && DT.
dominates(DeadSI, KillingSI)) {
2713 KillingSI, DeadSI, KillingOffset, DeadOffset,
DL, BatchAA,
2717 DeadSI->setOperand(0, Merged);
2718 ++NumModifiedStores;
2720 DeletedKillingLoc =
true;
2725 auto I = IOLs.find(DeadSI->getParent());
2726 if (
I != IOLs.end())
2727 I->second.erase(DeadSI);
2732 if (OR == OW_Complete) {
2734 << *DeadLocWrapper.DefInst <<
"\n KILLER: "
2735 << *KillingLocWrapper.DefInst <<
'\n');
2743 assert(SkipStores.size() - OrigNumSkipStores ==
Deleted.size() &&
2744 "SkipStores and Deleted out of sync?");
2746 return {
Changed, DeletedKillingLoc};
2749bool DSEState::eliminateDeadDefs(
const MemoryDefWrapper &KillingDefWrapper) {
2750 if (KillingDefWrapper.DefinedLocations.empty()) {
2751 LLVM_DEBUG(
dbgs() <<
"Failed to find analyzable write location for "
2752 << *KillingDefWrapper.DefInst <<
"\n");
2756 bool MadeChange =
false;
2757 for (
auto &KillingLocWrapper : KillingDefWrapper.DefinedLocations) {
2759 << *KillingLocWrapper.MemDef <<
" ("
2760 << *KillingLocWrapper.DefInst <<
")\n");
2761 auto [
Changed, DeletedKillingLoc] = eliminateDeadDefs(KillingLocWrapper);
2765 if (!DeletedKillingLoc && storeIsNoop(KillingLocWrapper.MemDef,
2766 KillingLocWrapper.UnderlyingObject)) {
2768 << *KillingLocWrapper.DefInst <<
'\n');
2770 NumRedundantStores++;
2775 if (!DeletedKillingLoc &&
2776 tryFoldIntoCalloc(KillingLocWrapper.MemDef,
2777 KillingLocWrapper.UnderlyingObject)) {
2778 LLVM_DEBUG(
dbgs() <<
"DSE: Remove memset after forming calloc:\n"
2779 <<
" DEAD: " << *KillingLocWrapper.DefInst <<
'\n');
2792 bool MadeChange =
false;
2793 DSEState State(
F,
AA, MSSA, DT, PDT, TLI, CI);
2795 for (
unsigned I = 0;
I < State.MemDefs.size();
I++) {
2797 if (State.SkipStores.count(KillingDef))
2800 MemoryDefWrapper KillingDefWrapper(
2801 KillingDef, State.getLocForInst(KillingDef->
getMemoryInst(),
2803 MadeChange |= State.eliminateDeadDefs(KillingDefWrapper);
2807 for (
auto &KV : State.IOLs)
2808 MadeChange |= State.removePartiallyOverlappedStores(KV.second);
2810 MadeChange |= State.eliminateRedundantStoresOfExistingValues();
2811 MadeChange |= State.eliminateDeadWritesAtEndOfFunction();
2812 MadeChange |= State.eliminateRedundantStoresViaDominatingConditions();
2814 while (!State.ToRemove.empty()) {
2815 Instruction *DeadInst = State.ToRemove.pop_back_val();
2835#ifdef LLVM_ENABLE_STATS
2862 if (skipFunction(
F))
2865 AliasAnalysis &
AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
2866 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
2868 getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F);
2869 MemorySSA &MSSA = getAnalysis<MemorySSAWrapperPass>().getMSSA();
2871 getAnalysis<PostDominatorTreeWrapperPass>().getPostDomTree();
2872 CycleInfo &CI = getAnalysis<CycleInfoWrapperPass>().getResult();
2876#ifdef LLVM_ENABLE_STATS
2885 void getAnalysisUsage(AnalysisUsage &AU)
const override {
2901char DSELegacyPass::ID = 0;
2918 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 cl::opt< bool > EnableInitializesImprovement("enable-dse-initializes-attr-improvement", cl::init(true), cl::Hidden, cl::desc("Enable the initializes attr improvement in DSE"))
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 cl::opt< bool > EnablePartialStoreMerging("enable-dse-partial-store-merging", cl::init(true), cl::Hidden, cl::desc("Enable partial store merging in DSE"))
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 cl::opt< unsigned > MemorySSADefsPerBlockLimit("dse-memoryssa-defs-per-block-limit", cl::init(5000), cl::Hidden, cl::desc("The number of MemoryDefs we consider as candidates to eliminated " "other stores per basic block (default = 5000)"))
static Constant * tryToMergePartialOverlappingStores(StoreInst *KillingI, StoreInst *DeadI, int64_t KillingOffset, int64_t DeadOffset, const DataLayout &DL, BatchAAResults &AA, DominatorTree *DT)
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 cl::opt< unsigned > MemorySSAOtherBBStepCost("dse-memoryssa-otherbb-cost", cl::init(5), cl::Hidden, cl::desc("The cost of a step in a different basic " "block than the killing MemoryDef" "(default = 5)"))
static bool tryToShorten(Instruction *DeadI, int64_t &DeadStart, uint64_t &DeadSize, int64_t KillingStart, uint64_t KillingSize, bool IsOverwriteEnd)
static cl::opt< unsigned > MemorySSAScanLimit("dse-memoryssa-scanlimit", cl::init(150), cl::Hidden, cl::desc("The number of memory instructions to scan for " "dead store elimination (default = 150)"))
static bool isFuncLocalAndNotCaptured(Value *Arg, const CallBase *CB, EarliestEscapeAnalysis &EA)
static cl::opt< unsigned > MemorySSASameBBStepCost("dse-memoryssa-samebb-cost", cl::init(1), cl::Hidden, cl::desc("The cost of a step in the same basic block as the killing MemoryDef" "(default = 1)"))
static cl::opt< bool > EnablePartialOverwriteTracking("enable-dse-partial-overwrite-tracking", cl::init(true), cl::Hidden, cl::desc("Enable partial-overwrite tracking in DSE"))
static OverwriteResult isPartialOverwrite(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 cl::opt< unsigned > MemorySSAPartialStoreLimit("dse-memoryssa-partial-store-limit", cl::init(5), cl::Hidden, cl::desc("The maximum number candidates that only partially overwrite the " "killing MemoryDef to consider" " (default = 5)"))
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 cl::opt< unsigned > MaxDepthRecursion("dse-max-dom-cond-depth", cl::init(1024), cl::Hidden, cl::desc("Max dominator tree recursion depth for eliminating redundant " "stores via dominating conditions"))
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 cl::opt< unsigned > MemorySSAUpwardsStepLimit("dse-memoryssa-walklimit", cl::init(90), cl::Hidden, cl::desc("The maximum number of steps while walking upwards to find " "MemoryDefs that may be killed (default = 90)"))
static cl::opt< bool > OptimizeMemorySSA("dse-optimize-memoryssa", cl::init(true), cl::Hidden, cl::desc("Allow DSE to optimize memory accesses."))
static bool hasInitializesAttr(Instruction *I)
static cl::opt< unsigned > MemorySSAPathCheckLimit("dse-memoryssa-path-check-limit", cl::init(50), cl::Hidden, cl::desc("The maximum number of blocks to check when trying to prove that " "all paths to an exit go through a killing block (default = 50)"))
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.
const SmallVectorImpl< MachineOperand > & 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.
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.
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 * 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.
brc_match< Cond_t, match_bind< BasicBlock >, match_bind< BasicBlock > > m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F)
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
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...
initializer< Ty > init(const Ty &Val)
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
DomTreeNodeBase< BasicBlock > DomTreeNode
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.
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.
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...
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
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.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
AAResults AliasAnalysis
Temporary typedef for legacy code that uses a generic AliasAnalysis pointer or reference.
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.