From ef93f7a11c347534ac768ec8bbbed64cd20c41d2 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Mon, 28 Dec 2020 23:30:38 +0300 Subject: [PATCH] [SimplifyCFG] FoldBranchToCommonDest: gracefully handle unreachable code () MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We might be dealing with an unreachable code, so the bonus instruction we clone might be self-referencing. There is a sanity check that all uses of bonus instructions that are not in the original block with said bonus instructions are PHI nodes, and that is obviously not the case for self-referencing instructions.. So if we find such an use, just rewrite it. Thanks to Mikael Holmén for the reproducer! Fixes https://bugs.llvm.org/show_bug.cgi?id=48450#c8 --- llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 7 +++ .../SimplifyCFG/fold-branch-to-common-dest.ll | 54 +++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index 67e0d2ac9cd7..7d5f6daba7b2 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -2986,6 +2986,13 @@ bool llvm::FoldBranchToCommonDest(BranchInst *BI, DomTreeUpdater *DTU, "Non-external users are never PHI instructions."); return false; } + if (User->getParent() == PredBlock) { + // The "exteral" use is in the block into which we just cloned the + // bonus instruction. This means two things: 1. we are in an + // unreachable block 2. the instruction is self-referencing. + // So let's just rewrite it... + return true; + } (void)BI; assert(isa(User) && "All external users must be PHI's."); auto *PN = cast(User); diff --git a/llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest.ll b/llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest.ll index 3a70241fed16..7455cc691cf9 100644 --- a/llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest.ll +++ b/llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest.ll @@ -836,3 +836,57 @@ for.bodythread-pre-split.loopback: if.end.loopexit: ret void } + +@f.b = external global i16, align 1 +define void @pr48450_3() { +; CHECK-LABEL: @pr48450_3( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_COND1:%.*]] +; CHECK: for.cond1: +; CHECK-NEXT: [[V:%.*]] = load i16, i16* @f.b, align 1 +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[V]], 1 +; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) +; CHECK-NEXT: br label [[FOR_COND1]] +; +entry: + br label %for.cond1 + +for.cond1: + %v = load i16, i16* @f.b, align 1 + %cmp = icmp slt i16 %v, 1 + br i1 %cmp, label %for.body, label %for.end + +for.body: + br label %for.cond1 + +for.end: + %tobool = icmp ne i16 %v, 0 + br i1 %tobool, label %if.then, label %if.end + +if.then: + unreachable + +if.end: + br label %for.cond2 + +for.cond2: + %c.0 = phi i16 [ undef, %if.end ], [ %inc, %if.end7 ] + %cmp3 = icmp slt i16 %c.0, 1 + br i1 %cmp3, label %for.body4, label %for.cond.cleanup + +for.cond.cleanup: + br label %cleanup + +for.body4: + br i1 undef, label %if.then6, label %if.end7 + +if.then6: + br label %cleanup + +if.end7: + %inc = add nsw i16 %c.0, 1 + br label %for.cond2 + +cleanup: + unreachable +}