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,
567 Assign->setKillAddress();
568 Assign->setAssignId(GetDeadLink());
572 if (NewFragment->SizeInBits == 0)
576 auto *NewAssign =
static_cast<decltype(Assign)
>(Assign->clone());
577 NewAssign->insertAfter(Assign->getIterator());
578 NewAssign->setAssignId(GetDeadLink());
580 SetDeadFragExpr(NewAssign, *NewFragment);
581 NewAssign->setKillAddress();
595 for (
auto &Attr : OldAttrs) {
596 if (Attr.hasKindAsEnum()) {
597 switch (Attr.getKindAsEnum()) {
600 case Attribute::Alignment:
602 if (
isAligned(Attr.getAlignment().valueOrOne(), PtrOffset))
605 case Attribute::Dereferenceable:
606 case Attribute::DereferenceableOrNull:
610 case Attribute::NonNull:
611 case Attribute::NoUndef:
619 Intrinsic->removeParamAttrs(ArgNo, AttrsToRemove);
623 uint64_t &DeadSize, int64_t KillingStart,
624 uint64_t KillingSize,
bool IsOverwriteEnd) {
626 Align PrefAlign = DeadIntrinsic->getDestAlign().valueOrOne();
642 int64_t ToRemoveStart = 0;
646 if (IsOverwriteEnd) {
651 ToRemoveStart = KillingStart + Off;
652 if (DeadSize <=
uint64_t(ToRemoveStart - DeadStart))
654 ToRemoveSize = DeadSize -
uint64_t(ToRemoveStart - DeadStart);
656 ToRemoveStart = DeadStart;
658 "Not overlapping accesses?");
659 ToRemoveSize = KillingSize -
uint64_t(DeadStart - KillingStart);
664 if (ToRemoveSize <= (PrefAlign.
value() - Off))
666 ToRemoveSize -= PrefAlign.
value() - Off;
669 "Should preserve selected alignment");
672 assert(ToRemoveSize > 0 &&
"Shouldn't reach here if nothing to remove");
673 assert(DeadSize > ToRemoveSize &&
"Can't remove more than original size");
675 uint64_t NewSize = DeadSize - ToRemoveSize;
676 if (DeadIntrinsic->isAtomic()) {
679 const uint32_t ElementSize = DeadIntrinsic->getElementSizeInBytes();
680 if (0 != NewSize % ElementSize)
685 << (IsOverwriteEnd ?
"END" :
"BEGIN") <<
": " << *DeadI
686 <<
"\n KILLER [" << ToRemoveStart <<
", "
687 << int64_t(ToRemoveStart + ToRemoveSize) <<
")\n");
689 DeadIntrinsic->setLength(NewSize);
690 DeadIntrinsic->setDestAlignment(PrefAlign);
692 Value *OrigDest = DeadIntrinsic->getRawDest();
693 if (!IsOverwriteEnd) {
694 Value *Indices[1] = {
695 ConstantInt::get(DeadIntrinsic->getLength()->getType(), ToRemoveSize)};
699 NewDestGEP->
setDebugLoc(DeadIntrinsic->getDebugLoc());
700 DeadIntrinsic->setDest(NewDestGEP);
710 DeadStart += ToRemoveSize;
717 int64_t &DeadStart,
uint64_t &DeadSize) {
722 int64_t KillingStart = OII->second;
723 uint64_t KillingSize = OII->first - KillingStart;
725 assert(OII->first - KillingStart >= 0 &&
"Size expected to be positive");
727 if (KillingStart > DeadStart &&
730 (
uint64_t)(KillingStart - DeadStart) < DeadSize &&
733 KillingSize >= DeadSize - (
uint64_t)(KillingStart - DeadStart)) {
734 if (
tryToShorten(DeadI, DeadStart, DeadSize, KillingStart, KillingSize,
745 int64_t &DeadStart,
uint64_t &DeadSize) {
750 int64_t KillingStart = OII->second;
751 uint64_t KillingSize = OII->first - KillingStart;
753 assert(OII->first - KillingStart >= 0 &&
"Size expected to be positive");
755 if (KillingStart <= DeadStart &&
758 KillingSize > (
uint64_t)(DeadStart - KillingStart)) {
761 assert(KillingSize - (
uint64_t)(DeadStart - KillingStart) < DeadSize &&
762 "Should have been handled as OW_Complete");
763 if (
tryToShorten(DeadI, DeadStart, DeadSize, KillingStart, KillingSize,
774 int64_t KillingOffset, int64_t DeadOffset,
818 unsigned BitOffsetDiff = (KillingOffset - DeadOffset) * 8;
819 unsigned LShiftAmount =
820 DL.isBigEndian() ? DeadValue.
getBitWidth() - BitOffsetDiff - KillingBits
823 LShiftAmount + KillingBits);
826 APInt Merged = (DeadValue & ~Mask) | (KillingValue << LShiftAmount);
828 <<
"\n Killing: " << *KillingI
829 <<
"\n Merged Value: " << Merged <<
'\n');
836 switch (
II->getIntrinsicID()) {
837 case Intrinsic::lifetime_start:
838 case Intrinsic::lifetime_end:
839 case Intrinsic::invariant_end:
840 case Intrinsic::launder_invariant_group:
841 case Intrinsic::assume:
843 case Intrinsic::dbg_declare:
844 case Intrinsic::dbg_label:
845 case Intrinsic::dbg_value:
860 if (CB->onlyAccessesInaccessibleMemory())
865 if (DI->
mayThrow() && !DefVisibleToCaller)
887struct MemoryLocationWrapper {
888 MemoryLocationWrapper(MemoryLocation MemLoc, MemoryDef *MemDef,
889 bool DefByInitializesAttr)
890 : MemLoc(MemLoc), MemDef(MemDef),
891 DefByInitializesAttr(DefByInitializesAttr) {
892 assert(MemLoc.Ptr &&
"MemLoc should be not null");
894 DefInst = MemDef->getMemoryInst();
897 MemoryLocation MemLoc;
898 const Value *UnderlyingObject;
901 bool DefByInitializesAttr =
false;
906struct MemoryDefWrapper {
907 MemoryDefWrapper(MemoryDef *MemDef,
908 ArrayRef<std::pair<MemoryLocation, bool>> MemLocations) {
910 for (
auto &[MemLoc, DefByInitializesAttr] : MemLocations)
911 DefinedLocations.push_back(
912 MemoryLocationWrapper(MemLoc, MemDef, DefByInitializesAttr));
918struct ArgumentInitInfo {
920 bool IsDeadOrInvisibleOnUnwind;
921 ConstantRangeList Inits;
936 bool CallHasNoUnwindAttr) {
942 for (
const auto &Arg : Args) {
943 if (!CallHasNoUnwindAttr && !Arg.IsDeadOrInvisibleOnUnwind)
945 if (Arg.Inits.empty())
950 for (
auto &Arg : Args.drop_front())
951 IntersectedIntervals = IntersectedIntervals.
intersectWith(Arg.Inits);
953 return IntersectedIntervals;
961 EarliestEscapeAnalysis EA;
970 BatchAAResults BatchAA;
974 PostDominatorTree &PDT;
975 const TargetLibraryInfo &TLI;
976 const DataLayout &DL;
982 SmallPtrSet<MemoryAccess *, 4> SkipStores;
984 DenseMap<const Value *, bool> CapturedBeforeReturn;
987 DenseMap<const Value *, bool> InvisibleToCallerAfterRet;
988 DenseMap<const Value *, uint64_t> InvisibleToCallerAfterRetBounded;
990 SmallPtrSet<BasicBlock *, 16> ThrowingBlocks;
993 DenseMap<BasicBlock *, unsigned> PostOrderNumbers;
997 MapVector<BasicBlock *, InstOverlapIntervalsTy> IOLs;
1001 bool AnyUnreachableExit;
1006 bool ShouldIterateEndOfFunctionDSE;
1009 SmallVector<Instruction *> ToRemove;
1013 PostDominatorTree &PDT,
const TargetLibraryInfo &TLI,
1014 const CycleInfo &CI);
1015 DSEState(
const DSEState &) =
delete;
1016 DSEState &operator=(
const DSEState &) =
delete;
1018 LocationSize strengthenLocationSize(
const Instruction *
I,
1019 LocationSize
Size)
const;
1029 OverwriteResult isOverwrite(
const Instruction *KillingI,
1030 const Instruction *DeadI,
1031 const MemoryLocation &KillingLoc,
1032 const MemoryLocation &DeadLoc,
1033 int64_t &KillingOff, int64_t &DeadOff);
1035 bool isInvisibleToCallerAfterRet(
const Value *V,
const Value *Ptr,
1036 const LocationSize StoreSize);
1038 bool isInvisibleToCallerOnUnwind(
const Value *V);
1040 std::optional<MemoryLocation> getLocForWrite(Instruction *
I)
const;
1045 getLocForInst(Instruction *
I,
bool ConsiderInitializesAttr);
1049 bool isRemovable(Instruction *
I);
1053 bool isCompleteOverwrite(
const MemoryLocation &DefLoc, Instruction *DefInst,
1054 Instruction *UseInst);
1057 bool isWriteAtEndOfFunction(MemoryDef *Def,
const MemoryLocation &DefLoc);
1062 std::optional<std::pair<MemoryLocation, bool>>
1063 getLocForTerminator(Instruction *
I)
const;
1067 bool isMemTerminatorInst(Instruction *
I)
const;
1071 bool isMemTerminator(
const MemoryLocation &Loc, Instruction *AccessI,
1072 Instruction *MaybeTerm);
1075 bool isReadClobber(
const MemoryLocation &DefLoc, Instruction *UseInst);
1082 bool isGuaranteedLoopIndependent(
const Instruction *Current,
1083 const Instruction *KillingDef,
1084 const MemoryLocation &CurrentLoc);
1089 bool isGuaranteedLoopInvariant(
const Value *Ptr);
1097 std::optional<MemoryAccess *>
1098 getDomMemoryDef(MemoryDef *KillingDef, MemoryAccess *StartAccess,
1099 const MemoryLocation &KillingLoc,
const Value *KillingUndObj,
1100 unsigned &ScanLimit,
unsigned &WalkerStepLimit,
1101 bool IsMemTerm,
unsigned &PartialLimit,
1102 bool IsInitializesAttrMemLoc);
1108 SmallPtrSetImpl<MemoryAccess *> *
Deleted =
nullptr);
1114 bool mayThrowBetween(Instruction *KillingI, Instruction *DeadI,
1115 const Value *KillingUndObj);
1122 bool isDSEBarrier(
const Value *KillingUndObj, Instruction *DeadI);
1126 bool eliminateDeadWritesAtEndOfFunction();
1130 bool tryFoldIntoCalloc(MemoryDef *Def,
const Value *DefUO);
1134 bool storeIsNoop(MemoryDef *Def,
const Value *DefUO);
1140 bool eliminateRedundantStoresOfExistingValues();
1145 bool eliminateRedundantStoresViaDominatingConditions();
1160 std::pair<bool, bool>
1161 eliminateDeadDefs(
const MemoryLocationWrapper &KillingLocWrapper);
1165 bool eliminateDeadDefs(
const MemoryDefWrapper &KillingDefWrapper);
1175 if (Visited.
insert(MA).second)
1192 :
F(
F),
AA(
AA), EA(DT, nullptr, &CI), BatchAA(
AA, &EA), MSSA(MSSA), DT(DT),
1193 PDT(PDT), TLI(TLI),
DL(
F.getDataLayout()), CI(CI) {
1198 PostOrderNumbers[BB] = PO++;
1201 if (
I.mayThrow() && !MA)
1202 ThrowingBlocks.insert(
I.getParent());
1206 (getLocForWrite(&
I) || isMemTerminatorInst(&
I) ||
1208 MemDefs.push_back(MD);
1215 if (AI.hasPassPointeeByValueCopyAttr()) {
1216 InvisibleToCallerAfterRet.insert({&AI, true});
1220 if (!AI.getType()->isPointerTy())
1224 if (Info.coversAllReachableMemory())
1225 InvisibleToCallerAfterRet.insert({&AI, true});
1226 else if (
uint64_t DeadBytes = Info.getNumberOfDeadBytes())
1227 InvisibleToCallerAfterRetBounded.insert({&AI, DeadBytes});
1231 return isa<UnreachableInst>(E->getTerminator());
1240 (
F == LibFunc_memset_chk ||
F == LibFunc_memcpy_chk)) {
1256OverwriteResult DSEState::isOverwrite(
const Instruction *KillingI,
1257 const Instruction *DeadI,
1258 const MemoryLocation &KillingLoc,
1259 const MemoryLocation &DeadLoc,
1260 int64_t &KillingOff, int64_t &DeadOff) {
1264 if (!isGuaranteedLoopIndependent(DeadI, KillingI, DeadLoc))
1267 LocationSize KillingLocSize =
1268 strengthenLocationSize(KillingI, KillingLoc.
Size);
1276 if (DeadUndObj == KillingUndObj && KillingLocSize.
isPrecise() &&
1278 std::optional<TypeSize> KillingUndObjSize =
1280 if (KillingUndObjSize && *KillingUndObjSize == KillingLocSize.
getValue())
1291 if (KillingMemI && DeadMemI) {
1292 const Value *KillingV = KillingMemI->getLength();
1293 const Value *DeadV = DeadMemI->getLength();
1294 if (KillingV == DeadV && BatchAA.
isMustAlias(DeadLoc, KillingLoc))
1303 const TypeSize KillingSize = KillingLocSize.
getValue();
1312 AliasResult AAR = BatchAA.
alias(KillingLoc, DeadLoc);
1318 if (KillingSize >= DeadSize)
1325 if (Off >= 0 && (uint64_t)Off + DeadSize <= KillingSize)
1331 if (DeadUndObj != KillingUndObj) {
1347 const Value *DeadBasePtr =
1349 const Value *KillingBasePtr =
1354 if (DeadBasePtr != KillingBasePtr)
1372 if (DeadOff >= KillingOff) {
1375 if (uint64_t(DeadOff - KillingOff) + DeadSize <= KillingSize)
1379 else if ((uint64_t)(DeadOff - KillingOff) < KillingSize)
1380 return OW_MaybePartial;
1384 else if ((uint64_t)(KillingOff - DeadOff) < DeadSize) {
1385 return OW_MaybePartial;
1392bool DSEState::isInvisibleToCallerAfterRet(
const Value *V,
const Value *Ptr,
1393 const LocationSize StoreSize) {
1397 auto IBounded = InvisibleToCallerAfterRetBounded.find(V);
1398 if (IBounded != InvisibleToCallerAfterRetBounded.end()) {
1399 int64_t ValueOffset;
1400 [[maybe_unused]]
const Value *BaseValue =
1410 ValueOffset + StoreSize.
getValue() <= IBounded->second &&
1414 auto I = InvisibleToCallerAfterRet.insert({
V,
false});
1415 if (
I.second && isInvisibleToCallerOnUnwind(V) &&
isNoAliasCall(V))
1418 return I.first->second;
1421bool DSEState::isInvisibleToCallerOnUnwind(
const Value *V) {
1422 bool RequiresNoCaptureBeforeUnwind;
1425 if (!RequiresNoCaptureBeforeUnwind)
1428 auto I = CapturedBeforeReturn.insert({
V,
true});
1436 return !
I.first->second;
1439std::optional<MemoryLocation> DSEState::getLocForWrite(Instruction *
I)
const {
1440 if (!
I->mayWriteToMemory())
1441 return std::nullopt;
1450DSEState::getLocForInst(Instruction *
I,
bool ConsiderInitializesAttr) {
1452 if (isMemTerminatorInst(
I)) {
1453 if (
auto Loc = getLocForTerminator(
I))
1454 Locations.push_back(std::make_pair(Loc->first,
false));
1458 if (
auto Loc = getLocForWrite(
I))
1459 Locations.push_back(std::make_pair(*Loc,
false));
1461 if (ConsiderInitializesAttr) {
1462 for (
auto &MemLoc : getInitializesArgMemLoc(
I)) {
1463 Locations.push_back(std::make_pair(MemLoc,
true));
1469bool DSEState::isRemovable(Instruction *
I) {
1470 assert(getLocForWrite(
I) &&
"Must have analyzable write");
1474 return SI->isUnordered();
1479 return !
MI->isVolatile();
1483 if (CB->isLifetimeStartOrEnd())
1486 return CB->use_empty() && CB->willReturn() && CB->doesNotThrow() &&
1487 !CB->isTerminator();
1493bool DSEState::isCompleteOverwrite(
const MemoryLocation &DefLoc,
1494 Instruction *DefInst, Instruction *UseInst) {
1502 if (CB->onlyAccessesInaccessibleMemory())
1505 int64_t InstWriteOffset, DepWriteOffset;
1506 if (
auto CC = getLocForWrite(UseInst))
1507 return isOverwrite(UseInst, DefInst, *CC, DefLoc, InstWriteOffset,
1508 DepWriteOffset) == OW_Complete;
1512bool DSEState::isWriteAtEndOfFunction(MemoryDef *Def,
1513 const MemoryLocation &DefLoc) {
1515 << *
Def->getMemoryInst()
1516 <<
") is at the end the function \n");
1518 SmallPtrSet<MemoryAccess *, 8> Visited;
1521 for (
unsigned I = 0;
I < WorkList.
size();
I++) {
1527 MemoryAccess *UseAccess = WorkList[
I];
1532 if (!isGuaranteedLoopInvariant(DefLoc.
Ptr))
1541 if (isReadClobber(DefLoc, UseInst)) {
1542 LLVM_DEBUG(
dbgs() <<
" ... hit read clobber " << *UseInst <<
".\n");
1552std::optional<std::pair<MemoryLocation, bool>>
1553DSEState::getLocForTerminator(Instruction *
I)
const {
1555 if (CB->getIntrinsicID() == Intrinsic::lifetime_end)
1562 return std::nullopt;
1565bool DSEState::isMemTerminatorInst(Instruction *
I)
const {
1567 return CB && (CB->getIntrinsicID() == Intrinsic::lifetime_end ||
1571bool DSEState::isMemTerminator(
const MemoryLocation &Loc, Instruction *AccessI,
1572 Instruction *MaybeTerm) {
1573 std::optional<std::pair<MemoryLocation, bool>> MaybeTermLoc =
1574 getLocForTerminator(MaybeTerm);
1585 auto TermLoc = MaybeTermLoc->first;
1586 if (MaybeTermLoc->second) {
1590 int64_t InstWriteOffset = 0;
1591 int64_t DepWriteOffset = 0;
1592 return isOverwrite(MaybeTerm, AccessI, TermLoc, Loc, InstWriteOffset,
1593 DepWriteOffset) == OW_Complete;
1596bool DSEState::isReadClobber(
const MemoryLocation &DefLoc,
1597 Instruction *UseInst) {
1610 if (CB->onlyAccessesInaccessibleMemory())
1616bool DSEState::isGuaranteedLoopIndependent(
const Instruction *Current,
1617 const Instruction *KillingDef,
1618 const MemoryLocation &CurrentLoc) {
1629 return isGuaranteedLoopInvariant(CurrentLoc.
Ptr);
1632bool DSEState::isGuaranteedLoopInvariant(
const Value *Ptr) {
1635 if (
GEP->hasAllConstantIndices())
1639 return I->getParent()->isEntryBlock() || !CI.
getCycle(
I->getParent());
1644std::optional<MemoryAccess *> DSEState::getDomMemoryDef(
1645 MemoryDef *KillingDef, MemoryAccess *StartAccess,
1646 const MemoryLocation &KillingLoc,
const Value *KillingUndObj,
1647 unsigned &ScanLimit,
unsigned &WalkerStepLimit,
bool IsMemTerm,
1648 unsigned &PartialLimit,
bool IsInitializesAttrMemLoc) {
1649 if (ScanLimit == 0 || WalkerStepLimit == 0) {
1651 return std::nullopt;
1654 MemoryAccess *Current = StartAccess;
1668 std::optional<MemoryLocation> CurrentLoc;
1671 dbgs() <<
" visiting " << *Current;
1684 return std::nullopt;
1692 if (WalkerStepLimit <= StepCost) {
1694 return std::nullopt;
1696 WalkerStepLimit -= StepCost;
1710 if (
canSkipDef(CurrentDef, !isInvisibleToCallerOnUnwind(KillingUndObj))) {
1711 CanOptimize =
false;
1717 if (mayThrowBetween(KillingI, CurrentI, KillingUndObj)) {
1719 return std::nullopt;
1724 if (isDSEBarrier(KillingUndObj, CurrentI)) {
1726 return std::nullopt;
1734 return std::nullopt;
1737 if (
any_of(Current->
uses(), [
this, &KillingLoc, StartAccess](Use &U) {
1738 if (auto *UseOrDef = dyn_cast<MemoryUseOrDef>(U.getUser()))
1739 return !MSSA.dominates(StartAccess, UseOrDef) &&
1740 isReadClobber(KillingLoc, UseOrDef->getMemoryInst());
1744 return std::nullopt;
1749 CurrentLoc = getLocForWrite(CurrentI);
1750 if (!CurrentLoc || !isRemovable(CurrentI)) {
1751 CanOptimize =
false;
1758 if (!isGuaranteedLoopIndependent(CurrentI, KillingI, *CurrentLoc)) {
1760 CanOptimize =
false;
1768 if (!isMemTerminator(*CurrentLoc, CurrentI, KillingI)) {
1769 CanOptimize =
false;
1773 int64_t KillingOffset = 0;
1774 int64_t DeadOffset = 0;
1775 auto OR = isOverwrite(KillingI, CurrentI, KillingLoc, *CurrentLoc,
1776 KillingOffset, DeadOffset);
1782 (OR == OW_Complete || OR == OW_MaybePartial))
1788 CanOptimize =
false;
1793 if (OR == OW_Unknown || OR == OW_None)
1795 else if (OR == OW_MaybePartial) {
1800 if (PartialLimit <= 1) {
1801 WalkerStepLimit -= 1;
1802 LLVM_DEBUG(
dbgs() <<
" ... reached partial limit ... continue with "
1816 SmallPtrSet<Instruction *, 16> KillingDefs;
1818 MemoryAccess *MaybeDeadAccess = Current;
1819 MemoryLocation MaybeDeadLoc = *CurrentLoc;
1821 LLVM_DEBUG(
dbgs() <<
" Checking for reads of " << *MaybeDeadAccess <<
" ("
1822 << *MaybeDeadI <<
")\n");
1825 SmallPtrSet<MemoryAccess *, 32> Visited;
1829 for (
unsigned I = 0;
I < WorkList.
size();
I++) {
1830 MemoryAccess *UseAccess = WorkList[
I];
1834 if (ScanLimit < (WorkList.
size() -
I)) {
1836 return std::nullopt;
1839 NumDomMemDefChecks++;
1842 if (
any_of(KillingDefs, [
this, UseAccess](Instruction *KI) {
1845 LLVM_DEBUG(
dbgs() <<
" ... skipping, dominated by killing block\n");
1856 if (
any_of(KillingDefs, [
this, UseInst](Instruction *KI) {
1859 LLVM_DEBUG(
dbgs() <<
" ... skipping, dominated by killing def\n");
1865 if (isMemTerminator(MaybeDeadLoc, MaybeDeadI, UseInst)) {
1868 <<
" ... skipping, memterminator invalidates following accesses\n");
1878 if (UseInst->
mayThrow() && !isInvisibleToCallerOnUnwind(KillingUndObj)) {
1880 return std::nullopt;
1887 bool IsKillingDefFromInitAttr =
false;
1888 if (IsInitializesAttrMemLoc) {
1889 if (KillingI == UseInst &&
1891 IsKillingDefFromInitAttr =
true;
1894 if (isReadClobber(MaybeDeadLoc, UseInst) && !IsKillingDefFromInitAttr) {
1896 return std::nullopt;
1902 if (MaybeDeadAccess == UseAccess &&
1903 !isGuaranteedLoopInvariant(MaybeDeadLoc.
Ptr)) {
1904 LLVM_DEBUG(
dbgs() <<
" ... found not loop invariant self access\n");
1905 return std::nullopt;
1911 if (KillingDef == UseAccess || MaybeDeadAccess == UseAccess) {
1927 if (isCompleteOverwrite(MaybeDeadLoc, MaybeDeadI, UseInst)) {
1929 if (PostOrderNumbers.
find(MaybeKillingBlock)->second <
1930 PostOrderNumbers.
find(MaybeDeadAccess->
getBlock())->second) {
1931 if (!isInvisibleToCallerAfterRet(KillingUndObj, KillingLoc.
Ptr,
1934 <<
" ... found killing def " << *UseInst <<
"\n");
1935 KillingDefs.
insert(UseInst);
1939 <<
" ... found preceeding def " << *UseInst <<
"\n");
1940 return std::nullopt;
1950 if (!isInvisibleToCallerAfterRet(KillingUndObj, KillingLoc.
Ptr,
1952 SmallPtrSet<BasicBlock *, 16> KillingBlocks;
1953 for (Instruction *KD : KillingDefs)
1954 KillingBlocks.
insert(KD->getParent());
1956 "Expected at least a single killing block");
1970 if (!AnyUnreachableExit)
1971 return std::nullopt;
1975 CommonPred =
nullptr;
1979 if (KillingBlocks.
count(CommonPred))
1980 return {MaybeDeadAccess};
1982 SetVector<BasicBlock *> WorkList;
1986 WorkList.
insert(CommonPred);
1988 for (BasicBlock *R : PDT.
roots()) {
1996 for (
unsigned I = 0;
I < WorkList.
size();
I++) {
1999 if (KillingBlocks.
count(Current))
2001 if (Current == MaybeDeadAccess->
getBlock())
2002 return std::nullopt;
2012 return std::nullopt;
2019 return {MaybeDeadAccess};
2022void DSEState::deleteDeadInstruction(Instruction *SI,
2023 SmallPtrSetImpl<MemoryAccess *> *
Deleted) {
2024 MemorySSAUpdater Updater(&MSSA);
2029 while (!NowDeadInsts.
empty()) {
2043 SkipStores.insert(MD);
2047 if (
SI->getValueOperand()->getType()->isPointerTy()) {
2049 if (CapturedBeforeReturn.erase(UO))
2050 ShouldIterateEndOfFunctionDSE =
true;
2051 InvisibleToCallerAfterRet.erase(UO);
2052 InvisibleToCallerAfterRetBounded.erase(UO);
2057 Updater.removeMemoryAccess(MA);
2061 if (
I != IOLs.end())
2062 I->second.erase(DeadInst);
2064 for (Use &O : DeadInst->
operands())
2084bool DSEState::mayThrowBetween(Instruction *KillingI, Instruction *DeadI,
2085 const Value *KillingUndObj) {
2089 if (KillingUndObj && isInvisibleToCallerOnUnwind(KillingUndObj))
2093 return ThrowingBlocks.count(KillingI->
getParent());
2094 return !ThrowingBlocks.empty();
2097bool DSEState::isDSEBarrier(
const Value *KillingUndObj, Instruction *DeadI) {
2100 if (DeadI->
mayThrow() && !isInvisibleToCallerOnUnwind(KillingUndObj))
2120bool DSEState::eliminateDeadWritesAtEndOfFunction() {
2121 bool MadeChange =
false;
2123 dbgs() <<
"Trying to eliminate MemoryDefs at the end of the function\n");
2125 ShouldIterateEndOfFunctionDSE =
false;
2127 if (SkipStores.contains(Def))
2131 auto DefLoc = getLocForWrite(DefI);
2132 if (!DefLoc || !isRemovable(DefI)) {
2134 "instruction not removable.\n");
2144 if (!isInvisibleToCallerAfterRet(UO, DefLoc->
Ptr, DefLoc->
Size))
2147 if (isWriteAtEndOfFunction(Def, *DefLoc)) {
2149 LLVM_DEBUG(
dbgs() <<
" ... MemoryDef is not accessed until the end "
2150 "of the function\n");
2156 }
while (ShouldIterateEndOfFunctionDSE);
2160bool DSEState::eliminateRedundantStoresViaDominatingConditions() {
2161 bool MadeChange =
false;
2162 LLVM_DEBUG(
dbgs() <<
"Trying to eliminate MemoryDefs whose value being "
2163 "written is implied by a dominating condition\n");
2165 using ConditionInfo = std::pair<Value *, Value *>;
2166 using ScopedHTType = ScopedHashTable<ConditionInfo, Instruction *>;
2170 ScopedHTType ActiveConditions;
2171 auto GetDominatingCondition = [&](
BasicBlock *BB)
2172 -> std::optional<std::tuple<ConditionInfo, Instruction *, BasicBlock *>> {
2175 return std::nullopt;
2180 if (BI->getSuccessor(0) == BI->getSuccessor(1))
2181 return std::nullopt;
2185 Value *StorePtr, *StoreVal;
2186 if (!
match(BI->getCondition(),
2190 return std::nullopt;
2196 return std::nullopt;
2198 unsigned ImpliedSuccIdx = Pred == ICmpInst::ICMP_EQ ? 0 : 1;
2199 BasicBlock *ImpliedSucc = BI->getSuccessor(ImpliedSuccIdx);
2200 return {{ConditionInfo(StorePtr, StoreVal), ICmpL, ImpliedSucc}};
2216 if (!SI || !
SI->isUnordered())
2220 {
SI->getPointerOperand(),
SI->getValueOperand()});
2228 MemoryAccess *ClobberingAccess =
2230 if (MSSA.
dominates(ClobberingAccess, LoadAccess)) {
2232 <<
"Removing No-Op Store:\n DEAD: " << *SI <<
'\n');
2234 NumRedundantStores++;
2241 auto MaybeCondition = GetDominatingCondition(BB);
2245 ScopedHTType::ScopeTy
Scope(ActiveConditions);
2246 if (MaybeCondition) {
2247 const auto &[
Cond, LI, ImpliedSucc] = *MaybeCondition;
2248 if (DT.
dominates(BasicBlockEdge(BB, ImpliedSucc), Child->getBlock())) {
2252 ActiveConditions.insert(
Cond, LI);
2259 Self(Child,
Depth + 1, Self);
2269bool DSEState::tryFoldIntoCalloc(MemoryDef *Def,
const Value *DefUO) {
2276 if (!StoredConstant || !StoredConstant->
isNullValue())
2279 if (!isRemovable(DefI))
2283 if (
F.hasFnAttribute(Attribute::SanitizeMemory) ||
2284 F.hasFnAttribute(Attribute::SanitizeAddress) ||
2285 F.hasFnAttribute(Attribute::SanitizeHWAddress) ||
F.getName() ==
"calloc")
2290 auto *InnerCallee =
Malloc->getCalledFunction();
2293 LibFunc
Func = NotLibFunc;
2294 StringRef ZeroedVariantName;
2295 if (!TLI.
getLibFunc(*InnerCallee, Func) || !TLI.
has(Func) ||
2296 Func != LibFunc_malloc) {
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 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.
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.
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.
@ BasicBlock
Various leaf nodes.
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
bool match(Val *V, const Pattern &P)
match_bind< Instruction > m_Instruction(Instruction *&I)
Match an instruction, capturing it if we match.
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
CmpClass_match< LHS, RHS, ICmpInst, true > m_c_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
Matches an ICmp with a predicate over LHS and RHS in either order.
auto m_Value()
Match an arbitrary value and ignore it.
SpecificCmpClass_match< LHS, RHS, ICmpInst > m_SpecificICmp(CmpPredicate MatchPred, const LHS &L, const RHS &R)
OneOps_match< OpTy, Instruction::Load > m_Load(const OpTy &Op)
Matches LoadInst.
brc_match< Cond_t, match_bind< BasicBlock >, match_bind< BasicBlock > > m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F)
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
SmallVector< DbgVariableRecord * > getDVRAssignmentMarkers(const Instruction *Inst)
Return a range of dbg_assign records for which Inst performs the assignment they encode.
LLVM_ABI bool calculateFragmentIntersect(const DataLayout &DL, const Value *Dest, uint64_t SliceOffsetInBits, uint64_t SliceSizeInBits, const DbgVariableRecord *DVRAssign, std::optional< DIExpression::FragmentInfo > &Result)
Calculate the fragment of the variable in DAI covered from (Dest + SliceOffsetInBits) to to (Dest + S...
initializer< Ty > init(const Ty &Val)
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
NodeAddr< DefNode * > Def
NodeAddr< NodeBase * > Node
NodeAddr< FuncNode * > Func
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
LLVM_ABI void initializeDSELegacyPassPass(PassRegistry &)
LLVM_ABI Constant * getInitialValueOfAllocation(const Value *V, const TargetLibraryInfo *TLI, Type *Ty)
If this is a call to an allocation function that initializes memory to a fixed value,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isStrongerThanMonotonic(AtomicOrdering AO)
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
LLVM_ABI void salvageDebugInfo(const MachineRegisterInfo &MRI, MachineInstr &MI)
Assuming the instruction MI is going to be deleted, attempt to salvage debug users of MI by writing t...
@ Store
The extracted value is stored (ExtractElement only).
Value * GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, const DataLayout &DL, bool AllowNonInbounds=true)
Analyze the specified pointer to see if it can be expressed as a base pointer plus a constant offset.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
LLVM_ABI bool isNoAliasCall(const Value *V)
Return true if this pointer is returned by a noalias function.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
DomTreeNodeBase< BasicBlock > DomTreeNode
auto dyn_cast_or_null(const Y &Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction is not used, and the instruction will return.
LLVM_ABI bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL, const TargetLibraryInfo *TLI, ObjectSizeOpts Opts={})
Compute the size of the object pointed by Ptr.
auto reverse(ContainerTy &&C)
LLVM_ABI bool canReplacePointersIfEqual(const Value *From, const Value *To, const DataLayout &DL)
Returns true if a pointer value From can be replaced with another pointer value \To if they are deeme...
bool isModSet(const ModRefInfo MRI)
LLVM_ABI bool NullPointerIsDefined(const Function *F, unsigned AS=0)
Check whether null pointer dereferencing is considered undefined behavior for a given function or an ...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI bool AreStatisticsEnabled()
Check if statistics are enabled.
LLVM_ABI bool isNotVisibleOnUnwind(const Value *Object, bool &RequiresNoCaptureBeforeUnwind)
Return true if Object memory is not visible after an unwind, in the sense that program semantics cann...
LLVM_ABI Value * emitCalloc(Value *Num, Value *Size, IRBuilderBase &B, const TargetLibraryInfo &TLI, unsigned AddrSpace)
Emit a call to the calloc function.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
auto post_order(const T &G)
Post-order traversal of a graph.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
uint64_t offsetToAlignment(uint64_t Value, Align Alignment)
Returns the offset to the next integer (mod 2**64) that is greater than or equal to Value and is a mu...
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI bool salvageKnowledge(Instruction *I, AssumptionCache *AC=nullptr, DominatorTree *DT=nullptr)
Calls BuildAssumeFromInst and if the resulting llvm.assume is valid insert if before I.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
LLVM_ABI bool PointerMayBeCaptured(const Value *V, bool ReturnCaptures, unsigned MaxUsesToExplore=0)
PointerMayBeCaptured - Return true if this pointer value may be captured by the enclosing function (w...
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI Value * getFreedOperand(const CallBase *CB, const TargetLibraryInfo *TLI)
If this if a call to a free function, return the freed operand.
LLVM_ABI bool isIdentifiedFunctionLocal(const Value *V)
Return true if V is umabigously identified at the function-level.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI FunctionPass * createDeadStoreEliminationPass()
LLVM_ABI Value * isBytewiseValue(Value *V, const DataLayout &DL)
If the specified value can be set by repeating the same byte in memory, return the i8 value that it i...
auto predecessors(const MachineBasicBlock *BB)
bool capturesAnything(CaptureComponents CC)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
AAResults AliasAnalysis
Temporary typedef for legacy code that uses a generic AliasAnalysis pointer or reference.
bool capturesNothing(CaptureComponents CC)
LLVM_ABI bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
bool isStrongerThan(AtomicOrdering AO, AtomicOrdering Other)
Returns true if ao is stronger than other as defined by the AtomicOrdering lattice,...
bool isRefSet(const ModRefInfo MRI)
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Various options to control the behavior of getObjectSize.
bool NullIsUnknownSize
If this is true, null pointers in address space 0 will be treated as though they can't be evaluated.