diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -102,7 +102,7 @@ // Default filename used for profile generation. std::string getDefaultProfileGenName() { - return DebugInfoCorrelate ? "default_%p.proflite" : "default_%m.profraw"; + return DebugInfoCorrelate ? "default_%m.proflite" : "default_%m.profraw"; } class EmitAssemblyHelper { diff --git a/compiler-rt/lib/profile/InstrProfilingMerge.c b/compiler-rt/lib/profile/InstrProfilingMerge.c --- a/compiler-rt/lib/profile/InstrProfilingMerge.c +++ b/compiler-rt/lib/profile/InstrProfilingMerge.c @@ -47,13 +47,16 @@ COMPILER_RT_VISIBILITY int __llvm_profile_check_compatibility(const char *ProfileData, uint64_t ProfileSize) { - /* Check profile header only for now */ __llvm_profile_header *Header = (__llvm_profile_header *)ProfileData; __llvm_profile_data *SrcDataStart, *SrcDataEnd, *SrcData, *DstData; + char *SrcCountersStart, *SrcCountersEnd; SrcDataStart = (__llvm_profile_data *)(ProfileData + sizeof(__llvm_profile_header) + Header->BinaryIdsSize); SrcDataEnd = SrcDataStart + Header->DataSize; + SrcCountersStart = (char *)SrcDataEnd; + SrcCountersEnd = SrcCountersStart + + Header->CountersSize * __llvm_profile_counter_entry_size(); if (ProfileSize < sizeof(__llvm_profile_header)) return 1; @@ -72,6 +75,11 @@ Header->ValueKindLast != IPVK_Last) return 1; + if (SrcCountersEnd - SrcCountersStart != + __llvm_profile_end_counters() - __llvm_profile_begin_counters()) { + return 1; + } + if (ProfileSize < sizeof(__llvm_profile_header) + Header->BinaryIdsSize + Header->DataSize * sizeof(__llvm_profile_data) + Header->NamesSize + @@ -102,13 +110,6 @@ COMPILER_RT_VISIBILITY int __llvm_profile_merge_from_buffer(const char *ProfileData, uint64_t ProfileSize) { - if (__llvm_profile_get_version() & VARIANT_MASK_DBG_CORRELATE) { - PROF_ERR( - "%s\n", - "Debug info correlation does not support profile merging at runtime. " - "Instead, merge raw profiles using the llvm-profdata tool."); - return 1; - } if (__llvm_profile_get_version() & VARIANT_MASK_TEMPORAL_PROF) { PROF_ERR("%s\n", "Temporal profiles do not support profile merging at runtime. " @@ -118,7 +119,8 @@ __llvm_profile_data *SrcDataStart, *SrcDataEnd, *SrcData, *DstData; __llvm_profile_header *Header = (__llvm_profile_header *)ProfileData; - char *SrcCountersStart; + char *SrcCountersStart, *DstCounter; + const char *SrcCountersEnd, *SrcCounter; const char *SrcNameStart; const char *SrcValueProfDataStart, *SrcValueProfData; uintptr_t CountersDelta = Header->CountersDelta; @@ -128,14 +130,36 @@ Header->BinaryIdsSize); SrcDataEnd = SrcDataStart + Header->DataSize; SrcCountersStart = (char *)SrcDataEnd; - SrcNameStart = SrcCountersStart + - Header->CountersSize * __llvm_profile_counter_entry_size(); + SrcCountersEnd = SrcCountersStart + + Header->CountersSize * __llvm_profile_counter_entry_size(); + SrcNameStart = SrcCountersEnd; SrcValueProfDataStart = SrcNameStart + Header->NamesSize + __llvm_profile_get_num_padding_bytes(Header->NamesSize); if (SrcNameStart < SrcCountersStart) return 1; + // Merge counters when there is no data section and debug info correlation is + // enabled. + if (Header->DataSize == 0) { + if (!(__llvm_profile_get_version() & VARIANT_MASK_DBG_CORRELATE)) { + PROF_ERR("%s\n", "Missing profile data section."); + return 1; + } + for (SrcCounter = SrcCountersStart, + DstCounter = __llvm_profile_begin_counters(); + SrcCounter < SrcCountersEnd;) { + if (__llvm_profile_get_version() & VARIANT_MASK_BYTE_COVERAGE) { + *DstCounter &= *SrcCounter; + } else { + *(uint64_t *)DstCounter += *(uint64_t *)SrcCounter; + } + SrcCounter += __llvm_profile_counter_entry_size(); + DstCounter += __llvm_profile_counter_entry_size(); + } + return 0; + } + for (SrcData = SrcDataStart, DstData = (__llvm_profile_data *)__llvm_profile_begin_data(), SrcValueProfData = SrcValueProfDataStart; diff --git a/compiler-rt/test/profile/Darwin/instrprof-debug-info-correlate.c b/compiler-rt/test/profile/Darwin/instrprof-debug-info-correlate.c --- a/compiler-rt/test/profile/Darwin/instrprof-debug-info-correlate.c +++ b/compiler-rt/test/profile/Darwin/instrprof-debug-info-correlate.c @@ -18,3 +18,23 @@ // RUN: llvm-profdata merge -o %t.cov.normal.profdata %t.cov.profraw // RUN: diff <(llvm-profdata show --all-functions --counts %t.cov.normal.profdata) <(llvm-profdata show --all-functions --counts %t.cov.profdata) + +// Test debug info correlate with online merging. + +// RUN: env LLVM_PROFILE_FILE=%t-1.profraw %run %t.normal +// RUN: env LLVM_PROFILE_FILE=%t-2.profraw %run %t.normal +// RUN: llvm-profdata merge -o %t.normal.profdata %t-1.profraw %t-2.profraw + +// RUN: rm -rf %t.profdir && mkdir %t.profdir +// RUN: env LLVM_PROFILE_FILE=%t.profdir/%m.proflite %run %t +// RUN: env LLVM_PROFILE_FILE=%t.profdir/%m.proflite %run %t +// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t.dSYM %t.profdir/ + +// RUN: diff <(llvm-profdata show --all-functions --counts %t.normal.profdata) <(llvm-profdata show --all-functions --counts %t.profdata) + +// RUN: rm -rf %t.profdir && mkdir %t.profdir +// RUN: env LLVM_PROFILE_FILE=%t.profdir/%m.cov.proflite %run %t.cov +// RUN: env LLVM_PROFILE_FILE=%t.profdir/%m.cov.proflite %run %t.cov +// RUN: llvm-profdata merge -o %t.cov.profdata --debug-info=%t.cov.dSYM %t.profdir/ + +// RUN: diff <(llvm-profdata show --all-functions --counts %t.cov.normal.profdata) <(llvm-profdata show --all-functions --counts %t.cov.profdata) diff --git a/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate.c b/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate.c --- a/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate.c +++ b/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate.c @@ -24,3 +24,23 @@ // RUN: llvm-profdata merge -o %t.cov.normal.profdata %t.cov.profraw // RUN: diff <(llvm-profdata show --all-functions --counts %t.cov.normal.profdata) <(llvm-profdata show --all-functions --counts %t.cov.profdata) + +// Test debug info correlate with online merging. + +// RUN: env LLVM_PROFILE_FILE=%t-1.profraw %run %t.normal +// RUN: env LLVM_PROFILE_FILE=%t-2.profraw %run %t.normal +// RUN: llvm-profdata merge -o %t.normal.profdata %t-1.profraw %t-2.profraw + +// RUN: rm -rf %t.profdir && mkdir %t.profdir +// RUN: env LLVM_PROFILE_FILE=%t.profdir/%m.proflite %run %t +// RUN: env LLVM_PROFILE_FILE=%t.profdir/%m.proflite %run %t +// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t %t.profdir/ + +// RUN: diff <(llvm-profdata show --all-functions --counts %t.normal.profdata) <(llvm-profdata show --all-functions --counts %t.profdata) + +// RUN: rm -rf %t.profdir && mkdir %t.profdir +// RUN: env LLVM_PROFILE_FILE=%t.profdir/%m.cov.proflite %run %t.cov +// RUN: env LLVM_PROFILE_FILE=%t.profdir/%m.cov.proflite %run %t.cov +// RUN: llvm-profdata merge -o %t.cov.profdata --debug-info=%t.cov %t.profdir/ + +// RUN: diff <(llvm-profdata show --all-functions --counts %t.cov.normal.profdata) <(llvm-profdata show --all-functions --counts %t.cov.profdata) diff --git a/compiler-rt/test/profile/instrprof-merge-error.c b/compiler-rt/test/profile/instrprof-merge-error.c --- a/compiler-rt/test/profile/instrprof-merge-error.c +++ b/compiler-rt/test/profile/instrprof-merge-error.c @@ -1,11 +1,5 @@ // RUN: rm -rf %t; mkdir %t -// RUN: %clang_pgogen -o %t/dbg -g -mllvm --debug-info-correlate -mllvm --disable-vp=true %s -// RUN: env LLVM_PROFILE_FILE=%t/dbg_%m.profdata %run %t/dbg 2>&1 | count 0 -// RUN: env LLVM_PROFILE_FILE=%t/dbg_%m.profdata %run %t/dbg 2>&1 | FileCheck %s --check-prefix=DBG - -// DBG: Debug info correlation does not support profile merging at runtime. - // RUN: %clang_pgogen -o %t/timeprof -mllvm -pgo-temporal-instrumentation %s // RUN: env LLVM_PROFILE_FILE=%t/timeprof_%m.profdata %run %t/timeprof 2>&1 | count 0 // RUN: env LLVM_PROFILE_FILE=%t/timeprof_%m.profdata %run %t/timeprof 2>&1 | FileCheck %s --check-prefix=TIMEPROF