forked from OSchip/llvm-project
[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.
This commit is contained in:
parent
414b47645d
commit
c8ba2b67a0
|
@ -2284,16 +2284,25 @@ bool CompatibleSets::shouldBelongToSameSet(ArrayRef<InvokeInst *> Invokes) {
|
|||
if (any_of(Invokes, IsIllegalToMerge))
|
||||
return false;
|
||||
|
||||
// All callees must be identical.
|
||||
// FIXME: support indirect callees?
|
||||
Value *Callee = nullptr;
|
||||
for (InvokeInst *II : Invokes) {
|
||||
Value *CurrCallee = II->getCalledOperand();
|
||||
assert(CurrCallee && "There is always a called operand.");
|
||||
if (!Callee)
|
||||
Callee = CurrCallee;
|
||||
else if (Callee != CurrCallee)
|
||||
// Either both `invoke`s must be direct,
|
||||
// or both `invoke`s must be indirect.
|
||||
auto IsIndirectCall = [](InvokeInst *II) { return II->isIndirectCall(); };
|
||||
bool HaveIndirectCalls = any_of(Invokes, IsIndirectCall);
|
||||
bool AllCallsAreIndirect = all_of(Invokes, IsIndirectCall);
|
||||
if (HaveIndirectCalls) {
|
||||
if (!AllCallsAreIndirect)
|
||||
return false;
|
||||
} else {
|
||||
// All callees must be identical.
|
||||
Value *Callee = nullptr;
|
||||
for (InvokeInst *II : Invokes) {
|
||||
Value *CurrCallee = II->getCalledOperand();
|
||||
assert(CurrCallee && "There is always a called operand.");
|
||||
if (!Callee)
|
||||
Callee = CurrCallee;
|
||||
else if (Callee != CurrCallee)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Either both `invoke`s must not have a normal destination,
|
||||
|
@ -2436,8 +2445,17 @@ static void MergeCompatibleInvokesImpl(ArrayRef<InvokeInst *> Invokes,
|
|||
{DominatorTree::Delete, II->getParent(), SuccOfPredBB});
|
||||
}
|
||||
|
||||
// Form the merged data operands for the merged invoke.
|
||||
for (Use &U : MergedInvoke->data_ops()) {
|
||||
bool IsIndirectCall = Invokes[0]->isIndirectCall();
|
||||
|
||||
// Form the merged operands for the merged invoke.
|
||||
for (Use &U : MergedInvoke->operands()) {
|
||||
// Only PHI together the indirect callees and data operands.
|
||||
if (MergedInvoke->isCallee(&U)) {
|
||||
if (!IsIndirectCall)
|
||||
continue;
|
||||
} else if (!MergedInvoke->isDataOperand(&U))
|
||||
continue;
|
||||
|
||||
// Don't create trivial PHI's with all-identical incoming values.
|
||||
bool NeedPHI = any_of(Invokes, [&U](InvokeInst *II) {
|
||||
return II->getOperand(U.getOperandNo()) != U.get();
|
||||
|
@ -2448,10 +2466,8 @@ static void MergeCompatibleInvokesImpl(ArrayRef<InvokeInst *> Invokes,
|
|||
// Form a PHI out of all the data ops under this index.
|
||||
PHINode *PN = PHINode::Create(
|
||||
U->getType(), /*NumReservedValues=*/Invokes.size(), "", MergedInvoke);
|
||||
for (InvokeInst *II : Invokes) {
|
||||
Use *IVU = II->data_operands_begin() + MergedInvoke->getDataOperandNo(&U);
|
||||
PN->addIncoming(IVU->get(), II->getParent());
|
||||
}
|
||||
for (InvokeInst *II : Invokes)
|
||||
PN->addIncoming(II->getOperand(U.getOperandNo()), II->getParent());
|
||||
|
||||
U.set(PN);
|
||||
}
|
||||
|
|
|
@ -2166,12 +2166,7 @@ define void @t36_different_indirect_callees(void()* %callee0, void()* %callee1)
|
|||
; CHECK-LABEL: @t36_different_indirect_callees(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
|
||||
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN0:%.*]], label [[IF_ELSE:%.*]]
|
||||
; CHECK: if.then0:
|
||||
; CHECK-NEXT: invoke void [[CALLEE0:%.*]]()
|
||||
; CHECK-NEXT: to label [[INVOKE_CONT0:%.*]] unwind label [[LPAD:%.*]]
|
||||
; CHECK: invoke.cont0:
|
||||
; CHECK-NEXT: unreachable
|
||||
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN1_INVOKE:%.*]], label [[IF_ELSE:%.*]]
|
||||
; CHECK: lpad:
|
||||
; CHECK-NEXT: [[EH:%.*]] = landingpad { i8*, i32 }
|
||||
; CHECK-NEXT: cleanup
|
||||
|
@ -2179,11 +2174,12 @@ define void @t36_different_indirect_callees(void()* %callee0, void()* %callee1)
|
|||
; CHECK-NEXT: resume { i8*, i32 } [[EH]]
|
||||
; CHECK: if.else:
|
||||
; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
|
||||
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1:%.*]], label [[IF_END:%.*]]
|
||||
; CHECK: if.then1:
|
||||
; CHECK-NEXT: invoke void [[CALLEE1:%.*]]()
|
||||
; CHECK-NEXT: to label [[INVOKE_CONT2:%.*]] unwind label [[LPAD]]
|
||||
; CHECK: invoke.cont2:
|
||||
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1_INVOKE]], label [[IF_END:%.*]]
|
||||
; CHECK: if.then1.invoke:
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = phi void ()* [ [[CALLEE1:%.*]], [[IF_ELSE]] ], [ [[CALLEE0:%.*]], [[ENTRY:%.*]] ]
|
||||
; CHECK-NEXT: invoke void [[TMP0]]()
|
||||
; CHECK-NEXT: to label [[IF_THEN1_CONT:%.*]] unwind label [[LPAD:%.*]]
|
||||
; CHECK: if.then1.cont:
|
||||
; CHECK-NEXT: unreachable
|
||||
; CHECK: if.end:
|
||||
; CHECK-NEXT: call void @sideeffect()
|
||||
|
@ -2295,12 +2291,7 @@ define void @t38_different_arguments_and_operand_bundes_are_fine(void(i32)* %cal
|
|||
; CHECK-LABEL: @t38_different_arguments_and_operand_bundes_are_fine(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
|
||||
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN0:%.*]], label [[IF_ELSE:%.*]]
|
||||
; CHECK: if.then0:
|
||||
; CHECK-NEXT: invoke void [[CALLEE0:%.*]](i32 0)
|
||||
; CHECK-NEXT: to label [[INVOKE_CONT0:%.*]] unwind label [[LPAD:%.*]]
|
||||
; CHECK: invoke.cont0:
|
||||
; CHECK-NEXT: unreachable
|
||||
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN1_INVOKE:%.*]], label [[IF_ELSE:%.*]]
|
||||
; CHECK: lpad:
|
||||
; CHECK-NEXT: [[EH:%.*]] = landingpad { i8*, i32 }
|
||||
; CHECK-NEXT: cleanup
|
||||
|
@ -2308,11 +2299,13 @@ define void @t38_different_arguments_and_operand_bundes_are_fine(void(i32)* %cal
|
|||
; CHECK-NEXT: resume { i8*, i32 } [[EH]]
|
||||
; CHECK: if.else:
|
||||
; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
|
||||
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1:%.*]], label [[IF_END:%.*]]
|
||||
; CHECK: if.then1:
|
||||
; CHECK-NEXT: invoke void [[CALLEE1:%.*]](i32 42)
|
||||
; CHECK-NEXT: to label [[INVOKE_CONT2:%.*]] unwind label [[LPAD]]
|
||||
; CHECK: invoke.cont2:
|
||||
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1_INVOKE]], label [[IF_END:%.*]]
|
||||
; CHECK: if.then1.invoke:
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ 42, [[IF_ELSE]] ], [ 0, [[ENTRY:%.*]] ]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = phi void (i32)* [ [[CALLEE1:%.*]], [[IF_ELSE]] ], [ [[CALLEE0:%.*]], [[ENTRY]] ]
|
||||
; CHECK-NEXT: invoke void [[TMP1]](i32 [[TMP0]])
|
||||
; CHECK-NEXT: to label [[IF_THEN1_CONT:%.*]] unwind label [[LPAD:%.*]]
|
||||
; CHECK: if.then1.cont:
|
||||
; CHECK-NEXT: unreachable
|
||||
; CHECK: if.end:
|
||||
; CHECK-NEXT: call void @sideeffect()
|
||||
|
@ -2353,12 +2346,7 @@ define void @t39_different_arguments_and_operand_bundes_are_fine(void()* %callee
|
|||
; CHECK-LABEL: @t39_different_arguments_and_operand_bundes_are_fine(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
|
||||
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN0:%.*]], label [[IF_ELSE:%.*]]
|
||||
; CHECK: if.then0:
|
||||
; CHECK-NEXT: invoke void [[CALLEE0:%.*]]() [ "abc"(i32 42) ]
|
||||
; CHECK-NEXT: to label [[INVOKE_CONT0:%.*]] unwind label [[LPAD:%.*]]
|
||||
; CHECK: invoke.cont0:
|
||||
; CHECK-NEXT: unreachable
|
||||
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN1_INVOKE:%.*]], label [[IF_ELSE:%.*]]
|
||||
; CHECK: lpad:
|
||||
; CHECK-NEXT: [[EH:%.*]] = landingpad { i8*, i32 }
|
||||
; CHECK-NEXT: cleanup
|
||||
|
@ -2366,11 +2354,13 @@ define void @t39_different_arguments_and_operand_bundes_are_fine(void()* %callee
|
|||
; CHECK-NEXT: resume { i8*, i32 } [[EH]]
|
||||
; CHECK: if.else:
|
||||
; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
|
||||
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1:%.*]], label [[IF_END:%.*]]
|
||||
; CHECK: if.then1:
|
||||
; CHECK-NEXT: invoke void [[CALLEE1:%.*]]() [ "abc"(i32 0) ]
|
||||
; CHECK-NEXT: to label [[INVOKE_CONT2:%.*]] unwind label [[LPAD]]
|
||||
; CHECK: invoke.cont2:
|
||||
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1_INVOKE]], label [[IF_END:%.*]]
|
||||
; CHECK: if.then1.invoke:
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ 0, [[IF_ELSE]] ], [ 42, [[ENTRY:%.*]] ]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = phi void ()* [ [[CALLEE1:%.*]], [[IF_ELSE]] ], [ [[CALLEE0:%.*]], [[ENTRY]] ]
|
||||
; CHECK-NEXT: invoke void [[TMP1]]() [ "abc"(i32 [[TMP0]]) ]
|
||||
; CHECK-NEXT: to label [[IF_THEN1_CONT:%.*]] unwind label [[LPAD:%.*]]
|
||||
; CHECK: if.then1.cont:
|
||||
; CHECK-NEXT: unreachable
|
||||
; CHECK: if.end:
|
||||
; CHECK-NEXT: call void @sideeffect()
|
||||
|
@ -2411,12 +2401,7 @@ define void @t40_different_arguments_and_operand_bundes_are_fine(void(i32)* %cal
|
|||
; CHECK-LABEL: @t40_different_arguments_and_operand_bundes_are_fine(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
|
||||
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN0:%.*]], label [[IF_ELSE:%.*]]
|
||||
; CHECK: if.then0:
|
||||
; CHECK-NEXT: invoke void [[CALLEE0:%.*]](i32 0) [ "abc"(i32 42) ]
|
||||
; CHECK-NEXT: to label [[INVOKE_CONT0:%.*]] unwind label [[LPAD:%.*]]
|
||||
; CHECK: invoke.cont0:
|
||||
; CHECK-NEXT: unreachable
|
||||
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN1_INVOKE:%.*]], label [[IF_ELSE:%.*]]
|
||||
; CHECK: lpad:
|
||||
; CHECK-NEXT: [[EH:%.*]] = landingpad { i8*, i32 }
|
||||
; CHECK-NEXT: cleanup
|
||||
|
@ -2424,11 +2409,14 @@ define void @t40_different_arguments_and_operand_bundes_are_fine(void(i32)* %cal
|
|||
; CHECK-NEXT: resume { i8*, i32 } [[EH]]
|
||||
; CHECK: if.else:
|
||||
; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
|
||||
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1:%.*]], label [[IF_END:%.*]]
|
||||
; CHECK: if.then1:
|
||||
; CHECK-NEXT: invoke void [[CALLEE1:%.*]](i32 42) [ "abc"(i32 0) ]
|
||||
; CHECK-NEXT: to label [[INVOKE_CONT2:%.*]] unwind label [[LPAD]]
|
||||
; CHECK: invoke.cont2:
|
||||
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1_INVOKE]], label [[IF_END:%.*]]
|
||||
; CHECK: if.then1.invoke:
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ 42, [[IF_ELSE]] ], [ 0, [[ENTRY:%.*]] ]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ 0, [[IF_ELSE]] ], [ 42, [[ENTRY]] ]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = phi void (i32)* [ [[CALLEE1:%.*]], [[IF_ELSE]] ], [ [[CALLEE0:%.*]], [[ENTRY]] ]
|
||||
; CHECK-NEXT: invoke void [[TMP2]](i32 [[TMP0]]) [ "abc"(i32 [[TMP1]]) ]
|
||||
; CHECK-NEXT: to label [[IF_THEN1_CONT:%.*]] unwind label [[LPAD:%.*]]
|
||||
; CHECK: if.then1.cont:
|
||||
; CHECK-NEXT: unreachable
|
||||
; CHECK: if.end:
|
||||
; CHECK-NEXT: call void @sideeffect()
|
||||
|
|
Loading…
Reference in New Issue