From fdf79b6770dae3af68ea2ba146b736bd78fe8322 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Sun, 28 Jan 2018 19:11:49 +0000 Subject: [PATCH] [InlineCost] Mark functions accessing varargs as not viable. This prevents functions accessing varargs from being inlined if they have the alwaysinline attribute. Reviewers: efriedma, rnk, davide Reviewed By: efriedma Differential Revision: https://reviews.llvm.org/D42556 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@323619 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/InlineCost.cpp | 18 ++++++++++++------ test/Transforms/Inline/inline-varargs.ll | 17 +++++++++++++++-- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/lib/Analysis/InlineCost.cpp b/lib/Analysis/InlineCost.cpp index 0e7be52cae7..b0e0acd3629 100644 --- a/lib/Analysis/InlineCost.cpp +++ b/lib/Analysis/InlineCost.cpp @@ -2040,12 +2040,18 @@ bool llvm::isInlineViable(Function &F) { cast(CS.getInstruction())->canReturnTwice()) return false; - // Disallow inlining functions that call @llvm.localescape. Doing this - // correctly would require major changes to the inliner. - if (CS.getCalledFunction() && - CS.getCalledFunction()->getIntrinsicID() == - llvm::Intrinsic::localescape) - return false; + if (CS.getCalledFunction()) + switch (CS.getCalledFunction()->getIntrinsicID()) { + default: + break; + // Disallow inlining functions that call @llvm.localescape. Doing this + // correctly would require major changes to the inliner. + case llvm::Intrinsic::localescape: + // Disallow inlining of functions that access VarArgs. + case llvm::Intrinsic::vastart: + case llvm::Intrinsic::vaend: + return false; + } } } diff --git a/test/Transforms/Inline/inline-varargs.ll b/test/Transforms/Inline/inline-varargs.ll index 215f4007b73..e84db690eb4 100644 --- a/test/Transforms/Inline/inline-varargs.ll +++ b/test/Transforms/Inline/inline-varargs.ll @@ -64,12 +64,25 @@ entry: ret i32 %va1 } +define internal i32 @varg_accessed_alwaysinline(...) alwaysinline { +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) + %res1 = call i32 (...) @varg_accessed(i32 10) + %res2 = call i32 (...) @varg_accessed_alwaysinline(i32 15) + %res = add i32 %res1, %res2 ret i32 %res } ; CHECK-LABEL: @call_vargs -; CHECK: %res = call i32 (...) @varg_accessed(i32 10) +; CHECK: %res1 = call i32 (...) @varg_accessed(i32 10) +; CHECK-NEXT: %res2 = call i32 (...) @varg_accessed_alwaysinline(i32 15) declare void @llvm.va_start(i8*) declare void @llvm.va_end(i8*)