diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -34,6 +34,7 @@ #include "llvm/Analysis/MemorySSAUpdater.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Analysis/ValueTracking.h" +#include "llvm/IR/AbstractCallSite.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CFG.h" @@ -2057,7 +2058,13 @@ // actually sink before encountering instruction that is unprofitable to sink? auto ProfitableToSinkInstruction = [&](LockstepReverseIterator &LRI) { unsigned NumPHIdValues = 0; - for (auto *I : *LRI) + for (auto *I : *LRI) { + // Sinking indirect calls prevents us from replacing the indirect call + // with a direct call once the callee is known. + if (auto *CB = dyn_cast(I)) + if (AbstractCallSite ACS = &CB->getCalledOperandUse()) + if (ACS.isIndirectCall()) + return false; for (auto *V : PHIOperands[I]) { if (InstructionsToSink.count(V) == 0) ++NumPHIdValues; @@ -2065,6 +2072,7 @@ // said instruction, due to the very same profitability check. // See @creating_too_many_phis in sink-common-code.ll. } + } LLVM_DEBUG(dbgs() << "SINK: #phid values: " << NumPHIdValues << "\n"); unsigned NumPHIInsts = NumPHIdValues / UnconditionalPreds.size(); if ((NumPHIdValues % UnconditionalPreds.size()) != 0) diff --git a/llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll b/llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll --- a/llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll +++ b/llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll @@ -1406,9 +1406,14 @@ define void @indirect_caller(i1 %c, i32 %v, void (i32)* %foo, void (i32)* %bar) { ; CHECK-LABEL: @indirect_caller( -; CHECK-NEXT: end: -; CHECK-NEXT: [[FOO_BAR:%.*]] = select i1 [[C:%.*]], void (i32)* [[FOO:%.*]], void (i32)* [[BAR:%.*]] -; CHECK-NEXT: tail call void [[FOO_BAR]](i32 [[V:%.*]]) +; 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: ret void ; br i1 %c, label %call_foo, label %call_bar