97#define DEBUG_TYPE "dse"
99STATISTIC(NumRemainingStores,
"Number of stores remaining after DSE");
100STATISTIC(NumRedundantStores,
"Number of redundant stores deleted");
102STATISTIC(NumFastOther,
"Number of other instrs removed");
103STATISTIC(NumCompletePartials,
"Number of stores dead by later partials");
104STATISTIC(NumModifiedStores,
"Number of stores modified");
109 "Number of times a valid candidate is returned from getDomMemoryDef");
111 "Number iterations check for reads in getDomMemoryDef");
114 "Controls which MemoryDefs are eliminated.");
130 switch (
II->getIntrinsicID()) {
131 default:
return false;
132 case Intrinsic::memset:
133 case Intrinsic::memcpy:
134 case Intrinsic::memcpy_element_unordered_atomic:
135 case Intrinsic::memset_element_unordered_atomic:
170enum OverwriteResult {
174 OW_PartialEarlierWithFullLater,
190 if (KillingII ==
nullptr || DeadII ==
nullptr)
192 if (KillingII->getIntrinsicID() != DeadII->getIntrinsicID())
195 switch (KillingII->getIntrinsicID()) {
196 case Intrinsic::masked_store:
197 case Intrinsic::vp_store: {
199 auto *KillingTy = KillingII->getArgOperand(0)->getType();
200 auto *DeadTy = DeadII->getArgOperand(0)->getType();
201 if (
DL.getTypeSizeInBits(KillingTy) !=
DL.getTypeSizeInBits(DeadTy))
208 Value *KillingPtr = KillingII->getArgOperand(1);
209 Value *DeadPtr = DeadII->getArgOperand(1);
210 if (KillingPtr != DeadPtr && !
AA.isMustAlias(KillingPtr, DeadPtr))
212 if (KillingII->getIntrinsicID() == Intrinsic::masked_store) {
215 if (KillingII->getArgOperand(2) != DeadII->getArgOperand(2))
217 }
else if (KillingII->getIntrinsicID() == Intrinsic::vp_store) {
220 if (KillingII->getArgOperand(2) != DeadII->getArgOperand(2))
223 if (KillingII->getArgOperand(3) != DeadII->getArgOperand(3))
246 int64_t KillingOff, int64_t DeadOff,
256 if (Opts.enable_dse_partial_overwrite_tracking &&
257 KillingOff < int64_t(DeadOff + DeadSize) &&
258 int64_t(KillingOff + KillingSize) >= DeadOff) {
261 auto &IM = IOL[DeadI];
262 LLVM_DEBUG(
dbgs() <<
"DSE: Partial overwrite: DeadLoc [" << DeadOff <<
", "
263 << int64_t(DeadOff + DeadSize) <<
") KillingLoc ["
264 << KillingOff <<
", " << int64_t(KillingOff + KillingSize)
271 int64_t KillingIntStart = KillingOff;
272 int64_t KillingIntEnd = KillingOff + KillingSize;
276 auto ILI = IM.lower_bound(KillingIntStart);
277 if (ILI != IM.end() && ILI->second <= KillingIntEnd) {
281 KillingIntStart = std::min(KillingIntStart, ILI->second);
282 KillingIntEnd = std::max(KillingIntEnd, ILI->first);
291 while (ILI != IM.end() && ILI->second <= KillingIntEnd) {
292 assert(ILI->second > KillingIntStart &&
"Unexpected interval");
293 KillingIntEnd = std::max(KillingIntEnd, ILI->first);
298 IM[KillingIntEnd] = KillingIntStart;
301 if (ILI->second <= DeadOff && ILI->first >= int64_t(DeadOff + DeadSize)) {
302 LLVM_DEBUG(
dbgs() <<
"DSE: Full overwrite from partials: DeadLoc ["
303 << DeadOff <<
", " << int64_t(DeadOff + DeadSize)
304 <<
") Composite KillingLoc [" << ILI->second <<
", "
305 << ILI->first <<
")\n");
306 ++NumCompletePartials;
313 if (Opts.enable_dse_partial_store_merging && KillingOff >= DeadOff &&
314 int64_t(DeadOff + DeadSize) > KillingOff &&
315 uint64_t(KillingOff - DeadOff) + KillingSize <= DeadSize) {
316 LLVM_DEBUG(
dbgs() <<
"DSE: Partial overwrite a dead load [" << DeadOff
317 <<
", " << int64_t(DeadOff + DeadSize)
318 <<
") by a killing store [" << KillingOff <<
", "
319 << int64_t(KillingOff + KillingSize) <<
")\n");
321 return OW_PartialEarlierWithFullLater;
333 if (!Opts.enable_dse_partial_overwrite_tracking &&
334 (KillingOff > DeadOff && KillingOff < int64_t(DeadOff + DeadSize) &&
335 int64_t(KillingOff + KillingSize) >= int64_t(DeadOff + DeadSize)))
347 if (!Opts.enable_dse_partial_overwrite_tracking &&
348 (KillingOff <= DeadOff && int64_t(KillingOff + KillingSize) > DeadOff)) {
349 assert(int64_t(KillingOff + KillingSize) < int64_t(DeadOff + DeadSize) &&
350 "Expect to be handled as OW_Complete");
370 using BlockAddressPair = std::pair<BasicBlock *, PHITransAddr>;
387 auto *MemLocPtr =
const_cast<Value *
>(MemLoc.
Ptr);
392 bool isFirstBlock =
true;
395 while (!WorkList.
empty()) {
407 assert(
B == SecondBB &&
"first block is not the store block");
409 isFirstBlock =
false;
415 for (; BI != EI; ++BI) {
417 if (
I->mayWriteToMemory() &&
I != SecondI)
423 "Should not hit the entry block because SI must be dominated by LI");
433 auto Inserted = Visited.
insert(std::make_pair(Pred, TranslatedPtr));
434 if (!Inserted.second) {
437 if (TranslatedPtr != Inserted.first->second)
442 WorkList.
push_back(std::make_pair(Pred, PredAddr));
451 bool IsOverwriteEnd) {
453 uint64_t DeadSliceSizeInBits = OldSizeInBits - NewSizeInBits;
460 uint64_t DeadSliceOffsetInBits = IsOverwriteEnd ? NewSizeInBits : 0;
461 auto SetDeadFragExpr = [](
auto *Assign,
465 uint64_t RelativeOffset = DeadFragment.OffsetInBits -
466 Assign->getExpression()
471 Assign->getExpression(), RelativeOffset, DeadFragment.SizeInBits)) {
472 Assign->setExpression(*
NewExpr);
479 DeadFragment.SizeInBits);
480 Assign->setExpression(Expr);
481 Assign->setKillLocation();
488 auto GetDeadLink = [&Ctx, &LinkToNothing]() {
491 return LinkToNothing;
497 std::optional<DIExpression::FragmentInfo> NewFragment;
499 DeadSliceSizeInBits, Assign,
506 Assign->setKillAddress();
507 Assign->setAssignId(GetDeadLink());
511 if (NewFragment->SizeInBits == 0)
515 auto *NewAssign =
static_cast<decltype(Assign)
>(Assign->clone());
516 NewAssign->insertAfter(Assign->getIterator());
517 NewAssign->setAssignId(GetDeadLink());
519 SetDeadFragExpr(NewAssign, *NewFragment);
520 NewAssign->setKillAddress();
534 for (
auto &Attr : OldAttrs) {
535 if (Attr.hasKindAsEnum()) {
536 switch (Attr.getKindAsEnum()) {
539 case Attribute::Alignment:
541 if (
isAligned(Attr.getAlignment().valueOrOne(), PtrOffset))
544 case Attribute::Dereferenceable:
545 case Attribute::DereferenceableOrNull:
549 case Attribute::NonNull:
550 case Attribute::NoUndef:
558 Intrinsic->removeParamAttrs(ArgNo, AttrsToRemove);
562 uint64_t &DeadSize, int64_t KillingStart,
563 uint64_t KillingSize,
bool IsOverwriteEnd) {
565 Align PrefAlign = DeadIntrinsic->getDestAlign().valueOrOne();
581 int64_t ToRemoveStart = 0;
585 if (IsOverwriteEnd) {
590 ToRemoveStart = KillingStart +
Off;
591 if (DeadSize <=
uint64_t(ToRemoveStart - DeadStart))
593 ToRemoveSize = DeadSize -
uint64_t(ToRemoveStart - DeadStart);
595 ToRemoveStart = DeadStart;
597 "Not overlapping accesses?");
598 ToRemoveSize = KillingSize -
uint64_t(DeadStart - KillingStart);
603 if (ToRemoveSize <= (PrefAlign.
value() -
Off))
605 ToRemoveSize -= PrefAlign.
value() -
Off;
608 "Should preserve selected alignment");
611 assert(ToRemoveSize > 0 &&
"Shouldn't reach here if nothing to remove");
612 assert(DeadSize > ToRemoveSize &&
"Can't remove more than original size");
614 uint64_t NewSize = DeadSize - ToRemoveSize;
615 if (DeadIntrinsic->isAtomic()) {
618 const uint32_t ElementSize = DeadIntrinsic->getElementSizeInBytes();
619 if (0 != NewSize % ElementSize)
624 << (IsOverwriteEnd ?
"END" :
"BEGIN") <<
": " << *DeadI
625 <<
"\n KILLER [" << ToRemoveStart <<
", "
626 << int64_t(ToRemoveStart + ToRemoveSize) <<
")\n");
628 DeadIntrinsic->setLength(NewSize);
629 DeadIntrinsic->setDestAlignment(PrefAlign);
631 Value *OrigDest = DeadIntrinsic->getRawDest();
632 if (!IsOverwriteEnd) {
633 Value *Indices[1] = {
634 ConstantInt::get(DeadIntrinsic->getLength()->getType(), ToRemoveSize)};
638 NewDestGEP->
setDebugLoc(DeadIntrinsic->getDebugLoc());
639 DeadIntrinsic->setDest(NewDestGEP);
648 DeadStart += ToRemoveSize;
655 int64_t &DeadStart,
uint64_t &DeadSize) {
660 int64_t KillingStart = OII->second;
661 uint64_t KillingSize = OII->first - KillingStart;
663 assert(OII->first - KillingStart >= 0 &&
"Size expected to be positive");
665 if (KillingStart > DeadStart &&
668 (
uint64_t)(KillingStart - DeadStart) < DeadSize &&
671 KillingSize >= DeadSize - (
uint64_t)(KillingStart - DeadStart)) {
672 if (
tryToShorten(DeadI, DeadStart, DeadSize, KillingStart, KillingSize,
683 int64_t &DeadStart,
uint64_t &DeadSize) {
688 int64_t KillingStart = OII->second;
689 uint64_t KillingSize = OII->first - KillingStart;
691 assert(OII->first - KillingStart >= 0 &&
"Size expected to be positive");
693 if (KillingStart <= DeadStart &&
696 KillingSize > (
uint64_t)(DeadStart - KillingStart)) {
699 assert(KillingSize - (
uint64_t)(DeadStart - KillingStart) < DeadSize &&
700 "Should have been handled as OW_Complete");
701 if (
tryToShorten(DeadI, DeadStart, DeadSize, KillingStart, KillingSize,
712 int64_t KillingOffset, int64_t DeadOffset,
756 unsigned BitOffsetDiff = (KillingOffset - DeadOffset) * 8;
757 unsigned LShiftAmount =
758 DL.isBigEndian() ? DeadValue.
getBitWidth() - BitOffsetDiff - KillingBits
761 LShiftAmount + KillingBits);
764 APInt Merged = (DeadValue & ~Mask) | (KillingValue << LShiftAmount);
766 <<
"\n Killing: " << *KillingI
767 <<
"\n Merged Value: " << Merged <<
'\n');
774 switch (
II->getIntrinsicID()) {
775 case Intrinsic::lifetime_start:
776 case Intrinsic::lifetime_end:
777 case Intrinsic::invariant_end:
778 case Intrinsic::launder_invariant_group:
779 case Intrinsic::assume:
781 case Intrinsic::dbg_declare:
782 case Intrinsic::dbg_label:
783 case Intrinsic::dbg_value:
798 if (CB->onlyAccessesInaccessibleMemory())
803 if (DI->
mayThrow() && !DefVisibleToCaller)
825struct MemoryLocationWrapper {
826 MemoryLocationWrapper(MemoryLocation MemLoc, MemoryDef *MemDef,
827 bool DefByInitializesAttr)
828 : MemLoc(MemLoc), MemDef(MemDef),
829 DefByInitializesAttr(DefByInitializesAttr) {
830 assert(MemLoc.Ptr &&
"MemLoc should be not null");
832 DefInst = MemDef->getMemoryInst();
835 MemoryLocation MemLoc;
836 const Value *UnderlyingObject;
839 bool DefByInitializesAttr =
false;
844struct MemoryDefWrapper {
845 MemoryDefWrapper(MemoryDef *MemDef,
846 ArrayRef<std::pair<MemoryLocation, bool>> MemLocations) {
848 for (
auto &[MemLoc, DefByInitializesAttr] : MemLocations)
849 DefinedLocations.push_back(
850 MemoryLocationWrapper(MemLoc, MemDef, DefByInitializesAttr));
856struct ArgumentInitInfo {
858 bool IsDeadOrInvisibleOnUnwind;
859 ConstantRangeList Inits;
874 bool CallHasNoUnwindAttr) {
880 for (
const auto &Arg : Args) {
881 if (!CallHasNoUnwindAttr && !Arg.IsDeadOrInvisibleOnUnwind)
883 if (Arg.Inits.empty())
888 for (
auto &Arg : Args.drop_front())
889 IntersectedIntervals = IntersectedIntervals.
intersectWith(Arg.Inits);
891 return IntersectedIntervals;
897 const ScalarOptions &Opts;
900 EarliestEscapeAnalysis EA;
909 BatchAAResults BatchAA;
913 PostDominatorTree &PDT;
914 const TargetLibraryInfo &TLI;
915 const DataLayout &DL;
921 SmallPtrSet<MemoryAccess *, 4> SkipStores;
923 DenseMap<const Value *, bool> CapturedBeforeReturn;
926 DenseMap<const Value *, bool> InvisibleToCallerAfterRet;
927 DenseMap<const Value *, uint64_t> InvisibleToCallerAfterRetBounded;
929 SmallPtrSet<BasicBlock *, 16> ThrowingBlocks;
932 DenseMap<BasicBlock *, unsigned> PostOrderNumbers;
936 MapVector<BasicBlock *, InstOverlapIntervalsTy> IOLs;
940 bool AnyUnreachableExit;
945 bool ShouldIterateEndOfFunctionDSE;
948 SmallVector<Instruction *> ToRemove;
952 MemorySSA &MSSA, DominatorTree &DT, PostDominatorTree &PDT,
953 const TargetLibraryInfo &TLI,
const CycleInfo &CI);
954 DSEState(
const DSEState &) =
delete;
955 DSEState &operator=(
const DSEState &) =
delete;
957 LocationSize strengthenLocationSize(
const Instruction *
I,
958 LocationSize
Size)
const;
968 OverwriteResult isOverwrite(
const Instruction *KillingI,
969 const Instruction *DeadI,
970 const MemoryLocation &KillingLoc,
971 const MemoryLocation &DeadLoc,
972 int64_t &KillingOff, int64_t &DeadOff);
974 bool isInvisibleToCallerAfterRet(
const Value *V,
const Value *Ptr,
975 const LocationSize StoreSize);
977 bool isInvisibleToCallerOnUnwind(
const Value *V);
979 std::optional<MemoryLocation> getLocForWrite(Instruction *
I)
const;
984 getLocForInst(Instruction *
I,
bool ConsiderInitializesAttr);
988 bool isRemovable(Instruction *
I);
992 bool isCompleteOverwrite(
const MemoryLocation &DefLoc, Instruction *DefInst,
993 Instruction *UseInst);
996 bool isWriteAtEndOfFunction(MemoryDef *Def,
const MemoryLocation &DefLoc);
1001 std::optional<std::pair<MemoryLocation, bool>>
1002 getLocForTerminator(Instruction *
I)
const;
1006 bool isMemTerminatorInst(Instruction *
I)
const;
1010 bool isMemTerminator(
const MemoryLocation &Loc, Instruction *AccessI,
1011 Instruction *MaybeTerm);
1014 bool isReadClobber(
const MemoryLocation &DefLoc, Instruction *UseInst);
1021 bool isGuaranteedLoopIndependent(
const Instruction *Current,
1022 const Instruction *KillingDef,
1023 const MemoryLocation &CurrentLoc);
1028 bool isGuaranteedLoopInvariant(
const Value *Ptr);
1036 std::optional<MemoryAccess *>
1037 getDomMemoryDef(MemoryDef *KillingDef, MemoryAccess *StartAccess,
1038 const MemoryLocation &KillingLoc,
const Value *KillingUndObj,
1039 unsigned &ScanLimit,
unsigned &WalkerStepLimit,
1040 bool IsMemTerm,
unsigned &PartialLimit,
1041 bool IsInitializesAttrMemLoc);
1047 SmallPtrSetImpl<MemoryAccess *> *
Deleted =
nullptr);
1053 bool mayThrowBetween(Instruction *KillingI, Instruction *DeadI,
1054 const Value *KillingUndObj);
1061 bool isDSEBarrier(
const Value *KillingUndObj, Instruction *DeadI);
1065 bool eliminateDeadWritesAtEndOfFunction();
1069 bool tryFoldIntoCalloc(MemoryDef *Def,
const Value *DefUO);
1073 bool storeIsNoop(MemoryDef *Def,
const Value *DefUO);
1079 bool eliminateRedundantStoresOfExistingValues();
1084 bool eliminateRedundantStoresViaDominatingConditions();
1099 std::pair<bool, bool>
1100 eliminateDeadDefs(
const MemoryLocationWrapper &KillingLocWrapper);
1104 bool eliminateDeadDefs(
const MemoryDefWrapper &KillingDefWrapper);
1114 if (Visited.
insert(MA).second)
1131 : Opts(Opts),
F(
F),
AA(
AA), EA(DT, nullptr, &CI), BatchAA(
AA, &EA),
1132 MSSA(MSSA), DT(DT), PDT(PDT), TLI(TLI),
DL(
F.getDataLayout()), CI(CI) {
1137 PostOrderNumbers[BB] = PO++;
1140 if (
I.mayThrow() && !MA)
1141 ThrowingBlocks.insert(
I.getParent());
1144 if (MD && MemDefs.size() < Opts.dse_memoryssa_defs_per_block_limit &&
1145 (getLocForWrite(&
I) || isMemTerminatorInst(&
I) ||
1146 (Opts.enable_dse_initializes_attr_improvement &&
1148 MemDefs.push_back(MD);
1155 if (AI.hasPassPointeeByValueCopyAttr()) {
1156 InvisibleToCallerAfterRet.insert({&AI, true});
1160 if (!AI.getType()->isPointerTy())
1164 if (Info.coversAllReachableMemory())
1165 InvisibleToCallerAfterRet.insert({&AI, true});
1166 else if (
uint64_t DeadBytes = Info.getNumberOfDeadBytes())
1167 InvisibleToCallerAfterRetBounded.insert({&AI, DeadBytes});
1171 return isa<UnreachableInst>(E->getTerminator());
1179 if (TLI.
has(
F) && (
F == LibFunc_memset_chk ||
F == LibFunc_memcpy_chk)) {
1195OverwriteResult DSEState::isOverwrite(
const Instruction *KillingI,
1196 const Instruction *DeadI,
1197 const MemoryLocation &KillingLoc,
1198 const MemoryLocation &DeadLoc,
1199 int64_t &KillingOff, int64_t &DeadOff) {
1203 if (!isGuaranteedLoopIndependent(DeadI, KillingI, DeadLoc))
1206 LocationSize KillingLocSize =
1207 strengthenLocationSize(KillingI, KillingLoc.
Size);
1215 if (DeadUndObj == KillingUndObj && KillingLocSize.
isPrecise() &&
1217 std::optional<TypeSize> KillingUndObjSize =
1219 if (KillingUndObjSize && *KillingUndObjSize == KillingLocSize.
getValue())
1230 if (KillingMemI && DeadMemI) {
1231 const Value *KillingV = KillingMemI->getLength();
1232 const Value *DeadV = DeadMemI->getLength();
1233 if (KillingV == DeadV && BatchAA.
isMustAlias(DeadLoc, KillingLoc))
1242 const TypeSize KillingSize = KillingLocSize.
getValue();
1251 AliasResult AAR = BatchAA.
alias(KillingLoc, DeadLoc);
1257 if (KillingSize >= DeadSize)
1270 if (DeadUndObj != KillingUndObj) {
1286 const Value *DeadBasePtr =
1288 const Value *KillingBasePtr =
1293 if (DeadBasePtr != KillingBasePtr)
1311 if (DeadOff >= KillingOff) {
1314 if (
uint64_t(DeadOff - KillingOff) + DeadSize <= KillingSize)
1318 else if ((
uint64_t)(DeadOff - KillingOff) < KillingSize)
1319 return OW_MaybePartial;
1323 else if ((
uint64_t)(KillingOff - DeadOff) < DeadSize) {
1324 return OW_MaybePartial;
1331bool DSEState::isInvisibleToCallerAfterRet(
const Value *V,
const Value *Ptr,
1332 const LocationSize StoreSize) {
1336 auto IBounded = InvisibleToCallerAfterRetBounded.find(V);
1337 if (IBounded != InvisibleToCallerAfterRetBounded.end()) {
1338 int64_t ValueOffset;
1339 [[maybe_unused]]
const Value *BaseValue =
1349 ValueOffset + StoreSize.
getValue() <= IBounded->second &&
1353 auto I = InvisibleToCallerAfterRet.insert({
V,
false});
1354 if (
I.second && isInvisibleToCallerOnUnwind(V) &&
isNoAliasCall(V))
1357 return I.first->second;
1360bool DSEState::isInvisibleToCallerOnUnwind(
const Value *V) {
1361 bool RequiresNoCaptureBeforeUnwind;
1364 if (!RequiresNoCaptureBeforeUnwind)
1367 auto I = CapturedBeforeReturn.insert({
V,
true});
1375 return !
I.first->second;
1378std::optional<MemoryLocation> DSEState::getLocForWrite(Instruction *
I)
const {
1379 if (!
I->mayWriteToMemory())
1380 return std::nullopt;
1389DSEState::getLocForInst(Instruction *
I,
bool ConsiderInitializesAttr) {
1391 if (isMemTerminatorInst(
I)) {
1392 if (
auto Loc = getLocForTerminator(
I))
1393 Locations.push_back(std::make_pair(Loc->first,
false));
1397 if (
auto Loc = getLocForWrite(
I))
1398 Locations.push_back(std::make_pair(*Loc,
false));
1400 if (ConsiderInitializesAttr) {
1401 for (
auto &MemLoc : getInitializesArgMemLoc(
I)) {
1402 Locations.push_back(std::make_pair(MemLoc,
true));
1408bool DSEState::isRemovable(Instruction *
I) {
1409 assert(getLocForWrite(
I) &&
"Must have analyzable write");
1413 return SI->isUnordered();
1418 return !
MI->isVolatile();
1422 if (CB->isLifetimeStartOrEnd())
1425 return CB->use_empty() && CB->willReturn() && CB->doesNotThrow() &&
1426 !CB->isTerminator();
1432bool DSEState::isCompleteOverwrite(
const MemoryLocation &DefLoc,
1433 Instruction *DefInst, Instruction *UseInst) {
1441 if (CB->onlyAccessesInaccessibleMemory())
1444 int64_t InstWriteOffset, DepWriteOffset;
1445 if (
auto CC = getLocForWrite(UseInst))
1446 return isOverwrite(UseInst, DefInst, *CC, DefLoc, InstWriteOffset,
1447 DepWriteOffset) == OW_Complete;
1451bool DSEState::isWriteAtEndOfFunction(MemoryDef *Def,
1452 const MemoryLocation &DefLoc) {
1454 << *
Def->getMemoryInst()
1455 <<
") is at the end the function \n");
1457 SmallPtrSet<MemoryAccess *, 8> Visited;
1460 for (
unsigned I = 0;
I < WorkList.
size();
I++) {
1461 if (WorkList.
size() >= Opts.dse_memoryssa_scanlimit) {
1466 MemoryAccess *UseAccess = WorkList[
I];
1471 if (!isGuaranteedLoopInvariant(DefLoc.
Ptr))
1480 if (isReadClobber(DefLoc, UseInst)) {
1481 LLVM_DEBUG(
dbgs() <<
" ... hit read clobber " << *UseInst <<
".\n");
1491std::optional<std::pair<MemoryLocation, bool>>
1492DSEState::getLocForTerminator(Instruction *
I)
const {
1494 if (CB->getIntrinsicID() == Intrinsic::lifetime_end)
1501 return std::nullopt;
1504bool DSEState::isMemTerminatorInst(Instruction *
I)
const {
1506 return CB && (CB->getIntrinsicID() == Intrinsic::lifetime_end ||
1510bool DSEState::isMemTerminator(
const MemoryLocation &Loc, Instruction *AccessI,
1511 Instruction *MaybeTerm) {
1512 std::optional<std::pair<MemoryLocation, bool>> MaybeTermLoc =
1513 getLocForTerminator(MaybeTerm);
1524 auto TermLoc = MaybeTermLoc->first;
1525 if (MaybeTermLoc->second) {
1529 int64_t InstWriteOffset = 0;
1530 int64_t DepWriteOffset = 0;
1531 return isOverwrite(MaybeTerm, AccessI, TermLoc, Loc, InstWriteOffset,
1532 DepWriteOffset) == OW_Complete;
1535bool DSEState::isReadClobber(
const MemoryLocation &DefLoc,
1536 Instruction *UseInst) {
1549 if (CB->onlyAccessesInaccessibleMemory())
1555bool DSEState::isGuaranteedLoopIndependent(
const Instruction *Current,
1556 const Instruction *KillingDef,
1557 const MemoryLocation &CurrentLoc) {
1568 return isGuaranteedLoopInvariant(CurrentLoc.
Ptr);
1571bool DSEState::isGuaranteedLoopInvariant(
const Value *Ptr) {
1574 if (
GEP->hasAllConstantIndices())
1578 return I->getParent()->isEntryBlock() || !CI.
getCycle(
I->getParent());
1583std::optional<MemoryAccess *> DSEState::getDomMemoryDef(
1584 MemoryDef *KillingDef, MemoryAccess *StartAccess,
1585 const MemoryLocation &KillingLoc,
const Value *KillingUndObj,
1586 unsigned &ScanLimit,
unsigned &WalkerStepLimit,
bool IsMemTerm,
1587 unsigned &PartialLimit,
bool IsInitializesAttrMemLoc) {
1588 if (ScanLimit == 0 || WalkerStepLimit == 0) {
1590 return std::nullopt;
1593 MemoryAccess *Current = StartAccess;
1602 bool CanOptimize = Opts.dse_optimize_memoryssa &&
1607 std::optional<MemoryLocation> CurrentLoc;
1610 dbgs() <<
" visiting " << *Current;
1623 return std::nullopt;
1629 ? Opts.dse_memoryssa_samebb_cost
1630 : Opts.dse_memoryssa_otherbb_cost;
1631 if (WalkerStepLimit <= StepCost) {
1633 return std::nullopt;
1635 WalkerStepLimit -= StepCost;
1649 if (
canSkipDef(CurrentDef, !isInvisibleToCallerOnUnwind(KillingUndObj))) {
1650 CanOptimize =
false;
1656 if (mayThrowBetween(KillingI, CurrentI, KillingUndObj)) {
1658 return std::nullopt;
1663 if (isDSEBarrier(KillingUndObj, CurrentI)) {
1665 return std::nullopt;
1673 return std::nullopt;
1676 if (
any_of(Current->
uses(), [
this, &KillingLoc, StartAccess](Use &U) {
1677 if (auto *UseOrDef = dyn_cast<MemoryUseOrDef>(U.getUser()))
1678 return !MSSA.dominates(StartAccess, UseOrDef) &&
1679 isReadClobber(KillingLoc, UseOrDef->getMemoryInst());
1683 return std::nullopt;
1688 CurrentLoc = getLocForWrite(CurrentI);
1689 if (!CurrentLoc || !isRemovable(CurrentI)) {
1690 CanOptimize =
false;
1697 if (!isGuaranteedLoopIndependent(CurrentI, KillingI, *CurrentLoc)) {
1699 CanOptimize =
false;
1707 if (!isMemTerminator(*CurrentLoc, CurrentI, KillingI)) {
1708 CanOptimize =
false;
1712 int64_t KillingOffset = 0;
1713 int64_t DeadOffset = 0;
1714 auto OR = isOverwrite(KillingI, CurrentI, KillingLoc, *CurrentLoc,
1715 KillingOffset, DeadOffset);
1721 (OR == OW_Complete || OR == OW_MaybePartial))
1727 CanOptimize =
false;
1732 if (OR == OW_Unknown || OR == OW_None)
1734 else if (OR == OW_MaybePartial) {
1739 if (PartialLimit <= 1) {
1740 WalkerStepLimit -= 1;
1741 LLVM_DEBUG(
dbgs() <<
" ... reached partial limit ... continue with "
1755 SmallPtrSet<Instruction *, 16> KillingDefs;
1757 MemoryAccess *MaybeDeadAccess = Current;
1758 MemoryLocation MaybeDeadLoc = *CurrentLoc;
1760 LLVM_DEBUG(
dbgs() <<
" Checking for reads of " << *MaybeDeadAccess <<
" ("
1761 << *MaybeDeadI <<
")\n");
1764 SmallPtrSet<MemoryAccess *, 32> Visited;
1768 for (
unsigned I = 0;
I < WorkList.
size();
I++) {
1769 MemoryAccess *UseAccess = WorkList[
I];
1773 if (ScanLimit < (WorkList.
size() -
I)) {
1775 return std::nullopt;
1778 NumDomMemDefChecks++;
1781 if (
any_of(KillingDefs, [
this, UseAccess](Instruction *KI) {
1784 LLVM_DEBUG(
dbgs() <<
" ... skipping, dominated by killing block\n");
1795 if (
any_of(KillingDefs, [
this, UseInst](Instruction *KI) {
1798 LLVM_DEBUG(
dbgs() <<
" ... skipping, dominated by killing def\n");
1804 if (isMemTerminator(MaybeDeadLoc, MaybeDeadI, UseInst)) {
1807 <<
" ... skipping, memterminator invalidates following accesses\n");
1817 if (UseInst->
mayThrow() && !isInvisibleToCallerOnUnwind(KillingUndObj)) {
1819 return std::nullopt;
1826 bool IsKillingDefFromInitAttr =
false;
1827 if (IsInitializesAttrMemLoc) {
1828 if (KillingI == UseInst &&
1830 IsKillingDefFromInitAttr =
true;
1833 if (isReadClobber(MaybeDeadLoc, UseInst) && !IsKillingDefFromInitAttr) {
1835 return std::nullopt;
1841 if (MaybeDeadAccess == UseAccess &&
1842 !isGuaranteedLoopInvariant(MaybeDeadLoc.
Ptr)) {
1843 LLVM_DEBUG(
dbgs() <<
" ... found not loop invariant self access\n");
1844 return std::nullopt;
1850 if (KillingDef == UseAccess || MaybeDeadAccess == UseAccess) {
1866 if (isCompleteOverwrite(MaybeDeadLoc, MaybeDeadI, UseInst)) {
1868 if (PostOrderNumbers.
find(MaybeKillingBlock)->second <
1869 PostOrderNumbers.
find(MaybeDeadAccess->
getBlock())->second) {
1870 if (!isInvisibleToCallerAfterRet(KillingUndObj, KillingLoc.
Ptr,
1873 <<
" ... found killing def " << *UseInst <<
"\n");
1874 KillingDefs.
insert(UseInst);
1878 <<
" ... found preceeding def " << *UseInst <<
"\n");
1879 return std::nullopt;
1889 if (!isInvisibleToCallerAfterRet(KillingUndObj, KillingLoc.
Ptr,
1891 SmallPtrSet<BasicBlock *, 16> KillingBlocks;
1892 for (Instruction *KD : KillingDefs)
1893 KillingBlocks.
insert(KD->getParent());
1895 "Expected at least a single killing block");
1909 if (!AnyUnreachableExit)
1910 return std::nullopt;
1914 CommonPred =
nullptr;
1918 if (KillingBlocks.
count(CommonPred))
1919 return {MaybeDeadAccess};
1921 SetVector<BasicBlock *> WorkList;
1925 WorkList.
insert(CommonPred);
1927 for (BasicBlock *R : PDT.
roots()) {
1935 for (
unsigned I = 0;
I < WorkList.
size();
I++) {
1938 if (KillingBlocks.
count(Current))
1940 if (Current == MaybeDeadAccess->
getBlock())
1941 return std::nullopt;
1950 if (WorkList.
size() >= Opts.dse_memoryssa_path_check_limit)
1951 return std::nullopt;
1958 return {MaybeDeadAccess};
1961void DSEState::deleteDeadInstruction(Instruction *SI,
1962 SmallPtrSetImpl<MemoryAccess *> *
Deleted) {
1963 MemorySSAUpdater Updater(&MSSA);
1968 while (!NowDeadInsts.
empty()) {
1982 SkipStores.insert(MD);
1986 if (
SI->getValueOperand()->getType()->isPointerTy()) {
1988 if (CapturedBeforeReturn.erase(UO))
1989 ShouldIterateEndOfFunctionDSE =
true;
1990 InvisibleToCallerAfterRet.erase(UO);
1991 InvisibleToCallerAfterRetBounded.erase(UO);
1996 Updater.removeMemoryAccess(MA);
2000 if (
I != IOLs.end())
2001 I->second.erase(DeadInst);
2003 for (Use &O : DeadInst->
operands())
2023bool DSEState::mayThrowBetween(Instruction *KillingI, Instruction *DeadI,
2024 const Value *KillingUndObj) {
2028 if (KillingUndObj && isInvisibleToCallerOnUnwind(KillingUndObj))
2032 return ThrowingBlocks.count(KillingI->
getParent());
2033 return !ThrowingBlocks.empty();
2036bool DSEState::isDSEBarrier(
const Value *KillingUndObj, Instruction *DeadI) {
2039 if (DeadI->
mayThrow() && !isInvisibleToCallerOnUnwind(KillingUndObj))
2059bool DSEState::eliminateDeadWritesAtEndOfFunction() {
2060 bool MadeChange =
false;
2062 dbgs() <<
"Trying to eliminate MemoryDefs at the end of the function\n");
2064 ShouldIterateEndOfFunctionDSE =
false;
2066 if (SkipStores.contains(Def))
2070 auto DefLoc = getLocForWrite(DefI);
2071 if (!DefLoc || !isRemovable(DefI)) {
2073 "instruction not removable.\n");
2083 if (!isInvisibleToCallerAfterRet(UO, DefLoc->
Ptr, DefLoc->
Size))
2086 if (isWriteAtEndOfFunction(Def, *DefLoc)) {
2088 LLVM_DEBUG(
dbgs() <<
" ... MemoryDef is not accessed until the end "
2089 "of the function\n");
2095 }
while (ShouldIterateEndOfFunctionDSE);
2099bool DSEState::eliminateRedundantStoresViaDominatingConditions() {
2100 bool MadeChange =
false;
2101 LLVM_DEBUG(
dbgs() <<
"Trying to eliminate MemoryDefs whose value being "
2102 "written is implied by a dominating condition\n");
2104 using ConditionInfo = std::pair<Value *, Value *>;
2105 using ScopedHTType = ScopedHashTable<ConditionInfo, Instruction *>;
2109 ScopedHTType ActiveConditions;
2110 auto GetDominatingCondition = [&](
BasicBlock *BB)
2111 -> std::optional<std::tuple<ConditionInfo, Instruction *, BasicBlock *>> {
2114 return std::nullopt;
2119 if (BI->getSuccessor(0) == BI->getSuccessor(1))
2120 return std::nullopt;
2124 Value *StorePtr, *StoreVal;
2125 if (!
match(BI->getCondition(),
2129 return std::nullopt;
2135 return std::nullopt;
2137 unsigned ImpliedSuccIdx = Pred == ICmpInst::ICMP_EQ ? 0 : 1;
2138 BasicBlock *ImpliedSucc = BI->getSuccessor(ImpliedSuccIdx);
2139 return {{ConditionInfo(StorePtr, StoreVal), ICmpL, ImpliedSucc}};
2143 if (
Depth > Opts.dse_max_dom_cond_depth)
2149 for (MemoryDef &Def :
2152 if (!SI || !
SI->isUnordered())
2156 {
SI->getPointerOperand(),
SI->getValueOperand()});
2164 MemoryAccess *ClobberingAccess =
2166 if (MSSA.
dominates(ClobberingAccess, LoadAccess)) {
2168 <<
"Removing No-Op Store:\n DEAD: " << *SI <<
'\n');
2170 NumRedundantStores++;
2177 auto MaybeCondition = GetDominatingCondition(BB);
2181 ScopedHTType::ScopeTy
Scope(ActiveConditions);
2182 if (MaybeCondition) {
2183 const auto &[
Cond, LI, ImpliedSucc] = *MaybeCondition;
2184 if (DT.
dominates(BasicBlockEdge(BB, ImpliedSucc), Child->getBlock())) {
2188 ActiveConditions.insert(
Cond, LI);
2195 Self(Child,
Depth + 1, Self);
2205bool DSEState::tryFoldIntoCalloc(MemoryDef *Def,
const Value *DefUO) {
2212 if (!StoredConstant || !StoredConstant->
isNullValue())
2215 if (!isRemovable(DefI))
2219 if (
F.hasFnAttribute(Attribute::SanitizeMemory) ||
2220 F.hasFnAttribute(Attribute::SanitizeAddress) ||
2221 F.hasFnAttribute(Attribute::SanitizeHWAddress) ||
F.getName() ==
"calloc")
2226 auto *InnerCallee =
Malloc->getCalledFunction();
2230 StringRef ZeroedVariantName;
2231 if (Func != LibFunc_malloc || !TLI.
has(Func)) {
2236 if (ZeroedVariantName.
empty())
2245 auto shouldCreateCalloc = [](CallInst *
Malloc, CallInst *Memset) {
2248 auto *MallocBB =
Malloc->getParent(), *MemsetBB = Memset->getParent();
2249 if (MallocBB == MemsetBB)
2251 auto *Ptr = Memset->getArgOperand(0);
2252 auto *TI = MallocBB->getTerminator();
2258 if (MemsetBB != FalseBB)
2269 assert(Func == LibFunc_malloc || !ZeroedVariantName.
empty());
2270 Value *Calloc =
nullptr;
2271 if (!ZeroedVariantName.
empty()) {
2272 LLVMContext &Ctx =
Malloc->getContext();
2273 AttributeList
Attrs = InnerCallee->getAttributes();
2275 Attrs.getFnAttr(Attribute::AllocKind).getAllocKind() |
2276 AllocFnKind::Zeroed;
2279 Attrs.addFnAttribute(Ctx, Attribute::getWithAllocKind(Ctx, AllocKind))
2280 .removeFnAttribute(Ctx,
"alloc-variant-zeroed");
2281 FunctionCallee ZeroedVariant =
Malloc->getModule()->getOrInsertFunction(
2282 ZeroedVariantName, InnerCallee->getFunctionType(), Attrs);
2284 ->setCallingConv(
Malloc->getCallingConv());
2287 CallInst *CI = IRB.CreateCall(ZeroedVariant, Args, ZeroedVariantName);
2291 Type *SizeTTy =
Malloc->getArgOperand(0)->getType();
2292 Calloc =
emitCalloc(ConstantInt::get(SizeTTy, 1),
Malloc->getArgOperand(0),
2293 IRB, TLI,
Malloc->getType()->getPointerAddressSpace());
2298 if (MDNode *MD =
Malloc->getMetadata(LLVMContext::MD_alloc_token))
2301 MemorySSAUpdater Updater(&MSSA);
2303 nullptr, MallocDef);
2305 Updater.insertDef(NewAccessMD,
true);
2306 Malloc->replaceAllUsesWith(Calloc);
2311bool DSEState::storeIsNoop(MemoryDef *Def,
const Value *DefUO) {
2315 Constant *StoredConstant =
nullptr;
2323 if (!isRemovable(DefI))
2326 if (StoredConstant) {
2331 if (InitC && InitC == StoredConstant)
2340 if (LoadI->getPointerOperand() ==
Store->getOperand(1)) {
2344 if (LoadAccess ==
Def->getDefiningAccess())
2350 SetVector<MemoryAccess *> ToCheck;
2351 MemoryAccess *Current =
2359 for (
unsigned I = 1;
I < ToCheck.
size(); ++
I) {
2360 Current = ToCheck[
I];
2363 for (
auto &Use : PhiAccess->incoming_values())
2375 if (LoadAccess != Current)
2387 for (
auto OI : IOL) {
2389 MemoryLocation Loc = *getLocForWrite(DeadI);
2390 assert(isRemovable(DeadI) &&
"Expect only removable instruction");
2393 int64_t DeadStart = 0;
2398 if (IntervalMap.empty())
2405bool DSEState::eliminateRedundantStoresOfExistingValues() {
2406 bool MadeChange =
false;
2407 LLVM_DEBUG(
dbgs() <<
"Trying to eliminate MemoryDefs that write the "
2408 "already existing value\n");
2409 for (
auto *Def : MemDefs) {
2414 auto MaybeDefLoc = getLocForWrite(DefInst);
2415 if (!MaybeDefLoc || !isRemovable(DefInst))
2418 MemoryDef *UpperDef;
2422 if (
Def->isOptimized())
2430 auto IsRedundantStore = [&]() {
2438 auto UpperLoc = getLocForWrite(UpperInst);
2441 int64_t InstWriteOffset = 0;
2442 int64_t DepWriteOffset = 0;
2443 auto OR = isOverwrite(UpperInst, DefInst, *UpperLoc, *MaybeDefLoc,
2444 InstWriteOffset, DepWriteOffset);
2446 return StoredByte && StoredByte == MemSetI->getOperand(1) &&
2453 if (!IsRedundantStore() || isReadClobber(*MaybeDefLoc, DefInst))
2455 LLVM_DEBUG(
dbgs() <<
"DSE: Remove No-Op Store:\n DEAD: " << *DefInst
2458 NumRedundantStores++;
2465DSEState::getInitializesArgMemLoc(
const Instruction *
I) {
2471 SmallMapVector<Value *, SmallVector<ArgumentInitInfo, 2>, 2>
Arguments;
2477 ConstantRangeList Inits;
2489 Inits = ConstantRangeList();
2497 bool IsDeadOrInvisibleOnUnwind =
2500 ArgumentInitInfo InitInfo{
Idx, IsDeadOrInvisibleOnUnwind, Inits};
2501 bool FoundAliasing =
false;
2502 for (
auto &[Arg, AliasList] :
Arguments) {
2508 FoundAliasing =
true;
2509 AliasList.push_back(InitInfo);
2514 FoundAliasing =
true;
2515 AliasList.push_back(ArgumentInitInfo{
Idx, IsDeadOrInvisibleOnUnwind,
2516 ConstantRangeList()});
2525 auto IntersectedRanges =
2527 if (IntersectedRanges.empty())
2530 for (
const auto &Arg : Args) {
2531 for (
const auto &
Range : IntersectedRanges) {
2545std::pair<bool, bool>
2546DSEState::eliminateDeadDefs(
const MemoryLocationWrapper &KillingLocWrapper) {
2548 bool DeletedKillingLoc =
false;
2549 unsigned ScanLimit = Opts.dse_memoryssa_scanlimit;
2550 unsigned WalkerStepLimit = Opts.dse_memoryssa_walklimit;
2551 unsigned PartialLimit = Opts.dse_memoryssa_partial_store_limit;
2554 SmallSetVector<MemoryAccess *, 8> ToCheck;
2558 SmallPtrSet<MemoryAccess *, 8>
Deleted;
2559 [[maybe_unused]]
unsigned OrigNumSkipStores = SkipStores.size();
2564 for (
unsigned I = 0;
I < ToCheck.
size();
I++) {
2565 MemoryAccess *Current = ToCheck[
I];
2566 if (
Deleted.contains(Current))
2568 std::optional<MemoryAccess *> MaybeDeadAccess = getDomMemoryDef(
2569 KillingLocWrapper.MemDef, Current, KillingLocWrapper.MemLoc,
2570 KillingLocWrapper.UnderlyingObject, ScanLimit, WalkerStepLimit,
2571 isMemTerminatorInst(KillingLocWrapper.DefInst), PartialLimit,
2572 KillingLocWrapper.DefByInitializesAttr);
2574 if (!MaybeDeadAccess) {
2578 MemoryAccess *DeadAccess = *MaybeDeadAccess;
2579 LLVM_DEBUG(
dbgs() <<
" Checking if we can kill " << *DeadAccess);
2581 LLVM_DEBUG(
dbgs() <<
"\n ... adding incoming values to worklist\n");
2590 if (PostOrderNumbers[IncomingBlock] > PostOrderNumbers[PhiBlock])
2591 ToCheck.
insert(IncomingAccess);
2602 MemoryDefWrapper DeadDefWrapper(
2606 assert(DeadDefWrapper.DefinedLocations.size() == 1);
2607 MemoryLocationWrapper &DeadLocWrapper =
2608 DeadDefWrapper.DefinedLocations.front();
2611 NumGetDomMemoryDefPassed++;
2615 if (isMemTerminatorInst(KillingLocWrapper.DefInst)) {
2616 if (KillingLocWrapper.UnderlyingObject != DeadLocWrapper.UnderlyingObject)
2619 << *DeadLocWrapper.DefInst <<
"\n KILLER: "
2620 << *KillingLocWrapper.DefInst <<
'\n');
2626 int64_t KillingOffset = 0;
2627 int64_t DeadOffset = 0;
2628 OverwriteResult
OR =
2629 isOverwrite(KillingLocWrapper.DefInst, DeadLocWrapper.DefInst,
2630 KillingLocWrapper.MemLoc, DeadLocWrapper.MemLoc,
2631 KillingOffset, DeadOffset);
2632 if (OR == OW_MaybePartial) {
2633 auto &IOL = IOLs[DeadLocWrapper.DefInst->
getParent()];
2635 DeadLocWrapper.MemLoc, KillingOffset,
2636 DeadOffset, DeadLocWrapper.DefInst, IOL);
2638 if (Opts.enable_dse_partial_store_merging &&
2639 OR == OW_PartialEarlierWithFullLater) {
2645 if (DeadSI && KillingSI && DT.
dominates(DeadSI, KillingSI)) {
2647 KillingSI, DeadSI, KillingOffset, DeadOffset,
DL, BatchAA,
2651 DeadSI->setOperand(0, Merged);
2652 ++NumModifiedStores;
2654 DeletedKillingLoc =
true;
2659 auto I = IOLs.find(DeadSI->getParent());
2660 if (
I != IOLs.end())
2661 I->second.erase(DeadSI);
2666 if (OR == OW_Complete) {
2668 << *DeadLocWrapper.DefInst <<
"\n KILLER: "
2669 << *KillingLocWrapper.DefInst <<
'\n');
2677 assert(SkipStores.size() - OrigNumSkipStores ==
Deleted.size() &&
2678 "SkipStores and Deleted out of sync?");
2680 return {
Changed, DeletedKillingLoc};
2683bool DSEState::eliminateDeadDefs(
const MemoryDefWrapper &KillingDefWrapper) {
2684 if (KillingDefWrapper.DefinedLocations.empty()) {
2685 LLVM_DEBUG(
dbgs() <<
"Failed to find analyzable write location for "
2686 << *KillingDefWrapper.DefInst <<
"\n");
2690 bool MadeChange =
false;
2691 for (
auto &KillingLocWrapper : KillingDefWrapper.DefinedLocations) {
2693 << *KillingLocWrapper.MemDef <<
" ("
2694 << *KillingLocWrapper.DefInst <<
")\n");
2695 auto [
Changed, DeletedKillingLoc] = eliminateDeadDefs(KillingLocWrapper);
2699 if (!DeletedKillingLoc && storeIsNoop(KillingLocWrapper.MemDef,
2700 KillingLocWrapper.UnderlyingObject)) {
2702 << *KillingLocWrapper.DefInst <<
'\n');
2704 NumRedundantStores++;
2709 if (!DeletedKillingLoc &&
2710 tryFoldIntoCalloc(KillingLocWrapper.MemDef,
2711 KillingLocWrapper.UnderlyingObject)) {
2712 LLVM_DEBUG(
dbgs() <<
"DSE: Remove memset after forming calloc:\n"
2713 <<
" DEAD: " << *KillingLocWrapper.DefInst <<
'\n');
2726 const ScalarOptions &Opts = ScalarOptions::Global;
2727 bool MadeChange =
false;
2728 DSEState State(Opts,
F,
AA, MSSA, DT, PDT, TLI, CI);
2730 for (
unsigned I = 0;
I < State.MemDefs.size();
I++) {
2732 if (State.SkipStores.count(KillingDef))
2735 MemoryDefWrapper KillingDefWrapper(
2738 Opts.enable_dse_initializes_attr_improvement));
2739 MadeChange |= State.eliminateDeadDefs(KillingDefWrapper);
2742 if (Opts.enable_dse_partial_overwrite_tracking)
2743 for (
auto &KV : State.IOLs)
2744 MadeChange |= State.removePartiallyOverlappedStores(KV.second);
2746 MadeChange |= State.eliminateRedundantStoresOfExistingValues();
2747 MadeChange |= State.eliminateDeadWritesAtEndOfFunction();
2748 MadeChange |= State.eliminateRedundantStoresViaDominatingConditions();
2750 while (!State.ToRemove.empty()) {
2751 Instruction *DeadInst = State.ToRemove.pop_back_val();
2771#ifdef LLVM_ENABLE_STATS
2798 if (skipFunction(
F))
2801 AliasAnalysis &
AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
2802 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
2804 getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F);
2805 MemorySSA &MSSA = getAnalysis<MemorySSAWrapperPass>().getMSSA();
2807 getAnalysis<PostDominatorTreeWrapperPass>().getPostDomTree();
2808 CycleInfo &CI = getAnalysis<CycleInfoWrapperPass>().getResult();
2812#ifdef LLVM_ENABLE_STATS
2821 void getAnalysisUsage(AnalysisUsage &AU)
const override {
2837char DSELegacyPass::ID = 0;
2854 return new DSELegacyPass();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Lower Kernel Arguments
This file implements a class to represent arbitrary precision integral constant values and operations...
ReachingDefInfo InstSet & ToRemove
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file declares an analysis pass that computes CycleInfo for LLVM IR, specialized from GenericCycl...
DXIL Forward Handle Accesses
static void shortenAssignment(Instruction *Inst, Value *OriginalDest, uint64_t OldSizeInBits, uint64_t NewSizeInBits, bool IsOverwriteEnd)
static bool eliminateDeadStores(Function &F, AliasAnalysis &AA, MemorySSA &MSSA, DominatorTree &DT, PostDominatorTree &PDT, const TargetLibraryInfo &TLI, const CycleInfo &CI)
MapVector< Instruction *, OverlapIntervalsTy > InstOverlapIntervalsTy
static bool canSkipDef(MemoryDef *D, bool DefVisibleToCaller)
static bool isShortenableAtTheEnd(Instruction *I)
Returns true if the end of this instruction can be safely shortened in length.
static bool isNoopIntrinsic(Instruction *I)
static ConstantRangeList getIntersectedInitRangeList(ArrayRef< ArgumentInitInfo > Args, bool CallHasNoUnwindAttr)
static bool tryToShortenBegin(Instruction *DeadI, OverlapIntervalsTy &IntervalMap, int64_t &DeadStart, uint64_t &DeadSize)
std::map< int64_t, int64_t > OverlapIntervalsTy
static void pushMemUses(MemoryAccess *Acc, SmallVectorImpl< MemoryAccess * > &WorkList, SmallPtrSetImpl< MemoryAccess * > &Visited)
static bool isShortenableAtTheBeginning(Instruction *I)
Returns true if the beginning of this instruction can be safely shortened in length.
static Constant * tryToMergePartialOverlappingStores(StoreInst *KillingI, StoreInst *DeadI, int64_t KillingOffset, int64_t DeadOffset, const DataLayout &DL, BatchAAResults &AA, DominatorTree *DT)
static OverwriteResult isPartialOverwrite(const ScalarOptions &Opts, const MemoryLocation &KillingLoc, const MemoryLocation &DeadLoc, int64_t KillingOff, int64_t DeadOff, Instruction *DeadI, InstOverlapIntervalsTy &IOL)
Return 'OW_Complete' if a store to the 'KillingLoc' location completely overwrites a store to the 'De...
static bool memoryIsNotModifiedBetween(Instruction *FirstI, Instruction *SecondI, BatchAAResults &AA, const DataLayout &DL, DominatorTree *DT)
Returns true if the memory which is accessed by the second instruction is not modified between the fi...
static OverwriteResult isMaskedStoreOverwrite(const Instruction *KillingI, const Instruction *DeadI, BatchAAResults &AA)
Check if two instruction are masked stores that completely overwrite one another.
static bool tryToShorten(Instruction *DeadI, int64_t &DeadStart, uint64_t &DeadSize, int64_t KillingStart, uint64_t KillingSize, bool IsOverwriteEnd)
static bool isFuncLocalAndNotCaptured(Value *Arg, const CallBase *CB, EarliestEscapeAnalysis &EA)
static std::optional< TypeSize > getPointerSize(const Value *V, const DataLayout &DL, const TargetLibraryInfo &TLI, const Function *F)
static bool tryToShortenEnd(Instruction *DeadI, OverlapIntervalsTy &IntervalMap, int64_t &DeadStart, uint64_t &DeadSize)
static void adjustArgAttributes(AnyMemIntrinsic *Intrinsic, unsigned ArgNo, uint64_t PtrOffset)
Update the attributes given that a memory access is updated (the dereferenced pointer could be moved ...
static bool hasInitializesAttr(Instruction *I)
This file provides an implementation of debug counters.
#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC)
This file defines the DenseMap class.
early cse Early CSE w MemorySSA
static bool runOnFunction(Function &F, bool PostInlining)
This is the interface for a simple mod/ref and alias analysis over globals.
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
static void deleteDeadInstruction(Instruction *I)
This file implements a map that provides insertion order iteration.
This file provides utility analysis objects describing memory locations.
This file exposes an interface to building/using memory SSA to walk memory instructions using a use/d...
Contains a collection of routines for determining if a given instruction is guaranteed to execute if ...
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
const SmallVectorImpl< MachineOperand > & Cond
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static bool VisitNode(MachineDomTreeNode *Node, Register TLSBaseAddrReg)
A manager for alias analyses.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
Class for arbitrary precision integers.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
unsigned getBitWidth() const
Return the number of bits in the APInt.
int64_t getSExtValue() const
Get sign extended value.
@ NoAlias
The two locations do not alias at all.
@ PartialAlias
The two locations alias, but only due to a partial overlap.
@ MustAlias
The two locations precisely alias each other.
constexpr int32_t getOffset() const
constexpr bool hasOffset() const
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
This class represents an incoming formal argument to a Function.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
An immutable pass that tracks lazily created AssumptionCache objects.
This class stores enough information to efficiently remove some attributes from an existing AttrBuild...
AttributeMask & addAttribute(Attribute::AttrKind Val)
Add an attribute to the mask.
This class holds the attributes for a particular argument, parameter, function, or return value.
LLVM_ABI ArrayRef< ConstantRange > getValueAsConstantRangeList() const
Return the attribute's value as a ConstantRange array.
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
bool isValid() const
Return true if the attribute is any kind of attribute.
LLVM Basic Block Representation.
const Function * getParent() const
Return the enclosing method, or null if none.
InstListType::iterator iterator
Instruction iterators...
This class is a wrapper over an AAResults, and it is intended to be used only when there are no IR ch...
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB)
bool isMustAlias(const MemoryLocation &LocA, const MemoryLocation &LocB)
ModRefInfo getModRefInfo(const Instruction *I, const std::optional< MemoryLocation > &OptLoc)
Represents analyses that only rely on functions' control flow.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
void setCallingConv(CallingConv::ID CC)
LLVM_ABI bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const
Determine whether the argument or parameter has the given attribute.
Attribute getParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) const
Get the attribute of a given kind from a given arg.
bool isByValArgument(unsigned ArgNo) const
Determine whether this argument is passed by value.
LLVM_ABI bool onlyAccessesInaccessibleMemOrArgMem() const
Determine if the function may only access memory that is either inaccessible from the IR or pointed t...
bool doesNotThrow() const
Determine if the call cannot unwind.
Value * getArgOperand(unsigned i) const
LLVM_ABI Value * getArgOperandWithAttribute(Attribute::AttrKind Kind) const
If one of the arguments has the specified attribute, returns its operand value.
unsigned arg_size() const
This class represents a list of constant ranges.
bool empty() const
Return true if this list contains no members.
LLVM_ABI ConstantRangeList intersectWith(const ConstantRangeList &CRL) const
Return the range list that results from the intersection of this ConstantRangeList with another Const...
const APInt & getLower() const
Return the lower value for this range.
const APInt & getUpper() const
Return the upper value for this range.
This is an important base class in LLVM.
bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
Analysis pass which computes a CycleInfo.
Legacy analysis pass which computes a CycleInfo.
static DIAssignID * getDistinct(LLVMContext &Context)
DbgVariableFragmentInfo FragmentInfo
static LLVM_ABI std::optional< DIExpression * > createFragmentExpression(const DIExpression *Expr, unsigned OffsetInBits, unsigned SizeInBits)
Create a DIExpression to describe one part of an aggregate variable that is fragmented across multipl...
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
A parsed version of the target data layout string in and methods for querying it.
Record of a variable value-assignment, aka a non instruction representation of the dbg....
static bool shouldExecute(CounterInfo &Counter)
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Analysis pass which computes a DominatorTree.
DomTreeNodeBase< NodeT > * getRootNode()
getRootNode - This returns the entry node for the CFG of the function.
NodeT * findNearestCommonDominator(NodeT *A, NodeT *B) const
Find nearest common dominator basic block for basic block A and B.
iterator_range< root_iterator > roots()
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
Context-sensitive CaptureAnalysis provider, which computes and caches the earliest common dominator c...
void removeInstruction(Instruction *I)
CaptureComponents getCapturesBefore(const Value *Object, const Instruction *I, bool OrAt, bool ReturnCaptures) override
Return how Object may be captured before instruction I, considering only provenance captures.
FunctionPass class - This class is used to implement most global optimizations.
const BasicBlock & getEntryBlock() const
CycleRef getCycle(const BlockT *Block) const
Find the innermost cycle containing Block.
static GetElementPtrInst * CreateInBounds(Type *PointeeType, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Create an "inbounds" getelementptr.
Legacy wrapper pass to provide the GlobalsAAResult object.
bool isEquality() const
Return true if this predicate is either EQ or NE.
LLVM_ABI bool mayThrow(bool IncludePhaseOneUnwind=false) const LLVM_READONLY
Return true if this instruction may throw an exception.
LLVM_ABI bool mayWriteToMemory() const LLVM_READONLY
Return true if this instruction may modify memory.
LLVM_ABI bool isAtomic() const LLVM_READONLY
Return true if this instruction has an AtomicOrdering of unordered or higher.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI bool isIdenticalToWhenDefined(const Instruction *I, bool IntersectAttrs=false) const LLVM_READONLY
This is like isIdenticalTo, except that it ignores the SubclassOptionalData flags,...
LLVM_ABI bool mayReadFromMemory() const LLVM_READONLY
Return true if this instruction may read memory.
LLVM_ABI AAMDNodes getAAMetadata() const
Returns the AA metadata for this instruction.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
const_iterator begin() const
bool empty() const
empty - Return true when no intervals are mapped.
const_iterator end() const
A wrapper class for inspecting calls to intrinsic functions.
This is an important class for using LLVM in a threaded context.
static LocationSize precise(uint64_t Value)
TypeSize getValue() const
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
This class implements a map that also provides access to all stored values in a deterministic order.
Value * getLength() const
BasicBlock * getBlock() const
Represents a read-write access to memory, whether it is a must-alias, or a may-alias.
void setOptimized(MemoryAccess *MA)
A wrapper analysis pass for the legacy pass manager that exposes a MemoryDepnedenceResults instance.
Representation for a specific memory location.
static LLVM_ABI MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
LocationSize Size
The maximum size of the location, in address-units, or UnknownSize if the size is not known.
static MemoryLocation getBeforeOrAfter(const Value *Ptr, const AAMDNodes &AATags=AAMDNodes())
Return a location that may access any location before or after Ptr, while remaining within the underl...
static MemoryLocation getAfter(const Value *Ptr, const AAMDNodes &AATags=AAMDNodes())
Return a location that may access any location after Ptr, while remaining within the underlying objec...
MemoryLocation getWithNewPtr(const Value *NewPtr) const
const Value * Ptr
The address of the start of the location.
static LLVM_ABI MemoryLocation getForDest(const MemIntrinsic *MI)
Return a location representing the destination of a memory set or transfer.
static LLVM_ABI std::optional< MemoryLocation > getOrNone(const Instruction *Inst)
static LLVM_ABI MemoryLocation getForArgument(const CallBase *Call, unsigned ArgIdx, const TargetLibraryInfo *TLI)
Return a location representing a particular argument of a call.
An analysis that produces MemorySSA for a function.
MemoryAccess * getClobberingMemoryAccess(const Instruction *I, BatchAAResults &AA)
Given a memory Mod/Ref/ModRef'ing instruction, calling this will give you the nearest dominating Memo...
Legacy analysis pass which computes MemorySSA.
Encapsulates MemorySSA, including all data associated with memory accesses.
DefsList * getBlockDefs(const BasicBlock *BB) const
Return the list of MemoryDef's and MemoryPhi's for a given basic block.
LLVM_ABI MemorySSAWalker * getSkipSelfWalker()
LLVM_ABI bool dominates(const MemoryAccess *A, const MemoryAccess *B) const
Given two memory accesses in potentially different blocks, determine whether MemoryAccess A dominates...
LLVM_ABI MemorySSAWalker * getWalker()
MemoryUseOrDef * getMemoryAccess(const Instruction *I) const
Given a memory Mod/Ref'ing instruction, get the MemorySSA access associated with it.
bool isLiveOnEntryDef(const MemoryAccess *MA) const
Return true if MA represents the live on entry value.
MemoryAccess * getDefiningAccess() const
Get the access that produces the memory state used by this Use.
Instruction * getMemoryInst() const
Get the instruction that this MemoryUse represents.
PHITransAddr - An address value which tracks and handles phi translation.
LLVM_ABI Value * translateValue(BasicBlock *CurBB, BasicBlock *PredBB, const DominatorTree *DT, bool MustDominate)
translateValue - PHI translate the current address up the CFG from CurBB to Pred, updating our state ...
LLVM_ABI bool isPotentiallyPHITranslatable() const
isPotentiallyPHITranslatable - If this needs PHI translation, return true if we have some hope of doi...
bool needsPHITranslationFromBlock(BasicBlock *BB) const
needsPHITranslationFromBlock - Return true if moving from the specified BasicBlock to its predecessor...
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Analysis pass which computes a PostDominatorTree.
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
LLVM_ABI bool dominates(const Instruction *I1, const Instruction *I2) const
Return true if I1 dominates I2.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
size_type size() const
Determine the number of elements in the SetVector.
void insert_range(Range &&R)
bool insert(const value_type &X)
Insert a new element into the SetVector.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this store instruction.
Value * getValueOperand()
constexpr bool empty() const
Check if the string is empty.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
bool has(LibFunc F) const
Tests whether a library function is available.
LibFunc getLibFunc(StringRef funcName) const
Searches for a particular function name.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
bool isPointerTy() const
True if this is an instance of PointerType.
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
bool isVoidTy() const
Return true if this is 'void'.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVMContext & getContext() const
All values hold a context through their type.
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
iterator_range< use_iterator > uses()
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
const ParentTy * getParent() const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
@ BasicBlock
Various leaf nodes.
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
bool match(Val *V, const Pattern &P)
match_bind< Instruction > m_Instruction(Instruction *&I)
Match an instruction, capturing it if we match.
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
CmpClass_match< LHS, RHS, ICmpInst, true > m_c_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
Matches an ICmp with a predicate over LHS and RHS in either order.
auto m_Value()
Match an arbitrary value and ignore it.
SpecificCmpClass_match< LHS, RHS, ICmpInst > m_SpecificICmp(CmpPredicate MatchPred, const LHS &L, const RHS &R)
OneOps_match< OpTy, Instruction::Load > m_Load(const OpTy &Op)
Matches LoadInst.
brc_match< Cond_t, match_bind< BasicBlock >, match_bind< BasicBlock > > m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F)
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
SmallVector< DbgVariableRecord * > getDVRAssignmentMarkers(const Instruction *Inst)
Return a range of dbg_assign records for which Inst performs the assignment they encode.
LLVM_ABI bool calculateFragmentIntersect(const DataLayout &DL, const Value *Dest, uint64_t SliceOffsetInBits, uint64_t SliceSizeInBits, const DbgVariableRecord *DVRAssign, std::optional< DIExpression::FragmentInfo > &Result)
Calculate the fragment of the variable in DAI covered from (Dest + SliceOffsetInBits) to to (Dest + S...
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
NodeAddr< DefNode * > Def
NodeAddr< NodeBase * > Node
NodeAddr< FuncNode * > Func
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
LLVM_ABI void initializeDSELegacyPassPass(PassRegistry &)
LLVM_ABI Constant * getInitialValueOfAllocation(const Value *V, const TargetLibraryInfo *TLI, Type *Ty)
If this is a call to an allocation function that initializes memory to a fixed value,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isStrongerThanMonotonic(AtomicOrdering AO)
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
LLVM_ABI void salvageDebugInfo(const MachineRegisterInfo &MRI, MachineInstr &MI)
Assuming the instruction MI is going to be deleted, attempt to salvage debug users of MI by writing t...
@ Store
The extracted value is stored (ExtractElement only).
Value * GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, const DataLayout &DL, bool AllowNonInbounds=true)
Analyze the specified pointer to see if it can be expressed as a base pointer plus a constant offset.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
LLVM_ABI bool isNoAliasCall(const Value *V)
Return true if this pointer is returned by a noalias function.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
DomTreeNodeBase< BasicBlock > DomTreeNode
auto make_isa_range(RangeT &&Range)
Return a range over Range containing only elements for which isa<T> holds, casting each of them to T.
auto dyn_cast_or_null(const Y &Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction is not used, and the instruction will return.
LLVM_ABI bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL, const TargetLibraryInfo *TLI, ObjectSizeOpts Opts={})
Compute the size of the object pointed by Ptr.
auto reverse(ContainerTy &&C)
LLVM_ABI bool canReplacePointersIfEqual(const Value *From, const Value *To, const DataLayout &DL)
Returns true if a pointer value From can be replaced with another pointer value \To if they are deeme...
bool isModSet(const ModRefInfo MRI)
LLVM_ABI bool NullPointerIsDefined(const Function *F, unsigned AS=0)
Check whether null pointer dereferencing is considered undefined behavior for a given function or an ...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI bool AreStatisticsEnabled()
Check if statistics are enabled.
LLVM_ABI bool isNotVisibleOnUnwind(const Value *Object, bool &RequiresNoCaptureBeforeUnwind)
Return true if Object memory is not visible after an unwind, in the sense that program semantics cann...
LLVM_ABI Value * emitCalloc(Value *Num, Value *Size, IRBuilderBase &B, const TargetLibraryInfo &TLI, unsigned AddrSpace)
Emit a call to the calloc function.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
auto post_order(const T &G)
Post-order traversal of a graph.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
uint64_t offsetToAlignment(uint64_t Value, Align Alignment)
Returns the offset to the next integer (mod 2**64) that is greater than or equal to Value and is a mu...
LLVM_ABI bool salvageKnowledge(Instruction *I, AssumptionCache *AC=nullptr, DominatorTree *DT=nullptr)
Calls BuildAssumeFromInst and if the resulting llvm.assume is valid insert if before I.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
LLVM_ABI bool PointerMayBeCaptured(const Value *V, bool ReturnCaptures, unsigned MaxUsesToExplore=0)
PointerMayBeCaptured - Return true if this pointer value may be captured by the enclosing function (w...
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI Value * getFreedOperand(const CallBase *CB, const TargetLibraryInfo *TLI)
If this if a call to a free function, return the freed operand.
LLVM_ABI bool isIdentifiedFunctionLocal(const Value *V)
Return true if V is umabigously identified at the function-level.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI FunctionPass * createDeadStoreEliminationPass()
LLVM_ABI Value * isBytewiseValue(Value *V, const DataLayout &DL)
If the specified value can be set by repeating the same byte in memory, return the i8 value that it i...
auto predecessors(const MachineBasicBlock *BB)
bool capturesAnything(CaptureComponents CC)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
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.