[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
This commit is contained in:
Jonas Paulsson 2020-03-04 17:11:40 +01:00
parent 6e60e1025f
commit c2dafe12dc
2 changed files with 43 additions and 0 deletions

View File

@ -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;

View File

@ -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
}