diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp --- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -1102,7 +1102,7 @@ return I.first->second; } - Optional getLocForWriteEx(Instruction *I) const { + Optional getLocForWriteEx(Instruction *I) { if (!I->mayWriteToMemory()) return None; @@ -1358,6 +1358,7 @@ Instruction *KillingI = KillingDef->getMemoryInst(); LLVM_DEBUG(dbgs() << " trying to get dominating access\n"); + bool CanOptimize = KillingDef->getDefiningAccess() == StartAccess; // Find the next clobbering Mod access for DefLoc, starting at StartAccess. Optional CurrentLoc; for (;; Current = cast(Current)->getDefiningAccess()) { @@ -1399,8 +1400,11 @@ Instruction *CurrentI = CurrentDef->getMemoryInst(); if (canSkipDef(CurrentDef, !isInvisibleToCallerBeforeRet(KillingUndObj), - TLI)) + TLI)) { + + CanOptimize &= !isa(CurrentDef->getMemoryInst()); continue; + } // Before we try to remove anything, check for any extra throwing // instructions that block us from DSEing @@ -1436,13 +1440,17 @@ // If Current cannot be analyzed or is not removable, check the next // candidate. - if (!hasAnalyzableMemoryWrite(CurrentI, TLI) || !isRemovable(CurrentI)) + if (!hasAnalyzableMemoryWrite(CurrentI, TLI) || !isRemovable(CurrentI)) { + CanOptimize = false; continue; + } // If Current does not have an analyzable write location, skip it CurrentLoc = getLocForWriteEx(CurrentI); - if (!CurrentLoc) + if (!CurrentLoc) { + CanOptimize = false; continue; + } // AliasAnalysis does not account for loops. Limit elimination to // candidates for which we can guarantee they always store to the same @@ -1450,6 +1458,7 @@ if (!isGuaranteedLoopIndependent(CurrentI, KillingI, *CurrentLoc)) { LLVM_DEBUG(dbgs() << " ... not guaranteed loop independent\n"); WalkerStepLimit -= 1; + CanOptimize = false; continue; } @@ -1457,13 +1466,23 @@ // If the killing def is a memory terminator (e.g. lifetime.end), check // the next candidate if the current Current does not write the same // underlying object as the terminator. - if (!isMemTerminator(*CurrentLoc, CurrentI, KillingI)) + if (!isMemTerminator(*CurrentLoc, CurrentI, KillingI)) { + CanOptimize = false; continue; + } } else { int64_t KillingOffset = 0; int64_t DeadOffset = 0; auto OR = isOverwrite(KillingI, CurrentI, KillingLoc, *CurrentLoc, KillingOffset, DeadOffset); + if (CanOptimize) { + if (OR == OW_Complete || OR == OW_MaybePartial) + KillingDef->setOptimized(CurrentDef); + if (OR != OW_None) { + CanOptimize = false; + } + } + // If Current does not write to the same object as KillingDef, check // the next candidate. if (OR == OW_Unknown || OR == OW_None)