summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/IPO/Attributor.cpp
diff options
context:
space:
mode:
authorJohannes Doerfert <johannes@jdoerfert.de>2019-11-01 21:59:32 -0500
committerJohannes Doerfert <johannes@jdoerfert.de>2019-11-02 00:54:00 -0500
commitc7ab19dbb0f1f5c76ff70c7acab9f20c796cafb3 (patch)
tree9f843bf545c011c257f55c8d3bc671f232420ea2 /llvm/lib/Transforms/IPO/Attributor.cpp
parent3cbe3314b4a02026e24fbc065fbbfc887bbc7392 (diff)
downloadbcm5719-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.cpp27
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();
}
}
OpenPOWER on IntegriCloud