aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/Local.cpp
diff options
context:
space:
mode:
authorRoman Lebedev <lebedev.ri@gmail.com>2022-02-05 01:28:24 +0300
committerRoman Lebedev <lebedev.ri@gmail.com>2022-02-05 02:15:07 +0300
commit598833c987593ce192fa827f162cae8c867c9d43 (patch)
tree26c07f684542d733551053df615e650be8ab39a7 /llvm/lib/Transforms/Utils/Local.cpp
parent75c1d1dab41709a9e0780ad2fbad23e46bfba4dd (diff)
downloadllvm-598833c987593ce192fa827f162cae8c867c9d43.zip
llvm-598833c987593ce192fa827f162cae8c867c9d43.tar.gz
llvm-598833c987593ce192fa827f162cae8c867c9d43.tar.bz2
[SimplifyCFG] `markAliveBlocks()`: recognize that normal dest of `invoke`d `noreturn` function is `unreachable`
As per LangRef's definition of `noreturn` attribute: ``` noreturn This function attribute indicates that the function never returns normally, hence through a return instruction. This produces undefined behavior at runtime if the function ever does dynamically return. nnotated functions may still raise an exception, i.a., nounwind is not implied. ```
Diffstat (limited to 'llvm/lib/Transforms/Utils/Local.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/Local.cpp39
1 files changed, 26 insertions, 13 deletions
diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index 9a10535..58eb7d4 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -2349,19 +2349,32 @@ static bool markAliveBlocks(Function &F,
isa<UndefValue>(Callee)) {
changeToUnreachable(II, false, DTU);
Changed = true;
- } else if (II->doesNotThrow() && canSimplifyInvokeNoUnwind(&F)) {
- if (II->use_empty() && II->onlyReadsMemory()) {
- // jump to the normal destination branch.
- BasicBlock *NormalDestBB = II->getNormalDest();
- BasicBlock *UnwindDestBB = II->getUnwindDest();
- BranchInst::Create(NormalDestBB, II);
- UnwindDestBB->removePredecessor(II->getParent());
- II->eraseFromParent();
- if (DTU)
- DTU->applyUpdates({{DominatorTree::Delete, BB, UnwindDestBB}});
- } else
- changeToCall(II, DTU);
- Changed = true;
+ } else {
+ if (II->doesNotReturn()) {
+ // If we found an invoke of a no-return function,
+ // insert an unreachable instruction after it (on the normal dest).
+ // Make sure there isn't *already* one there though.
+ Instruction *FirstNormalInst = &II->getNormalDest()->front();
+ if (!isa<UnreachableInst>(FirstNormalInst)) {
+ // Don't insert a call to llvm.trap right before the unreachable.
+ changeToUnreachable(FirstNormalInst, false, DTU);
+ Changed = true;
+ }
+ }
+ if (II->doesNotThrow() && canSimplifyInvokeNoUnwind(&F)) {
+ if (II->use_empty() && II->onlyReadsMemory()) {
+ // jump to the normal destination branch.
+ BasicBlock *NormalDestBB = II->getNormalDest();
+ BasicBlock *UnwindDestBB = II->getUnwindDest();
+ BranchInst::Create(NormalDestBB, II);
+ UnwindDestBB->removePredecessor(II->getParent());
+ II->eraseFromParent();
+ if (DTU)
+ DTU->applyUpdates({{DominatorTree::Delete, BB, UnwindDestBB}});
+ } else
+ changeToCall(II, DTU);
+ Changed = true;
+ }
}
} else if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(Terminator)) {
// Remove catchpads which cannot be reached.