summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp10
-rw-r--r--clang/lib/CodeGen/CodeGenPGO.cpp41
-rw-r--r--clang/lib/CodeGen/CodeGenPGO.h10
3 files changed, 60 insertions, 1 deletions
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 7d451e8f6d0..c0b4d8926a9 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -591,6 +591,16 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
EmitMCountInstrumentation();
PGO.assignRegionCounters(GD);
+ if (CGM.getPGOData()) {
+ if (const Decl *D = GD.getDecl()) {
+ // Turn on InlineHint attribute for hot functions.
+ if (CGM.getPGOData()->isHotFunction(CGM.getMangledName(GD)))
+ Fn->addFnAttr(llvm::Attribute::InlineHint);
+ // Turn on Cold attribute for cold functions.
+ else if (CGM.getPGOData()->isColdFunction(CGM.getMangledName(GD)))
+ Fn->addFnAttr(llvm::Attribute::Cold);
+ }
+ }
if (RetTy->isVoidType()) {
// Void type; nothing to return.
diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp
index a1782d32b44..d7c4709612a 100644
--- a/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -45,6 +45,7 @@ PGOProfileData::PGOProfileData(CodeGenModule &CGM, std::string Path)
const char *BufferStart = DataBuffer->getBufferStart();
const char *BufferEnd = DataBuffer->getBufferEnd();
const char *CurPtr = BufferStart;
+ uint64_t MaxCount = 0;
while (CurPtr < BufferEnd) {
// Read the mangled function name.
const char *FuncName = CurPtr;
@@ -65,8 +66,19 @@ PGOProfileData::PGOProfileData(CodeGenModule &CGM, std::string Path)
}
CurPtr = EndPtr;
+ // Read function count.
+ uint64_t Count = strtoll(CurPtr, &EndPtr, 10);
+ if (EndPtr == CurPtr || *EndPtr != '\n') {
+ ReportBadPGOData(CGM, "pgo-data file has bad count value");
+ return;
+ }
+ CurPtr = EndPtr + 1;
+ FunctionCounts[MangledName] = Count;
+ MaxCount = Count > MaxCount ? Count : MaxCount;
+
// There is one line for each counter; skip over those lines.
- for (unsigned N = 0; N < NumCounters; ++N) {
+ // Since function count is already read, we start the loop from 1.
+ for (unsigned N = 1; N < NumCounters; ++N) {
CurPtr = strchr(++CurPtr, '\n');
if (!CurPtr) {
ReportBadPGOData(CGM, "pgo data file is missing some counter info");
@@ -79,6 +91,33 @@ PGOProfileData::PGOProfileData(CodeGenModule &CGM, std::string Path)
DataOffsets[MangledName] = FuncName - BufferStart;
}
+ MaxFunctionCount = MaxCount;
+}
+
+/// Return true if a function is hot. If we know nothing about the function,
+/// return false.
+bool PGOProfileData::isHotFunction(StringRef MangledName) {
+ llvm::StringMap<uint64_t>::const_iterator CountIter =
+ FunctionCounts.find(MangledName);
+ // If we know nothing about the function, return false.
+ if (CountIter == FunctionCounts.end())
+ return false;
+ // FIXME: functions with >= 30% of the maximal function count are
+ // treated as hot. This number is from preliminary tuning on SPEC.
+ return CountIter->getValue() >= (uint64_t)(0.3 * (double)MaxFunctionCount);
+}
+
+/// Return true if a function is cold. If we know nothing about the function,
+/// return false.
+bool PGOProfileData::isColdFunction(StringRef MangledName) {
+ llvm::StringMap<uint64_t>::const_iterator CountIter =
+ FunctionCounts.find(MangledName);
+ // If we know nothing about the function, return false.
+ if (CountIter == FunctionCounts.end())
+ return false;
+ // FIXME: functions with <= 1% of the maximal function count are treated as
+ // cold. This number is from preliminary tuning on SPEC.
+ return CountIter->getValue() <= (uint64_t)(0.01 * (double)MaxFunctionCount);
}
bool PGOProfileData::getFunctionCounts(StringRef MangledName,
diff --git a/clang/lib/CodeGen/CodeGenPGO.h b/clang/lib/CodeGen/CodeGenPGO.h
index 2d1193bab0b..6409a10525b 100644
--- a/clang/lib/CodeGen/CodeGenPGO.h
+++ b/clang/lib/CodeGen/CodeGenPGO.h
@@ -33,12 +33,22 @@ private:
llvm::OwningPtr<llvm::MemoryBuffer> DataBuffer;
/// Offsets into DataBuffer for each function's counters
llvm::StringMap<unsigned> DataOffsets;
+ /// Execution counts for each function.
+ llvm::StringMap<uint64_t> FunctionCounts;
+ /// The maximal execution count among all functions.
+ uint64_t MaxFunctionCount;
CodeGenModule &CGM;
public:
PGOProfileData(CodeGenModule &CGM, std::string Path);
/// Fill Counts with the profile data for the given function name. Returns
/// false on success.
bool getFunctionCounts(StringRef MangledName, std::vector<uint64_t> &Counts);
+ /// Return true if a function is hot. If we know nothing about the function,
+ /// return false.
+ bool isHotFunction(StringRef MangledName);
+ /// Return true if a function is cold. If we know nothing about the function,
+ /// return false.
+ bool isColdFunction(StringRef MangledName);
};
/// Per-function PGO state. This class should generally not be used directly,
OpenPOWER on IntegriCloud