diff --git a/lib/Transforms/Scalar/DeadStoreElimination.cpp b/lib/Transforms/Scalar/DeadStoreElimination.cpp index 78004595ece..f6b2999c294 100644 --- a/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -19,6 +19,7 @@ #include "llvm/Transforms/Scalar.h" #include "llvm/Constants.h" #include "llvm/Function.h" +#include "llvm/GlobalVariable.h" #include "llvm/Instructions.h" #include "llvm/IntrinsicInst.h" #include "llvm/Pass.h" @@ -255,6 +256,17 @@ static uint64_t getPointerSize(Value *V, AliasAnalysis &AA) { return TD->getTypeAllocSize(PT->getElementType()); } +/// isObjectPointerWithTrustworthySize - Return true if the specified Value* is +/// pointing to an object with a pointer size we can trust. +static bool isObjectPointerWithTrustworthySize(const Value *V) { + if (const AllocaInst *AI = dyn_cast(V)) + return !AI->isArrayAllocation(); + if (const GlobalVariable *GV = dyn_cast(V)) + return !GV->isWeakForLinker(); + if (const Argument *A = dyn_cast(V)) + return A->hasByValAttr(); + return false; +} /// isCompleteOverwrite - Return true if a store to the 'Later' location /// completely overwrites a store to the 'Earlier' location. @@ -289,12 +301,29 @@ static bool isCompleteOverwrite(const AliasAnalysis::Location &Later, // larger than the earlier one. if (Later.Size == AliasAnalysis::UnknownSize || Earlier.Size == AliasAnalysis::UnknownSize || - Later.Size <= Earlier.Size || - AA.getTargetData() == 0) + Later.Size <= Earlier.Size || AA.getTargetData() == 0) return false; + // Check to see if the later store is to the entire object (either a global, + // an alloca, or a byval argument). If so, then it clearly overwrites any + // other store to the same object. const TargetData &TD = *AA.getTargetData(); + const Value *UO1 = P1->getUnderlyingObject(), *UO2 = P2->getUnderlyingObject(); + + // If we can't resolve the same pointers to the same object, then we can't + // analyze them at all. + if (UO1 != UO2) + return false; + + // If the "Later" store is to a recognizable object, get its size. + if (isObjectPointerWithTrustworthySize(UO2)) { + uint64_t ObjectSize = + TD.getTypeAllocSize(cast(UO2->getType())->getElementType()); + if (ObjectSize == Later.Size) + return true; + } + // Okay, we have stores to two completely different pointers. Try to // decompose the pointer into a "base + constant_offset" form. If the base // pointers are equal, then we can reason about the two stores. diff --git a/test/Transforms/DeadStoreElimination/PartialStore.ll b/test/Transforms/DeadStoreElimination/PartialStore.ll index 999229885dd..7ac1e0844ed 100644 --- a/test/Transforms/DeadStoreElimination/PartialStore.ll +++ b/test/Transforms/DeadStoreElimination/PartialStore.ll @@ -52,3 +52,20 @@ define void @test4(i8* %P) { store double 0.0, double* %Q ret void } + +; PR8657 +declare void @test5a(i32*) +define void @test5(i32 %i) nounwind ssp { + %A = alloca i32 + %B = bitcast i32* %A to i8* + %C = getelementptr i8* %B, i32 %i + store i8 10, i8* %C ;; Dead store to variable index. + store i32 20, i32* %A + + call void @test5a(i32* %A) + ret void +; CHECK: @test5( +; CHECK-NEXT: alloca +; CHECK-NEXT: store i32 20 +; CHECK-NEXT: call void @test5a +}