diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 10 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenPGO.cpp | 41 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenPGO.h | 10 |
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, |