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 @@ -1861,8 +1861,16 @@ // We are searching for the definition of the store's destination. // So, if that is the same definition as the load, then this is a // noop. Otherwise, fail. - if (LoadAccess != Current) + if (LoadAccess != Current) { + auto *CurrentStoreI = + dyn_cast(cast(Current)->getMemoryInst()); + if (CurrentStoreI && CurrentStoreI->getOperand(0) == LoadI) { + // This is a potentially clobbering here, but it writes the same value, + // so we can safely ignore it. + continue; + } return false; + } } return true; } 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 @@ -612,12 +612,10 @@ ; CHECK-LABEL: @pr49927( ; CHECK-NEXT: [[V:%.*]] = load i32, i32* [[P:%.*]], align 4 ; CHECK-NEXT: store i32 [[V]], i32* [[Q:%.*]], align 4 -; CHECK-NEXT: store i32 [[V]], i32* [[P]], align 4 ; CHECK-NEXT: ret void ; %v = load i32, i32* %p, align 4 store i32 %v, i32* %q, align 4 - ; FIXME: this store can be eliminated store i32 %v, i32* %p, align 4 ret void }