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 @@ -483,12 +483,6 @@ if (UO1 != UO2) return OW_Unknown; - // If the "Later" store is to a recognizable object, get its size. - uint64_t ObjectSize = getPointerSize(UO2, DL, TLI, F); - if (ObjectSize != MemoryLocation::UnknownSize) - if (ObjectSize == LaterSize && ObjectSize >= EarlierSize) - return OW_Complete; - // 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. @@ -497,6 +491,22 @@ const Value *BP1 = GetPointerBaseWithConstantOffset(P1, EarlierOff, DL); const Value *BP2 = GetPointerBaseWithConstantOffset(P2, LaterOff, DL); + // If the "Later" store is to a recognizable object, get its size. + uint64_t ObjectSize = getPointerSize(UO2, DL, TLI, F); + if (ObjectSize != MemoryLocation::UnknownSize) + if (ObjectSize == LaterSize && ObjectSize >= EarlierSize) + // If both writes are in the same basic block, there is no need to check + // if the writes are fully inside the underlying object, because the + // out-of-bounds access is guaranteed to execute. Note that the case when + // the block is exited early due to unwinding is already handled + // separately by DSE, by considering the unwinding calls as clobbers. If + // the writes are not in the same block, make sure they are inside the + // underlying object. + if (EarlierI->getParent() == LaterI->getParent() || + (EarlierOff + EarlierSize <= ObjectSize && + LaterOff + LaterSize <= ObjectSize)) + return OW_Complete; + // If the base pointers still differ, we have two completely different stores. if (BP1 != BP2) return OW_Unknown; diff --git a/llvm/test/Transforms/DeadStoreElimination/MSSA/out-of-bounds-stores.ll b/llvm/test/Transforms/DeadStoreElimination/MSSA/out-of-bounds-stores.ll --- a/llvm/test/Transforms/DeadStoreElimination/MSSA/out-of-bounds-stores.ll +++ b/llvm/test/Transforms/DeadStoreElimination/MSSA/out-of-bounds-stores.ll @@ -36,6 +36,8 @@ ; CHECK-NEXT: [[D:%.*]] = alloca [1 x i32], align 4 ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [1 x i32], [1 x i32]* [[D]], i64 0, i64 0 +; CHECK-NEXT: store i32 10, i32* [[ARRAYIDX]], align 4 ; CHECK-NEXT: br label [[FOR_INC:%.*]] ; CHECK: for.inc: ; CHECK-NEXT: br i1 [[C:%.*]], label [[FOR_BODY_1:%.*]], label [[FOR_END:%.*]]