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 @@ -2367,6 +2367,46 @@ return false; } + bool eliminateDeadStoresOfExisitingValues() { + bool MadeChange = false; + LLVM_DEBUG(dbgs() << "Trying to eliminate MemoryDefs that write the " + "already exisiting value\n"); + for (int I = MemDefs.size() - 1; I >= 0; I--) { + MemoryDef *Def = MemDefs[I]; + SmallVector WorkList; + SmallPtrSet Visited; + auto PushMemUses = [&WorkList, &Visited](MemoryAccess *Acc) { + if (!Visited.insert(Acc).second) + return; + for (Use &U : Acc->uses()) + WorkList.push_back(cast(U.getUser())); + }; + PushMemUses(Def); + for (unsigned I = 0; I < WorkList.size(); I++) { + if (WorkList.size() >= MemorySSAScanLimit) { + LLVM_DEBUG(dbgs() << " ... hit exploration limit.\n"); + return false; + } + MemoryAccess *UseAccess = WorkList[I]; + if (isa(UseAccess)) + continue; + + Instruction *UseInst = cast(UseAccess)->getMemoryInst(); + if (MemoryDef *UseDef = dyn_cast(UseAccess)) { + MemoryAccess *tmp = UseDef->getDefiningAccess(); + Instruction *tmpi = cast(tmp)->getMemoryInst(); + if (tmpi->isIdenticalTo(UseInst)) { + deleteDeadInstruction(UseInst); + MadeChange = true; + } else { + PushMemUses(UseDef); + } + } + } + } + return MadeChange; + } + /// Eliminate writes to objects that are not visible in the caller and are not /// accessed before returning from the function. bool eliminateDeadWritesAtEndOfFunction() { @@ -2632,7 +2672,7 @@ } } } - + MadeChange |= State.eliminateDeadStoresOfExisitingValues(); if (EnablePartialOverwriteTracking) for (auto &KV : State.IOLs) MadeChange |= removePartiallyOverlappedStores(State.DL, KV.second, TLI);