diff options
| author | Johannes Doerfert <johannes@jdoerfert.de> | 2019-11-01 21:59:32 -0500 |
|---|---|---|
| committer | Johannes Doerfert <johannes@jdoerfert.de> | 2019-11-02 00:54:00 -0500 |
| commit | c7ab19dbb0f1f5c76ff70c7acab9f20c796cafb3 (patch) | |
| tree | 9f843bf545c011c257f55c8d3bc671f232420ea2 /llvm/lib/Transforms/IPO/Attributor.cpp | |
| parent | 3cbe3314b4a02026e24fbc065fbbfc887bbc7392 (diff) | |
| download | bcm5719-llvm-c7ab19dbb0f1f5c76ff70c7acab9f20c796cafb3.tar.gz bcm5719-llvm-c7ab19dbb0f1f5c76ff70c7acab9f20c796cafb3.zip | |
[Attributor][FIX] Transform invoke of nounwind to call + br %normal_dest
Even if the invoked function may-return, we can replace it with a call
and branch if it is nounwind. We had almost everything in place to do
this but did not which actually caused a crash when we removed the
landingpad from the actually dead unwind block.
Exposed by the IPConstantProp tests.
Diffstat (limited to 'llvm/lib/Transforms/IPO/Attributor.cpp')
| -rw-r--r-- | llvm/lib/Transforms/IPO/Attributor.cpp | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp index fa0ea7e0ff1..448a2d4b6c1 100644 --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -2338,7 +2338,8 @@ struct AAIsDeadFunction : public AAIsDead { continue; const auto &NoReturnAA = A.getAAFor<AANoReturn>(*this, IRPosition::callsite_function(*CB)); - if (!NoReturnAA.isAssumedNoReturn()) + bool MayReturn = !NoReturnAA.isAssumedNoReturn(); + if (MayReturn && (!Invoke2CallAllowed || !isa<InvokeInst>(CB))) continue; Instruction *I = const_cast<Instruction *>(DeadEndI); BasicBlock *BB = I->getParent(); @@ -2361,6 +2362,26 @@ struct AAIsDeadFunction : public AAIsDead { if (AANoUnw.isAssumedNoUnwind()) { LLVM_DEBUG(dbgs() << "[AAIsDead] Replace invoke with call inst\n"); + CallInst *CI = createCallMatchingInvoke(II); + CI->insertBefore(II); + CI->takeName(II); + II->replaceAllUsesWith(CI); + + // If this is a nounwind + mayreturn invoke we only remove the unwind edge. + // This is done by moving the invoke into a new and dead block and connecting + // the normal destination of the invoke with a branch that follows the call + // replacement we created above. + if (MayReturn) { + BasicBlock *NewDeadBB = SplitBlock(BB, II, nullptr, nullptr, nullptr, ".i2c"); + assert(isa<BranchInst>(BB->getTerminator()) && + BB->getTerminator()->getNumSuccessors() == 1 && + BB->getTerminator()->getSuccessor(0) == NewDeadBB); + new UnreachableInst(I->getContext(), NewDeadBB); + BB->getTerminator()->setOperand(0, NormalDestBB); + A.deleteAfterManifest(*II); + continue; + } + // We do not need an invoke (II) but instead want a call followed // by an unreachable. However, we do not remove II as other // abstract attributes might have it cached as part of their @@ -2370,10 +2391,6 @@ struct AAIsDeadFunction : public AAIsDead { // only reached from the current block of II and then not reached // at all when we insert the unreachable. SplitBlockPredecessors(NormalDestBB, {BB}, ".i2c"); - CallInst *CI = createCallMatchingInvoke(II); - CI->insertBefore(II); - CI->takeName(II); - II->replaceAllUsesWith(CI); SplitPos = CI->getNextNode(); } } |

