Index: llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp =================================================================== --- llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -2383,6 +2383,44 @@ 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]; + MemoryAccess *DefAccess = dyn_cast(Def); + if (DefAccess == NULL) + continue; + if (isa(DefAccess)) + continue; + Instruction *DefInst = cast(DefAccess)->getMemoryInst(); + if (DefInst == NULL) { + continue; + } + for (Use &U : DefAccess->uses()) { + MemoryAccess *UseAccess = cast(U.getUser()); + if (MemoryDef *UseDef = dyn_cast(UseAccess)) { + MemoryAccess *UseDefAccess = UseDef->getDefiningAccess(); + if (UseDefAccess == NULL) { + continue; + } + Instruction *UseInst = cast(UseDefAccess)->getMemoryInst(); + if (UseInst == NULL) { + continue; + } + if (UseInst->isIdenticalTo(DefInst)) { + deleteDeadInstruction(DefInst); + 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() { @@ -2653,6 +2691,8 @@ } } + MadeChange |= State.eliminateDeadStoresOfExisitingValues(); + if (EnablePartialOverwriteTracking) for (auto &KV : State.IOLs) MadeChange |= removePartiallyOverlappedStores(State.DL, KV.second, TLI); Index: llvm/test/Transforms/DeadStoreElimination/MSSA/pr16520.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/DeadStoreElimination/MSSA/pr16520.ll @@ -0,0 +1,37 @@ +; RUN: opt -basic-aa -dse -S < %s | FileCheck %s +; PR16520 + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @_Z1fbRb(i1 zeroext %b, i8* nocapture %r) { +; CHECK-LABEL: @_Z1fbRb( +; CHECK-NEXT: entry: +; CHECK-NEXT: store i8 1, i8* %r, align 1 +; CHECK-NEXT: br i1 %b, label %if.then, label %if.else +; CHECK: if.then: ; preds = %entry +; CHECK-NEXT: tail call void @_Z1gv() +; CHECK-NEXT: br label %if.end +; CHECK: if.else: ; preds = %entry +; CHECK-NEXT: tail call void @_Z1hv() +; CHECK-NEXT: br label %if.end +; CHECK: if.end: ; preds = %if.else, %if.then +; CHECK-NEXT: ret void +; CHECK: declare void @_Z1gv() +; CHECK: declare void @_Z1hv() +; +entry: + store i8 1, i8* %r, align 1 + br i1 %b, label %if.then, label %if.else +if.then: ; preds = %entry + store i8 1, i8* %r, align 1 + tail call void @_Z1gv() + br label %if.end +if.else: ; preds = %entry + tail call void @_Z1hv() + br label %if.end +if.end: ; preds = %if.else, %if.then + ret void +} +declare void @_Z1gv() +declare void @_Z1hv()