1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-21 03:53:04 +02:00

[Local] Handle terminators with users in removeUnreachableBlocks.

Terminators like invoke can have users outside the current basic block.
We have to replace those users with undef, before replacing the
terminator.

This fixes a crash exposed by rL373430.

Reviewers: brzycki, asbirlea, davide, spatel

Reviewed By: asbirlea

Differential Revision: https://reviews.llvm.org/D68327

llvm-svn: 373513
This commit is contained in:
Florian Hahn 2019-10-02 19:38:24 +00:00
parent 9a90d3875f
commit 5bb7cdf861
2 changed files with 39 additions and 3 deletions

View File

@ -2246,9 +2246,13 @@ bool llvm::removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU,
}
BB->dropAllReferences();
if (DTU) {
// Remove the terminator of BB to clear the successor list of BB.
if (BB->getTerminator())
BB->getInstList().pop_back();
Instruction *TI = BB->getTerminator();
assert(TI && "Basic block should have a terminator");
// Terminators like invoke can have users. We have to replace their users,
// before removing them.
if (!TI->use_empty())
TI->replaceAllUsesWith(UndefValue::get(TI->getType()));
TI->eraseFromParent();
new UnreachableInst(BB->getContext(), BB);
assert(succ_empty(BB) && "The successor list of BB isn't empty before "
"applying corresponding DTU updates.");

View File

@ -867,6 +867,36 @@ TEST(Local, RemoveUnreachableBlocks) {
bb2:
br label %bb1
}
declare i32 @__gxx_personality_v0(...)
define void @invoke_terminator() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
entry:
br i1 undef, label %invoke.block, label %exit
invoke.block:
%cond = invoke zeroext i1 @invokable()
to label %continue.block unwind label %lpad.block
continue.block:
br i1 %cond, label %if.then, label %if.end
if.then:
unreachable
if.end:
unreachable
lpad.block:
%lp = landingpad { i8*, i32 }
catch i8* null
br label %exit
exit:
ret void
}
declare i1 @invokable()
)");
auto runEager = [&](Function &F, DominatorTree *DT) {
@ -890,12 +920,14 @@ TEST(Local, RemoveUnreachableBlocks) {
runWithDomTree(*M, "br_self_loop", runEager);
runWithDomTree(*M, "br_constant", runEager);
runWithDomTree(*M, "br_loop", runEager);
runWithDomTree(*M, "invoke_terminator", runEager);
// Test removeUnreachableBlocks under Lazy UpdateStrategy.
runWithDomTree(*M, "br_simple", runLazy);
runWithDomTree(*M, "br_self_loop", runLazy);
runWithDomTree(*M, "br_constant", runLazy);
runWithDomTree(*M, "br_loop", runLazy);
runWithDomTree(*M, "invoke_terminator", runLazy);
M = parseIR(C,
R"(