aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
diff options
context:
space:
mode:
authorRoman Lebedev <lebedev.ri@gmail.com>2022-02-08 15:42:03 +0300
committerRoman Lebedev <lebedev.ri@gmail.com>2022-02-08 17:49:38 +0300
commit8411560fd0751fc10ae03c85dabdb9d8b2b9ba6b (patch)
tree69a005a12e1d8430012193d642779eea241b67e2 /llvm/lib/Transforms/Utils/SimplifyCFG.cpp
parent1d5a3f70dc424bc755d9ff66055bb524ce1ee644 (diff)
downloadllvm-8411560fd0751fc10ae03c85dabdb9d8b2b9ba6b.zip
llvm-8411560fd0751fc10ae03c85dabdb9d8b2b9ba6b.tar.gz
llvm-8411560fd0751fc10ae03c85dabdb9d8b2b9ba6b.tar.bz2
[SimplifyCFG] 'merge compatible invokes': support normal destination w/ no uses, no PHI's
Even if the invokes have normal destination, iff it's the same block, we can merge them. For now, require that there are no PHI nodes, and the returned values of invokes aren't used.
Diffstat (limited to 'llvm/lib/Transforms/Utils/SimplifyCFG.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/SimplifyCFG.cpp53
1 files changed, 41 insertions, 12 deletions
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 5d09d2a..f039f87 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -2285,13 +2285,38 @@ bool CompatibleSets::shouldBelongToSameSet(ArrayRef<InvokeInst *> Invokes) {
return false;
}
- // Both `invoke`s must not have a normal destination.
- // FIXME: them sharing the normal destination should be fine?
+ // Either both `invoke`s must not have a normal destination,
+ // or both `invoke`s must have a normal destination,
auto HasNormalDest = [](InvokeInst *II) {
return !isa<UnreachableInst>(II->getNormalDest()->getFirstNonPHIOrDbg());
};
- if (any_of(Invokes, HasNormalDest))
- return false;
+ if (any_of(Invokes, HasNormalDest)) {
+ // Do not merge `invoke` that does not have a normal destination with one
+ // that does have a normal destination, even though doing so would be legal.
+ if (!all_of(Invokes, HasNormalDest))
+ return false;
+
+ // All normal destinations must be identical.
+ BasicBlock *NormalBB = nullptr;
+ for (InvokeInst *II : Invokes) {
+ BasicBlock *CurrNormalBB = II->getNormalDest();
+ assert(CurrNormalBB && "There is always a 'continue to' basic block.");
+ if (!NormalBB)
+ NormalBB = CurrNormalBB;
+ else if (NormalBB != CurrNormalBB)
+ return false;
+ }
+
+ // In the normal destination, there must be no PHI nodes.
+ // FIXME: just check that the incoming values are compatible?
+ if (!empty(NormalBB->phis()))
+ return false;
+
+ // For now, simply don't deal with `invoke`s that have uses.
+ auto Unused = [](InvokeInst *II) { return II->use_empty(); };
+ if (!all_of(Invokes, Unused))
+ return false;
+ }
#ifndef NDEBUG
// All unwind destinations must be identical.
@@ -2309,7 +2334,6 @@ bool CompatibleSets::shouldBelongToSameSet(ArrayRef<InvokeInst *> Invokes) {
// In the unwind destination, the incoming values for these two `invoke`s
// must be compatible .
- // We know we don't have the normal destination, so we don't check it.
if (!IncomingValuesAreCompatible(
Invokes.front()->getUnwindDest(),
{Invokes[0]->getParent(), Invokes[1]->getParent()}))
@@ -2348,9 +2372,12 @@ static void MergeCompatibleInvokesImpl(ArrayRef<InvokeInst *> Invokes,
if (DTU)
Updates.reserve(2 + 3 * Invokes.size());
+ bool HasNormalDest =
+ !isa<UnreachableInst>(Invokes[0]->getNormalDest()->getFirstNonPHIOrDbg());
+
// Clone one of the invokes into a new basic block.
// Since they are all compatible, it doesn't matter which invoke is cloned.
- InvokeInst *MergedInvoke = [&Invokes]() {
+ InvokeInst *MergedInvoke = [&Invokes, HasNormalDest]() {
InvokeInst *II0 = Invokes.front();
BasicBlock *II0BB = II0->getParent();
BasicBlock *InsertBeforeBlock =
@@ -2365,12 +2392,14 @@ static void MergeCompatibleInvokesImpl(ArrayRef<InvokeInst *> Invokes,
// NOTE: all invokes have the same attributes, so no handling needed.
MergedInvokeBB->getInstList().push_back(MergedInvoke);
- // For now, we've required that the normal destination is unreachable,
- // so just form a new block with unreachable terminator.
- BasicBlock *MergedNormalDest = BasicBlock::Create(
- Ctx, II0BB->getName() + ".cont", Func, InsertBeforeBlock);
- new UnreachableInst(Ctx, MergedNormalDest);
- MergedInvoke->setNormalDest(MergedNormalDest);
+ if (!HasNormalDest) {
+ // This set does not have a normal destination,
+ // so just form a new block with unreachable terminator.
+ BasicBlock *MergedNormalDest = BasicBlock::Create(
+ Ctx, II0BB->getName() + ".cont", Func, InsertBeforeBlock);
+ new UnreachableInst(Ctx, MergedNormalDest);
+ MergedInvoke->setNormalDest(MergedNormalDest);
+ }
// The unwind destination, however, remainds identical for all invokes here.