diff options
| -rw-r--r-- | clang/test/Frontend/optimization-remark-with-hotness.c | 2 | ||||
| -rw-r--r-- | llvm/include/llvm/Analysis/InlineCost.h | 2 | ||||
| -rw-r--r-- | llvm/lib/Analysis/InlineCost.cpp | 23 | ||||
| -rw-r--r-- | llvm/lib/Target/AMDGPU/AMDGPUInline.cpp | 5 | ||||
| -rw-r--r-- | llvm/lib/Transforms/IPO/AlwaysInliner.cpp | 21 | ||||
| -rw-r--r-- | llvm/test/Transforms/Inline/inline-remark.ll | 10 |
6 files changed, 44 insertions, 19 deletions
diff --git a/clang/test/Frontend/optimization-remark-with-hotness.c b/clang/test/Frontend/optimization-remark-with-hotness.c index 150b7324da5..5f4c83b46c8 100644 --- a/clang/test/Frontend/optimization-remark-with-hotness.c +++ b/clang/test/Frontend/optimization-remark-with-hotness.c @@ -66,7 +66,7 @@ void bar(int x) { int main(int argc, const char *argv[]) { for (int i = 0; i < 30; i++) - // expected-remark@+1 {{bar not inlined into main because it should never be inlined (cost=never): always inliner (hotness:}} + // expected-remark@+1 {{bar not inlined into main because it should never be inlined (cost=never): no alwaysinline attribute (hotness:}} bar(argc); return sum; } diff --git a/llvm/include/llvm/Analysis/InlineCost.h b/llvm/include/llvm/Analysis/InlineCost.h index 038d7f764ad..e3860933516 100644 --- a/llvm/include/llvm/Analysis/InlineCost.h +++ b/llvm/include/llvm/Analysis/InlineCost.h @@ -231,7 +231,7 @@ getInlineCost(CallSite CS, Function *Callee, const InlineParams &Params, ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE); /// Minimal filter to detect invalid constructs for inlining. -bool isInlineViable(Function &Callee); +InlineResult isInlineViable(Function &Callee); } #endif diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp index 48666566dd9..c66b9f38942 100644 --- a/llvm/lib/Analysis/InlineCost.cpp +++ b/llvm/lib/Analysis/InlineCost.cpp @@ -2022,9 +2022,10 @@ InlineCost llvm::getInlineCost( // Calls to functions with always-inline attributes should be inlined // whenever possible. if (CS.hasFnAttr(Attribute::AlwaysInline)) { - if (isInlineViable(*Callee)) + auto IsViable = isInlineViable(*Callee); + if (IsViable) return llvm::InlineCost::getAlways("always inline attribute"); - return llvm::InlineCost::getNever("inapplicable always inline attribute"); + return llvm::InlineCost::getNever(IsViable.message); } // Never inline functions with conflicting attributes (unless callee has @@ -2072,14 +2073,16 @@ InlineCost llvm::getInlineCost( return llvm::InlineCost::get(CA.getCost(), CA.getThreshold()); } -bool llvm::isInlineViable(Function &F) { +InlineResult llvm::isInlineViable(Function &F) { bool ReturnsTwice = F.hasFnAttribute(Attribute::ReturnsTwice); for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; ++BI) { // Disallow inlining of functions which contain indirect branches or // blockaddresses. - if (isa<IndirectBrInst>(BI->getTerminator()) || - BI->hasAddressTaken()) - return false; + if (isa<IndirectBrInst>(BI->getTerminator())) + return "contains indirect branches"; + + if (BI->hasAddressTaken()) + return "uses block address"; for (auto &II : *BI) { CallSite CS(&II); @@ -2088,13 +2091,13 @@ bool llvm::isInlineViable(Function &F) { // Disallow recursive calls. if (&F == CS.getCalledFunction()) - return false; + return "recursive call"; // Disallow calls which expose returns-twice to a function not previously // attributed as such. if (!ReturnsTwice && CS.isCall() && cast<CallInst>(CS.getInstruction())->canReturnTwice()) - return false; + return "exposes returns-twice attribute"; if (CS.getCalledFunction()) switch (CS.getCalledFunction()->getIntrinsicID()) { @@ -2103,12 +2106,14 @@ bool llvm::isInlineViable(Function &F) { // Disallow inlining of @llvm.icall.branch.funnel because current // backend can't separate call targets from call arguments. case llvm::Intrinsic::icall_branch_funnel: + return "disallowed inlining of @llvm.icall.branch.funnel"; // Disallow inlining functions that call @llvm.localescape. Doing this // correctly would require major changes to the inliner. case llvm::Intrinsic::localescape: + return "disallowed inlining of @llvm.localescape"; // Disallow inlining of functions that initialize VarArgs with va_start. case llvm::Intrinsic::vastart: - return false; + return "contains VarArgs initialized with va_start"; } } } diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInline.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInline.cpp index 5f518d7dfe2..0ad78e036a1 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUInline.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUInline.cpp @@ -181,9 +181,10 @@ InlineCost AMDGPUInliner::getInlineCost(CallSite CS) { return llvm::InlineCost::getNever("incompatible"); if (CS.hasFnAttr(Attribute::AlwaysInline)) { - if (isInlineViable(*Callee)) + auto IsViable = isInlineViable(*Callee); + if (IsViable) return llvm::InlineCost::getAlways("alwaysinline viable"); - return llvm::InlineCost::getNever("alwaysinline unviable"); + return llvm::InlineCost::getNever(IsViable.message); } if (isWrapperOnlyCall(CS)) diff --git a/llvm/lib/Transforms/IPO/AlwaysInliner.cpp b/llvm/lib/Transforms/IPO/AlwaysInliner.cpp index c7697556530..0058bb9832a 100644 --- a/llvm/lib/Transforms/IPO/AlwaysInliner.cpp +++ b/llvm/lib/Transforms/IPO/AlwaysInliner.cpp @@ -145,11 +145,20 @@ InlineCost AlwaysInlinerLegacyPass::getInlineCost(CallSite CS) { Function *Callee = CS.getCalledFunction(); // Only inline direct calls to functions with always-inline attributes - // that are viable for inlining. FIXME: We shouldn't even get here for - // declarations. - if (Callee && !Callee->isDeclaration() && - CS.hasFnAttr(Attribute::AlwaysInline) && isInlineViable(*Callee)) - return InlineCost::getAlways("always inliner"); + // that are viable for inlining. + if (!Callee) + return InlineCost::getNever("indirect call"); - return InlineCost::getNever("always inliner"); + // FIXME: We shouldn't even get here for declarations. + if (Callee->isDeclaration()) + return InlineCost::getNever("no definition"); + + if (!CS.hasFnAttr(Attribute::AlwaysInline)) + return InlineCost::getNever("no alwaysinline attribute"); + + auto IsViable = isInlineViable(*Callee); + if (!IsViable) + return InlineCost::getNever(IsViable.message); + + return InlineCost::getAlways("always inliner"); } diff --git a/llvm/test/Transforms/Inline/inline-remark.ll b/llvm/test/Transforms/Inline/inline-remark.ll index 402493542dc..bfb78c9ee88 100644 --- a/llvm/test/Transforms/Inline/inline-remark.ll +++ b/llvm/test/Transforms/Inline/inline-remark.ll @@ -46,6 +46,16 @@ define void @test2(i8*) { ret void } +;; Test 3 - InlineResult messages come from llvm::isInlineViable() +define void @test3() { +; CHECK-LABEL: @test3 +; CHECK-NEXT: call void @test3() [[ATTR4:#[0-9]+]] +; CHECK-NEXT: ret void + call void @test3() alwaysinline + ret void +} + ; CHECK: attributes [[ATTR1]] = { "inline-remark"="(cost=25, threshold=0)" } ; CHECK: attributes [[ATTR2]] = { "inline-remark"="(cost=never): recursive" } ; CHECK: attributes [[ATTR3]] = { "inline-remark"="unsupported operand bundle; (cost={{.*}}, threshold={{.*}})" } +; CHECK: attributes [[ATTR4]] = { alwaysinline "inline-remark"="(cost=never): recursive call" } |

