summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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