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 @@ -2361,6 +2361,40 @@ return false; } + /// Eliminates writes to variables where the value that is being written + /// is already stored in the variable + 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]; + if (SkipStores.find(Def) != SkipStores.end() || + !isRemovable(Def->getMemoryInst())) + continue; + MemoryAccess *DefAccess = dyn_cast(Def); + if (!DefAccess || isa(DefAccess)) + continue; + Instruction *DefInst = cast(DefAccess)->getMemoryInst(); + if (!DefInst) + continue; + for (auto UI = DefAccess->use_begin(), IE = DefAccess->use_end(); + UI != IE;) { + MemoryAccess *UseAccess = cast((UI++)->getUser()); + if (MemoryDef *UseDef = dyn_cast_or_null(UseAccess)) { + Instruction *UseInst = UseDef->getMemoryInst(); + if (!UseInst) + continue; + if (UseInst->isIdenticalTo(DefInst)) { + deleteDeadInstruction(UseInst); + MadeChange = true; + } + } + } + } + return MadeChange; + } + /// Eliminate writes to objects that are not visible in the caller and are not /// accessed before returning from the function. bool eliminateDeadWritesAtEndOfFunction() { @@ -2630,6 +2664,8 @@ } } + MadeChange |= State.eliminateDeadStoresOfExisitingValues(); + if (EnablePartialOverwriteTracking) for (auto &KV : State.IOLs) MadeChange |= removePartiallyOverlappedStores(State.DL, KV.second, TLI); diff --git a/llvm/test/Transforms/DeadStoreElimination/MSSA/simple.ll b/llvm/test/Transforms/DeadStoreElimination/MSSA/simple.ll --- a/llvm/test/Transforms/DeadStoreElimination/MSSA/simple.ll +++ b/llvm/test/Transforms/DeadStoreElimination/MSSA/simple.ll @@ -509,7 +509,6 @@ define void @test36(i8* %P, i8* %Q) { ; CHECK-LABEL: @test36( ; CHECK-NEXT: tail call void @llvm.memmove.p0i8.p0i8.i64(i8* [[P:%.*]], i8* [[Q:%.*]], i64 12, i1 false) -; CHECK-NEXT: tail call void @llvm.memmove.p0i8.p0i8.i64(i8* [[P]], i8* [[Q]], i64 12, i1 false) ; CHECK-NEXT: ret void ; @@ -521,7 +520,6 @@ define void @test36_atomic(i8* %P, i8* %Q) { ; CHECK-LABEL: @test36_atomic( ; CHECK-NEXT: tail call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 [[P:%.*]], i8* align 1 [[Q:%.*]], i64 12, i32 1) -; CHECK-NEXT: tail call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 [[P]], i8* align 1 [[Q]], i64 12, i32 1) ; CHECK-NEXT: ret void ; diff --git a/llvm/test/Transforms/DeadStoreElimination/MSSA/stores-of-existing-values.ll b/llvm/test/Transforms/DeadStoreElimination/MSSA/stores-of-existing-values.ll --- a/llvm/test/Transforms/DeadStoreElimination/MSSA/stores-of-existing-values.ll +++ b/llvm/test/Transforms/DeadStoreElimination/MSSA/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: @@ -54,7 +53,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 +179,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 +213,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 +264,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