diff --git a/compiler-rt/lib/profile/InstrProfilingWriter.c b/compiler-rt/lib/profile/InstrProfilingWriter.c --- a/compiler-rt/lib/profile/InstrProfilingWriter.c +++ b/compiler-rt/lib/profile/InstrProfilingWriter.c @@ -276,9 +276,6 @@ /* Create the header. */ __llvm_profile_header Header; - if (!NumData && (!DebugInfoCorrelate || !NumCounters)) - return 0; - /* Determine how much padding is needed before/after the counters and after * the names. */ uint64_t PaddingBytesBeforeCounters, PaddingBytesAfterCounters, diff --git a/compiler-rt/test/profile/Posix/instrprof-empty-profile.c b/compiler-rt/test/profile/Posix/instrprof-empty-profile.c new file mode 100644 --- /dev/null +++ b/compiler-rt/test/profile/Posix/instrprof-empty-profile.c @@ -0,0 +1,23 @@ +// Test a profile with only a header is generated when a src file is not in the +// selected files list provided via -fprofile-list. + +// RUN: mkdir -p %t.d +// RUN: echo "src:other.c" > %t-file.list +// RUN: %clang_profgen -fprofile-list=%t-file.list -o %t %s +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t +// RUN: llvm-profdata show %t.profraw | FileCheck %s --check-prefix=RAW-PROFILE-HEADER-ONLY + +// RUN: llvm-profdata merge -o %t.profdata %t.profraw +// RUN: llvm-profdata show %t.profdata | FileCheck %s --check-prefix=INDEXED-PROFILE-HEADER-ONLY + +int main() { return 0; } + +// RAW-PROFILE-HEADER-ONLY: Instrumentation level: Front-end +// RAW-PROFILE-HEADER-ONLY-NEXT: Total functions: 0 +// RAW-PROFILE-HEADER-ONLY-NEXT: Maximum function count: 0 +// RAW-PROFILE-HEADER-ONLY-NEXT: Maximum internal block count: 0 + +// INDEXED-PROFILE-HEADER-ONLY: Instrumentation level: Front-end +// INDEXED-PROFILE-HEADER-ONLY-NEXT: Total functions: 0 +// INDEXED-PROFILE-HEADER-ONLY-NEXT: Maximum function count: 0 +// INDEXED-PROFILE-HEADER-ONLY-NEXT: Maximum internal block count: 0 diff --git a/compiler-rt/test/profile/Posix/instrprof-shared-empty-profile.test b/compiler-rt/test/profile/Posix/instrprof-shared-empty-profile.test new file mode 100644 --- /dev/null +++ b/compiler-rt/test/profile/Posix/instrprof-shared-empty-profile.test @@ -0,0 +1,42 @@ +""" +This test produces two shared libraries: + +1. libt-instr.so is instrumented +2. libt-no-instr.so is built with profile rt linked in (via -u), but the object file is built + with instrumentation turned off. + +The test verifies concatenating profiles with only headers and no profile data and counters. +""" + +RUN: mkdir -p %t.d +RUN: %clang_profgen -o %t.d/libt-instr.so -fPIC -shared %S/../Inputs/instrprof-shared-lib.c +RUN: %clang -c -o %t.d/instrprof-shared-lib-no-instr.o -fPIC %S/../Inputs/instrprof-shared-lib.c +RUN: %clang_profgen -o %t.d/libt-no-instr.so -fPIC -shared %t.d/instrprof-shared-lib-no-instr.o + +# Header + Header +RUN: echo "src:other.c" > %t-file.list +RUN: %clang_profgen -fprofile-list=%t-file.list -o %t-no-instr-no-instr -L%t.d -rpath %t.d -lt-no-instr %S/../Inputs/instrprof-shared-main.c +RUN: env LLVM_PROFILE_FILE=%t-no-instr-no-instr.profraw %run %t-no-instr-no-instr +RUN: llvm-profdata show %t-no-instr-no-instr.profraw | FileCheck %s --check-prefix=HEADER-HEADER +// HEADER-HEADER: Instrumentation level: Front-end +// HEADER-HEADER-NEXT: Total functions: 0 +// HEADER-HEADER-NEXT: Maximum function count: 0 +// HEADER-HEADER-NEXT: Maximum internal block count: 0 + +# Header + Profile +RUN: %clang_profgen -fprofile-list=%t-file.list -o %t-no-instr-instr -L%t.d -rpath %t.d -lt-instr %S/../Inputs/instrprof-shared-main.c +RUN: env LLVM_PROFILE_FILE=%t-no-instr-instr.profraw %run %t-no-instr-instr +RUN: llvm-profdata show %t-no-instr-instr.profraw | FileCheck %s --check-prefix=HEADER-PROFILE +// HEADER-PROFILE: Instrumentation level: Front-end +// HEADER-PROFILE-NEXT: Total functions: 1 +// HEADER-PROFILE-NEXT: Maximum function count: 1000000 +// HEADER-PROFILE-NEXT: Maximum internal block count: 360000 + +# Profile + Header +RUN: %clang_profgen -o %t-instr-no-instr -L%t.d -rpath %t.d -lt-no-instr %S/../Inputs/instrprof-shared-main.c +RUN: env LLVM_PROFILE_FILE=%t-instr-no-instr.profraw %run %t-instr-no-instr +RUN: llvm-profdata show %t-instr-no-instr.profraw | FileCheck %s --check-prefix=PROFILE-HEADER +// PROFILE-HEADER: Instrumentation level: Front-end +// PROFILE-HEADER-NEXT: Total functions: 1 +// PROFILE-HEADER-NEXT: Maximum function count: 1 +// PROFILE-HEADER-NEXT: Maximum internal block count: 1000000 diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp --- a/llvm/lib/ProfileData/InstrProfReader.cpp +++ b/llvm/lib/ProfileData/InstrProfReader.cpp @@ -545,7 +545,9 @@ template Error RawInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) { - if (atEnd()) + // Keep reading profiles that consist of only headers and no profile data and + // counters. + while (atEnd()) // At this point, ValueDataStart field points to the next header. if (Error E = readNextHeader(getNextHeaderPos())) return error(std::move(E));