[llvm] c8ba2b6 - [SimplifyCFG] 'merge compatible invokes': fully support indirect invokes
Roman Lebedev via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 8 10:30:10 PST 2022
Author: Roman Lebedev
Date: 2022-02-08T21:29:38+03:00
New Revision: c8ba2b67a0adebd15dcda70766d4ebaa0ec03720
URL: https://github.com/llvm/llvm-project/commit/c8ba2b67a0adebd15dcda70766d4ebaa0ec03720
DIFF: https://github.com/llvm/llvm-project/commit/c8ba2b67a0adebd15dcda70766d4ebaa0ec03720.diff
LOG: [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.
Added:
Modified:
llvm/lib/Transforms/Utils/SimplifyCFG.cpp
llvm/test/Transforms/SimplifyCFG/X86/merge-compatible-invokes-of-landingpad.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 2f6757356dad..5c6a7b7dec56 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -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);
}
diff --git a/llvm/test/Transforms/SimplifyCFG/X86/merge-compatible-invokes-of-landingpad.ll b/llvm/test/Transforms/SimplifyCFG/X86/merge-compatible-invokes-of-landingpad.ll
index fb4444298461..20ecd03476c6 100644
--- a/llvm/test/Transforms/SimplifyCFG/X86/merge-compatible-invokes-of-landingpad.ll
+++ b/llvm/test/Transforms/SimplifyCFG/X86/merge-compatible-invokes-of-landingpad.ll
@@ -2166,12 +2166,7 @@ define void @t36_
diff erent_indirect_callees(void()* %callee0, void()* %callee1)
; CHECK-LABEL: @t36_
diff erent_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_
diff erent_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_
diff erent_arguments_and_operand_bundes_are_fine(void(i32)* %cal
; CHECK-LABEL: @t38_
diff erent_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_
diff erent_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_
diff erent_arguments_and_operand_bundes_are_fine(void()* %callee
; CHECK-LABEL: @t39_
diff erent_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_
diff erent_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_
diff erent_arguments_and_operand_bundes_are_fine(void(i32)* %cal
; CHECK-LABEL: @t40_
diff erent_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_
diff erent_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()
More information about the llvm-commits
mailing list