From c303463dcceb6a3b15e6f4d11d7c31c1ac2ce276 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Tue, 25 Sep 2012 10:03:40 +0000 Subject: [PATCH] Fix a case where SROA did not correctly detect dead PHI or selects due to chains or cycles between PHIs and/or selects. Also add a couple of really nice test cases reduced from Kostya's reports in PR13905 and PR13906. Both are fixed by this patch. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@164596 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/SROA.cpp | 15 ++++++--- test/Transforms/SROA/phi-and-select.ll | 45 ++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/lib/Transforms/Scalar/SROA.cpp b/lib/Transforms/Scalar/SROA.cpp index dbda6270725..b3e63ae355d 100644 --- a/lib/Transforms/Scalar/SROA.cpp +++ b/lib/Transforms/Scalar/SROA.cpp @@ -522,8 +522,10 @@ private: void insertUse(Instruction &I, int64_t Offset, uint64_t Size, bool IsSplittable = false) { - // Completely skip uses which don't overlap the allocation. - if ((Offset >= 0 && (uint64_t)Offset >= AllocSize) || + // Completely skip uses which have a zero size or don't overlap the + // allocation. + if (Size == 0 || + (Offset >= 0 && (uint64_t)Offset >= AllocSize) || (Offset < 0 && (uint64_t)-Offset >= Size)) { DEBUG(dbgs() << "WARNING: Ignoring " << Size << " byte use @" << Offset << " which starts past the end of the " << AllocSize @@ -697,6 +699,9 @@ private: SmallVector, 4> Uses; Visited.insert(Root); Uses.push_back(std::make_pair(cast(*U), Root)); + // If there are no loads or stores, the access is dead. We mark that as + // a size zero access. + Size = 0; do { Instruction *I, *UsedI; llvm::tie(UsedI, I) = Uses.pop_back_val(); @@ -824,9 +829,9 @@ private: } void insertUse(Instruction &User, int64_t Offset, uint64_t Size) { - // If the use extends outside of the allocation, record it as a dead use - // for elimination later. - if ((uint64_t)Offset >= AllocSize || + // If the use has a zero size or extends outside of the allocation, record + // it as a dead use for elimination later. + if (Size == 0 || (uint64_t)Offset >= AllocSize || (Offset < 0 && (uint64_t)-Offset >= Size)) return markAsDead(User); diff --git a/test/Transforms/SROA/phi-and-select.ll b/test/Transforms/SROA/phi-and-select.ll index ad0c55748dd..b55d917f728 100644 --- a/test/Transforms/SROA/phi-and-select.ll +++ b/test/Transforms/SROA/phi-and-select.ll @@ -327,3 +327,48 @@ exit: %load = load i32* %a ret i32 %load } + +define i32 @PR13905() { +; Check a pattern where we have a chain of dead phi nodes to ensure they are +; deleted and promotion can proceed. +; CHECK: @PR13905 +; CHECK-NOT: alloca i32 +; CHECK: ret i32 undef + +entry: + %h = alloca i32 + store i32 0, i32* %h + br i1 undef, label %loop1, label %exit + +loop1: + %phi1 = phi i32* [ null, %entry ], [ %h, %loop1 ], [ %h, %loop2 ] + br i1 undef, label %loop1, label %loop2 + +loop2: + br i1 undef, label %loop1, label %exit + +exit: + %phi2 = phi i32* [ %phi1, %loop2 ], [ null, %entry ] + ret i32 undef +} + +define i32 @PR13906() { +; Another pattern which can lead to crashes due to failing to clear out dead +; PHI nodes or select nodes. This triggers subtly differently from the above +; cases because the PHI node is (recursively) alive, but the select is dead. +; CHECK: @PR13906 +; CHECK-NOT: alloca + +entry: + %c = alloca i32 + store i32 0, i32* %c + br label %for.cond + +for.cond: + %d.0 = phi i32* [ undef, %entry ], [ %c, %if.then ], [ %d.0, %for.cond ] + br i1 undef, label %if.then, label %for.cond + +if.then: + %tmpcast.d.0 = select i1 undef, i32* %c, i32* %d.0 + br label %for.cond +}