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 @@ -1941,6 +1941,32 @@ return false; } + + /// Eliminates writes to locations where the value that is being written + /// is already stored at the same location. + bool eliminateRedundantStoresOfExisitingValues() { + auto MadeChange = false; + LLVM_DEBUG(dbgs() << "Trying to eliminate MemoryDefs that write the " + "already exisiting value\n"); + for (auto *Def : MemDefs) { + if (SkipStores.contains(Def) || MSSA.isLiveOnEntryDef(Def) || + !isRemovable(Def->getMemoryInst())) + continue; + auto UpperDef = dyn_cast_or_null(Def->getDefiningAccess()); + if (!UpperDef || MSSA.isLiveOnEntryDef(UpperDef)) + continue; + auto *DefInst = Def->getMemoryInst(); + auto *UpperInst = UpperDef->getMemoryInst(); + auto MaybeUpperLoc = getLocForWriteEx(UpperInst); + if (!MaybeUpperLoc || !DefInst->isIdenticalTo(UpperInst) || + isReadClobber(*MaybeUpperLoc, DefInst)) + continue; + deleteDeadInstruction(DefInst); + NumRedundantStores++; + MadeChange = true; + } + return MadeChange; + } }; static bool eliminateDeadStores(Function &F, AliasAnalysis &AA, MemorySSA &MSSA, @@ -2104,6 +2130,7 @@ } } + MadeChange |= State.eliminateRedundantStoresOfExisitingValues(); if (EnablePartialOverwriteTracking) for (auto &KV : State.IOLs) MadeChange |= removePartiallyOverlappedStores(State.DL, KV.second, TLI); diff --git a/llvm/test/Transforms/DeadStoreElimination/stores-of-existing-values.ll b/llvm/test/Transforms/DeadStoreElimination/stores-of-existing-values.ll --- a/llvm/test/Transforms/DeadStoreElimination/stores-of-existing-values.ll +++ b/llvm/test/Transforms/DeadStoreElimination/stores-of-existing-values.ll @@ -11,7 +11,6 @@ ; CHECK-NEXT: store i8 1, i8* [[R:%.*]], align 1 ; CHECK-NEXT: br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] ; CHECK: if.then: -; CHECK-NEXT: store i8 1, i8* [[R]], align 1 ; CHECK-NEXT: tail call void @fn_mayread_or_clobber() ; CHECK-NEXT: br label [[IF_END:%.*]] ; CHECK: if.else: @@ -38,8 +37,6 @@ } declare void @fn_mayread_or_clobber() - - declare void @fn_readonly() readonly define void @test2(i1 %b, i8* nocapture %r) { @@ -54,7 +51,6 @@ ; CHECK-NEXT: tail call void @fn_readonly() ; CHECK-NEXT: br label [[IF_END]] ; CHECK: if.end: -; CHECK-NEXT: store i8 1, i8* [[R]], align 1 ; CHECK-NEXT: ret void ; entry: @@ -181,7 +177,6 @@ ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond() ; CHECK-NEXT: br i1 [[C1]], label [[FOR_BODY:%.*]], label [[END:%.*]] ; CHECK: for.body: -; CHECK-NEXT: store i32 1, i32* [[P]], align 4 ; CHECK-NEXT: [[LV:%.*]] = load i32, i32* [[P]], align 4 ; CHECK-NEXT: br label [[FOR_HEADER]] ; CHECK: end: @@ -216,7 +211,6 @@ ; CHECK: bb2: ; CHECK-NEXT: ret void ; CHECK: bb3: -; CHECK-NEXT: store i32 0, i32* [[P]], align 4 ; CHECK-NEXT: ret void ; store i32 0, i32* %P @@ -268,7 +262,6 @@ ; CHECK-NEXT: call void @fn_mayread_or_clobber() ; CHECK-NEXT: ret void ; CHECK: bb3: -; CHECK-NEXT: store i32 0, i32* [[P]], align 4 ; CHECK-NEXT: ret void ; store i32 0, i32* %P