On Wed, Feb 5, 2014 at 12:40 PM, Manman Ren <[email protected]> wrote:
> Author: mren > Date: Wed Feb 5 14:40:15 2014 > New Revision: 200874 > > URL: http://llvm.org/viewvc/llvm-project?rev=200874&view=rev > Log: > PGO: instrumentation based profiling sets function attributes. > > We collect a maximal function count among all functions in the pgo data > file. > For functions that are hot, we set its InlineHint attribute. For functions > that > are cold, we set its Cold attribute. > > We currently treat functions with >= 30% of the maximal function count as > hot > and functions with <= 1% of the maximal function count are treated as cold. > These two numbers are from preliminary tuning on SPEC. > Do you have more specific info from SPEC runs and how these heuristic choices compare to other nearby values? (why 1% instead of 2 or 0.5? why 30 instead of 20 or 40 - etc) I'd love to see the graphs just out of curiosity's sake. > > This commit should not affect non-PGO builds and should boost performance > on > instrumentation based PGO. > > Added: > cfe/trunk/test/CodeGen/Inputs/instr-attribute.pgodata > cfe/trunk/test/CodeGen/instr-attribute.c > Modified: > cfe/trunk/lib/CodeGen/CodeGenFunction.cpp > cfe/trunk/lib/CodeGen/CodeGenPGO.cpp > cfe/trunk/lib/CodeGen/CodeGenPGO.h > > Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=200874&r1=200873&r2=200874&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original) > +++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Wed Feb 5 14:40:15 2014 > @@ -591,6 +591,16 @@ void CodeGenFunction::StartFunction(Glob > 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. > > Modified: cfe/trunk/lib/CodeGen/CodeGenPGO.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenPGO.cpp?rev=200874&r1=200873&r2=200874&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CodeGenPGO.cpp (original) > +++ cfe/trunk/lib/CodeGen/CodeGenPGO.cpp Wed Feb 5 14:40:15 2014 > @@ -45,6 +45,7 @@ PGOProfileData::PGOProfileData(CodeGenMo > 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(CodeGenMo > } > 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(CodeGenMo > > 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, > > Modified: cfe/trunk/lib/CodeGen/CodeGenPGO.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenPGO.h?rev=200874&r1=200873&r2=200874&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CodeGenPGO.h (original) > +++ cfe/trunk/lib/CodeGen/CodeGenPGO.h Wed Feb 5 14:40:15 2014 > @@ -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, > > Added: cfe/trunk/test/CodeGen/Inputs/instr-attribute.pgodata > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/Inputs/instr-attribute.pgodata?rev=200874&view=auto > > ============================================================================== > --- cfe/trunk/test/CodeGen/Inputs/instr-attribute.pgodata (added) > +++ cfe/trunk/test/CodeGen/Inputs/instr-attribute.pgodata Wed Feb 5 > 14:40:15 2014 > @@ -0,0 +1,39 @@ > +hot_100_percent 4 > +100000 > +4999950000 > +0 > +0 > + > +hot_40_percent 4 > +40000 > +799980000 > +0 > +0 > + > +normal_func 4 > +20000 > +199990000 > +0 > +0 > + > +cold_func 4 > +500 > +124750 > +0 > +0 > + > +main 13 > +1 > +100000 > +0 > +0 > +40000 > +0 > +0 > +20000 > +0 > +0 > +500 > +0 > +0 > + > > Added: cfe/trunk/test/CodeGen/instr-attribute.c > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/instr-attribute.c?rev=200874&view=auto > > ============================================================================== > --- cfe/trunk/test/CodeGen/instr-attribute.c (added) > +++ cfe/trunk/test/CodeGen/instr-attribute.c Wed Feb 5 14:40:15 2014 > @@ -0,0 +1,47 @@ > +// Test that instrumentation based profiling sets function attributes > correctly. > + > +// RUN: %clang %s -o - -mllvm -disable-llvm-optzns -emit-llvm -S > -fprofile-instr-use=%S/Inputs/instr-attribute.pgodata | FileCheck %s > + > +extern int atoi(const char *); > + > +// CHECK: hot_100_percent(i32 %i) [[HOT:#[0-9]+]] > +void hot_100_percent(int i) { > + while (i > 0) > + i--; > +} > + > +// CHECK: hot_40_percent(i32 %i) [[HOT]] > +void hot_40_percent(int i) { > + while (i > 0) > + i--; > +} > + > +// CHECK: normal_func(i32 %i) [[NORMAL:#[0-9]+]] > +void normal_func(int i) { > + while (i > 0) > + i--; > +} > + > +// CHECK: cold_func(i32 %i) [[COLD:#[0-9]+]] > +void cold_func(int i) { > + while (i > 0) > + i--; > +} > + > +// CHECK: attributes [[HOT]] = { inlinehint nounwind {{.*}} } > +// CHECK: attributes [[NORMAL]] = { nounwind {{.*}} } > +// CHECK: attributes [[COLD]] = { cold nounwind {{.*}} } > + > +int main(int argc, const char *argv[]) { > + int max = atoi(argv[1]); > + int i; > + for (i = 0; i < max; i++) > + hot_100_percent(i); > + for (i = 0; i < max * 4 / 10; i++) > + hot_40_percent(i); > + for (i = 0; i < max * 2 / 10; i++) > + normal_func(i); > + for (i = 0; i < max / 200; i++) > + cold_func(i); > + return 0; > +} > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
