Skip to content

Commit

Permalink
[SimplifyCFG] Skip merging return blocks if it would break a CallBr.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
JonPsson committed Mar 10, 2020
1 parent 6e60e10 commit c2dafe1
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 0 deletions.
15 changes: 15 additions & 0 deletions llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<CallBrInst>((*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;

Expand Down
28 changes: 28 additions & 0 deletions llvm/test/Transforms/SimplifyCFG/callbr-destinations.ll
Original file line number Diff line number Diff line change
@@ -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
}

0 comments on commit c2dafe1

Please sign in to comment.