<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>