diff options
Diffstat (limited to 'lib/Transforms/Scalar/DeadStoreElimination.cpp')
| -rw-r--r-- | lib/Transforms/Scalar/DeadStoreElimination.cpp | 278 |
1 files changed, 158 insertions, 120 deletions
diff --git a/lib/Transforms/Scalar/DeadStoreElimination.cpp b/lib/Transforms/Scalar/DeadStoreElimination.cpp index e703014bb0e6..dd1a2a6adb82 100644 --- a/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -30,6 +30,7 @@ #include "llvm/Analysis/MemoryDependenceAnalysis.h" #include "llvm/Analysis/MemoryLocation.h" #include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/Transforms/Utils/Local.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/Argument.h" #include "llvm/IR/BasicBlock.h" @@ -56,11 +57,10 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/Utils/Local.h" #include <algorithm> #include <cassert> -#include <cstdint> #include <cstddef> +#include <cstdint> #include <iterator> #include <map> #include <utility> @@ -115,6 +115,9 @@ deleteDeadInstruction(Instruction *I, BasicBlock::iterator *BBI, Instruction *DeadInst = NowDeadInsts.pop_back_val(); ++NumFastOther; + // Try to preserve debug information attached to the dead instruction. + salvageDebugInfo(*DeadInst); + // This instruction is dead, zap it, in stages. Start by removing it from // MemDep, which needs to know the operands and needs it to be in the // function. @@ -146,7 +149,8 @@ deleteDeadInstruction(Instruction *I, BasicBlock::iterator *BBI, /// Does this instruction write some memory? This only returns true for things /// that we can analyze with other helpers below. -static bool hasMemoryWrite(Instruction *I, const TargetLibraryInfo &TLI) { +static bool hasAnalyzableMemoryWrite(Instruction *I, + const TargetLibraryInfo &TLI) { if (isa<StoreInst>(I)) return true; if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) { @@ -156,6 +160,9 @@ static bool hasMemoryWrite(Instruction *I, const TargetLibraryInfo &TLI) { case Intrinsic::memset: case Intrinsic::memmove: case Intrinsic::memcpy: + case Intrinsic::memcpy_element_unordered_atomic: + case Intrinsic::memmove_element_unordered_atomic: + case Intrinsic::memset_element_unordered_atomic: case Intrinsic::init_trampoline: case Intrinsic::lifetime_end: return true; @@ -180,43 +187,45 @@ static bool hasMemoryWrite(Instruction *I, const TargetLibraryInfo &TLI) { /// Return a Location stored to by the specified instruction. If isRemovable /// returns true, this function and getLocForRead completely describe the memory /// operations for this instruction. -static MemoryLocation getLocForWrite(Instruction *Inst, AliasAnalysis &AA) { +static MemoryLocation getLocForWrite(Instruction *Inst) { + if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) return MemoryLocation::get(SI); - if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(Inst)) { + if (auto *MI = dyn_cast<AnyMemIntrinsic>(Inst)) { // memcpy/memmove/memset. MemoryLocation Loc = MemoryLocation::getForDest(MI); return Loc; } - IntrinsicInst *II = dyn_cast<IntrinsicInst>(Inst); - if (!II) - return MemoryLocation(); - - switch (II->getIntrinsicID()) { - default: - return MemoryLocation(); // Unhandled intrinsic. - case Intrinsic::init_trampoline: - // FIXME: We don't know the size of the trampoline, so we can't really - // handle it here. - return MemoryLocation(II->getArgOperand(0)); - case Intrinsic::lifetime_end: { - uint64_t Len = cast<ConstantInt>(II->getArgOperand(0))->getZExtValue(); - return MemoryLocation(II->getArgOperand(1), Len); - } + if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Inst)) { + switch (II->getIntrinsicID()) { + default: + return MemoryLocation(); // Unhandled intrinsic. + case Intrinsic::init_trampoline: + return MemoryLocation(II->getArgOperand(0)); + case Intrinsic::lifetime_end: { + uint64_t Len = cast<ConstantInt>(II->getArgOperand(0))->getZExtValue(); + return MemoryLocation(II->getArgOperand(1), Len); + } + } } + if (auto CS = CallSite(Inst)) + // All the supported TLI functions so far happen to have dest as their + // first argument. + return MemoryLocation(CS.getArgument(0)); + return MemoryLocation(); } -/// Return the location read by the specified "hasMemoryWrite" instruction if -/// any. +/// Return the location read by the specified "hasAnalyzableMemoryWrite" +/// instruction if any. static MemoryLocation getLocForRead(Instruction *Inst, const TargetLibraryInfo &TLI) { - assert(hasMemoryWrite(Inst, TLI) && "Unknown instruction case"); + assert(hasAnalyzableMemoryWrite(Inst, TLI) && "Unknown instruction case"); // The only instructions that both read and write are the mem transfer // instructions (memcpy/memmove). - if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(Inst)) + if (auto *MTI = dyn_cast<AnyMemTransferInst>(Inst)) return MemoryLocation::getForSource(MTI); return MemoryLocation(); } @@ -230,7 +239,7 @@ static bool isRemovable(Instruction *I) { if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) { switch (II->getIntrinsicID()) { - default: llvm_unreachable("doesn't pass 'hasMemoryWrite' predicate"); + default: llvm_unreachable("doesn't pass 'hasAnalyzableMemoryWrite' predicate"); case Intrinsic::lifetime_end: // Never remove dead lifetime_end's, e.g. because it is followed by a // free. @@ -243,9 +252,14 @@ static bool isRemovable(Instruction *I) { case Intrinsic::memcpy: // Don't remove volatile memory intrinsics. return !cast<MemIntrinsic>(II)->isVolatile(); + case Intrinsic::memcpy_element_unordered_atomic: + case Intrinsic::memmove_element_unordered_atomic: + case Intrinsic::memset_element_unordered_atomic: + return true; } } + // note: only get here for calls with analyzable writes - i.e. libcalls if (auto CS = CallSite(I)) return CS.getInstruction()->use_empty(); @@ -264,6 +278,8 @@ static bool isShortenableAtTheEnd(Instruction *I) { default: return false; case Intrinsic::memset: case Intrinsic::memcpy: + case Intrinsic::memcpy_element_unordered_atomic: + case Intrinsic::memset_element_unordered_atomic: // Do shorten memory intrinsics. // FIXME: Add memmove if it's also safe to transform. return true; @@ -280,35 +296,27 @@ static bool isShortenableAtTheEnd(Instruction *I) { static bool isShortenableAtTheBeginning(Instruction *I) { // FIXME: Handle only memset for now. Supporting memcpy/memmove should be // easily done by offsetting the source address. - IntrinsicInst *II = dyn_cast<IntrinsicInst>(I); - return II && II->getIntrinsicID() == Intrinsic::memset; + return isa<AnyMemSetInst>(I); } /// Return the pointer that is being written to. static Value *getStoredPointerOperand(Instruction *I) { - if (StoreInst *SI = dyn_cast<StoreInst>(I)) - return SI->getPointerOperand(); - if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(I)) - return MI->getDest(); - - if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) { - switch (II->getIntrinsicID()) { - default: llvm_unreachable("Unexpected intrinsic!"); - case Intrinsic::init_trampoline: - return II->getArgOperand(0); - } - } - - CallSite CS(I); - // All the supported functions so far happen to have dest as their first - // argument. - return CS.getArgument(0); + //TODO: factor this to reuse getLocForWrite + MemoryLocation Loc = getLocForWrite(I); + assert(Loc.Ptr && + "unable to find pointer written for analyzable instruction?"); + // TODO: most APIs don't expect const Value * + return const_cast<Value*>(Loc.Ptr); } static uint64_t getPointerSize(const Value *V, const DataLayout &DL, - const TargetLibraryInfo &TLI) { + const TargetLibraryInfo &TLI, + const Function *F) { uint64_t Size; - if (getObjectSize(V, Size, DL, &TLI)) + ObjectSizeOpts Opts; + Opts.NullIsUnknownSize = NullPointerIsDefined(F); + + if (getObjectSize(V, Size, DL, &TLI, Opts)) return Size; return MemoryLocation::UnknownSize; } @@ -338,7 +346,9 @@ static OverwriteResult isOverwrite(const MemoryLocation &Later, const TargetLibraryInfo &TLI, int64_t &EarlierOff, int64_t &LaterOff, Instruction *DepWrite, - InstOverlapIntervalsTy &IOL) { + InstOverlapIntervalsTy &IOL, + AliasAnalysis &AA, + const Function *F) { // If we don't know the sizes of either access, then we can't do a comparison. if (Later.Size == MemoryLocation::UnknownSize || Earlier.Size == MemoryLocation::UnknownSize) @@ -349,7 +359,7 @@ static OverwriteResult isOverwrite(const MemoryLocation &Later, // If the start pointers are the same, we just have to compare sizes to see if // the later store was larger than the earlier store. - if (P1 == P2) { + if (P1 == P2 || AA.isMustAlias(P1, P2)) { // Make sure that the Later size is >= the Earlier size. if (Later.Size >= Earlier.Size) return OW_Complete; @@ -367,7 +377,7 @@ static OverwriteResult isOverwrite(const MemoryLocation &Later, return OW_Unknown; // If the "Later" store is to a recognizable object, get its size. - uint64_t ObjectSize = getPointerSize(UO2, DL, TLI); + uint64_t ObjectSize = getPointerSize(UO2, DL, TLI, F); if (ObjectSize != MemoryLocation::UnknownSize) if (ObjectSize == Later.Size && ObjectSize >= Earlier.Size) return OW_Complete; @@ -415,9 +425,10 @@ static OverwriteResult isOverwrite(const MemoryLocation &Later, // Insert our part of the overlap into the map. auto &IM = IOL[DepWrite]; - DEBUG(dbgs() << "DSE: Partial overwrite: Earlier [" << EarlierOff << ", " << - int64_t(EarlierOff + Earlier.Size) << ") Later [" << - LaterOff << ", " << int64_t(LaterOff + Later.Size) << ")\n"); + LLVM_DEBUG(dbgs() << "DSE: Partial overwrite: Earlier [" << EarlierOff + << ", " << int64_t(EarlierOff + Earlier.Size) + << ") Later [" << LaterOff << ", " + << int64_t(LaterOff + Later.Size) << ")\n"); // Make sure that we only insert non-overlapping intervals and combine // adjacent intervals. The intervals are stored in the map with the ending @@ -454,11 +465,11 @@ static OverwriteResult isOverwrite(const MemoryLocation &Later, ILI = IM.begin(); if (ILI->second <= EarlierOff && ILI->first >= int64_t(EarlierOff + Earlier.Size)) { - DEBUG(dbgs() << "DSE: Full overwrite from partials: Earlier [" << - EarlierOff << ", " << - int64_t(EarlierOff + Earlier.Size) << - ") Composite Later [" << - ILI->second << ", " << ILI->first << ")\n"); + LLVM_DEBUG(dbgs() << "DSE: Full overwrite from partials: Earlier [" + << EarlierOff << ", " + << int64_t(EarlierOff + Earlier.Size) + << ") Composite Later [" << ILI->second << ", " + << ILI->first << ")\n"); ++NumCompletePartials; return OW_Complete; } @@ -469,10 +480,11 @@ static OverwriteResult isOverwrite(const MemoryLocation &Later, if (EnablePartialStoreMerging && LaterOff >= EarlierOff && int64_t(EarlierOff + Earlier.Size) > LaterOff && uint64_t(LaterOff - EarlierOff) + Later.Size <= Earlier.Size) { - DEBUG(dbgs() << "DSE: Partial overwrite an earlier load [" << EarlierOff - << ", " << int64_t(EarlierOff + Earlier.Size) - << ") by a later store [" << LaterOff << ", " - << int64_t(LaterOff + Later.Size) << ")\n"); + LLVM_DEBUG(dbgs() << "DSE: Partial overwrite an earlier load [" + << EarlierOff << ", " + << int64_t(EarlierOff + Earlier.Size) + << ") by a later store [" << LaterOff << ", " + << int64_t(LaterOff + Later.Size) << ")\n"); // TODO: Maybe come up with a better name? return OW_PartialEarlierWithFullLater; } @@ -514,8 +526,8 @@ static OverwriteResult isOverwrite(const MemoryLocation &Later, /// memory region into an identical pointer) then it doesn't actually make its /// input dead in the traditional sense. Consider this case: /// -/// memcpy(A <- B) -/// memcpy(A <- A) +/// memmove(A <- B) +/// memmove(A <- A) /// /// In this case, the second store to A does not make the first store to A dead. /// The usual situation isn't an explicit A<-A store like this (which can be @@ -531,23 +543,34 @@ static bool isPossibleSelfRead(Instruction *Inst, // Self reads can only happen for instructions that read memory. Get the // location read. MemoryLocation InstReadLoc = getLocForRead(Inst, TLI); - if (!InstReadLoc.Ptr) return false; // Not a reading instruction. + if (!InstReadLoc.Ptr) + return false; // Not a reading instruction. // If the read and written loc obviously don't alias, it isn't a read. - if (AA.isNoAlias(InstReadLoc, InstStoreLoc)) return false; + if (AA.isNoAlias(InstReadLoc, InstStoreLoc)) + return false; - // Okay, 'Inst' may copy over itself. However, we can still remove a the - // DepWrite instruction if we can prove that it reads from the same location - // as Inst. This handles useful cases like: - // memcpy(A <- B) - // memcpy(A <- B) - // Here we don't know if A/B may alias, but we do know that B/B are must - // aliases, so removing the first memcpy is safe (assuming it writes <= # - // bytes as the second one. - MemoryLocation DepReadLoc = getLocForRead(DepWrite, TLI); + if (isa<AnyMemCpyInst>(Inst)) { + // LLVM's memcpy overlap semantics are not fully fleshed out (see PR11763) + // but in practice memcpy(A <- B) either means that A and B are disjoint or + // are equal (i.e. there are not partial overlaps). Given that, if we have: + // + // memcpy/memmove(A <- B) // DepWrite + // memcpy(A <- B) // Inst + // + // with Inst reading/writing a >= size than DepWrite, we can reason as + // follows: + // + // - If A == B then both the copies are no-ops, so the DepWrite can be + // removed. + // - If A != B then A and B are disjoint locations in Inst. Since + // Inst.size >= DepWrite.size A and B are disjoint in DepWrite too. + // Therefore DepWrite can be removed. + MemoryLocation DepReadLoc = getLocForRead(DepWrite, TLI); - if (DepReadLoc.Ptr && AA.isMustAlias(InstReadLoc.Ptr, DepReadLoc.Ptr)) - return false; + if (DepReadLoc.Ptr && AA.isMustAlias(InstReadLoc.Ptr, DepReadLoc.Ptr)) + return false; + } // If DepWrite doesn't read memory or if we can't prove it is a must alias, // then it can't be considered dead. @@ -650,7 +673,8 @@ static bool handleFree(CallInst *F, AliasAnalysis *AA, MD->getPointerDependencyFrom(Loc, false, InstPt->getIterator(), BB); while (Dep.isDef() || Dep.isClobber()) { Instruction *Dependency = Dep.getInst(); - if (!hasMemoryWrite(Dependency, *TLI) || !isRemovable(Dependency)) + if (!hasAnalyzableMemoryWrite(Dependency, *TLI) || + !isRemovable(Dependency)) break; Value *DepPointer = @@ -660,8 +684,9 @@ static bool handleFree(CallInst *F, AliasAnalysis *AA, if (!AA->isMustAlias(F->getArgOperand(0), DepPointer)) break; - DEBUG(dbgs() << "DSE: Dead Store to soon to be freed memory:\n DEAD: " - << *Dependency << '\n'); + LLVM_DEBUG( + dbgs() << "DSE: Dead Store to soon to be freed memory:\n DEAD: " + << *Dependency << '\n'); // DCE instructions only used to calculate that store. BasicBlock::iterator BBI(Dependency); @@ -690,7 +715,8 @@ static bool handleFree(CallInst *F, AliasAnalysis *AA, static void removeAccessedObjects(const MemoryLocation &LoadedLoc, SmallSetVector<Value *, 16> &DeadStackObjects, const DataLayout &DL, AliasAnalysis *AA, - const TargetLibraryInfo *TLI) { + const TargetLibraryInfo *TLI, + const Function *F) { const Value *UnderlyingPointer = GetUnderlyingObject(LoadedLoc.Ptr, DL); // A constant can't be in the dead pointer set. @@ -707,7 +733,7 @@ static void removeAccessedObjects(const MemoryLocation &LoadedLoc, // Remove objects that could alias LoadedLoc. DeadStackObjects.remove_if([&](Value *I) { // See if the loaded location could alias the stack location. - MemoryLocation StackLoc(I, getPointerSize(I, DL, *TLI)); + MemoryLocation StackLoc(I, getPointerSize(I, DL, *TLI, F)); return !AA->isNoAlias(StackLoc, LoadedLoc); }); } @@ -754,7 +780,7 @@ static bool handleEndBlock(BasicBlock &BB, AliasAnalysis *AA, --BBI; // If we find a store, check to see if it points into a dead stack value. - if (hasMemoryWrite(&*BBI, *TLI) && isRemovable(&*BBI)) { + if (hasAnalyzableMemoryWrite(&*BBI, *TLI) && isRemovable(&*BBI)) { // See through pointer-to-pointer bitcasts SmallVector<Value *, 4> Pointers; GetUnderlyingObjects(getStoredPointerOperand(&*BBI), Pointers, DL); @@ -770,15 +796,16 @@ static bool handleEndBlock(BasicBlock &BB, AliasAnalysis *AA, if (AllDead) { Instruction *Dead = &*BBI; - DEBUG(dbgs() << "DSE: Dead Store at End of Block:\n DEAD: " - << *Dead << "\n Objects: "; - for (SmallVectorImpl<Value *>::iterator I = Pointers.begin(), - E = Pointers.end(); I != E; ++I) { - dbgs() << **I; - if (std::next(I) != E) - dbgs() << ", "; - } - dbgs() << '\n'); + LLVM_DEBUG(dbgs() << "DSE: Dead Store at End of Block:\n DEAD: " + << *Dead << "\n Objects: "; + for (SmallVectorImpl<Value *>::iterator I = Pointers.begin(), + E = Pointers.end(); + I != E; ++I) { + dbgs() << **I; + if (std::next(I) != E) + dbgs() << ", "; + } dbgs() + << '\n'); // DCE instructions only used to calculate that store. deleteDeadInstruction(Dead, &BBI, *MD, *TLI, IOL, InstrOrdering, &DeadStackObjects); @@ -790,8 +817,8 @@ static bool handleEndBlock(BasicBlock &BB, AliasAnalysis *AA, // Remove any dead non-memory-mutating instructions. if (isInstructionTriviallyDead(&*BBI, TLI)) { - DEBUG(dbgs() << "DSE: Removing trivially dead instruction:\n DEAD: " - << *&*BBI << '\n'); + LLVM_DEBUG(dbgs() << "DSE: Removing trivially dead instruction:\n DEAD: " + << *&*BBI << '\n'); deleteDeadInstruction(&*BBI, &BBI, *MD, *TLI, IOL, InstrOrdering, &DeadStackObjects); ++NumFastOther; MadeChange = true; @@ -820,7 +847,8 @@ static bool handleEndBlock(BasicBlock &BB, AliasAnalysis *AA, // the call is live. DeadStackObjects.remove_if([&](Value *I) { // See if the call site touches the value. - return isRefSet(AA->getModRefInfo(CS, I, getPointerSize(I, DL, *TLI))); + return isRefSet(AA->getModRefInfo(CS, I, getPointerSize(I, DL, *TLI, + BB.getParent()))); }); // If all of the allocas were clobbered by the call then we're not going @@ -848,8 +876,6 @@ static bool handleEndBlock(BasicBlock &BB, AliasAnalysis *AA, LoadedLoc = MemoryLocation::get(L); } else if (VAArgInst *V = dyn_cast<VAArgInst>(BBI)) { LoadedLoc = MemoryLocation::get(V); - } else if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(BBI)) { - LoadedLoc = MemoryLocation::getForSource(MTI); } else if (!BBI->mayReadFromMemory()) { // Instruction doesn't read memory. Note that stores that weren't removed // above will hit this case. @@ -861,7 +887,7 @@ static bool handleEndBlock(BasicBlock &BB, AliasAnalysis *AA, // Remove any allocas from the DeadPointer set that are loaded, as this // makes any stores above the access live. - removeAccessedObjects(LoadedLoc, DeadStackObjects, DL, AA, TLI); + removeAccessedObjects(LoadedLoc, DeadStackObjects, DL, AA, TLI, BB.getParent()); // If all of the allocas were clobbered by the access then we're not going // to find anything else to process. @@ -881,8 +907,8 @@ static bool tryToShorten(Instruction *EarlierWrite, int64_t &EarlierOffset, // Power of 2 vector writes are probably always a bad idea to optimize // as any store/memset/memcpy is likely using vector instructions so // shortening it to not vector size is likely to be slower - MemIntrinsic *EarlierIntrinsic = cast<MemIntrinsic>(EarlierWrite); - unsigned EarlierWriteAlign = EarlierIntrinsic->getAlignment(); + auto *EarlierIntrinsic = cast<AnyMemIntrinsic>(EarlierWrite); + unsigned EarlierWriteAlign = EarlierIntrinsic->getDestAlignment(); if (!IsOverwriteEnd) LaterOffset = int64_t(LaterOffset + LaterSize); @@ -890,15 +916,23 @@ static bool tryToShorten(Instruction *EarlierWrite, int64_t &EarlierOffset, !((EarlierWriteAlign != 0) && LaterOffset % EarlierWriteAlign == 0)) return false; - DEBUG(dbgs() << "DSE: Remove Dead Store:\n OW " - << (IsOverwriteEnd ? "END" : "BEGIN") << ": " << *EarlierWrite - << "\n KILLER (offset " << LaterOffset << ", " << EarlierSize - << ")\n"); - int64_t NewLength = IsOverwriteEnd ? LaterOffset - EarlierOffset : EarlierSize - (LaterOffset - EarlierOffset); + if (auto *AMI = dyn_cast<AtomicMemIntrinsic>(EarlierWrite)) { + // When shortening an atomic memory intrinsic, the newly shortened + // length must remain an integer multiple of the element size. + const uint32_t ElementSize = AMI->getElementSizeInBytes(); + if (0 != NewLength % ElementSize) + return false; + } + + LLVM_DEBUG(dbgs() << "DSE: Remove Dead Store:\n OW " + << (IsOverwriteEnd ? "END" : "BEGIN") << ": " + << *EarlierWrite << "\n KILLER (offset " << LaterOffset + << ", " << EarlierSize << ")\n"); + Value *EarlierWriteLength = EarlierIntrinsic->getLength(); Value *TrimmedLength = ConstantInt::get(EarlierWriteLength->getType(), NewLength); @@ -966,7 +1000,7 @@ static bool removePartiallyOverlappedStores(AliasAnalysis *AA, bool Changed = false; for (auto OI : IOL) { Instruction *EarlierWrite = OI.first; - MemoryLocation Loc = getLocForWrite(EarlierWrite, *AA); + MemoryLocation Loc = getLocForWrite(EarlierWrite); assert(isRemovable(EarlierWrite) && "Expect only removable instruction"); assert(Loc.Size != MemoryLocation::UnknownSize && "Unexpected mem loc"); @@ -1002,8 +1036,9 @@ static bool eliminateNoopStore(Instruction *Inst, BasicBlock::iterator &BBI, if (SI->getPointerOperand() == DepLoad->getPointerOperand() && isRemovable(SI) && memoryIsNotModifiedBetween(DepLoad, SI, AA)) { - DEBUG(dbgs() << "DSE: Remove Store Of Load from same pointer:\n LOAD: " - << *DepLoad << "\n STORE: " << *SI << '\n'); + LLVM_DEBUG( + dbgs() << "DSE: Remove Store Of Load from same pointer:\n LOAD: " + << *DepLoad << "\n STORE: " << *SI << '\n'); deleteDeadInstruction(SI, &BBI, *MD, *TLI, IOL, InstrOrdering); ++NumRedundantStores; @@ -1019,7 +1054,7 @@ static bool eliminateNoopStore(Instruction *Inst, BasicBlock::iterator &BBI, if (UnderlyingPointer && isCallocLikeFn(UnderlyingPointer, TLI) && memoryIsNotModifiedBetween(UnderlyingPointer, SI, AA)) { - DEBUG( + LLVM_DEBUG( dbgs() << "DSE: Remove null store to the calloc'ed object:\n DEAD: " << *Inst << "\n OBJECT: " << *UnderlyingPointer << '\n'); @@ -1067,7 +1102,7 @@ static bool eliminateDeadStores(BasicBlock &BB, AliasAnalysis *AA, } // Check to see if Inst writes to memory. If not, continue. - if (!hasMemoryWrite(Inst, *TLI)) + if (!hasAnalyzableMemoryWrite(Inst, *TLI)) continue; // eliminateNoopStore will update in iterator, if necessary. @@ -1085,7 +1120,7 @@ static bool eliminateDeadStores(BasicBlock &BB, AliasAnalysis *AA, continue; // Figure out what location is being stored to. - MemoryLocation Loc = getLocForWrite(Inst, *AA); + MemoryLocation Loc = getLocForWrite(Inst); // If we didn't get a useful location, fail. if (!Loc.Ptr) @@ -1107,7 +1142,9 @@ static bool eliminateDeadStores(BasicBlock &BB, AliasAnalysis *AA, // // Find out what memory location the dependent instruction stores. Instruction *DepWrite = InstDep.getInst(); - MemoryLocation DepLoc = getLocForWrite(DepWrite, *AA); + if (!hasAnalyzableMemoryWrite(DepWrite, *TLI)) + break; + MemoryLocation DepLoc = getLocForWrite(DepWrite); // If we didn't get a useful location, or if it isn't a size, bail out. if (!DepLoc.Ptr) break; @@ -1145,12 +1182,12 @@ static bool eliminateDeadStores(BasicBlock &BB, AliasAnalysis *AA, if (isRemovable(DepWrite) && !isPossibleSelfRead(Inst, Loc, DepWrite, *TLI, *AA)) { int64_t InstWriteOffset, DepWriteOffset; - OverwriteResult OR = - isOverwrite(Loc, DepLoc, DL, *TLI, DepWriteOffset, InstWriteOffset, - DepWrite, IOL); + OverwriteResult OR = isOverwrite(Loc, DepLoc, DL, *TLI, DepWriteOffset, + InstWriteOffset, DepWrite, IOL, *AA, + BB.getParent()); if (OR == OW_Complete) { - DEBUG(dbgs() << "DSE: Remove Dead Store:\n DEAD: " - << *DepWrite << "\n KILLER: " << *Inst << '\n'); + LLVM_DEBUG(dbgs() << "DSE: Remove Dead Store:\n DEAD: " << *DepWrite + << "\n KILLER: " << *Inst << '\n'); // Delete the store and now-dead instructions that feed it. deleteDeadInstruction(DepWrite, &BBI, *MD, *TLI, IOL, &InstrOrdering); @@ -1176,7 +1213,8 @@ static bool eliminateDeadStores(BasicBlock &BB, AliasAnalysis *AA, auto *Earlier = dyn_cast<StoreInst>(DepWrite); auto *Later = dyn_cast<StoreInst>(Inst); if (Earlier && isa<ConstantInt>(Earlier->getValueOperand()) && - Later && isa<ConstantInt>(Later->getValueOperand())) { + Later && isa<ConstantInt>(Later->getValueOperand()) && + memoryIsNotModifiedBetween(Earlier, Later, AA)) { // If the store we find is: // a) partially overwritten by the store to 'Loc' // b) the later store is fully contained in the earlier one and @@ -1207,9 +1245,9 @@ static bool eliminateDeadStores(BasicBlock &BB, AliasAnalysis *AA, // store, shifted appropriately. APInt Merged = (EarlierValue & ~Mask) | (LaterValue << LShiftAmount); - DEBUG(dbgs() << "DSE: Merge Stores:\n Earlier: " << *DepWrite - << "\n Later: " << *Inst - << "\n Merged Value: " << Merged << '\n'); + LLVM_DEBUG(dbgs() << "DSE: Merge Stores:\n Earlier: " << *DepWrite + << "\n Later: " << *Inst + << "\n Merged Value: " << Merged << '\n'); auto *SI = new StoreInst( ConstantInt::get(Earlier->getValueOperand()->getType(), Merged), |
