[llvm] r321940 - [InlineFunction] Inline vararg functions that do not access varargs.
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Sat Jan 6 11:45:40 PST 2018
Author: fhahn
Date: Sat Jan 6 11:45:40 2018
New Revision: 321940
URL: http://llvm.org/viewvc/llvm-project?rev=321940&view=rev
Log:
[InlineFunction] Inline vararg functions that do not access varargs.
If the varargs are not accessed by a function, we can inline the
function.
Reviewers: dblaikie, chandlerc, davide, efriedma, rnk, hfinkel
Reviewed By: efriedma
Differential Revision: https://reviews.llvm.org/D41335
Added:
llvm/trunk/test/Transforms/Inline/inline-varargs.ll
Removed:
llvm/trunk/test/Transforms/Inline/inline-musttail-varargs.ll
Modified:
llvm/trunk/lib/Analysis/InlineCost.cpp
llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp
Modified: llvm/trunk/lib/Analysis/InlineCost.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InlineCost.cpp?rev=321940&r1=321939&r2=321940&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/InlineCost.cpp (original)
+++ llvm/trunk/lib/Analysis/InlineCost.cpp Sat Jan 6 11:45:40 2018
@@ -136,6 +136,7 @@ class CallAnalyzer : public InstVisitor<
bool HasReturn;
bool HasIndirectBr;
bool HasFrameEscape;
+ bool UsesVarArgs;
/// Number of bytes allocated statically by the callee.
uint64_t AllocatedSize;
@@ -280,7 +281,7 @@ public:
IsCallerRecursive(false), IsRecursiveCall(false),
ExposesReturnsTwice(false), HasDynamicAlloca(false),
ContainsNoDuplicateCall(false), HasReturn(false), HasIndirectBr(false),
- HasFrameEscape(false), AllocatedSize(0), NumInstructions(0),
+ HasFrameEscape(false), UsesVarArgs(false), AllocatedSize(0), NumInstructions(0),
NumVectorInstructions(0), VectorBonus(0), SingleBBBonus(0),
EnableLoadElimination(true), LoadEliminationCost(0), NumConstantArgs(0),
NumConstantOffsetPtrArgs(0), NumAllocaArgs(0), NumConstantPtrCmps(0),
@@ -1233,6 +1234,10 @@ bool CallAnalyzer::visitCallSite(CallSit
case Intrinsic::localescape:
HasFrameEscape = true;
return false;
+ case Intrinsic::vastart:
+ case Intrinsic::vaend:
+ UsesVarArgs = true;
+ return false;
}
}
@@ -1567,7 +1572,7 @@ bool CallAnalyzer::analyzeBlock(BasicBlo
using namespace ore;
// If the visit this instruction detected an uninlinable pattern, abort.
if (IsRecursiveCall || ExposesReturnsTwice || HasDynamicAlloca ||
- HasIndirectBr || HasFrameEscape) {
+ HasIndirectBr || HasFrameEscape || UsesVarArgs) {
if (ORE)
ORE->emit([&]() {
return OptimizationRemarkMissed(DEBUG_TYPE, "NeverInline",
Modified: llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp?rev=321940&r1=321939&r2=321940&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp Sat Jan 6 11:45:40 2018
@@ -1500,10 +1500,9 @@ bool llvm::InlineFunction(CallSite CS, I
IFI.reset();
Function *CalledFunc = CS.getCalledFunction();
- if (!CalledFunc || // Can't inline external function or indirect
- CalledFunc->isDeclaration() ||
- (!ForwardVarArgsTo && CalledFunc->isVarArg())) // call, or call to a vararg function!
- return false;
+ if (!CalledFunc || // Can't inline external function or indirect
+ CalledFunc->isDeclaration()) // call!
+ return false;
// The inliner does not know how to inline through calls with operand bundles
// in general ...
@@ -1630,9 +1629,6 @@ bool llvm::InlineFunction(CallSite CS, I
auto &DL = Caller->getParent()->getDataLayout();
- 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.
CallSite::arg_iterator AI = CS.arg_begin();
@@ -1833,6 +1829,23 @@ bool llvm::InlineFunction(CallSite CS, I
if (!CI)
continue;
+ // Forward varargs from inlined call site to calls to the
+ // ForwardVarArgsTo function, if requested, and to musttail calls.
+ if (!VarArgsToForward.empty() &&
+ ((ForwardVarArgsTo &&
+ CI->getCalledFunction() == ForwardVarArgsTo) ||
+ CI->isMustTailCall())) {
+ SmallVector<Value *, 6> Params(CI->arg_operands());
+ Params.append(VarArgsToForward.begin(), VarArgsToForward.end());
+ CallInst *Call =
+ CallInst::Create(CI->getCalledFunction() ? CI->getCalledFunction()
+ : CI->getCalledValue(),
+ Params, "", CI);
+ Call->setDebugLoc(CI->getDebugLoc());
+ CI->replaceAllUsesWith(Call);
+ CI->eraseFromParent();
+ }
+
if (Function *F = CI->getCalledFunction())
InlinedDeoptimizeCalls |=
F->getIntrinsicID() == Intrinsic::experimental_deoptimize;
@@ -1860,16 +1873,6 @@ bool llvm::InlineFunction(CallSite CS, I
// 'nounwind'.
if (MarkNoUnwind)
CI->setDoesNotThrow();
-
- if (ForwardVarArgsTo && !VarArgsToForward.empty() &&
- CI->getCalledFunction() == ForwardVarArgsTo) {
- SmallVector<Value*, 6> Params(CI->arg_operands());
- Params.append(VarArgsToForward.begin(), VarArgsToForward.end());
- CallInst *Call = CallInst::Create(CI->getCalledFunction(), Params, "", CI);
- Call->setDebugLoc(CI->getDebugLoc());
- CI->replaceAllUsesWith(Call);
- CI->eraseFromParent();
- }
}
}
}
Removed: llvm/trunk/test/Transforms/Inline/inline-musttail-varargs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-musttail-varargs.ll?rev=321939&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-musttail-varargs.ll (original)
+++ llvm/trunk/test/Transforms/Inline/inline-musttail-varargs.ll (removed)
@@ -1,23 +0,0 @@
-; RUN: opt < %s -inline -instcombine -S | FileCheck %s
-; RUN: opt < %s -passes='cgscc(inline,function(instcombine))' -S | FileCheck %s
-
-; We can't inline this thunk yet, but one day we will be able to. And when we
-; do, this test case will be ready.
-
-declare void @ext_method(i8*, i32)
-
-define linkonce_odr void @thunk(i8* %this, ...) {
- %this_adj = getelementptr i8, i8* %this, i32 4
- musttail call void (i8*, ...) bitcast (void (i8*, i32)* @ext_method to void (i8*, ...)*)(i8* %this_adj, ...)
- ret void
-}
-
-define void @thunk_caller(i8* %p) {
- call void (i8*, ...) @thunk(i8* %p, i32 42)
- ret void
-}
-; CHECK-LABEL: define void @thunk_caller(i8* %p)
-; CHECK: call void (i8*, ...) @thunk(i8* %p, i32 42)
-
-; FIXME: Inline the thunk. This should be significantly easier than inlining
-; general varargs functions.
Added: llvm/trunk/test/Transforms/Inline/inline-varargs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-varargs.ll?rev=321940&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-varargs.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-varargs.ll Sat Jan 6 11:45:40 2018
@@ -0,0 +1,52 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline,function(instcombine))' -S | FileCheck %s
+
+declare void @ext_method(i8*, i32)
+declare void @vararg_fn(i8*, ...)
+
+define linkonce_odr void @thunk(i8* %this, ...) {
+ %this_adj = getelementptr i8, i8* %this, i32 4
+ musttail call void (i8*, ...) bitcast (void (i8*, i32)* @ext_method to void (i8*, ...)*)(i8* %this_adj, ...)
+ ret void
+}
+
+define void @thunk_caller(i8* %p) {
+ call void (i8*, ...) @thunk(i8* %p, i32 42)
+ ret void
+}
+; CHECK-LABEL: define void @thunk_caller(i8* %p)
+; CHECK: call void (i8*, ...) bitcast (void (i8*, i32)* @ext_method to void (i8*, ...)*)(i8* %this_adj.i, i32 42)
+
+define void @test_callee_2(i8* %this, ...) {
+ %this_adj = getelementptr i8, i8* %this, i32 4
+ musttail call void (i8*, ...) @vararg_fn(i8* %this_adj, ...)
+ ret void
+}
+
+define void @test_caller_2(i8* %p) {
+ call void (i8*, ...) @test_callee_2(i8* %p)
+ ret void
+}
+; CHECK-LABEL: define void @test_caller_2(i8* %p)
+; CHECK: call void (i8*, ...) @vararg_fn(i8* %this_adj.i)
+
+
+define internal i32 @varg_accessed(...) {
+entry:
+ %vargs = alloca i8*, align 8
+ %vargs.ptr = bitcast i8** %vargs to i8*
+ call void @llvm.va_start(i8* %vargs.ptr)
+ %va1 = va_arg i8** %vargs, i32
+ call void @llvm.va_end(i8* %vargs.ptr)
+ ret i32 %va1
+}
+
+define i32 @call_vargs() {
+ %res = call i32 (...) @varg_accessed(i32 10)
+ ret i32 %res
+}
+; CHECK-LABEL: @call_vargs
+; CHECK: %res = call i32 (...) @varg_accessed(i32 10)
+
+declare void @llvm.va_start(i8*)
+declare void @llvm.va_end(i8*)
More information about the llvm-commits
mailing list