[compiler-rt] r208940 - InstrProf: Fix shared object profiling
Duncan P. N. Exon Smith
dexonsmith at apple.com
Thu May 15 18:30:24 PDT 2014
Author: dexonsmith
Date: Thu May 15 20:30:24 2014
New Revision: 208940
URL: http://llvm.org/viewvc/llvm-project?rev=208940&view=rev
Log:
InstrProf: Fix shared object profiling
Change the API of the instrumented profiling library to work with shared
objects.
- Most things are now declared hidden, so that each executable gets
its own copy.
- Initialization hooks up a linked list of writers.
- The raw format with shared objects that are profiled consists of a
concatenated series of profiles. llvm-profdata knows how to deal
with that since r208938.
<rdar://problem/16918688>
Added:
compiler-rt/trunk/test/profile/Inputs/
compiler-rt/trunk/test/profile/Inputs/instrprof-dynamic-a.cpp
compiler-rt/trunk/test/profile/Inputs/instrprof-dynamic-b.cpp
compiler-rt/trunk/test/profile/Inputs/instrprof-dynamic-header.h
compiler-rt/trunk/test/profile/Inputs/instrprof-dynamic-main.cpp
compiler-rt/trunk/test/profile/instrprof-dynamic-one-shared.test
compiler-rt/trunk/test/profile/instrprof-dynamic-two-shared.test
Modified:
compiler-rt/trunk/lib/profile/InstrProfiling.c
compiler-rt/trunk/lib/profile/InstrProfiling.h
compiler-rt/trunk/lib/profile/InstrProfilingBuffer.c
compiler-rt/trunk/lib/profile/InstrProfilingFile.c
compiler-rt/trunk/lib/profile/InstrProfilingPlatformDarwin.c
compiler-rt/trunk/lib/profile/InstrProfilingPlatformOther.c
compiler-rt/trunk/lib/profile/InstrProfilingRuntime.cc
compiler-rt/trunk/test/profile/lit.cfg
Modified: compiler-rt/trunk/lib/profile/InstrProfiling.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/profile/InstrProfiling.c?rev=208940&r1=208939&r2=208940&view=diff
==============================================================================
--- compiler-rt/trunk/lib/profile/InstrProfiling.c (original)
+++ compiler-rt/trunk/lib/profile/InstrProfiling.c Thu May 15 20:30:24 2014
@@ -10,6 +10,7 @@
#include "InstrProfiling.h"
#include <string.h>
+__attribute__((visibility("hidden")))
uint64_t __llvm_profile_get_magic(void) {
/* Magic number to detect file format and endianness.
*
@@ -32,11 +33,13 @@ uint64_t __llvm_profile_get_magic(void)
(uint64_t)129;
}
+__attribute__((visibility("hidden")))
uint64_t __llvm_profile_get_version(void) {
/* This should be bumped any time the output format changes. */
return 1;
}
+__attribute__((visibility("hidden")))
void __llvm_profile_reset_counters(void) {
uint64_t *I = __llvm_profile_counters_begin();
uint64_t *E = __llvm_profile_counters_end();
Modified: compiler-rt/trunk/lib/profile/InstrProfiling.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/profile/InstrProfiling.h?rev=208940&r1=208939&r2=208940&view=diff
==============================================================================
--- compiler-rt/trunk/lib/profile/InstrProfiling.h (original)
+++ compiler-rt/trunk/lib/profile/InstrProfiling.h Thu May 15 20:30:24 2014
@@ -83,6 +83,9 @@ void __llvm_profile_set_filename(const c
/*! \brief Register to write instrumentation data to file at exit. */
int __llvm_profile_register_write_file_atexit(void);
+/*! \brief Register the write file function for this executable. */
+void __llvm_profile_register_write_file(void);
+
/*! \brief Get the magic token for the file format. */
uint64_t __llvm_profile_get_magic(void);
Modified: compiler-rt/trunk/lib/profile/InstrProfilingBuffer.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/profile/InstrProfilingBuffer.c?rev=208940&r1=208939&r2=208940&view=diff
==============================================================================
--- compiler-rt/trunk/lib/profile/InstrProfilingBuffer.c (original)
+++ compiler-rt/trunk/lib/profile/InstrProfilingBuffer.c Thu May 15 20:30:24 2014
@@ -10,14 +10,18 @@
#include "InstrProfiling.h"
#include <string.h>
+__attribute__((visibility("hidden")))
uint64_t __llvm_profile_get_size_for_buffer(void) {
/* Match logic in __llvm_profile_write_buffer(). */
+ const uint64_t NamesSize = PROFILE_RANGE_SIZE(names) * sizeof(char);
+ const uint64_t Padding = sizeof(uint64_t) - NamesSize % sizeof(uint64_t);
return sizeof(uint64_t) * PROFILE_HEADER_SIZE +
PROFILE_RANGE_SIZE(data) * sizeof(__llvm_profile_data) +
PROFILE_RANGE_SIZE(counters) * sizeof(uint64_t) +
- PROFILE_RANGE_SIZE(names) * sizeof(char);
+ NamesSize + Padding;
}
+__attribute__((visibility("hidden")))
int __llvm_profile_write_buffer(char *Buffer) {
/* Match logic in __llvm_profile_get_size_for_buffer().
* Match logic in __llvm_profile_write_file().
@@ -33,6 +37,10 @@ int __llvm_profile_write_buffer(char *Bu
const uint64_t DataSize = DataEnd - DataBegin;
const uint64_t CountersSize = CountersEnd - CountersBegin;
const uint64_t NamesSize = NamesEnd - NamesBegin;
+ const uint64_t Padding = sizeof(uint64_t) - NamesSize % sizeof(uint64_t);
+
+ /* Enough zeroes for padding. */
+ const char Zeroes[sizeof(uint64_t)] = {0};
/* Create the header. */
uint64_t Header[PROFILE_HEADER_SIZE];
@@ -54,6 +62,7 @@ int __llvm_profile_write_buffer(char *Bu
UPDATE_memcpy(DataBegin, DataSize * sizeof(__llvm_profile_data));
UPDATE_memcpy(CountersBegin, CountersSize * sizeof(uint64_t));
UPDATE_memcpy(NamesBegin, NamesSize * sizeof(char));
+ UPDATE_memcpy(Zeroes, Padding * sizeof(char));
#undef UPDATE_memcpy
return 0;
Modified: compiler-rt/trunk/lib/profile/InstrProfilingFile.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/profile/InstrProfilingFile.c?rev=208940&r1=208939&r2=208940&view=diff
==============================================================================
--- compiler-rt/trunk/lib/profile/InstrProfilingFile.c (original)
+++ compiler-rt/trunk/lib/profile/InstrProfilingFile.c Thu May 15 20:30:24 2014
@@ -25,6 +25,10 @@ static int writeFile(FILE *File) {
const uint64_t DataSize = DataEnd - DataBegin;
const uint64_t CountersSize = CountersEnd - CountersBegin;
const uint64_t NamesSize = NamesEnd - NamesBegin;
+ const uint64_t Padding = sizeof(uint64_t) - NamesSize % sizeof(uint64_t);
+
+ /* Enough zeroes for padding. */
+ const char Zeroes[sizeof(uint64_t)] = {0};
/* Create the header. */
uint64_t Header[PROFILE_HEADER_SIZE];
@@ -43,9 +47,30 @@ static int writeFile(FILE *File) {
CHECK_fwrite(DataBegin, sizeof(__llvm_profile_data), DataSize, File);
CHECK_fwrite(CountersBegin, sizeof(uint64_t), CountersSize, File);
CHECK_fwrite(NamesBegin, sizeof(char), NamesSize, File);
+ CHECK_fwrite(Zeroes, sizeof(char), Padding, File);
#undef CHECK_fwrite
- return 0;
+ return 0;
+}
+
+typedef struct __llvm_profile_writer {
+ struct __llvm_profile_writer *Next;
+ int (*Data)(FILE *);
+} __llvm_profile_writer;
+
+__attribute__((weak)) __llvm_profile_writer *__llvm_profile_HeadWriter = NULL;
+static __llvm_profile_writer Writer = {NULL, writeFile};
+
+__attribute__((visibility("hidden")))
+void __llvm_profile_register_write_file(void) {
+ static int HasBeenRegistered = 0;
+
+ if (HasBeenRegistered)
+ return;
+
+ HasBeenRegistered = 1;
+ Writer.Next = __llvm_profile_HeadWriter;
+ __llvm_profile_HeadWriter = &Writer;
}
static int writeFileWithName(const char *OutputName) {
@@ -57,19 +82,28 @@ static int writeFileWithName(const char
if (!OutputFile)
return -1;
- RetVal = writeFile(OutputFile);
+ __llvm_profile_writer *Writer = __llvm_profile_HeadWriter;
+ if (Writer)
+ for (; Writer; Writer = Writer->Next) {
+ RetVal = Writer->Data(OutputFile);
+ if (RetVal != 0)
+ break;
+ }
+ else
+ // Default to calling this executable's writeFile.
+ RetVal = writeFile(OutputFile);
fclose(OutputFile);
return RetVal;
}
-static const char *CurrentFilename = NULL;
-void __llvm_profile_set_filename(const char *Filename) {
- CurrentFilename = Filename;
+__attribute__((weak)) const char *__llvm_profile_CurrentFilename = NULL;
+__attribute__((weak)) void __llvm_profile_set_filename(const char *Filename) {
+ __llvm_profile_CurrentFilename = Filename;
}
int getpid(void);
-int __llvm_profile_write_file(void) {
+__attribute__((weak)) int __llvm_profile_write_file(void) {
char *AllocatedFilename = NULL;
int I, J;
int RetVal;
@@ -80,7 +114,7 @@ int __llvm_profile_write_file(void) {
int NumPids = 0;
/* Get the filename. */
- const char *Filename = CurrentFilename;
+ const char *Filename = __llvm_profile_CurrentFilename;
#define UPDATE_FILENAME(NextFilename) \
if (!Filename || !Filename[0]) Filename = NextFilename
UPDATE_FILENAME(getenv("LLVM_PROFILE_FILE"));
@@ -131,7 +165,7 @@ static void writeFileWithoutReturn(void)
__llvm_profile_write_file();
}
-int __llvm_profile_register_write_file_atexit(void) {
+__attribute__((weak)) int __llvm_profile_register_write_file_atexit(void) {
static int HasBeenRegistered = 0;
if (HasBeenRegistered)
Modified: compiler-rt/trunk/lib/profile/InstrProfilingPlatformDarwin.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/profile/InstrProfilingPlatformDarwin.c?rev=208940&r1=208939&r2=208940&view=diff
==============================================================================
--- compiler-rt/trunk/lib/profile/InstrProfilingPlatformDarwin.c (original)
+++ compiler-rt/trunk/lib/profile/InstrProfilingPlatformDarwin.c Thu May 15 20:30:24 2014
@@ -11,21 +11,33 @@
#if defined(__APPLE__)
/* Use linker magic to find the bounds of the Data section. */
+__attribute__((visibility("hidden")))
extern __llvm_profile_data DataStart __asm("section$start$__DATA$__llvm_prf_data");
+__attribute__((visibility("hidden")))
extern __llvm_profile_data DataEnd __asm("section$end$__DATA$__llvm_prf_data");
+__attribute__((visibility("hidden")))
extern char NamesStart __asm("section$start$__DATA$__llvm_prf_names");
+__attribute__((visibility("hidden")))
extern char NamesEnd __asm("section$end$__DATA$__llvm_prf_names");
+__attribute__((visibility("hidden")))
extern uint64_t CountersStart __asm("section$start$__DATA$__llvm_prf_cnts");
+__attribute__((visibility("hidden")))
extern uint64_t CountersEnd __asm("section$end$__DATA$__llvm_prf_cnts");
+__attribute__((visibility("hidden")))
const __llvm_profile_data *__llvm_profile_data_begin(void) {
return &DataStart;
}
+__attribute__((visibility("hidden")))
const __llvm_profile_data *__llvm_profile_data_end(void) {
return &DataEnd;
}
+__attribute__((visibility("hidden")))
const char *__llvm_profile_names_begin(void) { return &NamesStart; }
+__attribute__((visibility("hidden")))
const char *__llvm_profile_names_end(void) { return &NamesEnd; }
+__attribute__((visibility("hidden")))
uint64_t *__llvm_profile_counters_begin(void) { return &CountersStart; }
+__attribute__((visibility("hidden")))
uint64_t *__llvm_profile_counters_end(void) { return &CountersEnd; }
#endif
Modified: compiler-rt/trunk/lib/profile/InstrProfilingPlatformOther.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/profile/InstrProfilingPlatformOther.c?rev=208940&r1=208939&r2=208940&view=diff
==============================================================================
--- compiler-rt/trunk/lib/profile/InstrProfilingPlatformOther.c (original)
+++ compiler-rt/trunk/lib/profile/InstrProfilingPlatformOther.c Thu May 15 20:30:24 2014
@@ -26,6 +26,7 @@ static uint64_t *CountersLast = NULL;
* calls are only required (and only emitted) on targets where we haven't
* implemented linker magic to find the bounds of the sections.
*/
+__attribute__((visibility("hidden")))
void __llvm_profile_register_function(void *Data_) {
/* TODO: Only emit this function if we can't use linker magic. */
const __llvm_profile_data *Data = (__llvm_profile_data*)Data_;
@@ -54,14 +55,20 @@ void __llvm_profile_register_function(vo
#undef UPDATE_LAST
}
+__attribute__((visibility("hidden")))
const __llvm_profile_data *__llvm_profile_data_begin(void) {
return DataFirst;
}
+__attribute__((visibility("hidden")))
const __llvm_profile_data *__llvm_profile_data_end(void) {
return DataLast;
}
+__attribute__((visibility("hidden")))
const char *__llvm_profile_names_begin(void) { return NamesFirst; }
+__attribute__((visibility("hidden")))
const char *__llvm_profile_names_end(void) { return NamesLast; }
+__attribute__((visibility("hidden")))
uint64_t *__llvm_profile_counters_begin(void) { return CountersFirst; }
+__attribute__((visibility("hidden")))
uint64_t *__llvm_profile_counters_end(void) { return CountersLast; }
#endif
Modified: compiler-rt/trunk/lib/profile/InstrProfilingRuntime.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/profile/InstrProfilingRuntime.cc?rev=208940&r1=208939&r2=208940&view=diff
==============================================================================
--- compiler-rt/trunk/lib/profile/InstrProfilingRuntime.cc (original)
+++ compiler-rt/trunk/lib/profile/InstrProfilingRuntime.cc Thu May 15 20:30:24 2014
@@ -11,17 +11,20 @@ extern "C" {
#include "InstrProfiling.h"
-int __llvm_profile_runtime;
+__attribute__((visibility("hidden"))) int __llvm_profile_runtime;
}
namespace {
-class RegisterAtExit {
+class RegisterRuntime {
public:
- RegisterAtExit() { __llvm_profile_register_write_file_atexit(); }
+ RegisterRuntime() {
+ __llvm_profile_register_write_file_atexit();
+ __llvm_profile_register_write_file();
+ }
};
-RegisterAtExit Registration;
+RegisterRuntime Registration;
}
Added: compiler-rt/trunk/test/profile/Inputs/instrprof-dynamic-a.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/profile/Inputs/instrprof-dynamic-a.cpp?rev=208940&view=auto
==============================================================================
--- compiler-rt/trunk/test/profile/Inputs/instrprof-dynamic-a.cpp (added)
+++ compiler-rt/trunk/test/profile/Inputs/instrprof-dynamic-a.cpp Thu May 15 20:30:24 2014
@@ -0,0 +1,7 @@
+#include "instrprof-dynamic-header.h"
+void a() {
+ if (true) {
+ bar<void>();
+ bar<char>();
+ }
+}
Added: compiler-rt/trunk/test/profile/Inputs/instrprof-dynamic-b.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/profile/Inputs/instrprof-dynamic-b.cpp?rev=208940&view=auto
==============================================================================
--- compiler-rt/trunk/test/profile/Inputs/instrprof-dynamic-b.cpp (added)
+++ compiler-rt/trunk/test/profile/Inputs/instrprof-dynamic-b.cpp Thu May 15 20:30:24 2014
@@ -0,0 +1,7 @@
+#include "instrprof-dynamic-header.h"
+void b() {
+ if (true) {
+ bar<void>();
+ bar<int>();
+ }
+}
Added: compiler-rt/trunk/test/profile/Inputs/instrprof-dynamic-header.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/profile/Inputs/instrprof-dynamic-header.h?rev=208940&view=auto
==============================================================================
--- compiler-rt/trunk/test/profile/Inputs/instrprof-dynamic-header.h (added)
+++ compiler-rt/trunk/test/profile/Inputs/instrprof-dynamic-header.h Thu May 15 20:30:24 2014
@@ -0,0 +1,5 @@
+template <class T> void bar() {
+ if (true) {}
+}
+void a();
+void b();
Added: compiler-rt/trunk/test/profile/Inputs/instrprof-dynamic-main.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/profile/Inputs/instrprof-dynamic-main.cpp?rev=208940&view=auto
==============================================================================
--- compiler-rt/trunk/test/profile/Inputs/instrprof-dynamic-main.cpp (added)
+++ compiler-rt/trunk/test/profile/Inputs/instrprof-dynamic-main.cpp Thu May 15 20:30:24 2014
@@ -0,0 +1,9 @@
+#include "instrprof-dynamic-header.h"
+void foo(int K) { if (K) {} }
+int main(int argc, char *argv[]) {
+ foo(5);
+ bar<void>();
+ a();
+ b();
+ return 0;
+}
Added: compiler-rt/trunk/test/profile/instrprof-dynamic-one-shared.test
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/profile/instrprof-dynamic-one-shared.test?rev=208940&view=auto
==============================================================================
--- compiler-rt/trunk/test/profile/instrprof-dynamic-one-shared.test (added)
+++ compiler-rt/trunk/test/profile/instrprof-dynamic-one-shared.test Thu May 15 20:30:24 2014
@@ -0,0 +1,23 @@
+RUN: mkdir -p %t.d
+RUN: %clang_profgen -o %t.d/a.shared -fPIC -shared %S/Inputs/instrprof-dynamic-a.cpp
+RUN: %clang_profgen -o %t-shared -fPIC -rpath %t.d %t.d/a.shared %S/Inputs/instrprof-dynamic-b.cpp %S/Inputs/instrprof-dynamic-main.cpp
+
+RUN: %clang_profgen -o %t-static %S/Inputs/instrprof-dynamic-a.cpp %S/Inputs/instrprof-dynamic-b.cpp %S/Inputs/instrprof-dynamic-main.cpp
+
+RUN: env LLVM_PROFILE_FILE=%t-static.profraw %run %t-static
+RUN: env LLVM_PROFILE_FILE=%t-shared.profraw %run %t-shared
+
+RUN: llvm-profdata merge -o %t-static.profdata %t-static.profraw
+RUN: llvm-profdata merge -o %t-shared.profdata %t-shared.profraw
+
+RUN: %clang_profuse=%t-static.profdata -o %t-a.static.ll -S -emit-llvm %S/Inputs/instrprof-dynamic-a.cpp
+RUN: %clang_profuse=%t-shared.profdata -o %t-a.shared.ll -S -emit-llvm %S/Inputs/instrprof-dynamic-a.cpp
+RUN: diff %t-a.static.ll %t-a.shared.ll
+
+RUN: %clang_profuse=%t-static.profdata -o %t-b.static.ll -S -emit-llvm %S/Inputs/instrprof-dynamic-b.cpp
+RUN: %clang_profuse=%t-shared.profdata -o %t-b.shared.ll -S -emit-llvm %S/Inputs/instrprof-dynamic-b.cpp
+RUN: diff %t-b.static.ll %t-b.shared.ll
+
+RUN: %clang_profuse=%t-static.profdata -o %t-main.static.ll -S -emit-llvm %S/Inputs/instrprof-dynamic-main.cpp
+RUN: %clang_profuse=%t-shared.profdata -o %t-main.shared.ll -S -emit-llvm %S/Inputs/instrprof-dynamic-main.cpp
+RUN: diff %t-main.static.ll %t-main.shared.ll
Added: compiler-rt/trunk/test/profile/instrprof-dynamic-two-shared.test
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/profile/instrprof-dynamic-two-shared.test?rev=208940&view=auto
==============================================================================
--- compiler-rt/trunk/test/profile/instrprof-dynamic-two-shared.test (added)
+++ compiler-rt/trunk/test/profile/instrprof-dynamic-two-shared.test Thu May 15 20:30:24 2014
@@ -0,0 +1,24 @@
+RUN: mkdir -p %t.d
+RUN: %clang_profgen -o %t.d/a.shared -fPIC -shared %S/Inputs/instrprof-dynamic-a.cpp
+RUN: %clang_profgen -o %t.d/b.shared -fPIC -shared %S/Inputs/instrprof-dynamic-b.cpp
+RUN: %clang_profgen -o %t-shared -fPIC -rpath %t.d %t.d/a.shared %t.d/b.shared %S/Inputs/instrprof-dynamic-main.cpp
+
+RUN: %clang_profgen -o %t-static %S/Inputs/instrprof-dynamic-a.cpp %S/Inputs/instrprof-dynamic-b.cpp %S/Inputs/instrprof-dynamic-main.cpp
+
+RUN: env LLVM_PROFILE_FILE=%t-static.profraw %run %t-static
+RUN: env LLVM_PROFILE_FILE=%t-shared.profraw %run %t-shared
+
+RUN: llvm-profdata merge -o %t-static.profdata %t-static.profraw
+RUN: llvm-profdata merge -o %t-shared.profdata %t-shared.profraw
+
+RUN: %clang_profuse=%t-static.profdata -o %t-a.static.ll -S -emit-llvm %S/Inputs/instrprof-dynamic-a.cpp
+RUN: %clang_profuse=%t-shared.profdata -o %t-a.shared.ll -S -emit-llvm %S/Inputs/instrprof-dynamic-a.cpp
+RUN: diff %t-a.static.ll %t-a.shared.ll
+
+RUN: %clang_profuse=%t-static.profdata -o %t-b.static.ll -S -emit-llvm %S/Inputs/instrprof-dynamic-b.cpp
+RUN: %clang_profuse=%t-shared.profdata -o %t-b.shared.ll -S -emit-llvm %S/Inputs/instrprof-dynamic-b.cpp
+RUN: diff %t-b.static.ll %t-b.shared.ll
+
+RUN: %clang_profuse=%t-static.profdata -o %t-main.static.ll -S -emit-llvm %S/Inputs/instrprof-dynamic-main.cpp
+RUN: %clang_profuse=%t-shared.profdata -o %t-main.shared.ll -S -emit-llvm %S/Inputs/instrprof-dynamic-main.cpp
+RUN: diff %t-main.static.ll %t-main.shared.ll
Modified: compiler-rt/trunk/test/profile/lit.cfg
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/profile/lit.cfg?rev=208940&r1=208939&r2=208940&view=diff
==============================================================================
--- compiler-rt/trunk/test/profile/lit.cfg (original)
+++ compiler-rt/trunk/test/profile/lit.cfg Thu May 15 20:30:24 2014
@@ -27,6 +27,9 @@ if config.test_exec_root is None:
# Test suffixes.
config.suffixes = ['.c', '.cc', '.cpp', '.m', '.mm', '.ll', '.test']
+# What to exclude.
+config.excludes = ['Inputs']
+
# Clang flags.
clang_cflags = [config.target_cflags]
More information about the llvm-commits
mailing list