Index: lib/profile/InstrProfilingFile.c =================================================================== --- lib/profile/InstrProfilingFile.c +++ lib/profile/InstrProfilingFile.c @@ -225,6 +225,11 @@ fclose(ProfileFile); return NULL; } + // Truncate the file in case merging of value profile did not happend. + // (which can leave garbage at the end of profile file). + if (!VPMergeHook) + truncate(ProfileFileName, 0); + return ProfileFile; } @@ -234,6 +239,7 @@ FILE *OutputFile; int MergeDone = 0; + VPMergeHook = &lprofMergeValueProfData; if (!doMerging()) OutputFile = fopen(OutputName, "ab"); else Index: lib/profile/InstrProfilingMerge.c =================================================================== --- lib/profile/InstrProfilingMerge.c +++ lib/profile/InstrProfilingMerge.c @@ -17,8 +17,9 @@ #define INSTR_PROF_VALUE_PROF_DATA #include "InstrProfData.inc" -COMPILER_RT_WEAK void (*VPMergeHook)(ValueProfData *, - __llvm_profile_data *) = NULL; +COMPILER_RT_VISIBILITY +void (*VPMergeHook)(ValueProfData *, __llvm_profile_data *); + COMPILER_RT_VISIBILITY uint64_t lprofGetLoadModuleSignature() { /* A very fast way to compute a module signature. */ Index: lib/profile/InstrProfilingMergeFile.c =================================================================== --- lib/profile/InstrProfilingMergeFile.c +++ lib/profile/InstrProfilingMergeFile.c @@ -17,14 +17,11 @@ #define INSTR_PROF_VALUE_PROF_DATA #include "InstrProfData.inc" -void (*VPMergeHook)(ValueProfData *, - __llvm_profile_data *) = &lprofMergeValueProfData; - /* Merge value profile data pointed to by SrcValueProfData into * in-memory profile counters pointed by to DstData. */ void lprofMergeValueProfData(ValueProfData *SrcValueProfData, __llvm_profile_data *DstData) { - unsigned I, S, V, C; + unsigned I, S, V, C, Index = 0; InstrProfValueData *VData; ValueProfRecord *VR = getFirstValueProfRecord(SrcValueProfData); for (I = 0; I < SrcValueProfData->NumValueKinds; I++) { @@ -33,8 +30,9 @@ uint8_t NV = VR->SiteCountArray[S]; for (V = 0; V < NV; V++) { for (C = 0; C < VData[V].Count; C++) - __llvm_profile_instrument_target(VData[V].Value, DstData, S); + __llvm_profile_instrument_target(VData[S + V].Value, DstData, Index); } + ++Index; } VR = getValueProfRecordNext(VR); } Index: test/profile/instrprof-value-merge.c =================================================================== --- /dev/null +++ test/profile/instrprof-value-merge.c @@ -0,0 +1,48 @@ +// RUN: %clang_pgogen -o %t -O3 %s +// RUN: rm -rf %t.profdir +// RUN: env LLVM_PROFILE_FILE=%t.profdir/default_%m.profraw %run %t +// RUN: env LLVM_PROFILE_FILE=%t.profdir/default_%m.profraw %run %t +// RUN: env LLVM_PROFILE_FILE=%t.profdir/default_%m.profraw %run %t +// RUN: env LLVM_PROFILE_FILE=%t.profdir/default_%m.profraw %run %t 1 +// RUN: env LLVM_PROFILE_FILE=%t.profdir/default_%m.profraw %run %t 1 +// RUN: llvm-profdata show -counts -function=main -ic-targets -memop-sizes %t.profdir/default_*.profraw | FileCheck %s + +#include + +void (*f)(); + +char dst[200]; +char src[200]; +volatile int n; + +__attribute__((noinline)) void foo() {} + +__attribute__((noinline)) void bar() { + f = foo; + n = 4; +} +int main(int argc, char *argv[]) { + bar(); + if (argc == 1) + f(); + else { + memcpy((void *)dst, (void *)src, n); + memcpy((void *)(dst + 2), (void *)src, n + 1); + memcpy((void *)(dst + 9), (void *)src, n + 2); + } +} + +// CHECK: main: +// CHECK: Hash: 0x00010006e852da94 +// CHECK: Counters: 2 +// CHECK: Indirect Call Site Count: 1 +// CHECK: Number of Memory Intrinsics Calls: 3 +// CHECK: Block counts: [3, 2] +// CHECK: Indirect Target Results: +// CHECK: [ 0, foo, 3 ] +// CHECK: Memory Intrinsic Size Results: +// CHECK: [ 0, 4, 2 ] +// CHECK: [ 1, 5, 2 ] +// CHECK: [ 2, 6, 2 ] +// CHECK: Instrumentation level: IR +