From: Justin Bogner Date: Tue, 18 Mar 2014 21:58:06 +0000 (+0000) Subject: CodeGen: Include a function hash in instrumentation based profiling X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0ec537c758c02f77226f05404dd6f885fe5cc55e;p=clang CodeGen: Include a function hash in instrumentation based profiling The hash itself is still the number of counters, which isn't all that useful, but this separates the API changes from the actual implementation of the hash and will make it easier to transition to the ProfileData library once it's implemented. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@204186 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CodeGenPGO.cpp b/lib/CodeGen/CodeGenPGO.cpp index 207cb665b0..1f2fe38c40 100644 --- a/lib/CodeGen/CodeGenPGO.cpp +++ b/lib/CodeGen/CodeGenPGO.cpp @@ -58,10 +58,15 @@ PGOProfileData::PGOProfileData(CodeGenModule &CGM, std::string Path) ReportBadPGOData(CGM, "pgo data file has malformed function entry"); return; } - while (*--CurPtr != ' ') - ; StringRef FuncName(FuncStart, CurPtr - FuncStart); + // Skip over the function hash. + CurPtr = strchr(++CurPtr, '\n'); + if (!CurPtr) { + ReportBadPGOData(CGM, "pgo data file is missing the function hash"); + return; + } + // Read the number of counters. char *EndPtr; unsigned NumCounters = strtol(++CurPtr, &EndPtr, 10); @@ -99,7 +104,7 @@ PGOProfileData::PGOProfileData(CodeGenModule &CGM, std::string Path) MaxFunctionCount = MaxCount; } -bool PGOProfileData::getFunctionCounts(StringRef FuncName, +bool PGOProfileData::getFunctionCounts(StringRef FuncName, uint64_t &FuncHash, std::vector &Counts) { // Find the relevant section of the pgo-data file. llvm::StringMap::const_iterator OffsetIter = @@ -111,11 +116,15 @@ bool PGOProfileData::getFunctionCounts(StringRef FuncName, // Skip over the function name. CurPtr = strchr(CurPtr, '\n'); assert(CurPtr && "pgo-data has corrupted function entry"); - while (*--CurPtr != ' ') - ; - // Read the number of counters. char *EndPtr; + // Read the function hash. + FuncHash = strtoll(++CurPtr, &EndPtr, 10); + assert(EndPtr != CurPtr && *EndPtr == '\n' && + "pgo-data file has corrupted function hash"); + CurPtr = EndPtr; + + // Read the number of counters. unsigned NumCounters = strtol(++CurPtr, &EndPtr, 10); assert(EndPtr != CurPtr && *EndPtr == '\n' && NumCounters > 0 && "pgo-data file has corrupted number of counters"); @@ -246,15 +255,17 @@ llvm::GlobalVariable *CodeGenPGO::buildDataVar() { // Create data variable. auto *Int32Ty = llvm::Type::getInt32Ty(Ctx); + auto *Int64Ty = llvm::Type::getInt64Ty(Ctx); auto *Int8PtrTy = llvm::Type::getInt8PtrTy(Ctx); auto *Int64PtrTy = llvm::Type::getInt64PtrTy(Ctx); llvm::Type *DataTypes[] = { - Int32Ty, Int32Ty, Int8PtrTy, Int64PtrTy + Int32Ty, Int32Ty, Int64Ty, Int8PtrTy, Int64PtrTy }; auto *DataTy = llvm::StructType::get(Ctx, makeArrayRef(DataTypes)); llvm::Constant *DataVals[] = { llvm::ConstantInt::get(Int32Ty, getFuncName().size()), llvm::ConstantInt::get(Int32Ty, NumRegionCounters), + llvm::ConstantInt::get(Int64Ty, FunctionHash), llvm::ConstantExpr::getBitCast(Name, Int8PtrTy), llvm::ConstantExpr::getBitCast(RegionCounters, Int64PtrTy) }; @@ -847,6 +858,8 @@ void CodeGenPGO::mapRegionCounters(const Decl *D) { else if (const BlockDecl *BD = dyn_cast_or_null(D)) Walker.VisitBlockDecl(BD); NumRegionCounters = Walker.NextCounter; + // FIXME: The number of counters isn't sufficient for the hash + FunctionHash = NumRegionCounters; } void CodeGenPGO::computeRegionCounts(const Decl *D) { @@ -905,8 +918,9 @@ void CodeGenPGO::loadRegionCounts(PGOProfileData *PGOData) { // ignore counts when the input changes in various ways, e.g., by comparing a // hash value based on some characteristics of the input. RegionCounts = new std::vector(); - if (PGOData->getFunctionCounts(getFuncName(), *RegionCounts) || - RegionCounts->size() != NumRegionCounters) { + uint64_t Hash; + if (PGOData->getFunctionCounts(getFuncName(), Hash, *RegionCounts) || + Hash != FunctionHash || RegionCounts->size() != NumRegionCounters) { delete RegionCounts; RegionCounts = 0; } diff --git a/lib/CodeGen/CodeGenPGO.h b/lib/CodeGen/CodeGenPGO.h index 2f1fe5dba8..e859324ae0 100644 --- a/lib/CodeGen/CodeGenPGO.h +++ b/lib/CodeGen/CodeGenPGO.h @@ -42,7 +42,8 @@ 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 FuncName, std::vector &Counts); + bool getFunctionCounts(StringRef FuncName, uint64_t &FuncHash, + std::vector &Counts); /// Return the maximum of all known function counts. uint64_t getMaximumFunctionCount() { return MaxFunctionCount; } }; @@ -57,6 +58,7 @@ private: llvm::GlobalValue::LinkageTypes FuncLinkage; unsigned NumRegionCounters; + uint64_t FunctionHash; llvm::GlobalVariable *RegionCounters; llvm::DenseMap *RegionCounterMap; llvm::DenseMap *StmtCountMap; @@ -65,9 +67,9 @@ private: public: CodeGenPGO(CodeGenModule &CGM) - : CGM(CGM), PrefixedFuncName(0), NumRegionCounters(0), RegionCounters(0), - RegionCounterMap(0), StmtCountMap(0), RegionCounts(0), - CurrentRegionCount(0) {} + : CGM(CGM), PrefixedFuncName(0), NumRegionCounters(0), FunctionHash(0), + RegionCounters(0), RegionCounterMap(0), StmtCountMap(0), + RegionCounts(0), CurrentRegionCount(0) {} ~CodeGenPGO() { if (PrefixedFuncName) delete PrefixedFuncName; } diff --git a/test/Profile/Inputs/c-attributes.profdata b/test/Profile/Inputs/c-attributes.profdata index 38decbd556..97e682480d 100644 --- a/test/Profile/Inputs/c-attributes.profdata +++ b/test/Profile/Inputs/c-attributes.profdata @@ -1,20 +1,30 @@ -hot_100_percent 2 +hot_100_percent +2 +2 100000 4999950000 -hot_40_percent 2 +hot_40_percent +2 +2 40000 799980000 -normal_func 2 +normal_func +2 +2 20000 199990000 -cold_func 2 +cold_func +2 +2 500 124750 -main 6 +main +6 +6 1 0 100000 diff --git a/test/Profile/Inputs/c-counter-overflows.profdata b/test/Profile/Inputs/c-counter-overflows.profdata index 377a08502d..24863780ef 100644 --- a/test/Profile/Inputs/c-counter-overflows.profdata +++ b/test/Profile/Inputs/c-counter-overflows.profdata @@ -1,4 +1,6 @@ -main 8 +main +8 +8 1 68719476720 64424509425 diff --git a/test/Profile/Inputs/c-general.profdata b/test/Profile/Inputs/c-general.profdata index 083b8fe55b..a1d56104a2 100644 --- a/test/Profile/Inputs/c-general.profdata +++ b/test/Profile/Inputs/c-general.profdata @@ -1,10 +1,14 @@ -simple_loops 4 +simple_loops +4 +4 1 100 100 75 -conditionals 11 +conditionals +11 +11 1 100 50 @@ -17,7 +21,9 @@ conditionals 11 99 100 -early_exits 9 +early_exits +9 +9 1 0 51 @@ -28,7 +34,9 @@ early_exits 9 1 0 -jumps 22 +jumps +22 +22 1 1 0 @@ -52,7 +60,9 @@ jumps 22 10 9 -switches 19 +switches +19 +19 1 1 1 @@ -73,7 +83,9 @@ switches 19 1 0 -big_switch 17 +big_switch +17 +17 1 32 32 @@ -92,7 +104,9 @@ big_switch 17 2 2 -boolean_operators 8 +boolean_operators +8 +8 1 100 34 @@ -102,7 +116,9 @@ boolean_operators 8 33 50 -boolop_loops 9 +boolop_loops +9 +9 1 50 51 @@ -113,16 +129,22 @@ boolop_loops 9 50 26 -do_fallthrough 4 +do_fallthrough +4 +4 1 10 2 8 -main 1 +main +1 +1 1 -c-general.c:static_func 2 +c-general.c:static_func +2 +2 1 10 diff --git a/test/Profile/Inputs/c-outdated-data.profdata b/test/Profile/Inputs/c-outdated-data.profdata index e1c51a6975..27015be82d 100644 --- a/test/Profile/Inputs/c-outdated-data.profdata +++ b/test/Profile/Inputs/c-outdated-data.profdata @@ -1,8 +1,12 @@ -no_usable_data 3 +no_usable_data +3 +3 1 0 0 -main 1 +main +1 +1 1 diff --git a/test/Profile/Inputs/cxx-class.profdata b/test/Profile/Inputs/cxx-class.profdata index 983ab55116..756640d2f3 100644 --- a/test/Profile/Inputs/cxx-class.profdata +++ b/test/Profile/Inputs/cxx-class.profdata @@ -1,27 +1,41 @@ -_Z14simple_wrapperv 2 +_Z14simple_wrapperv +2 +2 1 100 -main 1 +main +1 +1 1 -_ZN6SimpleD1Ev 2 +_ZN6SimpleD1Ev +2 +2 0 0 -_ZN6SimpleD2Ev 2 +_ZN6SimpleD2Ev +2 +2 100 99 -_ZN6Simple6methodEv 2 +_ZN6Simple6methodEv +2 +2 100 99 -_ZN6SimpleC1Ei 2 +_ZN6SimpleC1Ei +2 +2 0 0 -_ZN6SimpleC2Ei 2 +_ZN6SimpleC2Ei +2 +2 100 99 diff --git a/test/Profile/Inputs/cxx-throws.profdata b/test/Profile/Inputs/cxx-throws.profdata index a49522f558..01e6c3c286 100644 --- a/test/Profile/Inputs/cxx-throws.profdata +++ b/test/Profile/Inputs/cxx-throws.profdata @@ -1,4 +1,6 @@ -_Z6throwsv 9 +_Z6throwsv +9 +9 1 100 100 @@ -9,6 +11,8 @@ _Z6throwsv 9 33 100 -main 1 +main +1 +1 1 diff --git a/test/Profile/Inputs/objc-general.profdata b/test/Profile/Inputs/objc-general.profdata index 06c9832b3c..8841e908c9 100644 --- a/test/Profile/Inputs/objc-general.profdata +++ b/test/Profile/Inputs/objc-general.profdata @@ -1,11 +1,17 @@ -objc-general.m:__13+[A foreach:]_block_invoke 2 +objc-general.m:__13+[A foreach:]_block_invoke +2 +2 2 1 -objc-general.m:+[A foreach:] 2 +objc-general.m:+[A foreach:] +2 +2 1 2 -main 1 +main +1 +1 1 diff --git a/test/Profile/c-linkage.c b/test/Profile/c-linkage.c index dddc895068..22a2535c4e 100644 --- a/test/Profile/c-linkage.c +++ b/test/Profile/c-linkage.c @@ -3,18 +3,18 @@ // CHECK: @__llvm_pgo_counters_foo = global [1 x i64] zeroinitializer, section "__DATA,__llvm_pgo_cnts", align 8 // CHECK: @__llvm_pgo_name_foo = constant [3 x i8] c"foo", section "__DATA,__llvm_pgo_names", align 1 -// CHECK: @__llvm_pgo_data_foo = constant { i32, i32, i8*, i64* } { i32 3, i32 1, i8* getelementptr inbounds ([3 x i8]* @__llvm_pgo_name_foo, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64]* @__llvm_pgo_counters_foo, i32 0, i32 0) }, section "__DATA,__llvm_pgo_data", align 8 +// CHECK: @__llvm_pgo_data_foo = constant { i32, i32, i64, i8*, i64* } { i32 3, i32 1, i64 1, i8* getelementptr inbounds ([3 x i8]* @__llvm_pgo_name_foo, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64]* @__llvm_pgo_counters_foo, i32 0, i32 0) }, section "__DATA,__llvm_pgo_data", align 8 void foo(void) { } // CHECK: @__llvm_pgo_counters_foo_weak = weak global [5 x i64] zeroinitializer, section "__DATA,__llvm_pgo_cnts", align 8 // CHECK: @__llvm_pgo_name_foo_weak = weak constant [8 x i8] c"foo_weak", section "__DATA,__llvm_pgo_names", align 1 -// CHECK: @__llvm_pgo_data_foo_weak = weak constant { i32, i32, i8*, i64* } { i32 8, i32 5, i8* getelementptr inbounds ([8 x i8]* @__llvm_pgo_name_foo_weak, i32 0, i32 0), i64* getelementptr inbounds ([5 x i64]* @__llvm_pgo_counters_foo_weak, i32 0, i32 0) }, section "__DATA,__llvm_pgo_data", align 8 +// CHECK: @__llvm_pgo_data_foo_weak = weak constant { i32, i32, i64, i8*, i64* } { i32 8, i32 5, i64 5, i8* getelementptr inbounds ([8 x i8]* @__llvm_pgo_name_foo_weak, i32 0, i32 0), i64* getelementptr inbounds ([5 x i64]* @__llvm_pgo_counters_foo_weak, i32 0, i32 0) }, section "__DATA,__llvm_pgo_data", align 8 void foo_weak(void) __attribute__((weak)); void foo_weak(void) { if (0){} if (0){} if (0){} if (0){} } // CHECK: @__llvm_pgo_counters_main = global [1 x i64] zeroinitializer, section "__DATA,__llvm_pgo_cnts", align 8 // CHECK: @__llvm_pgo_name_main = constant [4 x i8] c"main", section "__DATA,__llvm_pgo_names", align 1 -// CHECK: @__llvm_pgo_data_main = constant { i32, i32, i8*, i64* } { i32 4, i32 1, i8* getelementptr inbounds ([4 x i8]* @__llvm_pgo_name_main, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64]* @__llvm_pgo_counters_main, i32 0, i32 0) }, section "__DATA,__llvm_pgo_data", align 8 +// CHECK: @__llvm_pgo_data_main = constant { i32, i32, i64, i8*, i64* } { i32 4, i32 1, i64 1, i8* getelementptr inbounds ([4 x i8]* @__llvm_pgo_name_main, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64]* @__llvm_pgo_counters_main, i32 0, i32 0) }, section "__DATA,__llvm_pgo_data", align 8 static void foo_internal(void); int main(void) { foo(); @@ -25,7 +25,7 @@ int main(void) { // CHECK: @__llvm_pgo_counters_foo_internal = internal global [3 x i64] zeroinitializer, section "__DATA,__llvm_pgo_cnts", align 8 // CHECK: @__llvm_pgo_name_foo_internal = internal constant [24 x i8] c"c-linkage.c:foo_internal", section "__DATA,__llvm_pgo_names", align 1 -// CHECK: @__llvm_pgo_data_foo_internal = internal constant { i32, i32, i8*, i64* } { i32 24, i32 3, i8* getelementptr inbounds ([24 x i8]* @__llvm_pgo_name_foo_internal, i32 0, i32 0), i64* getelementptr inbounds ([3 x i64]* @__llvm_pgo_counters_foo_internal, i32 0, i32 0) }, section "__DATA,__llvm_pgo_data", align 8 +// CHECK: @__llvm_pgo_data_foo_internal = internal constant { i32, i32, i64, i8*, i64* } { i32 24, i32 3, i64 3, i8* getelementptr inbounds ([24 x i8]* @__llvm_pgo_name_foo_internal, i32 0, i32 0), i64* getelementptr inbounds ([3 x i64]* @__llvm_pgo_counters_foo_internal, i32 0, i32 0) }, section "__DATA,__llvm_pgo_data", align 8 static void foo_internal(void) { if (0){} if (0){} } -// CHECK: @llvm.used = appending global [4 x i8*] [i8* bitcast ({ i32, i32, i8*, i64* }* @__llvm_pgo_data_foo to i8*), i8* bitcast ({ i32, i32, i8*, i64* }* @__llvm_pgo_data_foo_weak to i8*), i8* bitcast ({ i32, i32, i8*, i64* }* @__llvm_pgo_data_main to i8*), i8* bitcast ({ i32, i32, i8*, i64* }* @__llvm_pgo_data_foo_internal to i8*)], section "llvm.metadata" +// CHECK: @llvm.used = appending global [4 x i8*] [i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_pgo_data_foo to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_pgo_data_foo_weak to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_pgo_data_main to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_pgo_data_foo_internal to i8*)], section "llvm.metadata" diff --git a/test/Profile/cxx-linkage.cpp b/test/Profile/cxx-linkage.cpp index 6597e25105..8c49dff26a 100644 --- a/test/Profile/cxx-linkage.cpp +++ b/test/Profile/cxx-linkage.cpp @@ -2,18 +2,18 @@ // CHECK: @__llvm_pgo_counters__Z3foov = global [1 x i64] zeroinitializer, section "__DATA,__llvm_pgo_cnts", align 8 // CHECK: @__llvm_pgo_name__Z3foov = constant [7 x i8] c"_Z3foov", section "__DATA,__llvm_pgo_names", align 1 -// CHECK: @__llvm_pgo_data__Z3foov = constant { i32, i32, i8*, i64* } { i32 7, i32 1, i8* getelementptr inbounds ([7 x i8]* @__llvm_pgo_name__Z3foov, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64]* @__llvm_pgo_counters__Z3foov, i32 0, i32 0) }, section "__DATA,__llvm_pgo_data", align 8 +// CHECK: @__llvm_pgo_data__Z3foov = constant { i32, i32, i64, i8*, i64* } { i32 7, i32 1, i64 1, i8* getelementptr inbounds ([7 x i8]* @__llvm_pgo_name__Z3foov, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64]* @__llvm_pgo_counters__Z3foov, i32 0, i32 0) }, section "__DATA,__llvm_pgo_data", align 8 void foo(void) { } // CHECK: @__llvm_pgo_counters__Z8foo_weakv = weak global [5 x i64] zeroinitializer, section "__DATA,__llvm_pgo_cnts", align 8 // CHECK: @__llvm_pgo_name__Z8foo_weakv = weak constant [12 x i8] c"_Z8foo_weakv", section "__DATA,__llvm_pgo_names", align 1 -// CHECK: @__llvm_pgo_data__Z8foo_weakv = weak constant { i32, i32, i8*, i64* } { i32 12, i32 5, i8* getelementptr inbounds ([12 x i8]* @__llvm_pgo_name__Z8foo_weakv, i32 0, i32 0), i64* getelementptr inbounds ([5 x i64]* @__llvm_pgo_counters__Z8foo_weakv, i32 0, i32 0) }, section "__DATA,__llvm_pgo_data", align 8 +// CHECK: @__llvm_pgo_data__Z8foo_weakv = weak constant { i32, i32, i64, i8*, i64* } { i32 12, i32 5, i64 5, i8* getelementptr inbounds ([12 x i8]* @__llvm_pgo_name__Z8foo_weakv, i32 0, i32 0), i64* getelementptr inbounds ([5 x i64]* @__llvm_pgo_counters__Z8foo_weakv, i32 0, i32 0) }, section "__DATA,__llvm_pgo_data", align 8 void foo_weak(void) __attribute__((weak)); void foo_weak(void) { if (0){} if (0){} if (0){} if (0){} } // CHECK: @__llvm_pgo_counters_main = global [1 x i64] zeroinitializer, section "__DATA,__llvm_pgo_cnts", align 8 // CHECK: @__llvm_pgo_name_main = constant [4 x i8] c"main", section "__DATA,__llvm_pgo_names", align 1 -// CHECK: @__llvm_pgo_data_main = constant { i32, i32, i8*, i64* } { i32 4, i32 1, i8* getelementptr inbounds ([4 x i8]* @__llvm_pgo_name_main, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64]* @__llvm_pgo_counters_main, i32 0, i32 0) }, section "__DATA,__llvm_pgo_data", align 8 +// CHECK: @__llvm_pgo_data_main = constant { i32, i32, i64, i8*, i64* } { i32 4, i32 1, i64 1, i8* getelementptr inbounds ([4 x i8]* @__llvm_pgo_name_main, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64]* @__llvm_pgo_counters_main, i32 0, i32 0) }, section "__DATA,__llvm_pgo_data", align 8 inline void foo_inline(void); int main(void) { foo(); @@ -24,7 +24,7 @@ int main(void) { // CHECK: @__llvm_pgo_counters__Z10foo_inlinev = linkonce_odr global [7 x i64] zeroinitializer, section "__DATA,__llvm_pgo_cnts", align 8 // CHECK: @__llvm_pgo_name__Z10foo_inlinev = linkonce_odr constant [15 x i8] c"_Z10foo_inlinev", section "__DATA,__llvm_pgo_names", align 1 -// CHECK: @__llvm_pgo_data__Z10foo_inlinev = linkonce_odr constant { i32, i32, i8*, i64* } { i32 15, i32 7, i8* getelementptr inbounds ([15 x i8]* @__llvm_pgo_name__Z10foo_inlinev, i32 0, i32 0), i64* getelementptr inbounds ([7 x i64]* @__llvm_pgo_counters__Z10foo_inlinev, i32 0, i32 0) }, section "__DATA,__llvm_pgo_data", align 8 +// CHECK: @__llvm_pgo_data__Z10foo_inlinev = linkonce_odr constant { i32, i32, i64, i8*, i64* } { i32 15, i32 7, i64 7, i8* getelementptr inbounds ([15 x i8]* @__llvm_pgo_name__Z10foo_inlinev, i32 0, i32 0), i64* getelementptr inbounds ([7 x i64]* @__llvm_pgo_counters__Z10foo_inlinev, i32 0, i32 0) }, section "__DATA,__llvm_pgo_data", align 8 inline void foo_inline(void) { if (0){} if (0){} if (0){} if (0){} if (0){} if (0){}} -// CHECK: @llvm.used = appending global [4 x i8*] [i8* bitcast ({ i32, i32, i8*, i64* }* @__llvm_pgo_data__Z3foov to i8*), i8* bitcast ({ i32, i32, i8*, i64* }* @__llvm_pgo_data__Z8foo_weakv to i8*), i8* bitcast ({ i32, i32, i8*, i64* }* @__llvm_pgo_data_main to i8*), i8* bitcast ({ i32, i32, i8*, i64* }* @__llvm_pgo_data__Z10foo_inlinev to i8*)], section "llvm.metadata" +// CHECK: @llvm.used = appending global [4 x i8*] [i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_pgo_data__Z3foov to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_pgo_data__Z8foo_weakv to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_pgo_data_main to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_pgo_data__Z10foo_inlinev to i8*)], section "llvm.metadata"