Skip to content

Commit 8411560

Browse files
committed
[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.
1 parent 1d5a3f7 commit 8411560

File tree

2 files changed

+54
-34
lines changed

2 files changed

+54
-34
lines changed

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

+41-12
Original file line numberDiff line numberDiff line change
@@ -2285,13 +2285,38 @@ bool CompatibleSets::shouldBelongToSameSet(ArrayRef<InvokeInst *> Invokes) {
22852285
return false;
22862286
}
22872287

2288-
// Both `invoke`s must not have a normal destination.
2289-
// FIXME: them sharing the normal destination should be fine?
2288+
// Either both `invoke`s must not have a normal destination,
2289+
// or both `invoke`s must have a normal destination,
22902290
auto HasNormalDest = [](InvokeInst *II) {
22912291
return !isa<UnreachableInst>(II->getNormalDest()->getFirstNonPHIOrDbg());
22922292
};
2293-
if (any_of(Invokes, HasNormalDest))
2294-
return false;
2293+
if (any_of(Invokes, HasNormalDest)) {
2294+
// Do not merge `invoke` that does not have a normal destination with one
2295+
// that does have a normal destination, even though doing so would be legal.
2296+
if (!all_of(Invokes, HasNormalDest))
2297+
return false;
2298+
2299+
// All normal destinations must be identical.
2300+
BasicBlock *NormalBB = nullptr;
2301+
for (InvokeInst *II : Invokes) {
2302+
BasicBlock *CurrNormalBB = II->getNormalDest();
2303+
assert(CurrNormalBB && "There is always a 'continue to' basic block.");
2304+
if (!NormalBB)
2305+
NormalBB = CurrNormalBB;
2306+
else if (NormalBB != CurrNormalBB)
2307+
return false;
2308+
}
2309+
2310+
// In the normal destination, there must be no PHI nodes.
2311+
// FIXME: just check that the incoming values are compatible?
2312+
if (!empty(NormalBB->phis()))
2313+
return false;
2314+
2315+
// For now, simply don't deal with `invoke`s that have uses.
2316+
auto Unused = [](InvokeInst *II) { return II->use_empty(); };
2317+
if (!all_of(Invokes, Unused))
2318+
return false;
2319+
}
22952320

22962321
#ifndef NDEBUG
22972322
// All unwind destinations must be identical.
@@ -2309,7 +2334,6 @@ bool CompatibleSets::shouldBelongToSameSet(ArrayRef<InvokeInst *> Invokes) {
23092334

23102335
// In the unwind destination, the incoming values for these two `invoke`s
23112336
// must be compatible .
2312-
// We know we don't have the normal destination, so we don't check it.
23132337
if (!IncomingValuesAreCompatible(
23142338
Invokes.front()->getUnwindDest(),
23152339
{Invokes[0]->getParent(), Invokes[1]->getParent()}))
@@ -2348,9 +2372,12 @@ static void MergeCompatibleInvokesImpl(ArrayRef<InvokeInst *> Invokes,
23482372
if (DTU)
23492373
Updates.reserve(2 + 3 * Invokes.size());
23502374

2375+
bool HasNormalDest =
2376+
!isa<UnreachableInst>(Invokes[0]->getNormalDest()->getFirstNonPHIOrDbg());
2377+
23512378
// Clone one of the invokes into a new basic block.
23522379
// Since they are all compatible, it doesn't matter which invoke is cloned.
2353-
InvokeInst *MergedInvoke = [&Invokes]() {
2380+
InvokeInst *MergedInvoke = [&Invokes, HasNormalDest]() {
23542381
InvokeInst *II0 = Invokes.front();
23552382
BasicBlock *II0BB = II0->getParent();
23562383
BasicBlock *InsertBeforeBlock =
@@ -2365,12 +2392,14 @@ static void MergeCompatibleInvokesImpl(ArrayRef<InvokeInst *> Invokes,
23652392
// NOTE: all invokes have the same attributes, so no handling needed.
23662393
MergedInvokeBB->getInstList().push_back(MergedInvoke);
23672394

2368-
// For now, we've required that the normal destination is unreachable,
2369-
// so just form a new block with unreachable terminator.
2370-
BasicBlock *MergedNormalDest = BasicBlock::Create(
2371-
Ctx, II0BB->getName() + ".cont", Func, InsertBeforeBlock);
2372-
new UnreachableInst(Ctx, MergedNormalDest);
2373-
MergedInvoke->setNormalDest(MergedNormalDest);
2395+
if (!HasNormalDest) {
2396+
// This set does not have a normal destination,
2397+
// so just form a new block with unreachable terminator.
2398+
BasicBlock *MergedNormalDest = BasicBlock::Create(
2399+
Ctx, II0BB->getName() + ".cont", Func, InsertBeforeBlock);
2400+
new UnreachableInst(Ctx, MergedNormalDest);
2401+
MergedInvoke->setNormalDest(MergedNormalDest);
2402+
}
23742403

23752404
// The unwind destination, however, remainds identical for all invokes here.
23762405

llvm/test/Transforms/SimplifyCFG/X86/merge-compatible-invokes-of-landingpad.ll

+13-22
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,7 @@ define void @t3_shared_identical_normal_dest() personality i8* bitcast (i32 (...
153153
; CHECK-LABEL: @t3_shared_identical_normal_dest(
154154
; CHECK-NEXT: entry:
155155
; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
156-
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN0:%.*]], label [[IF_ELSE:%.*]]
157-
; CHECK: if.then0:
158-
; CHECK-NEXT: invoke void @maybe_throw()
159-
; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
156+
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN1_INVOKE:%.*]], label [[IF_ELSE:%.*]]
160157
; CHECK: invoke.cont:
161158
; CHECK-NEXT: call void @sideeffect()
162159
; CHECK-NEXT: unreachable
@@ -167,10 +164,10 @@ define void @t3_shared_identical_normal_dest() personality i8* bitcast (i32 (...
167164
; CHECK-NEXT: resume { i8*, i32 } [[EH]]
168165
; CHECK: if.else:
169166
; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
170-
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1:%.*]], label [[IF_END:%.*]]
171-
; CHECK: if.then1:
167+
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1_INVOKE]], label [[IF_END:%.*]]
168+
; CHECK: if.then1.invoke:
172169
; CHECK-NEXT: invoke void @maybe_throw()
173-
; CHECK-NEXT: to label [[INVOKE_CONT]] unwind label [[LPAD]]
170+
; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
174171
; CHECK: if.end:
175172
; CHECK-NEXT: call void @sideeffect()
176173
; CHECK-NEXT: ret void
@@ -1642,10 +1639,7 @@ define void @t27_invoke_ret_value_is_used() personality i8* bitcast (i32 (...)*
16421639
; CHECK-LABEL: @t27_invoke_ret_value_is_used(
16431640
; CHECK-NEXT: entry:
16441641
; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
1645-
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN0:%.*]], label [[IF_ELSE:%.*]]
1646-
; CHECK: if.then0:
1647-
; CHECK-NEXT: [[V0:%.*]] = invoke i32 @returning_maybe_throw()
1648-
; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
1642+
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN1_INVOKE:%.*]], label [[IF_ELSE:%.*]]
16491643
; CHECK: invoke.cont:
16501644
; CHECK-NEXT: call void @sideeffect()
16511645
; CHECK-NEXT: unreachable
@@ -1656,10 +1650,10 @@ define void @t27_invoke_ret_value_is_used() personality i8* bitcast (i32 (...)*
16561650
; CHECK-NEXT: resume { i8*, i32 } [[EH]]
16571651
; CHECK: if.else:
16581652
; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
1659-
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1:%.*]], label [[IF_END:%.*]]
1660-
; CHECK: if.then1:
1661-
; CHECK-NEXT: [[V1:%.*]] = invoke i32 @returning_maybe_throw()
1662-
; CHECK-NEXT: to label [[INVOKE_CONT]] unwind label [[LPAD]]
1653+
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1_INVOKE]], label [[IF_END:%.*]]
1654+
; CHECK: if.then1.invoke:
1655+
; CHECK-NEXT: [[TMP0:%.*]] = invoke i32 @returning_maybe_throw()
1656+
; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
16631657
; CHECK: if.end:
16641658
; CHECK-NEXT: call void @sideeffect()
16651659
; CHECK-NEXT: ret void
@@ -1756,10 +1750,7 @@ define void @t29_common_normal_destination_and_unreachable_normal_destination()
17561750
; CHECK-LABEL: @t29_common_normal_destination_and_unreachable_normal_destination(
17571751
; CHECK-NEXT: entry:
17581752
; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
1759-
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN0:%.*]], label [[IF_ELSE0:%.*]]
1760-
; CHECK: if.then0:
1761-
; CHECK-NEXT: invoke void @maybe_throw()
1762-
; CHECK-NEXT: to label [[INVOKE_CONT0:%.*]] unwind label [[LPAD:%.*]]
1753+
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN1_INVOKE:%.*]], label [[IF_ELSE0:%.*]]
17631754
; CHECK: invoke.cont0:
17641755
; CHECK-NEXT: call void @sideeffect()
17651756
; CHECK-NEXT: unreachable
@@ -1770,10 +1761,10 @@ define void @t29_common_normal_destination_and_unreachable_normal_destination()
17701761
; CHECK-NEXT: resume { i8*, i32 } [[EH]]
17711762
; CHECK: if.else0:
17721763
; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
1773-
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1:%.*]], label [[IF_ELSE1:%.*]]
1774-
; CHECK: if.then1:
1764+
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1_INVOKE]], label [[IF_ELSE1:%.*]]
1765+
; CHECK: if.then1.invoke:
17751766
; CHECK-NEXT: invoke void @maybe_throw()
1776-
; CHECK-NEXT: to label [[INVOKE_CONT0]] unwind label [[LPAD]]
1767+
; CHECK-NEXT: to label [[INVOKE_CONT0:%.*]] unwind label [[LPAD:%.*]]
17771768
; CHECK: if.else1:
17781769
; CHECK-NEXT: [[C2:%.*]] = call i1 @cond()
17791770
; CHECK-NEXT: br i1 [[C2]], label [[IF_THEN2:%.*]], label [[IF_END:%.*]]

0 commit comments

Comments
 (0)