2740 lines · cpp
1//===- DeadStoreElimination.cpp - MemorySSA Backed Dead Store Elimination -===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// The code below implements dead store elimination using MemorySSA. It uses10// the following general approach: given a MemoryDef, walk upwards to find11// clobbering MemoryDefs that may be killed by the starting def. Then check12// that there are no uses that may read the location of the original MemoryDef13// in between both MemoryDefs. A bit more concretely:14//15// For all MemoryDefs StartDef:16// 1. Get the next dominating clobbering MemoryDef (MaybeDeadAccess) by walking17// upwards.18// 2. Check that there are no reads between MaybeDeadAccess and the StartDef by19// checking all uses starting at MaybeDeadAccess and walking until we see20// StartDef.21// 3. For each found CurrentDef, check that:22// 1. There are no barrier instructions between CurrentDef and StartDef (like23// throws or stores with ordering constraints).24// 2. StartDef is executed whenever CurrentDef is executed.25// 3. StartDef completely overwrites CurrentDef.26// 4. Erase CurrentDef from the function and MemorySSA.27//28//===----------------------------------------------------------------------===//29 30#include "llvm/Transforms/Scalar/DeadStoreElimination.h"31#include "llvm/ADT/APInt.h"32#include "llvm/ADT/DenseMap.h"33#include "llvm/ADT/MapVector.h"34#include "llvm/ADT/PostOrderIterator.h"35#include "llvm/ADT/SetVector.h"36#include "llvm/ADT/SmallPtrSet.h"37#include "llvm/ADT/SmallVector.h"38#include "llvm/ADT/Statistic.h"39#include "llvm/ADT/StringRef.h"40#include "llvm/Analysis/AliasAnalysis.h"41#include "llvm/Analysis/AssumptionCache.h"42#include "llvm/Analysis/CaptureTracking.h"43#include "llvm/Analysis/GlobalsModRef.h"44#include "llvm/Analysis/LoopInfo.h"45#include "llvm/Analysis/MemoryBuiltins.h"46#include "llvm/Analysis/MemoryLocation.h"47#include "llvm/Analysis/MemorySSA.h"48#include "llvm/Analysis/MemorySSAUpdater.h"49#include "llvm/Analysis/MustExecute.h"50#include "llvm/Analysis/PostDominators.h"51#include "llvm/Analysis/TargetLibraryInfo.h"52#include "llvm/Analysis/ValueTracking.h"53#include "llvm/IR/Argument.h"54#include "llvm/IR/AttributeMask.h"55#include "llvm/IR/BasicBlock.h"56#include "llvm/IR/Constant.h"57#include "llvm/IR/ConstantRangeList.h"58#include "llvm/IR/Constants.h"59#include "llvm/IR/DataLayout.h"60#include "llvm/IR/DebugInfo.h"61#include "llvm/IR/Dominators.h"62#include "llvm/IR/Function.h"63#include "llvm/IR/IRBuilder.h"64#include "llvm/IR/InstIterator.h"65#include "llvm/IR/InstrTypes.h"66#include "llvm/IR/Instruction.h"67#include "llvm/IR/Instructions.h"68#include "llvm/IR/IntrinsicInst.h"69#include "llvm/IR/Module.h"70#include "llvm/IR/PassManager.h"71#include "llvm/IR/PatternMatch.h"72#include "llvm/IR/Value.h"73#include "llvm/InitializePasses.h"74#include "llvm/Support/Casting.h"75#include "llvm/Support/CommandLine.h"76#include "llvm/Support/Debug.h"77#include "llvm/Support/DebugCounter.h"78#include "llvm/Support/ErrorHandling.h"79#include "llvm/Support/raw_ostream.h"80#include "llvm/Transforms/Scalar.h"81#include "llvm/Transforms/Utils/AssumeBundleBuilder.h"82#include "llvm/Transforms/Utils/BuildLibCalls.h"83#include "llvm/Transforms/Utils/Local.h"84#include <algorithm>85#include <cassert>86#include <cstdint>87#include <map>88#include <optional>89#include <utility>90 91using namespace llvm;92using namespace PatternMatch;93 94#define DEBUG_TYPE "dse"95 96STATISTIC(NumRemainingStores, "Number of stores remaining after DSE");97STATISTIC(NumRedundantStores, "Number of redundant stores deleted");98STATISTIC(NumFastStores, "Number of stores deleted");99STATISTIC(NumFastOther, "Number of other instrs removed");100STATISTIC(NumCompletePartials, "Number of stores dead by later partials");101STATISTIC(NumModifiedStores, "Number of stores modified");102STATISTIC(NumCFGChecks, "Number of stores modified");103STATISTIC(NumCFGTries, "Number of stores modified");104STATISTIC(NumCFGSuccess, "Number of stores modified");105STATISTIC(NumGetDomMemoryDefPassed,106 "Number of times a valid candidate is returned from getDomMemoryDef");107STATISTIC(NumDomMemDefChecks,108 "Number iterations check for reads in getDomMemoryDef");109 110DEBUG_COUNTER(MemorySSACounter, "dse-memoryssa",111 "Controls which MemoryDefs are eliminated.");112 113static cl::opt<bool>114EnablePartialOverwriteTracking("enable-dse-partial-overwrite-tracking",115 cl::init(true), cl::Hidden,116 cl::desc("Enable partial-overwrite tracking in DSE"));117 118static cl::opt<bool>119EnablePartialStoreMerging("enable-dse-partial-store-merging",120 cl::init(true), cl::Hidden,121 cl::desc("Enable partial store merging in DSE"));122 123static cl::opt<unsigned>124 MemorySSAScanLimit("dse-memoryssa-scanlimit", cl::init(150), cl::Hidden,125 cl::desc("The number of memory instructions to scan for "126 "dead store elimination (default = 150)"));127static cl::opt<unsigned> MemorySSAUpwardsStepLimit(128 "dse-memoryssa-walklimit", cl::init(90), cl::Hidden,129 cl::desc("The maximum number of steps while walking upwards to find "130 "MemoryDefs that may be killed (default = 90)"));131 132static cl::opt<unsigned> MemorySSAPartialStoreLimit(133 "dse-memoryssa-partial-store-limit", cl::init(5), cl::Hidden,134 cl::desc("The maximum number candidates that only partially overwrite the "135 "killing MemoryDef to consider"136 " (default = 5)"));137 138static cl::opt<unsigned> MemorySSADefsPerBlockLimit(139 "dse-memoryssa-defs-per-block-limit", cl::init(5000), cl::Hidden,140 cl::desc("The number of MemoryDefs we consider as candidates to eliminated "141 "other stores per basic block (default = 5000)"));142 143static cl::opt<unsigned> MemorySSASameBBStepCost(144 "dse-memoryssa-samebb-cost", cl::init(1), cl::Hidden,145 cl::desc(146 "The cost of a step in the same basic block as the killing MemoryDef"147 "(default = 1)"));148 149static cl::opt<unsigned>150 MemorySSAOtherBBStepCost("dse-memoryssa-otherbb-cost", cl::init(5),151 cl::Hidden,152 cl::desc("The cost of a step in a different basic "153 "block than the killing MemoryDef"154 "(default = 5)"));155 156static cl::opt<unsigned> MemorySSAPathCheckLimit(157 "dse-memoryssa-path-check-limit", cl::init(50), cl::Hidden,158 cl::desc("The maximum number of blocks to check when trying to prove that "159 "all paths to an exit go through a killing block (default = 50)"));160 161// This flags allows or disallows DSE to optimize MemorySSA during its162// traversal. Note that DSE optimizing MemorySSA may impact other passes163// downstream of the DSE invocation and can lead to issues not being164// reproducible in isolation (i.e. when MemorySSA is built from scratch). In165// those cases, the flag can be used to check if DSE's MemorySSA optimizations166// impact follow-up passes.167static cl::opt<bool>168 OptimizeMemorySSA("dse-optimize-memoryssa", cl::init(true), cl::Hidden,169 cl::desc("Allow DSE to optimize memory accesses."));170 171// TODO: remove this flag.172static cl::opt<bool> EnableInitializesImprovement(173 "enable-dse-initializes-attr-improvement", cl::init(true), cl::Hidden,174 cl::desc("Enable the initializes attr improvement in DSE"));175 176//===----------------------------------------------------------------------===//177// Helper functions178//===----------------------------------------------------------------------===//179using OverlapIntervalsTy = std::map<int64_t, int64_t>;180using InstOverlapIntervalsTy = MapVector<Instruction *, OverlapIntervalsTy>;181 182/// Returns true if the end of this instruction can be safely shortened in183/// length.184static bool isShortenableAtTheEnd(Instruction *I) {185 // Don't shorten stores for now186 if (isa<StoreInst>(I))187 return false;188 189 if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {190 switch (II->getIntrinsicID()) {191 default: return false;192 case Intrinsic::memset:193 case Intrinsic::memcpy:194 case Intrinsic::memcpy_element_unordered_atomic:195 case Intrinsic::memset_element_unordered_atomic:196 // Do shorten memory intrinsics.197 // FIXME: Add memmove if it's also safe to transform.198 return true;199 }200 }201 202 // Don't shorten libcalls calls for now.203 204 return false;205}206 207/// Returns true if the beginning of this instruction can be safely shortened208/// in length.209static bool isShortenableAtTheBeginning(Instruction *I) {210 // FIXME: Handle only memset for now. Supporting memcpy/memmove should be211 // easily done by offsetting the source address.212 return isa<AnyMemSetInst>(I);213}214 215static std::optional<TypeSize> getPointerSize(const Value *V,216 const DataLayout &DL,217 const TargetLibraryInfo &TLI,218 const Function *F) {219 uint64_t Size;220 ObjectSizeOpts Opts;221 Opts.NullIsUnknownSize = NullPointerIsDefined(F);222 223 if (getObjectSize(V, Size, DL, &TLI, Opts))224 return TypeSize::getFixed(Size);225 return std::nullopt;226}227 228namespace {229 230enum OverwriteResult {231 OW_Begin,232 OW_Complete,233 OW_End,234 OW_PartialEarlierWithFullLater,235 OW_MaybePartial,236 OW_None,237 OW_Unknown238};239 240} // end anonymous namespace241 242/// Check if two instruction are masked stores that completely243/// overwrite one another. More specifically, \p KillingI has to244/// overwrite \p DeadI.245static OverwriteResult isMaskedStoreOverwrite(const Instruction *KillingI,246 const Instruction *DeadI,247 BatchAAResults &AA) {248 const auto *KillingII = dyn_cast<IntrinsicInst>(KillingI);249 const auto *DeadII = dyn_cast<IntrinsicInst>(DeadI);250 if (KillingII == nullptr || DeadII == nullptr)251 return OW_Unknown;252 if (KillingII->getIntrinsicID() != DeadII->getIntrinsicID())253 return OW_Unknown;254 255 switch (KillingII->getIntrinsicID()) {256 case Intrinsic::masked_store:257 case Intrinsic::vp_store: {258 const DataLayout &DL = KillingII->getDataLayout();259 auto *KillingTy = KillingII->getArgOperand(0)->getType();260 auto *DeadTy = DeadII->getArgOperand(0)->getType();261 if (DL.getTypeSizeInBits(KillingTy) != DL.getTypeSizeInBits(DeadTy))262 return OW_Unknown;263 // Element count.264 if (cast<VectorType>(KillingTy)->getElementCount() !=265 cast<VectorType>(DeadTy)->getElementCount())266 return OW_Unknown;267 // Pointers.268 Value *KillingPtr = KillingII->getArgOperand(1);269 Value *DeadPtr = DeadII->getArgOperand(1);270 if (KillingPtr != DeadPtr && !AA.isMustAlias(KillingPtr, DeadPtr))271 return OW_Unknown;272 if (KillingII->getIntrinsicID() == Intrinsic::masked_store) {273 // Masks.274 // TODO: check that KillingII's mask is a superset of the DeadII's mask.275 if (KillingII->getArgOperand(2) != DeadII->getArgOperand(2))276 return OW_Unknown;277 } else if (KillingII->getIntrinsicID() == Intrinsic::vp_store) {278 // Masks.279 // TODO: check that KillingII's mask is a superset of the DeadII's mask.280 if (KillingII->getArgOperand(2) != DeadII->getArgOperand(2))281 return OW_Unknown;282 // Lengths.283 if (KillingII->getArgOperand(3) != DeadII->getArgOperand(3))284 return OW_Unknown;285 }286 return OW_Complete;287 }288 default:289 return OW_Unknown;290 }291}292 293/// Return 'OW_Complete' if a store to the 'KillingLoc' location completely294/// overwrites a store to the 'DeadLoc' location, 'OW_End' if the end of the295/// 'DeadLoc' location is completely overwritten by 'KillingLoc', 'OW_Begin'296/// if the beginning of the 'DeadLoc' location is overwritten by 'KillingLoc'.297/// 'OW_PartialEarlierWithFullLater' means that a dead (big) store was298/// overwritten by a killing (smaller) store which doesn't write outside the big299/// store's memory locations. Returns 'OW_Unknown' if nothing can be determined.300/// NOTE: This function must only be called if both \p KillingLoc and \p301/// DeadLoc belong to the same underlying object with valid \p KillingOff and302/// \p DeadOff.303static OverwriteResult isPartialOverwrite(const MemoryLocation &KillingLoc,304 const MemoryLocation &DeadLoc,305 int64_t KillingOff, int64_t DeadOff,306 Instruction *DeadI,307 InstOverlapIntervalsTy &IOL) {308 const uint64_t KillingSize = KillingLoc.Size.getValue();309 const uint64_t DeadSize = DeadLoc.Size.getValue();310 // We may now overlap, although the overlap is not complete. There might also311 // be other incomplete overlaps, and together, they might cover the complete312 // dead store.313 // Note: The correctness of this logic depends on the fact that this function314 // is not even called providing DepWrite when there are any intervening reads.315 if (EnablePartialOverwriteTracking &&316 KillingOff < int64_t(DeadOff + DeadSize) &&317 int64_t(KillingOff + KillingSize) >= DeadOff) {318 319 // Insert our part of the overlap into the map.320 auto &IM = IOL[DeadI];321 LLVM_DEBUG(dbgs() << "DSE: Partial overwrite: DeadLoc [" << DeadOff << ", "322 << int64_t(DeadOff + DeadSize) << ") KillingLoc ["323 << KillingOff << ", " << int64_t(KillingOff + KillingSize)324 << ")\n");325 326 // Make sure that we only insert non-overlapping intervals and combine327 // adjacent intervals. The intervals are stored in the map with the ending328 // offset as the key (in the half-open sense) and the starting offset as329 // the value.330 int64_t KillingIntStart = KillingOff;331 int64_t KillingIntEnd = KillingOff + KillingSize;332 333 // Find any intervals ending at, or after, KillingIntStart which start334 // before KillingIntEnd.335 auto ILI = IM.lower_bound(KillingIntStart);336 if (ILI != IM.end() && ILI->second <= KillingIntEnd) {337 // This existing interval is overlapped with the current store somewhere338 // in [KillingIntStart, KillingIntEnd]. Merge them by erasing the existing339 // intervals and adjusting our start and end.340 KillingIntStart = std::min(KillingIntStart, ILI->second);341 KillingIntEnd = std::max(KillingIntEnd, ILI->first);342 ILI = IM.erase(ILI);343 344 // Continue erasing and adjusting our end in case other previous345 // intervals are also overlapped with the current store.346 //347 // |--- dead 1 ---| |--- dead 2 ---|348 // |------- killing---------|349 //350 while (ILI != IM.end() && ILI->second <= KillingIntEnd) {351 assert(ILI->second > KillingIntStart && "Unexpected interval");352 KillingIntEnd = std::max(KillingIntEnd, ILI->first);353 ILI = IM.erase(ILI);354 }355 }356 357 IM[KillingIntEnd] = KillingIntStart;358 359 ILI = IM.begin();360 if (ILI->second <= DeadOff && ILI->first >= int64_t(DeadOff + DeadSize)) {361 LLVM_DEBUG(dbgs() << "DSE: Full overwrite from partials: DeadLoc ["362 << DeadOff << ", " << int64_t(DeadOff + DeadSize)363 << ") Composite KillingLoc [" << ILI->second << ", "364 << ILI->first << ")\n");365 ++NumCompletePartials;366 return OW_Complete;367 }368 }369 370 // Check for a dead store which writes to all the memory locations that371 // the killing store writes to.372 if (EnablePartialStoreMerging && KillingOff >= DeadOff &&373 int64_t(DeadOff + DeadSize) > KillingOff &&374 uint64_t(KillingOff - DeadOff) + KillingSize <= DeadSize) {375 LLVM_DEBUG(dbgs() << "DSE: Partial overwrite a dead load [" << DeadOff376 << ", " << int64_t(DeadOff + DeadSize)377 << ") by a killing store [" << KillingOff << ", "378 << int64_t(KillingOff + KillingSize) << ")\n");379 // TODO: Maybe come up with a better name?380 return OW_PartialEarlierWithFullLater;381 }382 383 // Another interesting case is if the killing store overwrites the end of the384 // dead store.385 //386 // |--dead--|387 // |-- killing --|388 //389 // In this case we may want to trim the size of dead store to avoid390 // generating stores to addresses which will definitely be overwritten killing391 // store.392 if (!EnablePartialOverwriteTracking &&393 (KillingOff > DeadOff && KillingOff < int64_t(DeadOff + DeadSize) &&394 int64_t(KillingOff + KillingSize) >= int64_t(DeadOff + DeadSize)))395 return OW_End;396 397 // Finally, we also need to check if the killing store overwrites the398 // beginning of the dead store.399 //400 // |--dead--|401 // |-- killing --|402 //403 // In this case we may want to move the destination address and trim the size404 // of dead store to avoid generating stores to addresses which will definitely405 // be overwritten killing store.406 if (!EnablePartialOverwriteTracking &&407 (KillingOff <= DeadOff && int64_t(KillingOff + KillingSize) > DeadOff)) {408 assert(int64_t(KillingOff + KillingSize) < int64_t(DeadOff + DeadSize) &&409 "Expect to be handled as OW_Complete");410 return OW_Begin;411 }412 // Otherwise, they don't completely overlap.413 return OW_Unknown;414}415 416/// Returns true if the memory which is accessed by the second instruction is not417/// modified between the first and the second instruction.418/// Precondition: Second instruction must be dominated by the first419/// instruction.420static bool421memoryIsNotModifiedBetween(Instruction *FirstI, Instruction *SecondI,422 BatchAAResults &AA, const DataLayout &DL,423 DominatorTree *DT) {424 // Do a backwards scan through the CFG from SecondI to FirstI. Look for425 // instructions which can modify the memory location accessed by SecondI.426 //427 // While doing the walk keep track of the address to check. It might be428 // different in different basic blocks due to PHI translation.429 using BlockAddressPair = std::pair<BasicBlock *, PHITransAddr>;430 SmallVector<BlockAddressPair, 16> WorkList;431 // Keep track of the address we visited each block with. Bail out if we432 // visit a block with different addresses.433 DenseMap<BasicBlock *, Value *> Visited;434 435 BasicBlock::iterator FirstBBI(FirstI);436 ++FirstBBI;437 BasicBlock::iterator SecondBBI(SecondI);438 BasicBlock *FirstBB = FirstI->getParent();439 BasicBlock *SecondBB = SecondI->getParent();440 MemoryLocation MemLoc;441 if (auto *MemSet = dyn_cast<MemSetInst>(SecondI))442 MemLoc = MemoryLocation::getForDest(MemSet);443 else444 MemLoc = MemoryLocation::get(SecondI);445 446 auto *MemLocPtr = const_cast<Value *>(MemLoc.Ptr);447 448 // Start checking the SecondBB.449 WorkList.push_back(450 std::make_pair(SecondBB, PHITransAddr(MemLocPtr, DL, nullptr)));451 bool isFirstBlock = true;452 453 // Check all blocks going backward until we reach the FirstBB.454 while (!WorkList.empty()) {455 BlockAddressPair Current = WorkList.pop_back_val();456 BasicBlock *B = Current.first;457 PHITransAddr &Addr = Current.second;458 Value *Ptr = Addr.getAddr();459 460 // Ignore instructions before FirstI if this is the FirstBB.461 BasicBlock::iterator BI = (B == FirstBB ? FirstBBI : B->begin());462 463 BasicBlock::iterator EI;464 if (isFirstBlock) {465 // Ignore instructions after SecondI if this is the first visit of SecondBB.466 assert(B == SecondBB && "first block is not the store block");467 EI = SecondBBI;468 isFirstBlock = false;469 } else {470 // It's not SecondBB or (in case of a loop) the second visit of SecondBB.471 // In this case we also have to look at instructions after SecondI.472 EI = B->end();473 }474 for (; BI != EI; ++BI) {475 Instruction *I = &*BI;476 if (I->mayWriteToMemory() && I != SecondI)477 if (isModSet(AA.getModRefInfo(I, MemLoc.getWithNewPtr(Ptr))))478 return false;479 }480 if (B != FirstBB) {481 assert(B != &FirstBB->getParent()->getEntryBlock() &&482 "Should not hit the entry block because SI must be dominated by LI");483 for (BasicBlock *Pred : predecessors(B)) {484 PHITransAddr PredAddr = Addr;485 if (PredAddr.needsPHITranslationFromBlock(B)) {486 if (!PredAddr.isPotentiallyPHITranslatable())487 return false;488 if (!PredAddr.translateValue(B, Pred, DT, false))489 return false;490 }491 Value *TranslatedPtr = PredAddr.getAddr();492 auto Inserted = Visited.insert(std::make_pair(Pred, TranslatedPtr));493 if (!Inserted.second) {494 // We already visited this block before. If it was with a different495 // address - bail out!496 if (TranslatedPtr != Inserted.first->second)497 return false;498 // ... otherwise just skip it.499 continue;500 }501 WorkList.push_back(std::make_pair(Pred, PredAddr));502 }503 }504 }505 return true;506}507 508static void shortenAssignment(Instruction *Inst, Value *OriginalDest,509 uint64_t OldOffsetInBits, uint64_t OldSizeInBits,510 uint64_t NewSizeInBits, bool IsOverwriteEnd) {511 const DataLayout &DL = Inst->getDataLayout();512 uint64_t DeadSliceSizeInBits = OldSizeInBits - NewSizeInBits;513 uint64_t DeadSliceOffsetInBits =514 OldOffsetInBits + (IsOverwriteEnd ? NewSizeInBits : 0);515 auto SetDeadFragExpr = [](auto *Assign,516 DIExpression::FragmentInfo DeadFragment) {517 // createFragmentExpression expects an offset relative to the existing518 // fragment offset if there is one.519 uint64_t RelativeOffset = DeadFragment.OffsetInBits -520 Assign->getExpression()521 ->getFragmentInfo()522 .value_or(DIExpression::FragmentInfo(0, 0))523 .OffsetInBits;524 if (auto NewExpr = DIExpression::createFragmentExpression(525 Assign->getExpression(), RelativeOffset, DeadFragment.SizeInBits)) {526 Assign->setExpression(*NewExpr);527 return;528 }529 // Failed to create a fragment expression for this so discard the value,530 // making this a kill location.531 auto *Expr = *DIExpression::createFragmentExpression(532 DIExpression::get(Assign->getContext(), {}), DeadFragment.OffsetInBits,533 DeadFragment.SizeInBits);534 Assign->setExpression(Expr);535 Assign->setKillLocation();536 };537 538 // A DIAssignID to use so that the inserted dbg.assign intrinsics do not539 // link to any instructions. Created in the loop below (once).540 DIAssignID *LinkToNothing = nullptr;541 LLVMContext &Ctx = Inst->getContext();542 auto GetDeadLink = [&Ctx, &LinkToNothing]() {543 if (!LinkToNothing)544 LinkToNothing = DIAssignID::getDistinct(Ctx);545 return LinkToNothing;546 };547 548 // Insert an unlinked dbg.assign intrinsic for the dead fragment after each549 // overlapping dbg.assign intrinsic.550 for (DbgVariableRecord *Assign : at::getDVRAssignmentMarkers(Inst)) {551 std::optional<DIExpression::FragmentInfo> NewFragment;552 if (!at::calculateFragmentIntersect(DL, OriginalDest, DeadSliceOffsetInBits,553 DeadSliceSizeInBits, Assign,554 NewFragment) ||555 !NewFragment) {556 // We couldn't calculate the intersecting fragment for some reason. Be557 // cautious and unlink the whole assignment from the store.558 Assign->setKillAddress();559 Assign->setAssignId(GetDeadLink());560 continue;561 }562 // No intersect.563 if (NewFragment->SizeInBits == 0)564 continue;565 566 // Fragments overlap: insert a new dbg.assign for this dead part.567 auto *NewAssign = static_cast<decltype(Assign)>(Assign->clone());568 NewAssign->insertAfter(Assign->getIterator());569 NewAssign->setAssignId(GetDeadLink());570 if (NewFragment)571 SetDeadFragExpr(NewAssign, *NewFragment);572 NewAssign->setKillAddress();573 }574}575 576/// Update the attributes given that a memory access is updated (the577/// dereferenced pointer could be moved forward when shortening a578/// mem intrinsic).579static void adjustArgAttributes(AnyMemIntrinsic *Intrinsic, unsigned ArgNo,580 uint64_t PtrOffset) {581 // Remember old attributes.582 AttributeSet OldAttrs = Intrinsic->getParamAttributes(ArgNo);583 584 // Find attributes that should be kept, and remove the rest.585 AttributeMask AttrsToRemove;586 for (auto &Attr : OldAttrs) {587 if (Attr.hasKindAsEnum()) {588 switch (Attr.getKindAsEnum()) {589 default:590 break;591 case Attribute::Alignment:592 // Only keep alignment if PtrOffset satisfy the alignment.593 if (isAligned(Attr.getAlignment().valueOrOne(), PtrOffset))594 continue;595 break;596 case Attribute::Dereferenceable:597 case Attribute::DereferenceableOrNull:598 // We could reduce the size of these attributes according to599 // PtrOffset. But we simply drop these for now.600 break;601 case Attribute::NonNull:602 case Attribute::NoUndef:603 continue;604 }605 }606 AttrsToRemove.addAttribute(Attr);607 }608 609 // Remove the attributes that should be dropped.610 Intrinsic->removeParamAttrs(ArgNo, AttrsToRemove);611}612 613static bool tryToShorten(Instruction *DeadI, int64_t &DeadStart,614 uint64_t &DeadSize, int64_t KillingStart,615 uint64_t KillingSize, bool IsOverwriteEnd) {616 auto *DeadIntrinsic = cast<AnyMemIntrinsic>(DeadI);617 Align PrefAlign = DeadIntrinsic->getDestAlign().valueOrOne();618 619 // We assume that memet/memcpy operates in chunks of the "largest" native620 // type size and aligned on the same value. That means optimal start and size621 // of memset/memcpy should be modulo of preferred alignment of that type. That622 // is it there is no any sense in trying to reduce store size any further623 // since any "extra" stores comes for free anyway.624 // On the other hand, maximum alignment we can achieve is limited by alignment625 // of initial store.626 627 // TODO: Limit maximum alignment by preferred (or abi?) alignment of the628 // "largest" native type.629 // Note: What is the proper way to get that value?630 // Should TargetTransformInfo::getRegisterBitWidth be used or anything else?631 // PrefAlign = std::min(DL.getPrefTypeAlign(LargestType), PrefAlign);632 633 int64_t ToRemoveStart = 0;634 uint64_t ToRemoveSize = 0;635 // Compute start and size of the region to remove. Make sure 'PrefAlign' is636 // maintained on the remaining store.637 if (IsOverwriteEnd) {638 // Calculate required adjustment for 'KillingStart' in order to keep639 // remaining store size aligned on 'PerfAlign'.640 uint64_t Off =641 offsetToAlignment(uint64_t(KillingStart - DeadStart), PrefAlign);642 ToRemoveStart = KillingStart + Off;643 if (DeadSize <= uint64_t(ToRemoveStart - DeadStart))644 return false;645 ToRemoveSize = DeadSize - uint64_t(ToRemoveStart - DeadStart);646 } else {647 ToRemoveStart = DeadStart;648 assert(KillingSize >= uint64_t(DeadStart - KillingStart) &&649 "Not overlapping accesses?");650 ToRemoveSize = KillingSize - uint64_t(DeadStart - KillingStart);651 // Calculate required adjustment for 'ToRemoveSize'in order to keep652 // start of the remaining store aligned on 'PerfAlign'.653 uint64_t Off = offsetToAlignment(ToRemoveSize, PrefAlign);654 if (Off != 0) {655 if (ToRemoveSize <= (PrefAlign.value() - Off))656 return false;657 ToRemoveSize -= PrefAlign.value() - Off;658 }659 assert(isAligned(PrefAlign, ToRemoveSize) &&660 "Should preserve selected alignment");661 }662 663 assert(ToRemoveSize > 0 && "Shouldn't reach here if nothing to remove");664 assert(DeadSize > ToRemoveSize && "Can't remove more than original size");665 666 uint64_t NewSize = DeadSize - ToRemoveSize;667 if (DeadIntrinsic->isAtomic()) {668 // When shortening an atomic memory intrinsic, the newly shortened669 // length must remain an integer multiple of the element size.670 const uint32_t ElementSize = DeadIntrinsic->getElementSizeInBytes();671 if (0 != NewSize % ElementSize)672 return false;673 }674 675 LLVM_DEBUG(dbgs() << "DSE: Remove Dead Store:\n OW "676 << (IsOverwriteEnd ? "END" : "BEGIN") << ": " << *DeadI677 << "\n KILLER [" << ToRemoveStart << ", "678 << int64_t(ToRemoveStart + ToRemoveSize) << ")\n");679 680 DeadIntrinsic->setLength(NewSize);681 DeadIntrinsic->setDestAlignment(PrefAlign);682 683 Value *OrigDest = DeadIntrinsic->getRawDest();684 if (!IsOverwriteEnd) {685 Value *Indices[1] = {686 ConstantInt::get(DeadIntrinsic->getLength()->getType(), ToRemoveSize)};687 Instruction *NewDestGEP = GetElementPtrInst::CreateInBounds(688 Type::getInt8Ty(DeadIntrinsic->getContext()), OrigDest, Indices, "",689 DeadI->getIterator());690 NewDestGEP->setDebugLoc(DeadIntrinsic->getDebugLoc());691 DeadIntrinsic->setDest(NewDestGEP);692 adjustArgAttributes(DeadIntrinsic, 0, ToRemoveSize);693 }694 695 // Update attached dbg.assign intrinsics. Assume 8-bit byte.696 shortenAssignment(DeadI, OrigDest, DeadStart * 8, DeadSize * 8, NewSize * 8,697 IsOverwriteEnd);698 699 // Finally update start and size of dead access.700 if (!IsOverwriteEnd)701 DeadStart += ToRemoveSize;702 DeadSize = NewSize;703 704 return true;705}706 707static bool tryToShortenEnd(Instruction *DeadI, OverlapIntervalsTy &IntervalMap,708 int64_t &DeadStart, uint64_t &DeadSize) {709 if (IntervalMap.empty() || !isShortenableAtTheEnd(DeadI))710 return false;711 712 OverlapIntervalsTy::iterator OII = --IntervalMap.end();713 int64_t KillingStart = OII->second;714 uint64_t KillingSize = OII->first - KillingStart;715 716 assert(OII->first - KillingStart >= 0 && "Size expected to be positive");717 718 if (KillingStart > DeadStart &&719 // Note: "KillingStart - KillingStart" is known to be positive due to720 // preceding check.721 (uint64_t)(KillingStart - DeadStart) < DeadSize &&722 // Note: "DeadSize - (uint64_t)(KillingStart - DeadStart)" is known to723 // be non negative due to preceding checks.724 KillingSize >= DeadSize - (uint64_t)(KillingStart - DeadStart)) {725 if (tryToShorten(DeadI, DeadStart, DeadSize, KillingStart, KillingSize,726 true)) {727 IntervalMap.erase(OII);728 return true;729 }730 }731 return false;732}733 734static bool tryToShortenBegin(Instruction *DeadI,735 OverlapIntervalsTy &IntervalMap,736 int64_t &DeadStart, uint64_t &DeadSize) {737 if (IntervalMap.empty() || !isShortenableAtTheBeginning(DeadI))738 return false;739 740 OverlapIntervalsTy::iterator OII = IntervalMap.begin();741 int64_t KillingStart = OII->second;742 uint64_t KillingSize = OII->first - KillingStart;743 744 assert(OII->first - KillingStart >= 0 && "Size expected to be positive");745 746 if (KillingStart <= DeadStart &&747 // Note: "DeadStart - KillingStart" is known to be non negative due to748 // preceding check.749 KillingSize > (uint64_t)(DeadStart - KillingStart)) {750 // Note: "KillingSize - (uint64_t)(DeadStart - DeadStart)" is known to751 // be positive due to preceding checks.752 assert(KillingSize - (uint64_t)(DeadStart - KillingStart) < DeadSize &&753 "Should have been handled as OW_Complete");754 if (tryToShorten(DeadI, DeadStart, DeadSize, KillingStart, KillingSize,755 false)) {756 IntervalMap.erase(OII);757 return true;758 }759 }760 return false;761}762 763static Constant *764tryToMergePartialOverlappingStores(StoreInst *KillingI, StoreInst *DeadI,765 int64_t KillingOffset, int64_t DeadOffset,766 const DataLayout &DL, BatchAAResults &AA,767 DominatorTree *DT) {768 769 if (DeadI && isa<ConstantInt>(DeadI->getValueOperand()) &&770 DL.typeSizeEqualsStoreSize(DeadI->getValueOperand()->getType()) &&771 KillingI && isa<ConstantInt>(KillingI->getValueOperand()) &&772 DL.typeSizeEqualsStoreSize(KillingI->getValueOperand()->getType()) &&773 memoryIsNotModifiedBetween(DeadI, KillingI, AA, DL, DT)) {774 // If the store we find is:775 // a) partially overwritten by the store to 'Loc'776 // b) the killing store is fully contained in the dead one and777 // c) they both have a constant value778 // d) none of the two stores need padding779 // Merge the two stores, replacing the dead store's value with a780 // merge of both values.781 // TODO: Deal with other constant types (vectors, etc), and probably782 // some mem intrinsics (if needed)783 784 APInt DeadValue = cast<ConstantInt>(DeadI->getValueOperand())->getValue();785 APInt KillingValue =786 cast<ConstantInt>(KillingI->getValueOperand())->getValue();787 unsigned KillingBits = KillingValue.getBitWidth();788 assert(DeadValue.getBitWidth() > KillingValue.getBitWidth());789 KillingValue = KillingValue.zext(DeadValue.getBitWidth());790 791 // Offset of the smaller store inside the larger store792 unsigned BitOffsetDiff = (KillingOffset - DeadOffset) * 8;793 unsigned LShiftAmount =794 DL.isBigEndian() ? DeadValue.getBitWidth() - BitOffsetDiff - KillingBits795 : BitOffsetDiff;796 APInt Mask = APInt::getBitsSet(DeadValue.getBitWidth(), LShiftAmount,797 LShiftAmount + KillingBits);798 // Clear the bits we'll be replacing, then OR with the smaller799 // store, shifted appropriately.800 APInt Merged = (DeadValue & ~Mask) | (KillingValue << LShiftAmount);801 LLVM_DEBUG(dbgs() << "DSE: Merge Stores:\n Dead: " << *DeadI802 << "\n Killing: " << *KillingI803 << "\n Merged Value: " << Merged << '\n');804 return ConstantInt::get(DeadI->getValueOperand()->getType(), Merged);805 }806 return nullptr;807}808 809// Returns true if \p I is an intrinsic that does not read or write memory.810static bool isNoopIntrinsic(Instruction *I) {811 if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {812 switch (II->getIntrinsicID()) {813 case Intrinsic::lifetime_start:814 case Intrinsic::lifetime_end:815 case Intrinsic::invariant_end:816 case Intrinsic::launder_invariant_group:817 case Intrinsic::assume:818 return true;819 case Intrinsic::dbg_declare:820 case Intrinsic::dbg_label:821 case Intrinsic::dbg_value:822 llvm_unreachable("Intrinsic should not be modeled in MemorySSA");823 default:824 return false;825 }826 }827 return false;828}829 830// Check if we can ignore \p D for DSE.831static bool canSkipDef(MemoryDef *D, bool DefVisibleToCaller) {832 Instruction *DI = D->getMemoryInst();833 // Calls that only access inaccessible memory cannot read or write any memory834 // locations we consider for elimination.835 if (auto *CB = dyn_cast<CallBase>(DI))836 if (CB->onlyAccessesInaccessibleMemory())837 return true;838 839 // We can eliminate stores to locations not visible to the caller across840 // throwing instructions.841 if (DI->mayThrow() && !DefVisibleToCaller)842 return true;843 844 // We can remove the dead stores, irrespective of the fence and its ordering845 // (release/acquire/seq_cst). Fences only constraints the ordering of846 // already visible stores, it does not make a store visible to other847 // threads. So, skipping over a fence does not change a store from being848 // dead.849 if (isa<FenceInst>(DI))850 return true;851 852 // Skip intrinsics that do not really read or modify memory.853 if (isNoopIntrinsic(DI))854 return true;855 856 return false;857}858 859namespace {860 861// A memory location wrapper that represents a MemoryLocation, `MemLoc`,862// defined by `MemDef`.863struct MemoryLocationWrapper {864 MemoryLocationWrapper(MemoryLocation MemLoc, MemoryDef *MemDef,865 bool DefByInitializesAttr)866 : MemLoc(MemLoc), MemDef(MemDef),867 DefByInitializesAttr(DefByInitializesAttr) {868 assert(MemLoc.Ptr && "MemLoc should be not null");869 UnderlyingObject = getUnderlyingObject(MemLoc.Ptr);870 DefInst = MemDef->getMemoryInst();871 }872 873 MemoryLocation MemLoc;874 const Value *UnderlyingObject;875 MemoryDef *MemDef;876 Instruction *DefInst;877 bool DefByInitializesAttr = false;878};879 880// A memory def wrapper that represents a MemoryDef and the MemoryLocation(s)881// defined by this MemoryDef.882struct MemoryDefWrapper {883 MemoryDefWrapper(MemoryDef *MemDef,884 ArrayRef<std::pair<MemoryLocation, bool>> MemLocations) {885 DefInst = MemDef->getMemoryInst();886 for (auto &[MemLoc, DefByInitializesAttr] : MemLocations)887 DefinedLocations.push_back(888 MemoryLocationWrapper(MemLoc, MemDef, DefByInitializesAttr));889 }890 Instruction *DefInst;891 SmallVector<MemoryLocationWrapper, 1> DefinedLocations;892};893 894struct ArgumentInitInfo {895 unsigned Idx;896 bool IsDeadOrInvisibleOnUnwind;897 ConstantRangeList Inits;898};899} // namespace900 901static bool hasInitializesAttr(Instruction *I) {902 CallBase *CB = dyn_cast<CallBase>(I);903 return CB && CB->getArgOperandWithAttribute(Attribute::Initializes);904}905 906// Return the intersected range list of the initializes attributes of "Args".907// "Args" are call arguments that alias to each other.908// If any argument in "Args" doesn't have dead_on_unwind attr and909// "CallHasNoUnwindAttr" is false, return empty.910static ConstantRangeList911getIntersectedInitRangeList(ArrayRef<ArgumentInitInfo> Args,912 bool CallHasNoUnwindAttr) {913 if (Args.empty())914 return {};915 916 // To address unwind, the function should have nounwind attribute or the917 // arguments have dead or invisible on unwind. Otherwise, return empty.918 for (const auto &Arg : Args) {919 if (!CallHasNoUnwindAttr && !Arg.IsDeadOrInvisibleOnUnwind)920 return {};921 if (Arg.Inits.empty())922 return {};923 }924 925 ConstantRangeList IntersectedIntervals = Args.front().Inits;926 for (auto &Arg : Args.drop_front())927 IntersectedIntervals = IntersectedIntervals.intersectWith(Arg.Inits);928 929 return IntersectedIntervals;930}931 932namespace {933 934struct DSEState {935 Function &F;936 AliasAnalysis &AA;937 EarliestEscapeAnalysis EA;938 939 /// The single BatchAA instance that is used to cache AA queries. It will940 /// not be invalidated over the whole run. This is safe, because:941 /// 1. Only memory writes are removed, so the alias cache for memory942 /// locations remains valid.943 /// 2. No new instructions are added (only instructions removed), so cached944 /// information for a deleted value cannot be accessed by a re-used new945 /// value pointer.946 BatchAAResults BatchAA;947 948 MemorySSA &MSSA;949 DominatorTree &DT;950 PostDominatorTree &PDT;951 const TargetLibraryInfo &TLI;952 const DataLayout &DL;953 const LoopInfo &LI;954 955 // Whether the function contains any irreducible control flow, useful for956 // being accurately able to detect loops.957 bool ContainsIrreducibleLoops;958 959 // All MemoryDefs that potentially could kill other MemDefs.960 SmallVector<MemoryDef *, 64> MemDefs;961 // Any that should be skipped as they are already deleted962 SmallPtrSet<MemoryAccess *, 4> SkipStores;963 // Keep track whether a given object is captured before return or not.964 DenseMap<const Value *, bool> CapturedBeforeReturn;965 // Keep track of all of the objects that are invisible to the caller after966 // the function returns.967 DenseMap<const Value *, bool> InvisibleToCallerAfterRet;968 // Keep track of blocks with throwing instructions not modeled in MemorySSA.969 SmallPtrSet<BasicBlock *, 16> ThrowingBlocks;970 // Post-order numbers for each basic block. Used to figure out if memory971 // accesses are executed before another access.972 DenseMap<BasicBlock *, unsigned> PostOrderNumbers;973 974 /// Keep track of instructions (partly) overlapping with killing MemoryDefs per975 /// basic block.976 MapVector<BasicBlock *, InstOverlapIntervalsTy> IOLs;977 // Check if there are root nodes that are terminated by UnreachableInst.978 // Those roots pessimize post-dominance queries. If there are such roots,979 // fall back to CFG scan starting from all non-unreachable roots.980 bool AnyUnreachableExit;981 982 // Whether or not we should iterate on removing dead stores at the end of the983 // function due to removing a store causing a previously captured pointer to984 // no longer be captured.985 bool ShouldIterateEndOfFunctionDSE;986 987 /// Dead instructions to be removed at the end of DSE.988 SmallVector<Instruction *> ToRemove;989 990 // Class contains self-reference, make sure it's not copied/moved.991 DSEState(const DSEState &) = delete;992 DSEState &operator=(const DSEState &) = delete;993 994 DSEState(Function &F, AliasAnalysis &AA, MemorySSA &MSSA, DominatorTree &DT,995 PostDominatorTree &PDT, const TargetLibraryInfo &TLI,996 const LoopInfo &LI)997 : F(F), AA(AA), EA(DT, &LI), BatchAA(AA, &EA), MSSA(MSSA), DT(DT),998 PDT(PDT), TLI(TLI), DL(F.getDataLayout()), LI(LI) {999 // Collect blocks with throwing instructions not modeled in MemorySSA and1000 // alloc-like objects.1001 unsigned PO = 0;1002 for (BasicBlock *BB : post_order(&F)) {1003 PostOrderNumbers[BB] = PO++;1004 for (Instruction &I : *BB) {1005 MemoryAccess *MA = MSSA.getMemoryAccess(&I);1006 if (I.mayThrow() && !MA)1007 ThrowingBlocks.insert(I.getParent());1008 1009 auto *MD = dyn_cast_or_null<MemoryDef>(MA);1010 if (MD && MemDefs.size() < MemorySSADefsPerBlockLimit &&1011 (getLocForWrite(&I) || isMemTerminatorInst(&I) ||1012 (EnableInitializesImprovement && hasInitializesAttr(&I))))1013 MemDefs.push_back(MD);1014 }1015 }1016 1017 // Treat byval, inalloca or dead on return arguments the same as Allocas,1018 // stores to them are dead at the end of the function.1019 for (Argument &AI : F.args())1020 if (AI.hasPassPointeeByValueCopyAttr() || AI.hasDeadOnReturnAttr())1021 InvisibleToCallerAfterRet.insert({&AI, true});1022 1023 // Collect whether there is any irreducible control flow in the function.1024 ContainsIrreducibleLoops = mayContainIrreducibleControl(F, &LI);1025 1026 AnyUnreachableExit = any_of(PDT.roots(), [](const BasicBlock *E) {1027 return isa<UnreachableInst>(E->getTerminator());1028 });1029 }1030 1031 static void pushMemUses(MemoryAccess *Acc,1032 SmallVectorImpl<MemoryAccess *> &WorkList,1033 SmallPtrSetImpl<MemoryAccess *> &Visited) {1034 for (Use &U : Acc->uses()) {1035 auto *MA = cast<MemoryAccess>(U.getUser());1036 if (Visited.insert(MA).second)1037 WorkList.push_back(MA);1038 }1039 };1040 1041 LocationSize strengthenLocationSize(const Instruction *I,1042 LocationSize Size) const {1043 if (auto *CB = dyn_cast<CallBase>(I)) {1044 LibFunc F;1045 if (TLI.getLibFunc(*CB, F) && TLI.has(F) &&1046 (F == LibFunc_memset_chk || F == LibFunc_memcpy_chk)) {1047 // Use the precise location size specified by the 3rd argument1048 // for determining KillingI overwrites DeadLoc if it is a memset_chk1049 // instruction. memset_chk will write either the amount specified as 3rd1050 // argument or the function will immediately abort and exit the program.1051 // NOTE: AA may determine NoAlias if it can prove that the access size1052 // is larger than the allocation size due to that being UB. To avoid1053 // returning potentially invalid NoAlias results by AA, limit the use of1054 // the precise location size to isOverwrite.1055 if (const auto *Len = dyn_cast<ConstantInt>(CB->getArgOperand(2)))1056 return LocationSize::precise(Len->getZExtValue());1057 }1058 }1059 return Size;1060 }1061 1062 /// Return 'OW_Complete' if a store to the 'KillingLoc' location (by \p1063 /// KillingI instruction) completely overwrites a store to the 'DeadLoc'1064 /// location (by \p DeadI instruction).1065 /// Return OW_MaybePartial if \p KillingI does not completely overwrite1066 /// \p DeadI, but they both write to the same underlying object. In that1067 /// case, use isPartialOverwrite to check if \p KillingI partially overwrites1068 /// \p DeadI. Returns 'OR_None' if \p KillingI is known to not overwrite the1069 /// \p DeadI. Returns 'OW_Unknown' if nothing can be determined.1070 OverwriteResult isOverwrite(const Instruction *KillingI,1071 const Instruction *DeadI,1072 const MemoryLocation &KillingLoc,1073 const MemoryLocation &DeadLoc,1074 int64_t &KillingOff, int64_t &DeadOff) {1075 // AliasAnalysis does not always account for loops. Limit overwrite checks1076 // to dependencies for which we can guarantee they are independent of any1077 // loops they are in.1078 if (!isGuaranteedLoopIndependent(DeadI, KillingI, DeadLoc))1079 return OW_Unknown;1080 1081 LocationSize KillingLocSize =1082 strengthenLocationSize(KillingI, KillingLoc.Size);1083 const Value *DeadPtr = DeadLoc.Ptr->stripPointerCasts();1084 const Value *KillingPtr = KillingLoc.Ptr->stripPointerCasts();1085 const Value *DeadUndObj = getUnderlyingObject(DeadPtr);1086 const Value *KillingUndObj = getUnderlyingObject(KillingPtr);1087 1088 // Check whether the killing store overwrites the whole object, in which1089 // case the size/offset of the dead store does not matter.1090 if (DeadUndObj == KillingUndObj && KillingLocSize.isPrecise() &&1091 isIdentifiedObject(KillingUndObj)) {1092 std::optional<TypeSize> KillingUndObjSize =1093 getPointerSize(KillingUndObj, DL, TLI, &F);1094 if (KillingUndObjSize && *KillingUndObjSize == KillingLocSize.getValue())1095 return OW_Complete;1096 }1097 1098 // FIXME: Vet that this works for size upper-bounds. Seems unlikely that we'll1099 // get imprecise values here, though (except for unknown sizes).1100 if (!KillingLocSize.isPrecise() || !DeadLoc.Size.isPrecise()) {1101 // In case no constant size is known, try to an IR values for the number1102 // of bytes written and check if they match.1103 const auto *KillingMemI = dyn_cast<MemIntrinsic>(KillingI);1104 const auto *DeadMemI = dyn_cast<MemIntrinsic>(DeadI);1105 if (KillingMemI && DeadMemI) {1106 const Value *KillingV = KillingMemI->getLength();1107 const Value *DeadV = DeadMemI->getLength();1108 if (KillingV == DeadV && BatchAA.isMustAlias(DeadLoc, KillingLoc))1109 return OW_Complete;1110 }1111 1112 // Masked stores have imprecise locations, but we can reason about them1113 // to some extent.1114 return isMaskedStoreOverwrite(KillingI, DeadI, BatchAA);1115 }1116 1117 const TypeSize KillingSize = KillingLocSize.getValue();1118 const TypeSize DeadSize = DeadLoc.Size.getValue();1119 // Bail on doing Size comparison which depends on AA for now1120 // TODO: Remove AnyScalable once Alias Analysis deal with scalable vectors1121 const bool AnyScalable =1122 DeadSize.isScalable() || KillingLocSize.isScalable();1123 1124 if (AnyScalable)1125 return OW_Unknown;1126 // Query the alias information1127 AliasResult AAR = BatchAA.alias(KillingLoc, DeadLoc);1128 1129 // If the start pointers are the same, we just have to compare sizes to see if1130 // the killing store was larger than the dead store.1131 if (AAR == AliasResult::MustAlias) {1132 // Make sure that the KillingSize size is >= the DeadSize size.1133 if (KillingSize >= DeadSize)1134 return OW_Complete;1135 }1136 1137 // If we hit a partial alias we may have a full overwrite1138 if (AAR == AliasResult::PartialAlias && AAR.hasOffset()) {1139 int32_t Off = AAR.getOffset();1140 if (Off >= 0 && (uint64_t)Off + DeadSize <= KillingSize)1141 return OW_Complete;1142 }1143 1144 // If we can't resolve the same pointers to the same object, then we can't1145 // analyze them at all.1146 if (DeadUndObj != KillingUndObj) {1147 // Non aliasing stores to different objects don't overlap. Note that1148 // if the killing store is known to overwrite whole object (out of1149 // bounds access overwrites whole object as well) then it is assumed to1150 // completely overwrite any store to the same object even if they don't1151 // actually alias (see next check).1152 if (AAR == AliasResult::NoAlias)1153 return OW_None;1154 return OW_Unknown;1155 }1156 1157 // Okay, we have stores to two completely different pointers. Try to1158 // decompose the pointer into a "base + constant_offset" form. If the base1159 // pointers are equal, then we can reason about the two stores.1160 DeadOff = 0;1161 KillingOff = 0;1162 const Value *DeadBasePtr =1163 GetPointerBaseWithConstantOffset(DeadPtr, DeadOff, DL);1164 const Value *KillingBasePtr =1165 GetPointerBaseWithConstantOffset(KillingPtr, KillingOff, DL);1166 1167 // If the base pointers still differ, we have two completely different1168 // stores.1169 if (DeadBasePtr != KillingBasePtr)1170 return OW_Unknown;1171 1172 // The killing access completely overlaps the dead store if and only if1173 // both start and end of the dead one is "inside" the killing one:1174 // |<->|--dead--|<->|1175 // |-----killing------|1176 // Accesses may overlap if and only if start of one of them is "inside"1177 // another one:1178 // |<->|--dead--|<-------->|1179 // |-------killing--------|1180 // OR1181 // |-------dead-------|1182 // |<->|---killing---|<----->|1183 //1184 // We have to be careful here as *Off is signed while *.Size is unsigned.1185 1186 // Check if the dead access starts "not before" the killing one.1187 if (DeadOff >= KillingOff) {1188 // If the dead access ends "not after" the killing access then the1189 // dead one is completely overwritten by the killing one.1190 if (uint64_t(DeadOff - KillingOff) + DeadSize <= KillingSize)1191 return OW_Complete;1192 // If start of the dead access is "before" end of the killing access1193 // then accesses overlap.1194 else if ((uint64_t)(DeadOff - KillingOff) < KillingSize)1195 return OW_MaybePartial;1196 }1197 // If start of the killing access is "before" end of the dead access then1198 // accesses overlap.1199 else if ((uint64_t)(KillingOff - DeadOff) < DeadSize) {1200 return OW_MaybePartial;1201 }1202 1203 // Can reach here only if accesses are known not to overlap.1204 return OW_None;1205 }1206 1207 bool isInvisibleToCallerAfterRet(const Value *V) {1208 if (isa<AllocaInst>(V))1209 return true;1210 1211 auto I = InvisibleToCallerAfterRet.insert({V, false});1212 if (I.second && isInvisibleToCallerOnUnwind(V) && isNoAliasCall(V))1213 I.first->second = capturesNothing(PointerMayBeCaptured(1214 V, /*ReturnCaptures=*/true, CaptureComponents::Provenance));1215 return I.first->second;1216 }1217 1218 bool isInvisibleToCallerOnUnwind(const Value *V) {1219 bool RequiresNoCaptureBeforeUnwind;1220 if (!isNotVisibleOnUnwind(V, RequiresNoCaptureBeforeUnwind))1221 return false;1222 if (!RequiresNoCaptureBeforeUnwind)1223 return true;1224 1225 auto I = CapturedBeforeReturn.insert({V, true});1226 if (I.second)1227 // NOTE: This could be made more precise by PointerMayBeCapturedBefore1228 // with the killing MemoryDef. But we refrain from doing so for now to1229 // limit compile-time and this does not cause any changes to the number1230 // of stores removed on a large test set in practice.1231 I.first->second = capturesAnything(PointerMayBeCaptured(1232 V, /*ReturnCaptures=*/false, CaptureComponents::Provenance));1233 return !I.first->second;1234 }1235 1236 std::optional<MemoryLocation> getLocForWrite(Instruction *I) const {1237 if (!I->mayWriteToMemory())1238 return std::nullopt;1239 1240 if (auto *CB = dyn_cast<CallBase>(I))1241 return MemoryLocation::getForDest(CB, TLI);1242 1243 return MemoryLocation::getOrNone(I);1244 }1245 1246 // Returns a list of <MemoryLocation, bool> pairs written by I.1247 // The bool means whether the write is from Initializes attr.1248 SmallVector<std::pair<MemoryLocation, bool>, 1>1249 getLocForInst(Instruction *I, bool ConsiderInitializesAttr) {1250 SmallVector<std::pair<MemoryLocation, bool>, 1> Locations;1251 if (isMemTerminatorInst(I)) {1252 if (auto Loc = getLocForTerminator(I))1253 Locations.push_back(std::make_pair(Loc->first, false));1254 return Locations;1255 }1256 1257 if (auto Loc = getLocForWrite(I))1258 Locations.push_back(std::make_pair(*Loc, false));1259 1260 if (ConsiderInitializesAttr) {1261 for (auto &MemLoc : getInitializesArgMemLoc(I)) {1262 Locations.push_back(std::make_pair(MemLoc, true));1263 }1264 }1265 return Locations;1266 }1267 1268 /// Assuming this instruction has a dead analyzable write, can we delete1269 /// this instruction?1270 bool isRemovable(Instruction *I) {1271 assert(getLocForWrite(I) && "Must have analyzable write");1272 1273 // Don't remove volatile/atomic stores.1274 if (StoreInst *SI = dyn_cast<StoreInst>(I))1275 return SI->isUnordered();1276 1277 if (auto *CB = dyn_cast<CallBase>(I)) {1278 // Don't remove volatile memory intrinsics.1279 if (auto *MI = dyn_cast<MemIntrinsic>(CB))1280 return !MI->isVolatile();1281 1282 // Never remove dead lifetime intrinsics, e.g. because they are followed1283 // by a free.1284 if (CB->isLifetimeStartOrEnd())1285 return false;1286 1287 return CB->use_empty() && CB->willReturn() && CB->doesNotThrow() &&1288 !CB->isTerminator();1289 }1290 1291 return false;1292 }1293 1294 /// Returns true if \p UseInst completely overwrites \p DefLoc1295 /// (stored by \p DefInst).1296 bool isCompleteOverwrite(const MemoryLocation &DefLoc, Instruction *DefInst,1297 Instruction *UseInst) {1298 // UseInst has a MemoryDef associated in MemorySSA. It's possible for a1299 // MemoryDef to not write to memory, e.g. a volatile load is modeled as a1300 // MemoryDef.1301 if (!UseInst->mayWriteToMemory())1302 return false;1303 1304 if (auto *CB = dyn_cast<CallBase>(UseInst))1305 if (CB->onlyAccessesInaccessibleMemory())1306 return false;1307 1308 int64_t InstWriteOffset, DepWriteOffset;1309 if (auto CC = getLocForWrite(UseInst))1310 return isOverwrite(UseInst, DefInst, *CC, DefLoc, InstWriteOffset,1311 DepWriteOffset) == OW_Complete;1312 return false;1313 }1314 1315 /// Returns true if \p Def is not read before returning from the function.1316 bool isWriteAtEndOfFunction(MemoryDef *Def, const MemoryLocation &DefLoc) {1317 LLVM_DEBUG(dbgs() << " Check if def " << *Def << " ("1318 << *Def->getMemoryInst()1319 << ") is at the end the function \n");1320 SmallVector<MemoryAccess *, 4> WorkList;1321 SmallPtrSet<MemoryAccess *, 8> Visited;1322 1323 pushMemUses(Def, WorkList, Visited);1324 for (unsigned I = 0; I < WorkList.size(); I++) {1325 if (WorkList.size() >= MemorySSAScanLimit) {1326 LLVM_DEBUG(dbgs() << " ... hit exploration limit.\n");1327 return false;1328 }1329 1330 MemoryAccess *UseAccess = WorkList[I];1331 if (isa<MemoryPhi>(UseAccess)) {1332 // AliasAnalysis does not account for loops. Limit elimination to1333 // candidates for which we can guarantee they always store to the same1334 // memory location.1335 if (!isGuaranteedLoopInvariant(DefLoc.Ptr))1336 return false;1337 1338 pushMemUses(cast<MemoryPhi>(UseAccess), WorkList, Visited);1339 continue;1340 }1341 // TODO: Checking for aliasing is expensive. Consider reducing the amount1342 // of times this is called and/or caching it.1343 Instruction *UseInst = cast<MemoryUseOrDef>(UseAccess)->getMemoryInst();1344 if (isReadClobber(DefLoc, UseInst)) {1345 LLVM_DEBUG(dbgs() << " ... hit read clobber " << *UseInst << ".\n");1346 return false;1347 }1348 1349 if (MemoryDef *UseDef = dyn_cast<MemoryDef>(UseAccess))1350 pushMemUses(UseDef, WorkList, Visited);1351 }1352 return true;1353 }1354 1355 /// If \p I is a memory terminator like llvm.lifetime.end or free, return a1356 /// pair with the MemoryLocation terminated by \p I and a boolean flag1357 /// indicating whether \p I is a free-like call.1358 std::optional<std::pair<MemoryLocation, bool>>1359 getLocForTerminator(Instruction *I) const {1360 if (auto *CB = dyn_cast<CallBase>(I)) {1361 if (CB->getIntrinsicID() == Intrinsic::lifetime_end)1362 return {1363 std::make_pair(MemoryLocation::getForArgument(CB, 0, &TLI), false)};1364 if (Value *FreedOp = getFreedOperand(CB, &TLI))1365 return {std::make_pair(MemoryLocation::getAfter(FreedOp), true)};1366 }1367 1368 return std::nullopt;1369 }1370 1371 /// Returns true if \p I is a memory terminator instruction like1372 /// llvm.lifetime.end or free.1373 bool isMemTerminatorInst(Instruction *I) const {1374 auto *CB = dyn_cast<CallBase>(I);1375 return CB && (CB->getIntrinsicID() == Intrinsic::lifetime_end ||1376 getFreedOperand(CB, &TLI) != nullptr);1377 }1378 1379 /// Returns true if \p MaybeTerm is a memory terminator for \p Loc from1380 /// instruction \p AccessI.1381 bool isMemTerminator(const MemoryLocation &Loc, Instruction *AccessI,1382 Instruction *MaybeTerm) {1383 std::optional<std::pair<MemoryLocation, bool>> MaybeTermLoc =1384 getLocForTerminator(MaybeTerm);1385 1386 if (!MaybeTermLoc)1387 return false;1388 1389 // If the terminator is a free-like call, all accesses to the underlying1390 // object can be considered terminated.1391 if (getUnderlyingObject(Loc.Ptr) !=1392 getUnderlyingObject(MaybeTermLoc->first.Ptr))1393 return false;1394 1395 auto TermLoc = MaybeTermLoc->first;1396 if (MaybeTermLoc->second) {1397 const Value *LocUO = getUnderlyingObject(Loc.Ptr);1398 return BatchAA.isMustAlias(TermLoc.Ptr, LocUO);1399 }1400 int64_t InstWriteOffset = 0;1401 int64_t DepWriteOffset = 0;1402 return isOverwrite(MaybeTerm, AccessI, TermLoc, Loc, InstWriteOffset,1403 DepWriteOffset) == OW_Complete;1404 }1405 1406 // Returns true if \p Use may read from \p DefLoc.1407 bool isReadClobber(const MemoryLocation &DefLoc, Instruction *UseInst) {1408 if (isNoopIntrinsic(UseInst))1409 return false;1410 1411 // Monotonic or weaker atomic stores can be re-ordered and do not need to be1412 // treated as read clobber.1413 if (auto SI = dyn_cast<StoreInst>(UseInst))1414 return isStrongerThan(SI->getOrdering(), AtomicOrdering::Monotonic);1415 1416 if (!UseInst->mayReadFromMemory())1417 return false;1418 1419 if (auto *CB = dyn_cast<CallBase>(UseInst))1420 if (CB->onlyAccessesInaccessibleMemory())1421 return false;1422 1423 return isRefSet(BatchAA.getModRefInfo(UseInst, DefLoc));1424 }1425 1426 /// Returns true if a dependency between \p Current and \p KillingDef is1427 /// guaranteed to be loop invariant for the loops that they are in. Either1428 /// because they are known to be in the same block, in the same loop level or1429 /// by guaranteeing that \p CurrentLoc only references a single MemoryLocation1430 /// during execution of the containing function.1431 bool isGuaranteedLoopIndependent(const Instruction *Current,1432 const Instruction *KillingDef,1433 const MemoryLocation &CurrentLoc) {1434 // If the dependency is within the same block or loop level (being careful1435 // of irreducible loops), we know that AA will return a valid result for the1436 // memory dependency. (Both at the function level, outside of any loop,1437 // would also be valid but we currently disable that to limit compile time).1438 if (Current->getParent() == KillingDef->getParent())1439 return true;1440 const Loop *CurrentLI = LI.getLoopFor(Current->getParent());1441 if (!ContainsIrreducibleLoops && CurrentLI &&1442 CurrentLI == LI.getLoopFor(KillingDef->getParent()))1443 return true;1444 // Otherwise check the memory location is invariant to any loops.1445 return isGuaranteedLoopInvariant(CurrentLoc.Ptr);1446 }1447 1448 /// Returns true if \p Ptr is guaranteed to be loop invariant for any possible1449 /// loop. In particular, this guarantees that it only references a single1450 /// MemoryLocation during execution of the containing function.1451 bool isGuaranteedLoopInvariant(const Value *Ptr) {1452 Ptr = Ptr->stripPointerCasts();1453 if (auto *GEP = dyn_cast<GEPOperator>(Ptr))1454 if (GEP->hasAllConstantIndices())1455 Ptr = GEP->getPointerOperand()->stripPointerCasts();1456 1457 if (auto *I = dyn_cast<Instruction>(Ptr)) {1458 return I->getParent()->isEntryBlock() ||1459 (!ContainsIrreducibleLoops && !LI.getLoopFor(I->getParent()));1460 }1461 return true;1462 }1463 1464 // Find a MemoryDef writing to \p KillingLoc and dominating \p StartAccess,1465 // with no read access between them or on any other path to a function exit1466 // block if \p KillingLoc is not accessible after the function returns. If1467 // there is no such MemoryDef, return std::nullopt. The returned value may not1468 // (completely) overwrite \p KillingLoc. Currently we bail out when we1469 // encounter an aliasing MemoryUse (read).1470 std::optional<MemoryAccess *>1471 getDomMemoryDef(MemoryDef *KillingDef, MemoryAccess *StartAccess,1472 const MemoryLocation &KillingLoc, const Value *KillingUndObj,1473 unsigned &ScanLimit, unsigned &WalkerStepLimit,1474 bool IsMemTerm, unsigned &PartialLimit,1475 bool IsInitializesAttrMemLoc) {1476 if (ScanLimit == 0 || WalkerStepLimit == 0) {1477 LLVM_DEBUG(dbgs() << "\n ... hit scan limit\n");1478 return std::nullopt;1479 }1480 1481 MemoryAccess *Current = StartAccess;1482 Instruction *KillingI = KillingDef->getMemoryInst();1483 LLVM_DEBUG(dbgs() << " trying to get dominating access\n");1484 1485 // Only optimize defining access of KillingDef when directly starting at its1486 // defining access. The defining access also must only access KillingLoc. At1487 // the moment we only support instructions with a single write location, so1488 // it should be sufficient to disable optimizations for instructions that1489 // also read from memory.1490 bool CanOptimize = OptimizeMemorySSA &&1491 KillingDef->getDefiningAccess() == StartAccess &&1492 !KillingI->mayReadFromMemory();1493 1494 // Find the next clobbering Mod access for DefLoc, starting at StartAccess.1495 std::optional<MemoryLocation> CurrentLoc;1496 for (;; Current = cast<MemoryDef>(Current)->getDefiningAccess()) {1497 LLVM_DEBUG({1498 dbgs() << " visiting " << *Current;1499 if (!MSSA.isLiveOnEntryDef(Current) && isa<MemoryUseOrDef>(Current))1500 dbgs() << " (" << *cast<MemoryUseOrDef>(Current)->getMemoryInst()1501 << ")";1502 dbgs() << "\n";1503 });1504 1505 // Reached TOP.1506 if (MSSA.isLiveOnEntryDef(Current)) {1507 LLVM_DEBUG(dbgs() << " ... found LiveOnEntryDef\n");1508 if (CanOptimize && Current != KillingDef->getDefiningAccess())1509 // The first clobbering def is... none.1510 KillingDef->setOptimized(Current);1511 return std::nullopt;1512 }1513 1514 // Cost of a step. Accesses in the same block are more likely to be valid1515 // candidates for elimination, hence consider them cheaper.1516 unsigned StepCost = KillingDef->getBlock() == Current->getBlock()1517 ? MemorySSASameBBStepCost1518 : MemorySSAOtherBBStepCost;1519 if (WalkerStepLimit <= StepCost) {1520 LLVM_DEBUG(dbgs() << " ... hit walker step limit\n");1521 return std::nullopt;1522 }1523 WalkerStepLimit -= StepCost;1524 1525 // Return for MemoryPhis. They cannot be eliminated directly and the1526 // caller is responsible for traversing them.1527 if (isa<MemoryPhi>(Current)) {1528 LLVM_DEBUG(dbgs() << " ... found MemoryPhi\n");1529 return Current;1530 }1531 1532 // Below, check if CurrentDef is a valid candidate to be eliminated by1533 // KillingDef. If it is not, check the next candidate.1534 MemoryDef *CurrentDef = cast<MemoryDef>(Current);1535 Instruction *CurrentI = CurrentDef->getMemoryInst();1536 1537 if (canSkipDef(CurrentDef, !isInvisibleToCallerOnUnwind(KillingUndObj))) {1538 CanOptimize = false;1539 continue;1540 }1541 1542 // Before we try to remove anything, check for any extra throwing1543 // instructions that block us from DSEing1544 if (mayThrowBetween(KillingI, CurrentI, KillingUndObj)) {1545 LLVM_DEBUG(dbgs() << " ... skip, may throw!\n");1546 return std::nullopt;1547 }1548 1549 // Check for anything that looks like it will be a barrier to further1550 // removal1551 if (isDSEBarrier(KillingUndObj, CurrentI)) {1552 LLVM_DEBUG(dbgs() << " ... skip, barrier\n");1553 return std::nullopt;1554 }1555 1556 // If Current is known to be on path that reads DefLoc or is a read1557 // clobber, bail out, as the path is not profitable. We skip this check1558 // for intrinsic calls, because the code knows how to handle memcpy1559 // intrinsics.1560 if (!isa<IntrinsicInst>(CurrentI) && isReadClobber(KillingLoc, CurrentI))1561 return std::nullopt;1562 1563 // Quick check if there are direct uses that are read-clobbers.1564 if (any_of(Current->uses(), [this, &KillingLoc, StartAccess](Use &U) {1565 if (auto *UseOrDef = dyn_cast<MemoryUseOrDef>(U.getUser()))1566 return !MSSA.dominates(StartAccess, UseOrDef) &&1567 isReadClobber(KillingLoc, UseOrDef->getMemoryInst());1568 return false;1569 })) {1570 LLVM_DEBUG(dbgs() << " ... found a read clobber\n");1571 return std::nullopt;1572 }1573 1574 // If Current does not have an analyzable write location or is not1575 // removable, skip it.1576 CurrentLoc = getLocForWrite(CurrentI);1577 if (!CurrentLoc || !isRemovable(CurrentI)) {1578 CanOptimize = false;1579 continue;1580 }1581 1582 // AliasAnalysis does not account for loops. Limit elimination to1583 // candidates for which we can guarantee they always store to the same1584 // memory location and not located in different loops.1585 if (!isGuaranteedLoopIndependent(CurrentI, KillingI, *CurrentLoc)) {1586 LLVM_DEBUG(dbgs() << " ... not guaranteed loop independent\n");1587 CanOptimize = false;1588 continue;1589 }1590 1591 if (IsMemTerm) {1592 // If the killing def is a memory terminator (e.g. lifetime.end), check1593 // the next candidate if the current Current does not write the same1594 // underlying object as the terminator.1595 if (!isMemTerminator(*CurrentLoc, CurrentI, KillingI)) {1596 CanOptimize = false;1597 continue;1598 }1599 } else {1600 int64_t KillingOffset = 0;1601 int64_t DeadOffset = 0;1602 auto OR = isOverwrite(KillingI, CurrentI, KillingLoc, *CurrentLoc,1603 KillingOffset, DeadOffset);1604 if (CanOptimize) {1605 // CurrentDef is the earliest write clobber of KillingDef. Use it as1606 // optimized access. Do not optimize if CurrentDef is already the1607 // defining access of KillingDef.1608 if (CurrentDef != KillingDef->getDefiningAccess() &&1609 (OR == OW_Complete || OR == OW_MaybePartial))1610 KillingDef->setOptimized(CurrentDef);1611 1612 // Once a may-aliasing def is encountered do not set an optimized1613 // access.1614 if (OR != OW_None)1615 CanOptimize = false;1616 }1617 1618 // If Current does not write to the same object as KillingDef, check1619 // the next candidate.1620 if (OR == OW_Unknown || OR == OW_None)1621 continue;1622 else if (OR == OW_MaybePartial) {1623 // If KillingDef only partially overwrites Current, check the next1624 // candidate if the partial step limit is exceeded. This aggressively1625 // limits the number of candidates for partial store elimination,1626 // which are less likely to be removable in the end.1627 if (PartialLimit <= 1) {1628 WalkerStepLimit -= 1;1629 LLVM_DEBUG(dbgs() << " ... reached partial limit ... continue with next access\n");1630 continue;1631 }1632 PartialLimit -= 1;1633 }1634 }1635 break;1636 };1637 1638 // Accesses to objects accessible after the function returns can only be1639 // eliminated if the access is dead along all paths to the exit. Collect1640 // the blocks with killing (=completely overwriting MemoryDefs) and check if1641 // they cover all paths from MaybeDeadAccess to any function exit.1642 SmallPtrSet<Instruction *, 16> KillingDefs;1643 KillingDefs.insert(KillingDef->getMemoryInst());1644 MemoryAccess *MaybeDeadAccess = Current;1645 MemoryLocation MaybeDeadLoc = *CurrentLoc;1646 Instruction *MaybeDeadI = cast<MemoryDef>(MaybeDeadAccess)->getMemoryInst();1647 LLVM_DEBUG(dbgs() << " Checking for reads of " << *MaybeDeadAccess << " ("1648 << *MaybeDeadI << ")\n");1649 1650 SmallVector<MemoryAccess *, 32> WorkList;1651 SmallPtrSet<MemoryAccess *, 32> Visited;1652 pushMemUses(MaybeDeadAccess, WorkList, Visited);1653 1654 // Check if DeadDef may be read.1655 for (unsigned I = 0; I < WorkList.size(); I++) {1656 MemoryAccess *UseAccess = WorkList[I];1657 1658 LLVM_DEBUG(dbgs() << " " << *UseAccess);1659 // Bail out if the number of accesses to check exceeds the scan limit.1660 if (ScanLimit < (WorkList.size() - I)) {1661 LLVM_DEBUG(dbgs() << "\n ... hit scan limit\n");1662 return std::nullopt;1663 }1664 --ScanLimit;1665 NumDomMemDefChecks++;1666 1667 if (isa<MemoryPhi>(UseAccess)) {1668 if (any_of(KillingDefs, [this, UseAccess](Instruction *KI) {1669 return DT.properlyDominates(KI->getParent(),1670 UseAccess->getBlock());1671 })) {1672 LLVM_DEBUG(dbgs() << " ... skipping, dominated by killing block\n");1673 continue;1674 }1675 LLVM_DEBUG(dbgs() << "\n ... adding PHI uses\n");1676 pushMemUses(UseAccess, WorkList, Visited);1677 continue;1678 }1679 1680 Instruction *UseInst = cast<MemoryUseOrDef>(UseAccess)->getMemoryInst();1681 LLVM_DEBUG(dbgs() << " (" << *UseInst << ")\n");1682 1683 if (any_of(KillingDefs, [this, UseInst](Instruction *KI) {1684 return DT.dominates(KI, UseInst);1685 })) {1686 LLVM_DEBUG(dbgs() << " ... skipping, dominated by killing def\n");1687 continue;1688 }1689 1690 // A memory terminator kills all preceeding MemoryDefs and all succeeding1691 // MemoryAccesses. We do not have to check it's users.1692 if (isMemTerminator(MaybeDeadLoc, MaybeDeadI, UseInst)) {1693 LLVM_DEBUG(1694 dbgs()1695 << " ... skipping, memterminator invalidates following accesses\n");1696 continue;1697 }1698 1699 if (isNoopIntrinsic(cast<MemoryUseOrDef>(UseAccess)->getMemoryInst())) {1700 LLVM_DEBUG(dbgs() << " ... adding uses of intrinsic\n");1701 pushMemUses(UseAccess, WorkList, Visited);1702 continue;1703 }1704 1705 if (UseInst->mayThrow() && !isInvisibleToCallerOnUnwind(KillingUndObj)) {1706 LLVM_DEBUG(dbgs() << " ... found throwing instruction\n");1707 return std::nullopt;1708 }1709 1710 // Uses which may read the original MemoryDef mean we cannot eliminate the1711 // original MD. Stop walk.1712 // If KillingDef is a CallInst with "initializes" attribute, the reads in1713 // the callee would be dominated by initializations, so it should be safe.1714 bool IsKillingDefFromInitAttr = false;1715 if (IsInitializesAttrMemLoc) {1716 if (KillingI == UseInst &&1717 KillingUndObj == getUnderlyingObject(MaybeDeadLoc.Ptr))1718 IsKillingDefFromInitAttr = true;1719 }1720 1721 if (isReadClobber(MaybeDeadLoc, UseInst) && !IsKillingDefFromInitAttr) {1722 LLVM_DEBUG(dbgs() << " ... found read clobber\n");1723 return std::nullopt;1724 }1725 1726 // If this worklist walks back to the original memory access (and the1727 // pointer is not guarenteed loop invariant) then we cannot assume that a1728 // store kills itself.1729 if (MaybeDeadAccess == UseAccess &&1730 !isGuaranteedLoopInvariant(MaybeDeadLoc.Ptr)) {1731 LLVM_DEBUG(dbgs() << " ... found not loop invariant self access\n");1732 return std::nullopt;1733 }1734 // Otherwise, for the KillingDef and MaybeDeadAccess we only have to check1735 // if it reads the memory location.1736 // TODO: It would probably be better to check for self-reads before1737 // calling the function.1738 if (KillingDef == UseAccess || MaybeDeadAccess == UseAccess) {1739 LLVM_DEBUG(dbgs() << " ... skipping killing def/dom access\n");1740 continue;1741 }1742 1743 // Check all uses for MemoryDefs, except for defs completely overwriting1744 // the original location. Otherwise we have to check uses of *all*1745 // MemoryDefs we discover, including non-aliasing ones. Otherwise we might1746 // miss cases like the following1747 // 1 = Def(LoE) ; <----- DeadDef stores [0,1]1748 // 2 = Def(1) ; (2, 1) = NoAlias, stores [2,3]1749 // Use(2) ; MayAlias 2 *and* 1, loads [0, 3].1750 // (The Use points to the *first* Def it may alias)1751 // 3 = Def(1) ; <---- Current (3, 2) = NoAlias, (3,1) = MayAlias,1752 // stores [0,1]1753 if (MemoryDef *UseDef = dyn_cast<MemoryDef>(UseAccess)) {1754 if (isCompleteOverwrite(MaybeDeadLoc, MaybeDeadI, UseInst)) {1755 BasicBlock *MaybeKillingBlock = UseInst->getParent();1756 if (PostOrderNumbers.find(MaybeKillingBlock)->second <1757 PostOrderNumbers.find(MaybeDeadAccess->getBlock())->second) {1758 if (!isInvisibleToCallerAfterRet(KillingUndObj)) {1759 LLVM_DEBUG(dbgs()1760 << " ... found killing def " << *UseInst << "\n");1761 KillingDefs.insert(UseInst);1762 }1763 } else {1764 LLVM_DEBUG(dbgs()1765 << " ... found preceeding def " << *UseInst << "\n");1766 return std::nullopt;1767 }1768 } else1769 pushMemUses(UseDef, WorkList, Visited);1770 }1771 }1772 1773 // For accesses to locations visible after the function returns, make sure1774 // that the location is dead (=overwritten) along all paths from1775 // MaybeDeadAccess to the exit.1776 if (!isInvisibleToCallerAfterRet(KillingUndObj)) {1777 SmallPtrSet<BasicBlock *, 16> KillingBlocks;1778 for (Instruction *KD : KillingDefs)1779 KillingBlocks.insert(KD->getParent());1780 assert(!KillingBlocks.empty() &&1781 "Expected at least a single killing block");1782 1783 // Find the common post-dominator of all killing blocks.1784 BasicBlock *CommonPred = *KillingBlocks.begin();1785 for (BasicBlock *BB : llvm::drop_begin(KillingBlocks)) {1786 if (!CommonPred)1787 break;1788 CommonPred = PDT.findNearestCommonDominator(CommonPred, BB);1789 }1790 1791 // If the common post-dominator does not post-dominate MaybeDeadAccess,1792 // there is a path from MaybeDeadAccess to an exit not going through a1793 // killing block.1794 if (!PDT.dominates(CommonPred, MaybeDeadAccess->getBlock())) {1795 if (!AnyUnreachableExit)1796 return std::nullopt;1797 1798 // Fall back to CFG scan starting at all non-unreachable roots if not1799 // all paths to the exit go through CommonPred.1800 CommonPred = nullptr;1801 }1802 1803 // If CommonPred itself is in the set of killing blocks, we're done.1804 if (KillingBlocks.count(CommonPred))1805 return {MaybeDeadAccess};1806 1807 SetVector<BasicBlock *> WorkList;1808 // If CommonPred is null, there are multiple exits from the function.1809 // They all have to be added to the worklist.1810 if (CommonPred)1811 WorkList.insert(CommonPred);1812 else1813 for (BasicBlock *R : PDT.roots()) {1814 if (!isa<UnreachableInst>(R->getTerminator()))1815 WorkList.insert(R);1816 }1817 1818 NumCFGTries++;1819 // Check if all paths starting from an exit node go through one of the1820 // killing blocks before reaching MaybeDeadAccess.1821 for (unsigned I = 0; I < WorkList.size(); I++) {1822 NumCFGChecks++;1823 BasicBlock *Current = WorkList[I];1824 if (KillingBlocks.count(Current))1825 continue;1826 if (Current == MaybeDeadAccess->getBlock())1827 return std::nullopt;1828 1829 // MaybeDeadAccess is reachable from the entry, so we don't have to1830 // explore unreachable blocks further.1831 if (!DT.isReachableFromEntry(Current))1832 continue;1833 1834 WorkList.insert_range(predecessors(Current));1835 1836 if (WorkList.size() >= MemorySSAPathCheckLimit)1837 return std::nullopt;1838 }1839 NumCFGSuccess++;1840 }1841 1842 // No aliasing MemoryUses of MaybeDeadAccess found, MaybeDeadAccess is1843 // potentially dead.1844 return {MaybeDeadAccess};1845 }1846 1847 /// Delete dead memory defs and recursively add their operands to ToRemove if1848 /// they became dead.1849 void1850 deleteDeadInstruction(Instruction *SI,1851 SmallPtrSetImpl<MemoryAccess *> *Deleted = nullptr) {1852 MemorySSAUpdater Updater(&MSSA);1853 SmallVector<Instruction *, 32> NowDeadInsts;1854 NowDeadInsts.push_back(SI);1855 --NumFastOther;1856 1857 while (!NowDeadInsts.empty()) {1858 Instruction *DeadInst = NowDeadInsts.pop_back_val();1859 ++NumFastOther;1860 1861 // Try to preserve debug information attached to the dead instruction.1862 salvageDebugInfo(*DeadInst);1863 salvageKnowledge(DeadInst);1864 1865 // Remove the Instruction from MSSA.1866 MemoryAccess *MA = MSSA.getMemoryAccess(DeadInst);1867 bool IsMemDef = MA && isa<MemoryDef>(MA);1868 if (MA) {1869 if (IsMemDef) {1870 auto *MD = cast<MemoryDef>(MA);1871 SkipStores.insert(MD);1872 if (Deleted)1873 Deleted->insert(MD);1874 if (auto *SI = dyn_cast<StoreInst>(MD->getMemoryInst())) {1875 if (SI->getValueOperand()->getType()->isPointerTy()) {1876 const Value *UO = getUnderlyingObject(SI->getValueOperand());1877 if (CapturedBeforeReturn.erase(UO))1878 ShouldIterateEndOfFunctionDSE = true;1879 InvisibleToCallerAfterRet.erase(UO);1880 }1881 }1882 }1883 1884 Updater.removeMemoryAccess(MA);1885 }1886 1887 auto I = IOLs.find(DeadInst->getParent());1888 if (I != IOLs.end())1889 I->second.erase(DeadInst);1890 // Remove its operands1891 for (Use &O : DeadInst->operands())1892 if (Instruction *OpI = dyn_cast<Instruction>(O)) {1893 O.set(PoisonValue::get(O->getType()));1894 if (isInstructionTriviallyDead(OpI, &TLI))1895 NowDeadInsts.push_back(OpI);1896 }1897 1898 EA.removeInstruction(DeadInst);1899 // Remove memory defs directly if they don't produce results, but only1900 // queue other dead instructions for later removal. They may have been1901 // used as memory locations that have been cached by BatchAA. Removing1902 // them here may lead to newly created instructions to be allocated at the1903 // same address, yielding stale cache entries.1904 if (IsMemDef && DeadInst->getType()->isVoidTy())1905 DeadInst->eraseFromParent();1906 else1907 ToRemove.push_back(DeadInst);1908 }1909 }1910 1911 // Check for any extra throws between \p KillingI and \p DeadI that block1912 // DSE. This only checks extra maythrows (those that aren't MemoryDef's).1913 // MemoryDef that may throw are handled during the walk from one def to the1914 // next.1915 bool mayThrowBetween(Instruction *KillingI, Instruction *DeadI,1916 const Value *KillingUndObj) {1917 // First see if we can ignore it by using the fact that KillingI is an1918 // alloca/alloca like object that is not visible to the caller during1919 // execution of the function.1920 if (KillingUndObj && isInvisibleToCallerOnUnwind(KillingUndObj))1921 return false;1922 1923 if (KillingI->getParent() == DeadI->getParent())1924 return ThrowingBlocks.count(KillingI->getParent());1925 return !ThrowingBlocks.empty();1926 }1927 1928 // Check if \p DeadI acts as a DSE barrier for \p KillingI. The following1929 // instructions act as barriers:1930 // * A memory instruction that may throw and \p KillingI accesses a non-stack1931 // object.1932 // * Atomic stores stronger that monotonic.1933 bool isDSEBarrier(const Value *KillingUndObj, Instruction *DeadI) {1934 // If DeadI may throw it acts as a barrier, unless we are to an1935 // alloca/alloca like object that does not escape.1936 if (DeadI->mayThrow() && !isInvisibleToCallerOnUnwind(KillingUndObj))1937 return true;1938 1939 // If DeadI is an atomic load/store stronger than monotonic, do not try to1940 // eliminate/reorder it.1941 if (DeadI->isAtomic()) {1942 if (auto *LI = dyn_cast<LoadInst>(DeadI))1943 return isStrongerThanMonotonic(LI->getOrdering());1944 if (auto *SI = dyn_cast<StoreInst>(DeadI))1945 return isStrongerThanMonotonic(SI->getOrdering());1946 if (auto *ARMW = dyn_cast<AtomicRMWInst>(DeadI))1947 return isStrongerThanMonotonic(ARMW->getOrdering());1948 if (auto *CmpXchg = dyn_cast<AtomicCmpXchgInst>(DeadI))1949 return isStrongerThanMonotonic(CmpXchg->getSuccessOrdering()) ||1950 isStrongerThanMonotonic(CmpXchg->getFailureOrdering());1951 llvm_unreachable("other instructions should be skipped in MemorySSA");1952 }1953 return false;1954 }1955 1956 /// Eliminate writes to objects that are not visible in the caller and are not1957 /// accessed before returning from the function.1958 bool eliminateDeadWritesAtEndOfFunction() {1959 bool MadeChange = false;1960 LLVM_DEBUG(1961 dbgs()1962 << "Trying to eliminate MemoryDefs at the end of the function\n");1963 do {1964 ShouldIterateEndOfFunctionDSE = false;1965 for (MemoryDef *Def : llvm::reverse(MemDefs)) {1966 if (SkipStores.contains(Def))1967 continue;1968 1969 Instruction *DefI = Def->getMemoryInst();1970 auto DefLoc = getLocForWrite(DefI);1971 if (!DefLoc || !isRemovable(DefI)) {1972 LLVM_DEBUG(dbgs() << " ... could not get location for write or "1973 "instruction not removable.\n");1974 continue;1975 }1976 1977 // NOTE: Currently eliminating writes at the end of a function is1978 // limited to MemoryDefs with a single underlying object, to save1979 // compile-time. In practice it appears the case with multiple1980 // underlying objects is very uncommon. If it turns out to be important,1981 // we can use getUnderlyingObjects here instead.1982 const Value *UO = getUnderlyingObject(DefLoc->Ptr);1983 if (!isInvisibleToCallerAfterRet(UO))1984 continue;1985 1986 if (isWriteAtEndOfFunction(Def, *DefLoc)) {1987 // See through pointer-to-pointer bitcasts1988 LLVM_DEBUG(dbgs() << " ... MemoryDef is not accessed until the end "1989 "of the function\n");1990 deleteDeadInstruction(DefI);1991 ++NumFastStores;1992 MadeChange = true;1993 }1994 }1995 } while (ShouldIterateEndOfFunctionDSE);1996 return MadeChange;1997 }1998 1999 /// If we have a zero initializing memset following a call to malloc,2000 /// try folding it into a call to calloc.2001 bool tryFoldIntoCalloc(MemoryDef *Def, const Value *DefUO) {2002 Instruction *DefI = Def->getMemoryInst();2003 MemSetInst *MemSet = dyn_cast<MemSetInst>(DefI);2004 if (!MemSet)2005 // TODO: Could handle zero store to small allocation as well.2006 return false;2007 Constant *StoredConstant = dyn_cast<Constant>(MemSet->getValue());2008 if (!StoredConstant || !StoredConstant->isNullValue())2009 return false;2010 2011 if (!isRemovable(DefI))2012 // The memset might be volatile..2013 return false;2014 2015 if (F.hasFnAttribute(Attribute::SanitizeMemory) ||2016 F.hasFnAttribute(Attribute::SanitizeAddress) ||2017 F.hasFnAttribute(Attribute::SanitizeHWAddress) ||2018 F.getName() == "calloc")2019 return false;2020 auto *Malloc = const_cast<CallInst *>(dyn_cast<CallInst>(DefUO));2021 if (!Malloc)2022 return false;2023 auto *InnerCallee = Malloc->getCalledFunction();2024 if (!InnerCallee)2025 return false;2026 LibFunc Func = NotLibFunc;2027 StringRef ZeroedVariantName;2028 if (!TLI.getLibFunc(*InnerCallee, Func) || !TLI.has(Func) ||2029 Func != LibFunc_malloc) {2030 Attribute Attr = Malloc->getFnAttr("alloc-variant-zeroed");2031 if (!Attr.isValid())2032 return false;2033 ZeroedVariantName = Attr.getValueAsString();2034 if (ZeroedVariantName.empty())2035 return false;2036 }2037 2038 // Gracefully handle malloc with unexpected memory attributes.2039 auto *MallocDef = dyn_cast_or_null<MemoryDef>(MSSA.getMemoryAccess(Malloc));2040 if (!MallocDef)2041 return false;2042 2043 auto shouldCreateCalloc = [](CallInst *Malloc, CallInst *Memset) {2044 // Check for br(icmp ptr, null), truebb, falsebb) pattern at the end2045 // of malloc block2046 auto *MallocBB = Malloc->getParent(),2047 *MemsetBB = Memset->getParent();2048 if (MallocBB == MemsetBB)2049 return true;2050 auto *Ptr = Memset->getArgOperand(0);2051 auto *TI = MallocBB->getTerminator();2052 BasicBlock *TrueBB, *FalseBB;2053 if (!match(TI, m_Br(m_SpecificICmp(ICmpInst::ICMP_EQ, m_Specific(Ptr),2054 m_Zero()),2055 TrueBB, FalseBB)))2056 return false;2057 if (MemsetBB != FalseBB)2058 return false;2059 return true;2060 };2061 2062 if (Malloc->getOperand(0) != MemSet->getLength())2063 return false;2064 if (!shouldCreateCalloc(Malloc, MemSet) || !DT.dominates(Malloc, MemSet) ||2065 !memoryIsNotModifiedBetween(Malloc, MemSet, BatchAA, DL, &DT))2066 return false;2067 IRBuilder<> IRB(Malloc);2068 assert(Func == LibFunc_malloc || !ZeroedVariantName.empty());2069 Value *Calloc = nullptr;2070 if (!ZeroedVariantName.empty()) {2071 LLVMContext &Ctx = Malloc->getContext();2072 AttributeList Attrs = InnerCallee->getAttributes();2073 AllocFnKind AllocKind =2074 Attrs.getFnAttr(Attribute::AllocKind).getAllocKind() |2075 AllocFnKind::Zeroed;2076 AllocKind &= ~AllocFnKind::Uninitialized;2077 Attrs =2078 Attrs.addFnAttribute(Ctx, Attribute::getWithAllocKind(Ctx, AllocKind))2079 .removeFnAttribute(Ctx, "alloc-variant-zeroed");2080 FunctionCallee ZeroedVariant = Malloc->getModule()->getOrInsertFunction(2081 ZeroedVariantName, InnerCallee->getFunctionType(), Attrs);2082 SmallVector<Value *, 3> Args;2083 Args.append(Malloc->arg_begin(), Malloc->arg_end());2084 Calloc = IRB.CreateCall(ZeroedVariant, Args, ZeroedVariantName);2085 } else {2086 Type *SizeTTy = Malloc->getArgOperand(0)->getType();2087 Calloc =2088 emitCalloc(ConstantInt::get(SizeTTy, 1), Malloc->getArgOperand(0),2089 IRB, TLI, Malloc->getType()->getPointerAddressSpace());2090 }2091 if (!Calloc)2092 return false;2093 2094 MemorySSAUpdater Updater(&MSSA);2095 auto *NewAccess =2096 Updater.createMemoryAccessAfter(cast<Instruction>(Calloc), nullptr,2097 MallocDef);2098 auto *NewAccessMD = cast<MemoryDef>(NewAccess);2099 Updater.insertDef(NewAccessMD, /*RenameUses=*/true);2100 Malloc->replaceAllUsesWith(Calloc);2101 deleteDeadInstruction(Malloc);2102 return true;2103 }2104 2105 // Check if there is a dominating condition, that implies that the value2106 // being stored in a ptr is already present in the ptr.2107 bool dominatingConditionImpliesValue(MemoryDef *Def) {2108 auto *StoreI = cast<StoreInst>(Def->getMemoryInst());2109 BasicBlock *StoreBB = StoreI->getParent();2110 Value *StorePtr = StoreI->getPointerOperand();2111 Value *StoreVal = StoreI->getValueOperand();2112 2113 DomTreeNode *IDom = DT.getNode(StoreBB)->getIDom();2114 if (!IDom)2115 return false;2116 2117 auto *BI = dyn_cast<BranchInst>(IDom->getBlock()->getTerminator());2118 if (!BI || !BI->isConditional())2119 return false;2120 2121 // In case both blocks are the same, it is not possible to determine2122 // if optimization is possible. (We would not want to optimize a store2123 // in the FalseBB if condition is true and vice versa.)2124 if (BI->getSuccessor(0) == BI->getSuccessor(1))2125 return false;2126 2127 Instruction *ICmpL;2128 CmpPredicate Pred;2129 if (!match(BI->getCondition(),2130 m_c_ICmp(Pred,2131 m_CombineAnd(m_Load(m_Specific(StorePtr)),2132 m_Instruction(ICmpL)),2133 m_Specific(StoreVal))) ||2134 !ICmpInst::isEquality(Pred))2135 return false;2136 2137 // In case the else blocks also branches to the if block or the other way2138 // around it is not possible to determine if the optimization is possible.2139 if (Pred == ICmpInst::ICMP_EQ &&2140 !DT.dominates(BasicBlockEdge(BI->getParent(), BI->getSuccessor(0)),2141 StoreBB))2142 return false;2143 2144 if (Pred == ICmpInst::ICMP_NE &&2145 !DT.dominates(BasicBlockEdge(BI->getParent(), BI->getSuccessor(1)),2146 StoreBB))2147 return false;2148 2149 MemoryAccess *LoadAcc = MSSA.getMemoryAccess(ICmpL);2150 MemoryAccess *ClobAcc =2151 MSSA.getSkipSelfWalker()->getClobberingMemoryAccess(Def, BatchAA);2152 2153 return MSSA.dominates(ClobAcc, LoadAcc);2154 }2155 2156 /// \returns true if \p Def is a no-op store, either because it2157 /// directly stores back a loaded value or stores zero to a calloced object.2158 bool storeIsNoop(MemoryDef *Def, const Value *DefUO) {2159 Instruction *DefI = Def->getMemoryInst();2160 StoreInst *Store = dyn_cast<StoreInst>(DefI);2161 MemSetInst *MemSet = dyn_cast<MemSetInst>(DefI);2162 Constant *StoredConstant = nullptr;2163 if (Store)2164 StoredConstant = dyn_cast<Constant>(Store->getOperand(0));2165 else if (MemSet)2166 StoredConstant = dyn_cast<Constant>(MemSet->getValue());2167 else2168 return false;2169 2170 if (!isRemovable(DefI))2171 return false;2172 2173 if (StoredConstant) {2174 Constant *InitC =2175 getInitialValueOfAllocation(DefUO, &TLI, StoredConstant->getType());2176 // If the clobbering access is LiveOnEntry, no instructions between them2177 // can modify the memory location.2178 if (InitC && InitC == StoredConstant)2179 return MSSA.isLiveOnEntryDef(2180 MSSA.getSkipSelfWalker()->getClobberingMemoryAccess(Def, BatchAA));2181 }2182 2183 if (!Store)2184 return false;2185 2186 if (dominatingConditionImpliesValue(Def))2187 return true;2188 2189 if (auto *LoadI = dyn_cast<LoadInst>(Store->getOperand(0))) {2190 if (LoadI->getPointerOperand() == Store->getOperand(1)) {2191 // Get the defining access for the load.2192 auto *LoadAccess = MSSA.getMemoryAccess(LoadI)->getDefiningAccess();2193 // Fast path: the defining accesses are the same.2194 if (LoadAccess == Def->getDefiningAccess())2195 return true;2196 2197 // Look through phi accesses. Recursively scan all phi accesses by2198 // adding them to a worklist. Bail when we run into a memory def that2199 // does not match LoadAccess.2200 SetVector<MemoryAccess *> ToCheck;2201 MemoryAccess *Current =2202 MSSA.getWalker()->getClobberingMemoryAccess(Def, BatchAA);2203 // We don't want to bail when we run into the store memory def. But,2204 // the phi access may point to it. So, pretend like we've already2205 // checked it.2206 ToCheck.insert(Def);2207 ToCheck.insert(Current);2208 // Start at current (1) to simulate already having checked Def.2209 for (unsigned I = 1; I < ToCheck.size(); ++I) {2210 Current = ToCheck[I];2211 if (auto PhiAccess = dyn_cast<MemoryPhi>(Current)) {2212 // Check all the operands.2213 for (auto &Use : PhiAccess->incoming_values())2214 ToCheck.insert(cast<MemoryAccess>(&Use));2215 continue;2216 }2217 2218 // If we found a memory def, bail. This happens when we have an2219 // unrelated write in between an otherwise noop store.2220 assert(isa<MemoryDef>(Current) &&2221 "Only MemoryDefs should reach here.");2222 // TODO: Skip no alias MemoryDefs that have no aliasing reads.2223 // We are searching for the definition of the store's destination.2224 // So, if that is the same definition as the load, then this is a2225 // noop. Otherwise, fail.2226 if (LoadAccess != Current)2227 return false;2228 }2229 return true;2230 }2231 }2232 2233 return false;2234 }2235 2236 bool removePartiallyOverlappedStores(InstOverlapIntervalsTy &IOL) {2237 bool Changed = false;2238 for (auto OI : IOL) {2239 Instruction *DeadI = OI.first;2240 MemoryLocation Loc = *getLocForWrite(DeadI);2241 assert(isRemovable(DeadI) && "Expect only removable instruction");2242 2243 const Value *Ptr = Loc.Ptr->stripPointerCasts();2244 int64_t DeadStart = 0;2245 uint64_t DeadSize = Loc.Size.getValue();2246 GetPointerBaseWithConstantOffset(Ptr, DeadStart, DL);2247 OverlapIntervalsTy &IntervalMap = OI.second;2248 Changed |= tryToShortenEnd(DeadI, IntervalMap, DeadStart, DeadSize);2249 if (IntervalMap.empty())2250 continue;2251 Changed |= tryToShortenBegin(DeadI, IntervalMap, DeadStart, DeadSize);2252 }2253 return Changed;2254 }2255 2256 /// Eliminates writes to locations where the value that is being written2257 /// is already stored at the same location.2258 bool eliminateRedundantStoresOfExistingValues() {2259 bool MadeChange = false;2260 LLVM_DEBUG(dbgs() << "Trying to eliminate MemoryDefs that write the "2261 "already existing value\n");2262 for (auto *Def : MemDefs) {2263 if (SkipStores.contains(Def) || MSSA.isLiveOnEntryDef(Def))2264 continue;2265 2266 Instruction *DefInst = Def->getMemoryInst();2267 auto MaybeDefLoc = getLocForWrite(DefInst);2268 if (!MaybeDefLoc || !isRemovable(DefInst))2269 continue;2270 2271 MemoryDef *UpperDef;2272 // To conserve compile-time, we avoid walking to the next clobbering def.2273 // Instead, we just try to get the optimized access, if it exists. DSE2274 // will try to optimize defs during the earlier traversal.2275 if (Def->isOptimized())2276 UpperDef = dyn_cast<MemoryDef>(Def->getOptimized());2277 else2278 UpperDef = dyn_cast<MemoryDef>(Def->getDefiningAccess());2279 if (!UpperDef || MSSA.isLiveOnEntryDef(UpperDef))2280 continue;2281 2282 Instruction *UpperInst = UpperDef->getMemoryInst();2283 auto IsRedundantStore = [&]() {2284 // We don't care about differences in call attributes here.2285 if (DefInst->isIdenticalToWhenDefined(UpperInst,2286 /*IntersectAttrs=*/true))2287 return true;2288 if (auto *MemSetI = dyn_cast<MemSetInst>(UpperInst)) {2289 if (auto *SI = dyn_cast<StoreInst>(DefInst)) {2290 // MemSetInst must have a write location.2291 auto UpperLoc = getLocForWrite(UpperInst);2292 if (!UpperLoc)2293 return false;2294 int64_t InstWriteOffset = 0;2295 int64_t DepWriteOffset = 0;2296 auto OR = isOverwrite(UpperInst, DefInst, *UpperLoc, *MaybeDefLoc,2297 InstWriteOffset, DepWriteOffset);2298 Value *StoredByte = isBytewiseValue(SI->getValueOperand(), DL);2299 return StoredByte && StoredByte == MemSetI->getOperand(1) &&2300 OR == OW_Complete;2301 }2302 }2303 return false;2304 };2305 2306 if (!IsRedundantStore() || isReadClobber(*MaybeDefLoc, DefInst))2307 continue;2308 LLVM_DEBUG(dbgs() << "DSE: Remove No-Op Store:\n DEAD: " << *DefInst2309 << '\n');2310 deleteDeadInstruction(DefInst);2311 NumRedundantStores++;2312 MadeChange = true;2313 }2314 return MadeChange;2315 }2316 2317 // Return the locations written by the initializes attribute.2318 // Note that this function considers:2319 // 1. Unwind edge: use "initializes" attribute only if the callee has2320 // "nounwind" attribute, or the argument has "dead_on_unwind" attribute,2321 // or the argument is invisible to caller on unwind. That is, we don't2322 // perform incorrect DSE on unwind edges in the current function.2323 // 2. Argument alias: for aliasing arguments, the "initializes" attribute is2324 // the intersected range list of their "initializes" attributes.2325 SmallVector<MemoryLocation, 1> getInitializesArgMemLoc(const Instruction *I);2326 2327 // Try to eliminate dead defs that access `KillingLocWrapper.MemLoc` and are2328 // killed by `KillingLocWrapper.MemDef`. Return whether2329 // any changes were made, and whether `KillingLocWrapper.DefInst` was deleted.2330 std::pair<bool, bool>2331 eliminateDeadDefs(const MemoryLocationWrapper &KillingLocWrapper);2332 2333 // Try to eliminate dead defs killed by `KillingDefWrapper` and return the2334 // change state: whether make any change.2335 bool eliminateDeadDefs(const MemoryDefWrapper &KillingDefWrapper);2336};2337} // namespace2338 2339// Return true if "Arg" is function local and isn't captured before "CB".2340static bool isFuncLocalAndNotCaptured(Value *Arg, const CallBase *CB,2341 EarliestEscapeAnalysis &EA) {2342 const Value *UnderlyingObj = getUnderlyingObject(Arg);2343 return isIdentifiedFunctionLocal(UnderlyingObj) &&2344 capturesNothing(2345 EA.getCapturesBefore(UnderlyingObj, CB, /*OrAt*/ true));2346}2347 2348SmallVector<MemoryLocation, 1>2349DSEState::getInitializesArgMemLoc(const Instruction *I) {2350 const CallBase *CB = dyn_cast<CallBase>(I);2351 if (!CB)2352 return {};2353 2354 // Collect aliasing arguments and their initializes ranges.2355 SmallMapVector<Value *, SmallVector<ArgumentInitInfo, 2>, 2> Arguments;2356 for (unsigned Idx = 0, Count = CB->arg_size(); Idx < Count; ++Idx) {2357 Value *CurArg = CB->getArgOperand(Idx);2358 if (!CurArg->getType()->isPointerTy())2359 continue;2360 2361 ConstantRangeList Inits;2362 Attribute InitializesAttr = CB->getParamAttr(Idx, Attribute::Initializes);2363 // initializes on byval arguments refers to the callee copy, not the2364 // original memory the caller passed in.2365 if (InitializesAttr.isValid() && !CB->isByValArgument(Idx))2366 Inits = InitializesAttr.getValueAsConstantRangeList();2367 2368 // Check whether "CurArg" could alias with global variables. We require2369 // either it's function local and isn't captured before or the "CB" only2370 // accesses arg or inaccessible mem.2371 if (!Inits.empty() && !CB->onlyAccessesInaccessibleMemOrArgMem() &&2372 !isFuncLocalAndNotCaptured(CurArg, CB, EA))2373 Inits = ConstantRangeList();2374 2375 // We don't perform incorrect DSE on unwind edges in the current function,2376 // and use the "initializes" attribute to kill dead stores if:2377 // - The call does not throw exceptions, "CB->doesNotThrow()".2378 // - Or the callee parameter has "dead_on_unwind" attribute.2379 // - Or the argument is invisible to caller on unwind, and there are no2380 // unwind edges from this call in the current function (e.g. `CallInst`).2381 bool IsDeadOrInvisibleOnUnwind =2382 CB->paramHasAttr(Idx, Attribute::DeadOnUnwind) ||2383 (isa<CallInst>(CB) && isInvisibleToCallerOnUnwind(CurArg));2384 ArgumentInitInfo InitInfo{Idx, IsDeadOrInvisibleOnUnwind, Inits};2385 bool FoundAliasing = false;2386 for (auto &[Arg, AliasList] : Arguments) {2387 auto AAR = BatchAA.alias(MemoryLocation::getBeforeOrAfter(Arg),2388 MemoryLocation::getBeforeOrAfter(CurArg));2389 if (AAR == AliasResult::NoAlias) {2390 continue;2391 } else if (AAR == AliasResult::MustAlias) {2392 FoundAliasing = true;2393 AliasList.push_back(InitInfo);2394 } else {2395 // For PartialAlias and MayAlias, there is an offset or may be an2396 // unknown offset between the arguments and we insert an empty init2397 // range to discard the entire initializes info while intersecting.2398 FoundAliasing = true;2399 AliasList.push_back(ArgumentInitInfo{Idx, IsDeadOrInvisibleOnUnwind,2400 ConstantRangeList()});2401 }2402 }2403 if (!FoundAliasing)2404 Arguments[CurArg] = {InitInfo};2405 }2406 2407 SmallVector<MemoryLocation, 1> Locations;2408 for (const auto &[_, Args] : Arguments) {2409 auto IntersectedRanges =2410 getIntersectedInitRangeList(Args, CB->doesNotThrow());2411 if (IntersectedRanges.empty())2412 continue;2413 2414 for (const auto &Arg : Args) {2415 for (const auto &Range : IntersectedRanges) {2416 int64_t Start = Range.getLower().getSExtValue();2417 int64_t End = Range.getUpper().getSExtValue();2418 // For now, we only handle locations starting at offset 0.2419 if (Start == 0)2420 Locations.push_back(MemoryLocation(CB->getArgOperand(Arg.Idx),2421 LocationSize::precise(End - Start),2422 CB->getAAMetadata()));2423 }2424 }2425 }2426 return Locations;2427}2428 2429std::pair<bool, bool>2430DSEState::eliminateDeadDefs(const MemoryLocationWrapper &KillingLocWrapper) {2431 bool Changed = false;2432 bool DeletedKillingLoc = false;2433 unsigned ScanLimit = MemorySSAScanLimit;2434 unsigned WalkerStepLimit = MemorySSAUpwardsStepLimit;2435 unsigned PartialLimit = MemorySSAPartialStoreLimit;2436 // Worklist of MemoryAccesses that may be killed by2437 // "KillingLocWrapper.MemDef".2438 SmallSetVector<MemoryAccess *, 8> ToCheck;2439 // Track MemoryAccesses that have been deleted in the loop below, so we can2440 // skip them. Don't use SkipStores for this, which may contain reused2441 // MemoryAccess addresses.2442 SmallPtrSet<MemoryAccess *, 8> Deleted;2443 [[maybe_unused]] unsigned OrigNumSkipStores = SkipStores.size();2444 ToCheck.insert(KillingLocWrapper.MemDef->getDefiningAccess());2445 2446 // Check if MemoryAccesses in the worklist are killed by2447 // "KillingLocWrapper.MemDef".2448 for (unsigned I = 0; I < ToCheck.size(); I++) {2449 MemoryAccess *Current = ToCheck[I];2450 if (Deleted.contains(Current))2451 continue;2452 std::optional<MemoryAccess *> MaybeDeadAccess = getDomMemoryDef(2453 KillingLocWrapper.MemDef, Current, KillingLocWrapper.MemLoc,2454 KillingLocWrapper.UnderlyingObject, ScanLimit, WalkerStepLimit,2455 isMemTerminatorInst(KillingLocWrapper.DefInst), PartialLimit,2456 KillingLocWrapper.DefByInitializesAttr);2457 2458 if (!MaybeDeadAccess) {2459 LLVM_DEBUG(dbgs() << " finished walk\n");2460 continue;2461 }2462 MemoryAccess *DeadAccess = *MaybeDeadAccess;2463 LLVM_DEBUG(dbgs() << " Checking if we can kill " << *DeadAccess);2464 if (isa<MemoryPhi>(DeadAccess)) {2465 LLVM_DEBUG(dbgs() << "\n ... adding incoming values to worklist\n");2466 for (Value *V : cast<MemoryPhi>(DeadAccess)->incoming_values()) {2467 MemoryAccess *IncomingAccess = cast<MemoryAccess>(V);2468 BasicBlock *IncomingBlock = IncomingAccess->getBlock();2469 BasicBlock *PhiBlock = DeadAccess->getBlock();2470 2471 // We only consider incoming MemoryAccesses that come before the2472 // MemoryPhi. Otherwise we could discover candidates that do not2473 // strictly dominate our starting def.2474 if (PostOrderNumbers[IncomingBlock] > PostOrderNumbers[PhiBlock])2475 ToCheck.insert(IncomingAccess);2476 }2477 continue;2478 }2479 // We cannot apply the initializes attribute to DeadAccess/DeadDef.2480 // It would incorrectly consider a call instruction as redundant store2481 // and remove this call instruction.2482 // TODO: this conflates the existence of a MemoryLocation with being able2483 // to delete the instruction. Fix isRemovable() to consider calls with2484 // side effects that cannot be removed, e.g. calls with the initializes2485 // attribute, and remove getLocForInst(ConsiderInitializesAttr = false).2486 MemoryDefWrapper DeadDefWrapper(2487 cast<MemoryDef>(DeadAccess),2488 getLocForInst(cast<MemoryDef>(DeadAccess)->getMemoryInst(),2489 /*ConsiderInitializesAttr=*/false));2490 assert(DeadDefWrapper.DefinedLocations.size() == 1);2491 MemoryLocationWrapper &DeadLocWrapper =2492 DeadDefWrapper.DefinedLocations.front();2493 LLVM_DEBUG(dbgs() << " (" << *DeadLocWrapper.DefInst << ")\n");2494 ToCheck.insert(DeadLocWrapper.MemDef->getDefiningAccess());2495 NumGetDomMemoryDefPassed++;2496 2497 if (!DebugCounter::shouldExecute(MemorySSACounter))2498 continue;2499 if (isMemTerminatorInst(KillingLocWrapper.DefInst)) {2500 if (KillingLocWrapper.UnderlyingObject != DeadLocWrapper.UnderlyingObject)2501 continue;2502 LLVM_DEBUG(dbgs() << "DSE: Remove Dead Store:\n DEAD: "2503 << *DeadLocWrapper.DefInst << "\n KILLER: "2504 << *KillingLocWrapper.DefInst << '\n');2505 deleteDeadInstruction(DeadLocWrapper.DefInst, &Deleted);2506 ++NumFastStores;2507 Changed = true;2508 } else {2509 // Check if DeadI overwrites KillingI.2510 int64_t KillingOffset = 0;2511 int64_t DeadOffset = 0;2512 OverwriteResult OR =2513 isOverwrite(KillingLocWrapper.DefInst, DeadLocWrapper.DefInst,2514 KillingLocWrapper.MemLoc, DeadLocWrapper.MemLoc,2515 KillingOffset, DeadOffset);2516 if (OR == OW_MaybePartial) {2517 auto &IOL = IOLs[DeadLocWrapper.DefInst->getParent()];2518 OR = isPartialOverwrite(KillingLocWrapper.MemLoc, DeadLocWrapper.MemLoc,2519 KillingOffset, DeadOffset,2520 DeadLocWrapper.DefInst, IOL);2521 }2522 if (EnablePartialStoreMerging && OR == OW_PartialEarlierWithFullLater) {2523 auto *DeadSI = dyn_cast<StoreInst>(DeadLocWrapper.DefInst);2524 auto *KillingSI = dyn_cast<StoreInst>(KillingLocWrapper.DefInst);2525 // We are re-using tryToMergePartialOverlappingStores, which requires2526 // DeadSI to dominate KillingSI.2527 // TODO: implement tryToMergeParialOverlappingStores using MemorySSA.2528 if (DeadSI && KillingSI && DT.dominates(DeadSI, KillingSI)) {2529 if (Constant *Merged = tryToMergePartialOverlappingStores(2530 KillingSI, DeadSI, KillingOffset, DeadOffset, DL, BatchAA,2531 &DT)) {2532 2533 // Update stored value of earlier store to merged constant.2534 DeadSI->setOperand(0, Merged);2535 ++NumModifiedStores;2536 Changed = true;2537 DeletedKillingLoc = true;2538 2539 // Remove killing store and remove any outstanding overlap2540 // intervals for the updated store.2541 deleteDeadInstruction(KillingSI, &Deleted);2542 auto I = IOLs.find(DeadSI->getParent());2543 if (I != IOLs.end())2544 I->second.erase(DeadSI);2545 break;2546 }2547 }2548 }2549 if (OR == OW_Complete) {2550 LLVM_DEBUG(dbgs() << "DSE: Remove Dead Store:\n DEAD: "2551 << *DeadLocWrapper.DefInst << "\n KILLER: "2552 << *KillingLocWrapper.DefInst << '\n');2553 deleteDeadInstruction(DeadLocWrapper.DefInst, &Deleted);2554 ++NumFastStores;2555 Changed = true;2556 }2557 }2558 }2559 2560 assert(SkipStores.size() - OrigNumSkipStores == Deleted.size() &&2561 "SkipStores and Deleted out of sync?");2562 2563 return {Changed, DeletedKillingLoc};2564}2565 2566bool DSEState::eliminateDeadDefs(const MemoryDefWrapper &KillingDefWrapper) {2567 if (KillingDefWrapper.DefinedLocations.empty()) {2568 LLVM_DEBUG(dbgs() << "Failed to find analyzable write location for "2569 << *KillingDefWrapper.DefInst << "\n");2570 return false;2571 }2572 2573 bool MadeChange = false;2574 for (auto &KillingLocWrapper : KillingDefWrapper.DefinedLocations) {2575 LLVM_DEBUG(dbgs() << "Trying to eliminate MemoryDefs killed by "2576 << *KillingLocWrapper.MemDef << " ("2577 << *KillingLocWrapper.DefInst << ")\n");2578 auto [Changed, DeletedKillingLoc] = eliminateDeadDefs(KillingLocWrapper);2579 MadeChange |= Changed;2580 2581 // Check if the store is a no-op.2582 if (!DeletedKillingLoc && storeIsNoop(KillingLocWrapper.MemDef,2583 KillingLocWrapper.UnderlyingObject)) {2584 LLVM_DEBUG(dbgs() << "DSE: Remove No-Op Store:\n DEAD: "2585 << *KillingLocWrapper.DefInst << '\n');2586 deleteDeadInstruction(KillingLocWrapper.DefInst);2587 NumRedundantStores++;2588 MadeChange = true;2589 continue;2590 }2591 // Can we form a calloc from a memset/malloc pair?2592 if (!DeletedKillingLoc &&2593 tryFoldIntoCalloc(KillingLocWrapper.MemDef,2594 KillingLocWrapper.UnderlyingObject)) {2595 LLVM_DEBUG(dbgs() << "DSE: Remove memset after forming calloc:\n"2596 << " DEAD: " << *KillingLocWrapper.DefInst << '\n');2597 deleteDeadInstruction(KillingLocWrapper.DefInst);2598 MadeChange = true;2599 continue;2600 }2601 }2602 return MadeChange;2603}2604 2605static bool eliminateDeadStores(Function &F, AliasAnalysis &AA, MemorySSA &MSSA,2606 DominatorTree &DT, PostDominatorTree &PDT,2607 const TargetLibraryInfo &TLI,2608 const LoopInfo &LI) {2609 bool MadeChange = false;2610 DSEState State(F, AA, MSSA, DT, PDT, TLI, LI);2611 // For each store:2612 for (unsigned I = 0; I < State.MemDefs.size(); I++) {2613 MemoryDef *KillingDef = State.MemDefs[I];2614 if (State.SkipStores.count(KillingDef))2615 continue;2616 2617 MemoryDefWrapper KillingDefWrapper(2618 KillingDef, State.getLocForInst(KillingDef->getMemoryInst(),2619 EnableInitializesImprovement));2620 MadeChange |= State.eliminateDeadDefs(KillingDefWrapper);2621 }2622 2623 if (EnablePartialOverwriteTracking)2624 for (auto &KV : State.IOLs)2625 MadeChange |= State.removePartiallyOverlappedStores(KV.second);2626 2627 MadeChange |= State.eliminateRedundantStoresOfExistingValues();2628 MadeChange |= State.eliminateDeadWritesAtEndOfFunction();2629 2630 while (!State.ToRemove.empty()) {2631 Instruction *DeadInst = State.ToRemove.pop_back_val();2632 DeadInst->eraseFromParent();2633 }2634 2635 return MadeChange;2636}2637 2638//===----------------------------------------------------------------------===//2639// DSE Pass2640//===----------------------------------------------------------------------===//2641PreservedAnalyses DSEPass::run(Function &F, FunctionAnalysisManager &AM) {2642 AliasAnalysis &AA = AM.getResult<AAManager>(F);2643 const TargetLibraryInfo &TLI = AM.getResult<TargetLibraryAnalysis>(F);2644 DominatorTree &DT = AM.getResult<DominatorTreeAnalysis>(F);2645 MemorySSA &MSSA = AM.getResult<MemorySSAAnalysis>(F).getMSSA();2646 PostDominatorTree &PDT = AM.getResult<PostDominatorTreeAnalysis>(F);2647 LoopInfo &LI = AM.getResult<LoopAnalysis>(F);2648 2649 bool Changed = eliminateDeadStores(F, AA, MSSA, DT, PDT, TLI, LI);2650 2651#ifdef LLVM_ENABLE_STATS2652 if (AreStatisticsEnabled())2653 for (auto &I : instructions(F))2654 NumRemainingStores += isa<StoreInst>(&I);2655#endif2656 2657 if (!Changed)2658 return PreservedAnalyses::all();2659 2660 PreservedAnalyses PA;2661 PA.preserveSet<CFGAnalyses>();2662 PA.preserve<MemorySSAAnalysis>();2663 PA.preserve<LoopAnalysis>();2664 return PA;2665}2666 2667namespace {2668 2669/// A legacy pass for the legacy pass manager that wraps \c DSEPass.2670class DSELegacyPass : public FunctionPass {2671public:2672 static char ID; // Pass identification, replacement for typeid2673 2674 DSELegacyPass() : FunctionPass(ID) {2675 initializeDSELegacyPassPass(*PassRegistry::getPassRegistry());2676 }2677 2678 bool runOnFunction(Function &F) override {2679 if (skipFunction(F))2680 return false;2681 2682 AliasAnalysis &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();2683 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();2684 const TargetLibraryInfo &TLI =2685 getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);2686 MemorySSA &MSSA = getAnalysis<MemorySSAWrapperPass>().getMSSA();2687 PostDominatorTree &PDT =2688 getAnalysis<PostDominatorTreeWrapperPass>().getPostDomTree();2689 LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();2690 2691 bool Changed = eliminateDeadStores(F, AA, MSSA, DT, PDT, TLI, LI);2692 2693#ifdef LLVM_ENABLE_STATS2694 if (AreStatisticsEnabled())2695 for (auto &I : instructions(F))2696 NumRemainingStores += isa<StoreInst>(&I);2697#endif2698 2699 return Changed;2700 }2701 2702 void getAnalysisUsage(AnalysisUsage &AU) const override {2703 AU.setPreservesCFG();2704 AU.addRequired<AAResultsWrapperPass>();2705 AU.addRequired<TargetLibraryInfoWrapperPass>();2706 AU.addPreserved<GlobalsAAWrapperPass>();2707 AU.addRequired<DominatorTreeWrapperPass>();2708 AU.addPreserved<DominatorTreeWrapperPass>();2709 AU.addRequired<PostDominatorTreeWrapperPass>();2710 AU.addRequired<MemorySSAWrapperPass>();2711 AU.addPreserved<PostDominatorTreeWrapperPass>();2712 AU.addPreserved<MemorySSAWrapperPass>();2713 AU.addRequired<LoopInfoWrapperPass>();2714 AU.addPreserved<LoopInfoWrapperPass>();2715 AU.addRequired<AssumptionCacheTracker>();2716 }2717};2718 2719} // end anonymous namespace2720 2721char DSELegacyPass::ID = 0;2722 2723INITIALIZE_PASS_BEGIN(DSELegacyPass, "dse", "Dead Store Elimination", false,2724 false)2725INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)2726INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass)2727INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)2728INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass)2729INITIALIZE_PASS_DEPENDENCY(MemorySSAWrapperPass)2730INITIALIZE_PASS_DEPENDENCY(MemoryDependenceWrapperPass)2731INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)2732INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)2733INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)2734INITIALIZE_PASS_END(DSELegacyPass, "dse", "Dead Store Elimination", false,2735 false)2736 2737LLVM_ABI FunctionPass *llvm::createDeadStoreEliminationPass() {2738 return new DSELegacyPass();2739}2740