Skip to content

Commit c8ba2b6

Browse files
committed
[SimplifyCFG] 'merge compatible invokes': fully support indirect invokes
As long as *all* the invokes in the set are indirect, we can merge them, but don't merge direct invokes into the set, even though it would be legal to do.
1 parent 414b476 commit c8ba2b6

File tree

2 files changed

+63
-59
lines changed

2 files changed

+63
-59
lines changed

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2284,16 +2284,25 @@ bool CompatibleSets::shouldBelongToSameSet(ArrayRef<InvokeInst *> Invokes) {
22842284
if (any_of(Invokes, IsIllegalToMerge))
22852285
return false;
22862286

2287-
// All callees must be identical.
2288-
// FIXME: support indirect callees?
2289-
Value *Callee = nullptr;
2290-
for (InvokeInst *II : Invokes) {
2291-
Value *CurrCallee = II->getCalledOperand();
2292-
assert(CurrCallee && "There is always a called operand.");
2293-
if (!Callee)
2294-
Callee = CurrCallee;
2295-
else if (Callee != CurrCallee)
2287+
// Either both `invoke`s must be direct,
2288+
// or both `invoke`s must be indirect.
2289+
auto IsIndirectCall = [](InvokeInst *II) { return II->isIndirectCall(); };
2290+
bool HaveIndirectCalls = any_of(Invokes, IsIndirectCall);
2291+
bool AllCallsAreIndirect = all_of(Invokes, IsIndirectCall);
2292+
if (HaveIndirectCalls) {
2293+
if (!AllCallsAreIndirect)
22962294
return false;
2295+
} else {
2296+
// All callees must be identical.
2297+
Value *Callee = nullptr;
2298+
for (InvokeInst *II : Invokes) {
2299+
Value *CurrCallee = II->getCalledOperand();
2300+
assert(CurrCallee && "There is always a called operand.");
2301+
if (!Callee)
2302+
Callee = CurrCallee;
2303+
else if (Callee != CurrCallee)
2304+
return false;
2305+
}
22972306
}
22982307

22992308
// Either both `invoke`s must not have a normal destination,
@@ -2436,8 +2445,17 @@ static void MergeCompatibleInvokesImpl(ArrayRef<InvokeInst *> Invokes,
24362445
{DominatorTree::Delete, II->getParent(), SuccOfPredBB});
24372446
}
24382447

2439-
// Form the merged data operands for the merged invoke.
2440-
for (Use &U : MergedInvoke->data_ops()) {
2448+
bool IsIndirectCall = Invokes[0]->isIndirectCall();
2449+
2450+
// Form the merged operands for the merged invoke.
2451+
for (Use &U : MergedInvoke->operands()) {
2452+
// Only PHI together the indirect callees and data operands.
2453+
if (MergedInvoke->isCallee(&U)) {
2454+
if (!IsIndirectCall)
2455+
continue;
2456+
} else if (!MergedInvoke->isDataOperand(&U))
2457+
continue;
2458+
24412459
// Don't create trivial PHI's with all-identical incoming values.
24422460
bool NeedPHI = any_of(Invokes, [&U](InvokeInst *II) {
24432461
return II->getOperand(U.getOperandNo()) != U.get();
@@ -2448,10 +2466,8 @@ static void MergeCompatibleInvokesImpl(ArrayRef<InvokeInst *> Invokes,
24482466
// Form a PHI out of all the data ops under this index.
24492467
PHINode *PN = PHINode::Create(
24502468
U->getType(), /*NumReservedValues=*/Invokes.size(), "", MergedInvoke);
2451-
for (InvokeInst *II : Invokes) {
2452-
Use *IVU = II->data_operands_begin() + MergedInvoke->getDataOperandNo(&U);
2453-
PN->addIncoming(IVU->get(), II->getParent());
2454-
}
2469+
for (InvokeInst *II : Invokes)
2470+
PN->addIncoming(II->getOperand(U.getOperandNo()), II->getParent());
24552471

24562472
U.set(PN);
24572473
}

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

Lines changed: 32 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2166,24 +2166,20 @@ define void @t36_different_indirect_callees(void()* %callee0, void()* %callee1)
21662166
; CHECK-LABEL: @t36_different_indirect_callees(
21672167
; CHECK-NEXT: entry:
21682168
; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
2169-
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN0:%.*]], label [[IF_ELSE:%.*]]
2170-
; CHECK: if.then0:
2171-
; CHECK-NEXT: invoke void [[CALLEE0:%.*]]()
2172-
; CHECK-NEXT: to label [[INVOKE_CONT0:%.*]] unwind label [[LPAD:%.*]]
2173-
; CHECK: invoke.cont0:
2174-
; CHECK-NEXT: unreachable
2169+
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN1_INVOKE:%.*]], label [[IF_ELSE:%.*]]
21752170
; CHECK: lpad:
21762171
; CHECK-NEXT: [[EH:%.*]] = landingpad { i8*, i32 }
21772172
; CHECK-NEXT: cleanup
21782173
; CHECK-NEXT: call void @destructor()
21792174
; CHECK-NEXT: resume { i8*, i32 } [[EH]]
21802175
; CHECK: if.else:
21812176
; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
2182-
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1:%.*]], label [[IF_END:%.*]]
2183-
; CHECK: if.then1:
2184-
; CHECK-NEXT: invoke void [[CALLEE1:%.*]]()
2185-
; CHECK-NEXT: to label [[INVOKE_CONT2:%.*]] unwind label [[LPAD]]
2186-
; CHECK: invoke.cont2:
2177+
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1_INVOKE]], label [[IF_END:%.*]]
2178+
; CHECK: if.then1.invoke:
2179+
; CHECK-NEXT: [[TMP0:%.*]] = phi void ()* [ [[CALLEE1:%.*]], [[IF_ELSE]] ], [ [[CALLEE0:%.*]], [[ENTRY:%.*]] ]
2180+
; CHECK-NEXT: invoke void [[TMP0]]()
2181+
; CHECK-NEXT: to label [[IF_THEN1_CONT:%.*]] unwind label [[LPAD:%.*]]
2182+
; CHECK: if.then1.cont:
21872183
; CHECK-NEXT: unreachable
21882184
; CHECK: if.end:
21892185
; CHECK-NEXT: call void @sideeffect()
@@ -2295,24 +2291,21 @@ define void @t38_different_arguments_and_operand_bundes_are_fine(void(i32)* %cal
22952291
; CHECK-LABEL: @t38_different_arguments_and_operand_bundes_are_fine(
22962292
; CHECK-NEXT: entry:
22972293
; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
2298-
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN0:%.*]], label [[IF_ELSE:%.*]]
2299-
; CHECK: if.then0:
2300-
; CHECK-NEXT: invoke void [[CALLEE0:%.*]](i32 0)
2301-
; CHECK-NEXT: to label [[INVOKE_CONT0:%.*]] unwind label [[LPAD:%.*]]
2302-
; CHECK: invoke.cont0:
2303-
; CHECK-NEXT: unreachable
2294+
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN1_INVOKE:%.*]], label [[IF_ELSE:%.*]]
23042295
; CHECK: lpad:
23052296
; CHECK-NEXT: [[EH:%.*]] = landingpad { i8*, i32 }
23062297
; CHECK-NEXT: cleanup
23072298
; CHECK-NEXT: call void @destructor()
23082299
; CHECK-NEXT: resume { i8*, i32 } [[EH]]
23092300
; CHECK: if.else:
23102301
; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
2311-
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1:%.*]], label [[IF_END:%.*]]
2312-
; CHECK: if.then1:
2313-
; CHECK-NEXT: invoke void [[CALLEE1:%.*]](i32 42)
2314-
; CHECK-NEXT: to label [[INVOKE_CONT2:%.*]] unwind label [[LPAD]]
2315-
; CHECK: invoke.cont2:
2302+
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1_INVOKE]], label [[IF_END:%.*]]
2303+
; CHECK: if.then1.invoke:
2304+
; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ 42, [[IF_ELSE]] ], [ 0, [[ENTRY:%.*]] ]
2305+
; CHECK-NEXT: [[TMP1:%.*]] = phi void (i32)* [ [[CALLEE1:%.*]], [[IF_ELSE]] ], [ [[CALLEE0:%.*]], [[ENTRY]] ]
2306+
; CHECK-NEXT: invoke void [[TMP1]](i32 [[TMP0]])
2307+
; CHECK-NEXT: to label [[IF_THEN1_CONT:%.*]] unwind label [[LPAD:%.*]]
2308+
; CHECK: if.then1.cont:
23162309
; CHECK-NEXT: unreachable
23172310
; CHECK: if.end:
23182311
; CHECK-NEXT: call void @sideeffect()
@@ -2353,24 +2346,21 @@ define void @t39_different_arguments_and_operand_bundes_are_fine(void()* %callee
23532346
; CHECK-LABEL: @t39_different_arguments_and_operand_bundes_are_fine(
23542347
; CHECK-NEXT: entry:
23552348
; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
2356-
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN0:%.*]], label [[IF_ELSE:%.*]]
2357-
; CHECK: if.then0:
2358-
; CHECK-NEXT: invoke void [[CALLEE0:%.*]]() [ "abc"(i32 42) ]
2359-
; CHECK-NEXT: to label [[INVOKE_CONT0:%.*]] unwind label [[LPAD:%.*]]
2360-
; CHECK: invoke.cont0:
2361-
; CHECK-NEXT: unreachable
2349+
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN1_INVOKE:%.*]], label [[IF_ELSE:%.*]]
23622350
; CHECK: lpad:
23632351
; CHECK-NEXT: [[EH:%.*]] = landingpad { i8*, i32 }
23642352
; CHECK-NEXT: cleanup
23652353
; CHECK-NEXT: call void @destructor()
23662354
; CHECK-NEXT: resume { i8*, i32 } [[EH]]
23672355
; CHECK: if.else:
23682356
; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
2369-
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1:%.*]], label [[IF_END:%.*]]
2370-
; CHECK: if.then1:
2371-
; CHECK-NEXT: invoke void [[CALLEE1:%.*]]() [ "abc"(i32 0) ]
2372-
; CHECK-NEXT: to label [[INVOKE_CONT2:%.*]] unwind label [[LPAD]]
2373-
; CHECK: invoke.cont2:
2357+
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1_INVOKE]], label [[IF_END:%.*]]
2358+
; CHECK: if.then1.invoke:
2359+
; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ 0, [[IF_ELSE]] ], [ 42, [[ENTRY:%.*]] ]
2360+
; CHECK-NEXT: [[TMP1:%.*]] = phi void ()* [ [[CALLEE1:%.*]], [[IF_ELSE]] ], [ [[CALLEE0:%.*]], [[ENTRY]] ]
2361+
; CHECK-NEXT: invoke void [[TMP1]]() [ "abc"(i32 [[TMP0]]) ]
2362+
; CHECK-NEXT: to label [[IF_THEN1_CONT:%.*]] unwind label [[LPAD:%.*]]
2363+
; CHECK: if.then1.cont:
23742364
; CHECK-NEXT: unreachable
23752365
; CHECK: if.end:
23762366
; CHECK-NEXT: call void @sideeffect()
@@ -2411,24 +2401,22 @@ define void @t40_different_arguments_and_operand_bundes_are_fine(void(i32)* %cal
24112401
; CHECK-LABEL: @t40_different_arguments_and_operand_bundes_are_fine(
24122402
; CHECK-NEXT: entry:
24132403
; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
2414-
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN0:%.*]], label [[IF_ELSE:%.*]]
2415-
; CHECK: if.then0:
2416-
; CHECK-NEXT: invoke void [[CALLEE0:%.*]](i32 0) [ "abc"(i32 42) ]
2417-
; CHECK-NEXT: to label [[INVOKE_CONT0:%.*]] unwind label [[LPAD:%.*]]
2418-
; CHECK: invoke.cont0:
2419-
; CHECK-NEXT: unreachable
2404+
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN1_INVOKE:%.*]], label [[IF_ELSE:%.*]]
24202405
; CHECK: lpad:
24212406
; CHECK-NEXT: [[EH:%.*]] = landingpad { i8*, i32 }
24222407
; CHECK-NEXT: cleanup
24232408
; CHECK-NEXT: call void @destructor()
24242409
; CHECK-NEXT: resume { i8*, i32 } [[EH]]
24252410
; CHECK: if.else:
24262411
; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
2427-
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1:%.*]], label [[IF_END:%.*]]
2428-
; CHECK: if.then1:
2429-
; CHECK-NEXT: invoke void [[CALLEE1:%.*]](i32 42) [ "abc"(i32 0) ]
2430-
; CHECK-NEXT: to label [[INVOKE_CONT2:%.*]] unwind label [[LPAD]]
2431-
; CHECK: invoke.cont2:
2412+
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1_INVOKE]], label [[IF_END:%.*]]
2413+
; CHECK: if.then1.invoke:
2414+
; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ 42, [[IF_ELSE]] ], [ 0, [[ENTRY:%.*]] ]
2415+
; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ 0, [[IF_ELSE]] ], [ 42, [[ENTRY]] ]
2416+
; CHECK-NEXT: [[TMP2:%.*]] = phi void (i32)* [ [[CALLEE1:%.*]], [[IF_ELSE]] ], [ [[CALLEE0:%.*]], [[ENTRY]] ]
2417+
; CHECK-NEXT: invoke void [[TMP2]](i32 [[TMP0]]) [ "abc"(i32 [[TMP1]]) ]
2418+
; CHECK-NEXT: to label [[IF_THEN1_CONT:%.*]] unwind label [[LPAD:%.*]]
2419+
; CHECK: if.then1.cont:
24322420
; CHECK-NEXT: unreachable
24332421
; CHECK: if.end:
24342422
; CHECK-NEXT: call void @sideeffect()

0 commit comments

Comments
 (0)