From c6cb2e4584f87fa464c75dd4c2e158589a28cb2f Mon Sep 17 00:00:00 2001 From: Jonas Paulsson Date: Wed, 4 Mar 2020 17:11:40 +0100 Subject: [PATCH] [SimplifyCFG] Skip merging return blocks if it would break a CallBr. SimplifyCFG should not merge empty return blocks and leave a CallBr behind with a duplicated destination since the verifier will then trigger an assert. This patch checks for this case and avoids the transformation. CodeGenPrepare has a similar check which also has a FIXME comment about why this is needed. It seems perhaps better if these two passes would eventually instead update the CallBr instruction instead of just checking and avoiding. This fixes https://bugs.llvm.org/show_bug.cgi?id=45062. Review: Craig Topper Differential Revision: https://reviews.llvm.org/D75620 --- .../lib/Transforms/Scalar/SimplifyCFGPass.cpp | 15 ++++++++++ .../SimplifyCFG/callbr-destinations.ll | 28 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 llvm/test/Transforms/SimplifyCFG/callbr-destinations.ll diff --git a/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp b/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp index 623a8b711ed895..ac53ff33e83624 100644 --- a/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp +++ b/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp @@ -104,6 +104,21 @@ static bool mergeEmptyReturnBlocks(Function &F) { continue; } + // Skip merging if this would result in a CallBr instruction with a + // duplicate destination. FIXME: See note in CodeGenPrepare.cpp. + bool SkipCallBr = false; + for (pred_iterator PI = pred_begin(&BB), E = pred_end(&BB); + PI != E && !SkipCallBr; ++PI) { + if (auto *CBI = dyn_cast((*PI)->getTerminator())) + for (unsigned i = 0, e = CBI->getNumSuccessors(); i != e; ++i) + if (RetBlock == CBI->getSuccessor(i)) { + SkipCallBr = true; + break; + } + } + if (SkipCallBr) + continue; + // Otherwise, we found a duplicate return block. Merge the two. Changed = true; diff --git a/llvm/test/Transforms/SimplifyCFG/callbr-destinations.ll b/llvm/test/Transforms/SimplifyCFG/callbr-destinations.ll new file mode 100644 index 00000000000000..18210e5e0b0603 --- /dev/null +++ b/llvm/test/Transforms/SimplifyCFG/callbr-destinations.ll @@ -0,0 +1,28 @@ +; RUN: opt < %s -simplifycfg -disable-output +; +; Test that SimplifyCFG does not cause CallBr instructions to have duplicate +; destinations, which will cause the verifier to assert. + +define void @fun0() { +entry: + callbr void asm sideeffect "", "X"(i8* blockaddress(@fun0, %bb1)) + to label %bb2 [label %bb1] + +bb1: ; preds = %bb + ret void + +bb2: ; preds = %bb + ret void +} + +define void @fun1() { +entry: + callbr void asm sideeffect "", "X"(i8* blockaddress(@fun1, %bb1)) + to label %bb2 [label %bb1] + +bb2: ; preds = %bb + ret void + +bb1: ; preds = %bb + ret void +}