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.");
119 cl::desc(
"Enable partial-overwrite tracking in DSE"));
124 cl::desc(
"Enable partial store merging in DSE"));
128 cl::desc(
"The number of memory instructions to scan for "
129 "dead store elimination (default = 150)"));
132 cl::desc(
"The maximum number of steps while walking upwards to find "
133 "MemoryDefs that may be killed (default = 90)"));
137 cl::desc(
"The maximum number candidates that only partially overwrite the "
138 "killing MemoryDef to consider"
143 cl::desc(
"The number of MemoryDefs we consider as candidates to eliminated "
144 "other stores per basic block (default = 5000)"));
149 "The cost of a step in the same basic block as the killing MemoryDef"
155 cl::desc(
"The cost of a step in a different basic "
156 "block than the killing MemoryDef"
161 cl::desc(
"The maximum number of blocks to check when trying to prove that "
162 "all paths to an exit go through a killing block (default = 50)"));
172 cl::desc(
"Allow DSE to optimize memory accesses."));
177 cl::desc(
"Enable the initializes attr improvement in DSE"));
181 cl::desc(
"Max dominator tree recursion depth for eliminating redundant "
182 "stores via dominating conditions"));
198 switch (
II->getIntrinsicID()) {
199 default:
return false;
200 case Intrinsic::memset:
201 case Intrinsic::memcpy:
202 case Intrinsic::memcpy_element_unordered_atomic:
203 case Intrinsic::memset_element_unordered_atomic:
238enum OverwriteResult {
242 OW_PartialEarlierWithFullLater,
258 if (KillingII ==
nullptr || DeadII ==
nullptr)
260 if (KillingII->getIntrinsicID() != DeadII->getIntrinsicID())
263 switch (KillingII->getIntrinsicID()) {
264 case Intrinsic::masked_store:
265 case Intrinsic::vp_store: {
267 auto *KillingTy = KillingII->getArgOperand(0)->getType();
268 auto *DeadTy = DeadII->getArgOperand(0)->getType();
269 if (
DL.getTypeSizeInBits(KillingTy) !=
DL.getTypeSizeInBits(DeadTy))
276 Value *KillingPtr = KillingII->getArgOperand(1);
277 Value *DeadPtr = DeadII->getArgOperand(1);
278 if (KillingPtr != DeadPtr && !
AA.isMustAlias(KillingPtr, DeadPtr))
280 if (KillingII->getIntrinsicID() == Intrinsic::masked_store) {
283 if (KillingII->getArgOperand(2) != DeadII->getArgOperand(2))
285 }
else if (KillingII->getIntrinsicID() == Intrinsic::vp_store) {
288 if (KillingII->getArgOperand(2) != DeadII->getArgOperand(2))
291 if (KillingII->getArgOperand(3) != DeadII->getArgOperand(3))
313 int64_t KillingOff, int64_t DeadOff,
324 KillingOff < int64_t(DeadOff + DeadSize) &&
325 int64_t(KillingOff + KillingSize) >= DeadOff) {
328 auto &IM = IOL[DeadI];
329 LLVM_DEBUG(
dbgs() <<
"DSE: Partial overwrite: DeadLoc [" << DeadOff <<
", "
330 << int64_t(DeadOff + DeadSize) <<
") KillingLoc ["
331 << KillingOff <<
", " << int64_t(KillingOff + KillingSize)
338 int64_t KillingIntStart = KillingOff;
339 int64_t KillingIntEnd = KillingOff + KillingSize;
343 auto ILI = IM.lower_bound(KillingIntStart);
344 if (ILI != IM.end() && ILI->second <= KillingIntEnd) {
348 KillingIntStart = std::min(KillingIntStart, ILI->second);
349 KillingIntEnd = std::max(KillingIntEnd, ILI->first);
358 while (ILI != IM.end() && ILI->second <= KillingIntEnd) {
359 assert(ILI->second > KillingIntStart &&
"Unexpected interval");
360 KillingIntEnd = std::max(KillingIntEnd, ILI->first);
365 IM[KillingIntEnd] = KillingIntStart;
368 if (ILI->second <= DeadOff && ILI->first >= int64_t(DeadOff + DeadSize)) {
369 LLVM_DEBUG(
dbgs() <<
"DSE: Full overwrite from partials: DeadLoc ["
370 << DeadOff <<
", " << int64_t(DeadOff + DeadSize)
371 <<
") Composite KillingLoc [" << ILI->second <<
", "
372 << ILI->first <<
")\n");
373 ++NumCompletePartials;
381 int64_t(DeadOff + DeadSize) > KillingOff &&
382 uint64_t(KillingOff - DeadOff) + KillingSize <= DeadSize) {
383 LLVM_DEBUG(
dbgs() <<
"DSE: Partial overwrite a dead load [" << DeadOff
384 <<
", " << int64_t(DeadOff + DeadSize)
385 <<
") by a killing store [" << KillingOff <<
", "
386 << int64_t(KillingOff + KillingSize) <<
")\n");
388 return OW_PartialEarlierWithFullLater;
401 (KillingOff > DeadOff && KillingOff < int64_t(DeadOff + DeadSize) &&
402 int64_t(KillingOff + KillingSize) >= int64_t(DeadOff + DeadSize)))
415 (KillingOff <= DeadOff && int64_t(KillingOff + KillingSize) > DeadOff)) {
416 assert(int64_t(KillingOff + KillingSize) < int64_t(DeadOff + DeadSize) &&
417 "Expect to be handled as OW_Complete");
437 using BlockAddressPair = std::pair<BasicBlock *, PHITransAddr>;
454 auto *MemLocPtr =
const_cast<Value *
>(MemLoc.
Ptr);
459 bool isFirstBlock =
true;
462 while (!WorkList.
empty()) {
474 assert(
B == SecondBB &&
"first block is not the store block");
476 isFirstBlock =
false;
482 for (; BI != EI; ++BI) {
484 if (
I->mayWriteToMemory() &&
I != SecondI)
490 "Should not hit the entry block because SI must be dominated by LI");
500 auto Inserted = Visited.
insert(std::make_pair(Pred, TranslatedPtr));
501 if (!Inserted.second) {
504 if (TranslatedPtr != Inserted.first->second)
509 WorkList.
push_back(std::make_pair(Pred, PredAddr));
518 bool IsOverwriteEnd) {
520 uint64_t DeadSliceSizeInBits = OldSizeInBits - NewSizeInBits;
527 uint64_t DeadSliceOffsetInBits = IsOverwriteEnd ? NewSizeInBits : 0;
528 auto SetDeadFragExpr = [](
auto *Assign,
532 uint64_t RelativeOffset = DeadFragment.OffsetInBits -
533 Assign->getExpression()
538 Assign->getExpression(), RelativeOffset, DeadFragment.SizeInBits)) {
539 Assign->setExpression(*
NewExpr);
546 DeadFragment.SizeInBits);
547 Assign->setExpression(Expr);
548 Assign->setKillLocation();
555 auto GetDeadLink = [&Ctx, &LinkToNothing]() {
558 return LinkToNothing;
564 std::optional<DIExpression::FragmentInfo> NewFragment;
566 DeadSliceSizeInBits, Assign,
573 Assign->setKillAddress();
574 Assign->setAssignId(GetDeadLink());
578 if (NewFragment->SizeInBits == 0)
582 auto *NewAssign =
static_cast<decltype(Assign)
>(Assign->clone());
583 NewAssign->insertAfter(Assign->getIterator());
584 NewAssign->setAssignId(GetDeadLink());
586 SetDeadFragExpr(NewAssign, *NewFragment);
587 NewAssign->setKillAddress();
601 for (
auto &Attr : OldAttrs) {
602 if (Attr.hasKindAsEnum()) {
603 switch (Attr.getKindAsEnum()) {
606 case Attribute::Alignment:
608 if (
isAligned(Attr.getAlignment().valueOrOne(), PtrOffset))
611 case Attribute::Dereferenceable:
612 case Attribute::DereferenceableOrNull:
616 case Attribute::NonNull:
617 case Attribute::NoUndef:
625 Intrinsic->removeParamAttrs(ArgNo, AttrsToRemove);
629 uint64_t &DeadSize, int64_t KillingStart,
630 uint64_t KillingSize,
bool IsOverwriteEnd) {
632 Align PrefAlign = DeadIntrinsic->getDestAlign().valueOrOne();
648 int64_t ToRemoveStart = 0;
652 if (IsOverwriteEnd) {
657 ToRemoveStart = KillingStart + Off;
658 if (DeadSize <=
uint64_t(ToRemoveStart - DeadStart))
660 ToRemoveSize = DeadSize -
uint64_t(ToRemoveStart - DeadStart);
662 ToRemoveStart = DeadStart;
664 "Not overlapping accesses?");
665 ToRemoveSize = KillingSize -
uint64_t(DeadStart - KillingStart);
670 if (ToRemoveSize <= (PrefAlign.
value() - Off))
672 ToRemoveSize -= PrefAlign.
value() - Off;
675 "Should preserve selected alignment");
678 assert(ToRemoveSize > 0 &&
"Shouldn't reach here if nothing to remove");
679 assert(DeadSize > ToRemoveSize &&
"Can't remove more than original size");
681 uint64_t NewSize = DeadSize - ToRemoveSize;
682 if (DeadIntrinsic->isAtomic()) {
685 const uint32_t ElementSize = DeadIntrinsic->getElementSizeInBytes();
686 if (0 != NewSize % ElementSize)
691 << (IsOverwriteEnd ?
"END" :
"BEGIN") <<
": " << *DeadI
692 <<
"\n KILLER [" << ToRemoveStart <<
", "
693 << int64_t(ToRemoveStart + ToRemoveSize) <<
")\n");
695 DeadIntrinsic->setLength(NewSize);
696 DeadIntrinsic->setDestAlignment(PrefAlign);
698 Value *OrigDest = DeadIntrinsic->getRawDest();
699 if (!IsOverwriteEnd) {
700 Value *Indices[1] = {
701 ConstantInt::get(DeadIntrinsic->getLength()->getType(), ToRemoveSize)};
705 NewDestGEP->
setDebugLoc(DeadIntrinsic->getDebugLoc());
706 DeadIntrinsic->setDest(NewDestGEP);
715 DeadStart += ToRemoveSize;
722 int64_t &DeadStart,
uint64_t &DeadSize) {
727 int64_t KillingStart = OII->second;
728 uint64_t KillingSize = OII->first - KillingStart;
730 assert(OII->first - KillingStart >= 0 &&
"Size expected to be positive");
732 if (KillingStart > DeadStart &&
735 (
uint64_t)(KillingStart - DeadStart) < DeadSize &&
738 KillingSize >= DeadSize - (
uint64_t)(KillingStart - DeadStart)) {
739 if (
tryToShorten(DeadI, DeadStart, DeadSize, KillingStart, KillingSize,
750 int64_t &DeadStart,
uint64_t &DeadSize) {
755 int64_t KillingStart = OII->second;
756 uint64_t KillingSize = OII->first - KillingStart;
758 assert(OII->first - KillingStart >= 0 &&
"Size expected to be positive");
760 if (KillingStart <= DeadStart &&
763 KillingSize > (
uint64_t)(DeadStart - KillingStart)) {
766 assert(KillingSize - (
uint64_t)(DeadStart - KillingStart) < DeadSize &&
767 "Should have been handled as OW_Complete");
768 if (
tryToShorten(DeadI, DeadStart, DeadSize, KillingStart, KillingSize,
779 int64_t KillingOffset, int64_t DeadOffset,
823 unsigned BitOffsetDiff = (KillingOffset - DeadOffset) * 8;
824 unsigned LShiftAmount =
825 DL.isBigEndian() ? DeadValue.
getBitWidth() - BitOffsetDiff - KillingBits
828 LShiftAmount + KillingBits);
831 APInt Merged = (DeadValue & ~Mask) | (KillingValue << LShiftAmount);
833 <<
"\n Killing: " << *KillingI
834 <<
"\n Merged Value: " << Merged <<
'\n');
841 switch (
II->getIntrinsicID()) {
842 case Intrinsic::lifetime_start:
843 case Intrinsic::lifetime_end:
844 case Intrinsic::invariant_end:
845 case Intrinsic::launder_invariant_group:
846 case Intrinsic::assume:
848 case Intrinsic::dbg_declare:
849 case Intrinsic::dbg_label:
850 case Intrinsic::dbg_value:
865 if (CB->onlyAccessesInaccessibleMemory())
870 if (DI->
mayThrow() && !DefVisibleToCaller)
892struct MemoryLocationWrapper {
893 MemoryLocationWrapper(MemoryLocation MemLoc, MemoryDef *MemDef,
894 bool DefByInitializesAttr)
895 : MemLoc(MemLoc), MemDef(MemDef),
896 DefByInitializesAttr(DefByInitializesAttr) {
897 assert(MemLoc.Ptr &&
"MemLoc should be not null");
899 DefInst = MemDef->getMemoryInst();
902 MemoryLocation MemLoc;
903 const Value *UnderlyingObject;
906 bool DefByInitializesAttr =
false;
911struct MemoryDefWrapper {
912 MemoryDefWrapper(MemoryDef *MemDef,
913 ArrayRef<std::pair<MemoryLocation, bool>> MemLocations) {
915 for (
auto &[MemLoc, DefByInitializesAttr] : MemLocations)
916 DefinedLocations.push_back(
917 MemoryLocationWrapper(MemLoc, MemDef, DefByInitializesAttr));
923struct ArgumentInitInfo {
925 bool IsDeadOrInvisibleOnUnwind;
926 ConstantRangeList Inits;
941 bool CallHasNoUnwindAttr) {
947 for (
const auto &Arg : Args) {
948 if (!CallHasNoUnwindAttr && !Arg.IsDeadOrInvisibleOnUnwind)
950 if (Arg.Inits.empty())
955 for (
auto &Arg : Args.drop_front())
956 IntersectedIntervals = IntersectedIntervals.
intersectWith(Arg.Inits);
958 return IntersectedIntervals;
966 EarliestEscapeAnalysis EA;
975 BatchAAResults BatchAA;
979 PostDominatorTree &PDT;
980 const TargetLibraryInfo &TLI;
981 const DataLayout &DL;
987 SmallPtrSet<MemoryAccess *, 4> SkipStores;
989 DenseMap<const Value *, bool> CapturedBeforeReturn;
992 DenseMap<const Value *, bool> InvisibleToCallerAfterRet;
993 DenseMap<const Value *, uint64_t> InvisibleToCallerAfterRetBounded;
995 SmallPtrSet<BasicBlock *, 16> ThrowingBlocks;
998 DenseMap<BasicBlock *, unsigned> PostOrderNumbers;
1002 MapVector<BasicBlock *, InstOverlapIntervalsTy> IOLs;
1006 bool AnyUnreachableExit;
1011 bool ShouldIterateEndOfFunctionDSE;
1014 SmallVector<Instruction *> ToRemove;
1018 PostDominatorTree &PDT,
const TargetLibraryInfo &TLI,
1019 const CycleInfo &CI);
1020 DSEState(
const DSEState &) =
delete;
1021 DSEState &operator=(
const DSEState &) =
delete;
1023 LocationSize strengthenLocationSize(
const Instruction *
I,
1024 LocationSize
Size)
const;
1034 OverwriteResult isOverwrite(
const Instruction *KillingI,
1035 const Instruction *DeadI,
1036 const MemoryLocation &KillingLoc,
1037 const MemoryLocation &DeadLoc,
1038 int64_t &KillingOff, int64_t &DeadOff);
1040 bool isInvisibleToCallerAfterRet(
const Value *V,
const Value *Ptr,
1041 const LocationSize StoreSize);
1043 bool isInvisibleToCallerOnUnwind(
const Value *V);
1045 std::optional<MemoryLocation> getLocForWrite(Instruction *
I)
const;
1050 getLocForInst(Instruction *
I,
bool ConsiderInitializesAttr);
1054 bool isRemovable(Instruction *
I);
1058 bool isCompleteOverwrite(
const MemoryLocation &DefLoc, Instruction *DefInst,
1059 Instruction *UseInst);
1062 bool isWriteAtEndOfFunction(MemoryDef *Def,
const MemoryLocation &DefLoc);
1067 std::optional<std::pair<MemoryLocation, bool>>
1068 getLocForTerminator(Instruction *
I)
const;
1072 bool isMemTerminatorInst(Instruction *
I)
const;
1076 bool isMemTerminator(
const MemoryLocation &Loc, Instruction *AccessI,
1077 Instruction *MaybeTerm);
1080 bool isReadClobber(
const MemoryLocation &DefLoc, Instruction *UseInst);
1087 bool isGuaranteedLoopIndependent(
const Instruction *Current,
1088 const Instruction *KillingDef,
1089 const MemoryLocation &CurrentLoc);
1094 bool isGuaranteedLoopInvariant(
const Value *Ptr);
1102 std::optional<MemoryAccess *>
1103 getDomMemoryDef(MemoryDef *KillingDef, MemoryAccess *StartAccess,
1104 const MemoryLocation &KillingLoc,
const Value *KillingUndObj,
1105 unsigned &ScanLimit,
unsigned &WalkerStepLimit,
1106 bool IsMemTerm,
unsigned &PartialLimit,
1107 bool IsInitializesAttrMemLoc);
1113 SmallPtrSetImpl<MemoryAccess *> *
Deleted =
nullptr);
1119 bool mayThrowBetween(Instruction *KillingI, Instruction *DeadI,
1120 const Value *KillingUndObj);
1127 bool isDSEBarrier(
const Value *KillingUndObj, Instruction *DeadI);
1131 bool eliminateDeadWritesAtEndOfFunction();
1135 bool tryFoldIntoCalloc(MemoryDef *Def,
const Value *DefUO);
1139 bool storeIsNoop(MemoryDef *Def,
const Value *DefUO);
1145 bool eliminateRedundantStoresOfExistingValues();
1150 bool eliminateRedundantStoresViaDominatingConditions();
1165 std::pair<bool, bool>
1166 eliminateDeadDefs(
const MemoryLocationWrapper &KillingLocWrapper);
1170 bool eliminateDeadDefs(
const MemoryDefWrapper &KillingDefWrapper);
1180 if (Visited.
insert(MA).second)
1197 :
F(
F),
AA(
AA), EA(DT, nullptr, &CI), BatchAA(
AA, &EA), MSSA(MSSA), DT(DT),
1198 PDT(PDT), TLI(TLI),
DL(
F.getDataLayout()), CI(CI) {
1203 PostOrderNumbers[BB] = PO++;
1206 if (
I.mayThrow() && !MA)
1207 ThrowingBlocks.insert(
I.getParent());
1211 (getLocForWrite(&
I) || isMemTerminatorInst(&
I) ||
1213 MemDefs.push_back(MD);
1220 if (AI.hasPassPointeeByValueCopyAttr()) {
1221 InvisibleToCallerAfterRet.insert({&AI, true});
1225 if (!AI.getType()->isPointerTy())
1229 if (Info.coversAllReachableMemory())
1230 InvisibleToCallerAfterRet.insert({&AI, true});
1231 else if (
uint64_t DeadBytes = Info.getNumberOfDeadBytes())
1232 InvisibleToCallerAfterRetBounded.insert({&AI, DeadBytes});
1236 return isa<UnreachableInst>(E->getTerminator());
1244 if (TLI.
has(
F) && (
F == LibFunc_memset_chk ||
F == LibFunc_memcpy_chk)) {
1260OverwriteResult DSEState::isOverwrite(
const Instruction *KillingI,
1261 const Instruction *DeadI,
1262 const MemoryLocation &KillingLoc,
1263 const MemoryLocation &DeadLoc,
1264 int64_t &KillingOff, int64_t &DeadOff) {
1268 if (!isGuaranteedLoopIndependent(DeadI, KillingI, DeadLoc))
1271 LocationSize KillingLocSize =
1272 strengthenLocationSize(KillingI, KillingLoc.
Size);
1280 if (DeadUndObj == KillingUndObj && KillingLocSize.
isPrecise() &&
1282 std::optional<TypeSize> KillingUndObjSize =
1284 if (KillingUndObjSize && *KillingUndObjSize == KillingLocSize.
getValue())
1295 if (KillingMemI && DeadMemI) {
1296 const Value *KillingV = KillingMemI->getLength();
1297 const Value *DeadV = DeadMemI->getLength();
1298 if (KillingV == DeadV && BatchAA.
isMustAlias(DeadLoc, KillingLoc))
1307 const TypeSize KillingSize = KillingLocSize.
getValue();
1316 AliasResult AAR = BatchAA.
alias(KillingLoc, DeadLoc);
1322 if (KillingSize >= DeadSize)
1329 if (Off >= 0 && (
uint64_t)Off + DeadSize <= KillingSize)
1335 if (DeadUndObj != KillingUndObj) {
1351 const Value *DeadBasePtr =
1353 const Value *KillingBasePtr =
1358 if (DeadBasePtr != KillingBasePtr)
1376 if (DeadOff >= KillingOff) {
1379 if (
uint64_t(DeadOff - KillingOff) + DeadSize <= KillingSize)
1383 else if ((
uint64_t)(DeadOff - KillingOff) < KillingSize)
1384 return OW_MaybePartial;
1388 else if ((
uint64_t)(KillingOff - DeadOff) < DeadSize) {
1389 return OW_MaybePartial;
1396bool DSEState::isInvisibleToCallerAfterRet(
const Value *V,
const Value *Ptr,
1397 const LocationSize StoreSize) {
1401 auto IBounded = InvisibleToCallerAfterRetBounded.find(V);
1402 if (IBounded != InvisibleToCallerAfterRetBounded.end()) {
1403 int64_t ValueOffset;
1404 [[maybe_unused]]
const Value *BaseValue =
1414 ValueOffset + StoreSize.
getValue() <= IBounded->second &&
1418 auto I = InvisibleToCallerAfterRet.insert({
V,
false});
1419 if (
I.second && isInvisibleToCallerOnUnwind(V) &&
isNoAliasCall(V))
1422 return I.first->second;
1425bool DSEState::isInvisibleToCallerOnUnwind(
const Value *V) {
1426 bool RequiresNoCaptureBeforeUnwind;
1429 if (!RequiresNoCaptureBeforeUnwind)
1432 auto I = CapturedBeforeReturn.insert({
V,
true});
1440 return !
I.first->second;
1443std::optional<MemoryLocation> DSEState::getLocForWrite(Instruction *
I)
const {
1444 if (!
I->mayWriteToMemory())
1445 return std::nullopt;
1454DSEState::getLocForInst(Instruction *
I,
bool ConsiderInitializesAttr) {
1456 if (isMemTerminatorInst(
I)) {
1457 if (
auto Loc = getLocForTerminator(
I))
1458 Locations.push_back(std::make_pair(Loc->first,
false));
1462 if (
auto Loc = getLocForWrite(
I))
1463 Locations.push_back(std::make_pair(*Loc,
false));
1465 if (ConsiderInitializesAttr) {
1466 for (
auto &MemLoc : getInitializesArgMemLoc(
I)) {
1467 Locations.push_back(std::make_pair(MemLoc,
true));
1473bool DSEState::isRemovable(Instruction *
I) {
1474 assert(getLocForWrite(
I) &&
"Must have analyzable write");
1478 return SI->isUnordered();
1483 return !
MI->isVolatile();
1487 if (CB->isLifetimeStartOrEnd())
1490 return CB->use_empty() && CB->willReturn() && CB->doesNotThrow() &&
1491 !CB->isTerminator();
1497bool DSEState::isCompleteOverwrite(
const MemoryLocation &DefLoc,
1498 Instruction *DefInst, Instruction *UseInst) {
1506 if (CB->onlyAccessesInaccessibleMemory())
1509 int64_t InstWriteOffset, DepWriteOffset;
1510 if (
auto CC = getLocForWrite(UseInst))
1511 return isOverwrite(UseInst, DefInst, *CC, DefLoc, InstWriteOffset,
1512 DepWriteOffset) == OW_Complete;
1516bool DSEState::isWriteAtEndOfFunction(MemoryDef *Def,
1517 const MemoryLocation &DefLoc) {
1519 << *
Def->getMemoryInst()
1520 <<
") is at the end the function \n");
1522 SmallPtrSet<MemoryAccess *, 8> Visited;
1525 for (
unsigned I = 0;
I < WorkList.
size();
I++) {
1531 MemoryAccess *UseAccess = WorkList[
I];
1536 if (!isGuaranteedLoopInvariant(DefLoc.
Ptr))
1545 if (isReadClobber(DefLoc, UseInst)) {
1546 LLVM_DEBUG(
dbgs() <<
" ... hit read clobber " << *UseInst <<
".\n");
1556std::optional<std::pair<MemoryLocation, bool>>
1557DSEState::getLocForTerminator(Instruction *
I)
const {
1559 if (CB->getIntrinsicID() == Intrinsic::lifetime_end)
1566 return std::nullopt;
1569bool DSEState::isMemTerminatorInst(Instruction *
I)
const {
1571 return CB && (CB->getIntrinsicID() == Intrinsic::lifetime_end ||
1575bool DSEState::isMemTerminator(
const MemoryLocation &Loc, Instruction *AccessI,
1576 Instruction *MaybeTerm) {
1577 std::optional<std::pair<MemoryLocation, bool>> MaybeTermLoc =
1578 getLocForTerminator(MaybeTerm);
1589 auto TermLoc = MaybeTermLoc->first;
1590 if (MaybeTermLoc->second) {
1594 int64_t InstWriteOffset = 0;
1595 int64_t DepWriteOffset = 0;
1596 return isOverwrite(MaybeTerm, AccessI, TermLoc, Loc, InstWriteOffset,
1597 DepWriteOffset) == OW_Complete;
1600bool DSEState::isReadClobber(
const MemoryLocation &DefLoc,
1601 Instruction *UseInst) {
1614 if (CB->onlyAccessesInaccessibleMemory())
1620bool DSEState::isGuaranteedLoopIndependent(
const Instruction *Current,
1621 const Instruction *KillingDef,
1622 const MemoryLocation &CurrentLoc) {
1633 return isGuaranteedLoopInvariant(CurrentLoc.
Ptr);
1636bool DSEState::isGuaranteedLoopInvariant(
const Value *Ptr) {
1639 if (
GEP->hasAllConstantIndices())
1643 return I->getParent()->isEntryBlock() || !CI.
getCycle(
I->getParent());
1648std::optional<MemoryAccess *> DSEState::getDomMemoryDef(
1649 MemoryDef *KillingDef, MemoryAccess *StartAccess,
1650 const MemoryLocation &KillingLoc,
const Value *KillingUndObj,
1651 unsigned &ScanLimit,
unsigned &WalkerStepLimit,
bool IsMemTerm,
1652 unsigned &PartialLimit,
bool IsInitializesAttrMemLoc) {
1653 if (ScanLimit == 0 || WalkerStepLimit == 0) {
1655 return std::nullopt;
1658 MemoryAccess *Current = StartAccess;
1672 std::optional<MemoryLocation> CurrentLoc;
1675 dbgs() <<
" visiting " << *Current;
1688 return std::nullopt;
1696 if (WalkerStepLimit <= StepCost) {
1698 return std::nullopt;
1700 WalkerStepLimit -= StepCost;
1714 if (
canSkipDef(CurrentDef, !isInvisibleToCallerOnUnwind(KillingUndObj))) {
1715 CanOptimize =
false;
1721 if (mayThrowBetween(KillingI, CurrentI, KillingUndObj)) {
1723 return std::nullopt;
1728 if (isDSEBarrier(KillingUndObj, CurrentI)) {
1730 return std::nullopt;
1738 return std::nullopt;
1741 if (
any_of(Current->
uses(), [
this, &KillingLoc, StartAccess](Use &U) {
1742 if (auto *UseOrDef = dyn_cast<MemoryUseOrDef>(U.getUser()))
1743 return !MSSA.dominates(StartAccess, UseOrDef) &&
1744 isReadClobber(KillingLoc, UseOrDef->getMemoryInst());
1748 return std::nullopt;
1753 CurrentLoc = getLocForWrite(CurrentI);
1754 if (!CurrentLoc || !isRemovable(CurrentI)) {
1755 CanOptimize =
false;
1762 if (!isGuaranteedLoopIndependent(CurrentI, KillingI, *CurrentLoc)) {
1764 CanOptimize =
false;
1772 if (!isMemTerminator(*CurrentLoc, CurrentI, KillingI)) {
1773 CanOptimize =
false;
1777 int64_t KillingOffset = 0;
1778 int64_t DeadOffset = 0;
1779 auto OR = isOverwrite(KillingI, CurrentI, KillingLoc, *CurrentLoc,
1780 KillingOffset, DeadOffset);
1786 (OR == OW_Complete || OR == OW_MaybePartial))
1792 CanOptimize =
false;
1797 if (OR == OW_Unknown || OR == OW_None)
1799 else if (OR == OW_MaybePartial) {
1804 if (PartialLimit <= 1) {
1805 WalkerStepLimit -= 1;
1806 LLVM_DEBUG(
dbgs() <<
" ... reached partial limit ... continue with "
1820 SmallPtrSet<Instruction *, 16> KillingDefs;
1822 MemoryAccess *MaybeDeadAccess = Current;
1823 MemoryLocation MaybeDeadLoc = *CurrentLoc;
1825 LLVM_DEBUG(
dbgs() <<
" Checking for reads of " << *MaybeDeadAccess <<
" ("
1826 << *MaybeDeadI <<
")\n");
1829 SmallPtrSet<MemoryAccess *, 32> Visited;
1833 for (
unsigned I = 0;
I < WorkList.
size();
I++) {
1834 MemoryAccess *UseAccess = WorkList[
I];
1838 if (ScanLimit < (WorkList.
size() -
I)) {
1840 return std::nullopt;
1843 NumDomMemDefChecks++;
1846 if (
any_of(KillingDefs, [
this, UseAccess](Instruction *KI) {
1849 LLVM_DEBUG(
dbgs() <<
" ... skipping, dominated by killing block\n");
1860 if (
any_of(KillingDefs, [
this, UseInst](Instruction *KI) {
1863 LLVM_DEBUG(
dbgs() <<
" ... skipping, dominated by killing def\n");
1869 if (isMemTerminator(MaybeDeadLoc, MaybeDeadI, UseInst)) {
1872 <<
" ... skipping, memterminator invalidates following accesses\n");
1882 if (UseInst->
mayThrow() && !isInvisibleToCallerOnUnwind(KillingUndObj)) {
1884 return std::nullopt;
1891 bool IsKillingDefFromInitAttr =
false;
1892 if (IsInitializesAttrMemLoc) {
1893 if (KillingI == UseInst &&
1895 IsKillingDefFromInitAttr =
true;
1898 if (isReadClobber(MaybeDeadLoc, UseInst) && !IsKillingDefFromInitAttr) {
1900 return std::nullopt;
1906 if (MaybeDeadAccess == UseAccess &&
1907 !isGuaranteedLoopInvariant(MaybeDeadLoc.
Ptr)) {
1908 LLVM_DEBUG(
dbgs() <<
" ... found not loop invariant self access\n");
1909 return std::nullopt;
1915 if (KillingDef == UseAccess || MaybeDeadAccess == UseAccess) {
1931 if (isCompleteOverwrite(MaybeDeadLoc, MaybeDeadI, UseInst)) {
1933 if (PostOrderNumbers.
find(MaybeKillingBlock)->second <
1934 PostOrderNumbers.
find(MaybeDeadAccess->
getBlock())->second) {
1935 if (!isInvisibleToCallerAfterRet(KillingUndObj, KillingLoc.
Ptr,
1938 <<
" ... found killing def " << *UseInst <<
"\n");
1939 KillingDefs.
insert(UseInst);
1943 <<
" ... found preceeding def " << *UseInst <<
"\n");
1944 return std::nullopt;
1954 if (!isInvisibleToCallerAfterRet(KillingUndObj, KillingLoc.
Ptr,
1956 SmallPtrSet<BasicBlock *, 16> KillingBlocks;
1957 for (Instruction *KD : KillingDefs)
1958 KillingBlocks.
insert(KD->getParent());
1960 "Expected at least a single killing block");
1974 if (!AnyUnreachableExit)
1975 return std::nullopt;
1979 CommonPred =
nullptr;
1983 if (KillingBlocks.
count(CommonPred))
1984 return {MaybeDeadAccess};
1986 SetVector<BasicBlock *> WorkList;
1990 WorkList.
insert(CommonPred);
1992 for (BasicBlock *R : PDT.
roots()) {
2000 for (
unsigned I = 0;
I < WorkList.
size();
I++) {
2003 if (KillingBlocks.
count(Current))
2005 if (Current == MaybeDeadAccess->
getBlock())
2006 return std::nullopt;
2016 return std::nullopt;
2023 return {MaybeDeadAccess};
2026void DSEState::deleteDeadInstruction(Instruction *SI,
2027 SmallPtrSetImpl<MemoryAccess *> *
Deleted) {
2028 MemorySSAUpdater Updater(&MSSA);
2033 while (!NowDeadInsts.
empty()) {
2047 SkipStores.insert(MD);
2051 if (
SI->getValueOperand()->getType()->isPointerTy()) {
2053 if (CapturedBeforeReturn.erase(UO))
2054 ShouldIterateEndOfFunctionDSE =
true;
2055 InvisibleToCallerAfterRet.erase(UO);
2056 InvisibleToCallerAfterRetBounded.erase(UO);
2061 Updater.removeMemoryAccess(MA);
2065 if (
I != IOLs.end())
2066 I->second.erase(DeadInst);
2068 for (Use &O : DeadInst->
operands())
2088bool DSEState::mayThrowBetween(Instruction *KillingI, Instruction *DeadI,
2089 const Value *KillingUndObj) {
2093 if (KillingUndObj && isInvisibleToCallerOnUnwind(KillingUndObj))
2097 return ThrowingBlocks.count(KillingI->
getParent());
2098 return !ThrowingBlocks.empty();
2101bool DSEState::isDSEBarrier(
const Value *KillingUndObj, Instruction *DeadI) {
2104 if (DeadI->
mayThrow() && !isInvisibleToCallerOnUnwind(KillingUndObj))
2124bool DSEState::eliminateDeadWritesAtEndOfFunction() {
2125 bool MadeChange =
false;
2127 dbgs() <<
"Trying to eliminate MemoryDefs at the end of the function\n");
2129 ShouldIterateEndOfFunctionDSE =
false;
2131 if (SkipStores.contains(Def))
2135 auto DefLoc = getLocForWrite(DefI);
2136 if (!DefLoc || !isRemovable(DefI)) {
2138 "instruction not removable.\n");
2148 if (!isInvisibleToCallerAfterRet(UO, DefLoc->
Ptr, DefLoc->
Size))
2151 if (isWriteAtEndOfFunction(Def, *DefLoc)) {
2153 LLVM_DEBUG(
dbgs() <<
" ... MemoryDef is not accessed until the end "
2154 "of the function\n");
2160 }
while (ShouldIterateEndOfFunctionDSE);
2164bool DSEState::eliminateRedundantStoresViaDominatingConditions() {
2165 bool MadeChange =
false;
2166 LLVM_DEBUG(
dbgs() <<
"Trying to eliminate MemoryDefs whose value being "
2167 "written is implied by a dominating condition\n");
2169 using ConditionInfo = std::pair<Value *, Value *>;
2170 using ScopedHTType = ScopedHashTable<ConditionInfo, Instruction *>;
2174 ScopedHTType ActiveConditions;
2175 auto GetDominatingCondition = [&](
BasicBlock *BB)
2176 -> std::optional<std::tuple<ConditionInfo, Instruction *, BasicBlock *>> {
2179 return std::nullopt;
2184 if (BI->getSuccessor(0) == BI->getSuccessor(1))
2185 return std::nullopt;
2189 Value *StorePtr, *StoreVal;
2190 if (!
match(BI->getCondition(),
2194 return std::nullopt;
2200 return std::nullopt;
2202 unsigned ImpliedSuccIdx = Pred == ICmpInst::ICMP_EQ ? 0 : 1;
2203 BasicBlock *ImpliedSucc = BI->getSuccessor(ImpliedSuccIdx);
2204 return {{ConditionInfo(StorePtr, StoreVal), ICmpL, ImpliedSucc}};
2214 for (MemoryDef &Def :
2217 if (!SI || !
SI->isUnordered())
2221 {
SI->getPointerOperand(),
SI->getValueOperand()});
2229 MemoryAccess *ClobberingAccess =
2231 if (MSSA.
dominates(ClobberingAccess, LoadAccess)) {
2233 <<
"Removing No-Op Store:\n DEAD: " << *SI <<
'\n');
2235 NumRedundantStores++;
2242 auto MaybeCondition = GetDominatingCondition(BB);
2246 ScopedHTType::ScopeTy
Scope(ActiveConditions);
2247 if (MaybeCondition) {
2248 const auto &[
Cond, LI, ImpliedSucc] = *MaybeCondition;
2249 if (DT.
dominates(BasicBlockEdge(BB, ImpliedSucc), Child->getBlock())) {
2253 ActiveConditions.insert(
Cond, LI);
2260 Self(Child,
Depth + 1, Self);
2270bool DSEState::tryFoldIntoCalloc(MemoryDef *Def,
const Value *DefUO) {
2277 if (!StoredConstant || !StoredConstant->
isNullValue())
2280 if (!isRemovable(DefI))
2284 if (
F.hasFnAttribute(Attribute::SanitizeMemory) ||
2285 F.hasFnAttribute(Attribute::SanitizeAddress) ||
2286 F.hasFnAttribute(Attribute::SanitizeHWAddress) ||
F.getName() ==
"calloc")
2291 auto *InnerCallee =
Malloc->getCalledFunction();
2295 StringRef ZeroedVariantName;
2296 if (Func != LibFunc_malloc || !TLI.
has(Func)) {
2301 if (ZeroedVariantName.
empty())
2310 auto shouldCreateCalloc = [](CallInst *
Malloc, CallInst *Memset) {
2313 auto *MallocBB =
Malloc->getParent(), *MemsetBB = Memset->getParent();
2314 if (MallocBB == MemsetBB)
2316 auto *Ptr = Memset->getArgOperand(0);
2317 auto *TI = MallocBB->getTerminator();
2323 if (MemsetBB != FalseBB)
2334 assert(Func == LibFunc_malloc || !ZeroedVariantName.
empty());
2335 Value *Calloc =
nullptr;
2336 if (!ZeroedVariantName.
empty()) {
2337 LLVMContext &Ctx =
Malloc->getContext();
2338 AttributeList
Attrs = InnerCallee->getAttributes();
2340 Attrs.getFnAttr(Attribute::AllocKind).getAllocKind() |
2341 AllocFnKind::Zeroed;
2344 Attrs.addFnAttribute(Ctx, Attribute::getWithAllocKind(Ctx, AllocKind))
2345 .removeFnAttribute(Ctx,
"alloc-variant-zeroed");
2346 FunctionCallee ZeroedVariant =
Malloc->getModule()->getOrInsertFunction(
2347 ZeroedVariantName, InnerCallee->getFunctionType(), Attrs);
2349 ->setCallingConv(
Malloc->getCallingConv());
2352 CallInst *CI = IRB.CreateCall(ZeroedVariant, Args, ZeroedVariantName);
2356 Type *SizeTTy =
Malloc->getArgOperand(0)->getType();
2357 Calloc =
emitCalloc(ConstantInt::get(SizeTTy, 1),
Malloc->getArgOperand(0),
2358 IRB, TLI,
Malloc->getType()->getPointerAddressSpace());
2363 if (MDNode *MD =
Malloc->getMetadata(LLVMContext::MD_alloc_token))
2366 MemorySSAUpdater Updater(&MSSA);
2368 nullptr, MallocDef);
2370 Updater.insertDef(NewAccessMD,
true);
2371 Malloc->replaceAllUsesWith(Calloc);
2376bool DSEState::storeIsNoop(MemoryDef *Def,
const Value *DefUO) {
2380 Constant *StoredConstant =
nullptr;
2388 if (!isRemovable(DefI))
2391 if (StoredConstant) {
2396 if (InitC && InitC == StoredConstant)
2405 if (LoadI->getPointerOperand() ==
Store->getOperand(1)) {
2409 if (LoadAccess ==
Def->getDefiningAccess())
2415 SetVector<MemoryAccess *> ToCheck;
2416 MemoryAccess *Current =
2424 for (
unsigned I = 1;
I < ToCheck.
size(); ++
I) {
2425 Current = ToCheck[
I];
2428 for (
auto &Use : PhiAccess->incoming_values())
2440 if (LoadAccess != Current)
2452 for (
auto OI : IOL) {
2454 MemoryLocation Loc = *getLocForWrite(DeadI);
2455 assert(isRemovable(DeadI) &&
"Expect only removable instruction");
2458 int64_t DeadStart = 0;
2463 if (IntervalMap.empty())
2470bool DSEState::eliminateRedundantStoresOfExistingValues() {
2471 bool MadeChange =
false;
2472 LLVM_DEBUG(
dbgs() <<
"Trying to eliminate MemoryDefs that write the "
2473 "already existing value\n");
2474 for (
auto *Def : MemDefs) {
2479 auto MaybeDefLoc = getLocForWrite(DefInst);
2480 if (!MaybeDefLoc || !isRemovable(DefInst))
2483 MemoryDef *UpperDef;
2487 if (
Def->isOptimized())
2495 auto IsRedundantStore = [&]() {
2503 auto UpperLoc = getLocForWrite(UpperInst);
2506 int64_t InstWriteOffset = 0;
2507 int64_t DepWriteOffset = 0;
2508 auto OR = isOverwrite(UpperInst, DefInst, *UpperLoc, *MaybeDefLoc,
2509 InstWriteOffset, DepWriteOffset);
2511 return StoredByte && StoredByte == MemSetI->getOperand(1) &&
2518 if (!IsRedundantStore() || isReadClobber(*MaybeDefLoc, DefInst))
2520 LLVM_DEBUG(
dbgs() <<
"DSE: Remove No-Op Store:\n DEAD: " << *DefInst
2523 NumRedundantStores++;
2530DSEState::getInitializesArgMemLoc(
const Instruction *
I) {
2536 SmallMapVector<Value *, SmallVector<ArgumentInitInfo, 2>, 2>
Arguments;
2542 ConstantRangeList Inits;
2554 Inits = ConstantRangeList();
2562 bool IsDeadOrInvisibleOnUnwind =
2565 ArgumentInitInfo InitInfo{Idx, IsDeadOrInvisibleOnUnwind, Inits};
2566 bool FoundAliasing =
false;
2567 for (
auto &[Arg, AliasList] :
Arguments) {
2573 FoundAliasing =
true;
2574 AliasList.push_back(InitInfo);
2579 FoundAliasing =
true;
2580 AliasList.push_back(ArgumentInitInfo{Idx, IsDeadOrInvisibleOnUnwind,
2581 ConstantRangeList()});
2590 auto IntersectedRanges =
2592 if (IntersectedRanges.empty())
2595 for (
const auto &Arg : Args) {
2596 for (
const auto &
Range : IntersectedRanges) {
2610std::pair<bool, bool>
2611DSEState::eliminateDeadDefs(
const MemoryLocationWrapper &KillingLocWrapper) {
2613 bool DeletedKillingLoc =
false;
2619 SmallSetVector<MemoryAccess *, 8> ToCheck;
2623 SmallPtrSet<MemoryAccess *, 8>
Deleted;
2624 [[maybe_unused]]
unsigned OrigNumSkipStores = SkipStores.size();
2629 for (
unsigned I = 0;
I < ToCheck.
size();
I++) {
2630 MemoryAccess *Current = ToCheck[
I];
2631 if (
Deleted.contains(Current))
2633 std::optional<MemoryAccess *> MaybeDeadAccess = getDomMemoryDef(
2634 KillingLocWrapper.MemDef, Current, KillingLocWrapper.MemLoc,
2635 KillingLocWrapper.UnderlyingObject, ScanLimit, WalkerStepLimit,
2636 isMemTerminatorInst(KillingLocWrapper.DefInst), PartialLimit,
2637 KillingLocWrapper.DefByInitializesAttr);
2639 if (!MaybeDeadAccess) {
2643 MemoryAccess *DeadAccess = *MaybeDeadAccess;
2644 LLVM_DEBUG(
dbgs() <<
" Checking if we can kill " << *DeadAccess);
2646 LLVM_DEBUG(
dbgs() <<
"\n ... adding incoming values to worklist\n");
2655 if (PostOrderNumbers[IncomingBlock] > PostOrderNumbers[PhiBlock])
2656 ToCheck.
insert(IncomingAccess);
2667 MemoryDefWrapper DeadDefWrapper(
2671 assert(DeadDefWrapper.DefinedLocations.size() == 1);
2672 MemoryLocationWrapper &DeadLocWrapper =
2673 DeadDefWrapper.DefinedLocations.front();
2676 NumGetDomMemoryDefPassed++;
2680 if (isMemTerminatorInst(KillingLocWrapper.DefInst)) {
2681 if (KillingLocWrapper.UnderlyingObject != DeadLocWrapper.UnderlyingObject)
2684 << *DeadLocWrapper.DefInst <<
"\n KILLER: "
2685 << *KillingLocWrapper.DefInst <<
'\n');
2691 int64_t KillingOffset = 0;
2692 int64_t DeadOffset = 0;
2693 OverwriteResult
OR =
2694 isOverwrite(KillingLocWrapper.DefInst, DeadLocWrapper.DefInst,
2695 KillingLocWrapper.MemLoc, DeadLocWrapper.MemLoc,
2696 KillingOffset, DeadOffset);
2697 if (OR == OW_MaybePartial) {
2698 auto &IOL = IOLs[DeadLocWrapper.DefInst->
getParent()];
2700 KillingOffset, DeadOffset,
2701 DeadLocWrapper.DefInst, IOL);
2709 if (DeadSI && KillingSI && DT.
dominates(DeadSI, KillingSI)) {
2711 KillingSI, DeadSI, KillingOffset, DeadOffset,
DL, BatchAA,
2715 DeadSI->setOperand(0, Merged);
2716 ++NumModifiedStores;
2718 DeletedKillingLoc =
true;
2723 auto I = IOLs.find(DeadSI->getParent());
2724 if (
I != IOLs.end())
2725 I->second.erase(DeadSI);
2730 if (OR == OW_Complete) {
2732 << *DeadLocWrapper.DefInst <<
"\n KILLER: "
2733 << *KillingLocWrapper.DefInst <<
'\n');
2741 assert(SkipStores.size() - OrigNumSkipStores ==
Deleted.size() &&
2742 "SkipStores and Deleted out of sync?");
2744 return {
Changed, DeletedKillingLoc};
2747bool DSEState::eliminateDeadDefs(
const MemoryDefWrapper &KillingDefWrapper) {
2748 if (KillingDefWrapper.DefinedLocations.empty()) {
2749 LLVM_DEBUG(
dbgs() <<
"Failed to find analyzable write location for "
2750 << *KillingDefWrapper.DefInst <<
"\n");
2754 bool MadeChange =
false;
2755 for (
auto &KillingLocWrapper : KillingDefWrapper.DefinedLocations) {
2757 << *KillingLocWrapper.MemDef <<
" ("
2758 << *KillingLocWrapper.DefInst <<
")\n");
2759 auto [
Changed, DeletedKillingLoc] = eliminateDeadDefs(KillingLocWrapper);
2763 if (!DeletedKillingLoc && storeIsNoop(KillingLocWrapper.MemDef,
2764 KillingLocWrapper.UnderlyingObject)) {
2766 << *KillingLocWrapper.DefInst <<
'\n');
2768 NumRedundantStores++;
2773 if (!DeletedKillingLoc &&
2774 tryFoldIntoCalloc(KillingLocWrapper.MemDef,
2775 KillingLocWrapper.UnderlyingObject)) {
2776 LLVM_DEBUG(
dbgs() <<
"DSE: Remove memset after forming calloc:\n"
2777 <<
" DEAD: " << *KillingLocWrapper.DefInst <<
'\n');
2790 bool MadeChange =
false;
2791 DSEState State(
F,
AA, MSSA, DT, PDT, TLI, CI);
2793 for (
unsigned I = 0;
I < State.MemDefs.size();
I++) {
2795 if (State.SkipStores.count(KillingDef))
2798 MemoryDefWrapper KillingDefWrapper(
2799 KillingDef, State.getLocForInst(KillingDef->
getMemoryInst(),
2801 MadeChange |= State.eliminateDeadDefs(KillingDefWrapper);
2805 for (
auto &KV : State.IOLs)
2806 MadeChange |= State.removePartiallyOverlappedStores(KV.second);
2808 MadeChange |= State.eliminateRedundantStoresOfExistingValues();
2809 MadeChange |= State.eliminateDeadWritesAtEndOfFunction();
2810 MadeChange |= State.eliminateRedundantStoresViaDominatingConditions();
2812 while (!State.ToRemove.empty()) {
2813 Instruction *DeadInst = State.ToRemove.pop_back_val();
2833#ifdef LLVM_ENABLE_STATS
2860 if (skipFunction(
F))
2863 AliasAnalysis &
AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
2864 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
2866 getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F);
2867 MemorySSA &MSSA = getAnalysis<MemorySSAWrapperPass>().getMSSA();
2869 getAnalysis<PostDominatorTreeWrapperPass>().getPostDomTree();
2870 CycleInfo &CI = getAnalysis<CycleInfoWrapperPass>().getResult();
2874#ifdef LLVM_ENABLE_STATS
2883 void getAnalysisUsage(AnalysisUsage &AU)
const override {
2899char DSELegacyPass::ID = 0;
2916 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 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.
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...
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.
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.