98#define DEBUG_TYPE "dse"
100STATISTIC(NumRemainingStores,
"Number of stores remaining after DSE");
101STATISTIC(NumRedundantStores,
"Number of redundant stores deleted");
103STATISTIC(NumFastOther,
"Number of other instrs removed");
104STATISTIC(NumCompletePartials,
"Number of stores dead by later partials");
105STATISTIC(NumModifiedStores,
"Number of stores modified");
110 "Number of times a valid candidate is returned from getDomMemoryDef");
112 "Number iterations check for reads in getDomMemoryDef");
115 "Controls which MemoryDefs are eliminated.");
131 switch (
II->getIntrinsicID()) {
132 default:
return false;
133 case Intrinsic::memset:
134 case Intrinsic::memcpy:
135 case Intrinsic::memcpy_element_unordered_atomic:
136 case Intrinsic::memset_element_unordered_atomic:
171enum OverwriteResult {
175 OW_PartialEarlierWithFullLater,
191 if (KillingII ==
nullptr || DeadII ==
nullptr)
193 if (KillingII->getIntrinsicID() != DeadII->getIntrinsicID())
196 switch (KillingII->getIntrinsicID()) {
197 case Intrinsic::masked_store:
198 case Intrinsic::vp_store: {
200 auto *KillingTy = KillingII->getArgOperand(0)->getType();
201 auto *DeadTy = DeadII->getArgOperand(0)->getType();
202 if (
DL.getTypeSizeInBits(KillingTy) !=
DL.getTypeSizeInBits(DeadTy))
209 Value *KillingPtr = KillingII->getArgOperand(1);
210 Value *DeadPtr = DeadII->getArgOperand(1);
211 if (KillingPtr != DeadPtr && !
AA.isMustAlias(KillingPtr, DeadPtr))
213 if (KillingII->getIntrinsicID() == Intrinsic::masked_store) {
216 if (KillingII->getArgOperand(2) != DeadII->getArgOperand(2))
218 }
else if (KillingII->getIntrinsicID() == Intrinsic::vp_store) {
221 if (KillingII->getArgOperand(2) != DeadII->getArgOperand(2))
224 if (KillingII->getArgOperand(3) != DeadII->getArgOperand(3))
247 int64_t KillingOff, int64_t DeadOff,
257 if (Opts.enable_dse_partial_overwrite_tracking &&
258 KillingOff < int64_t(DeadOff + DeadSize) &&
259 int64_t(KillingOff + KillingSize) >= DeadOff) {
262 auto &IM = IOL[DeadI];
263 LLVM_DEBUG(
dbgs() <<
"DSE: Partial overwrite: DeadLoc [" << DeadOff <<
", "
264 << int64_t(DeadOff + DeadSize) <<
") KillingLoc ["
265 << KillingOff <<
", " << int64_t(KillingOff + KillingSize)
272 int64_t KillingIntStart = KillingOff;
273 int64_t KillingIntEnd = KillingOff + KillingSize;
277 auto ILI = IM.lower_bound(KillingIntStart);
278 if (ILI != IM.end() && ILI->second <= KillingIntEnd) {
282 KillingIntStart = std::min(KillingIntStart, ILI->second);
283 KillingIntEnd = std::max(KillingIntEnd, ILI->first);
292 while (ILI != IM.end() && ILI->second <= KillingIntEnd) {
293 assert(ILI->second > KillingIntStart &&
"Unexpected interval");
294 KillingIntEnd = std::max(KillingIntEnd, ILI->first);
299 IM[KillingIntEnd] = KillingIntStart;
302 if (ILI->second <= DeadOff && ILI->first >= int64_t(DeadOff + DeadSize)) {
303 LLVM_DEBUG(
dbgs() <<
"DSE: Full overwrite from partials: DeadLoc ["
304 << DeadOff <<
", " << int64_t(DeadOff + DeadSize)
305 <<
") Composite KillingLoc [" << ILI->second <<
", "
306 << ILI->first <<
")\n");
307 ++NumCompletePartials;
314 if (Opts.enable_dse_partial_store_merging && KillingOff >= DeadOff &&
315 int64_t(DeadOff + DeadSize) > KillingOff &&
316 uint64_t(KillingOff - DeadOff) + KillingSize <= DeadSize) {
317 LLVM_DEBUG(
dbgs() <<
"DSE: Partial overwrite a dead load [" << DeadOff
318 <<
", " << int64_t(DeadOff + DeadSize)
319 <<
") by a killing store [" << KillingOff <<
", "
320 << int64_t(KillingOff + KillingSize) <<
")\n");
322 return OW_PartialEarlierWithFullLater;
334 if (!Opts.enable_dse_partial_overwrite_tracking &&
335 (KillingOff > DeadOff && KillingOff < int64_t(DeadOff + DeadSize) &&
336 int64_t(KillingOff + KillingSize) >= int64_t(DeadOff + DeadSize)))
348 if (!Opts.enable_dse_partial_overwrite_tracking &&
349 (KillingOff <= DeadOff && int64_t(KillingOff + KillingSize) > DeadOff)) {
350 assert(int64_t(KillingOff + KillingSize) < int64_t(DeadOff + DeadSize) &&
351 "Expect to be handled as OW_Complete");
371 using BlockAddressPair = std::pair<BasicBlock *, PHITransAddr>;
388 auto *MemLocPtr =
const_cast<Value *
>(MemLoc.
Ptr);
393 bool isFirstBlock =
true;
396 while (!WorkList.
empty()) {
408 assert(
B == SecondBB &&
"first block is not the store block");
410 isFirstBlock =
false;
416 for (; BI != EI; ++BI) {
418 if (
I->mayWriteToMemory() &&
I != SecondI)
424 "Should not hit the entry block because SI must be dominated by LI");
434 auto Inserted = Visited.
insert(std::make_pair(
Pred, TranslatedPtr));
435 if (!Inserted.second) {
438 if (TranslatedPtr != Inserted.first->second)
452 bool IsOverwriteEnd) {
454 uint64_t DeadSliceSizeInBits = OldSizeInBits - NewSizeInBits;
461 uint64_t DeadSliceOffsetInBits = IsOverwriteEnd ? NewSizeInBits : 0;
462 auto SetDeadFragExpr = [](
auto *Assign,
466 uint64_t RelativeOffset = DeadFragment.OffsetInBits -
467 Assign->getExpression()
472 Assign->getExpression(), RelativeOffset, DeadFragment.SizeInBits)) {
473 Assign->setExpression(*
NewExpr);
480 DeadFragment.SizeInBits);
481 Assign->setExpression(Expr);
482 Assign->setKillLocation();
489 auto GetDeadLink = [&Ctx, &LinkToNothing]() {
492 return LinkToNothing;
498 std::optional<DIExpression::FragmentInfo> NewFragment;
500 DeadSliceSizeInBits, Assign,
507 Assign->setKillAddress();
508 Assign->setAssignId(GetDeadLink());
512 if (NewFragment->SizeInBits == 0)
516 auto *NewAssign =
static_cast<decltype(Assign)
>(Assign->clone());
517 NewAssign->insertAfter(Assign->getIterator());
518 NewAssign->setAssignId(GetDeadLink());
520 SetDeadFragExpr(NewAssign, *NewFragment);
521 NewAssign->setKillAddress();
535 for (
auto &Attr : OldAttrs) {
536 if (Attr.hasKindAsEnum()) {
537 switch (Attr.getKindAsEnum()) {
540 case Attribute::Alignment:
542 if (
isAligned(Attr.getAlignment().valueOrOne(), PtrOffset))
545 case Attribute::Dereferenceable:
546 case Attribute::DereferenceableOrNull:
550 case Attribute::NonNull:
551 case Attribute::NoUndef:
559 Intrinsic->removeParamAttrs(ArgNo, AttrsToRemove);
563 uint64_t &DeadSize, int64_t KillingStart,
564 uint64_t KillingSize,
bool IsOverwriteEnd) {
566 Align PrefAlign = DeadIntrinsic->getDestAlign().valueOrOne();
582 int64_t ToRemoveStart = 0;
586 if (IsOverwriteEnd) {
591 ToRemoveStart = KillingStart +
Off;
592 if (DeadSize <=
uint64_t(ToRemoveStart - DeadStart))
594 ToRemoveSize = DeadSize -
uint64_t(ToRemoveStart - DeadStart);
596 ToRemoveStart = DeadStart;
598 "Not overlapping accesses?");
599 ToRemoveSize = KillingSize -
uint64_t(DeadStart - KillingStart);
604 if (ToRemoveSize <= (PrefAlign.
value() -
Off))
606 ToRemoveSize -= PrefAlign.
value() -
Off;
609 "Should preserve selected alignment");
612 assert(ToRemoveSize > 0 &&
"Shouldn't reach here if nothing to remove");
613 assert(DeadSize > ToRemoveSize &&
"Can't remove more than original size");
615 uint64_t NewSize = DeadSize - ToRemoveSize;
616 if (DeadIntrinsic->isAtomic()) {
619 const uint32_t ElementSize = DeadIntrinsic->getElementSizeInBytes();
620 if (0 != NewSize % ElementSize)
624 Value *OrigDest = DeadIntrinsic->getRawDest();
629 if (!IsOverwriteEnd &&
634 << (IsOverwriteEnd ?
"END" :
"BEGIN") <<
": " << *DeadI
635 <<
"\n KILLER [" << ToRemoveStart <<
", "
636 << int64_t(ToRemoveStart + ToRemoveSize) <<
")\n");
638 DeadIntrinsic->setLength(NewSize);
639 DeadIntrinsic->setDestAlignment(PrefAlign);
641 if (!IsOverwriteEnd) {
642 Value *Indices[1] = {ConstantInt::get(IndexTy, ToRemoveSize)};
646 NewDestGEP->
setDebugLoc(DeadIntrinsic->getDebugLoc());
647 DeadIntrinsic->setDest(NewDestGEP);
656 DeadStart += ToRemoveSize;
663 int64_t &DeadStart,
uint64_t &DeadSize) {
668 int64_t KillingStart = OII->second;
669 uint64_t KillingSize = OII->first - KillingStart;
671 assert(OII->first - KillingStart >= 0 &&
"Size expected to be positive");
673 if (KillingStart > DeadStart &&
676 (
uint64_t)(KillingStart - DeadStart) < DeadSize &&
679 KillingSize >= DeadSize - (
uint64_t)(KillingStart - DeadStart)) {
680 if (
tryToShorten(DeadI, DeadStart, DeadSize, KillingStart, KillingSize,
691 int64_t &DeadStart,
uint64_t &DeadSize) {
696 int64_t KillingStart = OII->second;
697 uint64_t KillingSize = OII->first - KillingStart;
699 assert(OII->first - KillingStart >= 0 &&
"Size expected to be positive");
701 if (KillingStart <= DeadStart &&
704 KillingSize > (
uint64_t)(DeadStart - KillingStart)) {
707 assert(KillingSize - (
uint64_t)(DeadStart - KillingStart) < DeadSize &&
708 "Should have been handled as OW_Complete");
709 if (
tryToShorten(DeadI, DeadStart, DeadSize, KillingStart, KillingSize,
720 int64_t KillingOffset, int64_t DeadOffset,
764 unsigned BitOffsetDiff = (KillingOffset - DeadOffset) * 8;
765 unsigned LShiftAmount =
766 DL.isBigEndian() ? DeadValue.
getBitWidth() - BitOffsetDiff - KillingBits
769 LShiftAmount + KillingBits);
772 APInt Merged = (DeadValue & ~Mask) | (KillingValue << LShiftAmount);
774 <<
"\n Killing: " << *KillingI
775 <<
"\n Merged Value: " << Merged <<
'\n');
782 switch (
II->getIntrinsicID()) {
783 case Intrinsic::lifetime_start:
784 case Intrinsic::lifetime_end:
785 case Intrinsic::invariant_end:
786 case Intrinsic::launder_invariant_group:
787 case Intrinsic::assume:
802 if (CB->onlyAccessesInaccessibleMemory())
807 if (DI->
mayThrow() && !DefVisibleToCaller)
829struct MemoryLocationWrapper {
830 MemoryLocationWrapper(MemoryLocation MemLoc, MemoryDef *MemDef,
831 bool DefByInitializesAttr)
832 : MemLoc(MemLoc), MemDef(MemDef),
833 DefByInitializesAttr(DefByInitializesAttr) {
834 assert(MemLoc.Ptr &&
"MemLoc should be not null");
836 DefInst = MemDef->getMemoryInst();
839 MemoryLocation MemLoc;
840 const Value *UnderlyingObject;
843 bool DefByInitializesAttr =
false;
848struct MemoryDefWrapper {
849 MemoryDefWrapper(MemoryDef *MemDef,
850 ArrayRef<std::pair<MemoryLocation, bool>> MemLocations) {
852 for (
auto &[MemLoc, DefByInitializesAttr] : MemLocations)
853 DefinedLocations.push_back(
854 MemoryLocationWrapper(MemLoc, MemDef, DefByInitializesAttr));
860struct ArgumentInitInfo {
862 bool IsDeadOrInvisibleOnUnwind;
863 ConstantRangeList Inits;
878 bool CallHasNoUnwindAttr) {
884 for (
const auto &Arg : Args) {
885 if (!CallHasNoUnwindAttr && !Arg.IsDeadOrInvisibleOnUnwind)
887 if (Arg.Inits.empty())
892 for (
auto &Arg : Args.drop_front())
893 IntersectedIntervals = IntersectedIntervals.
intersectWith(Arg.Inits);
895 return IntersectedIntervals;
901 const ScalarOptions &Opts;
904 EarliestEscapeAnalysis EA;
913 BatchAAResults BatchAA;
917 PostDominatorTree &PDT;
918 const TargetLibraryInfo &TLI;
919 const DataLayout &DL;
925 SmallPtrSet<MemoryAccess *, 4> SkipStores;
927 DenseMap<const Value *, bool> CapturedBeforeReturn;
930 DenseMap<const Value *, bool> InvisibleToCallerAfterRet;
931 DenseMap<const Value *, uint64_t> InvisibleToCallerAfterRetBounded;
933 SmallPtrSet<BasicBlock *, 16> ThrowingBlocks;
936 SmallPtrSet<BasicBlock *, 16> CoroEndBlocks;
939 DenseMap<BasicBlock *, unsigned> PostOrderNumbers;
943 MapVector<BasicBlock *, InstOverlapIntervalsTy> IOLs;
947 bool AnyUnreachableExit;
952 bool ShouldIterateEndOfFunctionDSE;
955 SmallVector<Instruction *> ToRemove;
959 MemorySSA &MSSA, DominatorTree &DT, PostDominatorTree &PDT,
960 const TargetLibraryInfo &TLI,
const CycleInfo &CI);
961 DSEState(
const DSEState &) =
delete;
962 DSEState &operator=(
const DSEState &) =
delete;
964 LocationSize strengthenLocationSize(
const Instruction *
I,
965 LocationSize
Size)
const;
975 OverwriteResult isOverwrite(
const Instruction *KillingI,
976 const Instruction *DeadI,
977 const MemoryLocation &KillingLoc,
978 const MemoryLocation &DeadLoc,
979 int64_t &KillingOff, int64_t &DeadOff);
981 bool isInvisibleToCallerAfterRet(
const Value *
V,
const Value *Ptr,
982 const LocationSize StoreSize);
984 bool isInvisibleToCallerOnUnwind(
const Value *
V);
986 std::optional<MemoryLocation> getLocForWrite(Instruction *
I)
const;
991 getLocForInst(Instruction *
I,
bool ConsiderInitializesAttr);
995 bool isRemovable(Instruction *
I);
999 bool isCompleteOverwrite(
const MemoryLocation &DefLoc, Instruction *DefInst,
1000 Instruction *UseInst);
1003 bool isWriteAtEndOfFunction(MemoryDef *Def,
const MemoryLocation &DefLoc);
1008 std::optional<std::pair<MemoryLocation, bool>>
1009 getLocForTerminator(Instruction *
I)
const;
1013 bool isMemTerminatorInst(Instruction *
I)
const;
1017 bool isMemTerminator(
const MemoryLocation &Loc, Instruction *AccessI,
1018 Instruction *MaybeTerm);
1021 bool isReadClobber(
const MemoryLocation &DefLoc, Instruction *UseInst);
1028 bool isGuaranteedLoopIndependent(
const Instruction *Current,
1029 const Instruction *KillingDef,
1030 const MemoryLocation &CurrentLoc);
1035 bool isGuaranteedLoopInvariant(
const Value *Ptr);
1043 std::optional<MemoryAccess *>
1044 getDomMemoryDef(MemoryDef *KillingDef, MemoryAccess *StartAccess,
1045 const MemoryLocation &KillingLoc,
const Value *KillingUndObj,
1046 unsigned &ScanLimit,
unsigned &WalkerStepLimit,
1047 bool IsMemTerm,
unsigned &PartialLimit,
1048 bool IsInitializesAttrMemLoc);
1054 SmallPtrSetImpl<MemoryAccess *> *
Deleted =
nullptr);
1060 bool mayThrowBetween(Instruction *KillingI, Instruction *DeadI,
1061 const Value *KillingUndObj);
1068 bool isDSEBarrier(
const Value *KillingUndObj, Instruction *DeadI);
1072 bool eliminateDeadWritesAtEndOfFunction();
1076 bool tryFoldIntoCalloc(MemoryDef *Def,
const Value *DefUO);
1080 bool storeIsNoop(MemoryDef *Def,
const Value *DefUO);
1086 bool eliminateRedundantStoresOfExistingValues();
1091 bool eliminateRedundantStoresViaDominatingConditions();
1106 std::pair<bool, bool>
1107 eliminateDeadDefs(
const MemoryLocationWrapper &KillingLocWrapper);
1111 bool eliminateDeadDefs(
const MemoryDefWrapper &KillingDefWrapper);
1121 if (Visited.
insert(MA).second)
1138 : Opts(Opts),
F(
F),
AA(
AA), EA(DT, nullptr, &CI), BatchAA(
AA, &EA),
1139 MSSA(MSSA), DT(DT), PDT(PDT),
TLI(
TLI),
DL(
F.getDataLayout()), CI(CI) {
1144 PostOrderNumbers[BB] = PO++;
1147 if (
I.mayThrow() && !MA)
1148 ThrowingBlocks.insert(
I.getParent());
1150 if (CEI->isFallthrough())
1151 CoroEndBlocks.insert(
I.getParent());
1155 if (MD && MemDefs.size() < Opts.dse_memoryssa_defs_per_block_limit &&
1156 (getLocForWrite(&
I) || isMemTerminatorInst(&
I) ||
1157 (Opts.enable_dse_initializes_attr_improvement &&
1159 MemDefs.push_back(MD);
1166 if (AI.hasPassPointeeByValueCopyAttr()) {
1167 InvisibleToCallerAfterRet.insert({&AI, true});
1171 if (!AI.getType()->isPointerTy())
1175 if (Info.coversAllReachableMemory())
1176 InvisibleToCallerAfterRet.insert({&AI, true});
1177 else if (
uint64_t DeadBytes = Info.getNumberOfDeadBytes())
1178 InvisibleToCallerAfterRetBounded.insert({&AI, DeadBytes});
1182 return isa<UnreachableInst>(E->getTerminator());
1189 LibFunc
F =
TLI.getLibFunc(*CB);
1190 if (
TLI.has(
F) && (
F == LibFunc_memset_chk ||
F == LibFunc_memcpy_chk)) {
1206OverwriteResult DSEState::isOverwrite(
const Instruction *KillingI,
1207 const Instruction *DeadI,
1208 const MemoryLocation &KillingLoc,
1209 const MemoryLocation &DeadLoc,
1210 int64_t &KillingOff, int64_t &DeadOff) {
1214 if (!isGuaranteedLoopIndependent(DeadI, KillingI, DeadLoc))
1217 LocationSize KillingLocSize =
1218 strengthenLocationSize(KillingI, KillingLoc.
Size);
1226 if (DeadUndObj == KillingUndObj && KillingLocSize.
isPrecise() &&
1228 std::optional<TypeSize> KillingUndObjSize =
1230 if (KillingUndObjSize && *KillingUndObjSize == KillingLocSize.
getValue())
1241 if (KillingMemI && DeadMemI) {
1242 const Value *KillingV = KillingMemI->getLength();
1243 const Value *DeadV = DeadMemI->getLength();
1244 if (KillingV == DeadV && BatchAA.
isMustAlias(DeadLoc, KillingLoc))
1253 const TypeSize KillingSize = KillingLocSize.
getValue();
1262 auto CheckAA = [&]() {
1264 AliasResult AAR = BatchAA.
alias(KillingLoc, DeadLoc);
1270 if (KillingSize >= DeadSize)
1293 if (DeadUndObj != KillingUndObj)
1297 unsigned IdxWidth =
DL.getIndexTypeSizeInBits(DeadPtr->
getType());
1298 if (IdxWidth !=
DL.getIndexTypeSizeInBits(KillingPtr->
getType()))
1306 APInt DeadBaseOff(IdxWidth, 0);
1307 APInt KillingBaseOff(IdxWidth, 0);
1309 DL, DeadBaseOff,
true);
1311 DL, KillingBaseOff,
true);
1315 if (DeadBasePtr != KillingBasePtr)
1331 if (KillingSize == 0)
1335 APInt Delta = DeadBaseOff - KillingBaseOff;
1336 if (Delta.
ult(KillingSize)) {
1343 return OW_MaybePartial;
1347 if ((-Delta).ult(DeadSize)) {
1348 KillingOff = (-Delta).getZExtValue();
1349 return OW_MaybePartial;
1356bool DSEState::isInvisibleToCallerAfterRet(
const Value *
V,
const Value *Ptr,
1357 const LocationSize StoreSize) {
1361 auto IBounded = InvisibleToCallerAfterRetBounded.find(
V);
1362 if (IBounded != InvisibleToCallerAfterRetBounded.end()) {
1363 int64_t ValueOffset;
1364 [[maybe_unused]]
const Value *BaseValue =
1374 ValueOffset + StoreSize.
getValue() <= IBounded->second &&
1378 auto I = InvisibleToCallerAfterRet.insert({
V,
false});
1382 return I.first->second;
1385bool DSEState::isInvisibleToCallerOnUnwind(
const Value *
V) {
1386 bool RequiresNoCaptureBeforeUnwind;
1389 if (!RequiresNoCaptureBeforeUnwind)
1392 auto I = CapturedBeforeReturn.insert({
V,
true});
1400 return !
I.first->second;
1403std::optional<MemoryLocation> DSEState::getLocForWrite(Instruction *
I)
const {
1404 if (!
I->mayWriteToMemory())
1405 return std::nullopt;
1414DSEState::getLocForInst(Instruction *
I,
bool ConsiderInitializesAttr) {
1416 if (isMemTerminatorInst(
I)) {
1417 if (
auto Loc = getLocForTerminator(
I))
1418 Locations.push_back(std::make_pair(Loc->first,
false));
1422 if (
auto Loc = getLocForWrite(
I))
1423 Locations.push_back(std::make_pair(*Loc,
false));
1425 if (ConsiderInitializesAttr) {
1426 for (
auto &MemLoc : getInitializesArgMemLoc(
I)) {
1427 Locations.push_back(std::make_pair(MemLoc,
true));
1433bool DSEState::isRemovable(Instruction *
I) {
1434 assert(getLocForWrite(
I) &&
"Must have analyzable write");
1438 return SI->isUnordered();
1443 return !
MI->isVolatile();
1447 if (CB->isLifetimeStartOrEnd())
1450 return CB->use_empty() && CB->willReturn() && CB->doesNotThrow() &&
1451 !CB->isTerminator();
1457bool DSEState::isCompleteOverwrite(
const MemoryLocation &DefLoc,
1458 Instruction *DefInst, Instruction *UseInst) {
1466 if (CB->onlyAccessesInaccessibleMemory())
1469 int64_t InstWriteOffset, DepWriteOffset;
1470 if (
auto CC = getLocForWrite(UseInst))
1471 return isOverwrite(UseInst, DefInst, *
CC, DefLoc, InstWriteOffset,
1472 DepWriteOffset) == OW_Complete;
1476bool DSEState::isWriteAtEndOfFunction(MemoryDef *Def,
1477 const MemoryLocation &DefLoc) {
1479 << *
Def->getMemoryInst()
1480 <<
") is at the end the function \n");
1482 SmallPtrSet<MemoryAccess *, 8> Visited;
1485 for (
unsigned I = 0;
I < WorkList.
size();
I++) {
1486 if (WorkList.
size() >= Opts.dse_memoryssa_scanlimit) {
1491 MemoryAccess *UseAccess = WorkList[
I];
1496 if (!isGuaranteedLoopInvariant(DefLoc.
Ptr))
1505 if (isReadClobber(DefLoc, UseInst)) {
1506 LLVM_DEBUG(
dbgs() <<
" ... hit read clobber " << *UseInst <<
".\n");
1516std::optional<std::pair<MemoryLocation, bool>>
1517DSEState::getLocForTerminator(Instruction *
I)
const {
1519 if (CB->getIntrinsicID() == Intrinsic::lifetime_end)
1526 return std::nullopt;
1529bool DSEState::isMemTerminatorInst(Instruction *
I)
const {
1531 return CB && (CB->getIntrinsicID() == Intrinsic::lifetime_end ||
1535bool DSEState::isMemTerminator(
const MemoryLocation &Loc, Instruction *AccessI,
1536 Instruction *MaybeTerm) {
1537 std::optional<std::pair<MemoryLocation, bool>> MaybeTermLoc =
1538 getLocForTerminator(MaybeTerm);
1549 auto TermLoc = MaybeTermLoc->first;
1550 if (MaybeTermLoc->second) {
1554 int64_t InstWriteOffset = 0;
1555 int64_t DepWriteOffset = 0;
1556 return isOverwrite(MaybeTerm, AccessI, TermLoc, Loc, InstWriteOffset,
1557 DepWriteOffset) == OW_Complete;
1560bool DSEState::isReadClobber(
const MemoryLocation &DefLoc,
1561 Instruction *UseInst) {
1574 if (CB->onlyAccessesInaccessibleMemory())
1580bool DSEState::isGuaranteedLoopIndependent(
const Instruction *Current,
1581 const Instruction *KillingDef,
1582 const MemoryLocation &CurrentLoc) {
1593 return isGuaranteedLoopInvariant(CurrentLoc.
Ptr);
1596bool DSEState::isGuaranteedLoopInvariant(
const Value *Ptr) {
1599 if (
GEP->hasAllConstantIndices())
1603 return I->getParent()->isEntryBlock() || !CI.
getCycle(
I->getParent());
1608std::optional<MemoryAccess *> DSEState::getDomMemoryDef(
1609 MemoryDef *KillingDef, MemoryAccess *StartAccess,
1610 const MemoryLocation &KillingLoc,
const Value *KillingUndObj,
1611 unsigned &ScanLimit,
unsigned &WalkerStepLimit,
bool IsMemTerm,
1612 unsigned &PartialLimit,
bool IsInitializesAttrMemLoc) {
1613 if (ScanLimit == 0 || WalkerStepLimit == 0) {
1615 return std::nullopt;
1618 MemoryAccess *Current = StartAccess;
1627 bool CanOptimize = Opts.dse_optimize_memoryssa &&
1632 std::optional<MemoryLocation> CurrentLoc;
1635 dbgs() <<
" visiting " << *Current;
1648 return std::nullopt;
1654 ? Opts.dse_memoryssa_samebb_cost
1655 : Opts.dse_memoryssa_otherbb_cost;
1656 if (WalkerStepLimit <= StepCost) {
1658 return std::nullopt;
1660 WalkerStepLimit -= StepCost;
1674 if (
canSkipDef(CurrentDef, !isInvisibleToCallerOnUnwind(KillingUndObj))) {
1675 CanOptimize =
false;
1681 if (mayThrowBetween(KillingI, CurrentI, KillingUndObj)) {
1683 return std::nullopt;
1688 if (isDSEBarrier(KillingUndObj, CurrentI)) {
1690 return std::nullopt;
1698 return std::nullopt;
1701 if (
any_of(Current->
uses(), [
this, &KillingLoc, StartAccess](Use &U) {
1702 if (auto *UseOrDef = dyn_cast<MemoryUseOrDef>(U.getUser()))
1703 return !MSSA.dominates(StartAccess, UseOrDef) &&
1704 isReadClobber(KillingLoc, UseOrDef->getMemoryInst());
1708 return std::nullopt;
1713 CurrentLoc = getLocForWrite(CurrentI);
1714 if (!CurrentLoc || !isRemovable(CurrentI)) {
1715 CanOptimize =
false;
1722 if (!isGuaranteedLoopIndependent(CurrentI, KillingI, *CurrentLoc)) {
1724 CanOptimize =
false;
1732 if (!isMemTerminator(*CurrentLoc, CurrentI, KillingI)) {
1733 CanOptimize =
false;
1737 int64_t KillingOffset = 0;
1738 int64_t DeadOffset = 0;
1739 auto OR = isOverwrite(KillingI, CurrentI, KillingLoc, *CurrentLoc,
1740 KillingOffset, DeadOffset);
1746 (OR == OW_Complete || OR == OW_MaybePartial))
1752 CanOptimize =
false;
1757 if (OR == OW_Unknown || OR == OW_None)
1759 else if (OR == OW_MaybePartial) {
1764 if (PartialLimit <= 1) {
1765 WalkerStepLimit -= 1;
1766 LLVM_DEBUG(
dbgs() <<
" ... reached partial limit ... continue with "
1780 SmallPtrSet<Instruction *, 16> KillingDefs;
1782 MemoryAccess *MaybeDeadAccess = Current;
1783 MemoryLocation MaybeDeadLoc = *CurrentLoc;
1785 LLVM_DEBUG(
dbgs() <<
" Checking for reads of " << *MaybeDeadAccess <<
" ("
1786 << *MaybeDeadI <<
")\n");
1789 SmallPtrSet<MemoryAccess *, 32> Visited;
1793 for (
unsigned I = 0;
I < WorkList.
size();
I++) {
1794 MemoryAccess *UseAccess = WorkList[
I];
1798 if (ScanLimit < (WorkList.
size() -
I)) {
1800 return std::nullopt;
1803 NumDomMemDefChecks++;
1806 if (
any_of(KillingDefs, [
this, UseAccess](Instruction *KI) {
1809 LLVM_DEBUG(
dbgs() <<
" ... skipping, dominated by killing block\n");
1820 if (
any_of(KillingDefs, [
this, UseInst](Instruction *KI) {
1823 LLVM_DEBUG(
dbgs() <<
" ... skipping, dominated by killing def\n");
1829 if (isMemTerminator(MaybeDeadLoc, MaybeDeadI, UseInst)) {
1832 <<
" ... skipping, memterminator invalidates following accesses\n");
1842 if (UseInst->
mayThrow() && !isInvisibleToCallerOnUnwind(KillingUndObj)) {
1844 return std::nullopt;
1851 bool IsKillingDefFromInitAttr =
false;
1852 if (IsInitializesAttrMemLoc) {
1853 if (KillingI == UseInst &&
1855 IsKillingDefFromInitAttr =
true;
1858 if (isReadClobber(MaybeDeadLoc, UseInst) && !IsKillingDefFromInitAttr) {
1860 return std::nullopt;
1866 if (MaybeDeadAccess == UseAccess &&
1867 !isGuaranteedLoopInvariant(MaybeDeadLoc.
Ptr)) {
1868 LLVM_DEBUG(
dbgs() <<
" ... found not loop invariant self access\n");
1869 return std::nullopt;
1875 if (KillingDef == UseAccess || MaybeDeadAccess == UseAccess) {
1891 if (isCompleteOverwrite(MaybeDeadLoc, MaybeDeadI, UseInst)) {
1893 if (PostOrderNumbers.
find(MaybeKillingBlock)->second <
1894 PostOrderNumbers.
find(MaybeDeadAccess->
getBlock())->second) {
1895 if (!isInvisibleToCallerAfterRet(KillingUndObj, KillingLoc.
Ptr,
1898 <<
" ... found killing def " << *UseInst <<
"\n");
1899 KillingDefs.
insert(UseInst);
1903 <<
" ... found preceeding def " << *UseInst <<
"\n");
1904 return std::nullopt;
1914 if (!isInvisibleToCallerAfterRet(KillingUndObj, KillingLoc.
Ptr,
1916 SmallPtrSet<BasicBlock *, 16> KillingBlocks;
1917 for (Instruction *KD : KillingDefs)
1918 KillingBlocks.
insert(KD->getParent());
1920 "Expected at least a single killing block");
1934 if (!AnyUnreachableExit)
1935 return std::nullopt;
1939 CommonPred =
nullptr;
1943 if (KillingBlocks.
count(CommonPred))
1944 return {MaybeDeadAccess};
1946 SetVector<BasicBlock *> WorkList;
1950 WorkList.
insert(CommonPred);
1952 for (BasicBlock *R : PDT.
roots()) {
1957 for (BasicBlock *R : CoroEndBlocks)
1964 for (
unsigned I = 0;
I < WorkList.
size();
I++) {
1967 if (KillingBlocks.
count(Current))
1969 if (Current == MaybeDeadAccess->
getBlock())
1970 return std::nullopt;
1979 if (WorkList.
size() >= Opts.dse_memoryssa_path_check_limit)
1980 return std::nullopt;
1987 return {MaybeDeadAccess};
1990void DSEState::deleteDeadInstruction(Instruction *SI,
1991 SmallPtrSetImpl<MemoryAccess *> *
Deleted) {
1992 MemorySSAUpdater Updater(&MSSA);
1997 while (!NowDeadInsts.
empty()) {
2011 SkipStores.insert(MD);
2015 if (
SI->getValueOperand()->getType()->isPointerTy()) {
2017 if (CapturedBeforeReturn.erase(UO))
2018 ShouldIterateEndOfFunctionDSE =
true;
2019 InvisibleToCallerAfterRet.erase(UO);
2020 InvisibleToCallerAfterRetBounded.erase(UO);
2025 Updater.removeMemoryAccess(MA);
2029 if (
I != IOLs.end())
2030 I->second.erase(DeadInst);
2032 for (Use &O : DeadInst->
operands())
2052bool DSEState::mayThrowBetween(Instruction *KillingI, Instruction *DeadI,
2053 const Value *KillingUndObj) {
2057 if (KillingUndObj && isInvisibleToCallerOnUnwind(KillingUndObj))
2061 return ThrowingBlocks.count(KillingI->
getParent());
2062 return !ThrowingBlocks.empty();
2065bool DSEState::isDSEBarrier(
const Value *KillingUndObj, Instruction *DeadI) {
2068 if (DeadI->
mayThrow() && !isInvisibleToCallerOnUnwind(KillingUndObj))
2088bool DSEState::eliminateDeadWritesAtEndOfFunction() {
2089 bool MadeChange =
false;
2091 dbgs() <<
"Trying to eliminate MemoryDefs at the end of the function\n");
2093 ShouldIterateEndOfFunctionDSE =
false;
2095 if (SkipStores.contains(Def))
2099 auto DefLoc = getLocForWrite(DefI);
2100 if (!DefLoc || !isRemovable(DefI)) {
2102 "instruction not removable.\n");
2112 if (!isInvisibleToCallerAfterRet(UO, DefLoc->
Ptr, DefLoc->
Size))
2115 if (isWriteAtEndOfFunction(Def, *DefLoc)) {
2117 LLVM_DEBUG(
dbgs() <<
" ... MemoryDef is not accessed until the end "
2118 "of the function\n");
2124 }
while (ShouldIterateEndOfFunctionDSE);
2128bool DSEState::eliminateRedundantStoresViaDominatingConditions() {
2129 bool MadeChange =
false;
2130 LLVM_DEBUG(
dbgs() <<
"Trying to eliminate MemoryDefs whose value being "
2131 "written is implied by a dominating condition\n");
2133 using ConditionInfo = std::pair<Value *, Value *>;
2134 using ScopedHTType = ScopedHashTable<ConditionInfo, Instruction *>;
2138 ScopedHTType ActiveConditions;
2139 using ConditionData = std::tuple<ConditionInfo, Instruction *, BasicBlock *>;
2140 auto GetDominatingCondition =
2149 if (BI->getSuccessor(0) == BI->getSuccessor(1))
2154 Value *StorePtr, *StoreVal;
2159 ConditionData TrueCond(ConditionInfo(StorePtr, ConstantInt::get(Ty, 1)),
2160 ICmpL, BI->getSuccessor(0));
2161 ConditionData FalseCond(ConditionInfo(StorePtr, ConstantInt::get(Ty, 0)),
2162 ICmpL, BI->getSuccessor(1));
2163 return {TrueCond, FalseCond};
2178 unsigned ImpliedSuccIdx =
Pred == ICmpInst::ICMP_EQ ? 0 : 1;
2179 BasicBlock *ImpliedSucc = BI->getSuccessor(ImpliedSuccIdx);
2180 return {{ConditionInfo(StorePtr, StoreVal), ICmpL, ImpliedSucc}};
2184 if (
Depth > Opts.dse_max_dom_cond_depth)
2190 for (MemoryDef &Def :
2193 if (!SI || !
SI->isUnordered())
2197 {
SI->getPointerOperand(),
SI->getValueOperand()});
2205 MemoryAccess *ClobberingAccess =
2207 if (MSSA.
dominates(ClobberingAccess, LoadAccess)) {
2209 <<
"Removing No-Op Store:\n DEAD: " << *SI <<
'\n');
2211 NumRedundantStores++;
2218 auto Conditions = GetDominatingCondition(BB);
2222 ScopedHTType::ScopeTy
Scope(ActiveConditions);
2223 for (
const auto &[
Cond, LI, ImpliedSucc] : Conditions) {
2224 if (DT.
dominates(BasicBlockEdge(BB, ImpliedSucc), Child->getBlock())) {
2228 ActiveConditions.insert(
Cond, LI);
2235 Self(Child,
Depth + 1, Self);
2245bool DSEState::tryFoldIntoCalloc(MemoryDef *Def,
const Value *DefUO) {
2252 if (!StoredConstant || !StoredConstant->
isNullValue())
2255 if (!isRemovable(DefI))
2259 if (
F.hasFnAttribute(Attribute::SanitizeMemory) ||
2260 F.hasFnAttribute(Attribute::SanitizeAddress) ||
2261 F.hasFnAttribute(Attribute::SanitizeHWAddress) ||
F.getName() ==
"calloc")
2266 auto *InnerCallee =
Malloc->getCalledFunction();
2269 LibFunc
Func =
TLI.getLibFunc(*InnerCallee);
2270 StringRef ZeroedVariantName;
2271 if (Func != LibFunc_malloc || !
TLI.has(Func)) {
2276 if (ZeroedVariantName.
empty())
2285 auto shouldCreateCalloc = [](CallInst *
Malloc, CallInst *Memset) {
2288 auto *MallocBB =
Malloc->getParent(), *MemsetBB = Memset->getParent();
2289 if (MallocBB == MemsetBB)
2291 auto *Ptr = Memset->getArgOperand(0);
2292 auto *TI = MallocBB->getTerminator();
2298 if (MemsetBB != FalseBB)
2309 assert(Func == LibFunc_malloc || !ZeroedVariantName.
empty());
2310 Value *Calloc =
nullptr;
2311 if (!ZeroedVariantName.
empty()) {
2312 LLVMContext &Ctx =
Malloc->getContext();
2313 AttributeList
Attrs = InnerCallee->getAttributes();
2315 Attrs.getFnAttr(Attribute::AllocKind).getAllocKind() |
2316 AllocFnKind::Zeroed;
2319 Attrs.addFnAttribute(Ctx, Attribute::getWithAllocKind(Ctx, AllocKind))
2320 .removeFnAttribute(Ctx,
"alloc-variant-zeroed");
2321 FunctionCallee ZeroedVariant =
Malloc->getModule()->getOrInsertFunction(
2322 ZeroedVariantName, InnerCallee->getFunctionType(), Attrs);
2324 ->setCallingConv(
Malloc->getCallingConv());
2327 CallInst *CI = IRB.CreateCall(ZeroedVariant, Args, ZeroedVariantName);
2331 Type *SizeTTy =
Malloc->getArgOperand(0)->getType();
2332 Calloc =
emitCalloc(ConstantInt::get(SizeTTy, 1),
Malloc->getArgOperand(0),
2333 IRB,
TLI,
Malloc->getType()->getPointerAddressSpace());
2338 if (MDNode *MD =
Malloc->getMetadata(LLVMContext::MD_alloc_token))
2341 MemorySSAUpdater Updater(&MSSA);
2343 nullptr, MallocDef);
2345 Updater.insertDef(NewAccessMD,
true);
2346 Malloc->replaceAllUsesWith(Calloc);
2351bool DSEState::storeIsNoop(MemoryDef *Def,
const Value *DefUO) {
2355 Constant *StoredConstant =
nullptr;
2363 if (!isRemovable(DefI))
2366 if (StoredConstant) {
2371 if (InitC && InitC == StoredConstant)
2380 bool AccessesSameLoc =
2381 LoadI->getPointerOperand() ==
Store->getPointerOperand() ||
2384 if (AccessesSameLoc) {
2388 if (LoadAccess ==
Def->getDefiningAccess())
2394 SetVector<MemoryAccess *> ToCheck;
2395 MemoryAccess *Current =
2403 for (
unsigned I = 1;
I < ToCheck.
size(); ++
I) {
2404 Current = ToCheck[
I];
2407 for (
auto &Use : PhiAccess->incoming_values())
2419 if (LoadAccess != Current)
2431 for (
auto OI : IOL) {
2433 MemoryLocation Loc = *getLocForWrite(DeadI);
2434 assert(isRemovable(DeadI) &&
"Expect only removable instruction");
2437 int64_t DeadStart = 0;
2441 if (IntervalMap.empty())
2448bool DSEState::eliminateRedundantStoresOfExistingValues() {
2449 bool MadeChange =
false;
2450 LLVM_DEBUG(
dbgs() <<
"Trying to eliminate MemoryDefs that write the "
2451 "already existing value\n");
2452 for (
auto *Def : MemDefs) {
2457 auto MaybeDefLoc = getLocForWrite(DefInst);
2458 if (!MaybeDefLoc || !isRemovable(DefInst))
2461 MemoryDef *UpperDef;
2465 if (
Def->isOptimized())
2473 auto IsRedundantStore = [&]() {
2481 auto UpperLoc = getLocForWrite(UpperInst);
2484 int64_t InstWriteOffset = 0;
2485 int64_t DepWriteOffset = 0;
2486 auto OR = isOverwrite(UpperInst, DefInst, *UpperLoc, *MaybeDefLoc,
2487 InstWriteOffset, DepWriteOffset);
2489 return StoredByte && StoredByte == MemSetI->getOperand(1) &&
2496 if (!IsRedundantStore() || isReadClobber(*MaybeDefLoc, DefInst))
2498 LLVM_DEBUG(
dbgs() <<
"DSE: Remove No-Op Store:\n DEAD: " << *DefInst
2501 NumRedundantStores++;
2508DSEState::getInitializesArgMemLoc(
const Instruction *
I) {
2514 SmallMapVector<Value *, SmallVector<ArgumentInitInfo, 2>, 2>
Arguments;
2520 ConstantRangeList Inits;
2532 Inits = ConstantRangeList();
2540 bool IsDeadOrInvisibleOnUnwind =
2543 ArgumentInitInfo InitInfo{
Idx, IsDeadOrInvisibleOnUnwind, Inits};
2544 bool FoundAliasing =
false;
2545 for (
auto &[Arg, AliasList] :
Arguments) {
2551 FoundAliasing =
true;
2552 AliasList.push_back(InitInfo);
2557 FoundAliasing =
true;
2558 AliasList.push_back(ArgumentInitInfo{
Idx, IsDeadOrInvisibleOnUnwind,
2559 ConstantRangeList()});
2568 auto IntersectedRanges =
2570 if (IntersectedRanges.empty())
2573 for (
const auto &Arg : Args) {
2574 for (
const auto &
Range : IntersectedRanges) {
2588std::pair<bool, bool>
2589DSEState::eliminateDeadDefs(
const MemoryLocationWrapper &KillingLocWrapper) {
2591 bool DeletedKillingLoc =
false;
2592 unsigned ScanLimit = Opts.dse_memoryssa_scanlimit;
2593 unsigned WalkerStepLimit = Opts.dse_memoryssa_walklimit;
2594 unsigned PartialLimit = Opts.dse_memoryssa_partial_store_limit;
2597 SmallSetVector<MemoryAccess *, 8> ToCheck;
2601 SmallPtrSet<MemoryAccess *, 8>
Deleted;
2602 [[maybe_unused]]
unsigned OrigNumSkipStores = SkipStores.size();
2607 for (
unsigned I = 0;
I < ToCheck.
size();
I++) {
2608 MemoryAccess *Current = ToCheck[
I];
2609 if (
Deleted.contains(Current))
2611 std::optional<MemoryAccess *> MaybeDeadAccess = getDomMemoryDef(
2612 KillingLocWrapper.MemDef, Current, KillingLocWrapper.MemLoc,
2613 KillingLocWrapper.UnderlyingObject, ScanLimit, WalkerStepLimit,
2614 isMemTerminatorInst(KillingLocWrapper.DefInst), PartialLimit,
2615 KillingLocWrapper.DefByInitializesAttr);
2617 if (!MaybeDeadAccess) {
2621 MemoryAccess *DeadAccess = *MaybeDeadAccess;
2622 LLVM_DEBUG(
dbgs() <<
" Checking if we can kill " << *DeadAccess);
2624 LLVM_DEBUG(
dbgs() <<
"\n ... adding incoming values to worklist\n");
2633 if (PostOrderNumbers[IncomingBlock] > PostOrderNumbers[PhiBlock])
2634 ToCheck.
insert(IncomingAccess);
2645 MemoryDefWrapper DeadDefWrapper(
2649 assert(DeadDefWrapper.DefinedLocations.size() == 1);
2650 MemoryLocationWrapper &DeadLocWrapper =
2651 DeadDefWrapper.DefinedLocations.front();
2654 NumGetDomMemoryDefPassed++;
2658 if (isMemTerminatorInst(KillingLocWrapper.DefInst)) {
2659 if (KillingLocWrapper.UnderlyingObject != DeadLocWrapper.UnderlyingObject)
2662 << *DeadLocWrapper.DefInst <<
"\n KILLER: "
2663 << *KillingLocWrapper.DefInst <<
'\n');
2669 int64_t KillingOffset = 0;
2670 int64_t DeadOffset = 0;
2671 OverwriteResult
OR =
2672 isOverwrite(KillingLocWrapper.DefInst, DeadLocWrapper.DefInst,
2673 KillingLocWrapper.MemLoc, DeadLocWrapper.MemLoc,
2674 KillingOffset, DeadOffset);
2675 if (OR == OW_MaybePartial) {
2676 auto &IOL = IOLs[DeadLocWrapper.DefInst->
getParent()];
2678 DeadLocWrapper.MemLoc, KillingOffset,
2679 DeadOffset, DeadLocWrapper.DefInst, IOL);
2681 if (Opts.enable_dse_partial_store_merging &&
2682 OR == OW_PartialEarlierWithFullLater) {
2688 if (DeadSI && KillingSI && DT.
dominates(DeadSI, KillingSI)) {
2690 KillingSI, DeadSI, KillingOffset, DeadOffset,
DL, BatchAA,
2694 DeadSI->setOperand(0, Merged);
2695 ++NumModifiedStores;
2697 DeletedKillingLoc =
true;
2702 auto I = IOLs.find(DeadSI->getParent());
2703 if (
I != IOLs.end())
2704 I->second.erase(DeadSI);
2709 if (OR == OW_Complete) {
2711 << *DeadLocWrapper.DefInst <<
"\n KILLER: "
2712 << *KillingLocWrapper.DefInst <<
'\n');
2720 assert(SkipStores.size() - OrigNumSkipStores ==
Deleted.size() &&
2721 "SkipStores and Deleted out of sync?");
2723 return {
Changed, DeletedKillingLoc};
2726bool DSEState::eliminateDeadDefs(
const MemoryDefWrapper &KillingDefWrapper) {
2727 if (KillingDefWrapper.DefinedLocations.empty()) {
2728 LLVM_DEBUG(
dbgs() <<
"Failed to find analyzable write location for "
2729 << *KillingDefWrapper.DefInst <<
"\n");
2733 bool MadeChange =
false;
2734 for (
auto &KillingLocWrapper : KillingDefWrapper.DefinedLocations) {
2736 << *KillingLocWrapper.MemDef <<
" ("
2737 << *KillingLocWrapper.DefInst <<
")\n");
2738 auto [
Changed, DeletedKillingLoc] = eliminateDeadDefs(KillingLocWrapper);
2742 if (!DeletedKillingLoc && storeIsNoop(KillingLocWrapper.MemDef,
2743 KillingLocWrapper.UnderlyingObject)) {
2745 << *KillingLocWrapper.DefInst <<
'\n');
2747 NumRedundantStores++;
2752 if (!DeletedKillingLoc &&
2753 tryFoldIntoCalloc(KillingLocWrapper.MemDef,
2754 KillingLocWrapper.UnderlyingObject)) {
2755 LLVM_DEBUG(
dbgs() <<
"DSE: Remove memset after forming calloc:\n"
2756 <<
" DEAD: " << *KillingLocWrapper.DefInst <<
'\n');
2770 bool MadeChange =
false;
2771 DSEState State(Opts,
F,
AA, MSSA, DT, PDT,
TLI, CI);
2773 for (
unsigned I = 0;
I < State.MemDefs.size();
I++) {
2775 if (State.SkipStores.count(KillingDef))
2778 MemoryDefWrapper KillingDefWrapper(
2781 Opts.enable_dse_initializes_attr_improvement));
2782 MadeChange |= State.eliminateDeadDefs(KillingDefWrapper);
2785 if (Opts.enable_dse_partial_overwrite_tracking)
2786 for (
auto &KV : State.IOLs)
2787 MadeChange |= State.removePartiallyOverlappedStores(KV.second);
2789 MadeChange |= State.eliminateRedundantStoresOfExistingValues();
2790 MadeChange |= State.eliminateDeadWritesAtEndOfFunction();
2791 MadeChange |= State.eliminateRedundantStoresViaDominatingConditions();
2793 while (!State.ToRemove.empty()) {
2794 Instruction *DeadInst = State.ToRemove.pop_back_val();
2814#ifdef LLVM_ENABLE_STATS
2841 if (skipFunction(
F))
2844 AliasAnalysis &
AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
2845 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
2847 getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F);
2848 MemorySSA &MSSA = getAnalysis<MemorySSAWrapperPass>().getMSSA();
2850 getAnalysis<PostDominatorTreeWrapperPass>().getPostDomTree();
2851 CycleInfo &CI = getAnalysis<CycleInfoWrapperPass>().getResult();
2855#ifdef LLVM_ENABLE_STATS
2864 void getAnalysisUsage(AnalysisUsage &AU)
const override {
2880char DSELegacyPass::ID = 0;
2897 return new DSELegacyPass();
const TargetLowering & TLI
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.
SmallVector< MachineOperand, 4 > 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.
uint64_t getZExtValue() const
Get zero extended value.
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.
bool ult(const APInt &RHS) const
Unsigned less than comparison.
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.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
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 * stripAndAccumulateConstantOffsets(const DataLayout &DL, APInt &Offset, bool AllowNonInbounds, bool AllowInvariantGroup=false, function_ref< bool(Value &Value, APInt &Offset)> ExternalAnalysis=nullptr, bool LookThroughIntToPtr=false) const
Accumulate the constant offset this value has compared to a base pointer.
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.
is_zero< true > m_Zero()
Match any null constant or a vector with all elements equal to 0.
NoWrapTrunc_match< OpTy, TruncInst::NoUnsignedWrap > m_NUWTrunc(const OpTy &Op)
Matches trunc nuw.
brc_match< Cond_t, match_bind< BasicBlock >, match_bind< BasicBlock > > m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F)
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.
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
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.
const ScalarOptions & getScalarOptions(const LLVMContext &C)
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.
@ End
Run the machine verifier once, at the end of the pipeline.
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.