summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEaswaran Raman <eraman@google.com>2015-12-22 00:32:35 +0000
committerEaswaran Raman <eraman@google.com>2015-12-22 00:32:35 +0000
commitbdb6f1dcc39c35882b2b7e22c820a88a179cad75 (patch)
tree415f4233b4b97d00e2eee94dea56c68723ba96b2
parent8827f2db855054b64a0944b39f8376ac317daf1f (diff)
downloadbcm5719-llvm-bdb6f1dcc39c35882b2b7e22c820a88a179cad75.tar.gz
bcm5719-llvm-bdb6f1dcc39c35882b2b7e22c820a88a179cad75.zip
Determine callee's hotness and adjust threshold based on that. NFC.
This uses the same criteria used in CFE's CodeGenPGO to identify hot and cold callees and uses values of inlinehint-threshold and inlinecold-threshold respectively as the thresholds for such callees. Differential Revision: http://reviews.llvm.org/D15245 llvm-svn: 256222
-rw-r--r--llvm/lib/Transforms/IPO/Inliner.cpp38
-rw-r--r--llvm/test/Transforms/Inline/inline-cold-callee.ll39
-rw-r--r--llvm/test/Transforms/Inline/inline-hot-callee.ll39
3 files changed, 109 insertions, 7 deletions
diff --git a/llvm/lib/Transforms/IPO/Inliner.cpp b/llvm/lib/Transforms/IPO/Inliner.cpp
index 14b1767721d..54505017136 100644
--- a/llvm/lib/Transforms/IPO/Inliner.cpp
+++ b/llvm/lib/Transforms/IPO/Inliner.cpp
@@ -288,18 +288,42 @@ unsigned Inliner::getInlineThreshold(CallSite CS) const {
OptSizeThreshold < Threshold)
Threshold = OptSizeThreshold;
- // Listen to the inlinehint attribute when it would increase the threshold
- // and the caller does not need to minimize its size.
Function *Callee = CS.getCalledFunction();
- bool InlineHint = Callee && !Callee->isDeclaration() &&
- Callee->hasFnAttribute(Attribute::InlineHint);
+ if (!Callee || Callee->isDeclaration())
+ return Threshold;
+
+ // If profile information is available, use that to adjust threshold of hot
+ // and cold functions.
+ // FIXME: The heuristic used below for determining hotness and coldness are
+ // based on preliminary SPEC tuning and may not be optimal. Replace this with
+ // a well-tuned heuristic based on *callsite* hotness and not callee hotness.
+ uint64_t FunctionCount = 0, MaxFunctionCount = 0;
+ bool HasPGOCounts = false;
+ if (Callee->getEntryCount() &&
+ Callee->getParent()->getMaximumFunctionCount()) {
+ HasPGOCounts = true;
+ FunctionCount = Callee->getEntryCount().getValue();
+ MaxFunctionCount =
+ Callee->getParent()->getMaximumFunctionCount().getValue();
+ }
+
+ // Listen to the inlinehint attribute or profile based hotness information
+ // when it would increase the threshold and the caller does not need to
+ // minimize its size.
+ bool InlineHint =
+ Callee->hasFnAttribute(Attribute::InlineHint) ||
+ (HasPGOCounts &&
+ FunctionCount >= (uint64_t)(0.3 * (double)MaxFunctionCount));
if (InlineHint && HintThreshold > Threshold &&
!Caller->hasFnAttribute(Attribute::MinSize))
Threshold = HintThreshold;
- // Listen to the cold attribute when it would decrease the threshold.
- bool ColdCallee = Callee && !Callee->isDeclaration() &&
- Callee->hasFnAttribute(Attribute::Cold);
+ // Listen to the cold attribute or profile based coldness information
+ // when it would decrease the threshold.
+ bool ColdCallee =
+ Callee->hasFnAttribute(Attribute::Cold) ||
+ (HasPGOCounts &&
+ FunctionCount <= (uint64_t)(0.01 * (double)MaxFunctionCount));
// Command line argument for InlineLimit will override the default
// ColdThreshold. If we have -inline-threshold but no -inlinecold-threshold,
// do not use the default cold threshold even if it is smaller.
diff --git a/llvm/test/Transforms/Inline/inline-cold-callee.ll b/llvm/test/Transforms/Inline/inline-cold-callee.ll
new file mode 100644
index 00000000000..1fd9f105db5
--- /dev/null
+++ b/llvm/test/Transforms/Inline/inline-cold-callee.ll
@@ -0,0 +1,39 @@
+; RUN: opt < %s -inline -inlinecold-threshold=0 -S | FileCheck %s
+
+; This tests that a cold callee gets the (lower) inlinecold-threshold even without
+; Cold hint and does not get inlined because the cost exceeds the inlinecold-threshold.
+; A callee with identical body does gets inlined because cost fits within the
+; inline-threshold
+
+define i32 @callee1(i32 %x) !prof !1 {
+ %x1 = add i32 %x, 1
+ %x2 = add i32 %x1, 1
+ %x3 = add i32 %x2, 1
+
+ ret i32 %x3
+}
+
+define i32 @callee2(i32 %x) !prof !2 {
+; CHECK-LABEL: @callee2(
+ %x1 = add i32 %x, 1
+ %x2 = add i32 %x1, 1
+ %x3 = add i32 %x2, 1
+
+ ret i32 %x3
+}
+
+define i32 @caller2(i32 %y1) !prof !2 {
+; CHECK-LABEL: @caller2(
+; CHECK: call i32 @callee2
+; CHECK-NOT: call i32 @callee1
+; CHECK: ret i32 %x3.i
+ %y2 = call i32 @callee2(i32 %y1)
+ %y3 = call i32 @callee1(i32 %y2)
+ ret i32 %y3
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"MaxFunctionCount", i32 1000}
+!1 = !{!"function_entry_count", i64 100}
+!2 = !{!"function_entry_count", i64 1}
+
diff --git a/llvm/test/Transforms/Inline/inline-hot-callee.ll b/llvm/test/Transforms/Inline/inline-hot-callee.ll
new file mode 100644
index 00000000000..93ea9d43c78
--- /dev/null
+++ b/llvm/test/Transforms/Inline/inline-hot-callee.ll
@@ -0,0 +1,39 @@
+; RUN: opt < %s -inline -inline-threshold=0 -inlinehint-threshold=100 -S | FileCheck %s
+
+; This tests that a hot callee gets the (higher) inlinehint-threshold even without
+; inline hints and gets inlined because the cost is less than inlinehint-threshold.
+; A cold callee with identical body does not get inlined because cost exceeds the
+; inline-threshold
+
+define i32 @callee1(i32 %x) !prof !1 {
+ %x1 = add i32 %x, 1
+ %x2 = add i32 %x1, 1
+ %x3 = add i32 %x2, 1
+
+ ret i32 %x3
+}
+
+define i32 @callee2(i32 %x) !prof !2 {
+; CHECK-LABEL: @callee2(
+ %x1 = add i32 %x, 1
+ %x2 = add i32 %x1, 1
+ %x3 = add i32 %x2, 1
+
+ ret i32 %x3
+}
+
+define i32 @caller2(i32 %y1) !prof !2 {
+; CHECK-LABEL: @caller2(
+; CHECK: call i32 @callee2
+; CHECK-NOT: call i32 @callee1
+; CHECK: ret i32 %x3.i
+ %y2 = call i32 @callee2(i32 %y1)
+ %y3 = call i32 @callee1(i32 %y2)
+ ret i32 %y3
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"MaxFunctionCount", i32 10}
+!1 = !{!"function_entry_count", i64 10}
+!2 = !{!"function_entry_count", i64 1}
+
OpenPOWER on IntegriCloud