summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYevgeny Rouban <yevgeny.rouban@azul.com>2019-02-01 10:44:43 +0000
committerYevgeny Rouban <yevgeny.rouban@azul.com>2019-02-01 10:44:43 +0000
commit15b17d0a7ccdc150e775df5589ebfb67566854f0 (patch)
treebbe230cabd40dd6ce6f017c800e002a15d09f1f4
parent212833ce766fb9b747672b249667e0161e52968c (diff)
downloadbcm5719-llvm-15b17d0a7ccdc150e775df5589ebfb67566854f0.tar.gz
bcm5719-llvm-15b17d0a7ccdc150e775df5589ebfb67566854f0.zip
Provide reason messages for unviable inlining
InlineCost's isInlineViable() is changed to return InlineResult instead of bool. This provides messages for failure reasons and allows to get more specific messages for cases where callsites are not viable for inlining. Reviewed By: xbolva00, anemet Differential Revision: https://reviews.llvm.org/D57089 llvm-svn: 352849
-rw-r--r--clang/test/Frontend/optimization-remark-with-hotness.c2
-rw-r--r--llvm/include/llvm/Analysis/InlineCost.h2
-rw-r--r--llvm/lib/Analysis/InlineCost.cpp23
-rw-r--r--llvm/lib/Target/AMDGPU/AMDGPUInline.cpp5
-rw-r--r--llvm/lib/Transforms/IPO/AlwaysInliner.cpp21
-rw-r--r--llvm/test/Transforms/Inline/inline-remark.ll10
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" }
OpenPOWER on IntegriCloud