]> granicus.if.org Git - clang/commitdiff
CodeGen: Include a function hash in instrumentation based profiling
authorJustin Bogner <mail@justinbogner.com>
Tue, 18 Mar 2014 21:58:06 +0000 (21:58 +0000)
committerJustin Bogner <mail@justinbogner.com>
Tue, 18 Mar 2014 21:58:06 +0000 (21:58 +0000)
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

lib/CodeGen/CodeGenPGO.cpp
lib/CodeGen/CodeGenPGO.h
test/Profile/Inputs/c-attributes.profdata
test/Profile/Inputs/c-counter-overflows.profdata
test/Profile/Inputs/c-general.profdata
test/Profile/Inputs/c-outdated-data.profdata
test/Profile/Inputs/cxx-class.profdata
test/Profile/Inputs/cxx-throws.profdata
test/Profile/Inputs/objc-general.profdata
test/Profile/c-linkage.c
test/Profile/cxx-linkage.cpp

index 207cb665b0fc53f7d58ce127c6f650ba38c7e379..1f2fe38c40e2193dd41485bd7b2bc4b2e994accb 100644 (file)
@@ -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<uint64_t> &Counts) {
   // Find the relevant section of the pgo-data file.
   llvm::StringMap<unsigned>::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<BlockDecl>(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<uint64_t>();
-  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;
   }
index 2f1fe5dba8aa1c427b6da9fa0d700faa61579458..e859324ae086048d7f9de55fef9c86281480fe86 100644 (file)
@@ -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<uint64_t> &Counts);
+  bool getFunctionCounts(StringRef FuncName, uint64_t &FuncHash,
+                         std::vector<uint64_t> &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<const Stmt*, unsigned> *RegionCounterMap;
   llvm::DenseMap<const Stmt*, uint64_t> *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;
   }
index 38decbd5568a7d573261c65cf2192e11df618078..97e682480dcc3357c4938890e2479828e03b98ed 100644 (file)
@@ -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
index 377a08502d104179263bcf7cc5bed33dd87aebb3..24863780ef8774da7a9dfcb2997e7e917cdc613a 100644 (file)
@@ -1,4 +1,6 @@
-main 8
+main
+8
+8
 1
 68719476720
 64424509425
index 083b8fe55b4d7b61be68a2c57cc7bded95dbf5e7..a1d56104a21c215b8c82fb1a92f81000178a93df 100644 (file)
@@ -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
 
index e1c51a6975d393515dd1c3a391af9c417e01e61e..27015be82d07b4b8030d447b3a48c4410295e1b0 100644 (file)
@@ -1,8 +1,12 @@
-no_usable_data 3
+no_usable_data
+3
+3
 1
 0
 0
 
-main 1
+main
+1
+1
 1
 
index 983ab5511655521d5880be823a910cbe81e4ba15..756640d2f334711c6b76433094d1d0730d83fe03 100644 (file)
@@ -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
 
index a49522f55844498765ff073494e1d249d693768b..01e6c3c286efb257f58f5c9e2988f32e941cf0e8 100644 (file)
@@ -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
 
index 06c9832b3c5894546c31eb59c53457ee7738d9ea..8841e908c92ae72b3ea3cb64c9bea833ed708bbc 100644 (file)
@@ -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
 
index dddc895068c3f0020e21c736f0e9fb3f9d92d434..22a2535c4e4bb63f965636ab5099ec7b9da1acf7 100644 (file)
@@ -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"
index 6597e25105b514f183ba50ff8d78b1f6ac75a978..8c49dff26a5dc40b6f07e937db0069f054e25f41 100644 (file)
@@ -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"