From: Jun Bum Lim Date: Thu, 30 Jun 2016 15:32:20 +0000 (+0000) Subject: [DSE] Fix bug in partial overwrite tracking X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fe4360eba5a19d89a1d8ebdd745380586464fc76;p=llvm [DSE] Fix bug in partial overwrite tracking Summary: Found cases where DSE incorrectly add partially-overwritten intervals. Please see the test case for details. Reviewers: mcrosier, eeckstein, hfinkel Subscribers: mcrosier, llvm-commits Differential Revision: http://reviews.llvm.org/D21859 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@274237 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/Scalar/DeadStoreElimination.cpp b/lib/Transforms/Scalar/DeadStoreElimination.cpp index 595a556b505..6b648ee23cc 100644 --- a/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -385,18 +385,25 @@ static OverwriteResult isOverwrite(const MemoryLocation &Later, // Find any intervals ending at, or after, LaterIntStart which start // before LaterIntEnd. auto ILI = IM.lower_bound(LaterIntStart); - if (ILI != IM.end() && ILI->second < LaterIntEnd) { - // This existing interval ends in the middle of - // [LaterIntStart, LaterIntEnd), erase it adjusting our start. + if (ILI != IM.end() && ILI->second <= LaterIntEnd) { + // This existing interval is overlapped with the current store somewhere + // in [LaterIntStart, LaterIntEnd]. Merge them by erasing the existing + // intervals and adjusting our start and end. LaterIntStart = std::min(LaterIntStart, ILI->second); LaterIntEnd = std::max(LaterIntEnd, ILI->first); ILI = IM.erase(ILI); - while (ILI != IM.end() && ILI->first <= LaterIntEnd) - ILI = IM.erase(ILI); - - if (ILI != IM.end() && ILI->second < LaterIntEnd) + // Continue erasing and adjusting our end in case other previous + // intervals are also overlapped with the current store. + // + // |--- ealier 1 ---| |--- ealier 2 ---| + // |------- later---------| + // + while (ILI != IM.end() && ILI->second <= LaterIntEnd) { + assert(ILI->second > LaterIntStart && "Unexpected interval"); LaterIntEnd = std::max(LaterIntEnd, ILI->first); + ILI = IM.erase(ILI); + } } IM[LaterIntEnd] = LaterIntStart; diff --git a/test/Transforms/DeadStoreElimination/combined-partial-overwrites.ll b/test/Transforms/DeadStoreElimination/combined-partial-overwrites.ll index bd639f629c8..cb015b2d1ce 100644 --- a/test/Transforms/DeadStoreElimination/combined-partial-overwrites.ll +++ b/test/Transforms/DeadStoreElimination/combined-partial-overwrites.ll @@ -198,3 +198,42 @@ entry: ret i8 0 } +define signext i8 @test6(i32 *%ptr) { +entry: +; CHECK-LABEL: @test6 + + store i32 0, i32* %ptr + + %bptr = bitcast i32* %ptr to i16* + %bptr1 = getelementptr inbounds i16, i16* %bptr, i64 0 + %bptr2 = getelementptr inbounds i16, i16* %bptr, i64 1 + + store i16 1456, i16* %bptr2, align 1 + store i16 65535, i16* %bptr1, align 1 + +; CHECK-NOT: store i32 0, i32* %ptr + + ret i8 0 +} + +define signext i8 @test7(i64 *%ptr) { +entry: +; CHECK-LABEL: @test7 + + store i64 0, i64* %ptr + + %bptr = bitcast i64* %ptr to i16* + %bptr1 = getelementptr inbounds i16, i16* %bptr, i64 0 + %bptr2 = getelementptr inbounds i16, i16* %bptr, i64 1 + %bptr3 = getelementptr inbounds i16, i16* %bptr, i64 2 + %bptr4 = getelementptr inbounds i16, i16* %bptr, i64 3 + + store i16 1346, i16* %bptr1, align 1 + store i16 1756, i16* %bptr3, align 1 + store i16 1456, i16* %bptr2, align 1 + store i16 5656, i16* %bptr4, align 1 + +; CHECK-NOT: store i64 0, i64* %ptr + + ret i8 0 +}