aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/InlineFunction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/Utils/InlineFunction.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/InlineFunction.cpp28
1 files changed, 22 insertions, 6 deletions
diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp
index 6b1391e..23a72e8 100644
--- a/llvm/lib/Transforms/Utils/InlineFunction.cpp
+++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp
@@ -1490,7 +1490,8 @@ static void updateCalleeCount(BlockFrequencyInfo *CallerBFI, BasicBlock *CallBB,
/// exists in the instruction stream. Similarly this will inline a recursive
/// function by one level.
bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
- AAResults *CalleeAAR, bool InsertLifetime) {
+ AAResults *CalleeAAR, bool InsertLifetime,
+ Function *ForwardVarArgsTo) {
Instruction *TheCall = CS.getInstruction();
assert(TheCall->getParent() && TheCall->getFunction()
&& "Instruction not in function!");
@@ -1500,8 +1501,9 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
Function *CalledFunc = CS.getCalledFunction();
if (!CalledFunc || // Can't inline external function or indirect
- CalledFunc->isDeclaration() || // call, or call to a vararg function!
- CalledFunc->getFunctionType()->isVarArg()) return false;
+ CalledFunc->isDeclaration() ||
+ (!ForwardVarArgsTo && CalledFunc->isVarArg())) // call, or call to a vararg function!
+ return false;
// The inliner does not know how to inline through calls with operand bundles
// in general ...
@@ -1628,8 +1630,8 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
auto &DL = Caller->getParent()->getDataLayout();
- assert(CalledFunc->arg_size() == CS.arg_size() &&
- "No varargs calls can be inlined!");
+ assert((CalledFunc->arg_size() == CS.arg_size() || ForwardVarArgsTo) &&
+ "Varargs calls can only be inlined if the Varargs are forwarded!");
// Calculate the vector of arguments to pass into the function cloner, which
// matches up the formal to the actual argument values.
@@ -1811,6 +1813,11 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
replaceDbgDeclareForAlloca(AI, AI, DIB, /*Deref=*/false);
}
+ SmallVector<Value*,4> VarArgsToForward;
+ for (unsigned i = CalledFunc->getFunctionType()->getNumParams();
+ i < CS.getNumArgOperands(); i++)
+ VarArgsToForward.push_back(CS.getArgOperand(i));
+
bool InlinedMustTailCalls = false, InlinedDeoptimizeCalls = false;
if (InlinedFunctionInfo.ContainsCalls) {
CallInst::TailCallKind CallSiteTailKind = CallInst::TCK_None;
@@ -1819,7 +1826,8 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
for (Function::iterator BB = FirstNewBlock, E = Caller->end(); BB != E;
++BB) {
- for (Instruction &I : *BB) {
+ for (auto II = BB->begin(); II != BB->end();) {
+ Instruction &I = *II++;
CallInst *CI = dyn_cast<CallInst>(&I);
if (!CI)
continue;
@@ -1850,6 +1858,14 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
// 'nounwind'.
if (MarkNoUnwind)
CI->setDoesNotThrow();
+
+ if (ForwardVarArgsTo && CI->getCalledFunction() == ForwardVarArgsTo) {
+ SmallVector<Value*, 6> Params(CI->arg_operands());
+ Params.append(VarArgsToForward.begin(), VarArgsToForward.end());
+ CallInst *Call = CallInst::Create(CI->getCalledFunction(), Params, "", CI);
+ CI->replaceAllUsesWith(Call);
+ CI->eraseFromParent();
+ }
}
}
}