From: Duncan P. N. Exon Smith Date: Wed, 16 Apr 2014 16:03:27 +0000 (+0000) Subject: InstrProf: Calculate a better function hash X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=98461062a9b329e6d46e5016fd13e4e65edf8c84;p=clang InstrProf: Calculate a better function hash The function hash should change when control flow changes. This patch hashes the type of each AST node that affects counters, rather than just counting how many there are. These types are combined into a small enumerator that currently has 16 values. The new hash algorithm packs the enums for consecutively visited types into a `uint64_t`. In order to save space for new types, the types are assumed to be 6-bit values (instead of 4-bit). In order to minimize overhead for functions with little control flow, the `uint64_t` is used directly as a hash if it never fills up; if it does, it's passed through an MD5 context. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@206397 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CodeGenPGO.cpp b/lib/CodeGen/CodeGenPGO.cpp index c451bef57c..d3d89e588a 100644 --- a/lib/CodeGen/CodeGenPGO.cpp +++ b/lib/CodeGen/CodeGenPGO.cpp @@ -17,7 +17,9 @@ #include "clang/AST/StmtVisitor.h" #include "llvm/Config/config.h" // for strtoull()/strtoul() define #include "llvm/IR/MDBuilder.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/MD5.h" using namespace clang; using namespace CodeGen; @@ -321,10 +323,73 @@ llvm::Function *CodeGenPGO::emitInitialization(CodeGenModule &CGM) { } namespace { +/// \brief Stable hasher for PGO region counters. +/// +/// PGOHash produces a stable hash of a given function's control flow. +/// +/// Changing the output of this hash will invalidate all previously generated +/// profiles -- i.e., don't do it. +/// +/// \note When this hash does eventually change (years?), we still need to +/// support old hashes. We'll need to pull in the version number from the +/// profile data format and use the matching hash function. +class PGOHash { + uint64_t Working; + unsigned Count; + llvm::MD5 MD5; + + static const int NumBitsPerType = 6; + static const unsigned NumTypesPerWord = sizeof(uint64_t) * 8 / NumBitsPerType; + static const unsigned TooBig = 1u << NumBitsPerType; + +public: + /// \brief Hash values for AST nodes. + /// + /// Distinct values for AST nodes that have region counters attached. + /// + /// These values must be stable. All new members must be added at the end, + /// and no members should be removed. Changing the enumeration value for an + /// AST node will affect the hash of every function that contains that node. + enum HashType : unsigned char { + None = 0, + LabelStmt = 1, + WhileStmt, + DoStmt, + ForStmt, + CXXForRangeStmt, + ObjCForCollectionStmt, + SwitchStmt, + CaseStmt, + DefaultStmt, + IfStmt, + CXXTryStmt, + CXXCatchStmt, + ConditionalOperator, + BinaryOperatorLAnd, + BinaryOperatorLOr, + BinaryConditionalOperator, + + // Keep this last. It's for the static assert that follows. + LastHashType + }; + static_assert(LastHashType <= TooBig, "Too many types in HashType"); + + // TODO: When this format changes, take in a version number here, and use the + // old hash calculation for file formats that used the old hash. + PGOHash() : Working(0), Count(0) {} + void combine(HashType Type); + uint64_t finalize(); +}; +const int PGOHash::NumBitsPerType; +const unsigned PGOHash::NumTypesPerWord; +const unsigned PGOHash::TooBig; + /// A RecursiveASTVisitor that fills a map of statements to PGO counters. struct MapRegionCounters : public RecursiveASTVisitor { /// The next counter value to assign. unsigned NextCounter; + /// The function hash. + PGOHash Hash; /// The map of statements to counters. llvm::DenseMap &CounterMap; @@ -356,33 +421,56 @@ namespace { } bool VisitStmt(const Stmt *S) { + auto Type = getHashType(S); + if (Type == PGOHash::None) + return true; + + CounterMap[S] = NextCounter++; + Hash.combine(Type); + return true; + } + PGOHash::HashType getHashType(const Stmt *S) { switch (S->getStmtClass()) { default: break; case Stmt::LabelStmtClass: + return PGOHash::LabelStmt; case Stmt::WhileStmtClass: + return PGOHash::WhileStmt; case Stmt::DoStmtClass: + return PGOHash::DoStmt; case Stmt::ForStmtClass: + return PGOHash::ForStmt; case Stmt::CXXForRangeStmtClass: + return PGOHash::CXXForRangeStmt; case Stmt::ObjCForCollectionStmtClass: + return PGOHash::ObjCForCollectionStmt; case Stmt::SwitchStmtClass: + return PGOHash::SwitchStmt; case Stmt::CaseStmtClass: + return PGOHash::CaseStmt; case Stmt::DefaultStmtClass: + return PGOHash::DefaultStmt; case Stmt::IfStmtClass: + return PGOHash::IfStmt; case Stmt::CXXTryStmtClass: + return PGOHash::CXXTryStmt; case Stmt::CXXCatchStmtClass: + return PGOHash::CXXCatchStmt; case Stmt::ConditionalOperatorClass: + return PGOHash::ConditionalOperator; case Stmt::BinaryConditionalOperatorClass: - CounterMap[S] = NextCounter++; - break; + return PGOHash::BinaryConditionalOperator; case Stmt::BinaryOperatorClass: { const BinaryOperator *BO = cast(S); - if (BO->getOpcode() == BO_LAnd || BO->getOpcode() == BO_LOr) - CounterMap[S] = NextCounter++; + if (BO->getOpcode() == BO_LAnd) + return PGOHash::BinaryOperatorLAnd; + if (BO->getOpcode() == BO_LOr) + return PGOHash::BinaryOperatorLOr; break; } } - return true; + return PGOHash::None; } }; @@ -774,6 +862,43 @@ namespace { }; } +void PGOHash::combine(HashType Type) { + // Check that we never combine 0 and only have six bits. + assert(Type && "Hash is invalid: unexpected type 0"); + assert(unsigned(Type) < TooBig && "Hash is invalid: too many types"); + + // Pass through MD5 if enough work has built up. + if (Count && Count % NumTypesPerWord == 0) { + using namespace llvm::support; + uint64_t Swapped = endian::byte_swap(Working); + MD5.update(llvm::makeArrayRef((uint8_t *)&Swapped, sizeof(Swapped))); + Working = 0; + } + + // Accumulate the current type. + ++Count; + Working = Working << NumBitsPerType | Type; +} + +uint64_t PGOHash::finalize() { + // Use Working as the hash directly if we never used MD5. + if (Count <= NumTypesPerWord) + // No need to byte swap here, since none of the math was endian-dependent. + // This number will be byte-swapped as required on endianness transitions, + // so we will see the same value on the other side. + return Working; + + // Check for remaining work in Working. + if (Working) + MD5.update(Working); + + // Finalize the MD5 and return the hash. + llvm::MD5::MD5Result Result; + MD5.final(Result); + using namespace llvm::support; + return endian::read(Result); +} + static void emitRuntimeHook(CodeGenModule &CGM) { const char *const RuntimeVarName = "__llvm_profile_runtime"; const char *const RuntimeUserName = "__llvm_profile_runtime_user"; @@ -851,8 +976,7 @@ void CodeGenPGO::mapRegionCounters(const Decl *D) { else if (const CapturedDecl *CD = dyn_cast_or_null(D)) Walker.TraverseDecl(const_cast(CD)); NumRegionCounters = Walker.NextCounter; - // FIXME: The number of counters isn't sufficient for the hash - FunctionHash = NumRegionCounters; + FunctionHash = Walker.Hash.finalize(); } void CodeGenPGO::computeRegionCounts(const Decl *D) { diff --git a/test/Profile/Inputs/c-attributes.profdata b/test/Profile/Inputs/c-attributes.profdata index 97e682480d..e4d4694a8d 100644 --- a/test/Profile/Inputs/c-attributes.profdata +++ b/test/Profile/Inputs/c-attributes.profdata @@ -23,7 +23,7 @@ cold_func 124750 main -6 +219169028 6 1 0 diff --git a/test/Profile/Inputs/c-captured.profdata b/test/Profile/Inputs/c-captured.profdata index c2490d9b68..c1baefc894 100644 --- a/test/Profile/Inputs/c-captured.profdata +++ b/test/Profile/Inputs/c-captured.profdata @@ -1,23 +1,23 @@ c-captured.c:__captured_stmt -2 +10 2 1 1 c-captured.c:__captured_stmt1 -3 +266 3 1 10 1 main -1 +0 1 1 debug_captured -3 +650 3 1 1 diff --git a/test/Profile/Inputs/c-counter-overflows.profdata b/test/Profile/Inputs/c-counter-overflows.profdata index 24863780ef..5a3633ecfc 100644 --- a/test/Profile/Inputs/c-counter-overflows.profdata +++ b/test/Profile/Inputs/c-counter-overflows.profdata @@ -1,5 +1,5 @@ main -8 +285734896137 8 1 68719476720 diff --git a/test/Profile/Inputs/c-general.profdata b/test/Profile/Inputs/c-general.profdata index b1d1d06122..19e5bd3db4 100644 --- a/test/Profile/Inputs/c-general.profdata +++ b/test/Profile/Inputs/c-general.profdata @@ -1,5 +1,5 @@ simple_loops -4 +16515 4 1 100 @@ -7,7 +7,7 @@ simple_loops 75 conditionals -11 +74917022372782735 11 1 100 @@ -22,7 +22,7 @@ conditionals 100 early_exits -9 +44128811889290 9 1 0 @@ -35,7 +35,7 @@ early_exits 0 jumps -22 +2016037664281362839 22 1 1 @@ -61,7 +61,7 @@ jumps 9 switches -19 +2745195701975551402 19 1 1 @@ -84,7 +84,7 @@ switches 0 big_switch -17 +10218718452081869619 17 1 32 @@ -105,7 +105,7 @@ big_switch 2 boolean_operators -8 +291222909838 8 1 100 @@ -117,7 +117,7 @@ boolean_operators 50 boolop_loops -9 +9760565944591 9 1 50 @@ -130,14 +130,14 @@ boolop_loops 26 conditional_operator -3 +848 3 1 0 1 do_fallthrough -4 +16586 4 1 10 @@ -145,12 +145,12 @@ do_fallthrough 8 main -1 +0 1 1 c-general.c:static_func -2 +4 2 1 10 diff --git a/test/Profile/Inputs/c-outdated-data.profdata b/test/Profile/Inputs/c-outdated-data.profdata index 27015be82d..d57a6e9d06 100644 --- a/test/Profile/Inputs/c-outdated-data.profdata +++ b/test/Profile/Inputs/c-outdated-data.profdata @@ -1,12 +1,12 @@ no_usable_data -3 +650 3 1 0 0 main -1 +0 1 1 diff --git a/test/Profile/Inputs/c-unprofiled-blocks.profdata b/test/Profile/Inputs/c-unprofiled-blocks.profdata index bf2158a4c5..87b48e13fb 100644 --- a/test/Profile/Inputs/c-unprofiled-blocks.profdata +++ b/test/Profile/Inputs/c-unprofiled-blocks.profdata @@ -1,5 +1,5 @@ never_called -9 +44257542701577 9 0 0 @@ -17,7 +17,7 @@ main 1 dead_code -10 +2859007309808137 10 1 0 diff --git a/test/Profile/Inputs/cxx-class.profdata b/test/Profile/Inputs/cxx-class.profdata index 756640d2f3..b4645edf93 100644 --- a/test/Profile/Inputs/cxx-class.profdata +++ b/test/Profile/Inputs/cxx-class.profdata @@ -1,40 +1,40 @@ _Z14simple_wrapperv -2 +4 2 1 100 main -1 +0 1 1 _ZN6SimpleD1Ev -2 +10 2 0 0 _ZN6SimpleD2Ev -2 +10 2 100 99 _ZN6Simple6methodEv -2 +10 2 100 99 _ZN6SimpleC1Ei -2 +10 2 0 0 _ZN6SimpleC2Ei -2 +10 2 100 99 diff --git a/test/Profile/Inputs/cxx-lambda.profdata b/test/Profile/Inputs/cxx-lambda.profdata index dd6c6ec4f6..36646b5ab3 100644 --- a/test/Profile/Inputs/cxx-lambda.profdata +++ b/test/Profile/Inputs/cxx-lambda.profdata @@ -1,17 +1,17 @@ cxx-lambda.cpp:_ZZ7lambdasvENK3$_0clEi -3 +654 3 10 9 9 main -1 +0 1 1 _Z7lambdasv -4 +41226 4 1 1 diff --git a/test/Profile/Inputs/cxx-templates.profdata b/test/Profile/Inputs/cxx-templates.profdata index f7e9dc105b..5ea840038d 100644 --- a/test/Profile/Inputs/cxx-templates.profdata +++ b/test/Profile/Inputs/cxx-templates.profdata @@ -1,16 +1,16 @@ main -1 +0 1 1 _Z4loopILj0EEvv -2 +4 2 1 0 _Z4loopILj100EEvv -2 +4 2 1 100 diff --git a/test/Profile/Inputs/cxx-throws.profdata b/test/Profile/Inputs/cxx-throws.profdata index 01e6c3c286..4016eca2ac 100644 --- a/test/Profile/Inputs/cxx-throws.profdata +++ b/test/Profile/Inputs/cxx-throws.profdata @@ -1,5 +1,5 @@ _Z6throwsv -9 +18359008150154 9 1 100 @@ -12,7 +12,7 @@ _Z6throwsv 100 main -1 +0 1 1 diff --git a/test/Profile/Inputs/objc-general.profdata b/test/Profile/Inputs/objc-general.profdata index 8841e908c9..8d6771f9b3 100644 --- a/test/Profile/Inputs/objc-general.profdata +++ b/test/Profile/Inputs/objc-general.profdata @@ -1,17 +1,17 @@ objc-general.m:__13+[A foreach:]_block_invoke -2 +10 2 2 1 objc-general.m:+[A foreach:] -2 +6 2 1 2 main -1 +0 1 1 diff --git a/test/Profile/c-linkage-available_externally.c b/test/Profile/c-linkage-available_externally.c index cbdf306c82..adc1e6eee5 100644 --- a/test/Profile/c-linkage-available_externally.c +++ b/test/Profile/c-linkage-available_externally.c @@ -4,7 +4,7 @@ // CHECK: @__llvm_profile_counters_foo = linkonce_odr global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8 // CHECK: @__llvm_profile_name_foo = linkonce_odr constant [3 x i8] c"foo", section "__DATA,__llvm_prf_names", align 1 -// CHECK: @__llvm_profile_data_foo = linkonce_odr constant { i32, i32, i64, i8*, i64* } { i32 3, i32 1, i64 1, i8* getelementptr inbounds ([3 x i8]* @__llvm_profile_name_foo, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64]* @__llvm_profile_counters_foo, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8 +// CHECK: @__llvm_profile_data_foo = linkonce_odr constant { i32, i32, i64, i8*, i64* } { i32 3, i32 1, i64 {{[0-9]+}}, i8* getelementptr inbounds ([3 x i8]* @__llvm_profile_name_foo, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64]* @__llvm_profile_counters_foo, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8 inline int foo(void) { return 1; } int main(void) { diff --git a/test/Profile/c-linkage.c b/test/Profile/c-linkage.c index 72eae1f0f3..482e8da900 100644 --- a/test/Profile/c-linkage.c +++ b/test/Profile/c-linkage.c @@ -4,18 +4,18 @@ // CHECK: @__llvm_profile_runtime = external global i32 // CHECK: @__llvm_profile_counters_foo = global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8 // CHECK: @__llvm_profile_name_foo = constant [3 x i8] c"foo", section "__DATA,__llvm_prf_names", align 1 -// CHECK: @__llvm_profile_data_foo = constant { i32, i32, i64, i8*, i64* } { i32 3, i32 1, i64 1, i8* getelementptr inbounds ([3 x i8]* @__llvm_profile_name_foo, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64]* @__llvm_profile_counters_foo, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8 +// CHECK: @__llvm_profile_data_foo = constant { i32, i32, i64, i8*, i64* } { i32 3, i32 1, i64 {{[0-9]+}}, i8* getelementptr inbounds ([3 x i8]* @__llvm_profile_name_foo, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64]* @__llvm_profile_counters_foo, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8 void foo(void) { } // CHECK: @__llvm_profile_counters_foo_weak = weak global [5 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8 // CHECK: @__llvm_profile_name_foo_weak = weak constant [8 x i8] c"foo_weak", section "__DATA,__llvm_prf_names", align 1 -// CHECK: @__llvm_profile_data_foo_weak = weak constant { i32, i32, i64, i8*, i64* } { i32 8, i32 5, i64 5, i8* getelementptr inbounds ([8 x i8]* @__llvm_profile_name_foo_weak, i32 0, i32 0), i64* getelementptr inbounds ([5 x i64]* @__llvm_profile_counters_foo_weak, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8 +// CHECK: @__llvm_profile_data_foo_weak = weak constant { i32, i32, i64, i8*, i64* } { i32 8, i32 5, i64 {{[0-9]+}}, i8* getelementptr inbounds ([8 x i8]* @__llvm_profile_name_foo_weak, i32 0, i32 0), i64* getelementptr inbounds ([5 x i64]* @__llvm_profile_counters_foo_weak, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8 void foo_weak(void) __attribute__((weak)); void foo_weak(void) { if (0){} if (0){} if (0){} if (0){} } // CHECK: @__llvm_profile_counters_main = global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8 // CHECK: @__llvm_profile_name_main = constant [4 x i8] c"main", section "__DATA,__llvm_prf_names", align 1 -// CHECK: @__llvm_profile_data_main = constant { i32, i32, i64, i8*, i64* } { i32 4, i32 1, i64 1, i8* getelementptr inbounds ([4 x i8]* @__llvm_profile_name_main, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64]* @__llvm_profile_counters_main, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8 +// CHECK: @__llvm_profile_data_main = constant { i32, i32, i64, i8*, i64* } { i32 4, i32 1, i64 {{[0-9]+}}, i8* getelementptr inbounds ([4 x i8]* @__llvm_profile_name_main, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64]* @__llvm_profile_counters_main, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8 static void foo_internal(void); int main(void) { foo(); @@ -26,7 +26,7 @@ int main(void) { // CHECK: @__llvm_profile_counters_foo_internal = internal global [3 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8 // CHECK: @__llvm_profile_name_foo_internal = internal constant [24 x i8] c"c-linkage.c:foo_internal", section "__DATA,__llvm_prf_names", align 1 -// CHECK: @__llvm_profile_data_foo_internal = internal constant { i32, i32, i64, i8*, i64* } { i32 24, i32 3, i64 3, i8* getelementptr inbounds ([24 x i8]* @__llvm_profile_name_foo_internal, i32 0, i32 0), i64* getelementptr inbounds ([3 x i64]* @__llvm_profile_counters_foo_internal, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8 +// CHECK: @__llvm_profile_data_foo_internal = internal constant { i32, i32, i64, i8*, i64* } { i32 24, i32 3, i64 {{[0-9]+}}, i8* getelementptr inbounds ([24 x i8]* @__llvm_profile_name_foo_internal, i32 0, i32 0), i64* getelementptr inbounds ([3 x i64]* @__llvm_profile_counters_foo_internal, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8 static void foo_internal(void) { if (0){} if (0){} } // CHECK: @llvm.used = appending global [5 x i8*] [i8* bitcast (i32 ()* @__llvm_profile_runtime_user to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_foo to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_foo_weak to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_main to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_foo_internal to i8*)], section "llvm.metadata" diff --git a/test/Profile/cxx-linkage.cpp b/test/Profile/cxx-linkage.cpp index 44c1983c84..92dfed9882 100644 --- a/test/Profile/cxx-linkage.cpp +++ b/test/Profile/cxx-linkage.cpp @@ -3,18 +3,18 @@ // CHECK: @__llvm_profile_runtime = external global i32 // CHECK: @__llvm_profile_counters__Z3foov = global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8 // CHECK: @__llvm_profile_name__Z3foov = constant [7 x i8] c"_Z3foov", section "__DATA,__llvm_prf_names", align 1 -// CHECK: @__llvm_profile_data__Z3foov = constant { i32, i32, i64, i8*, i64* } { i32 7, i32 1, i64 1, i8* getelementptr inbounds ([7 x i8]* @__llvm_profile_name__Z3foov, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64]* @__llvm_profile_counters__Z3foov, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8 +// CHECK: @__llvm_profile_data__Z3foov = constant { i32, i32, i64, i8*, i64* } { i32 7, i32 1, i64 {{[0-9]+}}, i8* getelementptr inbounds ([7 x i8]* @__llvm_profile_name__Z3foov, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64]* @__llvm_profile_counters__Z3foov, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8 void foo(void) { } // CHECK: @__llvm_profile_counters__Z8foo_weakv = weak global [5 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8 // CHECK: @__llvm_profile_name__Z8foo_weakv = weak constant [12 x i8] c"_Z8foo_weakv", section "__DATA,__llvm_prf_names", align 1 -// CHECK: @__llvm_profile_data__Z8foo_weakv = weak constant { i32, i32, i64, i8*, i64* } { i32 12, i32 5, i64 5, i8* getelementptr inbounds ([12 x i8]* @__llvm_profile_name__Z8foo_weakv, i32 0, i32 0), i64* getelementptr inbounds ([5 x i64]* @__llvm_profile_counters__Z8foo_weakv, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8 +// CHECK: @__llvm_profile_data__Z8foo_weakv = weak constant { i32, i32, i64, i8*, i64* } { i32 12, i32 5, i64 {{[0-9]+}}, i8* getelementptr inbounds ([12 x i8]* @__llvm_profile_name__Z8foo_weakv, i32 0, i32 0), i64* getelementptr inbounds ([5 x i64]* @__llvm_profile_counters__Z8foo_weakv, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8 void foo_weak(void) __attribute__((weak)); void foo_weak(void) { if (0){} if (0){} if (0){} if (0){} } // CHECK: @__llvm_profile_counters_main = global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8 // CHECK: @__llvm_profile_name_main = constant [4 x i8] c"main", section "__DATA,__llvm_prf_names", align 1 -// CHECK: @__llvm_profile_data_main = constant { i32, i32, i64, i8*, i64* } { i32 4, i32 1, i64 1, i8* getelementptr inbounds ([4 x i8]* @__llvm_profile_name_main, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64]* @__llvm_profile_counters_main, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8 +// CHECK: @__llvm_profile_data_main = constant { i32, i32, i64, i8*, i64* } { i32 4, i32 1, i64 {{[0-9]+}}, i8* getelementptr inbounds ([4 x i8]* @__llvm_profile_name_main, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64]* @__llvm_profile_counters_main, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8 inline void foo_inline(void); int main(void) { foo(); @@ -25,7 +25,7 @@ int main(void) { // CHECK: @__llvm_profile_counters__Z10foo_inlinev = linkonce_odr global [7 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8 // CHECK: @__llvm_profile_name__Z10foo_inlinev = linkonce_odr constant [15 x i8] c"_Z10foo_inlinev", section "__DATA,__llvm_prf_names", align 1 -// CHECK: @__llvm_profile_data__Z10foo_inlinev = linkonce_odr constant { i32, i32, i64, i8*, i64* } { i32 15, i32 7, i64 7, i8* getelementptr inbounds ([15 x i8]* @__llvm_profile_name__Z10foo_inlinev, i32 0, i32 0), i64* getelementptr inbounds ([7 x i64]* @__llvm_profile_counters__Z10foo_inlinev, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8 +// CHECK: @__llvm_profile_data__Z10foo_inlinev = linkonce_odr constant { i32, i32, i64, i8*, i64* } { i32 15, i32 7, i64 {{[0-9]+}}, i8* getelementptr inbounds ([15 x i8]* @__llvm_profile_name__Z10foo_inlinev, i32 0, i32 0), i64* getelementptr inbounds ([7 x i64]* @__llvm_profile_counters__Z10foo_inlinev, i32 0, i32 0) }, section "__DATA,__llvm_prf_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 [5 x i8*] [i8* bitcast (i32 ()* @__llvm_profile_runtime_user to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data__Z3foov to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data__Z8foo_weakv to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_main to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data__Z10foo_inlinev to i8*)], section "llvm.metadata"