From a80b6c15425f82521c624ff24c5c0a34cd534d54 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Wed, 2 Oct 2019 19:38:24 +0000 Subject: [PATCH] [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 --- llvm/lib/Transforms/Utils/Local.cpp | 10 ++++++--- llvm/unittests/Transforms/Utils/LocalTest.cpp | 32 +++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index 3a6b7a6..94339c2 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -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."); diff --git a/llvm/unittests/Transforms/Utils/LocalTest.cpp b/llvm/unittests/Transforms/Utils/LocalTest.cpp index ff2eda1..1f67a1e 100644 --- a/llvm/unittests/Transforms/Utils/LocalTest.cpp +++ b/llvm/unittests/Transforms/Utils/LocalTest.cpp @@ -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"( -- 2.7.4