1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00

[SimplifyCFG] Try 2: sink all-indirect indirect calls

Note that we don't want to turn a partially-direct call
into an indirect one, that will break ICP amongst other things.
This commit is contained in:
Roman Lebedev 2021-04-28 18:28:39 +03:00
parent 212ed808d3
commit 3b2bd88e88
2 changed files with 29 additions and 13 deletions

View File

@ -1733,6 +1733,32 @@ static bool canSinkInstructions(
}))
return false;
// For calls to be sinkable, they must all be indirect, or have same callee.
// I.e. if we have two direct calls to different callees, we don't want to
// turn that into an indirect call. Likewise, if we have an indirect call,
// and a direct call, we don't actually want to have a single indirect call.
if (isa<CallBase>(I0)) {
auto IsIndirectCall = [](const Instruction *I) {
return cast<CallBase>(I)->isIndirectCall();
};
bool HaveIndirectCalls = any_of(Insts, IsIndirectCall);
bool AllCallsAreIndirect = all_of(Insts, IsIndirectCall);
if (HaveIndirectCalls) {
if (!AllCallsAreIndirect)
return false;
} else {
// All callees must be identical.
Value *Callee = nullptr;
for (const Instruction *I : Insts) {
Value *CurrCallee = cast<CallBase>(I)->getCalledOperand();
if (!Callee)
Callee = CurrCallee;
else if (Callee != CurrCallee)
return false;
}
}
}
for (unsigned OI = 0, OE = I0->getNumOperands(); OI != OE; ++OI) {
Value *Op = I0->getOperand(OI);
if (Op->getType()->isTokenTy())
@ -1748,11 +1774,6 @@ static bool canSinkInstructions(
!canReplaceOperandWithVariable(I0, OI))
// We can't create a PHI from this GEP.
return false;
// Don't create indirect calls! The called value is the final operand.
if (isa<CallBase>(I0) && OI == OE - 1) {
// FIXME: if the call was *already* indirect, we should do this.
return false;
}
for (auto *I : Insts)
PHIOperands[I].push_back(I->getOperand(OI));
}

View File

@ -1409,14 +1409,9 @@ end:
define void @indirect_caller(i1 %c, i32 %v, void (i32)* %foo, void (i32)* %bar) {
; CHECK-LABEL: @indirect_caller(
; CHECK-NEXT: br i1 [[C:%.*]], label [[CALL_FOO:%.*]], label [[CALL_BAR:%.*]]
; CHECK: call_foo:
; CHECK-NEXT: tail call void [[FOO:%.*]](i32 [[V:%.*]])
; CHECK-NEXT: br label [[END:%.*]]
; CHECK: call_bar:
; CHECK-NEXT: tail call void [[BAR:%.*]](i32 [[V]])
; CHECK-NEXT: br label [[END]]
; CHECK: end:
; CHECK-NEXT: end:
; CHECK-NEXT: [[BAR_SINK:%.*]] = select i1 [[C:%.*]], void (i32)* [[FOO:%.*]], void (i32)* [[BAR:%.*]]
; CHECK-NEXT: tail call void [[BAR_SINK]](i32 [[V:%.*]])
; CHECK-NEXT: ret void
;
br i1 %c, label %call_foo, label %call_bar