Index: lib/Transforms/Scalar/DeadStoreElimination.cpp =================================================================== --- lib/Transforms/Scalar/DeadStoreElimination.cpp +++ lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -514,30 +514,50 @@ if (!InstDep.isDef() && !InstDep.isClobber()) continue; - // If we're storing the same value back to a pointer that we just - // loaded from, then the store can be removed. + // Check for cases where the store is redundant. if (StoreInst *SI = dyn_cast(Inst)) { + bool DeleteStore = false; + // If we're storing the same value back to a pointer that we just + // loaded from, then the store can be removed. if (LoadInst *DepLoad = dyn_cast(InstDep.getInst())) { if (SI->getPointerOperand() == DepLoad->getPointerOperand() && SI->getOperand(0) == DepLoad && isRemovable(SI)) { DEBUG(dbgs() << "DSE: Remove Store Of Load from same pointer:\n " << "LOAD: " << *DepLoad << "\n STORE: " << *SI << '\n'); + DeleteStore = true; + } + } - // DeleteDeadInstruction can delete the current instruction. Save BBI - // in case we need it. - WeakVH NextInst(BBI); - - DeleteDeadInstruction(SI, *MD, TLI); - - if (!NextInst) // Next instruction deleted. - BBI = BB.begin(); - else if (BBI != BB.begin()) // Revisit this instruction if possible. - --BBI; - ++NumFastStores; - MadeChange = true; - continue; + // If we find a store to memory which was defined by calloc + // we can remove the store if the value being stored is a + // constant zero (since calloc initialized the memory to + // that same value) or the store is undefined (if out of + // bounds). + if (isCallocLikeFn(InstDep.getInst(), TLI) && isRemovable(SI)) { + Value* V = SI->getValueOperand(); + if (isa(V) && cast(V)->isNullValue()) { + DEBUG(dbgs() << "DSE: Remove Store Of Zero to Calloc:\n " + << "CALLOC: " << *InstDep.getInst() << "\n" + << "STORE: " << *SI << '\n'); + DeleteStore = true; } } + + if (DeleteStore) { + // DeleteDeadInstruction can delete the current instruction. Save BBI + // in case we need it. + WeakVH NextInst(BBI); + + DeleteDeadInstruction(SI, *MD, TLI); + + if (!NextInst) // Next instruction deleted. + BBI = BB.begin(); + else if (BBI != BB.begin()) // Revisit this instruction if possible. + --BBI; + ++NumFastStores; + MadeChange = true; + continue; + } } // Figure out what location is being stored to. Index: test/Transforms/DeadStoreElimination/calloc-store.ll =================================================================== --- /dev/null +++ test/Transforms/DeadStoreElimination/calloc-store.ll @@ -0,0 +1,17 @@ +; RUN: opt < %s -basicaa -dse -S | FileCheck %s + +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" + +; Function Attrs: nounwind +declare noalias i8* @calloc(i64, i64) + +; Function Attrs: nounwind uwtable +define noalias i32* @test_store() { +; CHECK-LABEL: test_store + %1 = tail call noalias i8* @calloc(i64 1, i64 4) + %2 = bitcast i8* %1 to i32* + ; This store is dead and should be removed + store i32 0, i32* %2, align 4 +; CHECK-NOT: store i32 0, i32* %2, align 4 + ret i32* %2 +}