<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On 5 February 2014 12:40, Manman Ren <span dir="ltr"><<a href="mailto:manman.ren@gmail.com" target="_blank">manman.ren@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: mren<br>
Date: Wed Feb 5 14:40:15 2014<br>
New Revision: 200874<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=200874&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=200874&view=rev</a><br>
Log:<br>
PGO: instrumentation based profiling sets function attributes.<br>
<br>
We collect a maximal function count among all functions in the pgo data file.<br>
For functions that are hot, we set its InlineHint attribute. For functions that<br>
are cold, we set its Cold attribute.<br>
<br>
We currently treat functions with >= 30% of the maximal function count as hot<br>
and functions with <= 1% of the maximal function count are treated as cold.<br>
These two numbers are from preliminary tuning on SPEC.<br>
<br>
This commit should not affect non-PGO builds and should boost performance on<br>
instrumentation based PGO.<br>
<br>
Added:<br>
cfe/trunk/test/CodeGen/Inputs/instr-attribute.pgodata<br>
cfe/trunk/test/CodeGen/instr-attribute.c<br>
Modified:<br>
cfe/trunk/lib/CodeGen/CodeGenFunction.cpp<br>
cfe/trunk/lib/CodeGen/CodeGenPGO.cpp<br>
cfe/trunk/lib/CodeGen/CodeGenPGO.h<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=200874&r1=200873&r2=200874&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=200874&r1=200873&r2=200874&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Wed Feb 5 14:40:15 2014<br>
@@ -591,6 +591,16 @@ void CodeGenFunction::StartFunction(Glob<br>
EmitMCountInstrumentation();<br>
<br>
PGO.assignRegionCounters(GD);<br>
+ if (CGM.getPGOData()) {<br>
+ if (const Decl *D = GD.getDecl()) {<br></blockquote><div><br></div><div>-Werror, unused variable 'D'.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ // Turn on InlineHint attribute for hot functions.<br>
+ if (CGM.getPGOData()->isHotFunction(CGM.getMangledName(GD)))<br></blockquote><div><br></div><div>Do you want to pass "D" here instead, or remove the "const Decl *D =" part from the if-statement above?</div>
<div><br></div><div>Nick</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ Fn->addFnAttr(llvm::Attribute::InlineHint);<br>
+ // Turn on Cold attribute for cold functions.<br>
+ else if (CGM.getPGOData()->isColdFunction(CGM.getMangledName(GD)))<br>
+ Fn->addFnAttr(llvm::Attribute::Cold);<br>
+ }<br>
+ }<br>
<br>
if (RetTy->isVoidType()) {<br>
// Void type; nothing to return.<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CodeGenPGO.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenPGO.cpp?rev=200874&r1=200873&r2=200874&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenPGO.cpp?rev=200874&r1=200873&r2=200874&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CodeGenPGO.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CodeGenPGO.cpp Wed Feb 5 14:40:15 2014<br>
@@ -45,6 +45,7 @@ PGOProfileData::PGOProfileData(CodeGenMo<br>
const char *BufferStart = DataBuffer->getBufferStart();<br>
const char *BufferEnd = DataBuffer->getBufferEnd();<br>
const char *CurPtr = BufferStart;<br>
+ uint64_t MaxCount = 0;<br>
while (CurPtr < BufferEnd) {<br>
// Read the mangled function name.<br>
const char *FuncName = CurPtr;<br>
@@ -65,8 +66,19 @@ PGOProfileData::PGOProfileData(CodeGenMo<br>
}<br>
CurPtr = EndPtr;<br>
<br>
+ // Read function count.<br>
+ uint64_t Count = strtoll(CurPtr, &EndPtr, 10);<br>
+ if (EndPtr == CurPtr || *EndPtr != '\n') {<br>
+ ReportBadPGOData(CGM, "pgo-data file has bad count value");<br>
+ return;<br>
+ }<br>
+ CurPtr = EndPtr + 1;<br>
+ FunctionCounts[MangledName] = Count;<br>
+ MaxCount = Count > MaxCount ? Count : MaxCount;<br>
+<br>
// There is one line for each counter; skip over those lines.<br>
- for (unsigned N = 0; N < NumCounters; ++N) {<br>
+ // Since function count is already read, we start the loop from 1.<br>
+ for (unsigned N = 1; N < NumCounters; ++N) {<br>
CurPtr = strchr(++CurPtr, '\n');<br>
if (!CurPtr) {<br>
ReportBadPGOData(CGM, "pgo data file is missing some counter info");<br>
@@ -79,6 +91,33 @@ PGOProfileData::PGOProfileData(CodeGenMo<br>
<br>
DataOffsets[MangledName] = FuncName - BufferStart;<br>
}<br>
+ MaxFunctionCount = MaxCount;<br>
+}<br>
+<br>
+/// Return true if a function is hot. If we know nothing about the function,<br>
+/// return false.<br>
+bool PGOProfileData::isHotFunction(StringRef MangledName) {<br>
+ llvm::StringMap<uint64_t>::const_iterator CountIter =<br>
+ FunctionCounts.find(MangledName);<br>
+ // If we know nothing about the function, return false.<br>
+ if (CountIter == FunctionCounts.end())<br>
+ return false;<br>
+ // FIXME: functions with >= 30% of the maximal function count are<br>
+ // treated as hot. This number is from preliminary tuning on SPEC.<br>
+ return CountIter->getValue() >= (uint64_t)(0.3 * (double)MaxFunctionCount);<br>
+}<br>
+<br>
+/// Return true if a function is cold. If we know nothing about the function,<br>
+/// return false.<br>
+bool PGOProfileData::isColdFunction(StringRef MangledName) {<br>
+ llvm::StringMap<uint64_t>::const_iterator CountIter =<br>
+ FunctionCounts.find(MangledName);<br>
+ // If we know nothing about the function, return false.<br>
+ if (CountIter == FunctionCounts.end())<br>
+ return false;<br>
+ // FIXME: functions with <= 1% of the maximal function count are treated as<br>
+ // cold. This number is from preliminary tuning on SPEC.<br>
+ return CountIter->getValue() <= (uint64_t)(0.01 * (double)MaxFunctionCount);<br>
}<br>
<br>
bool PGOProfileData::getFunctionCounts(StringRef MangledName,<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CodeGenPGO.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenPGO.h?rev=200874&r1=200873&r2=200874&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenPGO.h?rev=200874&r1=200873&r2=200874&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CodeGenPGO.h (original)<br>
+++ cfe/trunk/lib/CodeGen/CodeGenPGO.h Wed Feb 5 14:40:15 2014<br>
@@ -33,12 +33,22 @@ private:<br>
llvm::OwningPtr<llvm::MemoryBuffer> DataBuffer;<br>
/// Offsets into DataBuffer for each function's counters<br>
llvm::StringMap<unsigned> DataOffsets;<br>
+ /// Execution counts for each function.<br>
+ llvm::StringMap<uint64_t> FunctionCounts;<br>
+ /// The maximal execution count among all functions.<br>
+ uint64_t MaxFunctionCount;<br>
CodeGenModule &CGM;<br>
public:<br>
PGOProfileData(CodeGenModule &CGM, std::string Path);<br>
/// Fill Counts with the profile data for the given function name. Returns<br>
/// false on success.<br>
bool getFunctionCounts(StringRef MangledName, std::vector<uint64_t> &Counts);<br>
+ /// Return true if a function is hot. If we know nothing about the function,<br>
+ /// return false.<br>
+ bool isHotFunction(StringRef MangledName);<br>
+ /// Return true if a function is cold. If we know nothing about the function,<br>
+ /// return false.<br>
+ bool isColdFunction(StringRef MangledName);<br>
};<br>
<br>
/// Per-function PGO state. This class should generally not be used directly,<br>
<br>
Added: cfe/trunk/test/CodeGen/Inputs/instr-attribute.pgodata<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/Inputs/instr-attribute.pgodata?rev=200874&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/Inputs/instr-attribute.pgodata?rev=200874&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGen/Inputs/instr-attribute.pgodata (added)<br>
+++ cfe/trunk/test/CodeGen/Inputs/instr-attribute.pgodata Wed Feb 5 14:40:15 2014<br>
@@ -0,0 +1,39 @@<br>
+hot_100_percent 4<br>
+100000<br>
+4999950000<br>
+0<br>
+0<br>
+<br>
+hot_40_percent 4<br>
+40000<br>
+799980000<br>
+0<br>
+0<br>
+<br>
+normal_func 4<br>
+20000<br>
+199990000<br>
+0<br>
+0<br>
+<br>
+cold_func 4<br>
+500<br>
+124750<br>
+0<br>
+0<br>
+<br>
+main 13<br>
+1<br>
+100000<br>
+0<br>
+0<br>
+40000<br>
+0<br>
+0<br>
+20000<br>
+0<br>
+0<br>
+500<br>
+0<br>
+0<br>
+<br>
<br>
Added: cfe/trunk/test/CodeGen/instr-attribute.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/instr-attribute.c?rev=200874&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/instr-attribute.c?rev=200874&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGen/instr-attribute.c (added)<br>
+++ cfe/trunk/test/CodeGen/instr-attribute.c Wed Feb 5 14:40:15 2014<br>
@@ -0,0 +1,47 @@<br>
+// Test that instrumentation based profiling sets function attributes correctly.<br>
+<br>
+// RUN: %clang %s -o - -mllvm -disable-llvm-optzns -emit-llvm -S -fprofile-instr-use=%S/Inputs/instr-attribute.pgodata | FileCheck %s<br>
+<br>
+extern int atoi(const char *);<br>
+<br>
+// CHECK: hot_100_percent(i32 %i) [[HOT:#[0-9]+]]<br>
+void hot_100_percent(int i) {<br>
+ while (i > 0)<br>
+ i--;<br>
+}<br>
+<br>
+// CHECK: hot_40_percent(i32 %i) [[HOT]]<br>
+void hot_40_percent(int i) {<br>
+ while (i > 0)<br>
+ i--;<br>
+}<br>
+<br>
+// CHECK: normal_func(i32 %i) [[NORMAL:#[0-9]+]]<br>
+void normal_func(int i) {<br>
+ while (i > 0)<br>
+ i--;<br>
+}<br>
+<br>
+// CHECK: cold_func(i32 %i) [[COLD:#[0-9]+]]<br>
+void cold_func(int i) {<br>
+ while (i > 0)<br>
+ i--;<br>
+}<br>
+<br>
+// CHECK: attributes [[HOT]] = { inlinehint nounwind {{.*}} }<br>
+// CHECK: attributes [[NORMAL]] = { nounwind {{.*}} }<br>
+// CHECK: attributes [[COLD]] = { cold nounwind {{.*}} }<br>
+<br>
+int main(int argc, const char *argv[]) {<br>
+ int max = atoi(argv[1]);<br>
+ int i;<br>
+ for (i = 0; i < max; i++)<br>
+ hot_100_percent(i);<br>
+ for (i = 0; i < max * 4 / 10; i++)<br>
+ hot_40_percent(i);<br>
+ for (i = 0; i < max * 2 / 10; i++)<br>
+ normal_func(i);<br>
+ for (i = 0; i < max / 200; i++)<br>
+ cold_func(i);<br>
+ return 0;<br>
+}<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div></div>