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 uint64_t NewSizeInBits,
bool IsOverwriteEnd) {
519 uint64_t DeadSliceSizeInBits = OldSizeInBits - NewSizeInBits;
521 OldOffsetInBits + (IsOverwriteEnd ? NewSizeInBits : 0);
522 auto SetDeadFragExpr = [](
auto *Assign,
526 uint64_t RelativeOffset = DeadFragment.OffsetInBits -
527 Assign->getExpression()
532 Assign->getExpression(), RelativeOffset, DeadFragment.SizeInBits)) {
533 Assign->setExpression(*
NewExpr);
540 DeadFragment.SizeInBits);
541 Assign->setExpression(Expr);
542 Assign->setKillLocation();
549 auto GetDeadLink = [&Ctx, &LinkToNothing]() {
552 return LinkToNothing;
558 std::optional<DIExpression::FragmentInfo> NewFragment;
560 DeadSliceSizeInBits, Assign,
565 Assign->setKillAddress();
566 Assign->setAssignId(GetDeadLink());
570 if (NewFragment->SizeInBits == 0)
574 auto *NewAssign =
static_cast<decltype(Assign)
>(Assign->clone());
575 NewAssign->insertAfter(Assign->getIterator());
576 NewAssign->setAssignId(GetDeadLink());
578 SetDeadFragExpr(NewAssign, *NewFragment);
579 NewAssign->setKillAddress();
593 for (
auto &Attr : OldAttrs) {
594 if (Attr.hasKindAsEnum()) {
595 switch (Attr.getKindAsEnum()) {
598 case Attribute::Alignment:
600 if (
isAligned(Attr.getAlignment().valueOrOne(), PtrOffset))
603 case Attribute::Dereferenceable:
604 case Attribute::DereferenceableOrNull:
608 case Attribute::NonNull:
609 case Attribute::NoUndef:
617 Intrinsic->removeParamAttrs(ArgNo, AttrsToRemove);
621 uint64_t &DeadSize, int64_t KillingStart,
622 uint64_t KillingSize,
bool IsOverwriteEnd) {
624 Align PrefAlign = DeadIntrinsic->getDestAlign().valueOrOne();
640 int64_t ToRemoveStart = 0;
644 if (IsOverwriteEnd) {
649 ToRemoveStart = KillingStart + Off;
650 if (DeadSize <=
uint64_t(ToRemoveStart - DeadStart))
652 ToRemoveSize = DeadSize -
uint64_t(ToRemoveStart - DeadStart);
654 ToRemoveStart = DeadStart;
656 "Not overlapping accesses?");
657 ToRemoveSize = KillingSize -
uint64_t(DeadStart - KillingStart);
662 if (ToRemoveSize <= (PrefAlign.
value() - Off))
664 ToRemoveSize -= PrefAlign.
value() - Off;
667 "Should preserve selected alignment");
670 assert(ToRemoveSize > 0 &&
"Shouldn't reach here if nothing to remove");
671 assert(DeadSize > ToRemoveSize &&
"Can't remove more than original size");
673 uint64_t NewSize = DeadSize - ToRemoveSize;
674 if (DeadIntrinsic->isAtomic()) {
677 const uint32_t ElementSize = DeadIntrinsic->getElementSizeInBytes();
678 if (0 != NewSize % ElementSize)
683 << (IsOverwriteEnd ?
"END" :
"BEGIN") <<
": " << *DeadI
684 <<
"\n KILLER [" << ToRemoveStart <<
", "
685 << int64_t(ToRemoveStart + ToRemoveSize) <<
")\n");
687 DeadIntrinsic->setLength(NewSize);
688 DeadIntrinsic->setDestAlignment(PrefAlign);
690 Value *OrigDest = DeadIntrinsic->getRawDest();
691 if (!IsOverwriteEnd) {
692 Value *Indices[1] = {
693 ConstantInt::get(DeadIntrinsic->getLength()->getType(), ToRemoveSize)};
697 NewDestGEP->
setDebugLoc(DeadIntrinsic->getDebugLoc());
698 DeadIntrinsic->setDest(NewDestGEP);
708 DeadStart += ToRemoveSize;
715 int64_t &DeadStart,
uint64_t &DeadSize) {
720 int64_t KillingStart = OII->second;
721 uint64_t KillingSize = OII->first - KillingStart;
723 assert(OII->first - KillingStart >= 0 &&
"Size expected to be positive");
725 if (KillingStart > DeadStart &&
728 (
uint64_t)(KillingStart - DeadStart) < DeadSize &&
731 KillingSize >= DeadSize - (
uint64_t)(KillingStart - DeadStart)) {
732 if (
tryToShorten(DeadI, DeadStart, DeadSize, KillingStart, KillingSize,
743 int64_t &DeadStart,
uint64_t &DeadSize) {
748 int64_t KillingStart = OII->second;
749 uint64_t KillingSize = OII->first - KillingStart;
751 assert(OII->first - KillingStart >= 0 &&
"Size expected to be positive");
753 if (KillingStart <= DeadStart &&
756 KillingSize > (
uint64_t)(DeadStart - KillingStart)) {
759 assert(KillingSize - (
uint64_t)(DeadStart - KillingStart) < DeadSize &&
760 "Should have been handled as OW_Complete");
761 if (
tryToShorten(DeadI, DeadStart, DeadSize, KillingStart, KillingSize,
772 int64_t KillingOffset, int64_t DeadOffset,
799 unsigned BitOffsetDiff = (KillingOffset - DeadOffset) * 8;
800 unsigned LShiftAmount =
801 DL.isBigEndian() ? DeadValue.
getBitWidth() - BitOffsetDiff - KillingBits
804 LShiftAmount + KillingBits);
807 APInt Merged = (DeadValue & ~Mask) | (KillingValue << LShiftAmount);
809 <<
"\n Killing: " << *KillingI
810 <<
"\n Merged Value: " << Merged <<
'\n');
819 switch (
II->getIntrinsicID()) {
820 case Intrinsic::lifetime_start:
821 case Intrinsic::lifetime_end:
822 case Intrinsic::invariant_end:
823 case Intrinsic::launder_invariant_group:
824 case Intrinsic::assume:
826 case Intrinsic::dbg_declare:
827 case Intrinsic::dbg_label:
828 case Intrinsic::dbg_value:
843 if (CB->onlyAccessesInaccessibleMemory())
848 if (DI->
mayThrow() && !DefVisibleToCaller)
870struct MemoryLocationWrapper {
871 MemoryLocationWrapper(MemoryLocation MemLoc, MemoryDef *MemDef,
872 bool DefByInitializesAttr)
873 : MemLoc(MemLoc), MemDef(MemDef),
874 DefByInitializesAttr(DefByInitializesAttr) {
875 assert(MemLoc.Ptr &&
"MemLoc should be not null");
877 DefInst = MemDef->getMemoryInst();
880 MemoryLocation MemLoc;
881 const Value *UnderlyingObject;
884 bool DefByInitializesAttr =
false;
889struct MemoryDefWrapper {
890 MemoryDefWrapper(MemoryDef *MemDef,
891 ArrayRef<std::pair<MemoryLocation, bool>> MemLocations) {
893 for (
auto &[MemLoc, DefByInitializesAttr] : MemLocations)
894 DefinedLocations.push_back(
895 MemoryLocationWrapper(MemLoc, MemDef, DefByInitializesAttr));
901struct ArgumentInitInfo {
903 bool IsDeadOrInvisibleOnUnwind;
904 ConstantRangeList Inits;
919 bool CallHasNoUnwindAttr) {
925 for (
const auto &Arg : Args) {
926 if (!CallHasNoUnwindAttr && !Arg.IsDeadOrInvisibleOnUnwind)
928 if (Arg.Inits.empty())
933 for (
auto &Arg : Args.drop_front())
934 IntersectedIntervals = IntersectedIntervals.
intersectWith(Arg.Inits);
936 return IntersectedIntervals;
944 EarliestEscapeAnalysis EA;
953 BatchAAResults BatchAA;
957 PostDominatorTree &PDT;
958 const TargetLibraryInfo &TLI;
959 const DataLayout &DL;
965 SmallPtrSet<MemoryAccess *, 4> SkipStores;
967 DenseMap<const Value *, bool> CapturedBeforeReturn;
970 DenseMap<const Value *, bool> InvisibleToCallerAfterRet;
971 DenseMap<const Value *, uint64_t> InvisibleToCallerAfterRetBounded;
973 SmallPtrSet<BasicBlock *, 16> ThrowingBlocks;
976 DenseMap<BasicBlock *, unsigned> PostOrderNumbers;
980 MapVector<BasicBlock *, InstOverlapIntervalsTy> IOLs;
984 bool AnyUnreachableExit;
989 bool ShouldIterateEndOfFunctionDSE;
996 PostDominatorTree &PDT,
const TargetLibraryInfo &TLI,
997 const CycleInfo &CI);
998 DSEState(
const DSEState &) =
delete;
999 DSEState &operator=(
const DSEState &) =
delete;
1001 LocationSize strengthenLocationSize(
const Instruction *
I,
1002 LocationSize
Size)
const;
1012 OverwriteResult isOverwrite(
const Instruction *KillingI,
1013 const Instruction *DeadI,
1014 const MemoryLocation &KillingLoc,
1015 const MemoryLocation &DeadLoc,
1016 int64_t &KillingOff, int64_t &DeadOff);
1018 bool isInvisibleToCallerAfterRet(
const Value *V,
const Value *Ptr,
1019 const LocationSize StoreSize);
1021 bool isInvisibleToCallerOnUnwind(
const Value *V);
1023 std::optional<MemoryLocation> getLocForWrite(Instruction *
I)
const;
1028 getLocForInst(Instruction *
I,
bool ConsiderInitializesAttr);
1032 bool isRemovable(Instruction *
I);
1036 bool isCompleteOverwrite(
const MemoryLocation &DefLoc, Instruction *DefInst,
1037 Instruction *UseInst);
1040 bool isWriteAtEndOfFunction(MemoryDef *Def,
const MemoryLocation &DefLoc);
1045 std::optional<std::pair<MemoryLocation, bool>>
1046 getLocForTerminator(Instruction *
I)
const;
1050 bool isMemTerminatorInst(Instruction *
I)
const;
1054 bool isMemTerminator(
const MemoryLocation &Loc, Instruction *AccessI,
1055 Instruction *MaybeTerm);
1058 bool isReadClobber(
const MemoryLocation &DefLoc, Instruction *UseInst);
1065 bool isGuaranteedLoopIndependent(
const Instruction *Current,
1066 const Instruction *KillingDef,
1067 const MemoryLocation &CurrentLoc);
1072 bool isGuaranteedLoopInvariant(
const Value *Ptr);
1080 std::optional<MemoryAccess *>
1081 getDomMemoryDef(MemoryDef *KillingDef, MemoryAccess *StartAccess,
1082 const MemoryLocation &KillingLoc,
const Value *KillingUndObj,
1083 unsigned &ScanLimit,
unsigned &WalkerStepLimit,
1084 bool IsMemTerm,
unsigned &PartialLimit,
1085 bool IsInitializesAttrMemLoc);
1091 SmallPtrSetImpl<MemoryAccess *> *
Deleted =
nullptr);
1097 bool mayThrowBetween(Instruction *KillingI, Instruction *DeadI,
1098 const Value *KillingUndObj);
1105 bool isDSEBarrier(
const Value *KillingUndObj, Instruction *DeadI);
1109 bool eliminateDeadWritesAtEndOfFunction();
1113 bool tryFoldIntoCalloc(MemoryDef *Def,
const Value *DefUO);
1117 bool storeIsNoop(MemoryDef *Def,
const Value *DefUO);
1123 bool eliminateRedundantStoresOfExistingValues();
1128 bool eliminateRedundantStoresViaDominatingConditions();
1143 std::pair<bool, bool>
1144 eliminateDeadDefs(
const MemoryLocationWrapper &KillingLocWrapper);
1148 bool eliminateDeadDefs(
const MemoryDefWrapper &KillingDefWrapper);
1158 if (Visited.
insert(MA).second)
1175 :
F(
F),
AA(
AA), EA(DT, nullptr, &CI), BatchAA(
AA, &EA), MSSA(MSSA), DT(DT),
1176 PDT(PDT), TLI(TLI),
DL(
F.getDataLayout()), CI(CI) {
1181 PostOrderNumbers[BB] = PO++;
1184 if (
I.mayThrow() && !MA)
1185 ThrowingBlocks.insert(
I.getParent());
1189 (getLocForWrite(&
I) || isMemTerminatorInst(&
I) ||
1191 MemDefs.push_back(MD);
1198 if (AI.hasPassPointeeByValueCopyAttr()) {
1199 InvisibleToCallerAfterRet.insert({&AI, true});
1203 if (!AI.getType()->isPointerTy())
1207 if (Info.coversAllReachableMemory())
1208 InvisibleToCallerAfterRet.insert({&AI, true});
1209 else if (
uint64_t DeadBytes = Info.getNumberOfDeadBytes())
1210 InvisibleToCallerAfterRetBounded.insert({&AI, DeadBytes});
1214 return isa<UnreachableInst>(E->getTerminator());
1223 (
F == LibFunc_memset_chk ||
F == LibFunc_memcpy_chk)) {
1239OverwriteResult DSEState::isOverwrite(
const Instruction *KillingI,
1240 const Instruction *DeadI,
1241 const MemoryLocation &KillingLoc,
1242 const MemoryLocation &DeadLoc,
1243 int64_t &KillingOff, int64_t &DeadOff) {
1247 if (!isGuaranteedLoopIndependent(DeadI, KillingI, DeadLoc))
1250 LocationSize KillingLocSize =
1251 strengthenLocationSize(KillingI, KillingLoc.
Size);
1259 if (DeadUndObj == KillingUndObj && KillingLocSize.
isPrecise() &&
1261 std::optional<TypeSize> KillingUndObjSize =
1263 if (KillingUndObjSize && *KillingUndObjSize == KillingLocSize.
getValue())
1274 if (KillingMemI && DeadMemI) {
1275 const Value *KillingV = KillingMemI->getLength();
1276 const Value *DeadV = DeadMemI->getLength();
1277 if (KillingV == DeadV && BatchAA.
isMustAlias(DeadLoc, KillingLoc))
1286 const TypeSize KillingSize = KillingLocSize.
getValue();
1295 AliasResult AAR = BatchAA.
alias(KillingLoc, DeadLoc);
1301 if (KillingSize >= DeadSize)
1308 if (Off >= 0 && (uint64_t)Off + DeadSize <= KillingSize)
1314 if (DeadUndObj != KillingUndObj) {
1330 const Value *DeadBasePtr =
1332 const Value *KillingBasePtr =
1337 if (DeadBasePtr != KillingBasePtr)
1355 if (DeadOff >= KillingOff) {
1358 if (uint64_t(DeadOff - KillingOff) + DeadSize <= KillingSize)
1362 else if ((uint64_t)(DeadOff - KillingOff) < KillingSize)
1363 return OW_MaybePartial;
1367 else if ((uint64_t)(KillingOff - DeadOff) < DeadSize) {
1368 return OW_MaybePartial;
1375bool DSEState::isInvisibleToCallerAfterRet(
const Value *V,
const Value *Ptr,
1376 const LocationSize StoreSize) {
1380 auto IBounded = InvisibleToCallerAfterRetBounded.find(V);
1381 if (IBounded != InvisibleToCallerAfterRetBounded.end()) {
1382 int64_t ValueOffset;
1383 [[maybe_unused]]
const Value *BaseValue =
1393 ValueOffset + StoreSize.
getValue() <= IBounded->second &&
1397 auto I = InvisibleToCallerAfterRet.insert({
V,
false});
1398 if (
I.second && isInvisibleToCallerOnUnwind(V) &&
isNoAliasCall(V))
1400 V,
true, CaptureComponents::Provenance));
1401 return I.first->second;
1404bool DSEState::isInvisibleToCallerOnUnwind(
const Value *V) {
1405 bool RequiresNoCaptureBeforeUnwind;
1408 if (!RequiresNoCaptureBeforeUnwind)
1411 auto I = CapturedBeforeReturn.insert({
V,
true});
1418 V,
false, CaptureComponents::Provenance));
1419 return !
I.first->second;
1422std::optional<MemoryLocation> DSEState::getLocForWrite(Instruction *
I)
const {
1423 if (!
I->mayWriteToMemory())
1424 return std::nullopt;
1433DSEState::getLocForInst(Instruction *
I,
bool ConsiderInitializesAttr) {
1435 if (isMemTerminatorInst(
I)) {
1436 if (
auto Loc = getLocForTerminator(
I))
1437 Locations.push_back(std::make_pair(Loc->first,
false));
1441 if (
auto Loc = getLocForWrite(
I))
1442 Locations.push_back(std::make_pair(*Loc,
false));
1444 if (ConsiderInitializesAttr) {
1445 for (
auto &MemLoc : getInitializesArgMemLoc(
I)) {
1446 Locations.push_back(std::make_pair(MemLoc,
true));
1452bool DSEState::isRemovable(Instruction *
I) {
1453 assert(getLocForWrite(
I) &&
"Must have analyzable write");
1457 return SI->isUnordered();
1462 return !
MI->isVolatile();
1466 if (CB->isLifetimeStartOrEnd())
1469 return CB->use_empty() && CB->willReturn() && CB->doesNotThrow() &&
1470 !CB->isTerminator();
1476bool DSEState::isCompleteOverwrite(
const MemoryLocation &DefLoc,
1477 Instruction *DefInst, Instruction *UseInst) {
1485 if (CB->onlyAccessesInaccessibleMemory())
1488 int64_t InstWriteOffset, DepWriteOffset;
1489 if (
auto CC = getLocForWrite(UseInst))
1490 return isOverwrite(UseInst, DefInst, *CC, DefLoc, InstWriteOffset,
1491 DepWriteOffset) == OW_Complete;
1495bool DSEState::isWriteAtEndOfFunction(MemoryDef *Def,
1496 const MemoryLocation &DefLoc) {
1498 << *
Def->getMemoryInst()
1499 <<
") is at the end the function \n");
1501 SmallPtrSet<MemoryAccess *, 8> Visited;
1504 for (
unsigned I = 0;
I < WorkList.
size();
I++) {
1510 MemoryAccess *UseAccess = WorkList[
I];
1515 if (!isGuaranteedLoopInvariant(DefLoc.
Ptr))
1524 if (isReadClobber(DefLoc, UseInst)) {
1525 LLVM_DEBUG(
dbgs() <<
" ... hit read clobber " << *UseInst <<
".\n");
1535std::optional<std::pair<MemoryLocation, bool>>
1536DSEState::getLocForTerminator(Instruction *
I)
const {
1538 if (CB->getIntrinsicID() == Intrinsic::lifetime_end)
1545 return std::nullopt;
1548bool DSEState::isMemTerminatorInst(Instruction *
I)
const {
1550 return CB && (CB->getIntrinsicID() == Intrinsic::lifetime_end ||
1554bool DSEState::isMemTerminator(
const MemoryLocation &Loc, Instruction *AccessI,
1555 Instruction *MaybeTerm) {
1556 std::optional<std::pair<MemoryLocation, bool>> MaybeTermLoc =
1557 getLocForTerminator(MaybeTerm);
1568 auto TermLoc = MaybeTermLoc->first;
1569 if (MaybeTermLoc->second) {
1573 int64_t InstWriteOffset = 0;
1574 int64_t DepWriteOffset = 0;
1575 return isOverwrite(MaybeTerm, AccessI, TermLoc, Loc, InstWriteOffset,
1576 DepWriteOffset) == OW_Complete;
1579bool DSEState::isReadClobber(
const MemoryLocation &DefLoc,
1580 Instruction *UseInst) {
1593 if (CB->onlyAccessesInaccessibleMemory())
1599bool DSEState::isGuaranteedLoopIndependent(
const Instruction *Current,
1600 const Instruction *KillingDef,
1601 const MemoryLocation &CurrentLoc) {
1612 return isGuaranteedLoopInvariant(CurrentLoc.
Ptr);
1615bool DSEState::isGuaranteedLoopInvariant(
const Value *Ptr) {
1618 if (
GEP->hasAllConstantIndices())
1622 return I->getParent()->isEntryBlock() || !CI.
getCycle(
I->getParent());
1627std::optional<MemoryAccess *> DSEState::getDomMemoryDef(
1628 MemoryDef *KillingDef, MemoryAccess *StartAccess,
1629 const MemoryLocation &KillingLoc,
const Value *KillingUndObj,
1630 unsigned &ScanLimit,
unsigned &WalkerStepLimit,
bool IsMemTerm,
1631 unsigned &PartialLimit,
bool IsInitializesAttrMemLoc) {
1632 if (ScanLimit == 0 || WalkerStepLimit == 0) {
1634 return std::nullopt;
1637 MemoryAccess *Current = StartAccess;
1651 std::optional<MemoryLocation> CurrentLoc;
1654 dbgs() <<
" visiting " << *Current;
1667 return std::nullopt;
1675 if (WalkerStepLimit <= StepCost) {
1677 return std::nullopt;
1679 WalkerStepLimit -= StepCost;
1693 if (
canSkipDef(CurrentDef, !isInvisibleToCallerOnUnwind(KillingUndObj))) {
1694 CanOptimize =
false;
1700 if (mayThrowBetween(KillingI, CurrentI, KillingUndObj)) {
1702 return std::nullopt;
1707 if (isDSEBarrier(KillingUndObj, CurrentI)) {
1709 return std::nullopt;
1717 return std::nullopt;
1720 if (
any_of(Current->
uses(), [
this, &KillingLoc, StartAccess](Use &U) {
1721 if (auto *UseOrDef = dyn_cast<MemoryUseOrDef>(U.getUser()))
1722 return !MSSA.dominates(StartAccess, UseOrDef) &&
1723 isReadClobber(KillingLoc, UseOrDef->getMemoryInst());
1727 return std::nullopt;
1732 CurrentLoc = getLocForWrite(CurrentI);
1733 if (!CurrentLoc || !isRemovable(CurrentI)) {
1734 CanOptimize =
false;
1741 if (!isGuaranteedLoopIndependent(CurrentI, KillingI, *CurrentLoc)) {
1743 CanOptimize =
false;
1751 if (!isMemTerminator(*CurrentLoc, CurrentI, KillingI)) {
1752 CanOptimize =
false;
1756 int64_t KillingOffset = 0;
1757 int64_t DeadOffset = 0;
1758 auto OR = isOverwrite(KillingI, CurrentI, KillingLoc, *CurrentLoc,
1759 KillingOffset, DeadOffset);
1765 (OR == OW_Complete || OR == OW_MaybePartial))
1771 CanOptimize =
false;
1776 if (OR == OW_Unknown || OR == OW_None)
1778 else if (OR == OW_MaybePartial) {
1783 if (PartialLimit <= 1) {
1784 WalkerStepLimit -= 1;
1785 LLVM_DEBUG(
dbgs() <<
" ... reached partial limit ... continue with "
1799 SmallPtrSet<Instruction *, 16> KillingDefs;
1801 MemoryAccess *MaybeDeadAccess = Current;
1802 MemoryLocation MaybeDeadLoc = *CurrentLoc;
1804 LLVM_DEBUG(
dbgs() <<
" Checking for reads of " << *MaybeDeadAccess <<
" ("
1805 << *MaybeDeadI <<
")\n");
1808 SmallPtrSet<MemoryAccess *, 32> Visited;
1812 for (
unsigned I = 0;
I < WorkList.
size();
I++) {
1813 MemoryAccess *UseAccess = WorkList[
I];
1817 if (ScanLimit < (WorkList.
size() -
I)) {
1819 return std::nullopt;
1822 NumDomMemDefChecks++;
1825 if (
any_of(KillingDefs, [
this, UseAccess](Instruction *KI) {
1828 LLVM_DEBUG(
dbgs() <<
" ... skipping, dominated by killing block\n");
1839 if (
any_of(KillingDefs, [
this, UseInst](Instruction *KI) {
1842 LLVM_DEBUG(
dbgs() <<
" ... skipping, dominated by killing def\n");
1848 if (isMemTerminator(MaybeDeadLoc, MaybeDeadI, UseInst)) {
1851 <<
" ... skipping, memterminator invalidates following accesses\n");
1861 if (UseInst->
mayThrow() && !isInvisibleToCallerOnUnwind(KillingUndObj)) {
1863 return std::nullopt;
1870 bool IsKillingDefFromInitAttr =
false;
1871 if (IsInitializesAttrMemLoc) {
1872 if (KillingI == UseInst &&
1874 IsKillingDefFromInitAttr =
true;
1877 if (isReadClobber(MaybeDeadLoc, UseInst) && !IsKillingDefFromInitAttr) {
1879 return std::nullopt;
1885 if (MaybeDeadAccess == UseAccess &&
1886 !isGuaranteedLoopInvariant(MaybeDeadLoc.
Ptr)) {
1887 LLVM_DEBUG(
dbgs() <<
" ... found not loop invariant self access\n");
1888 return std::nullopt;
1894 if (KillingDef == UseAccess || MaybeDeadAccess == UseAccess) {
1910 if (isCompleteOverwrite(MaybeDeadLoc, MaybeDeadI, UseInst)) {
1912 if (PostOrderNumbers.
find(MaybeKillingBlock)->second <
1913 PostOrderNumbers.
find(MaybeDeadAccess->
getBlock())->second) {
1914 if (!isInvisibleToCallerAfterRet(KillingUndObj, KillingLoc.
Ptr,
1917 <<
" ... found killing def " << *UseInst <<
"\n");
1918 KillingDefs.
insert(UseInst);
1922 <<
" ... found preceeding def " << *UseInst <<
"\n");
1923 return std::nullopt;
1933 if (!isInvisibleToCallerAfterRet(KillingUndObj, KillingLoc.
Ptr,
1935 SmallPtrSet<BasicBlock *, 16> KillingBlocks;
1936 for (Instruction *KD : KillingDefs)
1937 KillingBlocks.
insert(KD->getParent());
1939 "Expected at least a single killing block");
1953 if (!AnyUnreachableExit)
1954 return std::nullopt;
1958 CommonPred =
nullptr;
1962 if (KillingBlocks.
count(CommonPred))
1963 return {MaybeDeadAccess};
1965 SetVector<BasicBlock *> WorkList;
1969 WorkList.
insert(CommonPred);
1971 for (BasicBlock *R : PDT.
roots()) {
1979 for (
unsigned I = 0;
I < WorkList.
size();
I++) {
1982 if (KillingBlocks.
count(Current))
1984 if (Current == MaybeDeadAccess->
getBlock())
1985 return std::nullopt;
1995 return std::nullopt;
2002 return {MaybeDeadAccess};
2005void DSEState::deleteDeadInstruction(Instruction *SI,
2006 SmallPtrSetImpl<MemoryAccess *> *
Deleted) {
2007 MemorySSAUpdater Updater(&MSSA);
2012 while (!NowDeadInsts.
empty()) {
2026 SkipStores.insert(MD);
2030 if (
SI->getValueOperand()->getType()->isPointerTy()) {
2032 if (CapturedBeforeReturn.erase(UO))
2033 ShouldIterateEndOfFunctionDSE =
true;
2034 InvisibleToCallerAfterRet.erase(UO);
2035 InvisibleToCallerAfterRetBounded.erase(UO);
2040 Updater.removeMemoryAccess(MA);
2044 if (
I != IOLs.end())
2045 I->second.erase(DeadInst);
2047 for (Use &O : DeadInst->
operands())
2067bool DSEState::mayThrowBetween(Instruction *KillingI, Instruction *DeadI,
2068 const Value *KillingUndObj) {
2072 if (KillingUndObj && isInvisibleToCallerOnUnwind(KillingUndObj))
2076 return ThrowingBlocks.count(KillingI->
getParent());
2077 return !ThrowingBlocks.empty();
2080bool DSEState::isDSEBarrier(
const Value *KillingUndObj, Instruction *DeadI) {
2083 if (DeadI->
mayThrow() && !isInvisibleToCallerOnUnwind(KillingUndObj))
2103bool DSEState::eliminateDeadWritesAtEndOfFunction() {
2104 bool MadeChange =
false;
2106 dbgs() <<
"Trying to eliminate MemoryDefs at the end of the function\n");
2108 ShouldIterateEndOfFunctionDSE =
false;
2110 if (SkipStores.contains(Def))
2114 auto DefLoc = getLocForWrite(DefI);
2115 if (!DefLoc || !isRemovable(DefI)) {
2117 "instruction not removable.\n");
2127 if (!isInvisibleToCallerAfterRet(UO, DefLoc->
Ptr, DefLoc->
Size))
2130 if (isWriteAtEndOfFunction(Def, *DefLoc)) {
2132 LLVM_DEBUG(
dbgs() <<
" ... MemoryDef is not accessed until the end "
2133 "of the function\n");
2139 }
while (ShouldIterateEndOfFunctionDSE);
2143bool DSEState::eliminateRedundantStoresViaDominatingConditions() {
2144 bool MadeChange =
false;
2145 LLVM_DEBUG(
dbgs() <<
"Trying to eliminate MemoryDefs whose value being "
2146 "written is implied by a dominating condition\n");
2148 using ConditionInfo = std::pair<Value *, Value *>;
2149 using ScopedHTType = ScopedHashTable<ConditionInfo, Instruction *>;
2153 ScopedHTType ActiveConditions;
2154 auto GetDominatingCondition = [&](
BasicBlock *BB)
2155 -> std::optional<std::tuple<ConditionInfo, Instruction *, BasicBlock *>> {
2158 return std::nullopt;
2163 if (BI->getSuccessor(0) == BI->getSuccessor(1))
2164 return std::nullopt;
2168 Value *StorePtr, *StoreVal;
2169 if (!
match(BI->getCondition(),
2173 return std::nullopt;
2179 return std::nullopt;
2181 unsigned ImpliedSuccIdx = Pred == ICmpInst::ICMP_EQ ? 0 : 1;
2182 BasicBlock *ImpliedSucc = BI->getSuccessor(ImpliedSuccIdx);
2183 return {{ConditionInfo(StorePtr, StoreVal), ICmpL, ImpliedSucc}};
2199 if (!SI || !
SI->isUnordered())
2203 {
SI->getPointerOperand(),
SI->getValueOperand()});
2211 MemoryAccess *ClobberingAccess =
2213 if (MSSA.
dominates(ClobberingAccess, LoadAccess)) {
2215 <<
"Removing No-Op Store:\n DEAD: " << *SI <<
'\n');
2217 NumRedundantStores++;
2224 auto MaybeCondition = GetDominatingCondition(BB);
2228 ScopedHTType::ScopeTy
Scope(ActiveConditions);
2229 if (MaybeCondition) {
2230 const auto &[
Cond, LI, ImpliedSucc] = *MaybeCondition;
2231 if (DT.
dominates(BasicBlockEdge(BB, ImpliedSucc), Child->getBlock())) {
2235 ActiveConditions.insert(
Cond, LI);
2242 Self(Child,
Depth + 1, Self);
2252bool DSEState::tryFoldIntoCalloc(MemoryDef *Def,
const Value *DefUO) {
2259 if (!StoredConstant || !StoredConstant->
isNullValue())
2262 if (!isRemovable(DefI))
2266 if (
F.hasFnAttribute(Attribute::SanitizeMemory) ||
2267 F.hasFnAttribute(Attribute::SanitizeAddress) ||
2268 F.hasFnAttribute(Attribute::SanitizeHWAddress) ||
F.getName() ==
"calloc")
2273 auto *InnerCallee =
Malloc->getCalledFunction();
2276 LibFunc
Func = NotLibFunc;
2277 StringRef ZeroedVariantName;
2278 if (!TLI.
getLibFunc(*InnerCallee, Func) || !TLI.
has(Func) ||
2279 Func != LibFunc_malloc) {
2284 if (ZeroedVariantName.
empty())
2293 auto shouldCreateCalloc = [](CallInst *
Malloc, CallInst *Memset) {
2296 auto *MallocBB =
Malloc->getParent(), *MemsetBB = Memset->getParent();
2297 if (MallocBB == MemsetBB)
2299 auto *Ptr = Memset->getArgOperand(0);
2300 auto *TI = MallocBB->getTerminator();
2306 if (MemsetBB != FalseBB)
2317 assert(Func == LibFunc_malloc || !ZeroedVariantName.
empty());
2318 Value *Calloc =
nullptr;
2319 if (!ZeroedVariantName.
empty()) {
2320 LLVMContext &Ctx =
Malloc->getContext();
2321 AttributeList
Attrs = InnerCallee->getAttributes();
2323 Attrs.getFnAttr(Attribute::AllocKind).getAllocKind() |
2324 AllocFnKind::Zeroed;
2327 Attrs.addFnAttribute(Ctx, Attribute::getWithAllocKind(Ctx, AllocKind))
2328 .removeFnAttribute(Ctx,
"alloc-variant-zeroed");
2329 FunctionCallee ZeroedVariant =
Malloc->getModule()->getOrInsertFunction(
2330 ZeroedVariantName, InnerCallee->getFunctionType(), Attrs);
2332 ->setCallingConv(
Malloc->getCallingConv());
2335 CallInst *CI = IRB.CreateCall(ZeroedVariant, Args, ZeroedVariantName);
2339 Type *SizeTTy =
Malloc->getArgOperand(0)->getType();
2340 Calloc =
emitCalloc(ConstantInt::get(SizeTTy, 1),
Malloc->getArgOperand(0),
2341 IRB, TLI,
Malloc->getType()->getPointerAddressSpace());
2346 MemorySSAUpdater Updater(&MSSA);
2348 nullptr, MallocDef);
2350 Updater.insertDef(NewAccessMD,
true);
2351 Malloc->replaceAllUsesWith(Calloc);
2356bool DSEState::storeIsNoop(MemoryDef *Def,
const Value *DefUO) {
2360 Constant *StoredConstant =
nullptr;
2368 if (!isRemovable(DefI))
2371 if (StoredConstant) {
2376 if (InitC && InitC == StoredConstant)
2385 if (LoadI->getPointerOperand() ==
Store->getOperand(1)) {
2389 if (LoadAccess ==
Def->getDefiningAccess())
2395 SetVector<MemoryAccess *> ToCheck;
2396 MemoryAccess *Current =
2404 for (
unsigned I = 1;
I < ToCheck.
size(); ++
I) {
2405 Current = ToCheck[
I];
2408 for (
auto &Use : PhiAccess->incoming_values())
2420 if (LoadAccess != Current)
2432 for (
auto OI : IOL) {
2434 MemoryLocation Loc = *getLocForWrite(DeadI);
2435 assert(isRemovable(DeadI) &&
"Expect only removable instruction");
2438 int64_t DeadStart = 0;
2443 if (IntervalMap.empty())
2450bool DSEState::eliminateRedundantStoresOfExistingValues() {
2451 bool MadeChange =
false;
2452 LLVM_DEBUG(
dbgs() <<
"Trying to eliminate MemoryDefs that write the "
2453 "already existing value\n");
2454 for (
auto *Def : MemDefs) {
2459 auto MaybeDefLoc = getLocForWrite(DefInst);
2460 if (!MaybeDefLoc || !isRemovable(DefInst))
2463 MemoryDef *UpperDef;
2467 if (
Def->isOptimized())
2475 auto IsRedundantStore = [&]() {
2483 auto UpperLoc = getLocForWrite(UpperInst);
2486 int64_t InstWriteOffset = 0;
2487 int64_t DepWriteOffset = 0;
2488 auto OR = isOverwrite(UpperInst, DefInst, *UpperLoc, *MaybeDefLoc,
2489 InstWriteOffset, DepWriteOffset);
2491 return StoredByte && StoredByte == MemSetI->getOperand(1) &&
2498 if (!IsRedundantStore() || isReadClobber(*MaybeDefLoc, DefInst))
2500 LLVM_DEBUG(
dbgs() <<
"DSE: Remove No-Op Store:\n DEAD: " << *DefInst
2503 NumRedundantStores++;
2510DSEState::getInitializesArgMemLoc(
const Instruction *
I) {
2516 SmallMapVector<Value *, SmallVector<ArgumentInitInfo, 2>, 2>
Arguments;
2522 ConstantRangeList Inits;
2534 Inits = ConstantRangeList();
2542 bool IsDeadOrInvisibleOnUnwind =
2545 ArgumentInitInfo InitInfo{Idx, IsDeadOrInvisibleOnUnwind, Inits};
2546 bool FoundAliasing =
false;
2547 for (
auto &[Arg, AliasList] :
Arguments) {
2553 FoundAliasing =
true;
2554 AliasList.push_back(InitInfo);
2559 FoundAliasing =
true;
2560 AliasList.push_back(ArgumentInitInfo{Idx, IsDeadOrInvisibleOnUnwind,
2561 ConstantRangeList()});
2570 auto IntersectedRanges =
2572 if (IntersectedRanges.empty())
2575 for (
const auto &Arg : Args) {
2576 for (
const auto &
Range : IntersectedRanges) {
2590std::pair<bool, bool>
2591DSEState::eliminateDeadDefs(
const MemoryLocationWrapper &KillingLocWrapper) {
2593 bool DeletedKillingLoc =
false;
2599 SmallSetVector<MemoryAccess *, 8> ToCheck;
2603 SmallPtrSet<MemoryAccess *, 8>
Deleted;
2604 [[maybe_unused]]
unsigned OrigNumSkipStores = SkipStores.size();
2609 for (
unsigned I = 0;
I < ToCheck.
size();
I++) {
2610 MemoryAccess *Current = ToCheck[
I];
2611 if (
Deleted.contains(Current))
2613 std::optional<MemoryAccess *> MaybeDeadAccess = getDomMemoryDef(
2614 KillingLocWrapper.MemDef, Current, KillingLocWrapper.MemLoc,
2615 KillingLocWrapper.UnderlyingObject, ScanLimit, WalkerStepLimit,
2616 isMemTerminatorInst(KillingLocWrapper.DefInst), PartialLimit,
2617 KillingLocWrapper.DefByInitializesAttr);
2619 if (!MaybeDeadAccess) {
2623 MemoryAccess *DeadAccess = *MaybeDeadAccess;
2624 LLVM_DEBUG(
dbgs() <<
" Checking if we can kill " << *DeadAccess);
2626 LLVM_DEBUG(
dbgs() <<
"\n ... adding incoming values to worklist\n");
2635 if (PostOrderNumbers[IncomingBlock] > PostOrderNumbers[PhiBlock])
2636 ToCheck.
insert(IncomingAccess);
2647 MemoryDefWrapper DeadDefWrapper(
2651 assert(DeadDefWrapper.DefinedLocations.size() == 1);
2652 MemoryLocationWrapper &DeadLocWrapper =
2653 DeadDefWrapper.DefinedLocations.front();
2656 NumGetDomMemoryDefPassed++;
2660 if (isMemTerminatorInst(KillingLocWrapper.DefInst)) {
2661 if (KillingLocWrapper.UnderlyingObject != DeadLocWrapper.UnderlyingObject)
2664 << *DeadLocWrapper.DefInst <<
"\n KILLER: "
2665 << *KillingLocWrapper.DefInst <<
'\n');
2671 int64_t KillingOffset = 0;
2672 int64_t DeadOffset = 0;
2673 OverwriteResult
OR =
2674 isOverwrite(KillingLocWrapper.DefInst, DeadLocWrapper.DefInst,
2675 KillingLocWrapper.MemLoc, DeadLocWrapper.MemLoc,
2676 KillingOffset, DeadOffset);
2677 if (OR == OW_MaybePartial) {
2678 auto &IOL = IOLs[DeadLocWrapper.DefInst->
getParent()];
2680 KillingOffset, DeadOffset,
2681 DeadLocWrapper.DefInst, IOL);
2689 if (DeadSI && KillingSI && DT.
dominates(DeadSI, KillingSI)) {
2691 KillingSI, DeadSI, KillingOffset, DeadOffset,
DL, BatchAA,
2695 DeadSI->setOperand(0, Merged);
2696 ++NumModifiedStores;
2698 DeletedKillingLoc =
true;
2703 auto I = IOLs.find(DeadSI->getParent());
2704 if (
I != IOLs.end())
2705 I->second.erase(DeadSI);
2710 if (OR == OW_Complete) {
2712 << *DeadLocWrapper.DefInst <<
"\n KILLER: "
2713 << *KillingLocWrapper.DefInst <<
'\n');
2721 assert(SkipStores.size() - OrigNumSkipStores ==
Deleted.size() &&
2722 "SkipStores and Deleted out of sync?");
2724 return {
Changed, DeletedKillingLoc};
2727bool DSEState::eliminateDeadDefs(
const MemoryDefWrapper &KillingDefWrapper) {
2728 if (KillingDefWrapper.DefinedLocations.empty()) {
2729 LLVM_DEBUG(
dbgs() <<
"Failed to find analyzable write location for "
2730 << *KillingDefWrapper.DefInst <<
"\n");
2734 bool MadeChange =
false;
2735 for (
auto &KillingLocWrapper : KillingDefWrapper.DefinedLocations) {
2737 << *KillingLocWrapper.MemDef <<
" ("
2738 << *KillingLocWrapper.DefInst <<
")\n");
2739 auto [
Changed, DeletedKillingLoc] = eliminateDeadDefs(KillingLocWrapper);
2743 if (!DeletedKillingLoc && storeIsNoop(KillingLocWrapper.MemDef,
2744 KillingLocWrapper.UnderlyingObject)) {
2746 << *KillingLocWrapper.DefInst <<
'\n');
2748 NumRedundantStores++;
2753 if (!DeletedKillingLoc &&
2754 tryFoldIntoCalloc(KillingLocWrapper.MemDef,
2755 KillingLocWrapper.UnderlyingObject)) {
2756 LLVM_DEBUG(
dbgs() <<
"DSE: Remove memset after forming calloc:\n"
2757 <<
" DEAD: " << *KillingLocWrapper.DefInst <<
'\n');
2770 bool MadeChange =
false;
2771 DSEState State(
F,
AA, MSSA, DT, PDT, TLI, CI);
2773 for (
unsigned I = 0;
I < State.MemDefs.size();
I++) {
2775 if (State.SkipStores.count(KillingDef))
2778 MemoryDefWrapper KillingDefWrapper(
2779 KillingDef, State.getLocForInst(KillingDef->
getMemoryInst(),
2781 MadeChange |= State.eliminateDeadDefs(KillingDefWrapper);
2785 for (
auto &KV : State.IOLs)
2786 MadeChange |= State.removePartiallyOverlappedStores(KV.second);
2788 MadeChange |= State.eliminateRedundantStoresOfExistingValues();
2789 MadeChange |= State.eliminateDeadWritesAtEndOfFunction();
2790 MadeChange |= State.eliminateRedundantStoresViaDominatingConditions();
2792 while (!State.ToRemove.empty()) {
2793 Instruction *DeadInst = State.ToRemove.pop_back_val();
2813#ifdef LLVM_ENABLE_STATS
2840 if (skipFunction(
F))
2843 AliasAnalysis &
AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
2844 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
2846 getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F);
2847 MemorySSA &MSSA = getAnalysis<MemorySSAWrapperPass>().getMSSA();
2849 getAnalysis<PostDominatorTreeWrapperPass>().getPostDomTree();
2850 CycleInfo &CI = getAnalysis<CycleInfoWrapperPass>().getResult();
2854#ifdef LLVM_ENABLE_STATS
2863 void getAnalysisUsage(AnalysisUsage &AU)
const override {
2882char DSELegacyPass::ID = 0;
2899 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 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 void shortenAssignment(Instruction *Inst, Value *OriginalDest, uint64_t OldOffsetInBits, uint64_t OldSizeInBits, uint64_t NewSizeInBits, bool IsOverwriteEnd)
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.
ArrayRef - 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.
LLVM_ABI 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...
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) 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
CycleT * getCycle(const BlockT *Block) const
Find the innermost cycle containing a given 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.
Value * getValueOperand()
constexpr bool empty() const
empty - 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.
bool getLibFunc(StringRef funcName, LibFunc &F) 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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ 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)
bind_ty< 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, bind_ty< BasicBlock >, bind_ty< 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 &)
FunctionAddr VTableAddr Value
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...
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.
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.
FunctionAddr VTableAddr Count
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.
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.