Add prefix based function layout when profile is available.
authorDehao Chen <dehao@google.com>
Mon, 22 Feb 2016 22:14:14 +0000 (22:14 +0000)
committerDehao Chen <dehao@google.com>
Mon, 22 Feb 2016 22:14:14 +0000 (22:14 +0000)
Summary: If a function is hot, put it in text.hot section.

Reviewers: davidxl

Subscribers: eraman, mcrosier, llvm-commits

Differential Revision: http://reviews.llvm.org/D17460

llvm-svn: 261582

llvm/include/llvm/ProfileData/ProfileCommon.h
llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
llvm/lib/ProfileData/ProfileSummary.cpp
llvm/test/CodeGen/X86/partition-sections.ll [new file with mode: 0644]

index e7d6943..7663114 100644 (file)
@@ -21,6 +21,8 @@
 #define LLVM_PROFILEDATA_PROFILE_COMMON_H
 
 namespace llvm {
+class Function;
+class Module;
 namespace IndexedInstrProf {
 struct Summary;
 }
@@ -28,6 +30,8 @@ namespace sampleprof {
 class FunctionSamples;
 }
 struct InstrProfRecord;
+inline const char *getHotSectionPrefix() { return ".hot"; }
+inline const char *getUnlikelySectionPrefix() { return ".unlikely"; }
 // The profile summary is one or more (Cutoff, MinCount, NumCounts) triplets.
 // The semantics of counts depend on the type of profile. For instrumentation
 // profile, counts are block counts and for sample profile, counts are
@@ -66,6 +70,10 @@ protected:
 
 public:
   static const int Scale = 1000000;
+  // \brief Returns true if F is a hot function.
+  static bool isFunctionHot(const Function *F);
+  // \brief Returns true if F is unlikley executed.
+  static bool isFunctionUnlikely(const Function *F);
   inline std::vector<ProfileSummaryEntry> &getDetailedSummary();
   void computeDetailedSummary();
   /// \brief A vector of useful cutoff values for detailed summary.
index 81b429a..624eaec 100644 (file)
@@ -34,6 +34,7 @@
 #include "llvm/MC/MCSymbolELF.h"
 #include "llvm/MC/MCValue.h"
 #include "llvm/ProfileData/InstrProf.h"
+#include "llvm/ProfileData/ProfileCommon.h"
 #include "llvm/Support/COFF.h"
 #include "llvm/Support/Dwarf.h"
 #include "llvm/Support/ELF.h"
@@ -244,6 +245,11 @@ static StringRef getSectionPrefixForGlobal(SectionKind Kind) {
   return ".data.rel.ro";
 }
 
+static cl::opt<bool> GroupFunctionsByHotness(
+    "group-functions-by-hotness",
+    llvm::cl::desc("Partition hot/cold functions by sections prefix"),
+    cl::init(false));
+
 static MCSectionELF *
 selectELFSectionForGlobal(MCContext &Ctx, const GlobalValue *GV,
                           SectionKind Kind, Mangler &Mang,
@@ -294,6 +300,16 @@ selectELFSectionForGlobal(MCContext &Ctx, const GlobalValue *GV,
     Name = getSectionPrefixForGlobal(Kind);
   }
 
+  if (GroupFunctionsByHotness) {
+    if (const Function *F = dyn_cast<Function>(GV)) {
+      if (ProfileSummary::isFunctionHot(F)) {
+        Name += getHotSectionPrefix();
+      } else if (ProfileSummary::isFunctionUnlikely(F)) {
+        Name += getUnlikelySectionPrefix();
+      }
+    }
+  }
+
   if (EmitUniqueSection && UniqueSectionNames) {
     Name.push_back('.');
     TM.getNameWithPrefix(Name, GV, Mang, true);
index 0e2c43e..0363fbf 100644 (file)
@@ -11,6 +11,9 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "llvm/IR/Attributes.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Module.h"
 #include "llvm/ProfileData/InstrProf.h"
 #include "llvm/ProfileData/ProfileCommon.h"
 #include "llvm/ProfileData/SampleProf.h"
@@ -75,6 +78,24 @@ void ProfileSummary::computeDetailedSummary() {
   }
 }
 
+// Returns true if the function is a hot function.
+bool ProfileSummary::isFunctionHot(const Function *F) {
+  // FIXME: update when summary data is stored in module's metadata.
+  return false;
+}
+
+// Returns true if the function is a cold function.
+bool ProfileSummary::isFunctionUnlikely(const Function *F) {
+  if (F->hasFnAttribute(Attribute::Cold)) {
+    return true;
+  }
+  if (!F->getEntryCount()) {
+    return false;
+  }
+  // FIXME: update when summary data is stored in module's metadata.
+  return (*F->getEntryCount()) == 0;
+}
+
 InstrProfSummary::InstrProfSummary(const IndexedInstrProf::Summary &S)
     : ProfileSummary(), MaxInternalBlockCount(S.get(
                             IndexedInstrProf::Summary::MaxInternalBlockCount)),
diff --git a/llvm/test/CodeGen/X86/partition-sections.ll b/llvm/test/CodeGen/X86/partition-sections.ll
new file mode 100644 (file)
index 0000000..b05a381
--- /dev/null
@@ -0,0 +1,31 @@
+; RUN: llc < %s -group-functions-by-hotness=true | FileCheck %s -check-prefix=PARTITION
+; RUN: llc < %s -function-sections -group-functions-by-hotness=false | FileCheck %s -check-prefix=NO-PARTITION-FUNCTION-SECTION
+; RUN: llc < %s -function-sections -group-functions-by-hotness=true | FileCheck %s -check-prefix=PARTITION-FUNCTION-SECTION
+
+; PARTITION: .text.unlikely
+; PARTITION: .globl  _Z3foov
+; NO-PARTITION-FUNCTION-SECTION: .text._Z3foov
+; PARTITION-FUNCTION-SECTION: .text.unlikely._Z3foov
+define i32 @_Z3foov() #0 {
+  ret i32 0
+}
+
+; PARTITION: .globl  _Z3barv
+; NO-PARTITION-FUNCTION-SECTION: .text._Z3barv
+; PARTITION-FUNCTION-SECTION: .text.unlikely._Z3barv
+define i32 @_Z3barv() #1 !prof !0 {
+  ret i32 1
+}
+
+; PARTITION: .text
+; PARTITION: .globl  _Z3bazv
+; NO-PARTITION-FUNCTION-SECTION: .text._Z3bazv
+; PARTITION-FUNCTION-SECTION: .text._Z3bazv
+define i32 @_Z3bazv() #1 {
+  ret i32 2
+}
+
+attributes #0 = { nounwind uwtable cold }
+attributes #1 = { nounwind uwtable }
+
+!0 = !{!"function_entry_count", i64 0}